[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [PATCH] addgroup could assign already in use group
From:       tito <farmatito () tiscali ! it>
Date:       2014-09-20 14:45:14
Message-ID: 201409201645.14614.farmatito () tiscali ! it
[Download RAW message or body]

Hi,
while looking at the long username stuff and malloced getpwxx functions
I've noticed a bug in addgroup resulting in assignement of a wrong
(already in use) gid. In the function xgroup_study:

static void xgroup_study(struct group *g)
{

snip

	/* Check if the desired gid is free
	 * or find the first free one */
	while (1) {
		if (!getgrgid(g->gr_gid)) {


			return; /* found free group: return */
		}
snip

		g->gr_gid++;
	}
}

The call to getgrgid can return NULL also in case of error:

       0 or ENOENT or ESRCH or EBADF or EPERM or ...
              The given name or gid was not found.

       EINTR  A signal was caught.

       EIO    I/O error.

       EMFILE The maximum number (OPEN_MAX) of files was open already in the calling \
process.

       ENFILE The maximum number of files was open already in the system.

       ENOMEM Insufficient memory to allocate group structure.

       ERANGE Insufficient buffer space supplied.

a simple fix would be:

	while (1) {
-		if (!getgrgid(g->gr_gid)) {
+		if (!getgrgid(g->gr_gid) && errno == 0) {

which is tested and works with glibc but this is not optimal because as man page \
says:

"Experiments on various UNIX-like  systems shows that lots of different values occur \
in this situation:"  (entry is not found) "0, ENOENT, EBADF, ESRCH, EWOULDBLOCK, \
EPERM and probably others."

A better solution would be to use getgrgid_r but this increases binary size:

 diff -uNp loginutils/addgroup.c.original loginutils/addgroup.c
--- loginutils/addgroup.c.original      2014-08-13 13:56:04.000000000 +0200
+++ loginutils/addgroup.c       2014-09-20 16:32:44.193586505 +0200
@@ -32,7 +32,10 @@
 static void xgroup_study(struct group *g)
 {
        unsigned max = CONFIG_LAST_ID;
-
+       struct group  *gr;
+       struct group  grp;
+       char buffer[256];
+
        /* Make sure gr_name is unused */
        if (getgrnam(g->gr_name)) {
                bb_error_msg_and_die("%s '%s' in use", "group", g->gr_name);
@@ -53,8 +56,9 @@ static void xgroup_study(struct group *g
        /* Check if the desired gid is free
         * or find the first free one */
        while (1) {
-               if (!getgrgid(g->gr_gid)) {
-                       return; /* found free group: return */
+               if (getgrgid_r(g->gr_gid, &grp, buffer, 256, &gr) == 0) {
+                       if (gr == NULL)
+                               return; /* found free group: return */
                }
                if (option_mask32 & OPT_GID) {
                        /* -g N, cannot pick gid other than N: error */


Attached is a patch with this solution if you think it is worth the effort and size
increase to fix this corner case.

Ciao,
Tito


["addgroup2.patch" (text/x-patch)]

Addgroup could assign a wrong (already in use) gid
as getgrgid returns NULL also on error (e.g. ERANGE).

Signed-off-by: Tito Ragusa <farmatito@tiscali.it>

--- loginutils/addgroup.c.original	2014-08-13 13:56:04.000000000 +0200
+++ loginutils/addgroup.c	2014-09-20 16:32:44.193586505 +0200
@@ -32,7 +32,10 @@
 static void xgroup_study(struct group *g)
 {
 	unsigned max = CONFIG_LAST_ID;
-
+	struct group  *gr;
+	struct group  grp;
+	char buffer[256];
+	
 	/* Make sure gr_name is unused */
 	if (getgrnam(g->gr_name)) {
 		bb_error_msg_and_die("%s '%s' in use", "group", g->gr_name);
@@ -53,8 +56,9 @@ static void xgroup_study(struct group *g
 	/* Check if the desired gid is free
 	 * or find the first free one */
 	while (1) {
-		if (!getgrgid(g->gr_gid)) {
-			return; /* found free group: return */
+		if (getgrgid_r(g->gr_gid, &grp, buffer, 256, &gr) == 0) {
+			if (gr == NULL)
+				return; /* found free group: return */
 		}
 		if (option_mask32 & OPT_GID) {
 			/* -g N, cannot pick gid other than N: error */


_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic