Debian Bug report logs - #368501
manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3

version graph

Package: manpages-dev; Maintainer for manpages-dev is Martin Schulze <joey@debian.org>; Source for manpages-dev is src:manpages.

Reported by: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>

Date: Mon, 22 May 2006 18:33:02 UTC

Severity: minor

Found in version manpages/2.02-2

Done: Martin Schulze <joey@infodrom.org>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>:
New Bug report received and forwarded. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>
To: Debian Bug Tracking System <submit@bugs.debian.org>
Subject: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Mon, 22 May 2006 14:20:55 -0400
Package: manpages-dev
Version: 2.02-2
Severity: minor


Quite simply, the man pages for tempnam.3 and mktemp.3 both say to use
mkstemp.3 but that man page says to never use the function and
recommends using tmpfile.3.  tmpfile.3 seems happy to be called.

I hope that tmpfile() really is a secure call ... people seem confused.

-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.8-2-k7
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages manpages-dev depends on:
ii  manpages                      2.02-2     Manual pages about using a GNU/Lin

-- no debconf information



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Michael Kerrisk" <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #10 received at 368501@bugs.debian.org (full text, mbox):

From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>, 368501@bugs.debian.org
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Mon, 22 May 2006 21:26:23 +0200 (MEST)
> Von: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>
> Betreff: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use
> mkstemp.3 which says to use tmpfile.3
>
> Quite simply, the man pages for tempnam.3 and mktemp.3 both say to use
> mkstemp.3 but that man page says to never use the function and
> recommends using tmpfile.3.  tmpfile.3 seems happy to be called.
> 
> I hope that tmpfile() really is a secure call ... people seem confused.

Yes, they do.  By chance, I recently had the following comment to Joey
and Justin on the subject.

[[
> +Don't use this function, use
> +.BR tmpfile (3)
> +instead.  It is better defined and more portable.

This advice is dubious.  mkstemp() is standardised and well defined,
and serves a somewhat different purpose to tmpfile().
]]

The quoted text should just be removed from mkstemp.3...

Cheers,

Michael

-- 
Michael Kerrisk
maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 

Want to help with man page maintenance?  
Grab the latest tarball at
ftp://ftp.win.tue.nl/pub/linux-local/manpages/, 
read the HOWTOHELP file and grep the source 
files for 'FIXME'.



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Michael Kerrisk" <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #15 received at 368501@bugs.debian.org (full text, mbox):

From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>, 368501@bugs.debian.org
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Mon, 22 May 2006 21:29:00 +0200 (MEST)
Sorry, in case it wasn't clear.  The mkstemp.3 text that I referred
to comes from a Debian patch to the base man-pages package.  It
does not appear upstream.

Cheers,

Michael

-- 
Michael Kerrisk
maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 

Want to help with man page maintenance?  
Grab the latest tarball at
ftp://ftp.win.tue.nl/pub/linux-local/manpages/, 
read the HOWTOHELP file and grep the source 
files for 'FIXME'.



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Justin Pryzby <justinpryzby@users.sourceforge.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #20 received at 368501@bugs.debian.org (full text, mbox):

From: Justin Pryzby <justinpryzby@users.sourceforge.net>
To: "Christopher W. Curtis" <chris.curtis@riptidesoftware.com>, 368501@bugs.debian.org
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Mon, 22 May 2006 16:20:23 -0400
On Mon, May 22, 2006 at 02:20:55PM -0400, Christopher W. Curtis wrote:
> Package: manpages-dev
> Version: 2.02-2
You should really update the package, as it changes pretty quickly.
BTW, what suite are you running (stable sarge/testing etch/unstable
sid) that has 2.02-2, or is this not a networked machine?

> Quite simply, the man pages for tempnam.3 and mktemp.3 both say to use
> mkstemp.3 but that man page says to never use the function and
> recommends using tmpfile.3.  tmpfile.3 seems happy to be called.
I don't disagree that the situation is not ideal and should be fixed.

> I hope that tmpfile() really is a secure call ... people seem confused.
The low-level necessary thing is to use open() with flags
O_CREAT|O_EXCL, which means "create a new file, but fail if it already
exists".  In a unix program, you can just loop around open() with
various filenames (eg. from sprintf and a counter) to do this.
glibc fopen() has the "x" flag which does this more portably.

mkstemp.3
This guarantees to open the file with O_EXCL (though it doesn't
mention O_CREAT, and probably should), so it is safe.

tempnam.3
// TODO: malloc() ?
This generates a filename which didn't exist at some point during the
function call.  It is possible to use it securely:
	char *t;
	FILE *fp;
	if (NULL==(t=tempnam(NULL, NULL)) ||
		NULL==(fp=fopen(t, "wx"))) {
		fputs("Failed to create temporary file\n", stderr);
		exit(EXIT_FAILURE);
	}

