From: David Kalnischkies <david@kalnischkies.de>
Date: Wed, 9 Nov 2016 18:15:01 +0000 (+0100)
Subject: reset HOME, USER(NAME), TMPDIR & SHELL in DropPrivileges
X-Git-Tag: 1.4_beta1~41
X-Git-Url: https://git.saurik.com/apt.git/commitdiff_plain/34b491e735ad47c4805e63f3b83a659b8d10262b?hp=2c30cf43f1c4ab96f3eca849d7eb4923ffed40b1

reset HOME, USER(NAME), TMPDIR & SHELL in DropPrivileges

We can't cleanup the environment like e.g. sudo would do as you usually
want the environment to "leak" into these helpers, but some variables
like HOME should really not have still the value of the root user – it
could confuse the helpers (USER) and HOME isn't accessible anyhow.

Closes: 842877
---

diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 6c43bed90..d52e9b360 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -3051,6 +3051,26 @@ bool DropPrivileges()							/*{{{*/
 	 return _error->Error("Could restore a uid to root, privilege dropping did not work");
    }
 
+   if (_config->FindB("APT::Sandbox::ResetEnvironment", true))
+   {
+      setenv("HOME", pw->pw_dir, 1);
+      setenv("USER", pw->pw_name, 1);
+      setenv("USERNAME", pw->pw_name, 1);
+      setenv("LOGNAME", pw->pw_name, 1);
+      auto const shell = flNotDir(pw->pw_shell);
+      if (shell == "false" || shell == "nologin")
+	 setenv("SHELL", "/bin/sh", 1);
+      else
+	 setenv("SHELL", pw->pw_shell, 1);
+      auto const tmpdir = getenv("TMPDIR");
+      if (tmpdir != nullptr)
+      {
+	 auto const ourtmpdir = GetTempDir();
+	 if (ourtmpdir != tmpdir)
+	    setenv("TMPDIR", ourtmpdir.c_str(), 1);
+      }
+   }
+
    return true;
 }
 									/*}}}*/
diff --git a/debian/tests/run-tests b/debian/tests/run-tests
index 277594108..495f7edff 100644
--- a/debian/tests/run-tests
+++ b/debian/tests/run-tests
@@ -13,7 +13,7 @@ make -C build/test/interactive-helper
 # the host env does not pollute our environment
 env -i \
 APT_INTEGRATION_TESTS_SOURCE_DIR=$(pwd) \
-APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR=$(pwd)/build/test/interactive-helper \
+APT_INTEGRATION_TESTS_HELPERS_BIN_DIR=$(pwd)/build/test/interactive-helper \
 APT_INTEGRATION_TESTS_METHODS_DIR=/usr/lib/apt/methods \
 APT_INTEGRATION_TESTS_LIBEXEC_DIR=/usr/lib/apt/ \
 APT_INTEGRATION_TESTS_INTERNAL_SOLVER=/usr/lib/apt/solvers/apt \
diff --git a/test/integration/framework b/test/integration/framework
index d5b68da84..03633f28a 100644
--- a/test/integration/framework
+++ b/test/integration/framework
@@ -190,7 +190,7 @@ aptmark() { runapt apt-mark "$@"; }
 aptsortpkgs() { runapt apt-sortpkgs "$@"; }
 apt() { runapt apt "$@"; }
 apthelper() { runapt "${APTHELPERBINDIR}/apt-helper" "$@"; }
-aptwebserver() { runapt "${APTWEBSERVERBINDIR}/aptwebserver" "$@"; }
+aptwebserver() { runapt "${APTTESTHELPERSBINDIR}/aptwebserver" "$@"; }
 aptitude() { runapt aptitude "$@"; }
 aptextracttemplates() { runapt apt-extracttemplates "$@"; }
 aptinternalsolver() { runapt "${APTINTERNALSOLVER}" "$@"; }
