mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 12:28:58 +00:00
Many security improvements from OpenBSD:
implement mkdtemp improve man page for mk*temp use arc4random to seed extra XXX's randomly Optionally warn of unsafe mktemp uses From various commits by theo de raadt and Todd Miller. Obtained from: OpenBSD This should go into 2.2 after a testing period.
This commit is contained in:
parent
f5295b34ac
commit
2f253e75c8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=33295
@ -1,5 +1,5 @@
|
||||
# @(#)Makefile.inc 8.3 (Berkeley) 4/17/94
|
||||
# $Id: Makefile.inc,v 1.10 1997/10/15 16:16:07 bde Exp $
|
||||
# $Id: Makefile.inc,v 1.11 1997/10/21 08:41:10 bde Exp $
|
||||
|
||||
# stdio sources
|
||||
.PATH: ${.CURDIR}/../libc/stdio
|
||||
@ -30,6 +30,7 @@ MLINKS+=fseek.3 fgetpos.3 fseek.3 fsetpos.3 fseek.3 ftell.3 fseek.3 rewind.3
|
||||
MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
|
||||
MLINKS+=getc.3 fgetc.3 getc.3 getchar.3 getc.3 getw.3
|
||||
MLINKS+=mktemp.3 mkstemp.3
|
||||
MLINKS+=mktemp.3 mkdtemp.3
|
||||
MLINKS+=printf.3 asprintf.3 printf.3 fprintf.3 \
|
||||
printf.3 snprintf.3 printf.3 sprintf.3 \
|
||||
printf.3 vasprintf.3 \
|
||||
|
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dd February 11, 1998
|
||||
.Dt MKTEMP 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -43,6 +43,8 @@
|
||||
.Fn mktemp "char *template"
|
||||
.Ft int
|
||||
.Fn mkstemp "char *template"
|
||||
.Ft char *
|
||||
.Fn mkdtemp "char *template"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn mktemp
|
||||
@ -78,11 +80,18 @@ makes the same replacement to the template and creates the template file,
|
||||
mode 0600, returning a file descriptor opened for reading and writing.
|
||||
This avoids the race between testing for a file's existence and opening it
|
||||
for use.
|
||||
.Pp
|
||||
The
|
||||
.Fn mkdtemp
|
||||
function makes the same replacement to the template as in
|
||||
.Xr mktemp 3
|
||||
and creates the template directory, mode 0700.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn mktemp
|
||||
function
|
||||
returns a pointer to the template on success and
|
||||
and
|
||||
.Fn mkdtemp
|
||||
functions return a pointer to the template on success and
|
||||
.Dv NULL
|
||||
on failure.
|
||||
The
|
||||
@ -93,9 +102,9 @@ If either call fails an error code is placed in the global variable
|
||||
.Va errno .
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn mktemp
|
||||
and
|
||||
.Fn mkstemp
|
||||
and
|
||||
.Fn mkdtemp
|
||||
functions
|
||||
may set
|
||||
.Va errno
|
||||
@ -106,9 +115,9 @@ The pathname portion of the template is not an existing directory.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn mktemp
|
||||
and
|
||||
.Fn mkstemp
|
||||
and
|
||||
.Fn mkdtemp
|
||||
functions
|
||||
may also set
|
||||
.Va errno
|
||||
@ -124,12 +133,22 @@ may also set
|
||||
to any value specified by the
|
||||
.Xr open 2
|
||||
function.
|
||||
.Pp
|
||||
The
|
||||
.Fn mkdtemp
|
||||
function
|
||||
may also set
|
||||
.Va errno
|
||||
to any value specified by the
|
||||
.Xr mkdir 2
|
||||
function.
|
||||
.Sh NOTES
|
||||
A common problem that results in a core dump is that the programmer
|
||||
passes in a read-only string to
|
||||
.Fn mktemp
|
||||
or
|
||||
.Fn mkstemp .
|
||||
.Fn mktemp ,
|
||||
.Fn mkstemp
|
||||
or
|
||||
.Fn mkdtemp .
|
||||
This is common with programs that were developed before
|
||||
.St -ansiC
|
||||
compilers were common.
|
||||
@ -146,13 +165,24 @@ so that it will store string constants in a writable segment of memory.
|
||||
See
|
||||
.Xr gcc 1
|
||||
for more information.
|
||||
.Sh BUGS
|
||||
An attacker can guess the filenames produced by
|
||||
.Fn mktemp .
|
||||
Whenever it is possible
|
||||
.Fn mkstemp
|
||||
should be used instead.
|
||||
.Sh SEE ALSO
|
||||
.Xr chmod 2 ,
|
||||
.Xr getpid 2 ,
|
||||
.Xr mkdir 2 ,
|
||||
.Xr open 2 ,
|
||||
.Xr stat 2
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm mktemp
|
||||
.Fn mktemp
|
||||
function appeared in
|
||||
.At v7 .
|
||||
The
|
||||
.Fn mkdtemp
|
||||
function first appeared in
|
||||
.Ox 2.2 .
|
||||
|
@ -36,7 +36,7 @@
|
||||
static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$Id: mktemp.c,v 1.6 1997/02/22 15:02:16 peter Exp $";
|
||||
"$Id: mktemp.c,v 1.7 1997/04/07 18:01:10 guido Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -44,10 +44,11 @@ static const char rcsid[] =
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int _gettemp(char *, int *);
|
||||
static int _gettemp(char *, int *, int);
|
||||
|
||||
int
|
||||
mkstemp(path)
|
||||
@ -55,49 +56,91 @@ mkstemp(path)
|
||||
{
|
||||
int fd;
|
||||
|
||||
return (_gettemp(path, &fd) ? fd : -1);
|
||||
return (_gettemp(path, &fd, 0) ? fd : -1);
|
||||
}
|
||||
|
||||
char *
|
||||
mkdtemp(path)
|
||||
char *path;
|
||||
{
|
||||
return(_gettemp(path, (int *)NULL, 1) ? path : (char *)NULL);
|
||||
}
|
||||
|
||||
char *_mktemp(char *);
|
||||
|
||||
char *
|
||||
_mktemp(path)
|
||||
char *path;
|
||||
{
|
||||
return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL);
|
||||
}
|
||||
|
||||
#ifdef UNSAFE_WARN
|
||||
__warn_references(mktemp,
|
||||
"warning: mktemp() possibly used unsafely; consider using mkstemp()");
|
||||
#endif
|
||||
|
||||
char *
|
||||
mktemp(path)
|
||||
char *path;
|
||||
{
|
||||
return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
|
||||
return(_mktemp(path));
|
||||
}
|
||||
|
||||
static int
|
||||
_gettemp(path, doopen)
|
||||
_gettemp(path, doopen, domkdir)
|
||||
char *path;
|
||||
register int *doopen;
|
||||
int domkdir;
|
||||
{
|
||||
register char *start, *trv;
|
||||
struct stat sbuf;
|
||||
pid_t pid;
|
||||
int pid, rval;
|
||||
|
||||
if (doopen && domkdir) {
|
||||
errno = EINVAL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
pid = getpid();
|
||||
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
|
||||
while (*--trv == 'X') {
|
||||
*trv = (pid % 10) + '0';
|
||||
for (trv = path; *trv; ++trv)
|
||||
;
|
||||
--trv;
|
||||
while (*trv == 'X' && pid != 0) {
|
||||
*trv-- = (pid % 10) + '0';
|
||||
pid /= 10;
|
||||
}
|
||||
while (*trv == 'X') {
|
||||
char c;
|
||||
|
||||
pid = (arc4random() & 0xffff) % (26+26);
|
||||
if (pid < 26)
|
||||
c = pid + 'A';
|
||||
else
|
||||
c = (pid - 26) + 'a';
|
||||
*trv-- = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the target directory; if you have six X's and it
|
||||
* doesn't exist this runs for a *very* long time.
|
||||
*/
|
||||
for (start = trv + 1;; --trv) {
|
||||
if (trv <= path)
|
||||
break;
|
||||
if (*trv == '/') {
|
||||
*trv = '\0';
|
||||
if (stat(path, &sbuf))
|
||||
return(0);
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return(0);
|
||||
if (doopen || domkdir) {
|
||||
for (start = trv + 1;; --trv) {
|
||||
if (trv <= path)
|
||||
break;
|
||||
if (*trv == '/') {
|
||||
*trv = '\0';
|
||||
rval = stat(path, &sbuf);
|
||||
*trv = '/';
|
||||
if (rval != 0)
|
||||
return(0);
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
*trv = '/';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +151,12 @@ _gettemp(path, doopen)
|
||||
return(1);
|
||||
if (errno != EEXIST)
|
||||
return(0);
|
||||
}
|
||||
else if (lstat(path, &sbuf))
|
||||
} else if (domkdir) {
|
||||
if (mkdir(path, 0700) == 0)
|
||||
return(1);
|
||||
if (errno != EEXIST)
|
||||
return(0);
|
||||
} else if (lstat(path, &sbuf))
|
||||
return(errno == ENOENT ? 1 : 0);
|
||||
|
||||
/* tricky little algorithm for backward compatibility */
|
||||
|
Loading…
Reference in New Issue
Block a user