But if you don't use the "exclusive" mode, then it is insecure.  gcc
warns about use of this function.

mkdtemp.3
"Introduced in OpenBSD"; 'nuff said.  (Just kidding).  Since it
creates the directory (and presumably fails or retries if it exists),
it is safe to use; since it modifies a string it is passed instead of
a static buffer, it is even thread safe.

tmpnam.3 (and tmpnam_r.3)
I think this is one of the classically-buggy functions.  Since it
generates a filename, but doesn't ask the kernel to create that file
atomically, it is easy to pass its return value to fopen() and be done
with it; but, again, this is insecure if you don't use "exclusive"
mode.  It should be fine if you do use it, though.  It can be used
safely in a threaded program (but can be used unsafely too).  gcc
warns about use of this function.

mktemp.3
This is another classically-buggy function.  And again, there's not so
much something wrong with the function, but with how people use it.
It should be perfectly fine to call mktemp and pass the resulting
filename to an open call, but only if you use "exclusive" mode.  It
can be used thread-safely.  gcc warns about use of this function.

tmpfile.3
It opens the file, and (although it isn't mentioned as prominently as
it should be) does so in "exclusive" mode.  It is notable for never
exposing the filename.  It is notable for being impossible to use this
function in a thread-unsafe way.

mktemp.1
tempfile.1
These are both executables for eg. shellscripts, and don't concern the
manpages package.  They both use O_CREAT|O_EXCL, and so can be used
without race conditions, with the exception of mktemp -u.

!!
Note that it is never safe to remove a temporary file which has been
created and then recreate it, unless you use "exclusive" mode on every
creation.  Just to be clear, every time a temporary file is ever
opened, it must be with an "exclusive" flag implemented by the kernel,
otherwise there is guaranteed to be a race condition.  The exception
is if a temp file was previously opened "exclusively", and then
reopened; this should be safe on the condition that it was never
removed.
!!

Michael has mentioned the Debian-specific change; I'm including the
relevant diffs for review.

Suggestions to improve these pages would be welcomed.

Justin

--- manpages-2.28.orig/man3/mkstemp.3
+++ manpages-2.28/man3/mkstemp.3
@@ -75,12 +75,16 @@
 .BR mkstemp ().
 .SH "CONFORMING TO"
 4.3BSD, POSIX 1003.1-2001
-.SH NOTE
+.SH NOTES
 The prototype is in
 .I <unistd.h>
 for libc4, libc5, glibc1; glibc2 follows the Single Unix Specification
 and has the prototype in
 .IR <stdlib.h> .
+
+Don't use this function, use
+.BR tmpfile (3)
+instead.  It is better defined and more portable.
 .SH "SEE ALSO"
 .BR mkdtemp (3),
 .BR mktemp (3),
--- manpages-2.28.orig/man3/tmpfile.3
+++ manpages-2.28/man3/tmpfile.3
@@ -36,8 +36,8 @@
 .B FILE *tmpfile (void);
 .fi
 .SH DESCRIPTION
-The \fBtmpfile\fP() function generates a unique temporary filename.
-The temporary file is then opened in binary read/write (w+b) mode.
+The \fBtmpfile\fP() function opens a unique temporary file in binary
+read/write (w+b) mode.
 The file will be automatically deleted when it is closed or the
 program terminates normally.
 .SH "RETURN VALUE"
--- manpages-2.28.orig/man3/tmpnam.3
+++ manpages-2.28/man3/tmpnam.3
@@ -99,7 +99,7 @@
 .IR "<stdio.h>" .
 .SH BUGS
 Never use this function. Use
-.BR mkstemp (3)
+.BR tmpfile (3)
 instead.
 .SH "CONFORMING TO"
 SVID 2, POSIX, 4.3BSD, ISO 9899



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Christopher Curtis <chris.curtis@riptidesoftware.com>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #25 received at 368501@bugs.debian.org (full text, mbox):

From: Christopher Curtis <chris.curtis@riptidesoftware.com>
To: Justin Pryzby <justinpryzby@users.sourceforge.net>
Cc: 368501@bugs.debian.org
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Mon, 22 May 2006 17:36:09 -0400
Justin Pryzby wrote:
> On Mon, May 22, 2006 at 02:20:55PM -0400, Christopher W. Curtis wrote:
> 
>>Package: manpages-dev
>>Version: 2.02-2
> 
> You should really update the package, as it changes pretty quickly.
> BTW, what suite are you running (stable sarge/testing etch/unstable
> sid) that has 2.02-2, or is this not a networked machine?

