From 17d6fc4e643a15312a483eb4fa8dfa3f06a41e91 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 6 Jan 2020 12:30:38 +0100 Subject: [PATCH 1/2] gutils: Avoid null dereference if getpwuid fails to acquire some information about user Signed-off-by: Jakub Jelen --- glib/gutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/gutils.c b/glib/gutils.c index 6c89fc4cc9..572c06ce6a 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -681,7 +681,7 @@ g_get_user_database_entry (void) e.user_name = g_strdup (pw->pw_name); #ifndef __BIONIC__ - if (pw->pw_gecos && *pw->pw_gecos != '\0') + if (pw->pw_gecos && *pw->pw_gecos != '\0' && pw->pw_name) { gchar **gecos_fields; gchar **name_parts; -- GitLab From d2107c17c8080f20329641b37bb9cc27d328a306 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 6 Jan 2020 13:43:33 +0100 Subject: [PATCH 2/2] Reproducer for the null pw_name returned from getpwuid() Signed-off-by: Jakub Jelen --- glib/tests/getpwuid-preload.c | 45 +++++++++++++++++++++++++++++++ glib/tests/gutils-user-database.c | 43 +++++++++++++++++++++++++++++ glib/tests/meson.build | 21 +++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 glib/tests/getpwuid-preload.c create mode 100644 glib/tests/gutils-user-database.c diff --git a/glib/tests/getpwuid-preload.c b/glib/tests/getpwuid-preload.c new file mode 100644 index 0000000000..71df9cbf4f --- /dev/null +++ b/glib/tests/getpwuid-preload.c @@ -0,0 +1,45 @@ +/* GLIB - Library of useful routines for C programming + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + */ + +#include +#include +#include +#include + +static struct passwd my_pw; + +/* This is used in gutils.c used to make sure utility functions + * handling user information do not crash on bad data (for example + * caused by getpwuid returning some NULL elements. + */ +struct passwd * +getpwuid (uid_t uid) +{ + static struct passwd *(*real_getpwuid) (uid_t); + struct passwd *pw; + + if (real_getpwuid == NULL) + real_getpwuid = dlsym (RTLD_NEXT, "getpwuid"); + + pw = real_getpwuid (uid); + my_pw = *pw; + my_pw.pw_name = NULL; + return &my_pw; +} diff --git a/glib/tests/gutils-user-database.c b/glib/tests/gutils-user-database.c new file mode 100644 index 0000000000..aef599a7be --- /dev/null +++ b/glib/tests/gutils-user-database.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * See the included COPYING file for more information. + */ + +#include + +/* The function g_get_user_database_entry() is called from the + * g_get_real_name(), g_get_user_name() and g_build_home_dir() + * functions. These two calls are here just to invoke the code + * paths. The real-test is the ld_preload used to inject the + * NULL in place of pw->pw_name. + */ +static void +test_get_user_database_entry (void) +{ + const gchar *r = NULL; + + r = g_get_user_name (); + g_assert_nonnull (r); + + r = g_get_real_name (); + g_assert_nonnull (r); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/issues"); + + g_test_add_func ("/gutils/get_user_database_entry", test_get_user_database_entry); + + return g_test_run (); +} diff --git a/glib/tests/meson.build b/glib/tests/meson.build index c47133f241..073d47c7c9 100644 --- a/glib/tests/meson.build +++ b/glib/tests/meson.build @@ -148,6 +148,27 @@ else 'include' : {}, 'unix' : {}, } + if have_rtld_next + glib_tests += { + 'gutils-user-database' : { + 'depends' : [ + shared_library('getpwuid-preload', + 'getpwuid-preload.c', + name_prefix : '', + dependencies: libdl_dep, + install_dir : installed_tests_execdir, + install: installed_tests_enabled, + ), + ], + 'env' : { + 'LD_PRELOAD': '@0@/getpwuid-preload.so'.format(meson.current_build_dir()), + }, + 'installed_tests_env' : { + 'LD_PRELOAD': '@0@/getpwuid-preload.so'.format(installed_tests_execdir), + }, + }, + } + endif endif if installed_tests_enabled -- GitLab