Subject: Re: setsid(2) bug (correction)
To: Christos Zoulas <christos@deshaw.com>
From: Evil Pete <shipley@merde.dis.org>
List: current-users
Date: 02/24/1994 11:33:00
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <8702.762118379.1@merde.dis.org>

>
>
>I should have been more careful. The patch I posted before is not
>needed.  I got confused, because the following program worked under
>SunOS (while it should not). It prints 'Operation not permitted'
>correctly on NetBSD...


Here is a test file I got from Marc Teitelbaum a few years ago that tests
some of this stuff.


------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <8702.762118379.2@merde.dis.org>
Content-Description: S/src/pgrptest.c

/*
To: shipley@ucbarpa.Berkeley.EDU (Peter Shipley)
From: marc@okeeffe.Berkeley.EDU (Marc Teitelbaum)
Subject: test program

I hacked this up to test whether someones system was POSIX
conformant.  If these tests pass, then stock csh (etc) will
have race conditions if run under that system.

The reasoning behind all the restrictions may not be intuitive,
but once explained, it all makes sense (except for the restriction
on a pgrp leader - which was a bogosity forced by AT&T)

-------------

#define POSIX
*/

#include <sys/types.h>
#include <sys/errno.h>
#include <sys/signal.h>
#include <stdio.h>

#ifdef POSIX
#define setpgrp setpgid
#endif

int p;		/* semaphore */

main(argc, argv) 
char *argv[];
{
int cpid, ret, stat, wakeup();
extern errno;

    if (argc > 1 && strcmp(argv[1], "-l") == 0) {
	    kill(getppid(), SIGUSR1);
	    pause(); 
	    exit(0);
    }
    signal(SIGUSR1, wakeup);

#ifdef POSIX
    /* 1) test that session leader can't change process groups */
    if ((cpid = fork()) < 0)
	    fatalperror("fork1");
    if (cpid == 0) {
	    if (setsid() < 0)
		    fatalperror("setsid");
	    if ((cpid = fork()) < 0)
		    fatalperror("fork2");
	    if (cpid == 0) {
		    pause();
		    exit(0);
	    }
	    if (setpgrp(cpid, cpid) < 0)
		    fatalperror("setpgrp1");
	    if (setpgrp(0, cpid) < 0) {
		if (errno == EPERM)
		    printf(
		    "1) session leader properly denied to change pgrp\n");
		else
		    printf(
		    "1) session leader denied chaning pgrp, but with incorrect errno: %d\n",
			errno);
	    } else
		    printf(
			"1) FAILED: session leader allowed to change pgrp\n");
	    kill(cpid, SIGKILL);
	    exit(0);
    }
    wait(&stat);
#else
    printf("Not a POSIX system: skipping tests 1 and 4 (which use setsid())\n");
#endif

    /* 2) if pid != caller, check target pid is a child */
    if ((cpid = fork()) < 0)
	    fatalperror("fork3");
    if (cpid == 0) {
	    if ((cpid = fork()) < 0)
		    fatalperror("fork4");
	    if (cpid) { /* parent */
		    pause();
		    exit(0);
	    }
	    if (setpgrp(getppid(), getppid()) < 0) {
		    if (errno == ESRCH)
			    printf("2) child successfully denied changing pgrp of parent\n");
		    else
			    printf("2) child denied changing pgrp of parent, but wrong errno returned: %d\n", errno);
	    } else
		    printf("2) FAILED: child allowed to change pgrp of parent\n");
	    kill(getppid(), SIGKILL);
	    exit(0);
    }
    wait(&stat);

    /* 3) if target pid is a child, check the setpgrp fails if the child did an exec */
    p=1;
    if ((cpid = fork()) < 0)
	    fatalperror("fork+");
    if (cpid == 0 && (execl(argv[0], "pausing", "-l", 0) < 0))
	    fatalperror("exec");
    while(p)
	    ;
    if (setpgrp(cpid, cpid)	< 0) {
	    if (errno == EACCES)
		    printf("3) parent successfully denied setpgrping child which did exec\n");
	    else
		    printf("3) parent denied setpgrping child which did exec, but wrong errno returned: %d\n", errno);
    } else
	    printf("3) FAILED: parent allowed to change pgrp of child which did an exec\n");
    kill(cpid, SIGKILL);
    wait(&stat);

#ifdef POSIX
    /* 4) if target pid is a child, check that pid must be in same session as caller */
    p=1;
    if ((cpid = fork()) < 0)
	    fatalperror("fork++");
    if (cpid == 0) {
	    if (setsid() < 0)
		    fatalperror("setsid2");
	    if (execl(argv[0], "pausing", "-l", 0) < 0)
		    fatalperror("exec2");
    }
    while(p)
	    ;
    if (setpgrp(cpid, getpid()) < 0) {
	    if (errno == EPERM)
		    printf("4) parent sucessfully denied changing childs pgrp which is nin different session\n");
	    else
		    printf("4) parent denied changing childs pgrp which is in differnt session, but wrong error returned: %d\n",
			    errno);
    } else
	    printf("4) FAILED: parent allowed to change childs pgrp and child is in a different session\n");
    kill(cpid, SIGKILL);
    wait(&stat);
#endif

    /* 5) test that if pgid != pid, then there must exist a pid having pgrp in same session */
    if ((cpid = fork()) < 0)
	    fatalperror("fork...");
    if (cpid == 0) {
	    if ((cpid = fork()) < 0)
		    fatalperror("fork....");
	    if (cpid == 0) {
		    if (setpgrp(0, getppid()) < 0) {
			    if (errno == EPERM)
				    printf("5) pgid != pid, successfully denied entering pgid\n");
			    else
				    printf("5) pgid != [pid, successfully denied entering pgid, but wrong error returned: %d\n", 
					    errno);
		    } else
			printf("5) FAILED: pgid != pid, no one else was in pgid, and pid was allowed to change to pgid\n");
		exit(0);
	}
	wait(&stat);
	exit(0);
    }
    wait(&stat);
}

fatalperror(s)
    char *s;
{
    perror(s);
    fprintf(stderr, "test aborted\n");
    exit(1);
}

wakeup(){
    p=0;
}

------- =_aaaaaaaaaa0--

------------------------------------------------------------------------------