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.
--
To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org