[PATCH] nss: Add missing failure check to __nss_database_get (bug 28940)
Florian Weimer
fweimer@redhat.com
Fri Jul 11 16:38:58 GMT 2025
* DJ Delorie:
> Florian Weimer <fweimer@redhat.com> writes:
>> __nss_database_get (enum nss_database db, nss_action_list *actions)
>> {
>> struct nss_database_state *local = nss_database_state_get ();
>> + if (local == NULL)
>> + return false;
>> return nss_database_check_reload_and_get (local, actions, db);
>> }
>
> This fix is obvious, but at the moment, there are two places that need
> fixing:
>
> local = nss_database_state_get ();
>
> result = __nss_action_parse (service_line);
> if (result == NULL)
> return -1;
>
> atomic_store_release (&local->data.reload_disabled, 1);
Hmm. You mean we should check the return value of
nss_database_state_get () there as well?
>> +/* Perform a getlogin_r call in a subprocess, to obtain the number of
>> + allocations used and the expected result of a successful call. */
>> +static void
>> +initialize (void *ignored)
>> +{
>> + {
>> + FILE *fp = fopen (_PATH_NSSWITCH_CONF, "r");
>
> As this depends (sort of) on the contents of /etc/nsswitch.conf, should
> this test be run in a container where the contents of that can be
> controlled?
I think we get more interesting results if we don't run in a container.
For example, my user is supplied by sssd.
>> +/* Perform getlogin_r in a subprocess with fault injection. */
>> +static void
>> +test_in_subprocess (void *ignored)
>> +{
>> + unsigned int inject_at = shared->failing_allocation;
>> + char name[sizeof (shared->name)];
>> + int ret = getlogin_r (name, sizeof (name));
>> + shared->failing_allocation = ~0U;
>> + if (ret == 0)
>> + TEST_COMPARE_STRING (name, shared->name);
>
> So you're relying on name - an undefined string - being different than
> a result from a previous run? I would pre-initialize name to something
> instead of leaving it undefined.
I assigned to some unlikely result string.
I tried to add coverage for the issue you pointed out, but I hit an
assertion failure:
Fatal glibc error: XXX-lookup.c:60 (__nss_passwd_lookup2): assertion failed: *ni != NULL
But for some reason reload_disabled is still set to 1:
(gdb) print *(struct nss_database_state *)global_database_state
$2 = {data = {nsswitch_conf = {size = -1,
ino = 15408456814510331349, mtime = {
tv_sec = -3038287259199220267,
tv_nsec = -3038287259199220267}, ctime = {
tv_sec = -3038287259199220267,
tv_nsec = -3038287259199220267}}, services = {0x0, 0x0,
0x0, 0x0, 0x0, 0x555572f73630, 0x0 <repeats 11 times>},
reload_disabled = 1, initialized = false}, lock = 0,
root_ino = 0, root_dev = 0}
I don't quite see reason for that yet. Because of reload_disabled, we
take the fast path. I don't quite see how reload_disabled and
!initialized can be true at the same time.
Partial patch attached. Any ideas?
Thanks,
Florian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-nss-Add-missing-failure-check-to-__nss_database_get-.patch
Type: text/x-patch
Size: 11805 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20250711/6461d1c8/attachment-0001.bin>
More information about the Libc-alpha
mailing list