From f38e82e57403ccb0c035743f0fa4d0ee94385003 Mon Sep 17 00:00:00 2001 From: Qingqing Li Date: Tue, 1 Jul 2025 10:49:46 +0800 Subject: [PATCH] support: Pick group in support_capture_subprogram_self_sgid if UID == 0 Fix error reporting (false negatives) in SGID tests (cherry picked from commit 62fe2fb3c7d69e1ee580b2daf21fcd81a9ed454d) --- ...orting-false-negatives-in-SGID-tests.patch | 320 ++++++++++++++++++ glibc.spec | 68 ++-- ...up-in-support_capture_subprogram_sel.patch | 112 ++++++ 3 files changed, 468 insertions(+), 32 deletions(-) create mode 100644 Fix-error-reporting-false-negatives-in-SGID-tests.patch create mode 100644 support-Pick-group-in-support_capture_subprogram_sel.patch diff --git a/Fix-error-reporting-false-negatives-in-SGID-tests.patch b/Fix-error-reporting-false-negatives-in-SGID-tests.patch new file mode 100644 index 0000000..88d862f --- /dev/null +++ b/Fix-error-reporting-false-negatives-in-SGID-tests.patch @@ -0,0 +1,320 @@ +From 5a6276d97aa6f8ab105de811020ab7187e388dcb Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 22 May 2025 14:36:37 +0200 +Subject: [PATCH] Fix error reporting (false negatives) in SGID tests + +And simplify the interface of support_capture_subprogram_self_sgid. + +Use the existing framework for temporary directories (now with +mode 0700) and directory/file deletion. Handle all execution +errors within support_capture_subprogram_self_sgid. In particular, +this includes test failures because the invoked program did not +exit with exit status zero. Existing tests that expect exit +status 42 are adjusted to use zero instead. + +In addition, fix callers not to call exit (0) with test failures +pending (which may mask them, especially when running with --direct). + +Fixes commit 35fc356fa3b4f485bd3ba3114c9f774e5df7d3c2 +("elf: Fix subprocess status handling for tst-dlopen-sgid (bug 32987)"). + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 3a3fb2ed83f79100c116c824454095ecfb335ad7) +--- + elf/tst-dlopen-sgid.c | 8 +- + elf/tst-env-setuid-tunables.c | 18 +---- + elf/tst-env-setuid.c | 10 +-- + stdlib/tst-secure-getenv.c | 9 +-- + support/capture_subprocess.h | 10 ++- + support/support_capture_subprocess.c | 106 ++++++--------------------- + 6 files changed, 36 insertions(+), 125 deletions(-) + +diff --git a/elf/tst-dlopen-sgid.c b/elf/tst-dlopen-sgid.c +index 5688b79f2e..8aec52e19f 100644 +--- a/elf/tst-dlopen-sgid.c ++++ b/elf/tst-dlopen-sgid.c +@@ -70,13 +70,7 @@ do_test (void) + + free (libdir); + +- int status = support_capture_subprogram_self_sgid (magic_argument); +- +- if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) +- return EXIT_UNSUPPORTED; +- +- if (!WIFEXITED (status)) +- FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); ++ support_capture_subprogram_self_sgid (magic_argument); + + return 0; + } +diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c +index f0b92c97e7..4634498587 100644 +--- a/elf/tst-env-setuid-tunables.c ++++ b/elf/tst-env-setuid-tunables.c +@@ -116,10 +116,7 @@ do_test (int argc, char **argv) + + if (ret != 0) + exit (1); +- +- /* Special return code to make sure that the child executed all the way +- through. */ +- exit (42); ++ return 0; + } + else + { +@@ -138,18 +135,7 @@ do_test (int argc, char **argv) + continue; + } + +- int status = support_capture_subprogram_self_sgid (buf); +- +- /* Bail out early if unsupported. */ +- if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) +- return EXIT_UNSUPPORTED; +- +- if (WEXITSTATUS (status) != 42) +- { +- printf (" [%d] child failed with status %d\n", i, +- WEXITSTATUS (status)); +- support_record_failure (); +- } ++ support_capture_subprogram_self_sgid (buf); + } + return 0; + } +diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c +index 032ab44be2..d3753f0fe7 100644 +--- a/elf/tst-env-setuid.c ++++ b/elf/tst-env-setuid.c +@@ -104,20 +104,14 @@ do_test (int argc, char **argv) + if (ret != 0) + exit (1); + +- exit (EXIT_SUCCESS); ++ return 0; + } + else + { + if (test_parent () != 0) + exit (1); + +- int status = support_capture_subprogram_self_sgid (SETGID_CHILD); +- +- if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) +- return EXIT_UNSUPPORTED; +- +- if (!WIFEXITED (status)) +- FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); ++ support_capture_subprogram_self_sgid (SETGID_CHILD); + + return 0; + } +diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c +index b722f9909a..10847dacc5 100644 +--- a/stdlib/tst-secure-getenv.c ++++ b/stdlib/tst-secure-getenv.c +@@ -57,13 +57,7 @@ do_test (void) + exit (1); + } + +- int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT); +- +- if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) +- return EXIT_UNSUPPORTED; +- +- if (!WIFEXITED (status)) +- FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); ++ support_capture_subprogram_self_sgid (MAGIC_ARGUMENT); + + return 0; + } +@@ -82,6 +76,7 @@ alternative_main (int argc, char **argv) + if (secure_getenv ("PATH") != NULL) + FAIL_EXIT (4, "PATH variable not filtered out\n"); + ++ support_record_failure_barrier (); + exit (EXIT_SUCCESS); + } + } +diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h +index 098d63c6e3..48d99abe14 100644 +--- a/support/capture_subprocess.h ++++ b/support/capture_subprocess.h +@@ -41,10 +41,12 @@ struct support_capture_subprocess support_capture_subprocess + struct support_capture_subprocess support_capture_subprogram + (const char *file, char *const argv[]); + +-/* Copy the running program into a setgid binary and run it with CHILD_ID +- argument. If execution is successful, return the exit status of the child +- program, otherwise return a non-zero failure exit code. */ +-int support_capture_subprogram_self_sgid (const char *child_id); ++/* Copy the running program into a setgid binary and run it with ++ CHILD_ID argument. If the program exits with a non-zero status, ++ exit with that exit status (or status 1 if the program did not exit ++ normally). If the test cannot be performed, exit with ++ EXIT_UNSUPPORTED. */ ++void support_capture_subprogram_self_sgid (const char *child_id); + + /* Deallocate the subprocess data captured by + support_capture_subprocess. */ +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 76c8a235e3..21f024af41 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + + static void +@@ -112,105 +113,44 @@ support_capture_subprogram (const char *file, char *const argv[]) + /* Copies the executable into a restricted directory, so that we can + safely make it SGID with the TARGET group ID. Then runs the + executable. */ +-static int ++static void + copy_and_spawn_sgid (const char *child_id, gid_t gid) + { +- char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", +- test_dir, (intmax_t) getpid ()); ++ char *dirname = support_create_temp_directory ("tst-glibc-sgid-"); + char *execname = xasprintf ("%s/bin", dirname); +- int infd = -1; +- int outfd = -1; +- int ret = 1, status = 1; +- +- TEST_VERIFY (mkdir (dirname, 0700) == 0); +- if (support_record_failure_is_failed ()) +- goto err; ++ add_temp_file (execname); + +- infd = open ("/proc/self/exe", O_RDONLY); +- if (infd < 0) ++ if (access ("/proc/self/exe", R_OK) != 0) + FAIL_UNSUPPORTED ("unsupported: Cannot read binary from procfs\n"); + +- outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); +- TEST_VERIFY (outfd >= 0); +- if (support_record_failure_is_failed ()) +- goto err; +- +- char buf[4096]; +- for (;;) +- { +- ssize_t rdcount = read (infd, buf, sizeof (buf)); +- TEST_VERIFY (rdcount >= 0); +- if (support_record_failure_is_failed ()) +- goto err; +- if (rdcount == 0) +- break; +- char *p = buf; +- char *end = buf + rdcount; +- while (p != end) +- { +- ssize_t wrcount = write (outfd, buf, end - p); +- if (wrcount == 0) +- errno = ENOSPC; +- TEST_VERIFY (wrcount > 0); +- if (support_record_failure_is_failed ()) +- goto err; +- p += wrcount; +- } +- } ++ support_copy_file ("/proc/self/exe", execname); + +- bool chowned = false; +- TEST_VERIFY ((chowned = fchown (outfd, getuid (), gid) == 0) +- || errno == EPERM); +- if (support_record_failure_is_failed ()) +- goto err; +- else if (!chowned) +- { +- ret = 77; +- goto err; +- } ++ if (chown (execname, getuid (), gid) != 0) ++ FAIL_UNSUPPORTED ("cannot change group of \"%s\" to %jd: %m", ++ execname, (intmax_t) gid); + +- TEST_VERIFY (fchmod (outfd, 02750) == 0); +- if (support_record_failure_is_failed ()) +- goto err; +- TEST_VERIFY (close (outfd) == 0); +- if (support_record_failure_is_failed ()) +- goto err; +- TEST_VERIFY (close (infd) == 0); +- if (support_record_failure_is_failed ()) +- goto err; ++ if (chmod (execname, 02750) != 0) ++ FAIL_UNSUPPORTED ("cannot make \"%s\" SGID: %m ", execname); + + /* We have the binary, now spawn the subprocess. Avoid using + support_subprogram because we only want the program exit status, not the + contents. */ +- ret = 0; +- infd = outfd = -1; + + char * const args[] = {execname, (char *) child_id, NULL}; ++ int status = support_subprogram_wait (args[0], args); + +- status = support_subprogram_wait (args[0], args); ++ free (execname); ++ free (dirname); + +-err: +- if (outfd >= 0) +- close (outfd); +- if (infd >= 0) +- close (infd); +- if (execname != NULL) +- { +- unlink (execname); +- free (execname); +- } +- if (dirname != NULL) ++ if (WIFEXITED (status)) + { +- rmdir (dirname); +- free (dirname); ++ if (WEXITSTATUS (status) == 0) ++ return; ++ else ++ exit (WEXITSTATUS (status)); + } +- +- if (ret == 77) +- FAIL_UNSUPPORTED ("Failed to make sgid executable for test\n"); +- if (ret != 0) +- FAIL_EXIT1 ("Failed to make sgid executable for test\n"); +- +- return status; ++ else ++ FAIL_EXIT1 ("subprogram failed with status %d", status); + } + + /* Returns true if a group with NAME has been found, and writes its +@@ -252,7 +192,7 @@ find_sgid_group (gid_t *target, const char *name) + return ok; + } + +-int ++void + support_capture_subprogram_self_sgid (const char *child_id) + { + const int count = 64; +@@ -287,7 +227,7 @@ support_capture_subprogram_self_sgid (const char *child_id) + (intmax_t) getuid ()); + } + +- return copy_and_spawn_sgid (child_id, target); ++ copy_and_spawn_sgid (child_id, target); + } + + void +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index e3fe786..f1bb632 100644 --- a/glibc.spec +++ b/glibc.spec @@ -67,7 +67,7 @@ ############################################################################## Name: glibc Version: 2.38 -Release: 59 +Release: 60 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -292,6 +292,8 @@ Patch202: support-Add-support_record_failure_barrier.patch Patch203: elf-Test-case-for-bug-32976-CVE-2025-4802.patch Patch204: x86_64-Fix-typo-in-ifunc-impl-list.c.patch Patch205: elf-Fix-subprocess-status-handling-for-tst-dlopen-sg.patch +Patch206: support-Pick-group-in-support_capture_subprogram_sel.patch +Patch207: Fix-error-reporting-false-negatives-in-SGID-tests.patch #openEuler patch list Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch @@ -303,39 +305,37 @@ Patch9005: add-GB18030-2022-charmap-BZ-30243.patch Patch9006: fix-Segmentation-fault-in-nss-module.patch Patch9007: fix_nss_database_check_reload_and_get_memleak.patch Patch9008: 0001-fix-glibc-build-error-on-x86.patch - -Patch9010: add-Wl-z-noseparate-code-for-so.patch +Patch9009: add-Wl-z-noseparate-code-for-so.patch # Sw64 Port glibc -Patch9011: 0001-Sw64-Add-Sw64-entries-to-config.h.in.patch -Patch9012: 0002-Sw64-Add-relocations-and-ELF-flags-to-elf.h-and-scri.patch -Patch9013: 0003-Sw64-ABI-Implementation.patch -Patch9014: 0004-Sw64-Thread-Local-Storage-Support.patch -Patch9015: 0005-Sw64-Generic-math.h-and-soft-fp-Routines.patch -Patch9016: 0006-Sw64-Atomic-and-Locking-Implementation.patch -Patch9017: 0007-Sw64-Linux-Syscall-Interface.patch -Patch9018: 0008-Sw64-Linux-ABI.patch -Patch9019: 0009-Sw64-Add-ABI-Lists.patch -Patch9020: 0010-Sw64-Build-Infrastructure.patch -Patch9021: 0011-Sw64-Integer-Operation-Support.patch -Patch9022: 0012-Sw64-Memory-and-String-Implementation.patch -Patch9023: 0013-Sw64-math-support.patch -Patch9024: 0014-Sw64-float128-Implementation.patch -Patch9025: 0015-Sw64-Add-get_rounding_mode.patch -Patch9026: 0016-Sw64-Add-specific-math-difinitons.patch -Patch9027: 0017-Sw64-Introduce-elf-initfini.h-and-ELF_INITFINI-for-s.patch -Patch9028: 0018-Sw64-Type-definitions-for-nscd-on-sw64.patch -Patch9029: 0019-Sw64-GCC-frame-desciption-for-sw64.patch -Patch9030: 0020-Sw64-Update-libm-test-ulps.patch -Patch9031: 0021-Sw64-Add-test_numdouble.h-and-test_numfloat.h.patch -Patch9032: 0022-Sw64-Fix-posix-tst-glob_lstat_compat-on-sw64.patch -Patch9033: 0023-Sw64-add-getopt-weak-alias.patch - -Patch9034: 0001-x86-Set-preferred-CPU-features-on-the-KH-40000-and-K.patch -Patch9035: 0002-x86_64-Optimize-large-size-copy-in-memmove-ssse3.patch -Patch9036: 0003-x86-Set-default-non_temporal_threshold-for-Zhaoxin-p.patch - -Patch9037: fix-CVE-2019-1010023.patch +Patch9010: 0001-Sw64-Add-Sw64-entries-to-config.h.in.patch +Patch9011: 0002-Sw64-Add-relocations-and-ELF-flags-to-elf.h-and-scri.patch +Patch9012: 0003-Sw64-ABI-Implementation.patch +Patch9013: 0004-Sw64-Thread-Local-Storage-Support.patch +Patch9014: 0005-Sw64-Generic-math.h-and-soft-fp-Routines.patch +Patch9015: 0006-Sw64-Atomic-and-Locking-Implementation.patch +Patch9016: 0007-Sw64-Linux-Syscall-Interface.patch +Patch9017: 0008-Sw64-Linux-ABI.patch +Patch9018: 0009-Sw64-Add-ABI-Lists.patch +Patch9019: 0010-Sw64-Build-Infrastructure.patch +Patch9020: 0011-Sw64-Integer-Operation-Support.patch +Patch9021: 0012-Sw64-Memory-and-String-Implementation.patch +Patch9022: 0013-Sw64-math-support.patch +Patch9023: 0014-Sw64-float128-Implementation.patch +Patch9024: 0015-Sw64-Add-get_rounding_mode.patch +Patch9025: 0016-Sw64-Add-specific-math-difinitons.patch +Patch9026: 0017-Sw64-Introduce-elf-initfini.h-and-ELF_INITFINI-for-s.patch +Patch9027: 0018-Sw64-Type-definitions-for-nscd-on-sw64.patch +Patch9028: 0019-Sw64-GCC-frame-desciption-for-sw64.patch +Patch9029: 0020-Sw64-Update-libm-test-ulps.patch +Patch9030: 0021-Sw64-Add-test_numdouble.h-and-test_numfloat.h.patch +Patch9031: 0022-Sw64-Fix-posix-tst-glob_lstat_compat-on-sw64.patch +Patch9032: 0023-Sw64-add-getopt-weak-alias.patch + +Patch9033: 0001-x86-Set-preferred-CPU-features-on-the-KH-40000-and-K.patch +Patch9034: 0002-x86_64-Optimize-large-size-copy-in-memmove-ssse3.patch +Patch9035: 0003-x86-Set-default-non_temporal_threshold-for-Zhaoxin-p.patch +Patch9036: fix-CVE-2019-1010023.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1516,6 +1516,10 @@ fi %endif %changelog +* Tue Jul 01 2025 Qingqing Li - 2.38-60 +- support: Pick group in support_capture_subprogram_self_sgid if UID == 0 +- Fix error reporting (false negatives) in SGID tests + * Wed May 21 2025 Qingqing Li - 2.38-59 - elf: Fix subprocess status handling for tst-dlopen-sgid (bug 32987) diff --git a/support-Pick-group-in-support_capture_subprogram_sel.patch b/support-Pick-group-in-support_capture_subprogram_sel.patch new file mode 100644 index 0000000..23271de --- /dev/null +++ b/support-Pick-group-in-support_capture_subprogram_sel.patch @@ -0,0 +1,112 @@ +From 81f58dd9b7c3ec595ecdc0ea93a9c80ba2449169 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 21 May 2025 16:47:34 +0200 +Subject: [PATCH] support: Pick group in support_capture_subprogram_self_sgid + if UID == 0 + +When running as root, it is likely that we can run under any group. +Pick a harmless group from /etc/group in this case. + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 2f769cec448d84a62b7dd0d4ff56978fe22c0cd6) +--- + support/support_capture_subprocess.c | 58 ++++++++++++++++++++++++++-- + 1 file changed, 54 insertions(+), 4 deletions(-) + +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 4393210d68..76c8a235e3 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -21,7 +21,11 @@ + + #include + #include ++#include ++#include ++#include + #include ++#include + #include + #include + #include +@@ -209,10 +213,48 @@ err: + return status; + } + ++/* Returns true if a group with NAME has been found, and writes its ++ GID to *TARGET. */ ++static bool ++find_sgid_group (gid_t *target, const char *name) ++{ ++ /* Do not use getgrname_r because it does not work in statically ++ linked binaries if the system libc is different. */ ++ FILE *fp = fopen ("/etc/group", "rce"); ++ if (fp == NULL) ++ return false; ++ __fsetlocking (fp, FSETLOCKING_BYCALLER); ++ ++ bool ok = false; ++ struct scratch_buffer buf; ++ scratch_buffer_init (&buf); ++ while (true) ++ { ++ struct group grp; ++ struct group *result = NULL; ++ int status = fgetgrent_r (fp, &grp, buf.data, buf.length, &result); ++ if (status == 0 && result != NULL) ++ { ++ if (strcmp (result->gr_name, name) == 0) ++ { ++ *target = result->gr_gid; ++ ok = true; ++ break; ++ } ++ } ++ else if (errno != ERANGE) ++ break; ++ else if (!scratch_buffer_grow (&buf)) ++ break; ++ } ++ scratch_buffer_free (&buf); ++ fclose (fp); ++ return ok; ++} ++ + int + support_capture_subprogram_self_sgid (const char *child_id) + { +- gid_t target = 0; + const int count = 64; + gid_t groups[count]; + +@@ -224,6 +266,7 @@ support_capture_subprogram_self_sgid (const char *child_id) + (intmax_t) getuid ()); + + gid_t current = getgid (); ++ gid_t target = current; + for (int i = 0; i < ret; ++i) + { + if (groups[i] != current) +@@ -233,9 +276,16 @@ support_capture_subprogram_self_sgid (const char *child_id) + } + } + +- if (target == 0) +- FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n", +- (intmax_t) getuid ()); ++ if (target == current) ++ { ++ /* If running as root, try to find a harmless group for SGID. */ ++ if (getuid () != 0 ++ || (!find_sgid_group (&target, "nogroup") ++ && !find_sgid_group (&target, "bin") ++ && !find_sgid_group (&target, "daemon"))) ++ FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n", ++ (intmax_t) getuid ()); ++ } + + return copy_and_spawn_sgid (child_id, target); + } +-- +2.27.0 + -- Gitee