An excellent question!  I have no idea.  I must have gotten it from
testing at some point in time and subsequently removed that repository.

>>I hope that tmpfile() really is a secure call ... people seem confused.
> 
> The low-level necessary thing is to use open() with flags
> O_CREAT|O_EXCL, which means "create a new file, but fail if it already
> exists".  In a unix program, you can just loop around open() with
> various filenames (eg. from sprintf and a counter) to do this.
> glibc fopen() has the "x" flag which does this more portably.

Hmm, my fopen() manpage doesn't seem to mention 'x'.  I also saw a bug
report that 'm' isn't mentioned either.  'Tis a strange new world ...

I like that you analysed all the *te?mp.* function calls; it would be
nice if the thread info could be included in the manpages as well.

(I've actually moved to doing everything in memory so this doesn't even
impact me anymore, but thanks for caring about documentation.)

Chris



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to "Michael Kerrisk" <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #30 received at 368501@bugs.debian.org (full text, mbox):

From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: Justin Pryzby <justinpryzby@users.sourceforge.net>,368501@bugs.debian.org
Cc: chris.curtis@riptidesoftware.com
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Tue, 23 May 2006 00:24:06 +0200 (MEST)
Justin,

> On Mon, May 22, 2006 at 02:20:55PM -0400, Christopher W. Curtis wrote:
> > Package: manpages-dev
> > Version: 2.02-2
> You should really update the package, as it changes pretty quickly.
> BTW, what suite are you running (stable sarge/testing etch/unstable
> sid) that has 2.02-2, or is this not a networked machine?
> 
> > Quite simply, the man pages for tempnam.3 and mktemp.3 both say to use
> > mkstemp.3 but that man page says to never use the function and
> > recommends using tmpfile.3.  tmpfile.3 seems happy to be called.
> I don't disagree that the situation is not ideal and should be fixed.
> 
> > I hope that tmpfile() really is a secure call ... people seem confused.
> The low-level necessary thing is to use open() with flags
> O_CREAT|O_EXCL, which means "create a new file, but fail if it already
> exists".  In a unix program, you can just loop around open() with
> various filenames (eg. from sprintf and a counter) to do this.
> glibc fopen() has the "x" flag which does this more portably.
> 
> mkstemp.3
> This guarantees to open the file with O_EXCL (though it doesn't
> mention O_CREAT, and probably should), 

Absolutely no reason to mention O_CREAT...

> so it is safe.

Yes, but not for the reason you cite.

> tempnam.3
> // TODO: malloc() ?
> This generates a filename which didn't exist at some point during the
> function call.  It is possible to use it securely:
> 	char *t;
> 	FILE *fp;
> 	if (NULL==(t=tempnam(NULL, NULL)) ||
> 		NULL==(fp=fopen(t, "wx"))) {
> 		fputs("Failed to create temporary file\n", stderr);
> 		exit(EXIT_FAILURE);
> 	}
> 
> But if you don't use the "exclusive" mode, then it is insecure.  gcc
> warns about use of this function.

Not really; the real problem is the
use of environment variables.  TMPDIR could be used to influence
a program to create a file in the "wrong" place.  Glibc's
tempnam() ignores TMPDIR if the program is set-user-ID, but there
is no guarantee for other implementations.

> mkdtemp.3
> "Introduced in OpenBSD"; 'nuff said.  (Just kidding).  Since it
> creates the directory (and presumably fails or retries if it exists),
> it is safe to use; since it modifies a string it is passed instead of
> a static buffer, it is even thread safe.
> 
> tmpnam.3 (and tmpnam_r.3)
> I think this is one of the classically-buggy functions.  Since it
> generates a filename, but doesn't ask the kernel to create that file
> atomically, it is easy to pass its return value to fopen() and be done
> with it; but, again, this is insecure if you don't use "exclusive"
> mode.  It should be fine if you do use it, though.  

No!  The problem is that between creation of the name and opening
it (in /tmp, a world writable directory), some other program could 
create that file or create it as a symlink, causing the original
program to do the wrong thing.


> mktemp.3
> This is another classically-buggy function.  And again, there's not so
> much something wrong with the function, but with how people use it.

Wrong.  The problem is much the same as tmpnam().

You are stating your partial, and wrong understanding of things
as being authoritative.  This is not useful.

> Michael has mentioned the Debian-specific change; I'm including the
> relevant diffs for review.
> 
> Suggestions to improve these pages would be welcomed.

I have already suggested the main point that needs improvement.

