[PATCH] misc: Add mkostempat (BZ 19866)
Mark Wielaard
mark@klomp.org
Fri Jun 19 11:25:25 GMT 2026
Hi Adhemerval,
On Thu, 2026-06-18 at 16:11 -0300, Adhemerval Zanella wrote:
> The mkstemp family has a lot of potential pitfalls:
>
> 1. In-place mutation of the template, where makes string literals
> usage not possible.
> 2. The randomness count is baked in the string and it can not be
> changed (users can no ask for more).
> 3. O_CLOEXEC is not the default.
> 4. A lot of combinatorial variant: mkstemp -> mkostemp (flags) ->
> mkstemps (suffix) -> mkostemps (both)
> 5. No mode parameter, the file is always created as 0600.
> 6. Suffix typing and positioning: the XXXXXX must sit at exactly
> strlen(template) - suffixlen - 6 and mismatches are setups for
> EINVAL rather than compile-time errors.
> 7. mkostemp accepts only O_APPEND/O_CLOEXEC/O_SYNC(-ish); anything
> else is rejected, but the signature gives no hint.
>
> This patch adds mkostempat:
>
> int mkostempat (int dirfd, /* as other *at functions. */
> const char *prefix, /* maybe a relative or absolute. */
> const char *suffix, /* no '/' allowed; may be "" */
> unsigned int n_random, /* entropy chars, 0 -> default 6 */
> int oflags, /* extra O_* OR'd into the create */
> mode_t mode, /* e.g. 0600 */
> char *namebuf, /* output, or NULL */
> size_t namebuf_size); /* bound; ERANGE/ENAMETOOLONG on overflow */
>
> The functions is a GNU extension and a more flexible alternative to the
> mkstemp family: it creates the file relative to a directory descriptor
> (with openat's absolute-path/dirfd semantics)i. It also fixes the
> aforementioned issues:
>
> * dirfd first, AT_FDCWD semantics (as other *at functions).
> * namebuf/namebuf_size replaces the mutated template, killing the
> string-literal footgun and the lifetime coupling. NULL namebuf means
> "I only want the fd" (the common O_TMPFILE-adjacent case)
> * prefix+suffix+n_random replaces the XXXXXX/suffixlen convention.
> * O_CLOEXEC as the implicit default, with oflags for opt-out/extra flags.
> * mode so 0600 is a default the caller can override atomically.
When I mentioned it in
https://sourceware.org/bugzilla/show_bug.cgi?id=19866 I mostly wanted
an alternative for mkstemp that took a dirfd to go with the other at
calls to replace path based calls with dirfd calls to get rid of
various toctou issues with the path based calls. I appreciate the way
more flexible mkostempat but am a little afraid it becomes so
complicated that people won't have an easy transition to a more safe
api.
That said, I do like this. The dirfd argument, O_CLOEXEC and just
letting glibc decide what randomness/template is needed are clear
improvements.
If possible it would be nice to have some default for the prefix. Does
the prefix really matter? Maybe allow NULL for both prefix and suffix?
I understand that other at functions do allow (absolute) paths (slash
'/' chars), but that really just brings back the path based toctou
issues, so I would advise against it (although I see how there is a
consistency argument to be made wrt other at calls).
Could we make the namebuf pure output (that you have to free when
done)? If not, how does the user determine the namebuf_size?
When creating an O_TMPFILE I think the user still wants a path name to
use either when the file system didn't support O_TMPFILE so you had to
fall back to a real filename, or when used to (atomically) replace
another file (which I believe is a common use case for mkstemp) because
there is no flink that just takes an fd and a new (or to be replaced)
name. renameat still needs a pathname (maybe /proc/self/fd/nr?).
Cheers,
Mark
More information about the Libc-alpha
mailing list