Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Jul 2001 13:06:51 -0400
From:      "Jeroen C. van Gelderen" <jeroen@vangelderen.org>
To:        FreeBSD Stable <freebsd-stable@FreeBSD.ORG>
Subject:   initgroups unsolicited warning?
Message-ID:  <3B5713AB.79322FDA@vangelderen.org>

next in thread | raw e-mail | index | archive | help
Hi,

I am in the process of moving an anoncvs server from a 3.2 box to a
4-STABLE
machine and I've run into what I think is a libc problem. I'll try and
explain...

The anoncvs server basically is inetd listening on port 2401:
 cvspserver  stream  tcp  nowait/4/4  root  /usr/local/sbin/pserver
pserver

Instead of directly executing the CVS binary this calls a little wrapper
program
that does a chroot/setgid(2401)/setuid(2401) before it execs cvs,
effectively
creating a sandbox. This setup worked flawlessly on my 3.2 box but on a
4-STABLE
box it all of a sudden starts to cause problems :(

More specifically, the CVS client tells me:

 grolsch$ cvs get projects
 cvs [checkout aborted]: unrecognized auth response from
anoncvs.cryptix.org: 
     cvs: setgroups: Operation not permitted

I traced this to the following section of code in
contrib/cvs/src/server.c :
                                               
 #if HAVE_INITGROUPS
     if (initgroups (pw->pw_name, pw->pw_gid) < 0
 #  ifdef EPERM
         /* At least on the system I tried, initgroups() only works as
root.
            But we do still want to report ENOMEM and whatever other
            errors initgroups() might dish up.  */
         && errno != EPERM
 #  endif
         )
     {
         /* This could be a warning, but I'm not sure I see the point
            in doing that instead of an error given that it would happen
            on every connection.  We could log it somewhere and not tell
            the user.  But at least for now make it an error.  */
         printf ("error 0 initgroups failed: %s\n", strerror (errno));
         /* Don't worry about server_cleanup; server_active isn't set
yet.  */
         error_exit ();
     }
 #endif /* HAVE_INITGROUPS */

That is to say that I #ifdef-ed out this snippet and anoncvs worked
fine. As you
can see the intent is to try the initgroups (which will fail because we
are not
running as uid 0) and silently ignore EPERM. Problem is that our libc
does not
allow silent failure. From initgroups.c :

 int
 initgroups(uname, agroup)
         const char *uname;
         int agroup;
 {
         int groups[NGROUPS], ngroups;
 
         ngroups = NGROUPS;
         if (getgrouplist(uname, agroup, groups, &ngroups) < 0)
                 warnx("%s is in too many groups, using first %d",
                     uname, ngroups);
         if (setgroups(ngroups, groups) < 0) {
                 warn("setgroups");
                 ^^^^^^^^^^^^^^^^^^
                 return (-1);
         }
         return (0);
 }

This is pretty gross, a library call that spits out messages and it
clobbers the
pserver protocol and confuses the cvs client. I think the appropriate
fix is to
get rid of the warn statement:

Index: gen/initgroups.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/initgroups.c,v
retrieving revision 1.3
diff -c -r1.3 initgroups.c
*** gen/initgroups.c    1996/07/12 18:53:56     1.3
--- gen/initgroups.c    2001/07/19 17:02:04
***************
*** 53,59 ****
                warnx("%s is in too many groups, using first %d",
                    uname, ngroups);
        if (setgroups(ngroups, groups) < 0) {
-               warn("setgroups");
                return (-1);
        }
        return (0);
--- 53,58 ----


Comments? Should I file this as a PR when I can reach the freebsd.org
host again?

Cheers,
-JC


---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---

#include  <stdio.h>
#define BASE   "/home/anoncvs"
#define UID 2401
#define GID 2401
 
void error(int ret, char* msg)
{
        fprintf(stderr, "pserver failed: %s\n", msg);
        exit(ret);
}
 
 
int main(int argc, char* argv[])
{
        if( chdir(BASE)  ) error(1, "Could not chdir to " BASE);
        if( chroot(BASE) ) error(2, "Could not chroot to " BASE);
        if( setgid(GID)  ) error(3, "Could not set gid");
        if( setegid(GID) ) error(3, "Could not set gid");
        if( setuid(UID)  ) error(4, "Could not set uid");
        if( seteuid(UID) ) error(4, "Could not set uid");
        execl("/bin/cvs", "cvs",
              "--allow-root=/cvsroot-cryptix",
"--allow-root=/cvsroot-webfunds",
              "pserver", NULL);
        error(5, "Could not exec CVS");
}


-- 
Jeroen C. van Gelderen - jeroen@vangelderen.org

"A government that robs Peter to pay Paul can always depend
  upon the support of Paul."  --  George Bernard Shaw

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3B5713AB.79322FDA>