[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#806475: apt: Breaks debian-installer build, select with no read/write fds?



On Fri, Nov 27, 2015 at 09:08:35PM +0100, Cyril Brulebois wrote:
> | E: Method gave invalid 400 URI Failure message: Could not get new groups - getgroups (22: Invalid argument)
> | E: Method copy has died unexpectedly!
> | E: Sub-process copy returned an error code (112)

So, getgroups gets called there to verify that we really lost all groups
(beside the one _apt is in: nogroup). A few lines above we set the list
of (supplementary) groups containing only this group, then we switch uid
and gid (the later isn't enough for group switching aka we would be
still in root without the setgroups before).

So, us calling getgroups should really only return one group. Getting an
EINVAL suggests we get more than one… that is probably bad, but I have
a slight glimmer of hope that its just two times the same group – even
if that makes no sense… anyway, I can't reproduce this at the moment, so
it would be nice if someone could try the attached patch which could at
least tell us in which groups we remain (or it just works if we really
see duplicated groups here). Everything is possible I guess.

Given that schroot is involved mentioning if your host has an _apt user
or not might also help. As I learned today schroot is copying users and
groups into the schroot which makes all of this kinda strange… (#565613)
[two years of testing and you are still surprised on release…]

btw: To not block anyone: You can use the config option
Debug::NoDropPrivs to true to disable privilege dropping for the moment.


Best regards

David Kalnischkies
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 46de634..f754b31 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -2322,12 +2322,17 @@ bool DropPrivileges()							/*{{{*/
       return _error->Errno("seteuid", "Failed to seteuid");
 #endif
 
-   // 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 that the user isn't still in any supplementary groups
+   long const ngroups_max = sysconf(_SC_NGROUPS_MAX);
+   std::unique_ptr<gid_t[]> gidlist(new gid_t[ngroups_max]);
+   if (unlikely(gidlist == NULL))
+      return _error->Error("Allocation of a list of size %lu for getgroups failed", ngroups_max);
+   ssize_t gidlist_nr;
+   if ((gidlist_nr = getgroups(ngroups_max, gidlist.get())) < 0)
+      return _error->Errno("getgroups", "Could not get new groups (%lu)", ngroups_max);
+   for (ssize_t i = 0; i < gidlist_nr; ++i)
+      if (gidlist[i] != pw->pw_gid)
+	 return _error->Error("Could not switch group, user %s is still in group %d", toUser.c_str(), gidlist[i]);
 
    // Verify that gid, egid, uid, and euid changed
    if (getgid() != pw->pw_gid)

Attachment: signature.asc
Description: PGP signature


Reply to: