v07i090: Find security holes in shell-escapes

sources-request at mirror.UUCP sources-request at mirror.UUCP
Thu Dec 11 04:46:16 AEST 1986


Submitted by: ihnp4!utzoo!hcr!hcrvx1!hugh
Mod.sources: Volume 7, Issue 90
Archive-name: forktest

I would like to submit the following program to mod.sources.  I hope
that the comments are sufficient explanation.  I don't see that a
manual is worthwhile.

I have run this program under System V and Version 7.  I have not
tested it under BSD, but I know of no impediment.

With this program, I have found bugs in a number of UNIX System V
utilities.  I am sure that BSD programs would be just as buggy, but
I haven't tested them.  Here are some examples:

Programs that leave extra file descriptors open:
     sdb ! command
     mailx ~! command during message composition, and ! command (two extra)
     mail ! command
     rn ! or | command (5 extra!)
     cu ~! command (one extra: number 5)

Programs that leave signals ignored:
     mailx ~! command (SIGINT!)
     rn ! and | commands (SIGEMT!?)

I think that this list shows that it is easy to get fork(2) wrong.
I hope programmers will use ForkTest to catch this type of bug
early.  Exercise for the reader: what can you scribble on with those
extra file descriptors?

Hugh Redelmeier (416) 922-1937
utzoo!hcr!hugh

[  I wrote the Makefile and README.  --r$  ]
----------CUT HERE----------

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "End of shell archive."
# Contents:  Makefile README forktest.c
# Wrapped by rs at mirror on Wed Dec 10 13:44:46 1986
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'Makefile'" '(52 characters)'
if test -f 'Makefile' ; then 
  echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' >Makefile <<'@//E*O*F Makefile//'
X
Xforktest:	forktest.c
X	$(CC) $(CFLAGS) -o forktest
X
@//E*O*F Makefile//
if test 52 -ne "`wc -c <'Makefile'`"; then
    echo shar: error transmitting "'Makefile'" '(should have been 52 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(253 characters)'
if test -f 'README' ; then 
  echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' >README <<'@//E*O*F README//'
X
X[  This program is designed to be called by programs that allow
X   shell escapes.  It prints out the argc,argv parameters, and
X   lists the disposition of signals, alarm calls, etc.  The fun
X   part is when it lists the open file descriptors...  -r$ ]
@//E*O*F README//
if test 253 -ne "`wc -c <'README'`"; then
    echo shar: error transmitting "'README'" '(should have been 253 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'forktest.c'" '(3059 characters)'
if test -f 'forktest.c' ; then 
  echo shar: will not over-write existing file "'forktest.c'"
else
sed 's/^X//' >forktest.c <<'@//E*O*F forktest.c//'
X/* Fork Test: display args, open files, signals, etc.
X *
X * Simple as this program is, it has found bugs in the
X * way a number of programs fork off children.  To test
X * how a program is invoking its children, run this
X * program as a child.
X *
X * Generally, processes should be created with:
X *
X * - a reasonable arg count & list
X * - arg 0 should look like the name of the command
X *
X * - real and effective UIDs and GIDs should be reasonable.
X *   Beware setuid programs that fork children!
X *
X * - no pending alarm.  Version 7 apparently does not
X *   reset alarms upon an exec!
X *
X * - file descriptors 0 (STDIN), 1 (STDOUT), and 2 (STDERR)
X *   opened reasonably
X * - all other file descriptors closed (this program will
X *   describe all open channels)
X *
X * - all signals (except SIGKILL) set to SIG_DFL (this
X *   program will print all signals set otherwise)
X *
X * The output is fairly simple to understand.  When in
X * doubt, read the code (and a UNIX manual: exec(2),
X * getuid(2), alarm(2), signal(2), stat(2)).
X *
X * Room for Improvement:
X *
X * - strings should be printed in a way that shows funny characters.
X * - show misc. other bits of state
X *	- PID (who cares?)
X *	- umask
X *	- ulimit (System V)
X *	- stty settings of open TTYs
X *
X * Copyright (c) 1986 March 11  D. Hugh Redelmeier
X *
X * This program may be distributed and used without restriction.
X */
X
X#include <stdio.h>
X
Xextern unsigned alarm();	/* should be unsigned, but may be int */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X
Xstruct stat sb;
X
X#include <errno.h>
Xextern int errno;
Xextern char *sys_errlist[];
X
X#include <signal.h>
X
Xint (*signal())();
X
Xmain(argc, argv, envp)
Xint argc;
Xchar **argv, **envp;
X{
X	register int i;
X	unsigned al = alarm(0);	/* get it while it is hot */
X
X	printf("%d arg(s):", argc);
X	for (i=0; i<argc; i++)
X		if (argv[i] == NULL)
X			printf(" NULL!");
X		else
X			printf(" \"%s\"", argv[i]);
X	printf("\n");
X	if (argv[argc] != NULL)
X		printf("Arg list is not ended with a NULL!\n");
X
X	printf("Real UID = %d, GID = %d; Effective UID = %d, GID = %d.\n",
X		getuid(), getgid(), geteuid(), getegid());
X
X	if (al)
X		printf("Alarm set to go off in %u seconds.\n", al);
X
X	printf("File Descriptors:\n");
X	for (i=0; i!=40; i++)	/* I hope 40 is enough. */
X		if (fstat(i, &sb) == -1) {
X			if (errno != EBADF)
X				printf("\t%d error: %s\n", i, sys_errlist[errno]);
X		} else {
X			printf("\t%d: dev=%d, ino=%d, perm=0%04o, ",
X				i, sb.st_dev, sb.st_ino, sb.st_mode&07777);
X			switch (sb.st_mode & S_IFMT) {
X			case S_IFREG:
X				printf("pipe or regular file\n");
X				break;
X			/* extend as desired */
X			default:
X				printf("IFMT=0%o\n", sb.st_mode>>12);
X				break;
X			}
X		}
X
X	printf("Signals:\n");
X	for (i=1; i!=40; i++) {	/* I hope 40 is enough. */
X		register int n = (int) signal(i, SIG_IGN);
X		switch (n) {
X		case -1:
X		case SIG_DFL:
X			break;
X		case SIG_IGN:
X			printf("\t%d: SIG_IGN\n", i);
X			break;
X		default:
X			printf("\t%d: %d\n", i, n);
X			break;
X		}
X	}
X
X	printf("Environment:\n");
X	for (i=0; envp[i]!=NULL; i++)
X		printf("\t\"%s\"\n", envp[i]);
X
X	exit(0);
X}
@//E*O*F forktest.c//
if test 3059 -ne "`wc -c <'forktest.c'`"; then
    echo shar: error transmitting "'forktest.c'" '(should have been 3059 characters)'
fi
fi # end of overwriting check
echo shar: "End of shell archive."
exit 0



More information about the Mod.sources mailing list