Browse Source

Drop Privileges to "Debian-apt" in most acquire methods

Add a new "Debian-apt" user that owns the /var/lib/apt/lists
and /var/cache/apt/archive directories. The methods
http, https, ftp, gpgv, gzip switch to this user when they
start.

Thanks to Julian and "ioerror" and tors "switch_id()" code.
Michael Vogt 9 years ago
parent
commit
3927c6da48
8 changed files with 55 additions and 2 deletions
  1. 33 1
      apt-pkg/contrib/fileutl.cc
  2. 7 0
      debian/apt.postinst
  3. 2 0
      methods/copy.cc
  4. 3 0
      methods/ftp.cc
  5. 3 0
      methods/gpgv.cc
  6. 2 0
      methods/gzip.cc
  7. 3 1
      methods/http_main.cc
  8. 2 0
      methods/https.cc

+ 33 - 1
apt-pkg/contrib/fileutl.cc

@@ -48,6 +48,7 @@
 #include <errno.h>
 #include <glob.h>
 #include <pwd.h>
+#include <grp.h>
 
 #include <set>
 #include <algorithm>
@@ -64,6 +65,10 @@
 #include <endian.h>
 #include <stdint.h>
 
+#if __gnu_linux__
+#include <sys/prctl.h>
+#endif
+
 #include <apti18n.h>
 									/*}}}*/
 
@@ -2173,14 +2178,41 @@ bool DropPrivs()
    if (getuid() != 0)
       return true;
 
-   const std::string nobody = _config->Find("APT::User::Nobody", "nobody");
+   if(_config->FindB("Debug::NoDropPrivs", false) == true)
+      return true;
+
+   const std::string nobody = _config->Find("APT::User::Nobody", "Debian-apt");
    struct passwd *pw = getpwnam(nobody.c_str());
    if (pw == NULL)
       return _error->Warning("No user %s, can not drop rights", nobody.c_str());
+
+#if __gnu_linux__
+   // see prctl(2), needs linux3.5
+   int ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0,0, 0);
+   if(ret < 0)
+      _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret);
+#endif
+
+   if (setgroups(1, &pw->pw_gid) != 1)
+      return _error->Errno("setgroups", "Failed to setgroups");
+
+   if (setegid(pw->pw_gid) != 0)
+      return _error->Errno("setgid", "Failed to setgid");
    if (setgid(pw->pw_gid) != 0)
       return _error->Errno("setgid", "Failed to setgid");
+   
    if (setuid(pw->pw_uid) != 0)
       return _error->Errno("setuid", "Failed to setuid");
+   // the seteuid() is probably uneeded (at least thats what the linux
+   // man-page says about setuid(2)) but we cargo culted it anyway
+   if (setuid(pw->pw_uid) != 0)
+      return _error->Errno("setuid", "Failed to setuid");
+
+   // be defensive
+   if(setgid(0) != -1 || setegid(0) != -1)
+      return _error->Error("Could restore gid to root, privilege dropping does not work");
+   if(setuid(0) != -1 || seteuid(0) != -1)
+      return _error->Error("Could restore uid to root, privilege dropping does not work");
 
    return true;
 }

+ 7 - 0
debian/apt.postinst

@@ -26,6 +26,13 @@ case "$1" in
 	    fi
 	fi
 
+        # add unprivileged user for the apt methods
+        adduser --force-badname --system --no-create-home \
+            --quiet Debian-apt || true
+        chown -R Debian-apt:root \
+            /var/lib/apt/lists \
+            /var/cache/apt/archives
+
         # ensure tighter permissons on the logs, see LP: #975199
         if dpkg --compare-versions "$2" lt-nl 0.9.7.7; then
             # ensure permissions are right

+ 2 - 0
methods/copy.cc

@@ -118,6 +118,8 @@ int main()
 {
    setlocale(LC_ALL, "");
 
+   DropPrivs();
+
    CopyMethod Mth;
    return Mth.Run();
 }

+ 3 - 0
methods/ftp.cc

@@ -1107,6 +1107,9 @@ int main(int, const char *argv[])
 { 
    setlocale(LC_ALL, "");
 
+   // no more active ftp, sorry
+   DropPrivs();
+
    /* See if we should be come the http client - we do this for http
       proxy urls */
    if (getenv("ftp_proxy") != 0)

+ 3 - 0
methods/gpgv.cc

@@ -5,6 +5,7 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/gpgv.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/fileutl.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -262,6 +263,8 @@ int main()
 {
    setlocale(LC_ALL, "");
    
+   DropPrivs();
+
    GPGVMethod Mth;
 
    return Mth.Run();

+ 2 - 0
methods/gzip.cc

@@ -135,6 +135,8 @@ int main(int, char *argv[])
 {
    setlocale(LC_ALL, "");
 
+   DropPrivs();
+
    Prog = strrchr(argv[0],'/');
    ++Prog;
 

+ 3 - 1
methods/http_main.cc

@@ -1,5 +1,5 @@
 #include <config.h>
-
+#include <apt-pkg/fileutl.h>
 #include <signal.h>
 
 #include "http.h"
@@ -12,6 +12,8 @@ int main()
    // closes the connection (this is dealt with via ServerDie())
    signal(SIGPIPE, SIG_IGN);
 
+   DropPrivs();
+
    HttpMethod Mth;
    return Mth.Loop();
 }

+ 2 - 0
methods/https.cc

@@ -443,6 +443,8 @@ int main()
 {
    setlocale(LC_ALL, "");
 
+   DropPrivs();
+
    HttpsMethod Mth;
    curl_global_init(CURL_GLOBAL_SSL) ;