summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2014-10-07 21:17:04 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2014-10-07 21:17:04 +0200
commit8f45798d532223adc378a4ad9ecfc64b3be26e4f (patch)
treede964d38c9c216670993f188ed592b8cc900ae58
parentf8aba23f2e8a4c52869cd3869a716df28267597a (diff)
set PR_SET_NO_NEW_PRIVS also if run as non-root
Changing user and co works only as root, but can do some things for methods run as normal user as well to protect them from being able to call setuid binaries like sudo to elevate their privileges. Also uses a cheap trick now to build with old unsupporting kernels.
-rw-r--r--apt-pkg/contrib/fileutl.cc27
1 files changed, 16 insertions, 11 deletions
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 86eec7c36..844a6bd3c 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -2165,27 +2165,32 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode)/
/*}}}*/
bool DropPrivileges() /*{{{*/
{
+ if(_config->FindB("Debug::NoDropPrivs", false) == true)
+ return true;
+
+#if __gnu_linux__
+#if defined(PR_SET_NO_NEW_PRIVS) && ( PR_SET_NO_NEW_PRIVS != 38 )
+#error "PR_SET_NO_NEW_PRIVS is defined, but with a different value than expected!"
+#endif
+ // see prctl(2), needs linux3.5 at runtime - magic constant to avoid it at buildtime
+ int ret = prctl(38, 1, 0, 0, 0);
+ // ignore EINVAL - kernel is too old to understand the option
+ if(ret < 0 && errno != EINVAL)
+ _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
+#endif
+
// uid will be 0 in the end, but gid might be different anyway
- uid_t old_uid = getuid();
- gid_t old_gid = getgid();
+ uid_t const old_uid = getuid();
+ gid_t const old_gid = getgid();
if (old_uid != 0)
return true;
- if(_config->FindB("Debug::NoDropPrivs", false) == true)
- return true;
const std::string toUser = _config->Find("APT::Sandbox::User", "_apt");
struct passwd *pw = getpwnam(toUser.c_str());
if (pw == NULL)
return _error->Error("No user %s, can not drop rights", toUser.c_str());
-#if __gnu_linux__
- // see prctl(2), needs linux3.5
- int ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
- // ignore EINVAL - kernel is too old to understand the option
- if(ret < 0 && errno != EINVAL)
- _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
-#endif
// Do not change the order here, it might break things
if (setgroups(1, &pw->pw_gid))
return _error->Errno("setgroups", "Failed to setgroups");