]> git.saurik.com Git - apt.git/commitdiff
set PR_SET_NO_NEW_PRIVS also if run as non-root
authorDavid Kalnischkies <david@kalnischkies.de>
Tue, 7 Oct 2014 19:17:04 +0000 (21:17 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Tue, 7 Oct 2014 19:17:04 +0000 (21:17 +0200)
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.

apt-pkg/contrib/fileutl.cc

index 86eec7c366d0ee78afc74ebdd16221842e235cbc..844a6bd3cd53d02c61c6539834234ff7090bbe3b 100644 (file)
@@ -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");