> --- manpages-2.28.orig/man3/mkstemp.3
> +++ manpages-2.28/man3/mkstemp.3
> @@ -75,12 +75,16 @@
>  .BR mkstemp ().
>  .SH "CONFORMING TO"
>  4.3BSD, POSIX 1003.1-2001
> -.SH NOTE
> +.SH NOTES
>  The prototype is in
>  .I <unistd.h>
>  for libc4, libc5, glibc1; glibc2 follows the Single Unix Specification
>  and has the prototype in
>  .IR <stdlib.h> .
> +
> +Don't use this function, use
> +.BR tmpfile (3)
> +instead.  It is better defined and more portable.

Remove this patch.

>  .SH "SEE ALSO"
>  .BR mkdtemp (3),
>  .BR mktemp (3),
> --- manpages-2.28.orig/man3/tmpfile.3
> +++ manpages-2.28/man3/tmpfile.3
> @@ -36,8 +36,8 @@
>  .B FILE *tmpfile (void);
>  .fi
>  .SH DESCRIPTION
> -The \fBtmpfile\fP() function generates a unique temporary filename.
> -The temporary file is then opened in binary read/write (w+b) mode.
> +The \fBtmpfile\fP() function opens a unique temporary file in binary
> +read/write (w+b) mode.

This change has already (2.31) made its way upstream.

>  The file will be automatically deleted when it is closed or the
>  program terminates normally.
>  .SH "RETURN VALUE"
> --- manpages-2.28.orig/man3/tmpnam.3
> +++ manpages-2.28/man3/tmpnam.3
> @@ -99,7 +99,7 @@
>  .IR "<stdio.h>" .
>  .SH BUGS
>  Never use this function. Use
> -.BR mkstemp (3)
> +.BR tmpfile (3)

No. This is not needed.  mkstemp() is the right alternative.

Cheers,

Michael

-- 
Michael Kerrisk
maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 

Want to help with man page maintenance?  
Grab the latest tarball at
ftp://ftp.win.tue.nl/pub/linux-local/manpages/, 
read the HOWTOHELP file and grep the source 
files for 'FIXME'.



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Justin Pryzby <justinpryzby@users.sourceforge.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #35 received at 368501@bugs.debian.org (full text, mbox):

From: Justin Pryzby <justinpryzby@users.sourceforge.net>
To: Michael Kerrisk <mtk-manpages@gmx.net>, 368501@bugs.debian.org
Cc: chris.curtis@riptidesoftware.com
Subject: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Tue, 23 May 2006 10:44:15 -0400
On Tue, May 23, 2006 at 12:24:06AM +0200, Michael Kerrisk wrote:
> Justin,
> 
> > On Mon, May 22, 2006 at 02:20:55PM -0400, Christopher W. Curtis wrote:
> > > Package: manpages-dev
> > > Version: 2.02-2
> > You should really update the package, as it changes pretty quickly.
> > BTW, what suite are you running (stable sarge/testing etch/unstable
> > sid) that has 2.02-2, or is this not a networked machine?
> > 
> > > Quite simply, the man pages for tempnam.3 and mktemp.3 both say to use
> > > mkstemp.3 but that man page says to never use the function and
> > > recommends using tmpfile.3.  tmpfile.3 seems happy to be called.
> > I don't disagree that the situation is not ideal and should be fixed.
> > 
> > > I hope that tmpfile() really is a secure call ... people seem confused.
> > The low-level necessary thing is to use open() with flags
> > O_CREAT|O_EXCL, which means "create a new file, but fail if it already
> > exists".  In a unix program, you can just loop around open() with
> > various filenames (eg. from sprintf and a counter) to do this.
> > glibc fopen() has the "x" flag which does this more portably.
> > 
> > mkstemp.3
> > This guarantees to open the file with O_EXCL (though it doesn't
> > mention O_CREAT, and probably should), 
> 
> Absolutely no reason to mention O_CREAT...
> 
> > so it is safe.
> 
> Yes, but not for the reason you cite.
...

> > tmpnam.3 (and tmpnam_r.3)
> > I think this is one of the classically-buggy functions.  Since it
> > generates a filename, but doesn't ask the kernel to create that file
> > atomically, it is easy to pass its return value to fopen() and be done
> > with it; but, again, this is insecure if you don't use "exclusive"
> > mode.  It should be fine if you do use it, though.  
> 
> No!  The problem is that between creation of the name and opening
> it (in /tmp, a world writable directory), some other program could 
> create that file or create it as a symlink, causing the original
> program to do the wrong thing.
Not in exclusive mode..  In my test it didn't matter if it was a
dangling symlink, a real symlink, or a file.  Exclusive mode fails if
the pathname exists in any way:

|      O_EXCL When used with O_CREAT, if the file  already  exists  it  is  an
|             error and the open() will fail. In this context, a symbolic link
|             exists, regardless of where it points to.  

