From 3927c6da48c206b6b251661f44680d9883b4f6b4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 24 Sep 2014 16:22:05 +0200 Subject: 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. --- apt-pkg/contrib/fileutl.cc | 34 +++++++++++++++++++++++++++++++++- debian/apt.postinst | 7 +++++++ methods/copy.cc | 2 ++ methods/ftp.cc | 3 +++ methods/gpgv.cc | 3 +++ methods/gzip.cc | 2 ++ methods/http_main.cc | 4 +++- methods/https.cc | 2 ++ 8 files changed, 55 insertions(+), 2 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 6b8f04dea..de67a94b9 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,10 @@ #include #include +#if __gnu_linux__ +#include +#endif + #include /*}}}*/ @@ -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; } diff --git a/debian/apt.postinst b/debian/apt.postinst index fd3e273bb..08dc60f9c 100644 --- a/debian/apt.postinst +++ b/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 diff --git a/methods/copy.cc b/methods/copy.cc index b78053d36..18d70e153 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -118,6 +118,8 @@ int main() { setlocale(LC_ALL, ""); + DropPrivs(); + CopyMethod Mth; return Mth.Run(); } diff --git a/methods/ftp.cc b/methods/ftp.cc index 66787a7be..9d58aa3b9 100644 --- a/methods/ftp.cc +++ b/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) diff --git a/methods/gpgv.cc b/methods/gpgv.cc index ae521a2ed..159417883 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -262,6 +263,8 @@ int main() { setlocale(LC_ALL, ""); + DropPrivs(); + GPGVMethod Mth; return Mth.Run(); diff --git a/methods/gzip.cc b/methods/gzip.cc index df3f8828f..518e58f82 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -135,6 +135,8 @@ int main(int, char *argv[]) { setlocale(LC_ALL, ""); + DropPrivs(); + Prog = strrchr(argv[0],'/'); ++Prog; diff --git a/methods/http_main.cc b/methods/http_main.cc index 3b346a514..788582632 100644 --- a/methods/http_main.cc +++ b/methods/http_main.cc @@ -1,5 +1,5 @@ #include - +#include #include #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(); } diff --git a/methods/https.cc b/methods/https.cc index 0499af0c5..a40f37710 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -443,6 +443,8 @@ int main() { setlocale(LC_ALL, ""); + DropPrivs(); + HttpsMethod Mth; curl_global_init(CURL_GLOBAL_SSL) ; -- cgit v1.2.3-70-g09d2 From 5f2047ece8c192d919cd97fea73759ce07b416ce Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 16:47:55 +0200 Subject: DropPriv: Really call seteuid and not setuid, and add more checks The only thing we are missing is non-portable saved ids support. --- apt-pkg/contrib/fileutl.cc | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index de67a94b9..72e2dabd5 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2175,9 +2175,12 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode) bool DropPrivs() { - if (getuid() != 0) - return true; + /* uid will be 0 in the end, but gid might be different anyway */ + uid_t old_uid = getuid(); + gid_t old_gid = getgid(); + if (old_uid != 0) + return true; if(_config->FindB("Debug::NoDropPrivs", false) == true) return true; @@ -2197,22 +2200,43 @@ bool DropPrivs() return _error->Errno("setgroups", "Failed to setgroups"); if (setegid(pw->pw_gid) != 0) - return _error->Errno("setgid", "Failed to setgid"); + return _error->Errno("setegid", "Failed to setegid"); + 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"); + if (seteuid(pw->pw_uid) != 0) + return _error->Errno("seteuid", "Failed to seteuid"); + + /* Try changing GID/EGID */ + if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) + return _error->Error("Could restore a gid to root, privilege dropping did not work"); + + if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) + return _error->Error("Could restore a uid to root, privilege dropping did not work"); + + /* Verify the list of supplementary groups is what we expected */ + gid_t groups[1]; + if (getgroups(1, groups) != 1) + return _error->Errno("getgroups", "Could not get new groups"); + if (groups[0] != pw->pw_gid) + return _error->Error("Could not switch group"); + /* Verify gid, egid, uid, and euid */ + if (getgid() != pw->pw_gid) + return _error->Error("Could not switch group"); + if (getegid() != pw->pw_gid) + return _error->Error("Could not switch effective group"); + if (getuid() != pw->pw_uid) + return _error->Error("Could not switch user"); + if (geteuid() != pw->pw_uid) + return _error->Error("Could not switch effective user"); + + /* TODO: Check saved uid/saved gid as well */ return true; } -- cgit v1.2.3-70-g09d2 From eed65c79322c3c79facdea44ce39033b21972e36 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 17:29:53 +0200 Subject: Use _apt as our unprivileged user name Some people want to standardize on it, and BSDs do it too, so let's do the same. Reported-by: Paul Wise --- apt-pkg/contrib/fileutl.cc | 2 +- debian/apt.postinst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 72e2dabd5..8e7313e8f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2184,7 +2184,7 @@ bool DropPrivs() if(_config->FindB("Debug::NoDropPrivs", false) == true) return true; - const std::string nobody = _config->Find("APT::User::Nobody", "Debian-apt"); + const std::string nobody = _config->Find("APT::User::Nobody", "_apt"); struct passwd *pw = getpwnam(nobody.c_str()); if (pw == NULL) return _error->Warning("No user %s, can not drop rights", nobody.c_str()); diff --git a/debian/apt.postinst b/debian/apt.postinst index 08dc60f9c..fab026504 100644 --- a/debian/apt.postinst +++ b/debian/apt.postinst @@ -28,8 +28,8 @@ case "$1" in # add unprivileged user for the apt methods adduser --force-badname --system --no-create-home \ - --quiet Debian-apt || true - chown -R Debian-apt:root \ + --quiet _apt || true + chown -R _apt:root \ /var/lib/apt/lists \ /var/cache/apt/archives -- cgit v1.2.3-70-g09d2 From 3b084f06b65ea073176b26fd9e472dc0f76b44b0 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 20:02:54 +0200 Subject: DropPrivs: Do not use an invalid return check for setgroups() setgroups() returns 0 on success Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 8e7313e8f..98544b60c 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2196,7 +2196,7 @@ bool DropPrivs() _error->Warning("PR_SET_NO_NEW_PRIVS failed with %i", ret); #endif - if (setgroups(1, &pw->pw_gid) != 1) + if (setgroups(1, &pw->pw_gid)) return _error->Errno("setgroups", "Failed to setgroups"); if (setegid(pw->pw_gid) != 0) -- cgit v1.2.3-70-g09d2 From 550ab420d398f303ff8cbc51e1f4dab79f8cbdf2 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 20:57:30 +0200 Subject: DropPrivs: Also check for saved set-user-ID and set-group-ID --- apt-pkg/contrib/fileutl.cc | 20 ++++++++++++++++++++ buildlib/config.h.in | 4 ++++ configure.ac | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 98544b60c..05c2f2e00 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2237,6 +2237,26 @@ bool DropPrivs() if (geteuid() != pw->pw_uid) return _error->Error("Could not switch effective user"); +#ifdef HAVE_GETRESUID + uid_t ruid = 0; + uid_t euid = 0; + uid_t suid = 0; + if (getresuid(&ruid, &euid, &suid)) + return _error->Errno("getresuid", "Could not get saved set-user-ID"); + if (suid != pw->pw_uid) + return _error->Error("Could not switch saved set-user-ID"); +#endif + +#ifdef HAVE_GETRESGID + gid_t rgid = 0; + gid_t egid = 0; + gid_t sgid = 0; + if (getresgid(&rgid, &egid, &sgid)) + return _error->Errno("getresuid", "Could not get saved set-group-ID"); + if (sgid != pw->pw_gid) + return _error->Error("Could not switch saved set-group-ID"); +#endif + /* TODO: Check saved uid/saved gid as well */ return true; } diff --git a/buildlib/config.h.in b/buildlib/config.h.in index 6b72fb393..c0fd2e8c6 100644 --- a/buildlib/config.h.in +++ b/buildlib/config.h.in @@ -28,6 +28,10 @@ /* If there is no socklen_t, define this for the netdb shim */ #undef NEED_SOCKLEN_T_DEFINE +/* We need the getresuid() function */ +#undef HAVE_GETRESUID +#undef HAVE_GETRESGID + /* Define to the size of the filesize containing structures */ #undef _FILE_OFFSET_BITS diff --git a/configure.ac b/configure.ac index 89950fccd..5d0e0a9db 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,12 @@ AC_EGREP_HEADER(h_errno, netdb.h, [AC_MSG_RESULT(normal)], [AC_MSG_ERROR("not found.")]) ]) + +dnl check for setuid checking function +AC_CHECK_FUNCS(getresuid getresgid) +AC_SUBST(HAVE_GETRESUID) +AC_SUBST(HAVE_GETRESGID) + dnl Check for doxygen AC_PATH_PROG(DOXYGEN, doxygen) -- cgit v1.2.3-70-g09d2 From f1e3c8f002be54617656fc4ca525c3f1e57323f3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 20:59:53 +0200 Subject: DropPrivs: Improve comments Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 05c2f2e00..7ccaaa03f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2175,7 +2175,7 @@ bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode) bool DropPrivs() { - /* uid will be 0 in the end, but gid might be different anyway */ + // uid will be 0 in the end, but gid might be different anyway uid_t old_uid = getuid(); gid_t old_gid = getgid(); @@ -2195,7 +2195,7 @@ bool DropPrivs() if(ret < 0) _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"); @@ -2207,27 +2207,27 @@ bool DropPrivs() 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 (seteuid(pw->pw_uid) != 0) return _error->Errno("seteuid", "Failed to seteuid"); - /* Try changing GID/EGID */ + // Check that uid and gid changes do not work anymore if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) return _error->Error("Could restore a gid to root, privilege dropping did not work"); if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) return _error->Error("Could restore a uid to root, privilege dropping did not work"); - /* Verify the list of supplementary groups is what we expected */ + // Verify that the user has only a single group, and the correct one gid_t groups[1]; if (getgroups(1, groups) != 1) return _error->Errno("getgroups", "Could not get new groups"); if (groups[0] != pw->pw_gid) return _error->Error("Could not switch group"); - /* Verify gid, egid, uid, and euid */ + + // Verify that gid, egid, uid, and euid changed if (getgid() != pw->pw_gid) return _error->Error("Could not switch group"); if (getegid() != pw->pw_gid) @@ -2257,6 +2257,5 @@ bool DropPrivs() return _error->Error("Could not switch saved set-group-ID"); #endif - /* TODO: Check saved uid/saved gid as well */ return true; } -- cgit v1.2.3-70-g09d2 From 7b18d5592fd5e0bb173e193d1e6693a66065f971 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 21:49:19 +0200 Subject: methods: Fail if we cannot drop privileges --- apt-pkg/acquire-method.cc | 12 ++++++++++++ apt-pkg/acquire-method.h | 2 +- methods/copy.cc | 4 ++-- methods/ftp.cc | 6 +++--- methods/gpgv.cc | 4 ++-- methods/gzip.cc | 5 +++-- methods/http_main.cc | 4 ++-- methods/https.cc | 4 ++-- 8 files changed, 27 insertions(+), 14 deletions(-) diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index e4a937d1d..82f2fb3ce 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -118,6 +118,18 @@ void pkgAcqMethod::Fail(string Err,bool Transient) std::cout << "\n" << std::flush; } + /*}}}*/ +// AcqMethod::DropPrivsOrDie - Drop privileges or die /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgAcqMethod::DropPrivsOrDie() +{ + if (!DropPrivs()) { + Fail(false); + exit(112); /* call the european emergency number */ + } +} + /*}}}*/ // AcqMethod::URIStart - Indicate a download is starting /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index cbf79f860..cdeecc9a7 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -105,7 +105,7 @@ class pkgAcqMethod pkgAcqMethod(const char *Ver,unsigned long Flags = 0); virtual ~pkgAcqMethod() {}; - + void DropPrivsOrDie(); private: APT_HIDDEN void Dequeue(); }; diff --git a/methods/copy.cc b/methods/copy.cc index 18d70e153..3883c822b 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -118,8 +118,8 @@ int main() { setlocale(LC_ALL, ""); - DropPrivs(); - CopyMethod Mth; + + Mth.DropPrivsOrDie(); return Mth.Run(); } diff --git a/methods/ftp.cc b/methods/ftp.cc index 9d58aa3b9..a658b5657 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -1107,9 +1107,6 @@ 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) @@ -1134,6 +1131,9 @@ int main(int, const char *argv[]) } FtpMethod Mth; + + // no more active ftp, sorry + Mth.DropPrivsOrDie(); return Mth.Run(); } diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 159417883..4071cbac6 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -262,10 +262,10 @@ bool GPGVMethod::Fetch(FetchItem *Itm) int main() { setlocale(LC_ALL, ""); - - DropPrivs(); GPGVMethod Mth; + Mth.DropPrivsOrDie(); + return Mth.Run(); } diff --git a/methods/gzip.cc b/methods/gzip.cc index 518e58f82..7ffcda60f 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -135,11 +135,12 @@ int main(int, char *argv[]) { setlocale(LC_ALL, ""); - DropPrivs(); - Prog = strrchr(argv[0],'/'); ++Prog; GzipMethod Mth; + + Mth.DropPrivsOrDie(); + return Mth.Run(); } diff --git a/methods/http_main.cc b/methods/http_main.cc index 788582632..d7724701a 100644 --- a/methods/http_main.cc +++ b/methods/http_main.cc @@ -12,8 +12,8 @@ int main() // closes the connection (this is dealt with via ServerDie()) signal(SIGPIPE, SIG_IGN); - DropPrivs(); - HttpMethod Mth; + + Mth.DropPrivsOrDie(); return Mth.Loop(); } diff --git a/methods/https.cc b/methods/https.cc index a40f37710..a74d2a38b 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -443,11 +443,11 @@ int main() { setlocale(LC_ALL, ""); - DropPrivs(); - HttpsMethod Mth; curl_global_init(CURL_GLOBAL_SSL) ; + Mth.DropPrivsOrDie(); + return Mth.Run(); } -- cgit v1.2.3-70-g09d2 From bdc00df54d97c2825ce37dd1c249f633f199a80b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 21:53:45 +0200 Subject: DropPrivs: Move the re-set uid/gid thing to the end of the function Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 7ccaaa03f..6b54c81f9 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2213,13 +2213,6 @@ bool DropPrivs() if (seteuid(pw->pw_uid) != 0) return _error->Errno("seteuid", "Failed to seteuid"); - // Check that uid and gid changes do not work anymore - if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) - return _error->Error("Could restore a gid to root, privilege dropping did not work"); - - if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) - return _error->Error("Could restore a uid to root, privilege dropping did not work"); - // Verify that the user has only a single group, and the correct one gid_t groups[1]; if (getgroups(1, groups) != 1) @@ -2257,5 +2250,12 @@ bool DropPrivs() return _error->Error("Could not switch saved set-group-ID"); #endif + // Check that uid and gid changes do not work anymore + if (pw->pw_gid != old_gid && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) + return _error->Error("Could restore a gid to root, privilege dropping did not work"); + + if (pw->pw_uid != old_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) + return _error->Error("Could restore a uid to root, privilege dropping did not work"); + return true; } -- cgit v1.2.3-70-g09d2 From 48ed0977d23aeddfea58be967082ded0833fe227 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 22:00:33 +0200 Subject: DropPrivs: Add some comments for the more obscure setuid/setgid functions Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 6b54c81f9..b092a7798 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2231,6 +2231,7 @@ bool DropPrivs() return _error->Error("Could not switch effective user"); #ifdef HAVE_GETRESUID + // verify that the saved set-user-id was changed as well uid_t ruid = 0; uid_t euid = 0; uid_t suid = 0; @@ -2241,6 +2242,7 @@ bool DropPrivs() #endif #ifdef HAVE_GETRESGID + // verify that the saved set-group-id was changed as well gid_t rgid = 0; gid_t egid = 0; gid_t sgid = 0; -- cgit v1.2.3-70-g09d2 From ca8e327ab742c892485d2cd1478c756ac40b6912 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 22:07:27 +0200 Subject: DropPrivs: Hard-fail if the user does not exist Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index b092a7798..9d09dcdd3 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2187,7 +2187,7 @@ bool DropPrivs() const std::string nobody = _config->Find("APT::User::Nobody", "_apt"); struct passwd *pw = getpwnam(nobody.c_str()); if (pw == NULL) - return _error->Warning("No user %s, can not drop rights", nobody.c_str()); + return _error->Error("No user %s, can not drop rights", nobody.c_str()); #if __gnu_linux__ // see prctl(2), needs linux3.5 -- cgit v1.2.3-70-g09d2 From b8dae9a106791ef9f47a516ccb62ab6050f22282 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 22:26:41 +0200 Subject: DropPrivs: Use APT::Sandbox::User instead of Apt::User::Nobody Git-Dch: ignore --- apt-pkg/contrib/fileutl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 9d09dcdd3..e81f32a52 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2184,10 +2184,10 @@ bool DropPrivs() if(_config->FindB("Debug::NoDropPrivs", false) == true) return true; - const std::string nobody = _config->Find("APT::User::Nobody", "_apt"); - struct passwd *pw = getpwnam(nobody.c_str()); + 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", nobody.c_str()); + return _error->Error("No user %s, can not drop rights", toUser.c_str()); #if __gnu_linux__ // see prctl(2), needs linux3.5 -- cgit v1.2.3-70-g09d2 From 13a28d8549015d2b55fadef450bc56327b4ca7a2 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 24 Sep 2014 22:28:44 +0200 Subject: DropPrivs: Document what it does Git-Dch: ignore --- apt-pkg/contrib/fileutl.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index a8e255b86..9dd29eb9e 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -199,7 +199,17 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap = false); // check if the given file starts with a PGP cleartext signature bool StartsWithGPGClearTextSignature(std::string const &FileName); -// process releated +/** + * \brief Drop privileges + * + * Drop the privileges to the user _apt (or the one specified in + * APT::Sandbox::User). This does not set the supplementary group + * ids up correctly, it only uses the default group. Also prevent + * the process from gaining any new privileges afterwards, at least + * on Linux. + * + * \return true on success, false on failure with _error set + */ bool DropPrivs(); // File string manipulators -- cgit v1.2.3-70-g09d2 From 47d278dc7184606f751d015689e0c49eccde4547 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 24 Sep 2014 20:14:55 +0200 Subject: releasing package apt version 1.1~exp3 --- debian/changelog | 19 +++++++++++++++++++ methods/http_main.cc | 1 + 2 files changed, 20 insertions(+) diff --git a/debian/changelog b/debian/changelog index 32447d5e1..acbe7ddba 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +apt (1.1~exp3) experimental; urgency=medium + + [ Michael Vogt ] + * merged changes from debian/sid up to 1.0.9.1 + * Make /var/lib/apt/lists and /var/cache/apt/archives owned + by the new _apt user + * Drop Privileges in the following acquire methods: + copy, http, https, ftp, gpgv, gzip/bzip2/lzma/xz + * DropPrivs: Improvements based on feedback from error@debian.org + + [ Julian Andres Klode ] + * DropPriv: Really call seteuid and not setuid, and add more checks + * Use _apt as our unprivileged user name + * DropPrivs: Also check for saved set-user-ID and set-group-ID + * methods: Fail if we cannot drop privileges + * DropPrivs: Also check for saved set-user-ID and set-group-ID + + -- Michael Vogt Wed, 24 Sep 2014 22:30:09 +0200 + apt (1.1~exp2) experimental; urgency=medium [ Guillem Jover ] diff --git a/methods/http_main.cc b/methods/http_main.cc index d7724701a..f21a5709c 100644 --- a/methods/http_main.cc +++ b/methods/http_main.cc @@ -1,5 +1,6 @@ #include #include +#include #include #include "http.h" -- cgit v1.2.3-70-g09d2