From 895c2a92c069910357467f7ed1b3f73fd264d534 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 15 May 2026 09:23:07 +0200 Subject: [PATCH] Various fixes - groupmod.c: delete gr_free_members(&grp) to avoid double free - subordinateio.c: list_owner_ranges(): Fix duplicate range when username matches ID Resolves: RHEL-135902 Resolves: RHEL-114226 Signed-off-by: Iker Pedrosa --- shadow-4.15.0-groupmod-segfault.patch | 57 ++++++++ ...15.0-subordinate-fix-duplicate-range.patch | 124 ++++++++++++++++++ shadow-utils.spec | 13 +- 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 shadow-4.15.0-groupmod-segfault.patch create mode 100644 shadow-4.15.0-subordinate-fix-duplicate-range.patch diff --git a/shadow-4.15.0-groupmod-segfault.patch b/shadow-4.15.0-groupmod-segfault.patch new file mode 100644 index 0000000..8b6041a --- /dev/null +++ b/shadow-4.15.0-groupmod-segfault.patch @@ -0,0 +1,57 @@ +From 10429edc14673fbb8c78b25f1872c34e88e5f07f Mon Sep 17 00:00:00 2001 +From: lixinyun +Date: Wed, 29 May 2024 06:53:02 +0800 +Subject: [PATCH] src/groupmod.c: delete gr_free_members(&grp) to avoid double + free + +Groupmod -U may cause crashes because of double free. If without -a, the first free of (*ogrp).gr_mem is in gr_free_members(&grp), and then in gr_update without -n or gr_remove with -n. +Considering the minimal impact of modifications on existing code, delete gr_free_members(&grp) to avoid double free.Although this may seem reckless, the second free in two different positions will definitely be triggered, and the following two test cases can be used to illustrate the situation : + +[root@localhost src]# ./useradd u1 +[root@localhost src]# ./useradd u2 +[root@localhost src]# ./useradd u3 +[root@localhost src]# ./groupadd -U u1,u2,u3 g1 +[root@localhost src]# ./groupmod -n g2 -U u1,u2 g1 +Segmentation fault + +This case would free (*ogrp).gr_mem in gr_free_members(&grp) due to assignment statements grp = *ogrp, then in if (nflg && (gr_remove (group_name) == 0)), which finally calls gr_free_members(grent) to free (*ogrp).gr_mem again. + +[root@localhost src]# ./useradd u1 +[root@localhost src]# ./useradd u2 +[root@localhost src]# ./useradd u3 +[root@localhost src]# ./groupadd -U u1,u2,u3 g1 +[root@localhost src]# ./groupmod -U u1,u2 g1 +Segmentation fault + +The other case would free (*ogrp).gr_mem in gr_free_members(&grp) too, then in if (gr_update (&grp) == 0), which finally calls gr_free_members(grent) too to free (*ogrp).gr_mem again. + +So the first free is unnecessary, maybe we can drop it. + +Fixes: 342c934a3590 ("add -U option to groupadd and groupmod") +Closes: +Link: +Link: +Link: +Cc: "Serge E. Hallyn" +Reviewed-by: Alejandro Colomar +Signed-off-by: lixinyun +--- + src/groupmod.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/groupmod.c b/src/groupmod.c +index a29cf73f..989d7ea3 100644 +--- a/src/groupmod.c ++++ b/src/groupmod.c +@@ -250,8 +250,6 @@ static void grp_update (void) + + if (!aflg) { + // requested to replace the existing groups +- if (NULL != grp.gr_mem[0]) +- gr_free_members(&grp); + grp.gr_mem = XMALLOC(1, char *); + grp.gr_mem[0] = NULL; + } else { +-- +2.54.0 + diff --git a/shadow-4.15.0-subordinate-fix-duplicate-range.patch b/shadow-4.15.0-subordinate-fix-duplicate-range.patch new file mode 100644 index 0000000..773c080 --- /dev/null +++ b/shadow-4.15.0-subordinate-fix-duplicate-range.patch @@ -0,0 +1,124 @@ +From 67c42427a0941a4b47c04e8a95322be9d069ff32 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Tue, 15 Oct 2024 13:21:17 +0200 +Subject: [PATCH] lib/string/strcmp/: streq(): Add function + +Signed-off-by: Alejandro Colomar +--- + lib/subordinateio.c | 9 +++++---- + lib/Makefile.am | 2 ++ + lib/string/strcmp/streq.c | 12 ++++++++++++ + lib/string/strcmp/streq.h | 30 ++++++++++++++++++++++++++++++ + 4 files changed, 44 insertions(+) + create mode 100644 lib/string/strcmp/streq.c + create mode 100644 lib/string/strcmp/streq.h + +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 295df2bd..45085481 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -23,6 +23,7 @@ + + #include "alloc.h" + #include "string/sprintf.h" ++#include "string/strcmp/streq.h" + + + #define ID_SIZE 31 +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 4ea5ec4e..96393354 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -154,6 +154,8 @@ libshadow_la_SOURCES = \ + string/strtcpy.h \ + string/zustr2stp.c \ + string/zustr2stp.h \ ++ string/strcmp/streq.c \ ++ string/strcmp/streq.h \ + strtoday.c \ + sub.c \ + subordinateio.h \ +diff --git a/lib/string/strcmp/streq.c b/lib/string/strcmp/streq.c +new file mode 100644 +index 00000000..52057ed8 +--- /dev/null ++++ b/lib/string/strcmp/streq.c +@@ -0,0 +1,12 @@ ++// SPDX-FileCopyrightText: 2024, Alejandro Colomar ++// SPDX-License-Identifier: BSD-3-Clause ++ ++ ++#include ++ ++#include ++ ++#include "string/strcmp/streq.h" ++ ++ ++extern inline bool streq(const char *s1, const char *s2); +diff --git a/lib/string/strcmp/streq.h b/lib/string/strcmp/streq.h +new file mode 100644 +index 00000000..267045c5 +--- /dev/null ++++ b/lib/string/strcmp/streq.h +@@ -0,0 +1,30 @@ ++// SPDX-FileCopyrightText: 2024, Alejandro Colomar ++// SPDX-License-Identifier: BSD-3-Clause ++ ++ ++#ifndef SHADOW_INCLUDE_LIB_STRING_STRCMP_STREQ_H_ ++#define SHADOW_INCLUDE_LIB_STRING_STRCMP_STREQ_H_ ++ ++ ++#include ++ ++#include ++#include ++ ++#include "attr.h" ++ ++ ++ATTR_STRING(1) ++ATTR_STRING(2) ++inline bool streq(const char *s1, const char *s2); ++ ++ ++/* Return true if s1 and s2 compare equal. */ ++inline bool ++streq(const char *s1, const char *s2) ++{ ++ return strcmp(s1, s2) == 0; ++} ++ ++ ++#endif // include guard +-- +2.54.0 + + +diff -up shadow-4.15.0/lib/subordinateio.c.orig shadow-4.15.0/lib/subordinateio.c +--- shadow-4.15.0/lib/subordinateio.c.orig 2026-05-14 15:54:21.131636830 +0200 ++++ shadow-4.15.0/lib/subordinateio.c 2026-05-14 15:54:35.544472143 +0200 +@@ -868,18 +868,10 @@ int list_owner_ranges(const char *owner, + have_owner_id = get_owner_id(owner, id_type, id); + + commonio_rewind(db); +- while ((range = commonio_next(db)) != NULL) { +- if (0 == strcmp(range->owner, owner)) { +- if (!append_range(&ranges, range, count++)) { +- free(ranges); +- ranges = NULL; +- count = -1; +- goto out; +- } +- } +- +- // Let's also compare with the ID +- if (have_owner_id == true && 0 == strcmp(range->owner, id)) { ++ while (NULL != (range = commonio_next(db))) { ++ if ( streq(range->owner, owner) ++ || (have_owner_id && streq(range->owner, id))) ++ { + if (!append_range(&ranges, range, count++)) { + free(ranges); + ranges = NULL; diff --git a/shadow-utils.spec b/shadow-utils.spec index dfe8654..20c5457 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils Version: 4.15.0 -Release: 11%{?dist} +Release: 12%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -40,6 +40,11 @@ Patch8: shadow-4.15.0-groupmod-help.patch Patch9: shadow-4.15.0-passwd-audit.patch # Downstream only Patch10: shadow-4.15.0-passwd-database.patch +# https://github.com/shadow-maint/shadow/commit/10429edc14673fbb8c78b25f1872c34e88e5f07f +Patch11: shadow-4.15.0-groupmod-segfault.patch +# https://github.com/shadow-maint/shadow/commit/67c42427a0941a4b47c04e8a95322be9d069ff32 +# https://github.com/shadow-maint/shadow/commit/02e930892590efd4023586696d05ce7ce2838e0f +Patch12: shadow-4.15.0-subordinate-fix-duplicate-range.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -288,6 +293,12 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri May 15 2026 Iker Pedrosa - 2:4.15.0-12 +- groupmod.c: delete gr_free_members(&grp) to avoid double free + Resolves: RHEL-135902 +- subordinateio.c: list_owner_ranges(): Fix duplicate range when + username matches ID. Resolves: RHEL-114226 + * Mon Feb 23 2026 Iker Pedrosa - 2:4.15.0-11 - passwd.c: lock, open, close and unlock passwd database Resolves: RHEL-151055