From cca2e1155617304b5bcb3457309983cf8e99b067 Mon Sep 17 00:00:00 2001 From: Parnell Springmeyer Date: Mon, 13 Feb 2017 18:03:06 -0600 Subject: [PATCH] Resurrecting the single-wrapper read from sibling .real file behavior --- nixos/modules/security/wrappers/default.nix | 44 ++++++++++----------- nixos/modules/security/wrappers/wrapper.c | 28 ++++++++----- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index 757765ed08c4..0548b1d96593 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -8,24 +8,20 @@ let (n: v: (if v ? "program" then v else v // {program=n;})) wrappers); - mkWrapper = { program, source ? null, ...}: - let buildWrapper = '' - parentWrapperDir=$(dirname ${wrapperDir}) - gcc -Wall -O2 -DSOURCE_PROG=\"${source}\" -DWRAPPER_DIR=\"$parentWrapperDir\" \ - -Wformat -Wformat-security -Werror=format-security \ - -fstack-protector-strong --param ssp-buffer-size=4 \ - -D_FORTIFY_SOURCE=2 -fPIC \ - -lcap-ng -lcap ${./wrapper.c} -o $out/bin/${program}.wrapper -L ${pkgs.libcap.lib}/lib -L ${pkgs.libcap_ng}/lib \ - -I ${pkgs.libcap.dev}/include -I ${pkgs.libcap_ng}/include -I ${pkgs.linuxHeaders}/include - ''; - in pkgs.stdenv.mkDerivation { - name = "${program}-wrapper"; - unpackPhase = "true"; - installPhase = '' - mkdir -p $out/bin - ${buildWrapper} - ''; - }; + securityWrapper = pkgs.stdenv.mkDerivation { + name = "security-wrapper"; + unpackPhase = "true"; + installPhase = '' + mkdir -p $out/bin + parentWrapperDir=$(dirname ${wrapperDir}) + gcc -Wall -O2 -DWRAPPER_DIR=\"$parentWrapperDir\" \ + -Wformat -Wformat-security -Werror=format-security \ + -fstack-protector-strong --param ssp-buffer-size=4 \ + -D_FORTIFY_SOURCE=2 -fPIC \ + -lcap-ng -lcap ${./wrapper.c} -o $out/bin/security-wrapper -L ${pkgs.libcap.lib}/lib -L ${pkgs.libcap_ng}/lib \ + -I ${pkgs.libcap.dev}/include -I ${pkgs.libcap_ng}/include -I ${pkgs.linuxHeaders}/include + ''; + }; ###### Activation script for the setcap wrappers mkSetcapProgram = @@ -37,9 +33,9 @@ let , ... }: assert (lib.versionAtLeast (lib.getVersion config.boot.kernelPackages.kernel) "4.3"); - let wrapperDrv = mkWrapper { inherit program source; }; - in '' - cp ${wrapperDrv}/bin/${program}.wrapper $wrapperDir/${program} + '' + cp ${securityWrapper}/bin/security-wrapper $wrapperDir/${program} + echo -n "$source" > $wrapperDir/${program}.real # Prevent races chmod 0000 $wrapperDir/${program} @@ -65,9 +61,9 @@ let , permissions ? "u+rx,g+x,o+x" , ... }: - let wrapperDrv = mkWrapper { inherit program source; }; - in '' - cp ${wrapperDrv}/bin/${program}.wrapper $wrapperDir/${program} + '' + cp ${securityWrapper}/bin/security-wrapper $wrapperDir/${program} + echo -n "$source" > $wrapperDir/${program}.real # Prevent races chmod 0000 $wrapperDir/${program} diff --git a/nixos/modules/security/wrappers/wrapper.c b/nixos/modules/security/wrappers/wrapper.c index e6f2605143fe..4a656c54e3f9 100644 --- a/nixos/modules/security/wrappers/wrapper.c +++ b/nixos/modules/security/wrappers/wrapper.c @@ -21,9 +21,8 @@ extern char **environ; -// The SOURCE_PROG and WRAPPER_DIR macros are supplied at compile time -// for a security reason: So they cannot be changed at runtime. -static char * sourceProg = SOURCE_PROG; +// The WRAPPER_DIR macro is supplied at compile time so that it cannot +// be changed at runtime static char * wrapperDir = WRAPPER_DIR; // Wrapper debug variable name @@ -207,14 +206,25 @@ int main(int argc, char * * argv) // And, of course, we shouldn't be writable. assert(!(st.st_mode & (S_IWGRP | S_IWOTH))); - struct stat stR; - stat(sourceProg, &stR); + // Read the path of the real (wrapped) program from .real. + char realFN[PATH_MAX + 10]; + int realFNSize = snprintf (realFN, sizeof(realFN), "%s.real", selfPath); + assert (realFNSize < sizeof(realFN)); - // Make sure the program we're wrapping is non-zero - assert(stR.st_size > 0); + int fdSelf = open(realFN, O_RDONLY); + assert (fdSelf != -1); - // Read the capabilities set on the file and raise them in to the - // Ambient set so the program we're wrapping receives the + char sourceProg[PATH_MAX]; + len = read(fdSelf, sourceProg, PATH_MAX); + assert (len != -1); + assert (len < sizeof(sourceProg)); + assert (len > 0); + sourceProg[len] = 0; + + close(fdSelf); + + // Read the capabilities set on the wrapper and raise them in to + // the Ambient set so the program we're wrapping receives the // capabilities too! make_caps_ambient(selfPath);