Add mkostempsat(3).

This is a variant of mkostemps() which takes a directory descriptor and
returns a descriptor for a tempfile relative to that directory.  Unlike
the other mktemp functions, mkostempsat() can be used in capability
mode.

Reviewed by:	cem
Discussed with:	brooks
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D21031
This commit is contained in:
Mark Johnston 2019-07-29 19:02:16 +00:00
parent 4be6714234
commit 076574744c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350420
5 changed files with 55 additions and 19 deletions

View File

@ -297,6 +297,7 @@ int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *));
#endif #endif
int mkostemp(char *, int); int mkostemp(char *, int);
int mkostemps(char *, int, int); int mkostemps(char *, int, int);
int mkostempsat(int, char *, int, int);
void qsort_r(void *, size_t, size_t, void *, void qsort_r(void *, size_t, size_t, void *,
int (*)(void *, const void *, const void *)); int (*)(void *, const void *, const void *));
int radixsort(const unsigned char **, int, const unsigned char *, int radixsort(const unsigned char **, int, const unsigned char *,

View File

@ -63,7 +63,7 @@ MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
MLINKS+=getline.3 getdelim.3 MLINKS+=getline.3 getdelim.3
MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3 MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3 \ MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3 \
mktemp.3 mkostemp.3 mktemp.3 mkostemps.3 mktemp.3 mkostemp.3 mktemp.3 mkostemps.3 mktemp.3 mkostempsat.3
MLINKS+=open_memstream.3 open_wmemstream.3 MLINKS+=open_memstream.3 open_wmemstream.3
MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \ MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \
printf.3 snprintf.3 printf.3 sprintf.3 \ printf.3 snprintf.3 printf.3 sprintf.3 \

View File

@ -171,6 +171,10 @@ FBSD_1.5 {
gets_s; gets_s;
}; };
FBSD_1.6 {
mkostempsat;
};
FBSDprivate_1.0 { FBSDprivate_1.0 {
_flockfile; _flockfile;
_flockfile_debug_stub; _flockfile_debug_stub;

View File

@ -28,7 +28,7 @@
.\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93 .\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd August 8, 2013 .Dd July 29, 2019
.Dt MKTEMP 3 .Dt MKTEMP 3
.Os .Os
.Sh NAME .Sh NAME
@ -46,6 +46,8 @@
.Fn mkostemp "char *template" "int oflags" .Fn mkostemp "char *template" "int oflags"
.Ft int .Ft int
.Fn mkostemps "char *template" "int suffixlen" "int oflags" .Fn mkostemps "char *template" "int suffixlen" "int oflags"
.Ft int
.Fn mkostempsat "int dfd" "char *template" "int suffixlen" "int oflags"
.Ft char * .Ft char *
.Fn mkdtemp "char *template" .Fn mkdtemp "char *template"
.In unistd.h .In unistd.h
@ -126,6 +128,21 @@ function
are told the length of the suffix string. are told the length of the suffix string.
.Pp .Pp
The The
.Fn mkostempsat
function acts the same as
.Fn mkostemps
but takes an additional directory descriptor as a parameter.
The temporary file is created relative to the corresponding
directory, or to the current working directory if the special
value
.Dv AT_FDCWD
is specified.
If the template path is an absolute path, the
.Fa dfd
parameter is ignored and the behavior is identical to
.Fn mkostemps .
.Pp
The
.Fn mkdtemp .Fn mkdtemp
function makes the same replacement to the template as in function makes the same replacement to the template as in
.Fn mktemp .Fn mktemp
@ -262,9 +279,10 @@ and is not specified by
.St -p1003.1-2008 . .St -p1003.1-2008 .
The The
.Fn mkostemp , .Fn mkostemp ,
.Fn mkstemps .Fn mkstemps ,
and
.Fn mkostemps .Fn mkostemps
and
.Fn mkostempsat
functions do not conform to any standard. functions do not conform to any standard.
.Sh HISTORY .Sh HISTORY
A A
@ -293,6 +311,10 @@ and
.Fn mkostemps .Fn mkostemps
functions appeared in functions appeared in
.Fx 10.0 . .Fx 10.0 .
The
.Fn mkostempsat
function appeared in
.Fx 13.0 .
.Sh BUGS .Sh BUGS
This family of functions produces filenames which can be guessed, This family of functions produces filenames which can be guessed,
though the risk is minimized when large numbers of though the risk is minimized when large numbers of
@ -308,10 +330,11 @@ and opening it for use
(later in the user application) (later in the user application)
particularly dangerous from a security perspective. particularly dangerous from a security perspective.
Whenever it is possible, Whenever it is possible,
.Fn mkstemp .Fn mkstemp ,
or
.Fn mkostemp .Fn mkostemp
should be used instead, since it does not have the race condition. or
.Fn mkostempsat
should be used instead, since they do not have the race condition.
If If
.Fn mkstemp .Fn mkstemp
cannot be used, the filename created by cannot be used, the filename created by

View File

@ -49,17 +49,25 @@ __FBSDID("$FreeBSD$");
char *_mktemp(char *); char *_mktemp(char *);
static int _gettemp(char *, int *, int, int, int); static int _gettemp(int, char *, int *, int, int, int);
static const unsigned char padchar[] = static const unsigned char padchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int
mkostempsat(int dfd, char *path, int slen, int oflags)
{
int fd;
return (_gettemp(dfd, path, &fd, 0, slen, oflags) ? fd : -1);
}
int int
mkostemps(char *path, int slen, int oflags) mkostemps(char *path, int slen, int oflags)
{ {
int fd; int fd;
return (_gettemp(path, &fd, 0, slen, oflags) ? fd : -1); return (_gettemp(AT_FDCWD, path, &fd, 0, slen, oflags) ? fd : -1);
} }
int int
@ -67,7 +75,7 @@ mkstemps(char *path, int slen)
{ {
int fd; int fd;
return (_gettemp(path, &fd, 0, slen, 0) ? fd : -1); return (_gettemp(AT_FDCWD, path, &fd, 0, slen, 0) ? fd : -1);
} }
int int
@ -75,7 +83,7 @@ mkostemp(char *path, int oflags)
{ {
int fd; int fd;
return (_gettemp(path, &fd, 0, 0, oflags) ? fd : -1); return (_gettemp(AT_FDCWD, path, &fd, 0, 0, oflags) ? fd : -1);
} }
int int
@ -83,19 +91,19 @@ mkstemp(char *path)
{ {
int fd; int fd;
return (_gettemp(path, &fd, 0, 0, 0) ? fd : -1); return (_gettemp(AT_FDCWD, path, &fd, 0, 0, 0) ? fd : -1);
} }
char * char *
mkdtemp(char *path) mkdtemp(char *path)
{ {
return (_gettemp(path, (int *)NULL, 1, 0, 0) ? path : (char *)NULL); return (_gettemp(AT_FDCWD, path, (int *)NULL, 1, 0, 0) ? path : (char *)NULL);
} }
char * char *
_mktemp(char *path) _mktemp(char *path)
{ {
return (_gettemp(path, (int *)NULL, 0, 0, 0) ? path : (char *)NULL); return (_gettemp(AT_FDCWD, path, (int *)NULL, 0, 0, 0) ? path : (char *)NULL);
} }
__warn_references(mktemp, __warn_references(mktemp,
@ -108,7 +116,7 @@ mktemp(char *path)
} }
static int static int
_gettemp(char *path, int *doopen, int domkdir, int slen, int oflags) _gettemp(int dfd, char *path, int *doopen, int domkdir, int slen, int oflags)
{ {
char *start, *trv, *suffp, *carryp; char *start, *trv, *suffp, *carryp;
char *pad; char *pad;
@ -155,7 +163,7 @@ _gettemp(char *path, int *doopen, int domkdir, int slen, int oflags)
for (; trv > path; --trv) { for (; trv > path; --trv) {
if (*trv == '/') { if (*trv == '/') {
*trv = '\0'; *trv = '\0';
rval = stat(path, &sbuf); rval = fstatat(dfd, path, &sbuf, 0);
*trv = '/'; *trv = '/';
if (rval != 0) if (rval != 0)
return (0); return (0);
@ -168,11 +176,11 @@ _gettemp(char *path, int *doopen, int domkdir, int slen, int oflags)
} }
} }
oflags |= O_CREAT | O_EXCL | O_RDWR;
for (;;) { for (;;) {
if (doopen) { if (doopen) {
if ((*doopen = *doopen = _openat(dfd, path, oflags, 0600);
_open(path, O_CREAT|O_EXCL|O_RDWR|oflags, 0600)) >= if (*doopen >= 0)
0)
return (1); return (1);
if (errno != EEXIST) if (errno != EEXIST)
return (0); return (0);