On Thu, Apr 25, 2013 at 11:57:24PM -0500, Derek Martin wrote:
>                                                 The whole point of
> this subthread is that choosing not to rely on the system-provided
> library routines is folly.  You can't provide anything better
> portably--your system libraries will already use the best source of
> randomness available to them.

I'm reading this discussion with interest, more for my own academic
curiosity than anything practical.  As I understand it (and would
welcome corrections if I'm wrong)...

 - Mutt uses mktemp to help compute a unique filename, then opens the
   file with O_CREAT|O_EXCL.
 - The alternative is to use mktemps to open a file with whatever
   guarantees the OS gives you, then use link to give the file a
   name that has the desired suffix.

The attacks that mktemp has to defend against are:

 - content attacks, where the attacker wants you to open a file that
   they've created;
 - symlink attacks, where the attacker wants you to follow a symlink
   and thus open a file in an unsafe location, and
 - DOS attacks, where the attacker wants to prevent you from opening
   a tempfile by creating it before you do.

Opening the file with O_CREAT|O_EXCL is a solid defense against the
first two attacks in almost all common cases except when the temp
filesystem is mounted over NFSv2.  Using sufficient randomness with
a large address space defends against the third attack, and can mitigate
the other attacks in cases where O_EXCL is not guaranteed to be safe.

The open questions as far as I'm concerned are:

 - what does the OS's mkstemp guarantee about randomness;
 - what does it guarantee about race conditions on NFSv2, and
 - is mkstemp followed by link any safer than mktemp followed by O_EXCL?

The manual page for open(2) on GNU/Linux systems mentions that O_EXCL
is not guaranteed race-free on an NFSv2 system.  However, the man page
for mkstemp does not discuss NFSv2 at all, and doesn't promise to be
cryptographically random.

So I've looked at the source code of glibc.

First thing to notice is that mktemp, mkstemp, mkdtemp, etc are all
implemented by the same function.  Consequently, mkstemp is exactly
equivalent to calling mktemp and then opening the file with O_EXCL.

This means that mkstemp is not guaranteed race-free on an NFSv2 system,
and thus mkstemp+link is no safer than the current way of doing it.

Second thing is that the sources of randomness are as follows:

 - the pseudorandom value arrived at in the previous (if any) call to mk*temp
 - the system clock at microsecond precision
 - the system's high precision clock, if it has one (on x86 systems this
   maps to the assembly instruction "rdtsc")
 - the current pid

And that's all.

Moreover, if the first attempt to open a file fails then the subsequent
attempts are entirely predictable (value+=7777).

I therefore conclude that there is a large class of systems on which
mktemp et al do not use the best source of randomness available to them
unless you think the CPU's time stamp counter is difficult enough to
predict.

imc

Reply via email to