[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: [PATCH] adduser can create duplicate users
From: Tito <farmatito () tiscali ! it>
Date: 2007-10-27 13:59:25
Message-ID: 200710271559.25601.farmatito () tiscali ! it
[Download RAW message or body]
Hi,
this patch fixes a problem in adduser spotted by Ralf Friedl:
>Also, I think it is possible that this implementation results in
>duplicate user ids:
>The first loop, "while (!fgetpwent_r(..." find a free user id.
>The second loop, "while (getgrgid(p->pw_uid)) p->pw_uid++;" increments
>uid until it finds an unused group id.
>It is possible that this incremented uid is in use as a user id.
The patch is tested and works for me but I would like it to be reviewed on the list
to avoid some of mine silly errors ;-) .
As side effect the patch also reduces size:
root@localhost:~/Desktop/busybox.latest# scripts/bloat-o-meter busybox_old busybox_unstripped
function old new delta
bb_internal_fgetpwent_r 51 - -51
adduser_main 909 679 -230
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-281) Total: -281 bytes
The patch changes the passwd_study function:
static int passwd_study(const char *filename, struct passwd *p)
{
enum { min = 500, max = 65000 };
FILE *passwd;
passwd = xfopen(filename, "r");
/* EDR if uid is out of bounds, set to min */
if ((p->pw_uid > max) || (p->pw_uid < min))
p->pw_uid = min;
/* check for an already in use login name */
if (getpwnam(p->pw_name))
return 1;
/* search a free uid */
while (getpwuid(p->pw_uid))
p->pw_uid++;
if (!p->pw_gid) {
/* check for an already in use group name */
if (getgrnam(p->pw_name))
return 3;
/* search a free gid and free uid with the same value */
while (getgrgid(p->pw_uid) || getpwuid(p->pw_uid))
p->pw_uid++;
/* set gid = uid */
p->pw_gid = p->pw_uid;
}
/* EDR bounds check, could not be less than min */
if (p->pw_uid > max)
return 2;
return 0;
}
Ciao,
Tito
["adduser_fix.patch" (text/x-diff)]
--- loginutils/adduser.c.orig 2007-10-27 08:57:23.000000000 +0200
+++ loginutils/adduser.c 2007-10-27 15:54:25.000000000 +0200
@@ -20,11 +20,6 @@
{
enum { min = 500, max = 65000 };
FILE *passwd;
- /* We are using reentrant fgetpwent_r() in order to avoid
- * pulling in static buffers from libc (think static build here) */
- char buffer[256];
- struct passwd pw;
- struct passwd *result;
passwd = xfopen(filename, "r");
@@ -32,39 +27,29 @@
if ((p->pw_uid > max) || (p->pw_uid < min))
p->pw_uid = min;
- /* stuff to do:
- * make sure login isn't taken;
- * find free uid and gid;
- */
- while (!fgetpwent_r(passwd, &pw, buffer, sizeof(buffer), &result)) {
- if (strcmp(pw.pw_name, p->pw_name) == 0) {
- /* return 0; */
- return 1;
- }
- if ((pw.pw_uid >= p->pw_uid) && (pw.pw_uid < max)
- && (pw.pw_uid >= min)) {
- p->pw_uid = pw.pw_uid + 1;
- }
- }
-
- if (p->pw_gid == 0) {
- /* EDR check for an already existing gid */
- while (getgrgid(p->pw_uid) != NULL)
- p->pw_uid++;
-
- /* EDR also check for an existing group definition */
- if (getgrnam(p->pw_name) != NULL)
+ /* check for an already in use login name */
+ if (getpwnam(p->pw_name))
+ return 1;
+
+ /* search a free uid */
+ while (getpwuid(p->pw_uid))
+ p->pw_uid++;
+
+ if (!p->pw_gid) {
+ /* check for an already in use group name */
+ if (getgrnam(p->pw_name))
return 3;
-
- /* EDR create new gid always = uid */
+ /* search a free gid and free uid with the same value */
+ while (getgrgid(p->pw_uid) || getpwuid(p->pw_uid))
+ p->pw_uid++;
+ /* set gid = uid */
p->pw_gid = p->pw_uid;
}
- /* EDR bounds check */
- if ((p->pw_uid > max) || (p->pw_uid < min))
+ /* EDR bounds check, could not be less than min */
+ if (p->pw_uid > max)
return 2;
- /* return 1; */
return 0;
}
_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic