[PATCH 2/2] fcntl: drop nonnull attribute for openat, openat2's path argument [BZ #34313]

Sam James sam@gentoo.org
Tue Sep 1 21:29:19 GMT 2026


enh <enh@google.com> writes:

> is this actually true? i don't have a 7.2 kernel to test on, but
> looking at the source it looks like we wouldn't get as far as

I think you're right, but I'm also not sure it matters much. Dropping
the attribute isn't a promise that it's safe or anything (a wrong
nonnull attribute becomes very painful later on as gcc optimises based
on it). I wouldn't be surprised if O_EMPTYPATH was made like
AT_EMPTY_PATH.

Maybe that's not going to happen though.

>
> commit 5b313bcb6e3597dacd893ae9545fd087df46db45
> Author: Al Viro <viro@zeniv.linux.org.uk>
> Date:   Sat Oct 19 20:32:39 2024 -0400
>
>     teach filename_lookup() to treat NULL filename as ""
>
>     Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
>
> because we'd hit the failure path in
>
> static struct filename *
> do_getname(const char __user *filename, int flags, bool incomplete)
> {
>         struct filename *result;
>         char *kname;
>         int len;
>
>         result = alloc_filename();
>         if (unlikely(!result))
>                 return ERR_PTR(-ENOMEM);
>
>         /*
>          * First, try to embed the struct filename inside the names_cache
>          * allocation
>          */
>         kname = (char *)result->iname;
>         result->name = kname;
>
>         len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
>         /*
>          * Handle both empty path and copy failure in one go.
>          */
>         if (unlikely(len <= 0)) {
>                 /* The empty path is special. */
>                 if (!len && !(flags & LOOKUP_EMPTY))
>                         len = -ENOENT;
>         }
>
>         /*
>          * Uh-oh. We have a name that's approaching PATH_MAX. Allocate a
>          * separate struct filename so we can dedicate the entire
>          * names_cache allocation for the pathname, and re-do the copy from
>          * userland.
>          */
>         if (unlikely(len == EMBEDDED_NAME_MAX))
>                 len = getname_long(result, filename);
>         if (unlikely(len < 0)) {
>                 free_filename(result);
>                 return ERR_PTR(len);
>         }
>
>         initname(result);
>         if (likely(!incomplete))
>                 audit_getname(result);
>         return result;
> }
>
> first?
>
> (afaict the upstream kernel tests for these two syscalls also only
> test "" and not NULL.)
>
> On Sat, Aug 29, 2026 at 12:38 PM Sam James <sam@gentoo.org> wrote:
>>
>> .. and openat64.
>>
>> Linux 7.2 (31cf44efa6df72a524b40adefb80539f3a4e13ba) allows openat, openat2
>> to take a NULL path with the new O_EMPTYPATH flag, so the nonnull attribute
>> is no longer sound. Drop it.
>>
>> Bug: https://sourceware.org/PR34313
>> ---
>>  include/fcntl.h                                    |  6 ++----
>>  io/bits/fcntl2.h                                   | 12 ++++--------
>>  io/fcntl.h                                         |  8 +++-----
>>  sysdeps/unix/sysv/linux/bits/fcntl-linux-fortify.h |  2 +-
>>  sysdeps/unix/sysv/linux/bits/fcntl-linux.h         |  2 +-
>>  5 files changed, 11 insertions(+), 19 deletions(-)
>>
>> diff --git a/include/fcntl.h b/include/fcntl.h
>> index be435047bc..86890a5b3d 100644
>> --- a/include/fcntl.h
>> +++ b/include/fcntl.h
>> @@ -20,11 +20,9 @@ extern int __fcntl (int __fd, int __cmd, ...);
>>  libc_hidden_proto (__fcntl)
>>  extern int __fcntl64 (int __fd, int __cmd, ...) attribute_hidden;
>>  libc_hidden_proto (__fcntl64)
>> -extern int __openat (int __fd, const char *__file, int __oflag, ...)
>> -  __nonnull ((2));
>> +extern int __openat (int __fd, const char *__file, int __oflag, ...);
>>  libc_hidden_proto (__openat)
>> -extern int __openat64 (int __fd, const char *__file, int __oflag, ...)
>> -  __nonnull ((2));
>> +extern int __openat64 (int __fd, const char *__file, int __oflag, ...);
>>  libc_hidden_proto (__openat64)
>>
>>  extern int __open_2 (const char *__path, int __oflag);
>> diff --git a/io/bits/fcntl2.h b/io/bits/fcntl2.h
>> index f076cc3367..074c16b204 100644
>> --- a/io/bits/fcntl2.h
>> +++ b/io/bits/fcntl2.h
>> @@ -135,18 +135,14 @@ open64 (__fortify_clang_overload_arg (const char *, ,__path), int __oflag,
>>
>>  #ifdef __USE_ATFILE
>>  # ifndef __USE_FILE_OFFSET64
>> -extern int __openat_2 (int __fd, const char *__path, int __oflag)
>> -     __nonnull ((2));
>> +extern int __openat_2 (int __fd, const char *__path, int __oflag);
>>  extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
>> -                                       int __oflag, ...), openat)
>> -     __nonnull ((2));
>> +                                       int __oflag, ...), openat);
>>  # else
>>  extern int __REDIRECT (__openat_2, (int __fd, const char *__path,
>> -                                   int __oflag), __openat64_2)
>> -     __nonnull ((2));
>> +                                   int __oflag), __openat64_2);
>>  extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
>> -                                       int __oflag, ...), openat64)
>> -     __nonnull ((2));
>> +                                       int __oflag, ...), openat64);
>>  # endif
>>
>>  # ifdef __va_arg_pack_len
>> diff --git a/io/fcntl.h b/io/fcntl.h
>> index d0ad4d6652..3d90cc9adb 100644
>> --- a/io/fcntl.h
>> +++ b/io/fcntl.h
>> @@ -230,19 +230,17 @@ extern int open64 (const char *__file, int __oflag, ...) __nonnull ((1));
>>     This function is a cancellation point and therefore not marked with
>>     __THROW.  */
>>  # ifndef __USE_FILE_OFFSET64
>> -extern int openat (int __fd, const char *__file, int __oflag, ...)
>> -     __nonnull ((2));
>> +extern int openat (int __fd, const char *__file, int __oflag, ...);
>>  # else
>>  #  ifdef __REDIRECT
>>  extern int __REDIRECT (openat, (int __fd, const char *__file, int __oflag,
>> -                               ...), openat64) __nonnull ((2));
>> +                               ...), openat64);
>>  #  else
>>  #   define openat openat64
>>  #  endif
>>  # endif
>>  # ifdef __USE_LARGEFILE64
>> -extern int openat64 (int __fd, const char *__file, int __oflag, ...)
>> -     __nonnull ((2));
>> +extern int openat64 (int __fd, const char *__file, int __oflag, ...);
>>  # endif
>>  #endif
>>
>> diff --git a/sysdeps/unix/sysv/linux/bits/fcntl-linux-fortify.h b/sysdeps/unix/sysv/linux/bits/fcntl-linux-fortify.h
>> index 4c8f3a874e..b12b5b75da 100644
>> --- a/sysdeps/unix/sysv/linux/bits/fcntl-linux-fortify.h
>> +++ b/sysdeps/unix/sysv/linux/bits/fcntl-linux-fortify.h
>> @@ -25,7 +25,7 @@
>>  extern int __REDIRECT (__openat2_alias, (int __dfd, const char *__filename,
>>                                          const struct open_how *__how,
>>                                          size_t __usize), openat2)
>> -     __nonnull ((2, 3));
>> +     __nonnull ((3));
>>
>>  #if !__fortify_use_clang
>>  __errordecl (__openat2_invalid_size,
>> diff --git a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
>> index 587b815124..6aaa6cc4e7 100644
>> --- a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
>> +++ b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h
>> @@ -485,7 +485,7 @@ extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle,
>>  extern int openat2 (int __dfd, const char * __filename,
>>                     const struct open_how * __how,
>>                     __SIZE_TYPE__ __usize)
>> -     __nonnull ((2, 3));
>> +     __nonnull ((3));
>>
>>  #endif /* use GNU */
>>
>> --
>> 2.55.0
>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 418 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260901/647b111d/attachment.sig>


More information about the Libc-alpha mailing list