[PATCH] addgroup could assign already in use group
tito
farmatito at tiscali.it
Sat Feb 7 20:44:51 UTC 2015
Hi,
just a ping.
Ciao,
Tito
On Saturday 20 September 2014 16:45:14 tito wrote:
> 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
>
More information about the busybox
mailing list