Red Hat Bugzilla – Bug 240915
[RHEL4] userdel/usermod infinite loop with duplicate names in /etc/group or /etc/gshadow
Last modified: 2016-06-10 10:05:24 EDT
Description of problem:
If you have a group file that looks something like the following:
And you try to "userdel deleteme", userdel will go into an endless loop, leaking
memory, and can eventually crash the machine with OOM kills. The obvious
problem here is having duplicate groups; however, it would be nicer to be more
resilient in the case of these sort of errors.
In userdel.c (and usermod.c), there is a loop that goes through all of the
groups, looking to delete the current user (in this case "deleteme") from all of
the groups. As it goes throug each group, it removes the entry (if it exists)
from the group, then "updates" the group list with the new group.
1) It hits the line with "badgroup::30266:root,deleteme"
2) It removes the "deleteme", so the line would look like "badgroup::30266:root"
3) But, gr_update() actually does a "find by name", that finds the first entry.
It then "updates" that first entry, but doesn't fix the line it was originally
supposed to fix (the second line).
4) Now it goes to the next iteration of the loop and sees that the second line
still has deleteme, so it goes back to step 2); it does this endlessly.
Two solutions come to mind:
1) Just bomb out when we see duplicate entries in /etc/group and/or
/etc/gshadow; that way the administrator can take corrective action without
userdel/usermod running off into the weeds.
2) Deal with multiple group definitions gracefully.
Created attachment 155199 [details]
Patch to deal with multiple groups gracefully
This patch take approach 2), in that it attempts to deal with the multiple
groups gracefully. While looking at what gr_update (and hence commonio_update)
does, it does a "find_by_name" to find the entry to update. This is where the
problem stems from. If, instead, we use the pointer of the current entry we
are looking for, we will always update exactly the right entry. That's what
this patch does, by adding a new "commonio_update_entry" and the associated gr_
and gshadow_ equivalents.
Note that this is also a problem in RHEL-5 and upstream; however, I wanted to
get some feedback about whether this is the correct approach before I send it
there. (Coincidentally, where is the upstream for this sort of stuff; I tried
shadow.pld.org.pl as listed in the SPEC, but it didn't seem to be active?)
Created attachment 155540 [details]
improved patch, which covers same problem in useradd(#151484)
This request was evaluated by Red Hat Product Management for
inclusion in a Red Hat Enterprise Linux release. Since this
bugzilla is in a component that is not approved for the current
release, it has been closed with resolution deferred. You may
reopen this bugzilla for consideration in the next release.
shadow-utils-188.8.131.52-15.fc7 has been pushed to the Fedora 7 stable repository. If problems still persist, please make note of it in this bug report.
Good that it is in F7, but we need this backported to RHEL-4. Re-opening.
This request was evaluated by Red Hat Product Management for inclusion in a Red
Hat Enterprise Linux maintenance release. Product Management has requested
further review of this request by Red Hat Engineering, for potential
inclusion in a Red Hat Enterprise Linux Update release for currently deployed
products. This request is not yet committed for inclusion in an Update
Reviewing the improved patch. In lib/commonio.c is this:
+ tmp->eptr = db->ops->dup(newgr);
+ if (tmp->eptr == NULL)
+ return 1;
Should that return 0 since its an error?
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.
Created attachment 303718 [details]
update grpconv to update_entry function
all commands that call gr_next after running gr_update on a dup group are at
at least grpconv is. patch attached.
groupadd - only update a non existant group, however broken nsswitch could make
getgrnam return 0, and find_by_name would get a dup. but luckily the gr_next
occurs before gr_update
newusers -similar to groupadd
grpunconv - needs to be fixed, can fix just like my attached patch, if it's