Justin



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Michael Kerrisk <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #40 received at 368501@bugs.debian.org (full text, mbox):

From: Michael Kerrisk <mtk-manpages@gmx.net>
To: Justin Pryzby <justinpryzby@users.sourceforge.net>, 368501@bugs.debian.org
Cc: chris.curtis@riptidesoftware.com
Subject: Re: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Wed, 24 May 2006 02:07:19 +0200
Justin,

> > > tmpnam.3 (and tmpnam_r.3)
> > > I think this is one of the classically-buggy functions.  Since it
> > > generates a filename, but doesn't ask the kernel to create that file
> > > atomically, it is easy to pass its return value to fopen() and be 
> > > done
> > > with it; but, again, this is insecure if you don't use "exclusive"
> > > mode.  It should be fine if you do use it, though.  
> > 
> > No!  The problem is that between creation of the name and opening
> > it (in /tmp, a world writable directory), some other program could 
> > create that file or create it as a symlink, causing the original
> > program to do the wrong thing.
> Not in exclusive mode..  In my test it didn't matter if it was a
> dangling symlink, a real symlink, or a file.  Exclusive mode fails if
> the pathname exists in any way:

<blush>  Yes, you are right.  I should have read and thought harder
before I wrote that...  My apologies.

In 2.34, the tmpnam.3 man page will include the following
para:

    Although  tmpnam(3)  generates  names  that are difficult to
    guess, it is nevertheless possible  that  between  the  time
    that  tmpnam(3)  returns  a  pathname, and the time that the
    program opens it, another program might create that pathnam
    using  open(2),  or  create it as a symbolic link.  This can
    lead to security holes.  To avoid  such  possibilities,  use
    the  open(2)  O_EXCL  flag  to open the pathname.  Or better
    yet, use mkstemp(3) or tmpfile(3).

I added similar text to temnam.3.

I also removed the text "POSIX dictates tmpnam(3)" from mktemp.3.

Thanks Justin and Chris for your input.

Cheers,

Michael
-- 
Michael Kerrisk
maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 

Want to help with man page maintenance?  
Grab the latest tarball at
ftp://ftp.win.tue.nl/pub/linux-local/manpages/, 
read the HOWTOHELP file and grep the source 
files for 'FIXME'.



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Justin Pryzby <justinpryzby@users.sourceforge.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #45 received at 368501@bugs.debian.org (full text, mbox):

From: Justin Pryzby <justinpryzby@users.sourceforge.net>
To: Michael Kerrisk <mtk-manpages@gmx.net>, 368501@bugs.debian.org
Subject: Re: Bug#368501: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Wed, 24 May 2006 10:05:34 -0400
On Wed, May 24, 2006 at 02:07:19AM +0200, Michael Kerrisk wrote:
> Justin,
> 
> > > > tmpnam.3 (and tmpnam_r.3)
> > > > I think this is one of the classically-buggy functions.  Since it
> > > > generates a filename, but doesn't ask the kernel to create that file
> > > > atomically, it is easy to pass its return value to fopen() and be 
> > > > done
> > > > with it; but, again, this is insecure if you don't use "exclusive"
> > > > mode.  It should be fine if you do use it, though.  
> > > 
> > > No!  The problem is that between creation of the name and opening
> > > it (in /tmp, a world writable directory), some other program could 
> > > create that file or create it as a symlink, causing the original
> > > program to do the wrong thing.
> > Not in exclusive mode..  In my test it didn't matter if it was a
> > dangling symlink, a real symlink, or a file.  Exclusive mode fails if
> > the pathname exists in any way:
> 
> <blush>  Yes, you are right.  I should have read and thought harder
> before I wrote that...  My apologies.
> 
> In 2.34, the tmpnam.3 man page will include the following
> para:
> 
>     Although  tmpnam(3)  generates  names  that are difficult to
>     guess, it is nevertheless possible  that  between  the  time
>     that  tmpnam(3)  returns  a  pathname, and the time that the
>     program opens it, another program might create that pathnam
s/$/e/

>     using  open(2),  or  create it as a symbolic link.  This can
>     lead to security holes.  To avoid  such  possibilities,  use
>     the  open(2)  O_EXCL  flag  to open the pathname.  Or better
>     yet, use mkstemp(3) or tmpfile(3).

Justin



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Justin Pryzby <justinpryzby@users.sourceforge.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #50 received at 368501@bugs.debian.org (full text, mbox):

From: Justin Pryzby <justinpryzby@users.sourceforge.net>
To: Michael Kerrisk <mtk-manpages@gmx.net>, 368501@bugs.debian.org
Cc: chris.curtis@riptidesoftware.com
Subject: Re: Bug#368501: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Thu, 25 May 2006 11:21:33 -0400
On Wed, May 24, 2006 at 02:07:19AM +0200, Michael Kerrisk wrote:
> Justin,
> 
> > > > tmpnam.3 (and tmpnam_r.3)
> > > > I think this is one of the classically-buggy functions.  Since it
> > > > generates a filename, but doesn't ask the kernel to create that file
> > > > atomically, it is easy to pass its return value to fopen() and be 
> > > > done
> > > > with it; but, again, this is insecure if you don't use "exclusive"
> > > > mode.  It should be fine if you do use it, though.  
> > > 
> > > No!  The problem is that between creation of the name and opening
> > > it (in /tmp, a world writable directory), some other program could 
> > > create that file or create it as a symlink, causing the original
> > > program to do the wrong thing.
> > Not in exclusive mode..  In my test it didn't matter if it was a
> > dangling symlink, a real symlink, or a file.  Exclusive mode fails if
> > the pathname exists in any way:
> 
> <blush>  Yes, you are right.  I should have read and thought harder
> before I wrote that...  My apologies.
> 
> In 2.34, the tmpnam.3 man page will include the following
> para:
> 
>     Although  tmpnam(3)  generates  names  that are difficult to
>     guess, it is nevertheless possible  that  between  the  time
>     that  tmpnam(3)  returns  a  pathname, and the time that the
>     program opens it, another program might create that pathnam
>     using  open(2),  or  create it as a symbolic link.  This can
>     lead to security holes.  To avoid  such  possibilities,  use
>     the  open(2)  O_EXCL  flag  to open the pathname.  Or better
>     yet, use mkstemp(3) or tmpfile(3).
> 
> I added similar text to temnam.3.
> 
> I also removed the text "POSIX dictates tmpnam(3)" from mktemp.3.
I would like to propose the following additional changes.

Replace all occurances of the phrase "Never use >XXXXXX<" with "Gcc
warns about the use of >XXXXXX<".  This applies to the following:

  mktemp
  tmpnam
  tempnam

This is enough of a practical reason to not use those functions, IMO;
the functions themselves aren't broken, just people's use or
misunderstanding of them.  If the functions themselves shouldn't be
used for some other reason, then let's document that.

This is done for mktemp, but I think the real, necessary information
should be documented, instead of implying that 4.3BSD somehow
generates an "insecure temporary file name".  It is true that the name
is poor (since it is possible to need more than 26 temp files), but
lets get the real reasons right.  "every use of mktemp() is a security
risk."  Can we drop that?

Perhaps each function generating a name, (and not opening the file?)
should also include some explicit mention of O_EXCL:

  Temporary files must be opened with O_EXCL, and error conditions
  detected; to do otherwise introduces a race condition and a security
  risk.  If a temporary file is ever removed and later reopened,
  O_EXCL must be used again.

This applies to:

  mktemp
  tmpnam
  tempnam
  ?mkdtemp
  ?mkstemp

tmpfile seems to be the most portable; even mingw32 has it.  But, it
doesn't expose the filename.  This is easy to work around with some
simple loop:

  FILE *fp;
  char buf[]="tmp99";
  for (int i=0; i<=99; i++) {
  	int ret;
  	ret=snprintf(buf, "tmp%0d", i);
	assert_perror();
	if (NULL!=(fp=fopen(buf, "wx"))) {
		if (i==99) {
		  fprintf(stderr, "Failed to generate temp file\n");
		  exit(EXIT_FAILURE);
		}

		break;
	}
  }

BTW.  It occurs to me that using fopen(buf, "wx") is only safe if the
"x" is recognized; if fopen ignores unknown options, you're SOL.
libc6 ignores unknown fopen flags, (and only processes the first 5
mode characters), and I don't when "x" was introduced..

Let's rehash.

tmpfile() is portable, always thread-safe, and, dare I say it, always
secure.  Use it whenever you can; it isn't useful if you want a
temporary *name*, though.

mkdtemp creates a directory.  It isn't provided by mingw32 (my new
portability guage..), but it would be simple, obvious and intuitive to
write a replacement to return the name of a directory which was just
created by us, and NULL otherwise.

mkstemp creates a file, and returns the filename.  It isn't provided
by mingw32.  Older libc versions didn't set the file mode in a safe
way.

mktemp, tmpnam, and tempnam all generate filenames which you might
carelessly pass to open(), which is guaranteed to be at least a little
bit unsafe if you don't use O_EXCL, but secure if you do.  gcc is
obnoxious and warns about them all anyway (though some implementations
did stupidly limiting things, these functions themselves were not the
source of the problem..).  There is apparently no library function I
can call to generate a filename.  These all suggest tmpfile as a
replacement; while this isn't itself bad, I think it sucks that I have
to suffer through gcc warnings for functions which could otherwise be
useful.