@@ -331,7 +331,7 @@ setupenvironment() {
 	LIBRARYPATH="${APT_INTEGRATION_TESTS_LIBRARY_PATH:-"${BUILDDIRECTORY}/../apt-pkg"}"
         METHODSDIR="${APT_INTEGRATION_TESTS_METHODS_DIR:-"${BUILDDIRECTORY}/../methods"}"
         APTHELPERBINDIR="${APT_INTEGRATION_TESTS_LIBEXEC_DIR:-"${BUILDDIRECTORY}"}"
-        APTWEBSERVERBINDIR="${APT_INTEGRATION_TESTS_WEBSERVER_BIN_DIR:-"${BUILDDIRECTORY}/../test/interactive-helper"}"
+        APTTESTHELPERSBINDIR="${APT_INTEGRATION_TESTS_HELPERS_BIN_DIR:-"${BUILDDIRECTORY}/../test/interactive-helper"}"
         APTFTPARCHIVEBINDIR="${APT_INTEGRATION_TESTS_FTPARCHIVE_BIN_DIR:-"${BUILDDIRECTORY}/../ftparchive"}"
         APTINTERNALSOLVER="${APT_INTEGRATION_TESTS_INTERNAL_SOLVER:-"${BUILDDIRECTORY}/solvers/apt"}"
 	APTDUMPSOLVER="${APT_INTEGRATION_TESTS_DUMP_SOLVER:-"${BUILDDIRECTORY}/solvers/dump"}"
@@ -1296,7 +1296,7 @@ changetowebserver() {
 	else
 		shift
 	fi
-	if test -x "${APTWEBSERVERBINDIR}/aptwebserver"; then
+	if test -x "${APTTESTHELPERSBINDIR}/aptwebserver"; then
 		cd aptarchive
 		local LOG="webserver.log"
 		if ! aptwebserver --port 0 -o aptwebserver::fork=1 -o aptwebserver::portfile='aptwebserver.port' "$@" >$LOG 2>&1 ; then
diff --git a/test/integration/skip-apt-dropprivs b/test/integration/skip-apt-dropprivs
new file mode 100755
index 000000000..e0dd741cd
--- /dev/null
+++ b/test/integration/skip-apt-dropprivs
@@ -0,0 +1,32 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+
+setupenvironment
+configarchitecture 'amd64'
+
+aptdropprivs() { runapt "${APTTESTHELPERSBINDIR}/aptdropprivs" "$@"; }
+
+testsuccess aptdropprivs -- /bin/true
+testsuccess aptdropprivs --user "$USER" -- /bin/true
+testsuccess aptdropprivs --user 'nobody' -- /bin/true
+testsuccess aptdropprivs --user '_apt' -- /bin/true
+
+IDBIN='/usr/bin/id'
+testsuccessequal "$("$IDBIN")" aptdropprivs --user "$USER" -- "$IDBIN"
+
+SUDOBIN='/usr/bin/sudo'
+testequal "sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?" aptdropprivs --user 'nobody' -- "$SUDOBIN" "$IDBIN"
+
+if [ "$(id -u)" = '0' ]; then
+	testsuccessequal '_apt' aptdropprivs --user '_apt' -- "$IDBIN" '-un'
+	testsuccess aptdropprivs --user '_apt' -- '/bin/sh' '-c' 'export'
+	cp rootdir/tmp/testsuccess.output apt.env
+	testsuccessequal "export HOME='/nonexistent'" grep '^export HOME' apt.env
+	testsuccessequal "export USER='_apt'
+export USERNAME='_apt'" grep '^export USER' apt.env
+	testsuccessequal "export LOGNAME='_apt'" grep '^export LOGNAME' apt.env
+	testsuccessequal "export SHELL='/bin/sh'" grep '^export SHELL=' apt.env
+fi
diff --git a/test/interactive-helper/CMakeLists.txt b/test/interactive-helper/CMakeLists.txt
index 423fa30e6..5a32ca17e 100644
--- a/test/interactive-helper/CMakeLists.txt
+++ b/test/interactive-helper/CMakeLists.txt
@@ -6,6 +6,8 @@ add_executable(extract-control extract-control.cc)
 target_link_libraries(extract-control apt-pkg apt-inst)
 add_executable(aptwebserver aptwebserver.cc)
 target_link_libraries(aptwebserver apt-pkg  ${CMAKE_THREAD_LIBS_INIT})
+add_executable(aptdropprivs aptdropprivs.cc)
+target_link_libraries(aptdropprivs apt-pkg)
 add_executable(test_fileutl test_fileutl.cc)
 target_link_libraries(test_fileutl apt-pkg)
 
diff --git a/test/interactive-helper/aptdropprivs.cc b/test/interactive-helper/aptdropprivs.cc
new file mode 100644
index 000000000..1cc04f36a
--- /dev/null
+++ b/test/interactive-helper/aptdropprivs.cc
@@ -0,0 +1,27 @@
+#include <config.h>
+
+#include <apt-pkg/cmndline.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
+
+#include <unistd.h>
+
+int main(int const argc, const char * argv[])
+{
+   CommandLine::Args Args[] = {
+      {'c',"config-file",0,CommandLine::ConfigFile},
+      {'o',"option",0,CommandLine::ArbItem},
+      {0, "user", "APT::Sandbox::User", CommandLine::HasArg},
+      {0,0,0,0}
+   };
+
+   CommandLine CmdL(Args, _config);
+   if(CmdL.Parse(argc,argv) == false || DropPrivileges() == false)
+   {
+      _error->DumpErrors(std::cerr, GlobalError::DEBUG);
+      return 42;
+   }
+
+   return execv(CmdL.FileList[0], const_cast<char**>(CmdL.FileList));
+}