bostic@OKEEFFE.BERKELEY.EDU (Keith Bostic) (10/20/87)
Subject: mktemp is broken
Index: lib/libc/gen/mktemp.c 2.10BSD
Description:
mktemp(3), as distributed with 2.10BSD will fail if used
with setuid programs.
Repeat-By:
Try to create a temporary file in a directory that is writeable
not by the user, but by the setuid program.
Fix:
Unshar the attached file and replace lib/libc/gen/mktemp.c.
echo x - mktemp.c
sed 's/^X//' >mktemp.c << 'END-of-mktemp.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)mktemp.c 5.4 (Berkeley) 9/14/87";
X#endif LIBC_SCCS and not lint
X
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include <stdio.h>
X#include <ctype.h>
X
X#define YES 1
X#define NO 0
X
Xmkstemp(as)
X char *as;
X{
X int fd;
X
X return (_gettemp(as, &fd) ? fd : -1);
X}
X
Xchar *
Xmktemp(as)
X char *as;
X{
X return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
X}
X
Xstatic
X_gettemp(as, doopen)
X char *as;
X register int *doopen;
X{
X extern int errno;
X register char *start, *trv;
X struct stat sbuf;
X u_int pid;
X
X pid = getpid();
X
X /* extra X's get set to 0's */
X for (trv = as; *trv; ++trv);
X while (*--trv == 'X') {
X *trv = (pid % 10) + '0';
X pid /= 10;
X }
X
X /*
X * check for write permission on target directory; if you have
X * six X's and you can't write the directory, this will run for
X * a *very* long time.
X */
X for (start = ++trv; trv > as && *trv != '/'; --trv);
X if (*trv == '/') {
X *trv = '\0';
X if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
X return(NO);
X *trv = '/';
X }
X else if (stat(".", &sbuf) == -1)
X return(NO);
X
X for (;;) {
X if (doopen) {
X if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
X return(YES);
X if (errno != EEXIST)
X return(NO);
X }
X else if (stat(as, &sbuf))
X return(errno == ENOENT ? YES : NO);
X
X /* tricky little algorithm for backward compatibility */
X for (trv = start;;) {
X if (!*trv)
X return(NO);
X if (*trv == 'z')
X *trv++ = 'a';
X else {
X if (isdigit(*trv))
X *trv = 'a';
X else
X ++*trv;
X break;
X }
X }
X }
X /*NOTREACHED*/
X}
END-of-mktemp.c
exit