There must also be some conclusion to the indirection mentioned in the
title of this report:

"tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3"

I would suggest that tempnam, mktemp, and tempnam suggest either
function:

  "Use tmpfile or mkstemp instead".

And I would suggest to follow Michael's advice and not discourage the
use of mkstemp.  Otherwise, change the existing pages to point
directly to tmpfile.

I would also suggest that the following (presently in the Debian
.diff) is updated:

-The \fBtmpfile\fP() function generates a unique temporary filename.
-The temporary file is then opened in binary read/write (w+b) mode.
+The \fBtmpfile\fP() function opens a unique temporary file in binary
+read/write (w+b) mode.

I would suggest to replace this with "a uniquely named temporary file"
                                              ^^^^^^^^
since the file itself will be empty and other empty files exist, even
if not on the same host :)

In fact, the name itself is never exposed to the program, and is only
visible on the filesystem during the tmpfile() call; it is unlinked
immediately and the stream returned. 

(This was a bug previously known as #363518; I don't know what
combination of Joey/Michael should make the change).

Justin



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. Full text and rfc822 format available.

Acknowledgement sent to Michael Kerrisk <mtk-manpages@gmx.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #55 received at 368501@bugs.debian.org (full text, mbox):

From: Michael Kerrisk <mtk-manpages@gmx.net>
To: Justin Pryzby <justinpryzby@users.sourceforge.net>, 368501@bugs.debian.org
Cc: chris.curtis@riptidesoftware.com
Subject: Re: Re: Bug#368501: Re: Bug#368501: manpages-dev: tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3
Date: Thu, 25 May 2006 23:48:22 +0200
> > In 2.34, the tmpnam.3 man page will include the following
> > para:
> > 
> >     Although  tmpnam(3)  generates  names  that are difficult to
> >     guess, it is nevertheless possible  that  between  the  time
> >     that  tmpnam(3)  returns  a  pathname, and the time that the
> >     program opens it, another program might create that pathnam
> >     using  open(2),  or  create it as a symbolic link.  This can
> >     lead to security holes.  To avoid  such  possibilities,  use
> >     the  open(2)  O_EXCL  flag  to open the pathname.  Or better
> >     yet, use mkstemp(3) or tmpfile(3).
> > 
> > I added similar text to temnam.3.
> > 
> > I also removed the text "POSIX dictates tmpnam(3)" from mktemp.3.
>
> I would like to propose the following additional changes.
> 
> Replace all occurances of the phrase "Never use >XXXXXX<" with "Gcc
> warns about the use of >XXXXXX<".  This applies to the following:
> 
>   mktemp
>   tmpnam
>   tempnam
> 
> This is enough of a practical reason to not use those functions, IMO;

except that some people don't use gcc.  The page explains *why*
gcc gives the message.

> the functions themselves aren't broken, just people's use or
> misunderstanding of them.  If the functions themselves shouldn't be
> used for some other reason, then let's document that.

We do document it.  The point is this: mkstemp() and tmpfile() are
preferable to the other functions in all circumstances.  Therefore
the other functions should never be used.

> This is done for mktemp, but I think the real, necessary information
> should be documented, instead of implying that 4.3BSD somehow
> generates an "insecure temporary file name".  It is true that the name
> is poor (since it is possible to need more than 26 temp files), but
> lets get the real reasons right.  "every use of mktemp() is a security
> risk."  Can we drop that?

Well, it is a risk.  What if someone comes along and changes
the code to remove an O_EXCL, not realising the security
implications.  Just use mkstemp()...

> Perhaps each function generating a name, (and not opening the file?)
> should also include some explicit mention of O_EXCL:
> 
>   Temporary files must be opened with O_EXCL, and error conditions
>   detected; to do otherwise introduces a race condition and a security
>   risk.  If a temporary file is ever removed and later reopened,
>   O_EXCL must be used again.
> 
> This applies to:
> 
>   mktemp
>   tmpnam
>   tempnam
>   ?mkdtemp
>   ?mkstemp
> 
> tmpfile seems to be the most portable; even mingw32 has it.  But, it
> doesn't expose the filename.  This is easy to work around with some
> simple loop:
> 
>   FILE *fp;
>   char buf[]="tmp99";
>   for (int i=0; i<=99; i++) {
>   	int ret;
>   	ret=snprintf(buf, "tmp%0d", i);
> 	assert_perror();
> 	if (NULL!=(fp=fopen(buf, "wx"))) {
> 		if (i==99) {
> 		  fprintf(stderr, "Failed to generate temp file\n");
> 		  exit(EXIT_FAILURE);
> 		}
> 
> 		break;
> 	}
>   }
> 
> BTW.  It occurs to me that using fopen(buf, "wx") is only safe if the
> "x" is recognized; if fopen ignores unknown options, you're SOL.

Yes.

> libc6 ignores unknown fopen flags, (and only processes the first 5
> mode characters), and I don't when "x" was introduced..

Looks like it was there since at least 2.0.

> Let's rehash.
> 
> tmpfile() is portable, always thread-safe, and, dare I say it, always
> secure.  Use it whenever you can; it isn't useful if you want a
> temporary *name*, though.
> 
> mkdtemp creates a directory.  It isn't provided by mingw32 (my new
> portability guage..), but it would be simple, obvious and intuitive to
> write a replacement to return the name of a directory which was just
> created by us, and NULL otherwise.
> 
> mkstemp creates a file, and returns the filename.  It isn't provided
> by mingw32.  Older libc versions didn't set the file mode in a safe
> way.
> 
> mktemp, tmpnam, and tempnam all generate filenames which you might
> carelessly pass to open(), which is guaranteed to be at least a little
> bit unsafe if you don't use O_EXCL, but secure if you do.  gcc is
> obnoxious and warns about them all anyway (though some implementations
> did stupidly limiting things, these functions themselves were not the
> source of the problem..).  

Those stupidly limiting things do matter, for portable applications.
And the use of environment variables is problematic sof set-user-ID
programs on some implementations.

> There is apparently no library function I
> can call to generate a filename.  These all suggest tmpfile as a
> replacement; while this isn't itself bad, I think it sucks that I have
> to suffer through gcc warnings for functions which could otherwise be
> useful.
> 
> There must also be some conclusion to the indirection mentioned in the
> title of this report:
> 
> "tempnam.3, mktemp.3 says to use mkstemp.3 which says to use tmpfile.3"

Yes, but that is a Debian bug.  Upstream does not say this.

> I would suggest that tempnam, mktemp, and tempnam suggest either
> function:
> 
>   "Use tmpfile or mkstemp instead".

Which is what they now do.

> And I would suggest to follow Michael's advice and not discourage the
> use of mkstemp.  

Thanks.

> Otherwise, change the existing pages to point
> directly to tmpfile.
>
> I would also suggest that the following (presently in the Debian
> .diff) is updated:
> 
> -The \fBtmpfile\fP() function generates a unique temporary filename.
> -The temporary file is then opened in binary read/write (w+b) mode.
> +The \fBtmpfile\fP() function opens a unique temporary file in binary
> +read/write (w+b) mode.
> 
> I would suggest to replace this with "a uniquely named temporary file"
>                                               ^^^^^^^^

No -- I don't agree.  As you note, we don't get to see the name.

> since the file itself will be empty and other empty files exist, even
> if not on the same host :)

It is a unique fle -- e.g., it has a different i-node.  Unique
is not just about content.

> In fact, the name itself is never exposed to the program, and is only
> visible on the filesystem during the tmpfile() call; it is unlinked
> immediately and the stream returned. 

Yes.

Cheers,

Michael
-- 
Michael Kerrisk
maintainer of Linux man pages Sections 2, 3, 4, 5, and 7 

Want to help with man page maintenance?  
Grab the latest tarball at
ftp://ftp.win.tue.nl/pub/linux-local/manpages/, 
read the HOWTOHELP file and grep the source 
files for 'FIXME'.



Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#368501; Package manpages-dev. (Tue, 28 Oct 2008 14:12:06 GMT) Full text and rfc822 format available.

Acknowledgement sent to Michael Kerrisk <mtk.manpages@googlemail.com>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. (Tue, 28 Oct 2008 14:12:06 GMT) Full text and rfc822 format available.

Message #60 received at 368501@bugs.debian.org (full text, mbox):

From: Michael Kerrisk <mtk.manpages@googlemail.com>
To: 368501@bugs.debian.org
Subject: Close this report?
Date: Tue, 28 Oct 2008 09:08:45 -0500
As far as I'm concerned, this bug could be closed -- I think I've taken everything relevant upstream that I want to / should.  Please 
close the report, or let me know otherwise.

Cheers,

Michael




Bug closed, send any further explanations to "Christopher W. Curtis" <chris.curtis@riptidesoftware.com> Request was from Martin Schulze <joey@infodrom.org> to control@bugs.debian.org. (Fri, 21 Nov 2008 10:33:09 GMT) Full text and rfc822 format available.

Bug archived. Request was from Debbugs Internal Request <owner@bugs.debian.org> to internal_control@bugs.debian.org. (Sat, 20 Dec 2008 07:25:51 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Wed Apr 23 21:19:09 2014; Machine Name: beach.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.