[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Daemon impotent after dropping priviledges with setuid()



I think I understand what's happening, though I'm not sure that it should...

After the daemon's double-fork (with setsid()), the utility of the group
identification seems lost.

With a bit more detail:
	Say I have a directory owned by user "user1", who is a member of
"group1"; and that "user2" is also a member of "group1".  The directory
is set up to have group write permissions.
	Before the double-fork, yada yada, all members of "group1" can
write to this directory.  After the double-fork, only "user1" can write
to the directory.

It doesn't seem right, but that is what I observe.

The even stranger thing is that the program will append to an existing file...
just not create a new file.  This seems wrong.

Am I ignorant?  Does this happen on other people's machines?  Here's a simple
program that should demonstrate the problem, if you substitute three names,
see below:

======================================= testuid.c

/*  testuid.c       Testing post-setuid() functionality.
 */

#include    <sys/types.h>   // pid_t
#include    <unistd.h>      // getuid()
#include    <stdio.h>
#include    <string.h>

// ------------------ MAKE APPROPRIATE SUBSTITUTIONS FOR THESE:

#define     DIR_FILE_NAME       "/full/path/filename"
#define	    ALT_GRP_ID		1000		// substitute group id
#define	    ALT_USER_ID		1000		// substitute user id

// ------------------ WRITE FILE TO PATH/NAME

#define     MAX_FILE_LEN        512
#define     MAX_EXTN_LEN        10
#define     MAX_PARTIAL_FLEN    (MAX_FILE_LEN-(MAX_EXTN_LEN+2))

static int writeDiagFile(const char *extn, const char *msg)
{
  char      fname[MAX_FILE_LEN];
  FILE      *f= NULL;

    strncpy(fname, DIR_FILE_NAME, MAX_PARTIAL_FLEN);
    fname[MAX_PARTIAL_FLEN - 1]= '\0';
    strcat(fname, ".");
    strncat(fname, extn, MAX_EXTN_LEN);
    fname[MAX_FILE_LEN-1]= '\0';

    f= fopen(fname, "a+");
    if (!f)
    {   fprintf(stderr, "Unable to open file [%s] for writing by (%d,%d)", fname, getuid(),geteuid());
        perror("fopen");
        return -1;
    }
    fprintf(f, "Msg {%s} <= %s as %d\n", extn, msg, getuid());
    fclose(f);
    return 0;
}

int main(int argc, char * const argv[])
{
  int           retval;
  pid_t         xpid, ypid;

    if (writeDiagFile("beginning user", "1"))
        return -10;
    xpid= fork();
    if (0 > xpid)
    {   perror("fork problem");
        return xpid;
    }
    if (0 == xpid)  // only child does more
    {   if (writeDiagFile("child - after 1st fork", "2"))
            return -11;

        setsid();
        if (writeDiagFile("child - after fork/setsid()", "3"))
            return -12;

        ypid= fork();
        if (0 > ypid)
        {   perror("fork problem");
            return ypid;
        }
        if (0 == ypid)  // only child does more
        {   if (writeDiagFile("child - after fork/setsid/fork", "4"))
                return -13;
            retval= setgid(ALT_GRP_ID);  // valid group on system
            if (retval)
            {   perror("setgid");
                return retval;
            }
            retval= setuid(ALT_USER_ID); // valid user on system
            if (retval)
            {   perror("setuid");
                return retval;
            }

            if (writeDiagFile("child - after fork/setsid/fork/setuid", "5"))
                return -14;
            putc('\n', stderr);
        }
    }
    return retval;
}

======================================= testuid.c
gcc -Wall testuid.c -o testuid

Run as root to be able to change user & group.
Feel free to tell me about the stupid and obvious mistake[s].
I'm assuming that my use of stderr isn't the problem - the
earliest incarnation (in a daemon) didn't have the fprintf's,
but it had the same problem writing to a directory.


Reply to: