From 9f643a301165a0b1bb1fcb7b9c425809d5791a2f Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Thu, 1 Oct 2020 13:23:15 +0000 Subject: [PATCH 001/118] Add Provides: shadow The upstream source tarball is actually called 'shadow' rather than 'shadow-utils'. Add a compat provides for the former. --- shadow-utils.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/shadow-utils.spec b/shadow-utils.spec index c8c4d2c..fbfe028 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -68,6 +68,7 @@ BuildRequires: /usr/bin/xsltproc, /usr/bin/itstool Requires: libselinux >= 1.25.2-1 Requires: audit-libs >= 1.6.5 Requires: setup +Provides: shadow = %{epoch}:%{version}-%{release} %description The shadow-utils package includes the necessary programs for From b7aa9ac8ec1d0d0e3c8d7a8eeda42db41754bd80 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Tue, 3 Nov 2020 16:14:35 +0100 Subject: [PATCH 002/118] Rebuild with libsemanage.so.2 --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index fbfe028..3367171 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.8.1 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -261,6 +261,9 @@ done %{_mandir}/man8/vigr.8* %changelog +* Tue Nov 3 2020 Petr Lautrbach - 2:4.8.1-5 +- Rebuild with libsemanage.so.2 + * Wed Jul 29 2020 Fedora Release Engineering - 2:4.8.1-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From 4f395dd42db2c2f6582ac6b1be90c138e090e09f Mon Sep 17 00:00:00 2001 From: ipedrosa Date: Mon, 9 Nov 2020 10:53:20 +0100 Subject: [PATCH 003/118] commonio: force lock file sync (#1862056) --- ...-4.8.1-commonio-force-lock-file-sync.patch | 39 +++++++++++++++++++ shadow-utils.spec | 11 +++++- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 shadow-4.8.1-commonio-force-lock-file-sync.patch diff --git a/shadow-4.8.1-commonio-force-lock-file-sync.patch b/shadow-4.8.1-commonio-force-lock-file-sync.patch new file mode 100644 index 0000000..5ca7b53 --- /dev/null +++ b/shadow-4.8.1-commonio-force-lock-file-sync.patch @@ -0,0 +1,39 @@ +From fb0f702cbf958a5ee9097c1611212c9880b347ce Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Mon, 2 Nov 2020 17:08:55 +0100 +Subject: [PATCH] commonio: force lock file sync + +lib/commonio.c: after writing to the lock file, force a file sync to +the storage system. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1862056 +--- + lib/commonio.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/lib/commonio.c b/lib/commonio.c +index 16fa7e75..c5b3d104 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -157,7 +157,17 @@ static int do_lock_file (const char *file, const char *lock, bool log) + if (write (fd, buf, (size_t) len) != len) { + if (log) { + (void) fprintf (stderr, +- "%s: %s: %s\n", ++ "%s: %s file write error: %s\n", ++ Prog, file, strerror (errno)); ++ } ++ (void) close (fd); ++ unlink (file); ++ return 0; ++ } ++ if (fdatasync (fd) == -1) { ++ if (log) { ++ (void) fprintf (stderr, ++ "%s: %s file sync error: %s\n", + Prog, file, strerror (errno)); + } + (void) close (fd); +-- +2.26.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 3367171..9c45824 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.8.1 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -53,8 +53,11 @@ Patch40: shadow-4.8-ignore-login-prompt.patch Patch42: shadow-4.8-useradd-selinux-mail.patch # Clarify useradd man regarding "-d" parameter - already upstreamed Patch43: shadow-4.8.1-useradd-man-clarification.patch -# Upstreamed +# https://github.com/shadow-maint/shadow/commit/140510de9de4771feb3af1d859c09604043a4c9b +# https://github.com/shadow-maint/shadow/commit/8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 Patch44: shadow-4.8.1-check-local-groups.patch +# https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 +Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch License: BSD and GPLv2+ BuildRequires: gcc @@ -106,6 +109,7 @@ are used for managing group accounts. %patch42 -p1 -b .useradd-selinux-mail %patch43 -p1 -b .useradd-man-clarification %patch44 -p1 -b .check-local-groups +%patch45 -p1 -b .commonio-force-lock-file-sync iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -261,6 +265,9 @@ done %{_mandir}/man8/vigr.8* %changelog +* Mon Nov 9 2020 Iker Pedrosa - 2:4.8.1-6 +- commonio: force lock file sync (#1862056) + * Tue Nov 3 2020 Petr Lautrbach - 2:4.8.1-5 - Rebuild with libsemanage.so.2 From b01d32cfea47f1c7e6a6b71025c17d3f4abaf437 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Thu, 1 Oct 2020 13:23:15 +0000 Subject: [PATCH 004/118] Add Provides: shadow The upstream source tarball is actually called 'shadow' rather than 'shadow-utils'. Add a compat provides for the former. --- shadow-utils.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/shadow-utils.spec b/shadow-utils.spec index c8c4d2c..fbfe028 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -68,6 +68,7 @@ BuildRequires: /usr/bin/xsltproc, /usr/bin/itstool Requires: libselinux >= 1.25.2-1 Requires: audit-libs >= 1.6.5 Requires: setup +Provides: shadow = %{epoch}:%{version}-%{release} %description The shadow-utils package includes the necessary programs for From f527cc2a1b6702bffadd331a1604cf296fa78c71 Mon Sep 17 00:00:00 2001 From: ipedrosa Date: Mon, 9 Nov 2020 10:53:20 +0100 Subject: [PATCH 005/118] commonio: force lock file sync (#1862056) --- ...-4.8.1-commonio-force-lock-file-sync.patch | 39 +++++++++++++++++++ shadow-utils.spec | 12 +++++- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 shadow-4.8.1-commonio-force-lock-file-sync.patch diff --git a/shadow-4.8.1-commonio-force-lock-file-sync.patch b/shadow-4.8.1-commonio-force-lock-file-sync.patch new file mode 100644 index 0000000..5ca7b53 --- /dev/null +++ b/shadow-4.8.1-commonio-force-lock-file-sync.patch @@ -0,0 +1,39 @@ +From fb0f702cbf958a5ee9097c1611212c9880b347ce Mon Sep 17 00:00:00 2001 +From: ikerexxe +Date: Mon, 2 Nov 2020 17:08:55 +0100 +Subject: [PATCH] commonio: force lock file sync + +lib/commonio.c: after writing to the lock file, force a file sync to +the storage system. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1862056 +--- + lib/commonio.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/lib/commonio.c b/lib/commonio.c +index 16fa7e75..c5b3d104 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -157,7 +157,17 @@ static int do_lock_file (const char *file, const char *lock, bool log) + if (write (fd, buf, (size_t) len) != len) { + if (log) { + (void) fprintf (stderr, +- "%s: %s: %s\n", ++ "%s: %s file write error: %s\n", ++ Prog, file, strerror (errno)); ++ } ++ (void) close (fd); ++ unlink (file); ++ return 0; ++ } ++ if (fdatasync (fd) == -1) { ++ if (log) { ++ (void) fprintf (stderr, ++ "%s: %s file sync error: %s\n", + Prog, file, strerror (errno)); + } + (void) close (fd); +-- +2.26.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index fbfe028..845b1f5 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.8.1 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -53,8 +53,11 @@ Patch40: shadow-4.8-ignore-login-prompt.patch Patch42: shadow-4.8-useradd-selinux-mail.patch # Clarify useradd man regarding "-d" parameter - already upstreamed Patch43: shadow-4.8.1-useradd-man-clarification.patch -# Upstreamed +# https://github.com/shadow-maint/shadow/commit/140510de9de4771feb3af1d859c09604043a4c9b +# https://github.com/shadow-maint/shadow/commit/8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 Patch44: shadow-4.8.1-check-local-groups.patch +# https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 +Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch License: BSD and GPLv2+ BuildRequires: gcc @@ -106,6 +109,7 @@ are used for managing group accounts. %patch42 -p1 -b .useradd-selinux-mail %patch43 -p1 -b .useradd-man-clarification %patch44 -p1 -b .check-local-groups +%patch45 -p1 -b .commonio-force-lock-file-sync iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -261,6 +265,10 @@ done %{_mandir}/man8/vigr.8* %changelog +* Mon Nov 16 2020 Iker Pedrosa - 2:4.8.1-5 +- commonio: force lock file sync (#1862056) +- spec: add Provides keyword + * Wed Jul 29 2020 Fedora Release Engineering - 2:4.8.1-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild From 7abff5646c8f0d1b65db0e953247ccb15b2b42ce Mon Sep 17 00:00:00 2001 From: Robert Scheck Date: Thu, 24 Dec 2020 21:10:44 +0000 Subject: [PATCH 006/118] Spec file cleanup --- shadow-utils.spec | 108 +++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 9c45824..279be00 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -3,7 +3,7 @@ Name: shadow-utils Version: 4.8.1 Release: 6%{?dist} Epoch: 2 -URL: http://pkg-shadow.alioth.debian.org/ +URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz Source1: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz.asc Source2: shadow-utils.useradd @@ -144,66 +144,65 @@ autoreconf %make_build %install -rm -rf $RPM_BUILD_ROOT -%make_install gnulocaledir=$RPM_BUILD_ROOT/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs -install -d -m 755 $RPM_BUILD_ROOT/%{_sysconfdir}/default -install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/%{_sysconfdir}/login.defs -install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd +%make_install gnulocaledir=$RPM_BUILD_ROOT%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs +install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/default +install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/login.defs +install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/default/useradd ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser -ln -s useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8 -for subdir in $RPM_BUILD_ROOT/%{_mandir}/{??,??_??,??_??.*}/man* ; do +ln -s useradd.8 $RPM_BUILD_ROOT%{_mandir}/man8/adduser.8 +for subdir in $RPM_BUILD_ROOT%{_mandir}/{??,??_??,??_??.*}/man* ; do test -d $subdir && test -e $subdir/useradd.8 && echo ".so man8/useradd.8" > $subdir/adduser.8 done # Remove binaries we don't use. -rm $RPM_BUILD_ROOT/%{_bindir}/chfn -rm $RPM_BUILD_ROOT/%{_bindir}/chsh -rm $RPM_BUILD_ROOT/%{_bindir}/expiry -rm $RPM_BUILD_ROOT/%{_bindir}/groups -rm $RPM_BUILD_ROOT/%{_bindir}/login -rm $RPM_BUILD_ROOT/%{_bindir}/passwd -rm $RPM_BUILD_ROOT/%{_bindir}/su -rm $RPM_BUILD_ROOT/%{_bindir}/faillog -rm $RPM_BUILD_ROOT/%{_sysconfdir}/login.access -rm $RPM_BUILD_ROOT/%{_sysconfdir}/limits -rm $RPM_BUILD_ROOT/%{_sbindir}/logoutd -rm $RPM_BUILD_ROOT/%{_sbindir}/nologin -rm $RPM_BUILD_ROOT/%{_mandir}/man1/chfn.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/chfn.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/chsh.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/chsh.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/expiry.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/expiry.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/groups.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/groups.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/login.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/login.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/passwd.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/passwd.* -rm $RPM_BUILD_ROOT/%{_mandir}/man1/su.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man1/su.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/limits.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/limits.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/login.access.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/login.access.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/passwd.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/passwd.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/porttime.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/porttime.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/suauth.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/suauth.* -rm $RPM_BUILD_ROOT/%{_mandir}/man8/logoutd.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/logoutd.* -rm $RPM_BUILD_ROOT/%{_mandir}/man8/nologin.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/nologin.* -rm $RPM_BUILD_ROOT/%{_mandir}/man3/getspnam.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man3/getspnam.* -rm $RPM_BUILD_ROOT/%{_mandir}/man5/faillog.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man5/faillog.* -rm $RPM_BUILD_ROOT/%{_mandir}/man8/faillog.* -rm $RPM_BUILD_ROOT/%{_mandir}/*/man8/faillog.* +rm $RPM_BUILD_ROOT%{_bindir}/chfn +rm $RPM_BUILD_ROOT%{_bindir}/chsh +rm $RPM_BUILD_ROOT%{_bindir}/expiry +rm $RPM_BUILD_ROOT%{_bindir}/groups +rm $RPM_BUILD_ROOT%{_bindir}/login +rm $RPM_BUILD_ROOT%{_bindir}/passwd +rm $RPM_BUILD_ROOT%{_bindir}/su +rm $RPM_BUILD_ROOT%{_bindir}/faillog +rm $RPM_BUILD_ROOT%{_sysconfdir}/login.access +rm $RPM_BUILD_ROOT%{_sysconfdir}/limits +rm $RPM_BUILD_ROOT%{_sbindir}/logoutd +rm $RPM_BUILD_ROOT%{_sbindir}/nologin +rm $RPM_BUILD_ROOT%{_mandir}/man1/chfn.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chfn.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/chsh.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chsh.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/expiry.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/expiry.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/groups.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/groups.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/login.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/passwd.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/passwd.* +rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/limits.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/limits.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/login.access.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/login.access.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/passwd.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/passwd.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/porttime.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/porttime.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/suauth.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/suauth.* +rm $RPM_BUILD_ROOT%{_mandir}/man8/logoutd.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man8/logoutd.* +rm $RPM_BUILD_ROOT%{_mandir}/man8/nologin.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man8/nologin.* +rm $RPM_BUILD_ROOT%{_mandir}/man3/getspnam.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man3/getspnam.* +rm $RPM_BUILD_ROOT%{_mandir}/man5/faillog.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man5/faillog.* +rm $RPM_BUILD_ROOT%{_mandir}/man8/faillog.* +rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete %find_lang shadow @@ -217,7 +216,6 @@ done %files -f shadow.lang %doc NEWS doc/HOWTO README -%{!?_licensedir:%global license %%doc} %license gpl-2.0.txt shadow-bsd.txt %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/login.defs %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/default/useradd From cc2729413813140e9b1abb153976bc618abf36a6 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 8 Jan 2021 21:26:08 +0000 Subject: [PATCH 007/118] Add BuildRequires: make https://fedoraproject.org/wiki/Changes/Remove_make_from_BuildRoot --- shadow-utils.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/shadow-utils.spec b/shadow-utils.spec index 279be00..5f23763 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -60,6 +60,7 @@ Patch44: shadow-4.8.1-check-local-groups.patch Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch License: BSD and GPLv2+ +BuildRequires: make BuildRequires: gcc BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: audit-libs-devel >= 1.6.5 From 4e14ecca65608158ec9eb2418361b1c5dbb61a8d Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 27 Jan 2021 20:17:47 +0000 Subject: [PATCH 008/118] - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 5f23763..0d25632 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.8.1 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -264,6 +264,9 @@ done %{_mandir}/man8/vigr.8* %changelog +* Wed Jan 27 2021 Fedora Release Engineering - 2:4.8.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + * Mon Nov 9 2020 Iker Pedrosa - 2:4.8.1-6 - commonio: force lock file sync (#1862056) From 3e39e1d4e3a095e4aaa1395b4e393cfbd7372755 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 29 Mar 2021 12:29:20 +0200 Subject: [PATCH 009/118] - man: include lastlog file caveat (#951564) - Upstream links to several patches - Spec file cleanup by Robert Scheck - Add BuildRequires: make by Tom Stellard --- ....8.1-man-include-lastlog-file-caveat.patch | 33 +++++++++++++++++++ shadow-utils.spec | 21 +++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 shadow-4.8.1-man-include-lastlog-file-caveat.patch diff --git a/shadow-4.8.1-man-include-lastlog-file-caveat.patch b/shadow-4.8.1-man-include-lastlog-file-caveat.patch new file mode 100644 index 0000000..7be60c5 --- /dev/null +++ b/shadow-4.8.1-man-include-lastlog-file-caveat.patch @@ -0,0 +1,33 @@ +From df6ec1d1693c8c80c323b40d6fc82bb549363db3 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 29 Mar 2021 05:26:28 +0200 +Subject: [PATCH] man: include lastlog file caveat (#313) + +man/lastlog.8.xml: add another point to the caveats section regarding +the handling of the lastlog file by external tools. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=951564 +--- + man/lastlog.8.xml | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml +index fc096c8f..7e68282f 100644 +--- a/man/lastlog.8.xml ++++ b/man/lastlog.8.xml +@@ -233,5 +233,12 @@ + is no entries for users with UID between 170 and 800 lastlog will appear + to hang as it processes entries with UIDs 171-799). + ++ ++ Having high UIDs can create problems when handling the ++ /var/log/lastlog with external tools. Although the ++ actual file is sparse and does not use too much space, certain ++ applications are not designed to identify sparse files by default and may ++ require a specific option to handle them. ++ + + +-- +2.30.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 0d25632..8d1f5ea 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.8.1 -Release: 7%{?dist} +Release: 8%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -15,17 +15,19 @@ Source6: shadow-utils.HOME_MODE.xml Patch0: shadow-4.6-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable Patch1: shadow-4.8-goodname.patch -# Docfix for newusers - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/7384865775b0203b9cf5337a047744f0a4555868 Patch2: shadow-4.1.5.1-info-parent-dir.patch # Misc SElinux related changes - upstreamability unknown Patch6: shadow-4.8-selinux.patch -# Syslog message change - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/a8361e741040cd926c9c93aac89820052531b1a3 Patch11: shadow-4.1.5.1-logmsg.patch # SElinux related - upstreamability unknown Patch14: shadow-4.1.5.1-default-range.patch -# Misc manual page changes - only some of them could be upstreamed +# Misc manual page changes +# https://github.com/shadow-maint/shadow/commit/c0818ab01d1896784245eedec9495e1e6e0260af +# Changes in man/groupmems.8.xml, man/ja/man5/login.defs.5 and man/login.defs.5.xml not upstreamed Patch15: shadow-4.8.1-manfix.patch -# Userdel usage message change - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/f4cbf38ad7801bab6fae50e9b5a2effc3c48a1ea Patch17: shadow-4.1.5.1-userdel-helpfix.patch # Date parsing improvement - could be upstreamed Patch19: shadow-4.2.1-date-parsing.patch @@ -58,6 +60,8 @@ Patch43: shadow-4.8.1-useradd-man-clarification.patch Patch44: shadow-4.8.1-check-local-groups.patch # https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch +# https://github.com/shadow-maint/shadow/commit/df6ec1d1693c8c80c323b40d6fc82bb549363db3 +Patch46: shadow-4.8.1-man-include-lastlog-file-caveat.patch License: BSD and GPLv2+ BuildRequires: make @@ -111,6 +115,7 @@ are used for managing group accounts. %patch43 -p1 -b .useradd-man-clarification %patch44 -p1 -b .check-local-groups %patch45 -p1 -b .commonio-force-lock-file-sync +%patch46 -p1 -b .man-include-lastlog-file-caveat iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -264,6 +269,12 @@ done %{_mandir}/man8/vigr.8* %changelog +* Mon Mar 29 2021 Iker Pedrosa - 2:4.8.1-8 +- man: include lastlog file caveat (#951564) +- Upstream links to several patches +- Spec file cleanup by Robert Scheck +- Add BuildRequires: make by Tom Stellard + * Wed Jan 27 2021 Fedora Release Engineering - 2:4.8.1-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild From 5292920d9b991fcfc7edb4dd7d427a8ae93ef092 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 16 Apr 2021 16:18:35 +0200 Subject: [PATCH 010/118] - libsubid: creation and nsswitch support - Creation of subid and subid-devel subpackages --- shadow-4.8.1-libsubid_creation.patch | 1522 +++++++++++++ shadow-4.8.1-libsubid_nsswitch_support.patch | 2107 ++++++++++++++++++ shadow-utils.spec | 56 +- 3 files changed, 3683 insertions(+), 2 deletions(-) create mode 100644 shadow-4.8.1-libsubid_creation.patch create mode 100644 shadow-4.8.1-libsubid_nsswitch_support.patch diff --git a/shadow-4.8.1-libsubid_creation.patch b/shadow-4.8.1-libsubid_creation.patch new file mode 100644 index 0000000..072ed2e --- /dev/null +++ b/shadow-4.8.1-libsubid_creation.patch @@ -0,0 +1,1522 @@ +From 0a7888b1fad613a052b988b01a71933b67296e68 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sat, 18 Apr 2020 18:03:54 -0500 +Subject: [PATCH] Create a new libsubid + +Closes #154 + +Currently this has three functions: one which returns the +list of subuid ranges for a user, one returning the subgids, +and one which frees the ranges lists. + +I might be mistaken about what -disable-man means; some of +the code suggests it means just don't re-generate them, but +not totally ignore them. But that doesn't seem to really work, +so let's just ignore man/ when -disable-man. + +Remove --disable-shared. I'm not sure why it was there, but it stems +from long, long ago, and I suspect it comes from some ancient +toolchain bug. + +Create a tests/run_some, a shorter version of run_all. I'll +slowly add tests to this as I verify they work, then I can +work on fixing the once which don't. + +Also, don't touch man/ if not -enable-man. + +Changelog: + Apr 22: change the subid list api as recomended by Dan Walsh. + Apr 23: implement get_subid_owner + Apr 24: implement range add/release + Apr 25: finish tests and rebase + May 10: make @owner const + +Signed-off-by: Serge Hallyn +--- + Makefile.am | 13 +- + configure.ac | 3 +- + lib/subordinateio.c | 204 +++++++++++++++- + lib/subordinateio.h | 7 + + libsubid/Makefile.am | 25 ++ + libsubid/api.c | 231 ++++++++++++++++++ + libsubid/api.h | 17 ++ + libsubid/subid.h | 17 ++ + src/Makefile.am | 60 +++++ + src/free_subid_range.c | 50 ++++ + src/get_subid_owners.c | 40 +++ + src/list_subid_ranges.c | 41 ++++ + src/new_subid_range.c | 57 +++++ + tests/libsubid/01_list_ranges/config.txt | 0 + .../libsubid/01_list_ranges/config/etc/subgid | 2 + + .../libsubid/01_list_ranges/config/etc/subuid | 3 + + .../libsubid/01_list_ranges/list_ranges.test | 38 +++ + tests/libsubid/02_get_subid_owners/config.txt | 0 + .../02_get_subid_owners/config/etc/passwd | 20 ++ + .../02_get_subid_owners/config/etc/subgid | 2 + + .../02_get_subid_owners/config/etc/subuid | 4 + + .../02_get_subid_owners/get_subid_owners.test | 52 ++++ + .../03_add_remove/add_remove_subids.test | 59 +++++ + tests/libsubid/03_add_remove/config.txt | 0 + .../libsubid/03_add_remove/config/etc/passwd | 20 ++ + .../libsubid/03_add_remove/config/etc/subgid | 2 + + .../libsubid/03_add_remove/config/etc/subuid | 1 + + tests/run_some | 136 +++++++++++ + 31 files changed, 1105 insertions(+), 17 deletions(-) + create mode 100644 libsubid/Makefile.am + create mode 100644 libsubid/api.c + create mode 100644 libsubid/api.h + create mode 100644 libsubid/subid.h + create mode 100644 src/free_subid_range.c + create mode 100644 src/get_subid_owners.c + create mode 100644 src/list_subid_ranges.c + create mode 100644 src/new_subid_range.c + create mode 100644 tests/libsubid/01_list_ranges/config.txt + create mode 100644 tests/libsubid/01_list_ranges/config/etc/subgid + create mode 100644 tests/libsubid/01_list_ranges/config/etc/subuid + create mode 100755 tests/libsubid/01_list_ranges/list_ranges.test + create mode 100644 tests/libsubid/02_get_subid_owners/config.txt + create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/passwd + create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/subgid + create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/subuid + create mode 100755 tests/libsubid/02_get_subid_owners/get_subid_owners.test + create mode 100755 tests/libsubid/03_add_remove/add_remove_subids.test + create mode 100644 tests/libsubid/03_add_remove/config.txt + create mode 100644 tests/libsubid/03_add_remove/config/etc/passwd + create mode 100644 tests/libsubid/03_add_remove/config/etc/subgid + create mode 100644 tests/libsubid/03_add_remove/config/etc/subuid + create mode 100755 tests/run_some + +diff --git a/Makefile.am b/Makefile.am +index 8851f5d6..b6456cf9 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -2,5 +2,14 @@ + + EXTRA_DIST = NEWS README TODO shadow.spec.in + +-SUBDIRS = po man libmisc lib src \ +- contrib doc etc ++SUBDIRS = libmisc lib ++ ++if ENABLE_SUBIDS ++SUBDIRS += libsubid ++endif ++ ++SUBDIRS += src po contrib doc etc ++ ++if ENABLE_REGENERATE_MAN ++SUBDIRS += man ++endif +diff --git a/configure.ac b/configure.ac +index b8bc2b7a..b766eff0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -22,8 +22,8 @@ test "$prefix" = "/usr" && exec_prefix="" + + AC_GNU_SOURCE + +-AM_DISABLE_SHARED + AM_ENABLE_STATIC ++AM_ENABLE_SHARED + + AM_MAINTAINER_MODE + +@@ -725,6 +725,7 @@ AC_CONFIG_FILES([ + man/zh_TW/Makefile + libmisc/Makefile + lib/Makefile ++ libsubid/Makefile + src/Makefile + contrib/Makefile + etc/Makefile +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 0d89a64e..67202c98 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -13,14 +13,7 @@ + #include "subordinateio.h" + #include + #include +- +-struct subordinate_range { +- const char *owner; +- unsigned long start; +- unsigned long count; +-}; +- +-#define NFIELDS 3 ++#include + + /* + * subordinate_dup: create a duplicate range +@@ -78,7 +71,7 @@ static void *subordinate_parse (const char *line) + static char rangebuf[1024]; + int i; + char *cp; +- char *fields[NFIELDS]; ++ char *fields[SUBID_NFIELDS]; + + /* + * Copy the string to a temporary buffer so the substrings can +@@ -93,7 +86,7 @@ static void *subordinate_parse (const char *line) + * field. The fields are converted into NUL terminated strings. + */ + +- for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) { ++ for (cp = rangebuf, i = 0; (i < SUBID_NFIELDS) && (NULL != cp); i++) { + fields[i] = cp; + while (('\0' != *cp) && (':' != *cp)) { + cp++; +@@ -108,10 +101,10 @@ static void *subordinate_parse (const char *line) + } + + /* +- * There must be exactly NFIELDS colon separated fields or ++ * There must be exactly SUBID_NFIELDS colon separated fields or + * the entry is invalid. Also, fields must be non-blank. + */ +- if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0') ++ if (i != SUBID_NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0') + return NULL; + range.owner = fields[0]; + if (getulong (fields[1], &range.start) == 0) +@@ -314,6 +307,39 @@ static bool have_range(struct commonio_db *db, + return false; + } + ++static bool append_range(struct subordinate_range ***ranges, const struct subordinate_range *new, int n) ++{ ++ struct subordinate_range *tmp; ++ if (!*ranges) { ++ *ranges = malloc(2 * sizeof(struct subordinate_range **)); ++ if (!*ranges) ++ return false; ++ } else { ++ struct subordinate_range **new; ++ new = realloc(*ranges, (n + 2) * (sizeof(struct subordinate_range **))); ++ if (!new) ++ return false; ++ *ranges = new; ++ } ++ (*ranges)[n] = (*ranges)[n+1] = NULL; ++ tmp = subordinate_dup(new); ++ if (!tmp) ++ return false; ++ (*ranges)[n] = tmp; ++ return true; ++} ++ ++void free_subordinate_ranges(struct subordinate_range **ranges) ++{ ++ int i; ++ ++ if (!ranges) ++ return; ++ for (i = 0; ranges[i]; i++) ++ subordinate_free(ranges[i]); ++ free(ranges); ++} ++ + /* + * subordinate_range_cmp: compare uid ranges + * +@@ -692,6 +718,160 @@ gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) + start = find_free_range (&subordinate_gid_db, min, max, count); + return start == ULONG_MAX ? (gid_t) -1 : start; + } ++ ++/* ++ struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) ++ * ++ * @owner: username ++ * @id_type: UID or GUID ++ * ++ * Returns the subuid or subgid ranges which are owned by the specified ++ * user. Username may be a username or a string representation of a ++ * UID number. If id_type is UID, then subuids are returned, else ++ * subgids are returned. If there is an error, < 0 is returned. ++ * ++ * The caller must free the subordinate range list. ++ */ ++struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) ++{ ++ // TODO - need to handle owner being either uid or username ++ const struct subordinate_range *range; ++ struct subordinate_range **ranges = NULL; ++ struct commonio_db *db; ++ int size = 0; ++ ++ if (id_type == ID_TYPE_UID) ++ db = &subordinate_uid_db; ++ else ++ db = &subordinate_gid_db; ++ ++ commonio_rewind(db); ++ while ((range = commonio_next(db)) != NULL) { ++ if (0 == strcmp(range->owner, owner)) { ++ if (!append_range(&ranges, range, size++)) { ++ free_subordinate_ranges(ranges); ++ return NULL; ++ } ++ } ++ } ++ ++ return ranges; ++} ++ ++static bool all_digits(const char *str) ++{ ++ int i; ++ ++ for (i = 0; str[i] != '\0'; i++) ++ if (!isdigit(str[i])) ++ return false; ++ return true; ++} ++ ++static int append_uids(uid_t **uids, const char *owner, int n) ++{ ++ uid_t owner_uid; ++ uid_t *ret; ++ int i; ++ ++ if (all_digits(owner)) { ++ i = sscanf(owner, "%d", &owner_uid); ++ if (i != 1) { ++ // should not happen ++ free(*uids); ++ *uids = NULL; ++ return -1; ++ } ++ } else { ++ struct passwd *pwd = getpwnam(owner); ++ if (NULL == pwd) { ++ /* Username not defined in /etc/passwd, or error occured during lookup */ ++ free(*uids); ++ *uids = NULL; ++ return -1; ++ } ++ owner_uid = pwd->pw_uid; ++ } ++ ++ for (i = 0; i < n; i++) { ++ if (owner_uid == (*uids)[i]) ++ return n; ++ } ++ ++ ret = realloc(*uids, (n + 1) * sizeof(uid_t)); ++ if (!ret) { ++ free(*uids); ++ return -1; ++ } ++ ret[n] = owner_uid; ++ *uids = ret; ++ return n+1; ++} ++ ++int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) ++{ ++ const struct subordinate_range *range; ++ struct commonio_db *db; ++ int n = 0; ++ ++ *uids = NULL; ++ if (id_type == ID_TYPE_UID) ++ db = &subordinate_uid_db; ++ else ++ db = &subordinate_gid_db; ++ ++ commonio_rewind(db); ++ while ((range = commonio_next(db)) != NULL) { ++ if (id >= range->start && id < range->start + range-> count) { ++ n = append_uids(uids, range->owner, n); ++ if (n < 0) ++ break; ++ } ++ } ++ ++ return n; ++} ++ ++bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse) ++{ ++ struct commonio_db *db; ++ const struct subordinate_range *r; ++ ++ if (id_type == ID_TYPE_UID) ++ db = &subordinate_uid_db; ++ else ++ db = &subordinate_gid_db; ++ commonio_rewind(db); ++ if (reuse) { ++ while ((r = commonio_next(db)) != NULL) { ++ // TODO account for username vs uid_t ++ if (0 != strcmp(r->owner, range->owner)) ++ continue; ++ if (r->count >= range->count) { ++ range->count = r->count; ++ range->start = r->start; ++ return true; ++ } ++ } ++ } ++ ++ range->start = find_free_range(db, range->start, ULONG_MAX, range->count); ++ if (range->start == ULONG_MAX) ++ return false; ++ ++ return add_range(db, range->owner, range->start, range->count) == 1; ++} ++ ++bool release_subid_range(struct subordinate_range *range, enum subid_type id_type) ++{ ++ struct commonio_db *db; ++ if (id_type == ID_TYPE_UID) ++ db = &subordinate_uid_db; ++ else ++ db = &subordinate_gid_db; ++ return remove_range(db, range->owner, range->start, range->count) == 1; ++} ++ + #else /* !ENABLE_SUBIDS */ + extern int errno; /* warning: ANSI C forbids an empty source file */ + #endif /* !ENABLE_SUBIDS */ +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index a21d72b8..13a21341 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -11,6 +11,8 @@ + + #include + ++#include "../libsubid/subid.h" ++ + extern int sub_uid_close(void); + extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); + extern bool sub_uid_file_present (void); +@@ -23,6 +25,11 @@ extern int sub_uid_unlock (void); + extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); + extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); + extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); ++extern struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type); ++extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); ++extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); ++extern int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type); ++extern void free_subordinate_ranges(struct subordinate_range **ranges); + + extern int sub_gid_close(void); + extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); +diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am +new file mode 100644 +index 00000000..bdbc52c3 +--- /dev/null ++++ b/libsubid/Makefile.am +@@ -0,0 +1,25 @@ ++lib_LTLIBRARIES = libsubid.la ++libsubid_la_LDFLAGS = -Wl,-soname,libsubid.so.@LIBSUBID_ABI@ \ ++ -shared -version-info @LIBSUBID_ABI_MAJOR@ ++libsubid_la_SOURCES = api.c ++ ++MISCLIBS = \ ++ $(LIBAUDIT) \ ++ $(LIBSELINUX) \ ++ $(LIBSEMANAGE) \ ++ $(LIBCRYPT_NOPAM) \ ++ $(LIBSKEY) \ ++ $(LIBMD) \ ++ $(LIBECONF) \ ++ $(LIBCRYPT) \ ++ $(LIBTCB) ++ ++libsubid_la_LIBADD = \ ++ $(top_srcdir)/lib/libshadow.la \ ++ $(top_srcdir)/libmisc/libmisc.a \ ++ $(MISCLIBS) ++ ++AM_CPPFLAGS = \ ++ -I${top_srcdir}/lib \ ++ -I${top_srcdir}/libmisc \ ++ -DLOCALEDIR=\"$(datadir)/locale\" +diff --git a/libsubid/api.c b/libsubid/api.c +new file mode 100644 +index 00000000..91d73bed +--- /dev/null ++++ b/libsubid/api.c +@@ -0,0 +1,231 @@ ++/* ++ * Copyright (c) 2020 Serge Hallyn ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the copyright holders or contributors may not be used to ++ * endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "subordinateio.h" ++#include "idmapping.h" ++#include "api.h" ++ ++static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type) ++{ ++ struct subordinate_range **ranges = NULL; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_open(O_RDONLY)) { ++ return NULL; ++ } ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_open(O_RDONLY)) { ++ return NULL; ++ } ++ break; ++ default: ++ return NULL; ++ } ++ ++ ranges = list_owner_ranges(owner, id_type); ++ ++ if (id_type == ID_TYPE_UID) ++ sub_uid_close(); ++ else ++ sub_gid_close(); ++ ++ return ranges; ++} ++ ++struct subordinate_range **get_subuid_ranges(const char *owner) ++{ ++ return get_subid_ranges(owner, ID_TYPE_UID); ++} ++ ++struct subordinate_range **get_subgid_ranges(const char *owner) ++{ ++ return get_subid_ranges(owner, ID_TYPE_GID); ++} ++ ++void subid_free_ranges(struct subordinate_range **ranges) ++{ ++ return free_subordinate_ranges(ranges); ++} ++ ++int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type) ++{ ++ int ret = -1; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_open(O_RDONLY)) { ++ return -1; ++ } ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_open(O_RDONLY)) { ++ return -1; ++ } ++ break; ++ default: ++ return -1; ++ } ++ ++ ret = find_subid_owners(id, owner, id_type); ++ ++ if (id_type == ID_TYPE_UID) ++ sub_uid_close(); ++ else ++ sub_gid_close(); ++ ++ return ret; ++} ++ ++int get_subuid_owners(uid_t uid, uid_t **owner) ++{ ++ return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID); ++} ++ ++int get_subgid_owners(gid_t gid, uid_t **owner) ++{ ++ return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID); ++} ++ ++bool grant_subid_range(struct subordinate_range *range, bool reuse, ++ enum subid_type id_type) ++{ ++ bool ret; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_lock()) { ++ printf("Failed loging subuids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_uid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subuids (errno %d)\n", errno); ++ sub_uid_unlock(); ++ return false; ++ } ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_lock()) { ++ printf("Failed loging subgids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_gid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subgids (errno %d)\n", errno); ++ sub_gid_unlock(); ++ return false; ++ } ++ break; ++ default: ++ return false; ++ } ++ ++ ret = new_subid_range(range, id_type, reuse); ++ ++ if (id_type == ID_TYPE_UID) { ++ sub_uid_close(); ++ sub_uid_unlock(); ++ } else { ++ sub_gid_close(); ++ sub_gid_unlock(); ++ } ++ ++ return ret; ++} ++ ++bool grant_subuid_range(struct subordinate_range *range, bool reuse) ++{ ++ return grant_subid_range(range, reuse, ID_TYPE_UID); ++} ++ ++bool grant_subgid_range(struct subordinate_range *range, bool reuse) ++{ ++ return grant_subid_range(range, reuse, ID_TYPE_GID); ++} ++ ++bool free_subid_range(struct subordinate_range *range, enum subid_type id_type) ++{ ++ bool ret; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_lock()) { ++ printf("Failed loging subuids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_uid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subuids (errno %d)\n", errno); ++ sub_uid_unlock(); ++ return false; ++ } ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_lock()) { ++ printf("Failed loging subgids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_gid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subgids (errno %d)\n", errno); ++ sub_gid_unlock(); ++ return false; ++ } ++ break; ++ default: ++ return false; ++ } ++ ++ ret = release_subid_range(range, id_type); ++ ++ if (id_type == ID_TYPE_UID) { ++ sub_uid_close(); ++ sub_uid_unlock(); ++ } else { ++ sub_gid_close(); ++ sub_gid_unlock(); ++ } ++ ++ return ret; ++} ++ ++bool free_subuid_range(struct subordinate_range *range) ++{ ++ return free_subid_range(range, ID_TYPE_UID); ++} ++ ++bool free_subgid_range(struct subordinate_range *range) ++{ ++ return free_subid_range(range, ID_TYPE_GID); ++} +diff --git a/libsubid/api.h b/libsubid/api.h +new file mode 100644 +index 00000000..f65e3ec9 +--- /dev/null ++++ b/libsubid/api.h +@@ -0,0 +1,17 @@ ++#include "subid.h" ++#include ++ ++struct subordinate_range **get_subuid_ranges(const char *owner); ++struct subordinate_range **get_subgid_ranges(const char *owner); ++void subid_free_ranges(struct subordinate_range **ranges); ++ ++int get_subuid_owners(uid_t uid, uid_t **owner); ++int get_subgid_owners(uid_t uid, uid_t **owner); ++ ++/* range should be pre-allocated with owner and count filled in, start is ++ * ignored, can be 0 */ ++bool grant_subuid_range(struct subordinate_range *range, bool reuse); ++bool grant_subgid_range(struct subordinate_range *range, bool reuse); ++ ++bool free_subuid_range(struct subordinate_range *range); ++bool free_subgid_range(struct subordinate_range *range); +diff --git a/libsubid/subid.h b/libsubid/subid.h +new file mode 100644 +index 00000000..ba9a2f6f +--- /dev/null ++++ b/libsubid/subid.h +@@ -0,0 +1,17 @@ ++#include ++ ++#ifndef SUBID_RANGE_DEFINED ++#define SUBID_RANGE_DEFINED 1 ++struct subordinate_range { ++ const char *owner; ++ unsigned long start; ++ unsigned long count; ++}; ++ ++enum subid_type { ++ ID_TYPE_UID = 1, ++ ID_TYPE_GID = 2 ++}; ++ ++#define SUBID_NFIELDS 3 ++#endif +diff --git a/src/Makefile.am b/src/Makefile.am +index f175928a..8499ce08 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -156,4 +156,64 @@ if FCAPS + setcap cap_setuid+ep $(DESTDIR)$(ubindir)/newuidmap + setcap cap_setgid+ep $(DESTDIR)$(ubindir)/newgidmap + endif ++ ++noinst_PROGRAMS += list_subid_ranges \ ++ get_subid_owners \ ++ new_subid_range \ ++ free_subid_range ++ ++MISCLIBS = \ ++ $(LIBAUDIT) \ ++ $(LIBSELINUX) \ ++ $(LIBSEMANAGE) \ ++ $(LIBCRYPT_NOPAM) \ ++ $(LIBSKEY) \ ++ $(LIBMD) \ ++ $(LIBECONF) \ ++ $(LIBCRYPT) \ ++ $(LIBTCB) ++ ++list_subid_ranges_LDADD = \ ++ $(top_builddir)/lib/libshadow.la \ ++ $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libsubid/libsubid.la \ ++ $(MISCLIBS) ++ ++list_subid_ranges_CPPFLAGS = \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/libmisc \ ++ -I$(top_srcdir)/libsubid ++ ++get_subid_owners_LDADD = \ ++ $(top_builddir)/lib/libshadow.la \ ++ $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libsubid/libsubid.la \ ++ $(MISCLIBS) ++ ++get_subid_owners_CPPFLAGS = \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/libmisc \ ++ -I$(top_srcdir)/libsubid ++ ++new_subid_range_CPPFLAGS = \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/libmisc \ ++ -I$(top_srcdir)/libsubid ++ ++new_subid_range_LDADD = \ ++ $(top_builddir)/lib/libshadow.la \ ++ $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libsubid/libsubid.la \ ++ $(MISCLIBS) ++ ++free_subid_range_CPPFLAGS = \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/libmisc \ ++ -I$(top_srcdir)/libsubid ++ ++free_subid_range_LDADD = \ ++ $(top_builddir)/lib/libshadow.la \ ++ $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libsubid/libsubid.la \ ++ $(MISCLIBS) + endif +diff --git a/src/free_subid_range.c b/src/free_subid_range.c +new file mode 100644 +index 00000000..36858875 +--- /dev/null ++++ b/src/free_subid_range.c +@@ -0,0 +1,50 @@ ++#include ++#include ++#include "api.h" ++#include "stdlib.h" ++#include "prototypes.h" ++ ++/* Test program for the subid freeing routine */ ++ ++const char *Prog; ++ ++void usage(void) ++{ ++ fprintf(stderr, "Usage: %s [-g] user start count\n", Prog); ++ fprintf(stderr, " Release a user's subuid (or with -g, subgid) range\n"); ++ exit(EXIT_FAILURE); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int c; ++ bool ok; ++ struct subordinate_range range; ++ bool group = false; // get subuids by default ++ ++ Prog = Basename (argv[0]); ++ while ((c = getopt(argc, argv, "g")) != EOF) { ++ switch(c) { ++ case 'g': group = true; break; ++ default: usage(); ++ } ++ } ++ argv = &argv[optind]; ++ argc = argc - optind; ++ if (argc < 3) ++ usage(); ++ range.owner = argv[0]; ++ range.start = atoi(argv[1]); ++ range.count = atoi(argv[2]); ++ if (group) ++ ok = free_subgid_range(&range); ++ else ++ ok = free_subuid_range(&range); ++ ++ if (!ok) { ++ fprintf(stderr, "Failed freeing id range\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++ return 0; ++} +diff --git a/src/get_subid_owners.c b/src/get_subid_owners.c +new file mode 100644 +index 00000000..a4385540 +--- /dev/null ++++ b/src/get_subid_owners.c +@@ -0,0 +1,40 @@ ++#include ++#include "api.h" ++#include "stdlib.h" ++#include "prototypes.h" ++ ++const char *Prog; ++ ++void usage(void) ++{ ++ fprintf(stderr, "Usage: [-g] %s subuid\n", Prog); ++ fprintf(stderr, " list uids who own the given subuid\n"); ++ fprintf(stderr, " pass -g to query a subgid\n"); ++ exit(EXIT_FAILURE); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int i, n; ++ uid_t *uids; ++ ++ Prog = Basename (argv[0]); ++ if (argc < 2) { ++ usage(); ++ } ++ if (argc == 3 && strcmp(argv[1], "-g") == 0) ++ n = get_subgid_owners(atoi(argv[2]), &uids); ++ else if (argc == 2 && strcmp(argv[1], "-h") == 0) ++ usage(); ++ else ++ n = get_subuid_owners(atoi(argv[1]), &uids); ++ if (n < 0) { ++ fprintf(stderr, "No owners found\n"); ++ exit(1); ++ } ++ for (i = 0; i < n; i++) { ++ printf("%d\n", uids[i]); ++ } ++ free(uids); ++ return 0; ++} +diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c +new file mode 100644 +index 00000000..cdba610e +--- /dev/null ++++ b/src/list_subid_ranges.c +@@ -0,0 +1,41 @@ ++#include ++#include "api.h" ++#include "stdlib.h" ++#include "prototypes.h" ++ ++const char *Prog; ++ ++void usage(void) ++{ ++ fprintf(stderr, "Usage: %s [-g] user\n", Prog); ++ fprintf(stderr, " list subuid ranges for user\n"); ++ fprintf(stderr, " pass -g to list subgid ranges\n"); ++ exit(EXIT_FAILURE); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int i; ++ struct subordinate_range **ranges; ++ ++ Prog = Basename (argv[0]); ++ if (argc < 2) { ++ usage(); ++ } ++ if (argc == 3 && strcmp(argv[1], "-g") == 0) ++ ranges = get_subgid_ranges(argv[2]); ++ else if (argc == 2 && strcmp(argv[1], "-h") == 0) ++ usage(); ++ else ++ ranges = get_subuid_ranges(argv[1]); ++ if (!ranges) { ++ fprintf(stderr, "Error fetching ranges\n"); ++ exit(1); ++ } ++ for (i = 0; ranges[i]; i++) { ++ printf("%d: %s %lu %lu\n", i, ranges[i]->owner, ++ ranges[i]->start, ranges[i]->count); ++ } ++ subid_free_ranges(ranges); ++ return 0; ++} +diff --git a/src/new_subid_range.c b/src/new_subid_range.c +new file mode 100644 +index 00000000..6d7b033b +--- /dev/null ++++ b/src/new_subid_range.c +@@ -0,0 +1,57 @@ ++#include ++#include ++#include "api.h" ++#include "stdlib.h" ++#include "prototypes.h" ++ ++/* Test program for the subid creation routine */ ++ ++const char *Prog; ++ ++void usage(void) ++{ ++ fprintf(stderr, "Usage: %s [-g] [-n] user count\n", Prog); ++ fprintf(stderr, " Find a subuid (or with -g, subgid) range for user\n"); ++ fprintf(stderr, " If -n is given, a new range will be created even if one exists\n"); ++ fprintf(stderr, " count defaults to 65536\n"); ++ exit(EXIT_FAILURE); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int c; ++ struct subordinate_range range; ++ bool makenew = false; // reuse existing by default ++ bool group = false; // get subuids by default ++ bool ok; ++ ++ Prog = Basename (argv[0]); ++ while ((c = getopt(argc, argv, "gn")) != EOF) { ++ switch(c) { ++ case 'n': makenew = true; break; ++ case 'g': group = true; break; ++ default: usage(); ++ } ++ } ++ argv = &argv[optind]; ++ argc = argc - optind; ++ if (argc == 0) ++ usage(); ++ range.owner = argv[0]; ++ range.start = 0; ++ range.count = 65536; ++ if (argc > 1) ++ range.count = atoi(argv[1]); ++ if (group) ++ ok = grant_subgid_range(&range, !makenew); ++ else ++ ok = grant_subuid_range(&range, !makenew); ++ ++ if (!ok) { ++ fprintf(stderr, "Failed creating new id range\n"); ++ exit(EXIT_FAILURE); ++ } ++ printf("Subuid range %lu:%lu\n", range.start, range.count); ++ ++ return 0; ++} +diff --git a/tests/libsubid/01_list_ranges/config.txt b/tests/libsubid/01_list_ranges/config.txt +new file mode 100644 +index 00000000..e69de29b +diff --git a/tests/libsubid/01_list_ranges/config/etc/subgid b/tests/libsubid/01_list_ranges/config/etc/subgid +new file mode 100644 +index 00000000..b9495cfc +--- /dev/null ++++ b/tests/libsubid/01_list_ranges/config/etc/subgid +@@ -0,0 +1,2 @@ ++foo:200000:10000 ++root:500000:1000 +diff --git a/tests/libsubid/01_list_ranges/config/etc/subuid b/tests/libsubid/01_list_ranges/config/etc/subuid +new file mode 100644 +index 00000000..e5c537be +--- /dev/null ++++ b/tests/libsubid/01_list_ranges/config/etc/subuid +@@ -0,0 +1,3 @@ ++foo:300000:10000 ++foo:400000:10000 ++root:500000:1000 +diff --git a/tests/libsubid/01_list_ranges/list_ranges.test b/tests/libsubid/01_list_ranges/list_ranges.test +new file mode 100755 +index 00000000..b131303b +--- /dev/null ++++ b/tests/libsubid/01_list_ranges/list_ranges.test +@@ -0,0 +1,38 @@ ++#!/bin/sh ++ ++set -e ++ ++cd $(dirname $0) ++ ++. ../../common/config.sh ++. ../../common/log.sh ++ ++log_start "$0" "list_ranges shows subid ranges" ++ ++save_config ++ ++# restore the files on exit ++trap 'log_status "$0" "FAILURE"; restore_config' 0 ++ ++change_config ++ ++echo -n "list foo's ranges..." ++${build_path}/src/list_subid_ranges foo > /tmp/subuidlistout ++${build_path}/src/list_subid_ranges -g foo > /tmp/subgidlistout ++echo "OK" ++ ++echo -n "Check the subuid ranges..." ++[ $(wc -l /tmp/subuidlistout | awk '{ print $1 }') -eq 2 ] ++grep "0: foo 300000 10000" /tmp/subuidlistout ++grep "1: foo 400000 10000" /tmp/subuidlistout ++echo "OK" ++ ++echo -n "Check the subgid ranges..." ++[ $(wc -l /tmp/subgidlistout | awk '{ print $1 }') -eq 1 ] ++grep "0: foo 200000 10000" /tmp/subgidlistout ++echo "OK" ++ ++log_status "$0" "SUCCESS" ++restore_config ++trap '' 0 ++ +diff --git a/tests/libsubid/02_get_subid_owners/config.txt b/tests/libsubid/02_get_subid_owners/config.txt +new file mode 100644 +index 00000000..e69de29b +diff --git a/tests/libsubid/02_get_subid_owners/config/etc/passwd b/tests/libsubid/02_get_subid_owners/config/etc/passwd +new file mode 100644 +index 00000000..bf52df00 +--- /dev/null ++++ b/tests/libsubid/02_get_subid_owners/config/etc/passwd +@@ -0,0 +1,20 @@ ++root:x:0:0:root:/root:/bin/bash ++daemon:x:1:1:daemon:/usr/sbin:/bin/sh ++bin:x:2:2:bin:/bin:/bin/sh ++sys:x:3:3:sys:/dev:/bin/sh ++sync:x:4:65534:sync:/bin:/bin/sync ++games:x:5:60:games:/usr/games:/bin/sh ++man:x:6:12:man:/var/cache/man:/bin/sh ++lp:x:7:7:lp:/var/spool/lpd:/bin/sh ++mail:x:8:8:mail:/var/mail:/bin/sh ++news:x:9:9:news:/var/spool/news:/bin/sh ++uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh ++proxy:x:13:13:proxy:/bin:/bin/sh ++www-data:x:33:33:www-data:/var/www:/bin/sh ++backup:x:34:34:backup:/var/backups:/bin/sh ++list:x:38:38:Mailing List Manager:/var/list:/bin/sh ++irc:x:39:39:ircd:/var/run/ircd:/bin/sh ++gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh ++nobody:x:65534:65534:nobody:/nonexistent:/bin/sh ++Debian-exim:x:102:102::/var/spool/exim4:/bin/false ++foo:x:1000:1000::/home/foo:/bin/false +diff --git a/tests/libsubid/02_get_subid_owners/config/etc/subgid b/tests/libsubid/02_get_subid_owners/config/etc/subgid +new file mode 100644 +index 00000000..b9495cfc +--- /dev/null ++++ b/tests/libsubid/02_get_subid_owners/config/etc/subgid +@@ -0,0 +1,2 @@ ++foo:200000:10000 ++root:500000:1000 +diff --git a/tests/libsubid/02_get_subid_owners/config/etc/subuid b/tests/libsubid/02_get_subid_owners/config/etc/subuid +new file mode 100644 +index 00000000..dd11875a +--- /dev/null ++++ b/tests/libsubid/02_get_subid_owners/config/etc/subuid +@@ -0,0 +1,4 @@ ++foo:300000:10000 ++foo:400000:10000 ++foo:500000:10000 ++root:500000:1000 +diff --git a/tests/libsubid/02_get_subid_owners/get_subid_owners.test b/tests/libsubid/02_get_subid_owners/get_subid_owners.test +new file mode 100755 +index 00000000..145477cb +--- /dev/null ++++ b/tests/libsubid/02_get_subid_owners/get_subid_owners.test +@@ -0,0 +1,52 @@ ++#!/bin/sh ++ ++set -e ++ ++cd $(dirname $0) ++ ++. ../../common/config.sh ++. ../../common/log.sh ++ ++log_start "$0" "get subid owners" ++ ++save_config ++ ++# restore the files on exit ++trap 'log_status "$0" "FAILURE"; restore_config' 0 ++ ++change_config ++ ++echo -n "Noone owns 0 as a subid..." ++[ -z "$(${build_path}/src/get_subid_owners 0)" ] ++echo "OK" ++ ++echo -n "foo owns subuid 300000..." ++[ "$(${build_path}/src/get_subid_owners 300000)" = "1000" ] ++echo "OK" ++ ++echo -n "foo owns subgid 200000..." ++[ "$(${build_path}/src/get_subid_owners -g 200000)" = "1000" ] ++echo "OK" ++ ++echo -n "Noone owns subuid 200000..." ++[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ] ++echo "OK" ++ ++echo -n "Noone owns subgid 300000..." ++[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ] ++echo "OK" ++ ++echo -n "Both foo and root own subuid 500000..." ++cat > /tmp/expected << EOF ++1000 ++0 ++EOF ++${build_path}/src/get_subid_owners 500000 > /tmp/actual ++diff /tmp/expected /tmp/actual ++ ++echo "OK" ++ ++log_status "$0" "SUCCESS" ++restore_config ++trap '' 0 ++ +diff --git a/tests/libsubid/03_add_remove/add_remove_subids.test b/tests/libsubid/03_add_remove/add_remove_subids.test +new file mode 100755 +index 00000000..a24a9752 +--- /dev/null ++++ b/tests/libsubid/03_add_remove/add_remove_subids.test +@@ -0,0 +1,59 @@ ++#!/bin/sh ++ ++set -e ++ ++cd $(dirname $0) ++ ++. ../../common/config.sh ++. ../../common/log.sh ++ ++log_start "$0" "add and remove subid ranges" ++ ++save_config ++ ++# restore the files on exit ++trap 'log_status "$0" "FAILURE"; restore_config' 0 ++ ++change_config ++ ++echo -n "Existing ranges returned when possible..." ++res=$(${build_path}/src/new_subid_range foo 500) ++echo "debug" ++echo "res is $res" ++echo "wanted Subuid range 300000:10000" ++echo "end debug" ++[ "$res" = "Subuid range 300000:10000" ] ++[ $(grep -c foo /etc/subuid) -eq 1 ] ++echo "OK" ++ ++echo -n "New range returned if requested..." ++res=$(${build_path}/src/new_subid_range foo 500 -n) ++[ "$res" = "Subuid range 310000:500" ] ++[ $(grep -c foo /etc/subuid) -eq 2 ] ++echo "OK" ++ ++echo -n "Free works..." ++res=$(${build_path}/src/free_subid_range foo 310000 500) ++[ $(grep -c foo /etc/subuid) -eq 1 ] ++echo "OK" ++ ++echo -n "Subgids work too..." ++res=$(${build_path}/src/new_subid_range -g foo 100000) ++echo "DEBUG: res is ${res}" ++[ "$res" = "Subuid range 501000:100000" ] ++echo "DEBUG: subgid is:" ++cat /etc/subgid ++[ $(grep -c foo /etc/subgid) -eq 2 ] ++ ++echo -n "Subgid free works..." ++res=$(${build_path}/src/free_subid_range -g foo 501000 100000) ++echo "DEBUG: res is ${res}" ++echo "DEBUG: subgid is:" ++cat /etc/subgid ++[ $(grep -c foo /etc/subgid) -eq 1 ] ++echo "OK" ++ ++log_status "$0" "SUCCESS" ++restore_config ++trap '' 0 ++ +diff --git a/tests/libsubid/03_add_remove/config.txt b/tests/libsubid/03_add_remove/config.txt +new file mode 100644 +index 00000000..e69de29b +diff --git a/tests/libsubid/03_add_remove/config/etc/passwd b/tests/libsubid/03_add_remove/config/etc/passwd +new file mode 100644 +index 00000000..bf52df00 +--- /dev/null ++++ b/tests/libsubid/03_add_remove/config/etc/passwd +@@ -0,0 +1,20 @@ ++root:x:0:0:root:/root:/bin/bash ++daemon:x:1:1:daemon:/usr/sbin:/bin/sh ++bin:x:2:2:bin:/bin:/bin/sh ++sys:x:3:3:sys:/dev:/bin/sh ++sync:x:4:65534:sync:/bin:/bin/sync ++games:x:5:60:games:/usr/games:/bin/sh ++man:x:6:12:man:/var/cache/man:/bin/sh ++lp:x:7:7:lp:/var/spool/lpd:/bin/sh ++mail:x:8:8:mail:/var/mail:/bin/sh ++news:x:9:9:news:/var/spool/news:/bin/sh ++uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh ++proxy:x:13:13:proxy:/bin:/bin/sh ++www-data:x:33:33:www-data:/var/www:/bin/sh ++backup:x:34:34:backup:/var/backups:/bin/sh ++list:x:38:38:Mailing List Manager:/var/list:/bin/sh ++irc:x:39:39:ircd:/var/run/ircd:/bin/sh ++gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh ++nobody:x:65534:65534:nobody:/nonexistent:/bin/sh ++Debian-exim:x:102:102::/var/spool/exim4:/bin/false ++foo:x:1000:1000::/home/foo:/bin/false +diff --git a/tests/libsubid/03_add_remove/config/etc/subgid b/tests/libsubid/03_add_remove/config/etc/subgid +new file mode 100644 +index 00000000..b9495cfc +--- /dev/null ++++ b/tests/libsubid/03_add_remove/config/etc/subgid +@@ -0,0 +1,2 @@ ++foo:200000:10000 ++root:500000:1000 +diff --git a/tests/libsubid/03_add_remove/config/etc/subuid b/tests/libsubid/03_add_remove/config/etc/subuid +new file mode 100644 +index 00000000..cf80c2f7 +--- /dev/null ++++ b/tests/libsubid/03_add_remove/config/etc/subuid +@@ -0,0 +1 @@ ++foo:300000:10000 +diff --git a/tests/run_some b/tests/run_some +new file mode 100755 +index 00000000..2d085d59 +--- /dev/null ++++ b/tests/run_some +@@ -0,0 +1,136 @@ ++#!/bin/sh ++ ++set -e ++ ++export LC_ALL=C ++unset LANG ++unset LANGUAGE ++. common/config.sh ++ ++USE_PAM="yes" ++FAILURE_TESTS="yes" ++ ++succeeded=0 ++failed=0 ++failed_tests="" ++ ++run_test() ++{ ++ [ -f RUN_TEST.STOP ] && exit 1 ++ ++ if $1 > $1.log ++ then ++ succeeded=$((succeeded+1)) ++ echo -n "+" ++ else ++ failed=$((failed+1)) ++ failed_tests="$failed_tests $1" ++ echo -n "-" ++ fi ++ cat $1.log >> testsuite.log ++ [ -f /etc/passwd.lock ] && echo $1 /etc/passwd.lock || true ++ [ -f /etc/group.lock ] && echo $1 /etc/group.lock || true ++ [ -f /etc/shadow.lock ] && echo $1 /etc/shadow.lock || true ++ [ -f /etc/gshadow.lock ] && echo $1 /etc/gshadow.lock || true ++ if [ "$(stat -c"%G" /etc/shadow)" != "shadow" ] ++ then ++ echo $1 ++ ls -l /etc/shadow ++ chgrp shadow /etc/shadow ++ fi ++ if [ -d /nonexistent ] ++ then ++ echo $1 /nonexistent ++ rmdir /nonexistent ++ fi ++} ++ ++echo "+: test passed" ++echo "-: test failed" ++ ++# Empty the complete log. ++> testsuite.log ++ ++find ${build_path} -name "*.gcda" -delete ++run_test ./su/01/su_root.test ++run_test ./su/01/su_user.test ++find ${build_path} -name "*.gcda" -exec chmod a+rw {} \; ++run_test ./su/02/env_FOO-options_--login ++run_test ./su/02/env_FOO-options_--login_bash ++run_test ./su/02/env_FOO-options_--preserve-environment ++run_test ./su/02/env_FOO-options_--preserve-environment_bash ++run_test ./su/02/env_FOO-options_- ++run_test ./su/02/env_FOO-options_-_bash ++run_test ./su/02/env_FOO-options_-l-m ++run_test ./su/02/env_FOO-options_-l-m_bash ++run_test ./su/02/env_FOO-options_-l ++run_test ./su/02/env_FOO-options_-l_bash ++run_test ./su/02/env_FOO-options_-m_bash ++run_test ./su/02/env_FOO-options_-m ++run_test ./su/02/env_FOO-options_-p ++run_test ./su/02/env_FOO-options_-p_bash ++run_test ./su/02/env_FOO-options__bash ++run_test ./su/02/env_FOO-options_ ++run_test ./su/02/env_FOO-options_-p- ++run_test ./su/02/env_FOO-options_-p-_bash ++run_test ./su/02/env_special-options_-l-p ++run_test ./su/02/env_special-options_-l ++run_test ./su/02/env_special-options_-l-p_bash ++run_test ./su/02/env_special-options_-l_bash ++run_test ./su/02/env_special-options_-p ++run_test ./su/02/env_special-options_-p_bash ++run_test ./su/02/env_special-options_ ++run_test ./su/02/env_special-options__bash ++run_test ./su/02/env_special_root-options_-l-p ++run_test ./su/02/env_special_root-options_-l-p_bash ++run_test ./su/02/env_special_root-options_-l ++run_test ./su/02/env_special_root-options_-l_bash ++run_test ./su/02/env_special_root-options_-p ++run_test ./su/02/env_special_root-options_-p_bash ++run_test ./su/02/env_special_root-options_ ++run_test ./su/02/env_special_root-options__bash ++run_test ./su/03/su_run_command01.test ++run_test ./su/03/su_run_command02.test ++run_test ./su/03/su_run_command03.test ++run_test ./su/03/su_run_command04.test ++run_test ./su/03/su_run_command05.test ++run_test ./su/03/su_run_command06.test ++run_test ./su/03/su_run_command07.test ++run_test ./su/03/su_run_command08.test ++run_test ./su/03/su_run_command09.test ++run_test ./su/03/su_run_command10.test ++run_test ./su/03/su_run_command11.test ++run_test ./su/03/su_run_command12.test ++run_test ./su/03/su_run_command13.test ++run_test ./su/03/su_run_command14.test ++run_test ./su/03/su_run_command15.test ++run_test ./su/03/su_run_command16.test ++run_test ./su/03/su_run_command17.test ++run_test ./su/04/su_wrong_user.test ++run_test ./su/04/su_user_wrong_passwd.test ++run_test ./su/04/su_user_wrong_passwd_syslog.test ++run_test ./su/05/su_user_wrong_passwd_syslog.test ++run_test ./su/06/su_user_syslog.test ++run_test ./su/07/su_user_syslog.test ++run_test ./su/08/env_special-options_ ++run_test ./su/08/env_special_root-options_ ++run_test ./su/09/env_special-options_ ++run_test ./su/09/env_special_root-options_ ++run_test ./su/10_su_sulog_success/su.test ++run_test ./su/11_su_sulog_failure/su.test ++run_test ./su/12_su_child_failure/su.test ++run_test ./su/13_su_child_success/su.test ++run_test ./libsubid/01_list_ranges/list_ranges.test ++run_test ./libsubid/02_get_subid_owners/get_subid_owners.test ++run_test ./libsubid/03_add_remove/add_remove_subids.test ++ ++echo ++echo "$succeeded test(s) passed" ++echo "$failed test(s) failed" ++echo "log written in 'testsuite.log'" ++if [ "$failed" != "0" ] ++then ++ echo "the following tests failed:" ++ echo $failed_tests ++fi ++ +-- +2.30.2 + +From 607f1dd549cf9abc87af1cf29275f0d2d11eea29 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Fri, 19 Jun 2020 22:09:20 -0500 +Subject: [PATCH] libsubid: fix a prototype in api.h + +Signed-off-by: Serge Hallyn +--- + libsubid/api.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsubid/api.h b/libsubid/api.h +index f65e3ec9..fbdf0f9e 100644 +--- a/libsubid/api.h ++++ b/libsubid/api.h +@@ -6,7 +6,7 @@ struct subordinate_range **get_subgid_ranges(const char *owner); + void subid_free_ranges(struct subordinate_range **ranges); + + int get_subuid_owners(uid_t uid, uid_t **owner); +-int get_subgid_owners(uid_t uid, uid_t **owner); ++int get_subgid_owners(gid_t gid, uid_t **owner); + + /* range should be pre-allocated with owner and count filled in, start is + * ignored, can be 0 */ +-- +2.30.2 + +From b5fb1b38eea2fb0489ed088c82daf6700e72363e Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Fri, 1 Jan 2021 13:01:54 -0600 +Subject: [PATCH] libsubid: move libmisc.a to last LIBADD entry + +Closes #297 + +Signed-off-by: Serge Hallyn +--- + libsubid/Makefile.am | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am +index bdbc52c3..8bef1ecc 100644 +--- a/libsubid/Makefile.am ++++ b/libsubid/Makefile.am +@@ -16,8 +16,8 @@ MISCLIBS = \ + + libsubid_la_LIBADD = \ + $(top_srcdir)/lib/libshadow.la \ +- $(top_srcdir)/libmisc/libmisc.a \ +- $(MISCLIBS) ++ $(MISCLIBS) \ ++ $(top_srcdir)/libmisc/libmisc.a + + AM_CPPFLAGS = \ + -I${top_srcdir}/lib \ +-- +2.30.2 + +From 43a917cce54019799a8de037fd63780a2b640afc Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sat, 18 Apr 2020 14:57:56 -0500 +Subject: [PATCH] configure: define abi versions + +Signed-off-by: Serge Hallyn +--- + configure.ac | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index e4c6aaec..b8bc2b7a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,11 +1,21 @@ + dnl Process this file with autoconf to produce a configure script. +-AC_PREREQ([2.64]) ++AC_PREREQ([2.69]) ++m4_define([libsubid_abi_major], 1) ++m4_define([libsubid_abi_minor], 0) ++m4_define([libsubid_abi_micro], 0) ++m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) + AC_INIT([shadow], [4.8.1], [pkg-shadow-devel@lists.alioth.debian.org], [], + [https://github.com/shadow-maint/shadow]) + AM_INIT_AUTOMAKE([1.11 foreign dist-xz]) ++AC_CONFIG_MACRO_DIRS([m4]) + AM_SILENT_RULES([yes]) + AC_CONFIG_HEADERS([config.h]) + ++AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major]) ++AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor]) ++AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro]) ++AC_SUBST([LIBSUBID_ABI], [libsubid_abi]) ++ + dnl Some hacks... + test "$prefix" = "NONE" && prefix="/usr" + test "$prefix" = "/usr" && exec_prefix="" +-- +2.30.2 + diff --git a/shadow-4.8.1-libsubid_nsswitch_support.patch b/shadow-4.8.1-libsubid_nsswitch_support.patch new file mode 100644 index 0000000..eafa7c1 --- /dev/null +++ b/shadow-4.8.1-libsubid_nsswitch_support.patch @@ -0,0 +1,2107 @@ +From 514c1328b6c90d817ae0a9f7addfb3c9a11a275a Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sun, 31 Jan 2021 22:44:09 -0600 +Subject: [PATCH 1/6] try again to fix libmisc sharing problem + +Issue #297 reported seeing + +*** Warning: Linking the shared library libsubid.la against the +*** static library ../libmisc/libmisc.a is not portable! + +which commit b5fb1b38eea2fb0489ed088c82daf6700e72363e was supposed +to fix. But a few commits later it's back. So try to fix it +in the way the bug reporter suggested. This broke builds some +other ways, namely a few missing library specifications, so add +those. + +Signed-off-by: Serge Hallyn +--- + configure.ac | 2 +- + libmisc/Makefile.am | 6 +++--- + libsubid/Makefile.am | 6 ++++-- + src/Makefile.am | 37 +++++++++++++++++++++++-------------- + 4 files changed, 31 insertions(+), 20 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 6aaae6b7..7884bfb6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -55,7 +55,7 @@ AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ + gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ + lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ + getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ +- ruserok) ++ ruserok dlopen) + AC_SYS_LARGEFILE + + dnl Checks for typedefs, structures, and compiler characteristics. +diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am +index 7f43161f..9766a7ec 100644 +--- a/libmisc/Makefile.am ++++ b/libmisc/Makefile.am +@@ -3,9 +3,9 @@ EXTRA_DIST = .indent.pro xgetXXbyYY.c + + AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECONF_CPPFLAGS) + +-noinst_LIBRARIES = libmisc.a ++noinst_LTLIBRARIES = libmisc.la + +-libmisc_a_SOURCES = \ ++libmisc_la_SOURCES = \ + addgrps.c \ + age.c \ + audit_help.c \ +@@ -74,6 +74,6 @@ libmisc_a_SOURCES = \ + yesno.c + + if WITH_BTRFS +-libmisc_a_SOURCES += btrfs.c ++libmisc_la_SOURCES += btrfs.c + endif + +diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am +index 8bef1ecc..f24dbb94 100644 +--- a/libsubid/Makefile.am ++++ b/libsubid/Makefile.am +@@ -12,12 +12,14 @@ MISCLIBS = \ + $(LIBMD) \ + $(LIBECONF) \ + $(LIBCRYPT) \ ++ $(LIBACL) \ ++ $(LIBATTR) \ + $(LIBTCB) + + libsubid_la_LIBADD = \ + $(top_srcdir)/lib/libshadow.la \ +- $(MISCLIBS) \ +- $(top_srcdir)/libmisc/libmisc.a ++ $(top_srcdir)/libmisc/libmisc.la \ ++ $(MISCLIBS) + + AM_CPPFLAGS = \ + -I${top_srcdir}/lib \ +diff --git a/src/Makefile.am b/src/Makefile.am +index 8499ce08..e9d354fd 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -78,7 +78,7 @@ shadowsgidubins = passwd + endif + + LDADD = $(INTLLIBS) \ +- $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/lib/libshadow.la \ + $(LIBTCB) + +@@ -95,28 +95,37 @@ LIBCRYPT_NOPAM = $(LIBCRYPT) + endif + + chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +-newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) +-newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) ++newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl ++newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl + chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + expiry_LDADD = $(LDADD) $(LIBECONF) + gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) +-groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +-groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) ++groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl ++groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl + groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +-groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) ++groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl + grpck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + grpconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + grpunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF) ++newuidmap_SOURCES = newuidmap.c ../libmisc/nss.c ++newgidmap_SOURCES = newgidmap.c ../libmisc/nss.c ++groupadd_SOURCES = groupadd.c ../libmisc/nss.c ++groupmod_SOURCES = groupmod.c ../libmisc/nss.c ++groupdel_SOURCES = groupdel.c ../libmisc/nss.c ++newusers_SOURCES = newusers.c ../libmisc/nss.c ++useradd_SOURCES = useradd.c ../libmisc/nss.c ++usermod_SOURCES = usermod.c ../libmisc/nss.c ++userdel_SOURCES = userdel.c ../libmisc/nss.c + login_SOURCES = \ + login.c \ + login_nopam.c + login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF) +-newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) ++newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl + nologin_LDADD = + passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) + pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +@@ -127,9 +136,9 @@ su_SOURCES = \ + suauth.c + su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF) +-useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) +-userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) +-usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) ++useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl ++userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) -ldl ++usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl + vipw_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + + install-am: all-am +@@ -175,7 +184,7 @@ MISCLIBS = \ + + list_subid_ranges_LDADD = \ + $(top_builddir)/lib/libshadow.la \ +- $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ + $(MISCLIBS) + +@@ -186,7 +195,7 @@ list_subid_ranges_CPPFLAGS = \ + + get_subid_owners_LDADD = \ + $(top_builddir)/lib/libshadow.la \ +- $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ + $(MISCLIBS) + +@@ -202,7 +211,7 @@ new_subid_range_CPPFLAGS = \ + + new_subid_range_LDADD = \ + $(top_builddir)/lib/libshadow.la \ +- $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ + $(MISCLIBS) + +@@ -213,7 +222,7 @@ free_subid_range_CPPFLAGS = \ + + free_subid_range_LDADD = \ + $(top_builddir)/lib/libshadow.la \ +- $(top_builddir)/libmisc/libmisc.a \ ++ $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ + $(MISCLIBS) + endif +-- +2.30.2 + + +From 8492dee6632e340dee76eee895c3e30877bebf45 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sun, 31 Jan 2021 17:38:20 -0600 +Subject: [PATCH 2/6] subids: support nsswitch + +Closes #154 + +When starting any operation to do with subuid delegation, check +nsswitch for a module to use. If none is specified, then use +the traditional /etc/subuid and /etc/subgid files. + +Currently only one module is supported, and there is no fallback +to the files on errors. Several possibilities could be considered: + +1. in case of connection error, fall back to files +2. in case of unknown user, also fall back to files + +etc... + +When non-files nss module is used, functions to edit the range +are not supported. It may make sense to support it, but it also +may make sense to require another tool to be used. + +libsubordinateio also uses the nss_ helpers. This is how for instance +lxc could easily be converted to supporting nsswitch. + +Add a set of test cases, including a dummy libsubid_zzz module. This +hardcodes values such that: + +'ubuntu' gets 200000 - 300000 +'user1' gets 100000 - 165536 +'error' emulates an nss module error +'unknown' emulates a user unknown to the nss module +'conn' emulates a connection error ot the nss module + +Changes to libsubid: + +Change the list_owner_ranges api: return a count instead of making the array +null terminated. + +This is a breaking change, so bump the libsubid abi major number. + +Rename free_subuid_range and free_subgid_range to ungrant_subuid_range, +because otherwise it's confusing with free_subid_ranges which frees + memory. + +Run libsubid tests in jenkins + +Switch argument order in find_subid_owners + +Move the db locking into subordinateio.c + +Signed-off-by: Serge Hallyn +--- + configure.ac | 2 +- + lib/Makefile.am | 1 + + lib/nss.c | 157 ++++++++++++++++ + lib/prototypes.h | 69 ++++++++ + lib/subordinateio.c | 256 ++++++++++++++++++++++++--- + lib/subordinateio.h | 6 +- + libmisc/idmapping.h | 2 + + libsubid/Makefile.am | 2 +- + libsubid/api.c | 168 +++--------------- + libsubid/api.h | 10 +- + libsubid/subid.h | 8 + + src/Makefile.am | 29 +-- + src/check_subid_range.c | 48 +++++ + src/free_subid_range.c | 4 +- + src/list_subid_ranges.c | 10 +- + tests/libsubid/04_nss/Makefile | 12 ++ + tests/libsubid/04_nss/empty | 0 + tests/libsubid/04_nss/libsubid_zzz.c | 146 +++++++++++++++ + tests/libsubid/04_nss/nsswitch1.conf | 20 +++ + tests/libsubid/04_nss/nsswitch2.conf | 22 +++ + tests/libsubid/04_nss/nsswitch3.conf | 22 +++ + tests/libsubid/04_nss/subidnss.test | 22 +++ + tests/libsubid/04_nss/test_nss.c | 72 ++++++++ + tests/libsubid/04_nss/test_range | 50 ++++++ + tests/run_some | 1 + + 26 files changed, 935 insertions(+), 205 deletions(-) + create mode 100644 lib/nss.c + create mode 100644 src/check_subid_range.c + create mode 100644 tests/libsubid/04_nss/Makefile + create mode 100644 tests/libsubid/04_nss/empty + create mode 100644 tests/libsubid/04_nss/libsubid_zzz.c + create mode 100644 tests/libsubid/04_nss/nsswitch1.conf + create mode 100644 tests/libsubid/04_nss/nsswitch2.conf + create mode 100644 tests/libsubid/04_nss/nsswitch3.conf + create mode 100755 tests/libsubid/04_nss/subidnss.test + create mode 100644 tests/libsubid/04_nss/test_nss.c + create mode 100755 tests/libsubid/04_nss/test_range + +diff --git a/configure.ac b/configure.ac +index 7884bfb6..7f7e8784 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,6 +1,6 @@ + dnl Process this file with autoconf to produce a configure script. + AC_PREREQ([2.69]) +-m4_define([libsubid_abi_major], 1) ++m4_define([libsubid_abi_major], 2) + m4_define([libsubid_abi_minor], 0) + m4_define([libsubid_abi_micro], 0) + m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) +diff --git a/lib/Makefile.am b/lib/Makefile.am +index bd9d6bfb..ecf3ee25 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -31,6 +31,7 @@ libshadow_la_SOURCES = \ + groupio.h \ + gshadow.c \ + lockpw.c \ ++ nss.c \ + nscd.c \ + nscd.h \ + sssd.c \ +diff --git a/lib/nss.c b/lib/nss.c +new file mode 100644 +index 00000000..2f924740 +--- /dev/null ++++ b/lib/nss.c +@@ -0,0 +1,157 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "prototypes.h" ++#include "../libsubid/subid.h" ++ ++#define NSSWITCH "/etc/nsswitch.conf" ++ ++// NSS plugin handling for subids ++// If nsswitch has a line like ++// subid: sssd ++// then sssd will be consulted for subids. Unlike normal NSS dbs, ++// only one db is supported at a time. That's open to debate, but ++// the subids are a pretty limited resource, and local files seem ++// bound to step on any other allocations leading to insecure ++// conditions. ++static atomic_flag nss_init_started; ++static atomic_bool nss_init_completed; ++ ++static struct subid_nss_ops *subid_nss; ++ ++bool nss_is_initialized() { ++ return atomic_load(&nss_init_completed); ++} ++ ++void nss_exit() { ++ if (nss_is_initialized() && subid_nss) { ++ dlclose(subid_nss->handle); ++ free(subid_nss); ++ subid_nss = NULL; ++ } ++} ++ ++// nsswitch_path is an argument only to support testing. ++void nss_init(char *nsswitch_path) { ++ FILE *nssfp = NULL; ++ char *line = NULL, *p, *token, *saveptr; ++ size_t len = 0; ++ ++ if (atomic_flag_test_and_set(&nss_init_started)) { ++ // Another thread has started nss_init, wait for it to complete ++ while (!atomic_load(&nss_init_completed)) ++ usleep(100); ++ return; ++ } ++ ++ if (!nsswitch_path) ++ nsswitch_path = NSSWITCH; ++ ++ // read nsswitch.conf to check for a line like: ++ // subid: files ++ nssfp = fopen(nsswitch_path, "r"); ++ if (!nssfp) { ++ fprintf(stderr, "Failed opening %s: %m", nsswitch_path); ++ atomic_store(&nss_init_completed, true); ++ return; ++ } ++ while ((getline(&line, &len, nssfp)) != -1) { ++ if (line[0] == '\0' || line[0] == '#') ++ continue; ++ if (strlen(line) < 8) ++ continue; ++ if (strncasecmp(line, "subid:", 6) != 0) ++ continue; ++ p = &line[6]; ++ while ((*p) && isspace(*p)) ++ p++; ++ if (!*p) ++ continue; ++ for (token = strtok_r(p, " \n\t", &saveptr); ++ token; ++ token = strtok_r(NULL, " \n\t", &saveptr)) { ++ char libname[65]; ++ void *h; ++ if (strcmp(token, "files") == 0) { ++ subid_nss = NULL; ++ goto done; ++ } ++ if (strlen(token) > 50) { ++ fprintf(stderr, "Subid NSS module name too long (longer than 50 characters): %s\n", token); ++ fprintf(stderr, "Using files\n"); ++ subid_nss = NULL; ++ goto done; ++ } ++ snprintf(libname, 64, "libsubid_%s.so", token); ++ h = dlopen(libname, RTLD_LAZY); ++ if (!h) { ++ fprintf(stderr, "Error opening %s: %s\n", libname, dlerror()); ++ fprintf(stderr, "Using files\n"); ++ subid_nss = NULL; ++ goto done; ++ } ++ subid_nss = malloc(sizeof(*subid_nss)); ++ if (!subid_nss) { ++ dlclose(h); ++ goto done; ++ } ++ subid_nss->has_range = dlsym(h, "shadow_subid_has_range"); ++ if (!subid_nss->has_range) { ++ fprintf(stderr, "%s did not provide @has_range@\n", libname); ++ dlclose(h); ++ free(subid_nss); ++ subid_nss = NULL; ++ goto done; ++ } ++ subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges"); ++ if (!subid_nss->list_owner_ranges) { ++ fprintf(stderr, "%s did not provide @list_owner_ranges@\n", libname); ++ dlclose(h); ++ free(subid_nss); ++ subid_nss = NULL; ++ goto done; ++ } ++ subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); ++ if (!subid_nss->has_any_range) { ++ fprintf(stderr, "%s did not provide @has_any_range@\n", libname); ++ dlclose(h); ++ free(subid_nss); ++ subid_nss = NULL; ++ goto done; ++ } ++ subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); ++ if (!subid_nss->find_subid_owners) { ++ fprintf(stderr, "%s did not provide @find_subid_owners@\n", libname); ++ dlclose(h); ++ free(subid_nss); ++ subid_nss = NULL; ++ goto done; ++ } ++ subid_nss->handle = h; ++ goto done; ++ } ++ fprintf(stderr, "No usable subid NSS module found, using files\n"); ++ // subid_nss has to be null here, but to ease reviews: ++ free(subid_nss); ++ subid_nss = NULL; ++ goto done; ++ } ++ ++done: ++ atomic_store(&nss_init_completed, true); ++ free(line); ++ if (nssfp) { ++ atexit(nss_exit); ++ fclose(nssfp); ++ } ++} ++ ++struct subid_nss_ops *get_subid_nss_handle() { ++ nss_init(NULL); ++ return subid_nss; ++} +diff --git a/lib/prototypes.h b/lib/prototypes.h +index ac9ad274..0c42bcc2 100644 +--- a/lib/prototypes.h ++++ b/lib/prototypes.h +@@ -262,6 +262,75 @@ extern void motd (void); + /* myname.c */ + extern /*@null@*//*@only@*/struct passwd *get_my_pwent (void); + ++/* nss.c */ ++#include ++extern void nss_init(char *nsswitch_path); ++extern bool nss_is_initialized(); ++ ++struct subid_nss_ops { ++ /* ++ * nss_has_any_range: does a user own any subid range ++ * ++ * @owner: username ++ * @idtype: subuid or subgid ++ * @result: true if a subid allocation was found for @owner ++ * ++ * returns success if the module was able to determine an answer (true or false), ++ * else an error status. ++ */ ++ enum subid_status (*has_any_range)(const char *owner, enum subid_type idtype, bool *result); ++ ++ /* ++ * nss_has_range: does a user own a given subid range ++ * ++ * @owner: username ++ * @start: first subid in queried range ++ * @count: number of subids in queried range ++ * @idtype: subuid or subgid ++ * @result: true if @owner has been allocated the subid range. ++ * ++ * returns success if the module was able to determine an answer (true or false), ++ * else an error status. ++ */ ++ enum subid_status (*has_range)(const char *owner, unsigned long start, unsigned long count, enum subid_type idtype, bool *result); ++ ++ /* ++ * nss_list_owner_ranges: list the subid ranges delegated to a user. ++ * ++ * @owner - string representing username being queried ++ * @id_type - subuid or subgid ++ * @ranges - pointer to an array of struct subordinate_range pointers, or ++ * NULL. The returned array of struct subordinate_range and its ++ * members must be freed by the caller. ++ * @count - pointer to an integer into which the number of returned ranges ++ * is written. ++ ++ * returns success if the module was able to determine an answer, ++ * else an error status. ++ */ ++ enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges, int *count); ++ ++ /* ++ * nss_find_subid_owners: find uids who own a given subuid or subgid. ++ * ++ * @id - the delegated id (subuid or subgid) being queried ++ * @id_type - subuid or subgid ++ * @uids - pointer to an array of uids which will be allocated by ++ * nss_find_subid_owners() ++ * @count - number of uids found ++ * ++ * returns success if the module was able to determine an answer, ++ * else an error status. ++ */ ++ enum subid_status (*find_subid_owners)(unsigned long id, enum subid_type id_type, uid_t **uids, int *count); ++ ++ /* The dlsym handle to close */ ++ void *handle; ++}; ++ ++extern struct subid_nss_ops *get_subid_nss_handle(); ++ ++ + /* pam_pass_non_interactive.c */ + #ifdef USE_PAM + extern int do_pam_passwd_non_interactive (const char *pam_service, +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 67202c98..0bb29958 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + /* + * subordinate_dup: create a duplicate range +@@ -311,17 +312,17 @@ static bool append_range(struct subordinate_range ***ranges, const struct subord + { + struct subordinate_range *tmp; + if (!*ranges) { +- *ranges = malloc(2 * sizeof(struct subordinate_range **)); ++ *ranges = malloc(sizeof(struct subordinate_range *)); + if (!*ranges) + return false; + } else { + struct subordinate_range **new; +- new = realloc(*ranges, (n + 2) * (sizeof(struct subordinate_range **))); ++ new = realloc(*ranges, (n + 1) * (sizeof(struct subordinate_range *))); + if (!new) + return false; + *ranges = new; + } +- (*ranges)[n] = (*ranges)[n+1] = NULL; ++ (*ranges)[n] = NULL; + tmp = subordinate_dup(new); + if (!tmp) + return false; +@@ -329,13 +330,13 @@ static bool append_range(struct subordinate_range ***ranges, const struct subord + return true; + } + +-void free_subordinate_ranges(struct subordinate_range **ranges) ++void free_subordinate_ranges(struct subordinate_range **ranges, int count) + { + int i; + + if (!ranges) + return; +- for (i = 0; ranges[i]; i++) ++ for (i = 0; i < count; i++) + subordinate_free(ranges[i]); + free(ranges); + } +@@ -602,21 +603,46 @@ int sub_uid_open (int mode) + + bool sub_uid_assigned(const char *owner) + { ++ struct subid_nss_ops *h; ++ bool found; ++ enum subid_status status; ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->has_any_range(owner, ID_TYPE_UID, &found); ++ if (status == SUBID_STATUS_SUCCESS && found) ++ return true; ++ return false; ++ } ++ + return range_exists (&subordinate_uid_db, owner); + } + + bool have_sub_uids(const char *owner, uid_t start, unsigned long count) + { ++ struct subid_nss_ops *h; ++ bool found; ++ enum subid_status status; ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->has_range(owner, start, count, ID_TYPE_UID, &found); ++ if (status == SUBID_STATUS_SUCCESS && found) ++ return true; ++ return false; ++ } + return have_range (&subordinate_uid_db, owner, start, count); + } + + int sub_uid_add (const char *owner, uid_t start, unsigned long count) + { ++ if (get_subid_nss_handle()) ++ return -EOPNOTSUPP; + return add_range (&subordinate_uid_db, owner, start, count); + } + + int sub_uid_remove (const char *owner, uid_t start, unsigned long count) + { ++ if (get_subid_nss_handle()) ++ return -EOPNOTSUPP; + return remove_range (&subordinate_uid_db, owner, start, count); + } + +@@ -684,21 +710,45 @@ int sub_gid_open (int mode) + + bool have_sub_gids(const char *owner, gid_t start, unsigned long count) + { ++ struct subid_nss_ops *h; ++ bool found; ++ enum subid_status status; ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->has_range(owner, start, count, ID_TYPE_GID, &found); ++ if (status == SUBID_STATUS_SUCCESS && found) ++ return true; ++ return false; ++ } + return have_range(&subordinate_gid_db, owner, start, count); + } + + bool sub_gid_assigned(const char *owner) + { ++ struct subid_nss_ops *h; ++ bool found; ++ enum subid_status status; ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->has_any_range(owner, ID_TYPE_GID, &found); ++ if (status == SUBID_STATUS_SUCCESS && found) ++ return true; ++ return false; ++ } + return range_exists (&subordinate_gid_db, owner); + } + + int sub_gid_add (const char *owner, gid_t start, unsigned long count) + { ++ if (get_subid_nss_handle()) ++ return -EOPNOTSUPP; + return add_range (&subordinate_gid_db, owner, start, count); + } + + int sub_gid_remove (const char *owner, gid_t start, unsigned long count) + { ++ if (get_subid_nss_handle()) ++ return -EOPNOTSUPP; + return remove_range (&subordinate_gid_db, owner, start, count); + } + +@@ -720,42 +770,78 @@ gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) + } + + /* +- struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) ++ * int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) + * + * @owner: username + * @id_type: UID or GUID ++ * @ranges: pointer to array of ranges into which results will be placed. + * +- * Returns the subuid or subgid ranges which are owned by the specified ++ * Fills in the subuid or subgid ranges which are owned by the specified + * user. Username may be a username or a string representation of a + * UID number. If id_type is UID, then subuids are returned, else +- * subgids are returned. If there is an error, < 0 is returned. ++ * subgids are given. ++ ++ * Returns the number of ranges found, or < 0 on error. + * + * The caller must free the subordinate range list. + */ +-struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) ++int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges) + { + // TODO - need to handle owner being either uid or username +- const struct subordinate_range *range; + struct subordinate_range **ranges = NULL; ++ const struct subordinate_range *range; + struct commonio_db *db; +- int size = 0; ++ enum subid_status status; ++ int count = 0; ++ struct subid_nss_ops *h; + +- if (id_type == ID_TYPE_UID) ++ *in_ranges = NULL; ++ ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->list_owner_ranges(owner, id_type, in_ranges, &count); ++ if (status == SUBID_STATUS_SUCCESS) ++ return count; ++ return -1; ++ } ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_open(O_RDONLY)) { ++ return -1; ++ } + db = &subordinate_uid_db; +- else ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_open(O_RDONLY)) { ++ return -1; ++ } + db = &subordinate_gid_db; ++ break; ++ default: ++ return -1; ++ } + + commonio_rewind(db); + while ((range = commonio_next(db)) != NULL) { + if (0 == strcmp(range->owner, owner)) { +- if (!append_range(&ranges, range, size++)) { +- free_subordinate_ranges(ranges); +- return NULL; ++ if (!append_range(&ranges, range, count++)) { ++ free_subordinate_ranges(ranges, count-1); ++ ranges = NULL; ++ count = -1; ++ goto out; + } + } + } + +- return ranges; ++out: ++ if (id_type == ID_TYPE_UID) ++ sub_uid_close(); ++ else ++ sub_gid_close(); ++ ++ *in_ranges = ranges; ++ return count; + } + + static bool all_digits(const char *str) +@@ -808,17 +894,41 @@ static int append_uids(uid_t **uids, const char *owner, int n) + return n+1; + } + +-int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) ++int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) + { + const struct subordinate_range *range; ++ struct subid_nss_ops *h; ++ enum subid_status status; + struct commonio_db *db; + int n = 0; + +- *uids = NULL; +- if (id_type == ID_TYPE_UID) ++ h = get_subid_nss_handle(); ++ if (h) { ++ status = h->find_subid_owners(id, id_type, uids, &n); ++ // Several ways we could handle the error cases here. ++ if (status != SUBID_STATUS_SUCCESS) ++ return -1; ++ return n; ++ } ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_open(O_RDONLY)) { ++ return -1; ++ } + db = &subordinate_uid_db; +- else ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_open(O_RDONLY)) { ++ return -1; ++ } + db = &subordinate_gid_db; ++ break; ++ default: ++ return -1; ++ } ++ ++ *uids = NULL; + + commonio_rewind(db); + while ((range = commonio_next(db)) != NULL) { +@@ -829,6 +939,11 @@ int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) + } + } + ++ if (id_type == ID_TYPE_UID) ++ sub_uid_close(); ++ else ++ sub_gid_close(); ++ + return n; + } + +@@ -836,11 +951,40 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + { + struct commonio_db *db; + const struct subordinate_range *r; ++ bool ret; + +- if (id_type == ID_TYPE_UID) ++ if (get_subid_nss_handle()) ++ return false; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_lock()) { ++ printf("Failed loging subuids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_uid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subuids (errno %d)\n", errno); ++ sub_uid_unlock(); ++ return false; ++ } + db = &subordinate_uid_db; +- else ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_lock()) { ++ printf("Failed loging subgids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_gid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subgids (errno %d)\n", errno); ++ sub_gid_unlock(); ++ return false; ++ } + db = &subordinate_gid_db; ++ break; ++ default: ++ return false; ++ } ++ + commonio_rewind(db); + if (reuse) { + while ((r = commonio_next(db)) != NULL) { +@@ -856,20 +1000,74 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + } + + range->start = find_free_range(db, range->start, ULONG_MAX, range->count); +- if (range->start == ULONG_MAX) +- return false; + +- return add_range(db, range->owner, range->start, range->count) == 1; ++ if (range->start == ULONG_MAX) { ++ ret = false; ++ goto out; ++ } ++ ++ ret = add_range(db, range->owner, range->start, range->count) == 1; ++ ++out: ++ if (id_type == ID_TYPE_UID) { ++ sub_uid_close(); ++ sub_uid_unlock(); ++ } else { ++ sub_gid_close(); ++ sub_gid_unlock(); ++ } ++ ++ return ret; + } + + bool release_subid_range(struct subordinate_range *range, enum subid_type id_type) + { + struct commonio_db *db; +- if (id_type == ID_TYPE_UID) ++ bool ret; ++ ++ if (get_subid_nss_handle()) ++ return false; ++ ++ switch (id_type) { ++ case ID_TYPE_UID: ++ if (!sub_uid_lock()) { ++ printf("Failed loging subuids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_uid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subuids (errno %d)\n", errno); ++ sub_uid_unlock(); ++ return false; ++ } + db = &subordinate_uid_db; +- else ++ break; ++ case ID_TYPE_GID: ++ if (!sub_gid_lock()) { ++ printf("Failed loging subgids (errno %d)\n", errno); ++ return false; ++ } ++ if (!sub_gid_open(O_CREAT | O_RDWR)) { ++ printf("Failed opening subgids (errno %d)\n", errno); ++ sub_gid_unlock(); ++ return false; ++ } + db = &subordinate_gid_db; +- return remove_range(db, range->owner, range->start, range->count) == 1; ++ break; ++ default: ++ return false; ++ } ++ ++ ret = remove_range(db, range->owner, range->start, range->count) == 1; ++ ++ if (id_type == ID_TYPE_UID) { ++ sub_uid_close(); ++ sub_uid_unlock(); ++ } else { ++ sub_gid_close(); ++ sub_gid_unlock(); ++ } ++ ++ return ret; + } + + #else /* !ENABLE_SUBIDS */ +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index 13a21341..e4be482c 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -25,11 +25,11 @@ extern int sub_uid_unlock (void); + extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); + extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); + extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); +-extern struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type); ++extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges); + extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); + extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); +-extern int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type); +-extern void free_subordinate_ranges(struct subordinate_range **ranges); ++extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); ++extern void free_subordinate_ranges(struct subordinate_range **ranges, int count); + + extern int sub_gid_close(void); + extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); +diff --git a/libmisc/idmapping.h b/libmisc/idmapping.h +index 3f32db68..1a8efe68 100644 +--- a/libmisc/idmapping.h ++++ b/libmisc/idmapping.h +@@ -40,5 +40,7 @@ extern struct map_range *get_map_ranges(int ranges, int argc, char **argv); + extern void write_mapping(int proc_dir_fd, int ranges, + struct map_range *mappings, const char *map_file, uid_t ruid); + ++extern void nss_init(char *nsswitch_path); ++ + #endif /* _ID_MAPPING_H_ */ + +diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am +index f24dbb94..f543b5eb 100644 +--- a/libsubid/Makefile.am ++++ b/libsubid/Makefile.am +@@ -19,7 +19,7 @@ MISCLIBS = \ + libsubid_la_LIBADD = \ + $(top_srcdir)/lib/libshadow.la \ + $(top_srcdir)/libmisc/libmisc.la \ +- $(MISCLIBS) ++ $(MISCLIBS) -ldl + + AM_CPPFLAGS = \ + -I${top_srcdir}/lib \ +diff --git a/libsubid/api.c b/libsubid/api.c +index 91d73bed..737e1c8b 100644 +--- a/libsubid/api.c ++++ b/libsubid/api.c +@@ -38,132 +38,48 @@ + #include "idmapping.h" + #include "api.h" + +-static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type) ++static ++int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) + { +- struct subordinate_range **ranges = NULL; +- +- switch (id_type) { +- case ID_TYPE_UID: +- if (!sub_uid_open(O_RDONLY)) { +- return NULL; +- } +- break; +- case ID_TYPE_GID: +- if (!sub_gid_open(O_RDONLY)) { +- return NULL; +- } +- break; +- default: +- return NULL; +- } +- +- ranges = list_owner_ranges(owner, id_type); +- +- if (id_type == ID_TYPE_UID) +- sub_uid_close(); +- else +- sub_gid_close(); +- +- return ranges; ++ return list_owner_ranges(owner, id_type, ranges); + } + +-struct subordinate_range **get_subuid_ranges(const char *owner) ++int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges) + { +- return get_subid_ranges(owner, ID_TYPE_UID); ++ return get_subid_ranges(owner, ID_TYPE_UID, ranges); + } + +-struct subordinate_range **get_subgid_ranges(const char *owner) ++int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges) + { +- return get_subid_ranges(owner, ID_TYPE_GID); ++ return get_subid_ranges(owner, ID_TYPE_GID, ranges); + } + +-void subid_free_ranges(struct subordinate_range **ranges) ++void subid_free_ranges(struct subordinate_range **ranges, int count) + { +- return free_subordinate_ranges(ranges); ++ return free_subordinate_ranges(ranges, count); + } + +-int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type) ++static ++int get_subid_owner(unsigned long id, enum subid_type id_type, uid_t **owner) + { +- int ret = -1; +- +- switch (id_type) { +- case ID_TYPE_UID: +- if (!sub_uid_open(O_RDONLY)) { +- return -1; +- } +- break; +- case ID_TYPE_GID: +- if (!sub_gid_open(O_RDONLY)) { +- return -1; +- } +- break; +- default: +- return -1; +- } +- +- ret = find_subid_owners(id, owner, id_type); +- +- if (id_type == ID_TYPE_UID) +- sub_uid_close(); +- else +- sub_gid_close(); +- +- return ret; ++ return find_subid_owners(id, id_type, owner); + } + + int get_subuid_owners(uid_t uid, uid_t **owner) + { +- return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID); ++ return get_subid_owner((unsigned long)uid, ID_TYPE_UID, owner); + } + + int get_subgid_owners(gid_t gid, uid_t **owner) + { +- return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID); ++ return get_subid_owner((unsigned long)gid, ID_TYPE_GID, owner); + } + ++static + bool grant_subid_range(struct subordinate_range *range, bool reuse, + enum subid_type id_type) + { +- bool ret; +- +- switch (id_type) { +- case ID_TYPE_UID: +- if (!sub_uid_lock()) { +- printf("Failed loging subuids (errno %d)\n", errno); +- return false; +- } +- if (!sub_uid_open(O_CREAT | O_RDWR)) { +- printf("Failed opening subuids (errno %d)\n", errno); +- sub_uid_unlock(); +- return false; +- } +- break; +- case ID_TYPE_GID: +- if (!sub_gid_lock()) { +- printf("Failed loging subgids (errno %d)\n", errno); +- return false; +- } +- if (!sub_gid_open(O_CREAT | O_RDWR)) { +- printf("Failed opening subgids (errno %d)\n", errno); +- sub_gid_unlock(); +- return false; +- } +- break; +- default: +- return false; +- } +- +- ret = new_subid_range(range, id_type, reuse); +- +- if (id_type == ID_TYPE_UID) { +- sub_uid_close(); +- sub_uid_unlock(); +- } else { +- sub_gid_close(); +- sub_gid_unlock(); +- } +- +- return ret; ++ return new_subid_range(range, id_type, reuse); + } + + bool grant_subuid_range(struct subordinate_range *range, bool reuse) +@@ -176,56 +92,18 @@ bool grant_subgid_range(struct subordinate_range *range, bool reuse) + return grant_subid_range(range, reuse, ID_TYPE_GID); + } + +-bool free_subid_range(struct subordinate_range *range, enum subid_type id_type) ++static ++bool ungrant_subid_range(struct subordinate_range *range, enum subid_type id_type) + { +- bool ret; +- +- switch (id_type) { +- case ID_TYPE_UID: +- if (!sub_uid_lock()) { +- printf("Failed loging subuids (errno %d)\n", errno); +- return false; +- } +- if (!sub_uid_open(O_CREAT | O_RDWR)) { +- printf("Failed opening subuids (errno %d)\n", errno); +- sub_uid_unlock(); +- return false; +- } +- break; +- case ID_TYPE_GID: +- if (!sub_gid_lock()) { +- printf("Failed loging subgids (errno %d)\n", errno); +- return false; +- } +- if (!sub_gid_open(O_CREAT | O_RDWR)) { +- printf("Failed opening subgids (errno %d)\n", errno); +- sub_gid_unlock(); +- return false; +- } +- break; +- default: +- return false; +- } +- +- ret = release_subid_range(range, id_type); +- +- if (id_type == ID_TYPE_UID) { +- sub_uid_close(); +- sub_uid_unlock(); +- } else { +- sub_gid_close(); +- sub_gid_unlock(); +- } +- +- return ret; ++ return release_subid_range(range, id_type); + } + +-bool free_subuid_range(struct subordinate_range *range) ++bool ungrant_subuid_range(struct subordinate_range *range) + { +- return free_subid_range(range, ID_TYPE_UID); ++ return ungrant_subid_range(range, ID_TYPE_UID); + } + +-bool free_subgid_range(struct subordinate_range *range) ++bool ungrant_subgid_range(struct subordinate_range *range) + { +- return free_subid_range(range, ID_TYPE_GID); ++ return ungrant_subid_range(range, ID_TYPE_GID); + } +diff --git a/libsubid/api.h b/libsubid/api.h +index fbdf0f9e..97b04e25 100644 +--- a/libsubid/api.h ++++ b/libsubid/api.h +@@ -1,9 +1,9 @@ + #include "subid.h" + #include + +-struct subordinate_range **get_subuid_ranges(const char *owner); +-struct subordinate_range **get_subgid_ranges(const char *owner); +-void subid_free_ranges(struct subordinate_range **ranges); ++int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); ++int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); ++void subid_free_ranges(struct subordinate_range **ranges, int count); + + int get_subuid_owners(uid_t uid, uid_t **owner); + int get_subgid_owners(gid_t gid, uid_t **owner); +@@ -13,5 +13,5 @@ int get_subgid_owners(gid_t gid, uid_t **owner); + bool grant_subuid_range(struct subordinate_range *range, bool reuse); + bool grant_subgid_range(struct subordinate_range *range, bool reuse); + +-bool free_subuid_range(struct subordinate_range *range); +-bool free_subgid_range(struct subordinate_range *range); ++bool ungrant_subuid_range(struct subordinate_range *range); ++bool ungrant_subgid_range(struct subordinate_range *range); +diff --git a/libsubid/subid.h b/libsubid/subid.h +index ba9a2f6f..2f27ad8a 100644 +--- a/libsubid/subid.h ++++ b/libsubid/subid.h +@@ -1,4 +1,5 @@ + #include ++#include + + #ifndef SUBID_RANGE_DEFINED + #define SUBID_RANGE_DEFINED 1 +@@ -13,5 +14,12 @@ enum subid_type { + ID_TYPE_GID = 2 + }; + ++enum subid_status { ++ SUBID_STATUS_SUCCESS = 0, ++ SUBID_STATUS_UNKNOWN_USER = 1, ++ SUBID_STATUS_ERROR_CONN = 2, ++ SUBID_STATUS_ERROR = 3, ++}; ++ + #define SUBID_NFIELDS 3 + #endif +diff --git a/src/Makefile.am b/src/Makefile.am +index e9d354fd..35027013 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -111,15 +111,6 @@ grpck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + grpconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + grpunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF) +-newuidmap_SOURCES = newuidmap.c ../libmisc/nss.c +-newgidmap_SOURCES = newgidmap.c ../libmisc/nss.c +-groupadd_SOURCES = groupadd.c ../libmisc/nss.c +-groupmod_SOURCES = groupmod.c ../libmisc/nss.c +-groupdel_SOURCES = groupdel.c ../libmisc/nss.c +-newusers_SOURCES = newusers.c ../libmisc/nss.c +-useradd_SOURCES = useradd.c ../libmisc/nss.c +-usermod_SOURCES = usermod.c ../libmisc/nss.c +-userdel_SOURCES = userdel.c ../libmisc/nss.c + login_SOURCES = \ + login.c \ + login_nopam.c +@@ -169,7 +160,8 @@ endif + noinst_PROGRAMS += list_subid_ranges \ + get_subid_owners \ + new_subid_range \ +- free_subid_range ++ free_subid_range \ ++ check_subid_range + + MISCLIBS = \ + $(LIBAUDIT) \ +@@ -186,7 +178,7 @@ list_subid_ranges_LDADD = \ + $(top_builddir)/lib/libshadow.la \ + $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ +- $(MISCLIBS) ++ $(MISCLIBS) -ldl + + list_subid_ranges_CPPFLAGS = \ + -I$(top_srcdir)/lib \ +@@ -197,7 +189,7 @@ get_subid_owners_LDADD = \ + $(top_builddir)/lib/libshadow.la \ + $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ +- $(MISCLIBS) ++ $(MISCLIBS) -ldl + + get_subid_owners_CPPFLAGS = \ + -I$(top_srcdir)/lib \ +@@ -213,7 +205,7 @@ new_subid_range_LDADD = \ + $(top_builddir)/lib/libshadow.la \ + $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ +- $(MISCLIBS) ++ $(MISCLIBS) -ldl + + free_subid_range_CPPFLAGS = \ + -I$(top_srcdir)/lib \ +@@ -224,5 +216,14 @@ free_subid_range_LDADD = \ + $(top_builddir)/lib/libshadow.la \ + $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ +- $(MISCLIBS) ++ $(MISCLIBS) -ldl ++ ++check_subid_range_CPPFLAGS = \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/libmisc ++ ++check_subid_range_LDADD = \ ++ $(top_builddir)/lib/libshadow.la \ ++ $(top_builddir)/libmisc/libmisc.la \ ++ $(MISCLIBS) -ldl + endif +diff --git a/src/check_subid_range.c b/src/check_subid_range.c +new file mode 100644 +index 00000000..fb1c2cfc +--- /dev/null ++++ b/src/check_subid_range.c +@@ -0,0 +1,48 @@ ++// This program is for testing purposes only. ++// usage is "[program] owner [u|g] start count ++// Exits 0 if owner has subid range starting start, of size count ++// Exits 1 otherwise. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "defines.h" ++#include "prototypes.h" ++#include "subordinateio.h" ++#include "idmapping.h" ++ ++const char *Prog; ++ ++int main(int argc, char **argv) ++{ ++ char *owner; ++ unsigned long start, count; ++ bool check_uids; ++ Prog = Basename (argv[0]); ++ ++ if (argc != 5) ++ exit(1); ++ ++ owner = argv[1]; ++ check_uids = argv[2][0] == 'u'; ++ start = strtoul(argv[3], NULL, 10); ++ if (start == ULONG_MAX && errno == ERANGE) ++ exit(1); ++ count = strtoul(argv[4], NULL, 10); ++ if (count == ULONG_MAX && errno == ERANGE) ++ exit(1); ++ if (check_uids) { ++ if (have_sub_uids(owner, start, count)) ++ exit(0); ++ exit(1); ++ } ++ if (have_sub_gids(owner, start, count)) ++ exit(0); ++ exit(1); ++} +diff --git a/src/free_subid_range.c b/src/free_subid_range.c +index 36858875..de6bc58f 100644 +--- a/src/free_subid_range.c ++++ b/src/free_subid_range.c +@@ -37,9 +37,9 @@ int main(int argc, char *argv[]) + range.start = atoi(argv[1]); + range.count = atoi(argv[2]); + if (group) +- ok = free_subgid_range(&range); ++ ok = ungrant_subgid_range(&range); + else +- ok = free_subuid_range(&range); ++ ok = ungrant_subuid_range(&range); + + if (!ok) { + fprintf(stderr, "Failed freeing id range\n"); +diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c +index cdba610e..440ef911 100644 +--- a/src/list_subid_ranges.c ++++ b/src/list_subid_ranges.c +@@ -15,7 +15,7 @@ void usage(void) + + int main(int argc, char *argv[]) + { +- int i; ++ int i, count=0; + struct subordinate_range **ranges; + + Prog = Basename (argv[0]); +@@ -23,19 +23,19 @@ int main(int argc, char *argv[]) + usage(); + } + if (argc == 3 && strcmp(argv[1], "-g") == 0) +- ranges = get_subgid_ranges(argv[2]); ++ count = get_subgid_ranges(argv[2], &ranges); + else if (argc == 2 && strcmp(argv[1], "-h") == 0) + usage(); + else +- ranges = get_subuid_ranges(argv[1]); ++ count = get_subuid_ranges(argv[1], &ranges); + if (!ranges) { + fprintf(stderr, "Error fetching ranges\n"); + exit(1); + } +- for (i = 0; ranges[i]; i++) { ++ for (i = 0; i < count; i++) { + printf("%d: %s %lu %lu\n", i, ranges[i]->owner, + ranges[i]->start, ranges[i]->count); + } +- subid_free_ranges(ranges); ++ subid_free_ranges(ranges, count); + return 0; + } +diff --git a/tests/libsubid/04_nss/Makefile b/tests/libsubid/04_nss/Makefile +new file mode 100644 +index 00000000..6cd3225f +--- /dev/null ++++ b/tests/libsubid/04_nss/Makefile +@@ -0,0 +1,12 @@ ++all: test_nss libsubid_zzz.so ++ ++test_nss: test_nss.c ../../../lib/nss.c ++ gcc -c -I../../../lib/ -I../../.. -o test_nss.o test_nss.c ++ gcc -o test_nss test_nss.o ../../../libmisc/.libs/libmisc.a ../../../lib/.libs/libshadow.a -ldl ++ ++libsubid_zzz.so: libsubid_zzz.c ++ gcc -c -I../../../lib/ -I../../.. -I../../../libmisc -I../../../libsubid libsubid_zzz.c ++ gcc -L../../../libsubid -shared -o libsubid_zzz.so libsubid_zzz.o ../../../lib/.libs/libshadow.a -ldl ++ ++clean: ++ rm -f *.o *.so test_nss +diff --git a/tests/libsubid/04_nss/empty b/tests/libsubid/04_nss/empty +new file mode 100644 +index 00000000..e69de29b +diff --git a/tests/libsubid/04_nss/libsubid_zzz.c b/tests/libsubid/04_nss/libsubid_zzz.c +new file mode 100644 +index 00000000..b56a4bae +--- /dev/null ++++ b/tests/libsubid/04_nss/libsubid_zzz.c +@@ -0,0 +1,146 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum subid_status shadow_subid_has_any_range(const char *owner, enum subid_type t, bool *result) ++{ ++ if (strcmp(owner, "ubuntu") == 0) { ++ *result = true; ++ return SUBID_STATUS_SUCCESS; ++ } ++ if (strcmp(owner, "error") == 0) { ++ *result = false; ++ return SUBID_STATUS_ERROR; ++ } ++ if (strcmp(owner, "unknown") == 0) { ++ *result = false; ++ return SUBID_STATUS_UNKNOWN_USER; ++ } ++ if (strcmp(owner, "conn") == 0) { ++ *result = false; ++ return SUBID_STATUS_ERROR_CONN; ++ } ++ if (t == ID_TYPE_UID) { ++ *result = strcmp(owner, "user1") == 0; ++ return SUBID_STATUS_SUCCESS; ++ } ++ ++ *result = strcmp(owner, "group1") == 0; ++ return SUBID_STATUS_SUCCESS; ++} ++ ++enum subid_status shadow_subid_has_range(const char *owner, unsigned long start, unsigned long count, enum subid_type t, bool *result) ++{ ++ if (strcmp(owner, "ubuntu") == 0 && ++ start >= 200000 && ++ count <= 100000) { ++ *result = true; ++ return SUBID_STATUS_SUCCESS; ++ } ++ *result = false; ++ if (strcmp(owner, "error") == 0) ++ return SUBID_STATUS_ERROR; ++ if (strcmp(owner, "unknown") == 0) ++ return SUBID_STATUS_UNKNOWN_USER; ++ if (strcmp(owner, "conn") == 0) ++ return SUBID_STATUS_ERROR_CONN; ++ ++ if (t == ID_TYPE_UID && strcmp(owner, "user1") != 0) ++ return SUBID_STATUS_SUCCESS; ++ if (t == ID_TYPE_GID && strcmp(owner, "group1") != 0) ++ return SUBID_STATUS_SUCCESS; ++ ++ if (start < 100000) ++ return SUBID_STATUS_SUCCESS; ++ if (count >= 65536) ++ return SUBID_STATUS_SUCCESS; ++ *result = true; ++ return SUBID_STATUS_SUCCESS; ++} ++ ++// So if 'user1' or 'ubuntu' is defined in passwd, we'll return those values, ++// to ease manual testing. For automated testing, if you return those values, ++// we'll return 1000 for ubuntu and 1001 otherwise. ++static uid_t getnamuid(const char *name) { ++ struct passwd *pw; ++ ++ pw = getpwnam(name); ++ if (pw) ++ return pw->pw_uid; ++ ++ // For testing purposes ++ return strcmp(name, "ubuntu") == 0 ? (uid_t)1000 : (uid_t)1001; ++} ++ ++static int alloc_uid(uid_t **uids, uid_t id) { ++ *uids = malloc(sizeof(uid_t)); ++ if (!*uids) ++ return -1; ++ *uids[0] = id; ++ return 1; ++} ++ ++enum subid_status shadow_subid_find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids, int *count) ++{ ++ if (id >= 100000 && id < 165536) { ++ *count = alloc_uid(uids, getnamuid("user1")); ++ if (*count == 1) ++ return SUBID_STATUS_SUCCESS; ++ return SUBID_STATUS_ERROR; // out of memory ++ } ++ if (id >= 200000 && id < 300000) { ++ *count = alloc_uid(uids, getnamuid("ubuntu")); ++ if (*count == 1) ++ return SUBID_STATUS_SUCCESS; ++ return SUBID_STATUS_ERROR; // out of memory ++ } ++ *count = 0; // nothing found ++ return SUBID_STATUS_SUCCESS; ++} ++ ++enum subid_status shadow_subid_list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges, int *count) ++{ ++ struct subordinate_range **ranges; ++ ++ *count = 0; ++ if (strcmp(owner, "error") == 0) ++ return SUBID_STATUS_ERROR; ++ if (strcmp(owner, "unknown") == 0) ++ return SUBID_STATUS_UNKNOWN_USER; ++ if (strcmp(owner, "conn") == 0) ++ return SUBID_STATUS_ERROR_CONN; ++ ++ *ranges = NULL; ++ if (strcmp(owner, "user1") != 0 && strcmp(owner, "ubuntu") != 0 && ++ strcmp(owner, "group1") != 0) ++ return SUBID_STATUS_SUCCESS; ++ if (id_type == ID_TYPE_GID && strcmp(owner, "user1") == 0) ++ return SUBID_STATUS_SUCCESS; ++ if (id_type == ID_TYPE_UID && strcmp(owner, "group1") == 0) ++ return SUBID_STATUS_SUCCESS; ++ ranges = (struct subordinate_range **)malloc(sizeof(struct subordinate_range *)); ++ if (!*ranges) ++ return SUBID_STATUS_ERROR; ++ ranges[0] = (struct subordinate_range *)malloc(sizeof(struct subordinate_range)); ++ if (!ranges[0]) { ++ free(*ranges); ++ *ranges = NULL; ++ return SUBID_STATUS_ERROR; ++ } ++ ranges[0]->owner = strdup(owner); ++ if (strcmp(owner, "user1") == 0 || strcmp(owner, "group1") == 0) { ++ ranges[0]->start = 100000; ++ ranges[0]->count = 65536; ++ } else { ++ ranges[0]->start = 200000; ++ ranges[0]->count = 100000; ++ } ++ ++ *count = 1; ++ *in_ranges = ranges; ++ ++ return SUBID_STATUS_SUCCESS; ++} +diff --git a/tests/libsubid/04_nss/nsswitch1.conf b/tests/libsubid/04_nss/nsswitch1.conf +new file mode 100644 +index 00000000..43764a39 +--- /dev/null ++++ b/tests/libsubid/04_nss/nsswitch1.conf +@@ -0,0 +1,20 @@ ++# /etc/nsswitch.conf ++# ++# Example configuration of GNU Name Service Switch functionality. ++# If you have the `glibc-doc-reference' and `info' packages installed, try: ++# `info libc "Name Service Switch"' for information about this file. ++ ++passwd: files systemd ++group: files systemd ++shadow: files ++gshadow: files ++ ++hosts: files mdns4_minimal [NOTFOUND=return] dns ++networks: files ++ ++protocols: db files ++services: db files ++ethers: db files ++rpc: db files ++ ++netgroup: nis +diff --git a/tests/libsubid/04_nss/nsswitch2.conf b/tests/libsubid/04_nss/nsswitch2.conf +new file mode 100644 +index 00000000..d371a36c +--- /dev/null ++++ b/tests/libsubid/04_nss/nsswitch2.conf +@@ -0,0 +1,22 @@ ++# /etc/nsswitch.conf ++# ++# Example configuration of GNU Name Service Switch functionality. ++# If you have the `glibc-doc-reference' and `info' packages installed, try: ++# `info libc "Name Service Switch"' for information about this file. ++ ++passwd: files systemd ++group: files systemd ++shadow: files ++gshadow: files ++ ++hosts: files mdns4_minimal [NOTFOUND=return] dns ++networks: files ++ ++protocols: db files ++services: db files ++ethers: db files ++rpc: db files ++ ++netgroup: nis ++ ++subid: files +diff --git a/tests/libsubid/04_nss/nsswitch3.conf b/tests/libsubid/04_nss/nsswitch3.conf +new file mode 100644 +index 00000000..19f2d934 +--- /dev/null ++++ b/tests/libsubid/04_nss/nsswitch3.conf +@@ -0,0 +1,22 @@ ++# /etc/nsswitch.conf ++# ++# Example configuration of GNU Name Service Switch functionality. ++# If you have the `glibc-doc-reference' and `info' packages installed, try: ++# `info libc "Name Service Switch"' for information about this file. ++ ++passwd: files systemd ++group: files systemd ++shadow: files ++gshadow: files ++ ++hosts: files mdns4_minimal [NOTFOUND=return] dns ++networks: files ++ ++protocols: db files ++services: db files ++ethers: db files ++rpc: db files ++ ++netgroup: nis ++ ++subid: zzz +diff --git a/tests/libsubid/04_nss/subidnss.test b/tests/libsubid/04_nss/subidnss.test +new file mode 100755 +index 00000000..3d40dc8c +--- /dev/null ++++ b/tests/libsubid/04_nss/subidnss.test +@@ -0,0 +1,22 @@ ++#!/bin/sh ++ ++set -e ++ ++cd $(dirname $0) ++ ++. ../../common/config.sh ++. ../../common/log.sh ++ ++make ++ ++export LD_LIBRARY_PATH=.:../../../lib/.libs:$LD_LIBRARY_PATH ++ ++./test_nss 1 ++./test_nss 2 ++./test_nss 3 ++ ++unshare -Urm ./test_range ++ ++log_status "$0" "SUCCESS" ++ ++trap '' 0 +diff --git a/tests/libsubid/04_nss/test_nss.c b/tests/libsubid/04_nss/test_nss.c +new file mode 100644 +index 00000000..5d903ab4 +--- /dev/null ++++ b/tests/libsubid/04_nss/test_nss.c +@@ -0,0 +1,72 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern bool nss_is_initialized(); ++extern struct subid_nss_ops *get_subid_nss_handle(); ++ ++void test1() { ++ // nsswitch1 has no subid: entry ++ setenv("LD_LIBRARY_PATH", ".", 1); ++ printf("Test with no subid entry\n"); ++ nss_init("./nsswitch1.conf"); ++ if (!nss_is_initialized() || get_subid_nss_handle()) ++ exit(1); ++ // second run should change nothing ++ printf("Test with no subid entry, second run\n"); ++ nss_init("./nsswitch1.conf"); ++ if (!nss_is_initialized() || get_subid_nss_handle()) ++ exit(1); ++} ++ ++void test2() { ++ // nsswitch2 has a subid: files entry ++ printf("test with 'files' subid entry\n"); ++ nss_init("./nsswitch2.conf"); ++ if (!nss_is_initialized() || get_subid_nss_handle()) ++ exit(1); ++ // second run should change nothing ++ printf("test with 'files' subid entry, second run\n"); ++ nss_init("./nsswitch2.conf"); ++ if (!nss_is_initialized() || get_subid_nss_handle()) ++ exit(1); ++} ++ ++void test3() { ++ // nsswitch3 has a subid: testnss entry ++ printf("test with 'test' subid entry\n"); ++ nss_init("./nsswitch3.conf"); ++ if (!nss_is_initialized() || !get_subid_nss_handle()) ++ exit(1); ++ // second run should change nothing ++ printf("test with 'test' subid entry, second run\n"); ++ nss_init("./nsswitch3.conf"); ++ if (!nss_is_initialized() || !get_subid_nss_handle()) ++ exit(1); ++} ++ ++const char *Prog; ++ ++int main(int argc, char *argv[]) ++{ ++ int which; ++ ++ Prog = Basename(argv[0]); ++ ++ if (argc < 1) ++ exit(1); ++ ++ which = atoi(argv[1]); ++ switch(which) { ++ case 1: test1(); break; ++ case 2: test2(); break; ++ case 3: test3(); break; ++ default: exit(1); ++ } ++ ++ printf("nss parsing tests done\n"); ++ exit(0); ++} +diff --git a/tests/libsubid/04_nss/test_range b/tests/libsubid/04_nss/test_range +new file mode 100755 +index 00000000..356764fb +--- /dev/null ++++ b/tests/libsubid/04_nss/test_range +@@ -0,0 +1,50 @@ ++#!/bin/sh ++ ++set -x ++ ++echo "starting check_range tests" ++ ++export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ++mount --bind ./nsswitch3.conf /etc/nsswitch.conf ++cleanup1() { ++ umount /etc/nsswitch.conf ++} ++trap cleanup1 EXIT HUP INT TERM ++../../../src/check_subid_range user1 u 100000 65535 ++if [ $? -ne 0 ]; then ++ exit 1 ++fi ++../../../src/check_subid_range user2 u 100000 65535 ++if [ $? -eq 0 ]; then ++ exit 1 ++fi ++../../../src/check_subid_range unknown u 100000 65535 ++if [ $? -eq 0 ]; then ++ exit 1 ++fi ++../../../src/check_subid_range error u 100000 65535 ++if [ $? -eq 0 ]; then ++ exit 1 ++fi ++../../../src/check_subid_range user1 u 1000 65535 ++if [ $? -eq 0 ]; then ++ exit 1 ++fi ++ ++umount /etc/nsswitch.conf ++ ++mount --bind ./nsswitch1.conf /etc/nsswitch.conf ++mount --bind ./empty /etc/subuid ++ ++cleanup2() { ++ umount /etc/subuid ++ umount /etc/nsswitch.conf ++} ++trap cleanup2 EXIT HUP INT TERM ++../../../src/check_subid_range user1 u 100000 65535 ++if [ $? -eq 0 ]; then ++ exit 1 ++fi ++ ++echo "check_range tests complete" ++exit 0 +diff --git a/tests/run_some b/tests/run_some +index 15b4816a..e6f6eb5a 100755 +--- a/tests/run_some ++++ b/tests/run_some +@@ -127,6 +127,7 @@ run_test ./newuidmap/01_newuidmap/newuidmap.test + run_test ./libsubid/01_list_ranges/list_ranges.test + run_test ./libsubid/02_get_subid_owners/get_subid_owners.test + run_test ./libsubid/03_add_remove/add_remove_subids.test ++run_test ./libsubid/04_nss/subidnss.test + + echo + echo "$succeeded test(s) passed" +-- +2.30.2 + + +From 0f4347d1483191b2142546416a9eefe0c9459600 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Thu, 15 Apr 2021 09:52:29 -0500 +Subject: [PATCH 3/6] clean up libsubid headers + +Move libsubid/api.h into libsubid/subid.h, and document the api in subid.h + +Signed-off-by: Serge Hallyn +--- + libsubid/api.c | 2 +- + libsubid/api.h | 17 ------- + libsubid/subid.h | 105 ++++++++++++++++++++++++++++++++++++++++ + src/free_subid_range.c | 2 +- + src/get_subid_owners.c | 2 +- + src/list_subid_ranges.c | 2 +- + src/new_subid_range.c | 2 +- + 7 files changed, 110 insertions(+), 22 deletions(-) + delete mode 100644 libsubid/api.h + +diff --git a/libsubid/api.c b/libsubid/api.c +index 737e1c8b..a1b5bb3f 100644 +--- a/libsubid/api.c ++++ b/libsubid/api.c +@@ -36,7 +36,7 @@ + #include + #include "subordinateio.h" + #include "idmapping.h" +-#include "api.h" ++#include "subid.h" + + static + int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) +diff --git a/libsubid/api.h b/libsubid/api.h +deleted file mode 100644 +index 97b04e25..00000000 +--- a/libsubid/api.h ++++ /dev/null +@@ -1,17 +0,0 @@ +-#include "subid.h" +-#include +- +-int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); +-int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); +-void subid_free_ranges(struct subordinate_range **ranges, int count); +- +-int get_subuid_owners(uid_t uid, uid_t **owner); +-int get_subgid_owners(gid_t gid, uid_t **owner); +- +-/* range should be pre-allocated with owner and count filled in, start is +- * ignored, can be 0 */ +-bool grant_subuid_range(struct subordinate_range *range, bool reuse); +-bool grant_subgid_range(struct subordinate_range *range, bool reuse); +- +-bool ungrant_subuid_range(struct subordinate_range *range); +-bool ungrant_subgid_range(struct subordinate_range *range); +diff --git a/libsubid/subid.h b/libsubid/subid.h +index 2f27ad8a..769463f6 100644 +--- a/libsubid/subid.h ++++ b/libsubid/subid.h +@@ -21,5 +21,110 @@ enum subid_status { + SUBID_STATUS_ERROR = 3, + }; + ++/* ++ * get_subuid_ranges: return a list of UID ranges for a user ++ * ++ * @owner: username being queried ++ * @ranges: a pointer to a subordinate range ** in which the result will be ++ * returned. ++ * ++ * returns: number of ranges found, ir < 0 on error. ++ */ ++int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); ++ ++/* ++ * get_subgid_ranges: return a list of GID ranges for a user ++ * ++ * @owner: username being queried ++ * @ranges: a pointer to a subordinate range ** in which the result will be ++ * returned. ++ * ++ * returns: number of ranges found, ir < 0 on error. ++ */ ++int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); ++ ++/* ++ * subid_free_ranges: free an array of subordinate_ranges returned by either ++ * get_subuid_ranges() or get_subgid_ranges(). ++ * ++ * @ranges: the ranges to free ++ * @count: the number of ranges in @ranges ++ */ ++void subid_free_ranges(struct subordinate_range **ranges, int count); ++ ++/* ++ * get_subuid_owners: return a list of uids to which the given uid has been ++ * delegated. ++ * ++ * @uid: The subuid being queried ++ * @owners: a pointer to an array of uids into which the results are placed. ++ * The returned array must be freed by the caller. ++ * ++ * Returns the number of uids returned, or < 0 on error. ++ */ ++int get_subuid_owners(uid_t uid, uid_t **owner); ++ ++/* ++ * get_subgid_owners: return a list of uids to which the given gid has been ++ * delegated. ++ * ++ * @uid: The subgid being queried ++ * @owners: a pointer to an array of uids into which the results are placed. ++ * The returned array must be freed by the caller. ++ * ++ * Returns the number of uids returned, or < 0 on error. ++ */ ++int get_subgid_owners(gid_t gid, uid_t **owner); ++ ++/* ++ * grant_subuid_range: assign a subuid range to a user ++ * ++ * @range: pointer to a struct subordinate_range detailing the UID range ++ * to allocate. ->owner must be the username, and ->count must be ++ * filled in. ->start is ignored, and will contain the start ++ * of the newly allocated range, upon success. ++ * ++ * Returns true if the delegation succeeded, false otherwise. If true, ++ * then the range from (range->start, range->start + range->count) will ++ * be delegated to range->owner. ++ */ ++bool grant_subuid_range(struct subordinate_range *range, bool reuse); ++ ++/* ++ * grant_subsid_range: assign a subgid range to a user ++ * ++ * @range: pointer to a struct subordinate_range detailing the GID range ++ * to allocate. ->owner must be the username, and ->count must be ++ * filled in. ->start is ignored, and will contain the start ++ * of the newly allocated range, upon success. ++ * ++ * Returns true if the delegation succeeded, false otherwise. If true, ++ * then the range from (range->start, range->start + range->count) will ++ * be delegated to range->owner. ++ */ ++bool grant_subgid_range(struct subordinate_range *range, bool reuse); ++ ++/* ++ * ungrant_subuid_range: remove a subuid allocation. ++ * ++ * @range: pointer to a struct subordinate_range detailing the UID allocation ++ * to remove. ++ * ++ * Returns true if successful, false if it failed, for instance if the ++ * delegation did not exist. ++ */ ++bool ungrant_subuid_range(struct subordinate_range *range); ++ ++/* ++ * ungrant_subuid_range: remove a subgid allocation. ++ * ++ * @range: pointer to a struct subordinate_range detailing the GID allocation ++ * to remove. ++ * ++ * Returns true if successful, false if it failed, for instance if the ++ * delegation did not exist. ++ */ ++bool ungrant_subgid_range(struct subordinate_range *range); ++ + #define SUBID_NFIELDS 3 + #endif +diff --git a/src/free_subid_range.c b/src/free_subid_range.c +index de6bc58f..3701a262 100644 +--- a/src/free_subid_range.c ++++ b/src/free_subid_range.c +@@ -1,6 +1,6 @@ + #include + #include +-#include "api.h" ++#include "subid.h" + #include "stdlib.h" + #include "prototypes.h" + +diff --git a/src/get_subid_owners.c b/src/get_subid_owners.c +index a4385540..409e3fea 100644 +--- a/src/get_subid_owners.c ++++ b/src/get_subid_owners.c +@@ -1,5 +1,5 @@ + #include +-#include "api.h" ++#include "subid.h" + #include "stdlib.h" + #include "prototypes.h" + +diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c +index 440ef911..21b2c192 100644 +--- a/src/list_subid_ranges.c ++++ b/src/list_subid_ranges.c +@@ -1,5 +1,5 @@ + #include +-#include "api.h" ++#include "subid.h" + #include "stdlib.h" + #include "prototypes.h" + +diff --git a/src/new_subid_range.c b/src/new_subid_range.c +index 6d7b033b..dde196b3 100644 +--- a/src/new_subid_range.c ++++ b/src/new_subid_range.c +@@ -1,6 +1,6 @@ + #include + #include +-#include "api.h" ++#include "subid.h" + #include "stdlib.h" + #include "prototypes.h" + +-- +2.30.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 8d1f5ea..551de7a 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.8.1 -Release: 8%{?dist} +Release: 9%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -11,6 +11,11 @@ Source3: shadow-utils.login.defs Source4: shadow-bsd.txt Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt Source6: shadow-utils.HOME_MODE.xml + +### Globals ### +%global includesubiddir %{_includedir}/subid + +### Patches ### # Misc small changes - most probably non-upstreamable Patch0: shadow-4.6-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable @@ -62,6 +67,15 @@ Patch44: shadow-4.8.1-check-local-groups.patch Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch # https://github.com/shadow-maint/shadow/commit/df6ec1d1693c8c80c323b40d6fc82bb549363db3 Patch46: shadow-4.8.1-man-include-lastlog-file-caveat.patch +# https://github.com/shadow-maint/shadow/commit/0a7888b1fad613a052b988b01a71933b67296e68 +# https://github.com/shadow-maint/shadow/commit/607f1dd549cf9abc87af1cf29275f0d2d11eea29 +# https://github.com/shadow-maint/shadow/commit/b5fb1b38eea2fb0489ed088c82daf6700e72363e +# https://github.com/shadow-maint/shadow/commit/43a917cce54019799a8de037fd63780a2b640afc +Patch47: shadow-4.8.1-libsubid_creation.patch +# https://github.com/shadow-maint/shadow/commit/514c1328b6c90d817ae0a9f7addfb3c9a11a275a +# https://github.com/shadow-maint/shadow/commit/8492dee6632e340dee76eee895c3e30877bebf45 +# https://github.com/shadow-maint/shadow/commit/0f4347d1483191b2142546416a9eefe0c9459600 +Patch48: shadow-4.8.1-libsubid_nsswitch_support.patch License: BSD and GPLv2+ BuildRequires: make @@ -90,6 +104,23 @@ for all users. The useradd, userdel, and usermod commands are used for managing user accounts. The groupadd, groupdel, and groupmod commands are used for managing group accounts. + +### Subpackages ### +%package subid +Summary: A library to manage subordinate uid and gid ranges +License: BSD and GPLv2+ + +%description subid +Utility library that provides a way to manage subid ranges. + + +%package subid-devel +Summary: Development package for shadow-utils-subid +License: BSD and GPLv2+ + +%description subid-devel +Development files for shadow-utils-subid. + %prep %setup -q -n shadow-%{version} %patch0 -p1 -b .redhat @@ -116,6 +147,8 @@ are used for managing group accounts. %patch44 -p1 -b .check-local-groups %patch45 -p1 -b .commonio-force-lock-file-sync %patch46 -p1 -b .man-include-lastlog-file-caveat +%patch47 -p1 -b .libsubid_creation +%patch48 -p1 -b .libsubid_nsswitch_support iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -145,7 +178,7 @@ autoreconf --with-selinux \ --without-libcrack \ --without-libpam \ - --disable-shared \ + --enable-shared \ --with-group-name-max-length=32 %make_build @@ -220,6 +253,14 @@ for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do echo "%%lang($lang) $dir/man*/*" >> shadow.lang done +# Move header files to its own folder +echo $(ls) +mkdir -p $RPM_BUILD_ROOT/%{includesubiddir} +install -m 644 libsubid/subid.h $RPM_BUILD_ROOT/%{includesubiddir}/ + +# Remove .la files created by libsubid +rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la + %files -f shadow.lang %doc NEWS doc/HOWTO README %license gpl-2.0.txt shadow-bsd.txt @@ -268,7 +309,18 @@ done %{_mandir}/man8/vipw.8* %{_mandir}/man8/vigr.8* +%files subid +%{_libdir}/libsubid.so.* + +%files subid-devel +%{includesubiddir}/subid.h +%{_libdir}/libsubid.so + %changelog +* Fri Apr 16 2021 Iker Pedrosa - 2:4.8.1-9 +- libsubid: creation and nsswitch support +- Creation of subid and subid-devel subpackages + * Mon Mar 29 2021 Iker Pedrosa - 2:4.8.1-8 - man: include lastlog file caveat (#951564) - Upstream links to several patches From 9725f21893de6a073b8213be6ae0d8739a797a75 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 29 Mar 2021 12:29:20 +0200 Subject: [PATCH 011/118] - man: include lastlog file caveat (#951564) - Upstream links to several patches --- ....8.1-man-include-lastlog-file-caveat.patch | 33 +++++++++++++++++++ shadow-utils.spec | 19 ++++++++--- 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 shadow-4.8.1-man-include-lastlog-file-caveat.patch diff --git a/shadow-4.8.1-man-include-lastlog-file-caveat.patch b/shadow-4.8.1-man-include-lastlog-file-caveat.patch new file mode 100644 index 0000000..7be60c5 --- /dev/null +++ b/shadow-4.8.1-man-include-lastlog-file-caveat.patch @@ -0,0 +1,33 @@ +From df6ec1d1693c8c80c323b40d6fc82bb549363db3 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 29 Mar 2021 05:26:28 +0200 +Subject: [PATCH] man: include lastlog file caveat (#313) + +man/lastlog.8.xml: add another point to the caveats section regarding +the handling of the lastlog file by external tools. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=951564 +--- + man/lastlog.8.xml | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml +index fc096c8f..7e68282f 100644 +--- a/man/lastlog.8.xml ++++ b/man/lastlog.8.xml +@@ -233,5 +233,12 @@ + is no entries for users with UID between 170 and 800 lastlog will appear + to hang as it processes entries with UIDs 171-799). + ++ ++ Having high UIDs can create problems when handling the ++ /var/log/lastlog with external tools. Although the ++ actual file is sparse and does not use too much space, certain ++ applications are not designed to identify sparse files by default and may ++ require a specific option to handle them. ++ + + +-- +2.30.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 845b1f5..87d7138 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.8.1 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -15,17 +15,19 @@ Source6: shadow-utils.HOME_MODE.xml Patch0: shadow-4.6-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable Patch1: shadow-4.8-goodname.patch -# Docfix for newusers - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/7384865775b0203b9cf5337a047744f0a4555868 Patch2: shadow-4.1.5.1-info-parent-dir.patch # Misc SElinux related changes - upstreamability unknown Patch6: shadow-4.8-selinux.patch -# Syslog message change - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/a8361e741040cd926c9c93aac89820052531b1a3 Patch11: shadow-4.1.5.1-logmsg.patch # SElinux related - upstreamability unknown Patch14: shadow-4.1.5.1-default-range.patch -# Misc manual page changes - only some of them could be upstreamed +# Misc manual page changes +# https://github.com/shadow-maint/shadow/commit/c0818ab01d1896784245eedec9495e1e6e0260af +# Changes in man/groupmems.8.xml, man/ja/man5/login.defs.5 and man/login.defs.5.xml not upstreamed Patch15: shadow-4.8.1-manfix.patch -# Userdel usage message change - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/f4cbf38ad7801bab6fae50e9b5a2effc3c48a1ea Patch17: shadow-4.1.5.1-userdel-helpfix.patch # Date parsing improvement - could be upstreamed Patch19: shadow-4.2.1-date-parsing.patch @@ -58,6 +60,8 @@ Patch43: shadow-4.8.1-useradd-man-clarification.patch Patch44: shadow-4.8.1-check-local-groups.patch # https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch +# https://github.com/shadow-maint/shadow/commit/df6ec1d1693c8c80c323b40d6fc82bb549363db3 +Patch46: shadow-4.8.1-man-include-lastlog-file-caveat.patch License: BSD and GPLv2+ BuildRequires: gcc @@ -110,6 +114,7 @@ are used for managing group accounts. %patch43 -p1 -b .useradd-man-clarification %patch44 -p1 -b .check-local-groups %patch45 -p1 -b .commonio-force-lock-file-sync +%patch46 -p1 -b .man-include-lastlog-file-caveat iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -265,6 +270,10 @@ done %{_mandir}/man8/vigr.8* %changelog +* Mon Apr 26 2021 Iker Pedrosa - 2:4.8.1-6 +- man: include lastlog file caveat (#951564) +- Upstream links to several patches + * Mon Nov 16 2020 Iker Pedrosa - 2:4.8.1-5 - commonio: force lock file sync (#1862056) - spec: add Provides keyword From 1ec508822531eeeac9ec6ddd1f18ad24cfdc98ba Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 6 May 2021 11:41:05 +0200 Subject: [PATCH 012/118] - man: mention NSS in new[ug]idmap manpages - libsubid: move development header to shadow folder --- ...w-4.8.1-man-mention-nss-in-newuidmap.patch | 44 +++++++++++++++++++ shadow-utils.spec | 11 ++++- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 shadow-4.8.1-man-mention-nss-in-newuidmap.patch diff --git a/shadow-4.8.1-man-mention-nss-in-newuidmap.patch b/shadow-4.8.1-man-mention-nss-in-newuidmap.patch new file mode 100644 index 0000000..e26cfa7 --- /dev/null +++ b/shadow-4.8.1-man-mention-nss-in-newuidmap.patch @@ -0,0 +1,44 @@ +From 186b1b7ac1a68d0fcc618a22da1a99232b420911 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Tue, 4 May 2021 14:39:26 -0500 +Subject: [PATCH] manpages: mention NSS in new[ug]idmap manpages + +Closes #328 + +Signed-off-by: Serge Hallyn +--- + man/newgidmap.1.xml | 3 ++- + man/newuidmap.1.xml | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml +index 71b03e56..76fc1e30 100644 +--- a/man/newgidmap.1.xml ++++ b/man/newgidmap.1.xml +@@ -88,7 +88,8 @@ + DESCRIPTION + + The newgidmap sets /proc/[pid]/gid_map based on its +- command line arguments and the gids allowed in /etc/subgid. ++ command line arguments and the gids allowed (either in /etc/subgid or ++ through the configured NSS subid module). + Note that the root user is not exempted from the requirement for a valid + /etc/subgid entry. + +diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml +index a6f1f085..44eca50a 100644 +--- a/man/newuidmap.1.xml ++++ b/man/newuidmap.1.xml +@@ -88,7 +88,8 @@ + DESCRIPTION + + The newuidmap sets /proc/[pid]/uid_map based on its +- command line arguments and the uids allowed in /etc/subuid. ++ command line arguments and the uids allowed (either in /etc/subuid or ++ through the configured NSS subid module). + Note that the root user is not exempted from the requirement for a valid + /etc/subuid entry. + +-- +2.30.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 551de7a..3a8e510 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.8.1 -Release: 9%{?dist} +Release: 10%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -13,7 +13,7 @@ Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt Source6: shadow-utils.HOME_MODE.xml ### Globals ### -%global includesubiddir %{_includedir}/subid +%global includesubiddir %{_includedir}/shadow ### Patches ### # Misc small changes - most probably non-upstreamable @@ -76,6 +76,8 @@ Patch47: shadow-4.8.1-libsubid_creation.patch # https://github.com/shadow-maint/shadow/commit/8492dee6632e340dee76eee895c3e30877bebf45 # https://github.com/shadow-maint/shadow/commit/0f4347d1483191b2142546416a9eefe0c9459600 Patch48: shadow-4.8.1-libsubid_nsswitch_support.patch +# https://github.com/shadow-maint/shadow/commit/186b1b7ac1a68d0fcc618a22da1a99232b420911 +Patch49: shadow-4.8.1-man-mention-nss-in-newuidmap.patch License: BSD and GPLv2+ BuildRequires: make @@ -149,6 +151,7 @@ Development files for shadow-utils-subid. %patch46 -p1 -b .man-include-lastlog-file-caveat %patch47 -p1 -b .libsubid_creation %patch48 -p1 -b .libsubid_nsswitch_support +%patch49 -p1 -b .man-mention-nss-in-newuidmap iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -317,6 +320,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Thu May 6 2021 Iker Pedrosa - 2:4.8.1-10 +- man: mention NSS in new[ug]idmap manpages +- libsubid: move development header to shadow folder + * Fri Apr 16 2021 Iker Pedrosa - 2:4.8.1-9 - libsubid: creation and nsswitch support - Creation of subid and subid-devel subpackages From cbc60528c36bf3d3d802813d7e1ac04b66b14a69 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 21 Jun 2021 13:24:36 +0200 Subject: [PATCH 013/118] libsubid improvements - libsubid: don't print error messages on stderr by default - libsubid: libsubid_init return false if out of memory - useradd: fix SUB_UID_COUNT=0 - libsubid: don't return owner in list_owner_ranges API call - libsubid: libsubid_init don't print messages on error - libsubid: fix newusers when nss provides subids - man: clarify subid delegation - libsubid: make shadow_logfd not extern --- ...bid_fix_newusers_nss_provides_subids.patch | 151 + ...bsubid_init_not_print_error_messages.patch | 40 + shadow-4.8.1-libsubid_init_return_false.patch | 37 + ...4.8.1-libsubid_make_logfd_not_extern.patch | 41 + ....1-libsubid_not_print_error_messages.patch | 2443 +++++++++++++++++ ....1-libsubid_simplify_ranges_variable.patch | 264 ++ ...w-4.8.1-man_clarify_subid_delegation.patch | 246 ++ shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch | 44 + shadow-utils.spec | 37 +- 9 files changed, 3302 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch create mode 100644 shadow-4.8.1-libsubid_init_not_print_error_messages.patch create mode 100644 shadow-4.8.1-libsubid_init_return_false.patch create mode 100644 shadow-4.8.1-libsubid_make_logfd_not_extern.patch create mode 100644 shadow-4.8.1-libsubid_not_print_error_messages.patch create mode 100644 shadow-4.8.1-libsubid_simplify_ranges_variable.patch create mode 100644 shadow-4.8.1-man_clarify_subid_delegation.patch create mode 100644 shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch diff --git a/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch b/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch new file mode 100644 index 0000000..c0ca905 --- /dev/null +++ b/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch @@ -0,0 +1,151 @@ +diff -up shadow-4.8.1/lib/nss.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/nss.c +--- shadow-4.8.1/lib/nss.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.772741048 +0200 ++++ shadow-4.8.1/lib/nss.c 2021-05-25 09:37:14.782741188 +0200 +@@ -116,14 +116,6 @@ void nss_init(char *nsswitch_path) { + subid_nss = NULL; + goto done; + } +- subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); +- if (!subid_nss->has_any_range) { +- fprintf(shadow_logfd, "%s did not provide @has_any_range@\n", libname); +- dlclose(h); +- free(subid_nss); +- subid_nss = NULL; +- goto done; +- } + subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); + if (!subid_nss->find_subid_owners) { + fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname); +diff -up shadow-4.8.1/lib/prototypes.h.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/prototypes.h +--- shadow-4.8.1/lib/prototypes.h.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 ++++ shadow-4.8.1/lib/prototypes.h 2021-05-25 09:37:14.782741188 +0200 +@@ -279,18 +279,6 @@ extern bool nss_is_initialized(); + + struct subid_nss_ops { + /* +- * nss_has_any_range: does a user own any subid range +- * +- * @owner: username +- * @idtype: subuid or subgid +- * @result: true if a subid allocation was found for @owner +- * +- * returns success if the module was able to determine an answer (true or false), +- * else an error status. +- */ +- enum subid_status (*has_any_range)(const char *owner, enum subid_type idtype, bool *result); +- +- /* + * nss_has_range: does a user own a given subid range + * + * @owner: username +diff -up shadow-4.8.1/lib/subordinateio.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/subordinateio.c +--- shadow-4.8.1/lib/subordinateio.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 ++++ shadow-4.8.1/lib/subordinateio.c 2021-05-25 09:37:14.782741188 +0200 +@@ -598,19 +598,8 @@ int sub_uid_open (int mode) + return commonio_open (&subordinate_uid_db, mode); + } + +-bool sub_uid_assigned(const char *owner) ++bool local_sub_uid_assigned(const char *owner) + { +- struct subid_nss_ops *h; +- bool found; +- enum subid_status status; +- h = get_subid_nss_handle(); +- if (h) { +- status = h->has_any_range(owner, ID_TYPE_UID, &found); +- if (status == SUBID_STATUS_SUCCESS && found) +- return true; +- return false; +- } +- + return range_exists (&subordinate_uid_db, owner); + } + +@@ -720,18 +709,8 @@ bool have_sub_gids(const char *owner, gi + return have_range(&subordinate_gid_db, owner, start, count); + } + +-bool sub_gid_assigned(const char *owner) ++bool local_sub_gid_assigned(const char *owner) + { +- struct subid_nss_ops *h; +- bool found; +- enum subid_status status; +- h = get_subid_nss_handle(); +- if (h) { +- status = h->has_any_range(owner, ID_TYPE_GID, &found); +- if (status == SUBID_STATUS_SUCCESS && found) +- return true; +- return false; +- } + return range_exists (&subordinate_gid_db, owner); + } + +diff -up shadow-4.8.1/lib/subordinateio.h.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/subordinateio.h +--- shadow-4.8.1/lib/subordinateio.h.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 ++++ shadow-4.8.1/lib/subordinateio.h 2021-05-25 09:37:14.782741188 +0200 +@@ -16,7 +16,7 @@ + extern int sub_uid_close(void); + extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); + extern bool sub_uid_file_present (void); +-extern bool sub_uid_assigned(const char *owner); ++extern bool local_sub_uid_assigned(const char *owner); + extern int sub_uid_lock (void); + extern int sub_uid_setdbname (const char *filename); + extern /*@observer@*/const char *sub_uid_dbname (void); +@@ -34,7 +34,7 @@ extern void free_subordinate_ranges(stru + extern int sub_gid_close(void); + extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); + extern bool sub_gid_file_present (void); +-extern bool sub_gid_assigned(const char *owner); ++extern bool local_sub_gid_assigned(const char *owner); + extern int sub_gid_lock (void); + extern int sub_gid_setdbname (const char *filename); + extern /*@observer@*/const char *sub_gid_dbname (void); +diff -up shadow-4.8.1/src/newusers.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/src/newusers.c +--- shadow-4.8.1/src/newusers.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.776741104 +0200 ++++ shadow-4.8.1/src/newusers.c 2021-05-25 09:37:25.955897160 +0200 +@@ -1021,6 +1021,24 @@ static void close_files (void) + #endif /* ENABLE_SUBIDS */ + } + ++static bool want_subuids(void) ++{ ++ if (get_subid_nss_handle() != NULL) ++ return false; ++ if (getdef_ulong ("SUB_UID_COUNT", 65536) == 0) ++ return false; ++ return true; ++} ++ ++static bool want_subgids(void) ++{ ++ if (get_subid_nss_handle() != NULL) ++ return false; ++ if (getdef_ulong ("SUB_GID_COUNT", 65536) == 0) ++ return false; ++ return true; ++} ++ + int main (int argc, char **argv) + { + char buf[BUFSIZ]; +@@ -1250,7 +1268,7 @@ int main (int argc, char **argv) + /* + * Add subordinate uids if the user does not have them. + */ +- if (is_sub_uid && !sub_uid_assigned(fields[0])) { ++ if (is_sub_uid && want_subuids() && !local_sub_uid_assigned(fields[0])) { + uid_t sub_uid_start = 0; + unsigned long sub_uid_count = 0; + if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) { +@@ -1270,7 +1288,7 @@ int main (int argc, char **argv) + /* + * Add subordinate gids if the user does not have them. + */ +- if (is_sub_gid && !sub_gid_assigned(fields[0])) { ++ if (is_sub_gid && want_subgids() && !local_sub_gid_assigned(fields[0])) { + gid_t sub_gid_start = 0; + unsigned long sub_gid_count = 0; + if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) { diff --git a/shadow-4.8.1-libsubid_init_not_print_error_messages.patch b/shadow-4.8.1-libsubid_init_not_print_error_messages.patch new file mode 100644 index 0000000..820a043 --- /dev/null +++ b/shadow-4.8.1-libsubid_init_not_print_error_messages.patch @@ -0,0 +1,40 @@ +From b0e86b959fe5c086ffb5e7eaf3c1b1e9219411e9 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sun, 23 May 2021 08:03:10 -0500 +Subject: [PATCH] libsubid_init: don't print messages on error + +Signed-off-by: Serge Hallyn +--- + libsubid/api.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/libsubid/api.c b/libsubid/api.c +index c4848142..b477b271 100644 +--- a/libsubid/api.c ++++ b/libsubid/api.c +@@ -46,12 +46,10 @@ bool libsubid_init(const char *progname, FILE * logfd) + { + if (progname) { + progname = strdup(progname); +- if (progname) { ++ if (progname) + Prog = progname; +- } else { +- fprintf(stderr, "Out of memory"); ++ else + return false; +- } + } + + if (logfd) { +@@ -60,7 +58,6 @@ bool libsubid_init(const char *progname, FILE * logfd) + } + shadow_logfd = fopen("/dev/null", "w"); + if (!shadow_logfd) { +- fprintf(stderr, "ERROR opening /dev/null for error messages. Using stderr."); + shadow_logfd = stderr; + return false; + } +-- +2.30.2 + diff --git a/shadow-4.8.1-libsubid_init_return_false.patch b/shadow-4.8.1-libsubid_init_return_false.patch new file mode 100644 index 0000000..4d02d0d --- /dev/null +++ b/shadow-4.8.1-libsubid_init_return_false.patch @@ -0,0 +1,37 @@ +From e34f49c1966fcaa9390a544a0136ec189a3c870e Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Mon, 17 May 2021 08:48:03 -0500 +Subject: [PATCH] libsubid_init: return false if out of memory + +The rest of the run isn't likely to get much better, is it? + +Thanks to Alexey for pointing this out. + +Signed-off-by: Serge Hallyn +Cc: Alexey Tikhonov +--- + libsubid/api.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/libsubid/api.c b/libsubid/api.c +index 8ca09859..8618e500 100644 +--- a/libsubid/api.c ++++ b/libsubid/api.c +@@ -46,10 +46,12 @@ bool libsubid_init(const char *progname, FILE * logfd) + { + if (progname) { + progname = strdup(progname); +- if (progname) ++ if (progname) { + Prog = progname; +- else ++ } else { + fprintf(stderr, "Out of memory"); ++ return false; ++ } + } + + if (logfd) { +-- +2.30.2 + diff --git a/shadow-4.8.1-libsubid_make_logfd_not_extern.patch b/shadow-4.8.1-libsubid_make_logfd_not_extern.patch new file mode 100644 index 0000000..2994442 --- /dev/null +++ b/shadow-4.8.1-libsubid_make_logfd_not_extern.patch @@ -0,0 +1,41 @@ +From 1d767fb779d7b203ad609540d1dc605cf62d1050 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Fri, 28 May 2021 22:02:16 -0500 +Subject: [PATCH] libsubid/api.c: make shadow_logfd not extern + +Closes #346 + +Also #include stdio.h + +Signed-off-by: Serge Hallyn +--- + libsubid/api.c | 2 +- + libsubid/subid.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libsubid/api.c b/libsubid/api.c +index b477b271..a7b904d0 100644 +--- a/libsubid/api.c ++++ b/libsubid/api.c +@@ -40,7 +40,7 @@ + #include "subid.h" + + const char *Prog = "(libsubid)"; +-extern FILE * shadow_logfd; ++FILE *shadow_logfd; + + bool libsubid_init(const char *progname, FILE * logfd) + { +diff --git a/libsubid/subid.h b/libsubid/subid.h +index 5fef2572..eabafe4d 100644 +--- a/libsubid/subid.h ++++ b/libsubid/subid.h +@@ -1,4 +1,5 @@ + #include ++#include + #include + + #ifndef SUBID_RANGE_DEFINED +-- +2.31.1 + diff --git a/shadow-4.8.1-libsubid_not_print_error_messages.patch b/shadow-4.8.1-libsubid_not_print_error_messages.patch new file mode 100644 index 0000000..3cef98c --- /dev/null +++ b/shadow-4.8.1-libsubid_not_print_error_messages.patch @@ -0,0 +1,2443 @@ +diff -up shadow-4.8.1/lib/commonio.c.libsubid_not_print_error_messages shadow-4.8.1/lib/commonio.c +--- shadow-4.8.1/lib/commonio.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.919268967 +0200 ++++ shadow-4.8.1/lib/commonio.c 2021-05-24 13:04:19.928269091 +0200 +@@ -144,7 +144,7 @@ static int do_lock_file (const char *fil + fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600); + if (-1 == fd) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s: %s\n", + Prog, file, strerror (errno)); + } +@@ -156,7 +156,7 @@ static int do_lock_file (const char *fil + len = (ssize_t) strlen (buf) + 1; + if (write (fd, buf, (size_t) len) != len) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s file write error: %s\n", + Prog, file, strerror (errno)); + } +@@ -166,7 +166,7 @@ static int do_lock_file (const char *fil + } + if (fdatasync (fd) == -1) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s file sync error: %s\n", + Prog, file, strerror (errno)); + } +@@ -179,7 +179,7 @@ static int do_lock_file (const char *fil + if (link (file, lock) == 0) { + retval = check_link_count (file); + if ((0==retval) && log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s: lock file already used\n", + Prog, file); + } +@@ -190,7 +190,7 @@ static int do_lock_file (const char *fil + fd = open (lock, O_RDWR); + if (-1 == fd) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s: %s\n", + Prog, lock, strerror (errno)); + } +@@ -202,7 +202,7 @@ static int do_lock_file (const char *fil + close (fd); + if (len <= 0) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: existing lock file %s without a PID\n", + Prog, lock); + } +@@ -213,7 +213,7 @@ static int do_lock_file (const char *fil + buf[len] = '\0'; + if (get_pid (buf, &pid) == 0) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: existing lock file %s with an invalid PID '%s'\n", + Prog, lock, buf); + } +@@ -223,7 +223,7 @@ static int do_lock_file (const char *fil + } + if (kill (pid, 0) == 0) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: lock %s already used by PID %lu\n", + Prog, lock, (unsigned long) pid); + } +@@ -233,7 +233,7 @@ static int do_lock_file (const char *fil + } + if (unlink (lock) != 0) { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: cannot get lock %s: %s\n", + Prog, lock, strerror (errno)); + } +@@ -245,13 +245,13 @@ static int do_lock_file (const char *fil + if (link (file, lock) == 0) { + retval = check_link_count (file); + if ((0==retval) && log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: %s: lock file already used\n", + Prog, file); + } + } else { + if (log) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: cannot get lock %s: %s\n", + Prog, lock, strerror (errno)); + } +@@ -442,7 +442,7 @@ int commonio_lock (struct commonio_db *d + if (0 == lock_count) { + if (lckpwdf () == -1) { + if (geteuid () != 0) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + "%s: Permission denied.\n", + Prog); + } +@@ -478,7 +478,7 @@ int commonio_lock (struct commonio_db *d + } + /* no unnecessary retries on "permission denied" errors */ + if (geteuid () != 0) { +- (void) fprintf (stderr, "%s: Permission denied.\n", ++ (void) fprintf (shadow_logfd, "%s: Permission denied.\n", + Prog); + return 0; + } +@@ -1109,7 +1109,7 @@ int commonio_update (struct commonio_db + p = find_entry_by_name (db, db->ops->getname (eptr)); + if (NULL != p) { + if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) { +- fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename); ++ fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename); + db->ops->free (nentry); + return 0; + } +@@ -1214,7 +1214,7 @@ int commonio_remove (struct commonio_db + return 0; + } + if (next_entry_by_name (db, p->next, name) != NULL) { +- fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename); ++ fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename); + return 0; + } + +diff -up shadow-4.8.1/lib/encrypt.c.libsubid_not_print_error_messages shadow-4.8.1/lib/encrypt.c +--- shadow-4.8.1/lib/encrypt.c.libsubid_not_print_error_messages 2019-12-01 18:02:43.000000000 +0100 ++++ shadow-4.8.1/lib/encrypt.c 2021-05-24 13:04:19.928269091 +0200 +@@ -81,7 +81,7 @@ + method = &nummethod[0]; + } + } +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("crypt method not supported by libcrypt? (%s)\n"), + method); + exit (EXIT_FAILURE); +diff -up shadow-4.8.1/lib/getdef.c.libsubid_not_print_error_messages shadow-4.8.1/lib/getdef.c +--- shadow-4.8.1/lib/getdef.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.915268912 +0200 ++++ shadow-4.8.1/lib/getdef.c 2021-05-24 13:04:19.928269091 +0200 +@@ -250,7 +250,7 @@ int getdef_num (const char *item, int df + if ( (getlong (d->value, &val) == 0) + || (val > INT_MAX) + || (val < INT_MIN)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("configuration error - cannot parse %s value: '%s'"), + item, d->value); + return dflt; +@@ -285,7 +285,7 @@ unsigned int getdef_unum (const char *it + if ( (getlong (d->value, &val) == 0) + || (val < 0) + || (val > INT_MAX)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("configuration error - cannot parse %s value: '%s'"), + item, d->value); + return dflt; +@@ -318,7 +318,7 @@ long getdef_long (const char *item, long + } + + if (getlong (d->value, &val) == 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("configuration error - cannot parse %s value: '%s'"), + item, d->value); + return dflt; +@@ -351,7 +351,7 @@ unsigned long getdef_ulong (const char * + + if (getulong (d->value, &val) == 0) { + /* FIXME: we should have a getulong */ +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("configuration error - cannot parse %s value: '%s'"), + item, d->value); + return dflt; +@@ -389,7 +389,7 @@ int putdef_str (const char *name, const + cp = strdup (value); + if (NULL == cp) { + (void) fputs (_("Could not allocate space for config info.\n"), +- stderr); ++ shadow_logfd); + SYSLOG ((LOG_ERR, "could not allocate space for config info")); + return -1; + } +@@ -434,7 +434,7 @@ static /*@observer@*/ /*@null@*/struct i + goto out; + } + } +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("configuration error - unknown item '%s' (notify administrator)\n"), + name); + SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name)); +diff -up shadow-4.8.1/libmisc/addgrps.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/addgrps.c +--- shadow-4.8.1/libmisc/addgrps.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/addgrps.c 2021-05-24 13:04:19.929269104 +0200 +@@ -93,7 +93,7 @@ int add_groups (const char *list) + + grp = getgrnam (token); /* local, no need for xgetgrnam */ + if (NULL == grp) { +- fprintf (stderr, _("Warning: unknown group %s\n"), ++ fprintf (shadow_logfd, _("Warning: unknown group %s\n"), + token); + continue; + } +@@ -105,7 +105,7 @@ int add_groups (const char *list) + } + + if (ngroups >= sysconf (_SC_NGROUPS_MAX)) { +- fputs (_("Warning: too many groups\n"), stderr); ++ fputs (_("Warning: too many groups\n"), shadow_logfd); + break; + } + tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T)); +diff -up shadow-4.8.1/libmisc/audit_help.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/audit_help.c +--- shadow-4.8.1/libmisc/audit_help.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 ++++ shadow-4.8.1/libmisc/audit_help.c 2021-05-24 13:04:19.929269104 +0200 +@@ -59,7 +59,7 @@ void audit_help_open (void) + return; + } + (void) fputs (_("Cannot open audit interface - aborting.\n"), +- stderr); ++ shadow_logfd); + exit (EXIT_FAILURE); + } + } +diff -up shadow-4.8.1/libmisc/chowntty.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/chowntty.c +--- shadow-4.8.1/libmisc/chowntty.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/chowntty.c 2021-05-24 13:04:19.929269104 +0200 +@@ -75,7 +75,7 @@ void chown_tty (const struct passwd *inf + || (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) { + int err = errno; + +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Unable to change owner or mode of tty stdin: %s"), + strerror (err)); + SYSLOG ((LOG_WARN, +diff -up shadow-4.8.1/libmisc/cleanup_group.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/cleanup_group.c +--- shadow-4.8.1/libmisc/cleanup_group.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 ++++ shadow-4.8.1/libmisc/cleanup_group.c 2021-05-24 13:04:19.929269104 +0200 +@@ -203,7 +203,7 @@ void cleanup_report_del_group_gshadow (v + void cleanup_unlock_group (unused void *arg) + { + if (gr_unlock () == 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); +@@ -223,7 +223,7 @@ void cleanup_unlock_group (unused void * + void cleanup_unlock_gshadow (unused void *arg) + { + if (sgr_unlock () == 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); +diff -up shadow-4.8.1/libmisc/cleanup_user.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/cleanup_user.c +--- shadow-4.8.1/libmisc/cleanup_user.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 ++++ shadow-4.8.1/libmisc/cleanup_user.c 2021-05-24 13:04:19.929269104 +0200 +@@ -120,7 +120,7 @@ void cleanup_report_add_user_shadow (voi + void cleanup_unlock_passwd (unused void *arg) + { + if (pw_unlock () == 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); +@@ -139,7 +139,7 @@ void cleanup_unlock_passwd (unused void + void cleanup_unlock_shadow (unused void *arg) + { + if (spw_unlock () == 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); +diff -up shadow-4.8.1/libmisc/copydir.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/copydir.c +--- shadow-4.8.1/libmisc/copydir.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.898268677 +0200 ++++ shadow-4.8.1/libmisc/copydir.c 2021-05-24 13:04:19.929269104 +0200 +@@ -125,11 +125,11 @@ static void error_acl (struct error_cont + } + + va_start (ap, fmt); +- (void) fprintf (stderr, _("%s: "), Prog); +- if (vfprintf (stderr, fmt, ap) != 0) { +- (void) fputs (_(": "), stderr); ++ (void) fprintf (shadow_logfd, _("%s: "), Prog); ++ if (vfprintf (shadow_logfd, fmt, ap) != 0) { ++ (void) fputs (_(": "), shadow_logfd); + } +- (void) fprintf (stderr, "%s\n", strerror (errno)); ++ (void) fprintf (shadow_logfd, "%s\n", strerror (errno)); + va_end (ap); + } + +@@ -248,7 +248,7 @@ int copy_tree (const char *src_root, con + } + + if (!S_ISDIR (sb.st_mode)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + "%s: %s is not a directory", + Prog, src_root); + return -1; +diff -up shadow-4.8.1/libmisc/env.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/env.c +--- shadow-4.8.1/libmisc/env.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/env.c 2021-05-24 13:04:19.929269104 +0200 +@@ -171,7 +171,7 @@ void addenv (const char *string, /*@null + } + newenvp = __newenvp; + } else { +- (void) fputs (_("Environment overflow\n"), stderr); ++ (void) fputs (_("Environment overflow\n"), shadow_logfd); + newenvc--; + free (newenvp[newenvc]); + } +diff -up shadow-4.8.1/libmisc/find_new_gid.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_gid.c +--- shadow-4.8.1/libmisc/find_new_gid.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.914268898 +0200 ++++ shadow-4.8.1/libmisc/find_new_gid.c 2021-05-24 13:04:19.929269104 +0200 +@@ -74,7 +74,7 @@ static int get_ranges (bool sys_group, g + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: SYS_GID_MIN (%lu), " + "GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), + Prog, (unsigned long) *min_id, +@@ -104,7 +104,7 @@ static int get_ranges (bool sys_group, g + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: GID_MIN (%lu), " + "GID_MAX (%lu)\n"), + Prog, (unsigned long) *min_id, +@@ -220,7 +220,7 @@ int find_new_gid (bool sys_group, + * more likely to want to stop and address the + * issue. + */ +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Encountered error attempting to use " + "preferred GID: %s\n"), + Prog, strerror (result)); +@@ -250,7 +250,7 @@ int find_new_gid (bool sys_group, + /* Create an array to hold all of the discovered GIDs */ + used_gids = malloc (sizeof (bool) * (gid_max +1)); + if (NULL == used_gids) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to allocate memory: %s\n"), + Prog, strerror (errno)); + return -1; +@@ -330,7 +330,7 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique system GID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -373,7 +373,7 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique system GID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -433,7 +433,7 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique GID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -476,7 +476,7 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique GID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -495,7 +495,7 @@ int find_new_gid (bool sys_group, + } + + /* The code reached here and found no available IDs in the range */ +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique GID (no more available GIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available GIDs on the system")); +diff -up shadow-4.8.1/libmisc/find_new_sub_gids.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_sub_gids.c +--- shadow-4.8.1/libmisc/find_new_sub_gids.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/find_new_sub_gids.c 2021-05-24 13:04:19.930269118 +0200 +@@ -61,7 +61,7 @@ int find_new_sub_gids (const char *owner + count = getdef_ulong ("SUB_GID_COUNT", 65536); + + if (min > max || count >= max || (min + count - 1) > max) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: SUB_GID_MIN (%lu)," + " SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"), + Prog, min, max, count); +@@ -70,7 +70,7 @@ int find_new_sub_gids (const char *owner + + start = sub_gid_find_free_range(min, max, count); + if (start == (gid_t)-1) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique subordinate GID range\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system")); +diff -up shadow-4.8.1/libmisc/find_new_sub_uids.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_sub_uids.c +--- shadow-4.8.1/libmisc/find_new_sub_uids.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/find_new_sub_uids.c 2021-05-24 13:04:19.930269118 +0200 +@@ -61,7 +61,7 @@ int find_new_sub_uids (const char *owner + count = getdef_ulong ("SUB_UID_COUNT", 65536); + + if (min > max || count >= max || (min + count - 1) > max) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: SUB_UID_MIN (%lu)," + " SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"), + Prog, min, max, count); +@@ -70,7 +70,7 @@ int find_new_sub_uids (const char *owner + + start = sub_uid_find_free_range(min, max, count); + if (start == (uid_t)-1) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique subordinate UID range\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system")); +diff -up shadow-4.8.1/libmisc/find_new_uid.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_uid.c +--- shadow-4.8.1/libmisc/find_new_uid.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.914268898 +0200 ++++ shadow-4.8.1/libmisc/find_new_uid.c 2021-05-24 13:04:19.930269118 +0200 +@@ -74,7 +74,7 @@ static int get_ranges (bool sys_user, ui + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: SYS_UID_MIN (%lu), " + "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), + Prog, (unsigned long) *min_id, +@@ -104,7 +104,7 @@ static int get_ranges (bool sys_user, ui + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: Invalid configuration: UID_MIN (%lu), " + "UID_MAX (%lu)\n"), + Prog, (unsigned long) *min_id, +@@ -220,7 +220,7 @@ int find_new_uid(bool sys_user, + * more likely to want to stop and address the + * issue. + */ +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Encountered error attempting to use " + "preferred UID: %s\n"), + Prog, strerror (result)); +@@ -250,7 +250,7 @@ int find_new_uid(bool sys_user, + /* Create an array to hold all of the discovered UIDs */ + used_uids = malloc (sizeof (bool) * (uid_max +1)); + if (NULL == used_uids) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: failed to allocate memory: %s\n"), + Prog, strerror (errno)); + return -1; +@@ -330,7 +330,7 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique system UID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -373,7 +373,7 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique system UID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -433,7 +433,7 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique UID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -476,7 +476,7 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique UID (%s). " + "Suppressing additional messages.\n"), + Prog, strerror (result)); +@@ -495,7 +495,7 @@ int find_new_uid(bool sys_user, + } + + /* The code reached here and found no available IDs in the range */ +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Can't get unique UID (no more available UIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available UIDs on the system")); +diff -up shadow-4.8.1/libmisc/gettime.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/gettime.c +--- shadow-4.8.1/libmisc/gettime.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/gettime.c 2021-05-24 13:04:19.930269118 +0200 +@@ -61,23 +61,23 @@ + epoch = strtoull (source_date_epoch, &endptr, 10); + if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) + || (errno != 0 && epoch == 0)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n"), + strerror(errno)); + } else if (endptr == source_date_epoch) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n"), + endptr); + } else if (*endptr != '\0') { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n"), + endptr); + } else if (epoch > ULONG_MAX) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu\n"), + ULONG_MAX, epoch); + } else if (epoch > fallback) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to the current time (%lu) but was found to be: %llu\n"), + fallback, epoch); + } else { +diff -up shadow-4.8.1/libmisc/idmapping.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/idmapping.c +--- shadow-4.8.1/libmisc/idmapping.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/idmapping.c 2021-05-24 13:20:06.679312187 +0200 +@@ -47,19 +47,19 @@ struct map_range *get_map_ranges(int ran + int idx, argidx; + + if (ranges < 0 || argc < 0) { +- fprintf(stderr, "%s: error calculating number of arguments\n", Prog); ++ fprintf(shadow_logfd, "%s: error calculating number of arguments\n", Prog); + return NULL; + } + + if (ranges != ((argc + 2) / 3)) { +- fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); ++ fprintf(shadow_logfd, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); + return NULL; + } + + if ((ranges * 3) > argc) { +- fprintf(stderr, "ranges: %u argc: %d\n", ++ fprintf(shadow_logfd, "ranges: %u argc: %d\n", + ranges, argc); +- fprintf(stderr, ++ fprintf(shadow_logfd, + _( "%s: Not enough arguments to form %u mappings\n"), + Prog, ranges); + return NULL; +@@ -67,7 +67,7 @@ struct map_range *get_map_ranges(int ran + + mappings = calloc(ranges, sizeof(*mappings)); + if (!mappings) { +- fprintf(stderr, _( "%s: Memory allocation failure\n"), ++ fprintf(shadow_logfd, _( "%s: Memory allocation failure\n"), + Prog); + exit(EXIT_FAILURE); + } +@@ -88,24 +88,24 @@ struct map_range *get_map_ranges(int ran + return NULL; + } + if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) { +- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); + exit(EXIT_FAILURE); + } + if (mapping->upper > UINT_MAX || + mapping->lower > UINT_MAX || + mapping->count > UINT_MAX) { +- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); + exit(EXIT_FAILURE); + } + if (mapping->lower + mapping->count > UINT_MAX || + mapping->upper + mapping->count > UINT_MAX) { +- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); + exit(EXIT_FAILURE); + } + if (mapping->lower + mapping->count < mapping->lower || + mapping->upper + mapping->count < mapping->upper) { + /* this one really shouldn't be possible given previous checks */ +- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); + exit(EXIT_FAILURE); + } + } +@@ -157,19 +157,19 @@ void write_mapping(int proc_dir_fd, int + } else if (strcmp(map_file, "gid_map") == 0) { + cap = CAP_SETGID; + } else { +- fprintf(stderr, _("%s: Invalid map file %s specified\n"), Prog, map_file); ++ fprintf(shadow_logfd, _("%s: Invalid map file %s specified\n"), Prog, map_file); + exit(EXIT_FAILURE); + } + + /* Align setuid- and fscaps-based new{g,u}idmap behavior. */ + if (geteuid() == 0 && geteuid() != ruid) { + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { +- fprintf(stderr, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); ++ fprintf(shadow_logfd, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); + exit(EXIT_FAILURE); + } + + if (seteuid(ruid) < 0) { +- fprintf(stderr, _("%s: Could not seteuid to %d\n"), Prog, ruid); ++ fprintf(shadow_logfd, _("%s: Could not seteuid to %d\n"), Prog, ruid); + exit(EXIT_FAILURE); + } + } +@@ -179,7 +179,7 @@ void write_mapping(int proc_dir_fd, int + data[0].effective = CAP_TO_MASK(cap); + data[0].permitted = data[0].effective; + if (capset(&hdr, data) < 0) { +- fprintf(stderr, _("%s: Could not set caps\n"), Prog); ++ fprintf(shadow_logfd, _("%s: Could not set caps\n"), Prog); + exit(EXIT_FAILURE); + } + #endif +@@ -197,7 +197,7 @@ void write_mapping(int proc_dir_fd, int + mapping->lower, + mapping->count); + if ((written <= 0) || (written >= (bufsize - (pos - buf)))) { +- fprintf(stderr, _("%s: snprintf failed!\n"), Prog); ++ fprintf(shadow_logfd, _("%s: snprintf failed!\n"), Prog); + exit(EXIT_FAILURE); + } + pos += written; +@@ -206,12 +206,12 @@ void write_mapping(int proc_dir_fd, int + /* Write the mapping to the mapping file */ + fd = openat(proc_dir_fd, map_file, O_WRONLY); + if (fd < 0) { +- fprintf(stderr, _("%s: open of %s failed: %s\n"), ++ fprintf(shadow_logfd, _("%s: open of %s failed: %s\n"), + Prog, map_file, strerror(errno)); + exit(EXIT_FAILURE); + } + if (write(fd, buf, pos - buf) != (pos - buf)) { +- fprintf(stderr, _("%s: write to %s failed: %s\n"), ++ fprintf(shadow_logfd, _("%s: write to %s failed: %s\n"), + Prog, map_file, strerror(errno)); + exit(EXIT_FAILURE); + } +diff -up shadow-4.8.1/libmisc/limits.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/limits.c +--- shadow-4.8.1/libmisc/limits.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/limits.c 2021-05-24 13:04:19.930269118 +0200 +@@ -548,7 +548,7 @@ void setup_limits (const struct passwd * + #ifdef LIMITS + if (info->pw_uid != 0) { + if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) { +- (void) fputs (_("Too many logins.\n"), stderr); ++ (void) fputs (_("Too many logins.\n"), shadow_logfd); + (void) sleep (2); /* XXX: Should be FAIL_DELAY */ + exit (EXIT_FAILURE); + } +diff -up shadow-4.8.1/libmisc/pam_pass.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pam_pass.c +--- shadow-4.8.1/libmisc/pam_pass.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/pam_pass.c 2021-05-24 13:04:19.930269118 +0200 +@@ -59,20 +59,20 @@ void do_pam_passwd (const char *user, bo + + ret = pam_start ("passwd", user, &conv, &pamh); + if (ret != PAM_SUCCESS) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("passwd: pam_start() failed, error %d\n"), ret); + exit (10); /* XXX */ + } + + ret = pam_chauthtok (pamh, flags); + if (ret != PAM_SUCCESS) { +- fprintf (stderr, _("passwd: %s\n"), pam_strerror (pamh, ret)); +- fputs (_("passwd: password unchanged\n"), stderr); ++ fprintf (shadow_logfd, _("passwd: %s\n"), pam_strerror (pamh, ret)); ++ fputs (_("passwd: password unchanged\n"), shadow_logfd); + pam_end (pamh, ret); + exit (10); /* XXX */ + } + +- fputs (_("passwd: password updated successfully\n"), stderr); ++ fputs (_("passwd: password updated successfully\n"), shadow_logfd); + (void) pam_end (pamh, PAM_SUCCESS); + } + #else /* !USE_PAM */ +diff -up shadow-4.8.1/libmisc/pam_pass_non_interactive.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pam_pass_non_interactive.c +--- shadow-4.8.1/libmisc/pam_pass_non_interactive.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/pam_pass_non_interactive.c 2021-05-24 13:04:19.930269118 +0200 +@@ -76,7 +76,7 @@ static int ni_conv (int num_msg, + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: PAM modules requesting echoing are not supported.\n"), + Prog); + goto failed_conversation; +@@ -88,7 +88,7 @@ static int ni_conv (int num_msg, + break; + case PAM_ERROR_MSG: + if ( (NULL == msg[count]->msg) +- || (fprintf (stderr, "%s\n", msg[count]->msg) <0)) { ++ || (fprintf (shadow_logfd, "%s\n", msg[count]->msg) <0)) { + goto failed_conversation; + } + responses[count].resp = NULL; +@@ -101,7 +101,7 @@ static int ni_conv (int num_msg, + responses[count].resp = NULL; + break; + default: +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: conversation type %d not supported.\n"), + Prog, msg[count]->msg_style); + goto failed_conversation; +@@ -143,7 +143,7 @@ int do_pam_passwd_non_interactive (const + + ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh); + if (ret != PAM_SUCCESS) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: (user %s) pam_start failure %d\n"), + Prog, username, ret); + return 1; +@@ -152,7 +152,7 @@ int do_pam_passwd_non_interactive (const + non_interactive_password = password; + ret = pam_chauthtok (pamh, 0); + if (ret != PAM_SUCCESS) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: (user %s) pam_chauthtok() failed, error:\n" + "%s\n"), + Prog, username, pam_strerror (pamh, ret)); +diff -up shadow-4.8.1/libmisc/prefix_flag.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/prefix_flag.c +--- shadow-4.8.1/libmisc/prefix_flag.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.930269118 +0200 ++++ shadow-4.8.1/libmisc/prefix_flag.c 2021-05-24 13:21:11.538205727 +0200 +@@ -80,14 +80,14 @@ extern const char* process_prefix_flag ( + if ( (strcmp (argv[i], "--prefix") == 0) + || (strcmp (argv[i], short_opt) == 0)) { + if (NULL != prefix) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: multiple --prefix options\n"), + Prog); + exit (E_BAD_ARG); + } + + if (i + 1 == argc) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: option '%s' requires an argument\n"), + Prog, argv[i]); + exit (E_BAD_ARG); +diff -up shadow-4.8.1/libmisc/pwdcheck.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pwdcheck.c +--- shadow-4.8.1/libmisc/pwdcheck.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/pwdcheck.c 2021-05-24 13:04:19.930269118 +0200 +@@ -51,7 +51,7 @@ void passwd_check (const char *user, con + if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) { + SYSLOG ((LOG_WARN, "incorrect password for `%s'", user)); + (void) sleep (1); +- fprintf (stderr, _("Incorrect password for %s.\n"), user); ++ fprintf (shadow_logfd, _("Incorrect password for %s.\n"), user); + exit (EXIT_FAILURE); + } + } +diff -up shadow-4.8.1/libmisc/root_flag.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/root_flag.c +--- shadow-4.8.1/libmisc/root_flag.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/root_flag.c 2021-05-24 14:39:04.286481468 +0200 +@@ -62,14 +62,14 @@ extern void process_root_flag (const cha + if ( (strcmp (argv[i], "--root") == 0) + || (strcmp (argv[i], short_opt) == 0)) { + if (NULL != newroot) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: multiple --root options\n"), + Prog); + exit (E_BAD_ARG); + } + + if (i + 1 == argc) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: option '%s' requires an argument\n"), + Prog, argv[i]); + exit (E_BAD_ARG); +@@ -88,34 +88,34 @@ static void change_root (const char* new + /* Drop privileges */ + if ( (setregid (getgid (), getgid ()) != 0) + || (setreuid (getuid (), getuid ()) != 0)) { +- fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), ++ fprintf (shadow_logfd, _("%s: failed to drop privileges (%s)\n"), + Prog, strerror (errno)); + exit (EXIT_FAILURE); + } + + if ('/' != newroot[0]) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: invalid chroot path '%s'\n"), + Prog, newroot); + exit (E_BAD_ARG); + } + + if (access (newroot, F_OK) != 0) { +- fprintf(stderr, ++ fprintf(shadow_logfd, + _("%s: cannot access chroot directory %s: %s\n"), + Prog, newroot, strerror (errno)); + exit (E_BAD_ARG); + } + + if (chdir (newroot) != 0) { +- fprintf(stderr, ++ fprintf(shadow_logfd, + _("%s: cannot chdir to chroot directory %s: %s\n"), + Prog, newroot, strerror (errno)); + exit (E_BAD_ARG); + } + + if (chroot (newroot) != 0) { +- fprintf(stderr, ++ fprintf(shadow_logfd, + _("%s: unable to chroot to directory %s: %s\n"), + Prog, newroot, strerror (errno)); + exit (E_BAD_ARG); +diff -up shadow-4.8.1/libmisc/salt.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/salt.c +--- shadow-4.8.1/libmisc/salt.c.libsubid_not_print_error_messages 2019-12-01 18:02:43.000000000 +0100 ++++ shadow-4.8.1/libmisc/salt.c 2021-05-24 13:04:19.930269118 +0200 +@@ -344,7 +344,7 @@ static /*@observer@*/const char *gensalt + salt_len = (size_t) shadow_random (8, 16); + #endif /* USE_SHA_CRYPT */ + } else if (0 != strcmp (method, "DES")) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Invalid ENCRYPT_METHOD value: '%s'.\n" + "Defaulting to DES.\n"), + method); +diff -up shadow-4.8.1/libmisc/setupenv.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/setupenv.c +--- shadow-4.8.1/libmisc/setupenv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/setupenv.c 2021-05-24 13:04:19.930269118 +0200 +@@ -219,7 +219,7 @@ void setup_env (struct passwd *info) + static char temp_pw_dir[] = "/"; + + if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) { +- fprintf (stderr, _("Unable to cd to '%s'\n"), ++ fprintf (shadow_logfd, _("Unable to cd to '%s'\n"), + info->pw_dir); + SYSLOG ((LOG_WARN, + "unable to cd to `%s' for user `%s'\n", +diff -up shadow-4.8.1/libmisc/user_busy.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/user_busy.c +--- shadow-4.8.1/libmisc/user_busy.c.libsubid_not_print_error_messages 2020-01-23 19:04:44.000000000 +0100 ++++ shadow-4.8.1/libmisc/user_busy.c 2021-05-24 13:04:19.931269132 +0200 +@@ -96,7 +96,7 @@ static int user_busy_utmp (const char *n + continue; + } + +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: user %s is currently logged in\n"), + Prog, name); + return 1; +@@ -249,7 +249,7 @@ static int user_busy_processes (const ch + #ifdef ENABLE_SUBIDS + sub_uid_close(); + #endif +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: user %s is currently used by process %d\n"), + Prog, name, pid); + return 1; +@@ -272,7 +272,7 @@ static int user_busy_processes (const ch + #ifdef ENABLE_SUBIDS + sub_uid_close(); + #endif +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: user %s is currently used by process %d\n"), + Prog, name, pid); + return 1; +diff -up shadow-4.8.1/libmisc/xgetXXbyYY.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/xgetXXbyYY.c +--- shadow-4.8.1/libmisc/xgetXXbyYY.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/xgetXXbyYY.c 2021-05-24 13:04:19.931269132 +0200 +@@ -74,7 +74,7 @@ + + result = malloc(sizeof(LOOKUP_TYPE)); + if (NULL == result) { +- fprintf (stderr, _("%s: out of memory\n"), ++ fprintf (shadow_logfd, _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +@@ -84,7 +84,7 @@ + LOOKUP_TYPE *resbuf = NULL; + buffer = (char *)realloc (buffer, length); + if (NULL == buffer) { +- fprintf (stderr, _("%s: out of memory\n"), ++ fprintf (shadow_logfd, _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +@@ -132,7 +132,7 @@ + if (result) { + result = DUP_FUNCTION(result); + if (NULL == result) { +- fprintf (stderr, _("%s: out of memory\n"), ++ fprintf (shadow_logfd, _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +diff -up shadow-4.8.1/libmisc/xmalloc.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/xmalloc.c +--- shadow-4.8.1/libmisc/xmalloc.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/libmisc/xmalloc.c 2021-05-24 13:04:19.931269132 +0200 +@@ -54,7 +54,7 @@ + + ptr = (char *) malloc (size); + if (NULL == ptr) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: failed to allocate memory: %s\n"), + Prog, strerror (errno)); + exit (13); +diff -up shadow-4.8.1/lib/nscd.c.libsubid_not_print_error_messages shadow-4.8.1/lib/nscd.c +--- shadow-4.8.1/lib/nscd.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/lib/nscd.c 2021-05-24 13:04:19.928269091 +0200 +@@ -25,13 +25,13 @@ int nscd_flush_cache (const char *servic + + if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) { + /* run_command writes its own more detailed message. */ +- (void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); ++ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); + return -1; + } + + code = WEXITSTATUS (status); + if (!WIFEXITED (status)) { +- (void) fprintf (stderr, ++ (void) fprintf (shadow_logfd, + _("%s: nscd did not terminate normally (signal %d)\n"), + Prog, WTERMSIG (status)); + return -1; +@@ -43,9 +43,9 @@ int nscd_flush_cache (const char *servic + /* nscd is installed, but it isn't active. */ + return 0; + } else if (code != 0) { +- (void) fprintf (stderr, _("%s: nscd exited with status %d\n"), ++ (void) fprintf (shadow_logfd, _("%s: nscd exited with status %d\n"), + Prog, code); +- (void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); ++ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); + return -1; + } + +diff -up shadow-4.8.1/lib/nss.c.libsubid_not_print_error_messages shadow-4.8.1/lib/nss.c +--- shadow-4.8.1/lib/nss.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.924269036 +0200 ++++ shadow-4.8.1/lib/nss.c 2021-05-24 13:04:19.928269091 +0200 +@@ -56,7 +56,7 @@ void nss_init(char *nsswitch_path) { + // subid: files + nssfp = fopen(nsswitch_path, "r"); + if (!nssfp) { +- fprintf(stderr, "Failed opening %s: %m", nsswitch_path); ++ fprintf(shadow_logfd, "Failed opening %s: %m", nsswitch_path); + atomic_store(&nss_init_completed, true); + return; + } +@@ -82,16 +82,16 @@ void nss_init(char *nsswitch_path) { + goto done; + } + if (strlen(token) > 50) { +- fprintf(stderr, "Subid NSS module name too long (longer than 50 characters): %s\n", token); +- fprintf(stderr, "Using files\n"); ++ fprintf(shadow_logfd, "Subid NSS module name too long (longer than 50 characters): %s\n", token); ++ fprintf(shadow_logfd, "Using files\n"); + subid_nss = NULL; + goto done; + } + snprintf(libname, 64, "libsubid_%s.so", token); + h = dlopen(libname, RTLD_LAZY); + if (!h) { +- fprintf(stderr, "Error opening %s: %s\n", libname, dlerror()); +- fprintf(stderr, "Using files\n"); ++ fprintf(shadow_logfd, "Error opening %s: %s\n", libname, dlerror()); ++ fprintf(shadow_logfd, "Using files\n"); + subid_nss = NULL; + goto done; + } +@@ -102,7 +102,7 @@ void nss_init(char *nsswitch_path) { + } + subid_nss->has_range = dlsym(h, "shadow_subid_has_range"); + if (!subid_nss->has_range) { +- fprintf(stderr, "%s did not provide @has_range@\n", libname); ++ fprintf(shadow_logfd, "%s did not provide @has_range@\n", libname); + dlclose(h); + free(subid_nss); + subid_nss = NULL; +@@ -110,7 +110,7 @@ void nss_init(char *nsswitch_path) { + } + subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges"); + if (!subid_nss->list_owner_ranges) { +- fprintf(stderr, "%s did not provide @list_owner_ranges@\n", libname); ++ fprintf(shadow_logfd, "%s did not provide @list_owner_ranges@\n", libname); + dlclose(h); + free(subid_nss); + subid_nss = NULL; +@@ -118,7 +118,7 @@ void nss_init(char *nsswitch_path) { + } + subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); + if (!subid_nss->has_any_range) { +- fprintf(stderr, "%s did not provide @has_any_range@\n", libname); ++ fprintf(shadow_logfd, "%s did not provide @has_any_range@\n", libname); + dlclose(h); + free(subid_nss); + subid_nss = NULL; +@@ -126,7 +126,7 @@ void nss_init(char *nsswitch_path) { + } + subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); + if (!subid_nss->find_subid_owners) { +- fprintf(stderr, "%s did not provide @find_subid_owners@\n", libname); ++ fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname); + dlclose(h); + free(subid_nss); + subid_nss = NULL; +@@ -135,7 +135,7 @@ void nss_init(char *nsswitch_path) { + subid_nss->handle = h; + goto done; + } +- fprintf(stderr, "No usable subid NSS module found, using files\n"); ++ fprintf(shadow_logfd, "No usable subid NSS module found, using files\n"); + // subid_nss has to be null here, but to ease reviews: + free(subid_nss); + subid_nss = NULL; +diff -up shadow-4.8.1/lib/prototypes.h.libsubid_not_print_error_messages shadow-4.8.1/lib/prototypes.h +--- shadow-4.8.1/lib/prototypes.h.libsubid_not_print_error_messages 2021-05-24 13:04:19.924269036 +0200 ++++ shadow-4.8.1/lib/prototypes.h 2021-05-24 13:04:19.928269091 +0200 +@@ -59,7 +59,8 @@ + #include "defines.h" + #include "commonio.h" + +-extern /*@observer@*/ const char *Prog; ++extern /*@observer@*/ const char *Prog; /* Program name showed in error messages */ ++extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ + + /* addgrps.c */ + #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) +diff -up shadow-4.8.1/lib/selinux.c.libsubid_not_print_error_messages shadow-4.8.1/lib/selinux.c +--- shadow-4.8.1/lib/selinux.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.911268857 +0200 ++++ shadow-4.8.1/lib/selinux.c 2021-05-24 13:04:32.746445679 +0200 +@@ -135,7 +135,7 @@ static int selinux_log_cb (int type, con + && (errno != EAFNOSUPPORT)) { + + (void) fputs (_("Cannot open audit interface.\n"), +- stderr); ++ shadow_logfd); + SYSLOG ((LOG_WARN, "Cannot open audit interface.")); + } + } +@@ -188,7 +188,7 @@ int check_selinux_permit (const char *pe + selinux_set_callback (SELINUX_CB_LOG, (union selinux_callback) selinux_log_cb); + + if (getprevcon (&user_context_str) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: can not get previous SELinux process context: %s\n"), + Prog, strerror (errno)); + SYSLOG ((LOG_WARN, +diff -up shadow-4.8.1/lib/semanage.c.libsubid_not_print_error_messages shadow-4.8.1/lib/semanage.c +--- shadow-4.8.1/lib/semanage.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.900268705 +0200 ++++ shadow-4.8.1/lib/semanage.c 2021-05-24 13:05:24.747162090 +0200 +@@ -69,7 +69,7 @@ static void semanage_error_callback (unu + switch (semanage_msg_get_level (handle)) { + case SEMANAGE_MSG_ERR: + case SEMANAGE_MSG_WARN: +- fprintf (stderr, _("[libsemanage]: %s\n"), message); ++ fprintf (shadow_logfd, _("[libsemanage]: %s\n"), message); + break; + case SEMANAGE_MSG_INFO: + /* nop */ +@@ -87,7 +87,7 @@ static semanage_handle_t *semanage_init + + handle = semanage_handle_create (); + if (NULL == handle) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Cannot create SELinux management handle\n")); + return NULL; + } +@@ -96,26 +96,26 @@ static semanage_handle_t *semanage_init + + ret = semanage_is_managed (handle); + if (ret != 1) { +- fprintf (stderr, _("SELinux policy not managed\n")); ++ fprintf (shadow_logfd, _("SELinux policy not managed\n")); + goto fail; + } + + ret = semanage_access_check (handle); + if (ret < SEMANAGE_CAN_READ) { +- fprintf (stderr, _("Cannot read SELinux policy store\n")); ++ fprintf (shadow_logfd, _("Cannot read SELinux policy store\n")); + goto fail; + } + + ret = semanage_connect (handle); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Cannot establish SELinux management connection\n")); + goto fail; + } + + ret = semanage_begin_transaction (handle); + if (ret != 0) { +- fprintf (stderr, _("Cannot begin SELinux transaction\n")); ++ fprintf (shadow_logfd, _("Cannot begin SELinux transaction\n")); + goto fail; + } + +@@ -137,7 +137,7 @@ static int semanage_user_mod (semanage_h + + semanage_seuser_query (handle, key, &seuser); + if (NULL == seuser) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not query seuser for %s\n"), login_name); + ret = 1; + goto done; +@@ -146,7 +146,7 @@ static int semanage_user_mod (semanage_h + #if 0 + ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not set serange for %s\n"), login_name); + ret = 1; + goto done; +@@ -155,7 +155,7 @@ static int semanage_user_mod (semanage_h + + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not set sename for %s\n"), + login_name); + ret = 1; +@@ -164,7 +164,7 @@ static int semanage_user_mod (semanage_h + + ret = semanage_seuser_modify_local (handle, key, seuser); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not modify login mapping for %s\n"), + login_name); + ret = 1; +@@ -188,7 +188,7 @@ static int semanage_user_add (semanage_h + + ret = semanage_seuser_create (handle, &seuser); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Cannot create SELinux login mapping for %s\n"), + login_name); + ret = 1; +@@ -197,7 +197,7 @@ static int semanage_user_add (semanage_h + + ret = semanage_seuser_set_name (handle, seuser, login_name); + if (ret != 0) { +- fprintf (stderr, _("Could not set name for %s\n"), login_name); ++ fprintf (shadow_logfd, _("Could not set name for %s\n"), login_name); + ret = 1; + goto done; + } +@@ -205,7 +205,7 @@ static int semanage_user_add (semanage_h + #if 0 + ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not set serange for %s\n"), + login_name); + ret = 1; +@@ -215,7 +215,7 @@ static int semanage_user_add (semanage_h + + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not set SELinux user for %s\n"), + login_name); + ret = 1; +@@ -224,7 +224,7 @@ static int semanage_user_add (semanage_h + + ret = semanage_seuser_modify_local (handle, key, seuser); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not add login mapping for %s\n"), + login_name); + ret = 1; +@@ -252,21 +252,21 @@ int set_seuser (const char *login_name, + + handle = semanage_init (); + if (NULL == handle) { +- fprintf (stderr, _("Cannot init SELinux management\n")); ++ fprintf (shadow_logfd, _("Cannot init SELinux management\n")); + ret = 1; + goto done; + } + + ret = semanage_seuser_key_create (handle, login_name, &key); + if (ret != 0) { +- fprintf (stderr, _("Cannot create SELinux user key\n")); ++ fprintf (shadow_logfd, _("Cannot create SELinux user key\n")); + ret = 1; + goto done; + } + + ret = semanage_seuser_exists (handle, key, &seuser_exists); + if (ret < 0) { +- fprintf (stderr, _("Cannot verify the SELinux user\n")); ++ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); + ret = 1; + goto done; + } +@@ -274,7 +274,7 @@ int set_seuser (const char *login_name, + if (0 != seuser_exists) { + ret = semanage_user_mod (handle, key, login_name, seuser_name); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Cannot modify SELinux user mapping\n")); + ret = 1; + goto done; +@@ -282,7 +282,7 @@ int set_seuser (const char *login_name, + } else { + ret = semanage_user_add (handle, key, login_name, seuser_name); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Cannot add SELinux user mapping\n")); + ret = 1; + goto done; +@@ -291,7 +291,7 @@ int set_seuser (const char *login_name, + + ret = semanage_commit (handle); + if (ret < 0) { +- fprintf (stderr, _("Cannot commit SELinux transaction\n")); ++ fprintf (shadow_logfd, _("Cannot commit SELinux transaction\n")); + ret = 1; + goto done; + } +@@ -317,27 +317,27 @@ int del_seuser (const char *login_name) + + handle = semanage_init (); + if (NULL == handle) { +- fprintf (stderr, _("Cannot init SELinux management\n")); ++ fprintf (shadow_logfd, _("Cannot init SELinux management\n")); + ret = 1; + goto done; + } + + ret = semanage_seuser_key_create (handle, login_name, &key); + if (ret != 0) { +- fprintf (stderr, _("Cannot create SELinux user key\n")); ++ fprintf (shadow_logfd, _("Cannot create SELinux user key\n")); + ret = 1; + goto done; + } + + ret = semanage_seuser_exists (handle, key, &exists); + if (ret < 0) { +- fprintf (stderr, _("Cannot verify the SELinux user\n")); ++ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); + ret = 1; + goto done; + } + + if (0 == exists) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Login mapping for %s is not defined, OK if default mapping was used\n"), + login_name); + ret = 0; /* probably default mapping */ +@@ -346,13 +346,13 @@ int del_seuser (const char *login_name) + + ret = semanage_seuser_exists_local (handle, key, &exists); + if (ret < 0) { +- fprintf (stderr, _("Cannot verify the SELinux user\n")); ++ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); + ret = 1; + goto done; + } + + if (0 == exists) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Login mapping for %s is defined in policy, cannot be deleted\n"), + login_name); + ret = 0; /* Login mapping defined in policy can't be deleted */ +@@ -361,7 +361,7 @@ int del_seuser (const char *login_name) + + ret = semanage_seuser_del_local (handle, key); + if (ret != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("Could not delete login mapping for %s"), + login_name); + ret = 1; +@@ -370,7 +370,7 @@ int del_seuser (const char *login_name) + + ret = semanage_commit (handle); + if (ret < 0) { +- fprintf (stderr, _("Cannot commit SELinux transaction\n")); ++ fprintf (shadow_logfd, _("Cannot commit SELinux transaction\n")); + ret = 1; + goto done; + } +diff -up shadow-4.8.1/lib/spawn.c.libsubid_not_print_error_messages shadow-4.8.1/lib/spawn.c +--- shadow-4.8.1/lib/spawn.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/lib/spawn.c 2021-05-24 13:04:19.929269104 +0200 +@@ -48,7 +48,7 @@ int run_command (const char *cmd, const + } + + (void) fflush (stdout); +- (void) fflush (stderr); ++ (void) fflush (shadow_logfd); + + pid = fork (); + if (0 == pid) { +@@ -57,11 +57,11 @@ int run_command (const char *cmd, const + if (ENOENT == errno) { + exit (E_CMD_NOTFOUND); + } +- fprintf (stderr, "%s: cannot execute %s: %s\n", ++ fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", + Prog, cmd, strerror (errno)); + exit (E_CMD_NOEXEC); + } else if ((pid_t)-1 == pid) { +- fprintf (stderr, "%s: cannot execute %s: %s\n", ++ fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", + Prog, cmd, strerror (errno)); + return -1; + } +@@ -74,7 +74,7 @@ int run_command (const char *cmd, const + || ((pid_t)-1 != wpid && wpid != pid)); + + if ((pid_t)-1 == wpid) { +- fprintf (stderr, "%s: waitpid (status: %d): %s\n", ++ fprintf (shadow_logfd, "%s: waitpid (status: %d): %s\n", + Prog, *status, strerror (errno)); + return -1; + } +diff -up shadow-4.8.1/libsubid/api.c.libsubid_not_print_error_messages shadow-4.8.1/libsubid/api.c +--- shadow-4.8.1/libsubid/api.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/libsubid/api.c 2021-05-24 13:04:19.931269132 +0200 +@@ -32,12 +32,39 @@ + #include + #include + #include ++#include + #include + #include + #include "subordinateio.h" + #include "idmapping.h" + #include "subid.h" + ++const char *Prog = "(libsubid)"; ++extern FILE * shadow_logfd; ++ ++bool libsubid_init(const char *progname, FILE * logfd) ++{ ++ if (progname) { ++ progname = strdup(progname); ++ if (progname) ++ Prog = progname; ++ else ++ fprintf(stderr, "Out of memory"); ++ } ++ ++ if (logfd) { ++ shadow_logfd = logfd; ++ return true; ++ } ++ shadow_logfd = fopen("/dev/null", "w"); ++ if (!shadow_logfd) { ++ fprintf(stderr, "ERROR opening /dev/null for error messages. Using stderr."); ++ shadow_logfd = stderr; ++ return false; ++ } ++ return true; ++} ++ + static + int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) + { +diff -up shadow-4.8.1/libsubid/subid.h.libsubid_not_print_error_messages shadow-4.8.1/libsubid/subid.h +--- shadow-4.8.1/libsubid/subid.h.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/libsubid/subid.h 2021-05-24 13:04:19.931269132 +0200 +@@ -22,6 +22,22 @@ enum subid_status { + }; + + /* ++ * libsubid_init: initialize libsubid ++ * ++ * @progname: Name to display as program. If NULL, then "(libsubid)" will be ++ * shown in error messages. ++ * @logfd: Open file pointer to pass error messages to. If NULL, then ++ * /dev/null will be opened and messages will be sent there. The ++ * default if libsubid_init() is not called is stderr (2). ++ * ++ * This function does not need to be called. If not called, then the defaults ++ * will be used. ++ * ++ * Returns false if an error occurred. ++ */ ++bool libsubid_init(const char *progname, FILE *logfd); ++ ++/* + * get_subuid_ranges: return a list of UID ranges for a user + * + * @owner: username being queried +diff -up shadow-4.8.1/lib/tcbfuncs.c.libsubid_not_print_error_messages shadow-4.8.1/lib/tcbfuncs.c +--- shadow-4.8.1/lib/tcbfuncs.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/lib/tcbfuncs.c 2021-05-24 13:04:19.929269104 +0200 +@@ -72,8 +72,8 @@ shadowtcb_status shadowtcb_gain_priv (vo + * to exit soon. + */ + #define OUT_OF_MEMORY do { \ +- fprintf (stderr, _("%s: out of memory\n"), Prog); \ +- (void) fflush (stderr); \ ++ fprintf (shadow_logfd, _("%s: out of memory\n"), Prog); \ ++ (void) fflush (shadow_logfd); \ + } while (false) + + /* Returns user's tcb directory path relative to TCB_DIR. */ +@@ -116,7 +116,7 @@ static /*@null@*/ char *shadowtcb_path_r + return NULL; + } + if (lstat (path, &st) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), + Prog, path, strerror (errno)); + free (path); +@@ -132,7 +132,7 @@ static /*@null@*/ char *shadowtcb_path_r + return rval; + } + if (!S_ISLNK (st.st_mode)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: %s is neither a directory, nor a symlink.\n"), + Prog, path); + free (path); +@@ -140,7 +140,7 @@ static /*@null@*/ char *shadowtcb_path_r + } + ret = readlink (path, link, sizeof (link) - 1); + if (-1 == ret) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot read symbolic link %s: %s\n"), + Prog, path, strerror (errno)); + free (path); +@@ -149,7 +149,7 @@ static /*@null@*/ char *shadowtcb_path_r + free (path); + if ((size_t)ret >= sizeof(link) - 1) { + link[sizeof(link) - 1] = '\0'; +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Suspiciously long symlink: %s\n"), + Prog, link); + return NULL; +@@ -207,7 +207,7 @@ static shadowtcb_status mkdir_leading (c + } + ptr = path; + if (stat (TCB_DIR, &st) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), + Prog, TCB_DIR, strerror (errno)); + goto out_free_path; +@@ -219,19 +219,19 @@ static shadowtcb_status mkdir_leading (c + return SHADOWTCB_FAILURE; + } + if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot create directory %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free_dir; + } + if (chown (dir, 0, st.st_gid) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free_dir; + } + if (chmod (dir, 0711) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free_dir; +@@ -261,7 +261,7 @@ static shadowtcb_status unlink_suffs (co + return SHADOWTCB_FAILURE; + } + if ((unlink (tmp) != 0) && (errno != ENOENT)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: unlink: %s: %s\n"), + Prog, tmp, strerror (errno)); + free (tmp); +@@ -286,7 +286,7 @@ static shadowtcb_status rmdir_leading (c + } + if (rmdir (dir) != 0) { + if (errno != ENOTEMPTY) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot remove directory %s: %s\n"), + Prog, dir, strerror (errno)); + ret = SHADOWTCB_FAILURE; +@@ -315,7 +315,7 @@ static shadowtcb_status move_dir (const + goto out_free_nomem; + } + if (stat (olddir, &oldmode) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), + Prog, olddir, strerror (errno)); + goto out_free; +@@ -342,7 +342,7 @@ static shadowtcb_status move_dir (const + goto out_free; + } + if (rename (real_old_dir, real_new_dir) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot rename %s to %s: %s\n"), + Prog, real_old_dir, real_new_dir, strerror (errno)); + goto out_free; +@@ -351,7 +351,7 @@ static shadowtcb_status move_dir (const + goto out_free; + } + if ((unlink (olddir) != 0) && (errno != ENOENT)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot remove %s: %s\n"), + Prog, olddir, strerror (errno)); + goto out_free; +@@ -365,7 +365,7 @@ static shadowtcb_status move_dir (const + } + if ( (strcmp (real_new_dir, newdir) != 0) + && (symlink (real_new_dir_rel, newdir) != 0)) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot create symbolic link %s: %s\n"), + Prog, real_new_dir_rel, strerror (errno)); + goto out_free; +@@ -464,37 +464,37 @@ shadowtcb_status shadowtcb_move (/*@NULL + return SHADOWTCB_FAILURE; + } + if (stat (tcbdir, &dirmode) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), + Prog, tcbdir, strerror (errno)); + goto out_free; + } + if (chown (tcbdir, 0, 0) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owners of %s: %s\n"), + Prog, tcbdir, strerror (errno)); + goto out_free; + } + if (chmod (tcbdir, 0700) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), + Prog, tcbdir, strerror (errno)); + goto out_free; + } + if (lstat (shadow, &filemode) != 0) { + if (errno != ENOENT) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot lstat %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; + } +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Warning, user %s has no tcb shadow file.\n"), + Prog, user_newname); + } else { + if (!S_ISREG (filemode.st_mode) || + filemode.st_nlink != 1) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Emergency: %s's tcb shadow is not a " + "regular file with st_nlink=1.\n" + "The account is left locked.\n"), +@@ -502,13 +502,13 @@ shadowtcb_status shadowtcb_move (/*@NULL + goto out_free; + } + if (chown (shadow, user_newid, filemode.st_gid) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; + } + if (chmod (shadow, filemode.st_mode & 07777) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; +@@ -518,7 +518,7 @@ shadowtcb_status shadowtcb_move (/*@NULL + goto out_free; + } + if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), + Prog, tcbdir, strerror (errno)); + goto out_free; +@@ -543,7 +543,7 @@ shadowtcb_status shadowtcb_create (const + return SHADOWTCB_SUCCESS; + } + if (stat (TCB_DIR, &tcbdir_stat) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), + Prog, TCB_DIR, strerror (errno)); + return SHADOWTCB_FAILURE; +@@ -563,39 +563,39 @@ shadowtcb_status shadowtcb_create (const + return SHADOWTCB_FAILURE; + } + if (mkdir (dir, 0700) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: mkdir: %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free; + } + fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot open %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; + } + close (fd); + if (chown (shadow, 0, authgid) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; + } + if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), + Prog, shadow, strerror (errno)); + goto out_free; + } + if (chown (dir, 0, authgid) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free; + } + if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) { +- fprintf (stderr, ++ fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), + Prog, dir, strerror (errno)); + goto out_free; +diff -up shadow-4.8.1/src/chage.c.libsubid_not_print_error_messages shadow-4.8.1/src/chage.c +--- shadow-4.8.1/src/chage.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 ++++ shadow-4.8.1/src/chage.c 2021-05-24 13:04:19.931269132 +0200 +@@ -62,6 +62,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool + dflg = false, /* set last password change date */ +@@ -816,6 +817,7 @@ int main (int argc, char **argv) + * Get the program name so that error messages can use it. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + sanitize_env (); + (void) setlocale (LC_ALL, ""); +diff -up shadow-4.8.1/src/check_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/check_subid_range.c +--- shadow-4.8.1/src/check_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.925269050 +0200 ++++ shadow-4.8.1/src/check_subid_range.c 2021-05-24 13:04:19.931269132 +0200 +@@ -18,6 +18,7 @@ + #include "idmapping.h" + + const char *Prog; ++FILE *shadow_logfd = NULL; + + int main(int argc, char **argv) + { +@@ -25,6 +26,7 @@ int main(int argc, char **argv) + unsigned long start, count; + bool check_uids; + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + if (argc != 5) + exit(1); +diff -up shadow-4.8.1/src/chfn.c.libsubid_not_print_error_messages shadow-4.8.1/src/chfn.c +--- shadow-4.8.1/src/chfn.c.libsubid_not_print_error_messages 2019-11-12 01:18:25.000000000 +0100 ++++ shadow-4.8.1/src/chfn.c 2021-05-24 13:04:19.931269132 +0200 +@@ -57,6 +57,7 @@ + * Global variables. + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + static char fullnm[BUFSIZ]; + static char roomno[BUFSIZ]; + static char workph[BUFSIZ]; +@@ -634,6 +635,7 @@ int main (int argc, char **argv) + * prefix to most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + sanitize_env (); + (void) setlocale (LC_ALL, ""); +diff -up shadow-4.8.1/src/chgpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/chgpasswd.c +--- shadow-4.8.1/src/chgpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.909268829 +0200 ++++ shadow-4.8.1/src/chgpasswd.c 2021-05-24 14:40:13.975427046 +0200 +@@ -66,6 +66,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +@@ -499,6 +500,7 @@ int main (int argc, char **argv) + int line = 0; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/chpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/chpasswd.c +--- shadow-4.8.1/src/chpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.909268829 +0200 ++++ shadow-4.8.1/src/chpasswd.c 2021-05-24 14:43:57.102454551 +0200 +@@ -63,6 +63,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +@@ -487,6 +488,7 @@ int main (int argc, char **argv) + int line = 0; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/chsh.c.libsubid_not_print_error_messages shadow-4.8.1/src/chsh.c +--- shadow-4.8.1/src/chsh.c.libsubid_not_print_error_messages 2019-11-12 01:18:25.000000000 +0100 ++++ shadow-4.8.1/src/chsh.c 2021-05-24 13:04:19.931269132 +0200 +@@ -59,6 +59,7 @@ + * Global variables + */ + const char *Prog; /* Program name */ ++FILE *shadow_logfd = NULL; + static bool amroot; /* Real UID is root */ + static char loginsh[BUFSIZ]; /* Name of new login shell */ + /* command line options */ +@@ -441,6 +442,7 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/expiry.c.libsubid_not_print_error_messages shadow-4.8.1/src/expiry.c +--- shadow-4.8.1/src/expiry.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/expiry.c 2021-05-24 13:04:19.931269132 +0200 +@@ -46,6 +46,7 @@ + + /* Global variables */ + const char *Prog; ++FILE *shadow_logfd = NULL; + static bool cflg = false; + + /* local function prototypes */ +@@ -144,6 +145,7 @@ int main (int argc, char **argv) + struct spwd *spwd; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + sanitize_env (); + +diff -up shadow-4.8.1/src/faillog.c.libsubid_not_print_error_messages shadow-4.8.1/src/faillog.c +--- shadow-4.8.1/src/faillog.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 ++++ shadow-4.8.1/src/faillog.c 2021-05-24 13:04:19.932269146 +0200 +@@ -62,6 +62,7 @@ static void reset (void); + * Global variables + */ + const char *Prog; /* Program name */ ++FILE *shadow_logfd = NULL; + static FILE *fail; /* failure file stream */ + static time_t seconds; /* that number of days in seconds */ + static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ +@@ -573,6 +574,7 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/free_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/free_subid_range.c +--- shadow-4.8.1/src/free_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/src/free_subid_range.c 2021-05-24 13:04:19.932269146 +0200 +@@ -7,6 +7,7 @@ + /* Test program for the subid freeing routine */ + + const char *Prog; ++FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -23,6 +24,7 @@ int main(int argc, char *argv[]) + bool group = false; // get subuids by default + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + while ((c = getopt(argc, argv, "g")) != EOF) { + switch(c) { + case 'g': group = true; break; +diff -up shadow-4.8.1/src/get_subid_owners.c.libsubid_not_print_error_messages shadow-4.8.1/src/get_subid_owners.c +--- shadow-4.8.1/src/get_subid_owners.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/src/get_subid_owners.c 2021-05-24 13:04:19.932269146 +0200 +@@ -4,6 +4,7 @@ + #include "prototypes.h" + + const char *Prog; ++FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -19,6 +20,7 @@ int main(int argc, char *argv[]) + uid_t *uids; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + if (argc < 2) { + usage(); + } +diff -up shadow-4.8.1/src/gpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/gpasswd.c +--- shadow-4.8.1/src/gpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 ++++ shadow-4.8.1/src/gpasswd.c 2021-05-24 13:04:19.932269146 +0200 +@@ -58,6 +58,7 @@ + */ + /* The name of this command, as it is invoked */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + #ifdef SHADOWGRP + /* Indicate if shadow groups are enabled on the system +@@ -926,6 +927,7 @@ int main (int argc, char **argv) + */ + bywho = getuid (); + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + OPENLOG ("gpasswd"); + setbuf (stdout, NULL); +diff -up shadow-4.8.1/src/groupadd.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupadd.c +--- shadow-4.8.1/src/groupadd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 ++++ shadow-4.8.1/src/groupadd.c 2021-05-24 13:04:19.932269146 +0200 +@@ -72,6 +72,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static /*@null@*/char *group_name; + static gid_t group_id; +@@ -582,6 +583,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/groupdel.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupdel.c +--- shadow-4.8.1/src/groupdel.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 ++++ shadow-4.8.1/src/groupdel.c 2021-05-24 13:04:19.932269146 +0200 +@@ -58,6 +58,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static char *group_name; + static gid_t group_id = -1; +@@ -377,6 +378,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/groupmems.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupmems.c +--- shadow-4.8.1/src/groupmems.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/groupmems.c 2021-05-24 13:04:19.932269146 +0200 +@@ -65,6 +65,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static char *adduser = NULL; + static char *deluser = NULL; +@@ -595,6 +596,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/groupmod.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupmod.c +--- shadow-4.8.1/src/groupmod.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 ++++ shadow-4.8.1/src/groupmod.c 2021-05-24 13:04:19.932269146 +0200 +@@ -76,6 +76,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + #ifdef SHADOWGRP + static bool is_shadow_grp; +@@ -799,6 +800,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/groups.c.libsubid_not_print_error_messages shadow-4.8.1/src/groups.c +--- shadow-4.8.1/src/groups.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/groups.c 2021-05-24 13:04:19.932269146 +0200 +@@ -43,6 +43,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + /* local function prototypes */ + static void print_groups (const char *member); +@@ -126,6 +127,7 @@ int main (int argc, char **argv) + * Get the program name so that error messages can use it. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + if (argc == 1) { + +diff -up shadow-4.8.1/src/grpck.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpck.c +--- shadow-4.8.1/src/grpck.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/grpck.c 2021-05-24 13:04:19.932269146 +0200 +@@ -68,6 +68,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static const char *grp_file = GROUP_FILE; + static bool use_system_grp_file = true; +@@ -836,6 +837,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/grpconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpconv.c +--- shadow-4.8.1/src/grpconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/grpconv.c 2021-05-24 13:04:19.932269146 +0200 +@@ -59,6 +59,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool gr_locked = false; + static bool sgr_locked = false; +@@ -146,6 +147,7 @@ int main (int argc, char **argv) + struct sgrp sgent; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/grpunconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpunconv.c +--- shadow-4.8.1/src/grpunconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/grpunconv.c 2021-05-24 13:04:19.932269146 +0200 +@@ -59,6 +59,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool gr_locked = false; + static bool sgr_locked = false; +@@ -145,6 +146,7 @@ int main (int argc, char **argv) + const struct sgrp *sg; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/lastlog.c.libsubid_not_print_error_messages shadow-4.8.1/src/lastlog.c +--- shadow-4.8.1/src/lastlog.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 ++++ shadow-4.8.1/src/lastlog.c 2021-05-24 13:04:19.932269146 +0200 +@@ -59,6 +59,7 @@ + * Global variables + */ + const char *Prog; /* Program name */ ++FILE *shadow_logfd = NULL; + static FILE *lastlogfile; /* lastlog file stream */ + static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ + static bool has_umin = false; +@@ -304,6 +305,7 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/list_subid_ranges.c.libsubid_not_print_error_messages shadow-4.8.1/src/list_subid_ranges.c +--- shadow-4.8.1/src/list_subid_ranges.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/src/list_subid_ranges.c 2021-05-24 13:04:19.932269146 +0200 +@@ -4,6 +4,7 @@ + #include "prototypes.h" + + const char *Prog; ++FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -19,6 +20,7 @@ int main(int argc, char *argv[]) + struct subordinate_range **ranges; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + if (argc < 2) { + usage(); + } +diff -up shadow-4.8.1/src/login.c.libsubid_not_print_error_messages shadow-4.8.1/src/login.c +--- shadow-4.8.1/src/login.c.libsubid_not_print_error_messages 2020-01-12 14:58:49.000000000 +0100 ++++ shadow-4.8.1/src/login.c 2021-05-24 13:04:19.933269160 +0200 +@@ -83,6 +83,7 @@ static pam_handle_t *pamh = NULL; + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static const char *hostname = ""; + static /*@null@*/ /*@only@*/char *username = NULL; +@@ -577,6 +578,7 @@ int main (int argc, char **argv) + + amroot = (getuid () == 0); + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + if (geteuid() != 0) { + fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog); +diff -up shadow-4.8.1/src/logoutd.c.libsubid_not_print_error_messages shadow-4.8.1/src/logoutd.c +--- shadow-4.8.1/src/logoutd.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/logoutd.c 2021-05-24 13:04:19.933269160 +0200 +@@ -44,6 +44,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + #ifndef DEFAULT_HUP_MESG + #define DEFAULT_HUP_MESG _("login time exceeded\n\n") +@@ -187,6 +188,7 @@ int main (int argc, char **argv) + * Start syslogging everything + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + OPENLOG ("logoutd"); + +diff -up shadow-4.8.1/src/newgidmap.c.libsubid_not_print_error_messages shadow-4.8.1/src/newgidmap.c +--- shadow-4.8.1/src/newgidmap.c.libsubid_not_print_error_messages 2019-10-13 04:52:08.000000000 +0200 ++++ shadow-4.8.1/src/newgidmap.c 2021-05-24 13:04:19.933269160 +0200 +@@ -45,6 +45,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + + static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups) +@@ -175,6 +176,7 @@ int main(int argc, char **argv) + bool allow_setgroups = false; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + /* + * The valid syntax are +diff -up shadow-4.8.1/src/newgrp.c.libsubid_not_print_error_messages shadow-4.8.1/src/newgrp.c +--- shadow-4.8.1/src/newgrp.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 ++++ shadow-4.8.1/src/newgrp.c 2021-05-24 14:45:30.372720097 +0200 +@@ -49,6 +49,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + extern char **newenvp; + extern char **environ; +@@ -444,6 +445,7 @@ int main (int argc, char **argv) + * don't need to re-exec anything. -- JWP + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + is_newgrp = (strcmp (Prog, "newgrp") == 0); + OPENLOG (is_newgrp ? "newgrp" : "sg"); + gid = getgid (); +diff -up shadow-4.8.1/src/new_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/new_subid_range.c +--- shadow-4.8.1/src/new_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 ++++ shadow-4.8.1/src/new_subid_range.c 2021-05-24 13:04:19.933269160 +0200 +@@ -7,6 +7,7 @@ + /* Test program for the subid creation routine */ + + const char *Prog; ++FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -26,6 +27,7 @@ int main(int argc, char *argv[]) + bool ok; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + while ((c = getopt(argc, argv, "gn")) != EOF) { + switch(c) { + case 'n': makenew = true; break; +diff -up shadow-4.8.1/src/newuidmap.c.libsubid_not_print_error_messages shadow-4.8.1/src/newuidmap.c +--- shadow-4.8.1/src/newuidmap.c.libsubid_not_print_error_messages 2019-10-13 04:52:08.000000000 +0200 ++++ shadow-4.8.1/src/newuidmap.c 2021-05-24 13:04:19.933269160 +0200 +@@ -45,6 +45,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool verify_range(struct passwd *pw, struct map_range *range) + { +@@ -105,6 +106,7 @@ int main(int argc, char **argv) + int written; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + /* + * The valid syntax are +diff -up shadow-4.8.1/src/newusers.c.libsubid_not_print_error_messages shadow-4.8.1/src/newusers.c +--- shadow-4.8.1/src/newusers.c.libsubid_not_print_error_messages 2020-01-17 16:47:56.000000000 +0100 ++++ shadow-4.8.1/src/newusers.c 2021-05-24 13:04:19.933269160 +0200 +@@ -75,6 +75,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool rflg = false; /* create a system account */ + #ifndef USE_PAM +@@ -1040,6 +1041,7 @@ int main (int argc, char **argv) + #endif /* USE_PAM */ + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/passwd.c.libsubid_not_print_error_messages shadow-4.8.1/src/passwd.c +--- shadow-4.8.1/src/passwd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 ++++ shadow-4.8.1/src/passwd.c 2021-05-24 13:04:19.933269160 +0200 +@@ -66,6 +66,7 @@ + * Global variables + */ + const char *Prog; /* Program name */ ++FILE *shadow_logfd = NULL; + + static char *name; /* The name of user whose password is being changed */ + static char *myname; /* The current user's name */ +@@ -752,6 +753,7 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/pwck.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwck.c +--- shadow-4.8.1/src/pwck.c.libsubid_not_print_error_messages 2019-10-13 02:56:08.000000000 +0200 ++++ shadow-4.8.1/src/pwck.c 2021-05-24 13:04:19.933269160 +0200 +@@ -70,6 +70,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool use_system_pw_file = true; + static bool use_system_spw_file = true; +diff -up shadow-4.8.1/src/pwconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwconv.c +--- shadow-4.8.1/src/pwconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/pwconv.c 2021-05-24 13:04:19.933269160 +0200 +@@ -89,6 +89,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool spw_locked = false; + static bool pw_locked = false; +@@ -176,6 +177,7 @@ int main (int argc, char **argv) + struct spwd spent; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/pwunconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwunconv.c +--- shadow-4.8.1/src/pwunconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/pwunconv.c 2021-05-24 13:04:19.933269160 +0200 +@@ -53,6 +53,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static bool spw_locked = false; + static bool pw_locked = false; +@@ -137,6 +138,7 @@ int main (int argc, char **argv) + const struct spwd *spwd; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/su.c.libsubid_not_print_error_messages shadow-4.8.1/src/su.c +--- shadow-4.8.1/src/su.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/su.c 2021-05-24 13:04:19.934269173 +0200 +@@ -82,6 +82,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */ + static bool caller_is_root = false; + static uid_t caller_uid; +@@ -699,6 +700,7 @@ static void save_caller_context (char ** + * most error messages. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + caller_uid = getuid (); + caller_is_root = (caller_uid == 0); +diff -up shadow-4.8.1/src/sulogin.c.libsubid_not_print_error_messages shadow-4.8.1/src/sulogin.c +--- shadow-4.8.1/src/sulogin.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/src/sulogin.c 2021-05-24 13:04:19.934269173 +0200 +@@ -50,6 +50,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static char name[BUFSIZ]; + static char pass[BUFSIZ]; +@@ -106,6 +107,7 @@ static RETSIGTYPE catch_signals (unused + #endif + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); +diff -up shadow-4.8.1/src/useradd.c.libsubid_not_print_error_messages shadow-4.8.1/src/useradd.c +--- shadow-4.8.1/src/useradd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.918268953 +0200 ++++ shadow-4.8.1/src/useradd.c 2021-05-24 13:04:19.934269173 +0200 +@@ -92,6 +92,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + /* + * These defaults are used if there is no defaults file. +@@ -2301,6 +2302,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/userdel.c.libsubid_not_print_error_messages shadow-4.8.1/src/userdel.c +--- shadow-4.8.1/src/userdel.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.907268801 +0200 ++++ shadow-4.8.1/src/userdel.c 2021-05-24 13:04:19.934269173 +0200 +@@ -89,6 +89,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static char *user_name; + static uid_t user_id; +@@ -941,6 +942,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); +diff -up shadow-4.8.1/src/usermod.c.libsubid_not_print_error_messages shadow-4.8.1/src/usermod.c +--- shadow-4.8.1/src/usermod.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.917268939 +0200 ++++ shadow-4.8.1/src/usermod.c 2021-05-24 13:04:19.934269173 +0200 +@@ -102,6 +102,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static char *user_name; + static char *user_newname; +@@ -2214,6 +2215,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.8.1/src/vipw.c.libsubid_not_print_error_messages shadow-4.8.1/src/vipw.c +--- shadow-4.8.1/src/vipw.c.libsubid_not_print_error_messages 2019-12-01 17:52:32.000000000 +0100 ++++ shadow-4.8.1/src/vipw.c 2021-05-24 13:04:19.934269173 +0200 +@@ -63,6 +63,7 @@ + * Global variables + */ + const char *Prog; ++FILE *shadow_logfd = NULL; + + static const char *filename, *fileeditname; + static bool filelocked = false; +@@ -481,6 +482,7 @@ int main (int argc, char **argv) + bool do_vipw; + + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); diff --git a/shadow-4.8.1-libsubid_simplify_ranges_variable.patch b/shadow-4.8.1-libsubid_simplify_ranges_variable.patch new file mode 100644 index 0000000..4cd848b --- /dev/null +++ b/shadow-4.8.1-libsubid_simplify_ranges_variable.patch @@ -0,0 +1,264 @@ +diff -up shadow-4.8.1/configure.ac.libsubid_simplify_ranges_variable shadow-4.8.1/configure.ac +--- shadow-4.8.1/configure.ac.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.165917066 +0200 ++++ shadow-4.8.1/configure.ac 2021-05-24 15:02:56.184917324 +0200 +@@ -1,6 +1,6 @@ + dnl Process this file with autoconf to produce a configure script. + AC_PREREQ([2.69]) +-m4_define([libsubid_abi_major], 2) ++m4_define([libsubid_abi_major], 3) + m4_define([libsubid_abi_minor], 0) + m4_define([libsubid_abi_micro], 0) + m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) +diff -up shadow-4.8.1/lib/prototypes.h.libsubid_simplify_ranges_variable shadow-4.8.1/lib/prototypes.h +--- shadow-4.8.1/lib/prototypes.h.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.184917324 +0200 ++++ shadow-4.8.1/lib/prototypes.h 2021-05-24 16:38:57.610619467 +0200 +@@ -309,16 +309,15 @@ struct subid_nss_ops { + * + * @owner - string representing username being queried + * @id_type - subuid or subgid +- * @ranges - pointer to an array of struct subordinate_range pointers, or +- * NULL. The returned array of struct subordinate_range and its +- * members must be freed by the caller. ++ * @ranges - pointer to an array of struct subid_range, or NULL. The ++ * returned array must be freed by the caller. + * @count - pointer to an integer into which the number of returned ranges + * is written. + + * returns success if the module was able to determine an answer, + * else an error status. + */ +- enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges, int *count); ++ enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subid_range **ranges, int *count); + + /* + * nss_find_subid_owners: find uids who own a given subuid or subgid. +diff -up shadow-4.8.1/libsubid/api.c.libsubid_simplify_ranges_variable shadow-4.8.1/libsubid/api.c +--- shadow-4.8.1/libsubid/api.c.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.467989079 +0200 ++++ shadow-4.8.1/libsubid/api.c 2021-05-24 16:42:32.091584531 +0200 +@@ -68,26 +68,21 @@ bool libsubid_init(const char *progname, + } + + static +-int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) ++int get_subid_ranges(const char *owner, enum subid_type id_type, struct subid_range **ranges) + { + return list_owner_ranges(owner, id_type, ranges); + } + +-int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges) ++int get_subuid_ranges(const char *owner, struct subid_range **ranges) + { + return get_subid_ranges(owner, ID_TYPE_UID, ranges); + } + +-int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges) ++int get_subgid_ranges(const char *owner, struct subid_range **ranges) + { + return get_subid_ranges(owner, ID_TYPE_GID, ranges); + } + +-void subid_free_ranges(struct subordinate_range **ranges, int count) +-{ +- return free_subordinate_ranges(ranges, count); +-} +- + static + int get_subid_owner(unsigned long id, enum subid_type id_type, uid_t **owner) + { +diff -up shadow-4.8.1/libsubid/subid.h.libsubid_simplify_ranges_variable shadow-4.8.1/libsubid/subid.h +--- shadow-4.8.1/libsubid/subid.h.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.468989093 +0200 ++++ shadow-4.8.1/libsubid/subid.h 2021-05-24 16:43:49.697657383 +0200 +@@ -3,6 +3,15 @@ + + #ifndef SUBID_RANGE_DEFINED + #define SUBID_RANGE_DEFINED 1 ++ ++/* subid_range is just a starting point and size of a range */ ++struct subid_range { ++ unsigned long start; ++ unsigned long count; ++}; ++ ++/* subordinage_range is a subid_range plus an owner, representing ++ * a range in /etc/subuid or /etc/subgid */ + struct subordinate_range { + const char *owner; + unsigned long start; +@@ -41,32 +50,27 @@ bool libsubid_init(const char *progname, + * get_subuid_ranges: return a list of UID ranges for a user + * + * @owner: username being queried +- * @ranges: a pointer to a subordinate range ** in which the result will be +- * returned. ++ * @ranges: a pointer to an array of subid_range structs in which the result ++ * will be returned. ++ * ++ * The caller must free(ranges) when done. + * + * returns: number of ranges found, ir < 0 on error. + */ +-int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); ++int get_subuid_ranges(const char *owner, struct subid_range **ranges); + + /* + * get_subgid_ranges: return a list of GID ranges for a user + * + * @owner: username being queried +- * @ranges: a pointer to a subordinate range ** in which the result will be +- * returned. ++ * @ranges: a pointer to an array of subid_range structs in which the result ++ * will be returned. + * +- * returns: number of ranges found, ir < 0 on error. +- */ +-int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); +- +-/* +- * subid_free_ranges: free an array of subordinate_ranges returned by either +- * get_subuid_ranges() or get_subgid_ranges(). ++ * The caller must free(ranges) when done. + * +- * @ranges: the ranges to free +- * @count: the number of ranges in @ranges ++ * returns: number of ranges found, ir < 0 on error. + */ +-void subid_free_ranges(struct subordinate_range **ranges, int count); ++int get_subgid_ranges(const char *owner, struct subid_range **ranges); + + /* + * get_subuid_owners: return a list of uids to which the given uid has been +diff -up shadow-4.8.1/lib/subordinateio.c.libsubid-simplify shadow-4.8.1/lib/subordinateio.c +--- shadow-4.8.1/lib/subordinateio.c.libsubid-simplify 2021-05-24 17:27:38.721035241 +0200 ++++ shadow-4.8.1/lib/subordinateio.c 2021-05-24 17:28:06.481420946 +0200 +@@ -11,6 +11,7 @@ + #include + #include "commonio.h" + #include "subordinateio.h" ++#include "../libsubid/subid.h" + #include + #include + #include +@@ -308,25 +309,21 @@ static bool have_range(struct commonio_d + return false; + } + +-static bool append_range(struct subordinate_range ***ranges, const struct subordinate_range *new, int n) ++static bool append_range(struct subid_range **ranges, const struct subordinate_range *new, int n) + { +- struct subordinate_range *tmp; + if (!*ranges) { +- *ranges = malloc(sizeof(struct subordinate_range *)); ++ *ranges = malloc(sizeof(struct subid_range)); + if (!*ranges) + return false; + } else { +- struct subordinate_range **new; +- new = realloc(*ranges, (n + 1) * (sizeof(struct subordinate_range *))); +- if (!new) ++ struct subid_range *alloced; ++ alloced = realloc(*ranges, (n + 1) * (sizeof(struct subid_range))); ++ if (!alloced) + return false; +- *ranges = new; ++ *ranges = alloced; + } +- (*ranges)[n] = NULL; +- tmp = subordinate_dup(new); +- if (!tmp) +- return false; +- (*ranges)[n] = tmp; ++ (*ranges)[n].start = new->start; ++ (*ranges)[n].count = new->count; + return true; + } + +@@ -785,10 +782,10 @@ gid_t sub_gid_find_free_range(gid_t min, + * + * The caller must free the subordinate range list. + */ +-int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges) ++int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_range **in_ranges) + { + // TODO - need to handle owner being either uid or username +- struct subordinate_range **ranges = NULL; ++ struct subid_range *ranges = NULL; + const struct subordinate_range *range; + struct commonio_db *db; + enum subid_status status; +@@ -826,7 +823,7 @@ int list_owner_ranges(const char *owner, + while ((range = commonio_next(db)) != NULL) { + if (0 == strcmp(range->owner, owner)) { + if (!append_range(&ranges, range, count++)) { +- free_subordinate_ranges(ranges, count-1); ++ free(ranges); + ranges = NULL; + count = -1; + goto out; +diff -up shadow-4.8.1/lib/subordinateio.h.libsubid_simplify_ranges_variable shadow-4.8.1/lib/subordinateio.h +--- shadow-4.8.1/lib/subordinateio.h.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.467989079 +0200 ++++ shadow-4.8.1/lib/subordinateio.h 2021-05-24 16:40:56.978269647 +0200 +@@ -25,7 +25,7 @@ extern int sub_uid_unlock (void); + extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); + extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); + extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); +-extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges); ++extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_range **ranges); + extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); + extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); + extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); +diff -up shadow-4.8.1/src/list_subid_ranges.c.libsubid_simplify_ranges_variable shadow-4.8.1/src/list_subid_ranges.c +--- shadow-4.8.1/src/list_subid_ranges.c.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.468989093 +0200 ++++ shadow-4.8.1/src/list_subid_ranges.c 2021-05-24 16:45:10.884779740 +0200 +@@ -17,27 +17,29 @@ void usage(void) + int main(int argc, char *argv[]) + { + int i, count=0; +- struct subordinate_range **ranges; ++ struct subid_range *ranges; ++ const char *owner; + + Prog = Basename (argv[0]); + shadow_logfd = stderr; +- if (argc < 2) { ++ if (argc < 2) + usage(); +- } +- if (argc == 3 && strcmp(argv[1], "-g") == 0) +- count = get_subgid_ranges(argv[2], &ranges); +- else if (argc == 2 && strcmp(argv[1], "-h") == 0) ++ owner = argv[1]; ++ if (argc == 3 && strcmp(argv[1], "-g") == 0) { ++ owner = argv[2]; ++ count = get_subgid_ranges(owner, &ranges); ++ } else if (argc == 2 && strcmp(argv[1], "-h") == 0) { + usage(); +- else +- count = get_subuid_ranges(argv[1], &ranges); ++ } else { ++ count = get_subuid_ranges(owner, &ranges); ++ } + if (!ranges) { + fprintf(stderr, "Error fetching ranges\n"); + exit(1); + } + for (i = 0; i < count; i++) { +- printf("%d: %s %lu %lu\n", i, ranges[i]->owner, +- ranges[i]->start, ranges[i]->count); ++ printf("%d: %s %lu %lu\n", i, owner, ++ ranges[i].start, ranges[i].count); + } +- subid_free_ranges(ranges, count); + return 0; + } +diff -up shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c.libsubid_simplify_ranges_variable shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c +--- shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.166917079 +0200 ++++ shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c 2021-05-24 15:03:01.469989106 +0200 +@@ -113,7 +113,7 @@ enum subid_status shadow_subid_list_owne + if (strcmp(owner, "conn") == 0) + return SUBID_STATUS_ERROR_CONN; + +- *ranges = NULL; ++ *in_ranges = NULL; + if (strcmp(owner, "user1") != 0 && strcmp(owner, "ubuntu") != 0 && + strcmp(owner, "group1") != 0) + return SUBID_STATUS_SUCCESS; diff --git a/shadow-4.8.1-man_clarify_subid_delegation.patch b/shadow-4.8.1-man_clarify_subid_delegation.patch new file mode 100644 index 0000000..b7d01b8 --- /dev/null +++ b/shadow-4.8.1-man_clarify_subid_delegation.patch @@ -0,0 +1,246 @@ +From d5b15f8633d0eabed885cd16feda224ec2d59072 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 24 May 2021 12:14:43 +0200 +Subject: [PATCH] man: clarify subid delegation + +Clarify that the subid delegation can only come from one source. +Moreover, add an example of what might happen if the subid source is NSS +and useradd is executed. + +Related: https://github.com/shadow-maint/shadow/issues/331 +--- + man/newgidmap.1.xml | 12 +++++++++--- + man/newuidmap.1.xml | 10 ++++++++-- + 2 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml +index 76fc1e30..7aaf34bf 100644 +--- a/man/newgidmap.1.xml ++++ b/man/newgidmap.1.xml +@@ -88,9 +88,15 @@ + DESCRIPTION + + The newgidmap sets /proc/[pid]/gid_map based on its +- command line arguments and the gids allowed (either in /etc/subgid or +- through the configured NSS subid module). +- Note that the root user is not exempted from the requirement for a valid ++ command line arguments and the gids allowed. The subid delegation can come either from files ++ (/etc/subgid) or from the configured NSS subid module. Only one of them ++ can be chosen at a time. So, for example, if the subid source is configured as NSS and ++ groupadd is executed, then the command will fail and the entry will not be ++ created in /etc/subgid. ++ ++ ++ ++ Note that the root group is not exempted from the requirement for a valid + /etc/subgid entry. + + +diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml +index 44eca50a..4bc1ef7a 100644 +--- a/man/newuidmap.1.xml ++++ b/man/newuidmap.1.xml +@@ -88,8 +88,14 @@ + DESCRIPTION + + The newuidmap sets /proc/[pid]/uid_map based on its +- command line arguments and the uids allowed (either in /etc/subuid or +- through the configured NSS subid module). ++ command line arguments and the uids allowed. The subid delegation can come either from files ++ (/etc/subuid) or from the configured NSS subid module. Only one of them ++ can be chosen at a time. So, for example, if the subid source is configured as NSS and ++ useradd is executed, then the command will fail and the entry will not be ++ created in /etc/subuid. ++ ++ ++ + Note that the root user is not exempted from the requirement for a valid + /etc/subuid entry. + +-- +2.30.2 + +From 68ebbf936038e4e4c8b5105bd3246ef9709b6354 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 7 Jun 2021 11:50:56 +0200 +Subject: [PATCH 1/2] man: clarify subid delegation behaviour + +Following the discussion https://github.com/shadow-maint/shadow/pull/345 +I have changed the documentation to clarify the behaviour of subid +delegation when any subid source except files is configured. +--- + man/newgidmap.1.xml | 11 +++++------ + man/newuidmap.1.xml | 11 +++++------ + 2 files changed, 10 insertions(+), 12 deletions(-) + +diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml +index 7aaf34bf..681aefcb 100644 +--- a/man/newgidmap.1.xml ++++ b/man/newgidmap.1.xml +@@ -87,12 +87,11 @@ + + DESCRIPTION + +- The newgidmap sets /proc/[pid]/gid_map based on its +- command line arguments and the gids allowed. The subid delegation can come either from files +- (/etc/subgid) or from the configured NSS subid module. Only one of them +- can be chosen at a time. So, for example, if the subid source is configured as NSS and +- groupadd is executed, then the command will fail and the entry will not be +- created in /etc/subgid. ++ The newgidmap sets /proc/[pid]/gid_map ++ based on its command line arguments and the gids allowed. Subgid ++ delegation can either be managed via /etc/subgid ++ or through the configured NSS subid module. These options are mutually ++ exclusive. + + + +diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml +index 4bc1ef7a..09e65d80 100644 +--- a/man/newuidmap.1.xml ++++ b/man/newuidmap.1.xml +@@ -87,12 +87,11 @@ + + DESCRIPTION + +- The newuidmap sets /proc/[pid]/uid_map based on its +- command line arguments and the uids allowed. The subid delegation can come either from files +- (/etc/subuid) or from the configured NSS subid module. Only one of them +- can be chosen at a time. So, for example, if the subid source is configured as NSS and +- useradd is executed, then the command will fail and the entry will not be +- created in /etc/subuid. ++ The newuidmap sets /proc/[pid]/uid_map ++ based on its command line arguments and the uids allowed. Subuid ++ delegation can either be managed via /etc/subuid or ++ through the configured NSS subid module. These options are mutually ++ exclusive. + + + +-- +2.31.1 + + +From 0faec51bf0ec24e6e3d098cc55ed42584dd24efe Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 11 Jun 2021 15:25:42 +0200 +Subject: [PATCH 2/2] man: definition and configuration of subid + +Define the subid functionality and explain the way to configure its +delegation. +--- + man/subgid.5.xml | 32 +++++++++++++++++++++++++++++++- + man/subuid.5.xml | 32 +++++++++++++++++++++++++++++++- + 2 files changed, 62 insertions(+), 2 deletions(-) + +diff --git a/man/subgid.5.xml b/man/subgid.5.xml +index 70c561c4..02f421ab 100644 +--- a/man/subgid.5.xml ++++ b/man/subgid.5.xml +@@ -38,6 +38,11 @@ + Biederman + Creation, 2013 + ++ ++ Iker ++ Pedrosa ++ Developer, 2021 ++ + + + subgid +@@ -48,11 +53,36 @@ + + + subgid +- the subordinate gid file ++ the configuration for subordinate group ids + + + + DESCRIPTION ++ ++ Subgid authorizes a group id to map ranges of group ids from its namespace ++ into child namespaces. ++ ++ ++ The delegation of the subordinate gids can be configured via the ++ subid field in ++ /etc/nsswitch.conf file. Only one value can be set ++ as the delegation source. Setting this field to ++ files configures the delegation of gids to ++ /etc/subgid. Setting any other value treats ++ the delegation as a plugin following with a name of the form ++ libsubid_$value.so. If the value or plugin is ++ missing, then the subordinate gid delegation falls back to ++ files. ++ ++ ++ Note, that groupadd will only create entries in ++ /etc/subgid if subid delegation is managed via subid ++ files. ++ ++ ++ ++ ++ LOCAL SUBORDINATE DELEGATION + + Each line in /etc/subgid contains + a user name and a range of subordinate group ids that user +diff --git a/man/subuid.5.xml b/man/subuid.5.xml +index ec6a85f5..990d162e 100644 +--- a/man/subuid.5.xml ++++ b/man/subuid.5.xml +@@ -38,6 +38,11 @@ + Biederman + Creation, 2013 + ++ ++ Iker ++ Pedrosa ++ Developer, 2021 ++ + + + subuid +@@ -48,11 +53,36 @@ + + + subuid +- the subordinate uid file ++ the configuration for subordinate user ids + + + + DESCRIPTION ++ ++ Subuid authorizes a user id to map ranges of user ids from its namespace ++ into child namespaces. ++ ++ ++ The delegation of the subordinate uids can be configured via the ++ subid field in ++ /etc/nsswitch.conf file. Only one value can be set ++ as the delegation source. Setting this field to ++ files configures the delegation of uids to ++ /etc/subuid. Setting any other value treats ++ the delegation as a plugin following with a name of the form ++ libsubid_$value.so. If the value or plugin is ++ missing, then the subordinate uid delegation falls back to ++ files. ++ ++ ++ Note, that useradd will only create entries in ++ /etc/subuid if subid delegation is managed via subid ++ files. ++ ++ ++ ++ ++ LOCAL SUBORDINATE DELEGATION + + Each line in /etc/subuid contains + a user name and a range of subordinate user ids that user +-- +2.31.1 + diff --git a/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch b/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch new file mode 100644 index 0000000..f393368 --- /dev/null +++ b/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch @@ -0,0 +1,44 @@ +From 663824ef4ca927aa2b4319b69e0bfa68282ec719 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sat, 22 May 2021 11:42:02 -0500 +Subject: [PATCH] Fix useradd with SUB_UID_COUNT=0 + +Closes #298 + +Fix useradd when SUB_UID_COUNT=0 in login.defs. + +Signed-off-by: Serge Hallyn +--- + src/useradd.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 06accb2f..9862ae55 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2386,6 +2386,8 @@ int main (int argc, char **argv) + #ifdef ENABLE_SUBIDS + uid_t uid_min; + uid_t uid_max; ++ unsigned long subuid_count; ++ unsigned long subgid_count; + #endif + + /* +@@ -2427,9 +2429,11 @@ int main (int argc, char **argv) + #ifdef ENABLE_SUBIDS + uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); + uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); +- is_sub_uid = sub_uid_file_present () && !rflg && ++ subuid_count = getdef_ulong ("SUB_UID_COUNT", 65536); ++ subgid_count = getdef_ulong ("SUB_GID_COUNT", 65536); ++ is_sub_uid = subuid_count > 0 && sub_uid_file_present () && !rflg && + (!user_id || (user_id <= uid_max && user_id >= uid_min)); +- is_sub_gid = sub_gid_file_present () && !rflg && ++ is_sub_gid = subgid_count > 0 && sub_gid_file_present () && !rflg && + (!user_id || (user_id <= uid_max && user_id >= uid_min)); + #endif /* ENABLE_SUBIDS */ + +-- +2.30.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 3a8e510..164c0d7 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.8.1 -Release: 10%{?dist} +Release: 11%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -78,6 +78,23 @@ Patch47: shadow-4.8.1-libsubid_creation.patch Patch48: shadow-4.8.1-libsubid_nsswitch_support.patch # https://github.com/shadow-maint/shadow/commit/186b1b7ac1a68d0fcc618a22da1a99232b420911 Patch49: shadow-4.8.1-man-mention-nss-in-newuidmap.patch +# https://github.com/shadow-maint/shadow/commit/f9831a4a1a20b0e8fe47cc72ec20018ec04dbb90 +Patch50: shadow-4.8.1-libsubid_not_print_error_messages.patch +# https://github.com/shadow-maint/shadow/commit/c6cab4a7bafa18d9d65a333cac1261e7b5e32bc9 +Patch51: shadow-4.8.1-libsubid_init_return_false.patch +# https://github.com/shadow-maint/shadow/commit/2f1f45d64fc7c10e7a3cbe00e89f63714343e526 +Patch52: shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch +# https://github.com/shadow-maint/shadow/commit/ea7af4e1543c63590d4107ae075fea385028997d +Patch53: shadow-4.8.1-libsubid_simplify_ranges_variable.patch +# https://github.com/shadow-maint/shadow/commit/0fe42f571c69f0105d31305f995c9887aeb9525e +Patch54: shadow-4.8.1-libsubid_init_not_print_error_messages.patch +# https://github.com/shadow-maint/shadow/commit/ec1951c181faed188464396b2cfdd2efb726c7f3 +Patch55: shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch +# https://github.com/shadow-maint/shadow/commit/087112244327be50abc24f9ec8afbf60ae8b2dec +# https://github.com/shadow-maint/shadow/pull/353 +Patch56: shadow-4.8.1-man_clarify_subid_delegation.patch +# https://github.com/shadow-maint/shadow/commit/bd920ab36a6c641e4a8769f8c7f8ca738ec61820 +Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch License: BSD and GPLv2+ BuildRequires: make @@ -152,6 +169,14 @@ Development files for shadow-utils-subid. %patch47 -p1 -b .libsubid_creation %patch48 -p1 -b .libsubid_nsswitch_support %patch49 -p1 -b .man-mention-nss-in-newuidmap +%patch50 -p1 -b .libsubid_not_print_error_messages +%patch51 -p1 -b .libsubid_init_return_false +%patch52 -p1 -b .useradd_SUB_UID_COUNT-0 +%patch53 -p1 -b .libsubid_simplify_ranges_variable +%patch54 -p1 -b .libsubid_init_not_print_error_messages +%patch55 -p1 -b .libsubid_fix_newusers_nss_provides_subids +%patch56 -p1 -b .man_clarify_subid_delegation +%patch57 -p1 -b .libsubid_make_logfd_not_extern iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -320,6 +345,16 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jun 21 2021 Iker Pedrosa - 2:4.8.1-11 +- libsubid: don't print error messages on stderr by default +- libsubid: libsubid_init return false if out of memory +- useradd: fix SUB_UID_COUNT=0 +- libsubid: don't return owner in list_owner_ranges API call +- libsubid: libsubid_init don't print messages on error +- libsubid: fix newusers when nss provides subids +- man: clarify subid delegation +- libsubid: make shadow_logfd not extern + * Thu May 6 2021 Iker Pedrosa - 2:4.8.1-10 - man: mention NSS in new[ug]idmap manpages - libsubid: move development header to shadow folder From cb2f54a2c1acc479e370af2480471e87fc29f750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Thu, 3 Jun 2021 15:53:35 +0200 Subject: [PATCH 014/118] Backport support for yescrypt hash method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-yescrypt-support.patch | 960 ++++++++++++++++++++++++++++ shadow-utils.login.defs | 18 +- shadow-utils.spec | 9 +- 3 files changed, 984 insertions(+), 3 deletions(-) create mode 100644 shadow-4.8.1-yescrypt-support.patch diff --git a/shadow-4.8.1-yescrypt-support.patch b/shadow-4.8.1-yescrypt-support.patch new file mode 100644 index 0000000..aff941b --- /dev/null +++ b/shadow-4.8.1-yescrypt-support.patch @@ -0,0 +1,960 @@ +From 5cd04d03f94622c12220d4a6352824af081b8531 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= +Date: Sun, 27 Dec 2020 21:09:25 +0100 +Subject: [PATCH] Add yescrypt support + +--- + configure.ac | 13 +++++ + etc/login.defs | 14 +++++ + lib/encrypt.c | 3 ++ + lib/getdef.c | 3 ++ + libmisc/obscure.c | 3 ++ + libmisc/salt.c | 94 +++++++++++++++++++++++++++++++- + src/chgpasswd.c | 113 ++++++++++++++++++++------------------ + src/chpasswd.c | 107 +++++++++++++++++++----------------- + src/newusers.c | 134 +++++++++++++++++++++++++--------------------- + src/passwd.c | 3 ++ + 10 files changed, 322 insertions(+), 165 deletions(-) + +Index: shadow-4.8.1/configure.ac +=================================================================== +--- shadow-4.8.1.orig/configure.ac ++++ shadow-4.8.1/configure.ac +@@ -290,6 +290,9 @@ AC_ARG_WITH(sha-crypt, + AC_ARG_WITH(bcrypt, + [AC_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])], + [with_bcrypt=$withval], [with_bcrypt=no]) ++AC_ARG_WITH(yescrypt, ++ [AC_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])], ++ [with_yescrypt=$withval], [with_yescrypt=no]) + AC_ARG_WITH(nscd, + [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])], + [with_nscd=$withval], [with_nscd=yes]) +@@ -322,6 +325,11 @@ if test "$with_bcrypt" = "yes"; then + AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm]) + fi + ++AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes") ++if test "$with_yescrypt" = "yes"; then ++ AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm]) ++fi ++ + if test "$with_nscd" = "yes"; then + AC_CHECK_FUNC(posix_spawn, + [AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])], +@@ -402,6 +410,10 @@ AC_SUBST(LIBCRYPT) + AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], + [AC_MSG_ERROR([crypt() not found])]) + ++AC_SUBST(LIYESCRYPT) ++AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt], ++ [AC_MSG_ERROR([crypt() not found])]) ++ + AC_SUBST(LIBACL) + if test "$with_acl" != "no"; then + AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"]) +@@ -752,6 +764,7 @@ echo " shadow group support: $enable_sh + echo " S/Key support: $with_skey" + echo " SHA passwords encryption: $with_sha_crypt" + echo " bcrypt passwords encryption: $with_bcrypt" ++echo " yescrypt passwords encryption: $with_yescrypt" + echo " nscd support: $with_nscd" + echo " sssd support: $with_sssd" + echo " subordinate IDs support: $enable_subids" +Index: shadow-4.8.1/etc/login.defs +=================================================================== +--- shadow-4.8.1.orig/etc/login.defs ++++ shadow-4.8.1/etc/login.defs +@@ -326,6 +326,7 @@ CHFN_RESTRICT rwh + # If set to SHA256, SHA256-based algorithm will be used for encrypting password + # If set to SHA512, SHA512-based algorithm will be used for encrypting password + # If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password ++# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password + # If set to DES, DES-based algorithm will be used for encrypting password (default) + # Overrides the MD5_CRYPT_ENAB option + # +@@ -366,6 +367,19 @@ CHFN_RESTRICT rwh + #BCRYPT_MAX_ROUNDS 13 + + # ++# Only works if ENCRYPT_METHOD is set to YESCRYPT. ++# ++# Define the YESCRYPT cost factor. ++# With a higher cost factor, it is more difficult to brute-force the password. ++# However, more CPU time and more memory will be needed to authenticate users ++# if this value is increased. ++# ++# If not specified, a cost factor of 5 will be used. ++# The value must be within the 1-11 range. ++# ++#YESCRYPT_COST_FACTOR 5 ++ ++# + # List of groups to add to the user's supplementary group set + # when logging in from the console (as determined by the CONSOLE + # setting). Default is none. +Index: shadow-4.8.1/lib/encrypt.c +=================================================================== +--- shadow-4.8.1.orig/lib/encrypt.c ++++ shadow-4.8.1/lib/encrypt.c +@@ -74,6 +74,9 @@ + case '6': + method = "SHA512"; + break; ++ case 'y': ++ method = "YESCRYPT"; ++ break; + default: + { + static char nummethod[4] = "$x$"; +Index: shadow-4.8.1/lib/getdef.c +=================================================================== +--- shadow-4.8.1.orig/lib/getdef.c ++++ shadow-4.8.1/lib/getdef.c +@@ -117,6 +117,9 @@ static struct itemdef def_table[] = { + {"BCRYPT_MAX_ROUNDS", NULL}, + {"BCRYPT_MIN_ROUNDS", NULL}, + #endif ++#ifdef USE_YESCRYPT ++ {"YESCRYPT_COST_FACTOR", NULL}, ++#endif + {"SUB_GID_COUNT", NULL}, + {"SUB_GID_MAX", NULL}, + {"SUB_GID_MIN", NULL}, +Index: shadow-4.8.1/libmisc/obscure.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/obscure.c ++++ shadow-4.8.1/libmisc/obscure.c +@@ -272,6 +272,9 @@ static /*@observer@*//*@null@*/const cha + #ifdef USE_BCRYPT + || (strcmp (result, "BCRYPT") == 0) + #endif ++#ifdef USE_YESCRYPT ++ || (strcmp (result, "YESCRYPT") == 0) ++#endif + ) { + return NULL; + } +Index: shadow-4.8.1/libmisc/salt.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/salt.c ++++ shadow-4.8.1/libmisc/salt.c +@@ -32,6 +32,10 @@ static /*@observer@*/const char *SHA_sal + static /*@observer@*/const char *gensalt_bcrypt (void); + static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds); + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++static /*@observer@*/const char *gensalt_yescrypt (void); ++static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_rounds); ++#endif /* USE_YESCRYPT */ + + #ifndef HAVE_L64A + static /*@observer@*/char *l64a(long value) +@@ -263,6 +267,78 @@ static /*@observer@*/const char *gensalt + } + #endif /* USE_BCRYPT */ + ++#ifdef USE_YESCRYPT ++/* Default cost if not explicitly specified. */ ++#define Y_COST_DEFAULT 5 ++/* Minimum cost. */ ++#define Y_COST_MIN 1 ++/* Maximum cost. */ ++#define Y_COST_MAX 11 ++/* ++ * Return a salt prefix specifying the cost for the YESCRYPT method. ++ */ ++static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_cost) ++{ ++ static char cost_prefix[5]; ++ long cost; ++ ++ if (NULL == prefered_cost) { ++ cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); ++ } else { ++ cost = *prefered_cost; ++ } ++ ++ if (cost < Y_COST_MIN) { ++ cost = Y_COST_MIN; ++ } ++ if (cost > Y_COST_MAX) { ++ cost = Y_COST_MAX; ++ } ++ ++ cost_prefix[0] = 'j'; ++ if (cost < 3) { ++ cost_prefix[1] = 0x36 + cost; ++ } else if (cost < 6) { ++ cost_prefix[1] = 0x34 + cost; ++ } else { ++ cost_prefix[1] = 0x3b + cost; ++ } ++ cost_prefix[2] = cost >= 3 ? 'T' : '5'; ++ cost_prefix[3] = '$'; ++ cost_prefix[4] = 0; ++ ++ return cost_prefix; ++} ++ ++/* ++ * Default number of base64 characters used for the salt. ++ * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more ++ * traditional 128 bits (16 bytes) salt, this 144 bits salt is always ++ * represented by the same number of base64 characters without padding ++ * issue, even with a non-standard base64 encoding scheme. ++ */ ++#define YESCRYPT_SALT_SIZE 24 ++/* ++ * Generate a 22 character salt string for yescrypt. ++ */ ++static /*@observer@*/const char *gensalt_yescrypt (void) ++{ ++ static char salt[32]; ++ ++ salt[0] = '\0'; ++ ++ seedRNG (); ++ strcat (salt, l64a (random())); ++ do { ++ strcat (salt, l64a (random())); ++ } while (strlen (salt) < YESCRYPT_SALT_SIZE); ++ ++ salt[YESCRYPT_SALT_SIZE] = '\0'; ++ ++ return salt; ++} ++#endif /* USE_YESCRYPT */ ++ + /* + * Generate salt of size salt_size. + */ +@@ -302,6 +378,7 @@ static /*@observer@*/const char *gensalt + * If meth is specified, an additional parameter can be provided. + * * For the SHA256 and SHA512 method, this specifies the number of rounds + * (if not NULL). ++ * * For the YESCRYPT method, this specifies the cost factor (if not NULL). + */ + /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg) + { +@@ -333,6 +410,11 @@ static /*@observer@*/const char *gensalt + BCRYPTMAGNUM(result); + strcat(result, BCRYPT_salt_rounds((int *)arg)); + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++ } else if (0 == strcmp (method, "YESCRYPT")) { ++ MAGNUM(result, 'y'); ++ strcat(result, YESCRYPT_salt_cost((int *)arg)); ++#endif /* USE_YESCRYPT */ + #ifdef USE_SHA_CRYPT + } else if (0 == strcmp (method, "SHA256")) { + MAGNUM(result, '5'); +@@ -362,11 +444,21 @@ static /*@observer@*/const char *gensalt + return result; + } else { + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++ if (0 == strcmp (method, "YESCRYPT")) { ++ strncat (result, gensalt_yescrypt (), ++ sizeof (result) - strlen (result) - 1); ++ return result; ++ } else { ++#endif /* USE_YESCRYPT */ + strncat (result, gensalt (salt_len), + sizeof (result) - strlen (result) - 1); ++#ifdef USE_YESCRYPT ++ } ++#endif /* USE_YESCRYPT */ + #ifdef USE_BCRYPT + } +-#endif /* USE_BCRYPT */ ++#endif /* USE_BCRYPT */ + + return result; + } +Index: shadow-4.8.1/src/chgpasswd.c +=================================================================== +--- shadow-4.8.1.orig/src/chgpasswd.c ++++ shadow-4.8.1/src/chgpasswd.c +@@ -69,9 +69,9 @@ const char *Prog; + FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + static bool sflg = false; +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + + static /*@null@*//*@observer@*/const char *crypt_method = NULL; + #define cflg (NULL != crypt_method) +@@ -81,6 +81,9 @@ static long sha_rounds = 5000; + #ifdef USE_BCRYPT + static long bcrypt_rounds = 13; + #endif ++#ifdef USE_YESCRYPT ++static long yescrypt_cost = 5; ++#endif + + #ifdef SHADOWGRP + static bool is_shadow_grp; +@@ -139,14 +142,15 @@ static /*@noreturn@*/void usage (int sta + Prog); + (void) fprintf (usageout, + _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), +-#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) + "NONE DES MD5" +-#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +- "NONE DES MD5 SHA256 SHA512 BCRYPT" +-#elif defined(USE_SHA_CRYPT) +- "NONE DES MD5 SHA256 SHA512" +-#else +- "NONE DES MD5 BCRYPT" ++#if defined(USE_SHA_CRYPT) ++ " SHA256 SHA512" ++#endif ++#if defined(USE_BCRYPT) ++ " BCRYPT" ++#endif ++#if defined(USE_YESCRYPT) ++ " YESCRYPT" + #endif + ); + (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); +@@ -155,11 +159,11 @@ static /*@noreturn@*/void usage (int sta + " the MD5 algorithm\n"), + usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" +- " crypt algorithms\n"), ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" ++ " or YESCRYPT crypt algorithms\n"), + usageout); +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + (void) fputs ("\n", usageout); + + exit (status); +@@ -173,19 +177,22 @@ static /*@noreturn@*/void usage (int sta + static void process_flags (int argc, char **argv) + { + int c; ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ int bad_s; ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + static struct option long_options[] = { + {"crypt-method", required_argument, NULL, 'c'}, + {"encrypted", no_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {"md5", no_argument, NULL, 'm'}, + {"root", required_argument, NULL, 'R'}, +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + {"sha-rounds", required_argument, NULL, 's'}, +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + {NULL, 0, NULL, '\0'} + }; + while ((c = getopt_long (argc, argv, +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + "c:ehmR:s:", + #else + "c:ehmR:", +@@ -206,40 +213,36 @@ static void process_flags (int argc, cha + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': + sflg = true; ++ bad_s = 0; ++#if defined(USE_SHA_CRYPT) + if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) +- && (0 == getlong(optarg, &sha_rounds))) +- || ( (0 == strcmp (crypt_method, "BCRYPT")) ++ && (0 == getlong(optarg, &sha_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) ++ if (( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &bcrypt_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) ++ if (( (0 == strcmp (crypt_method, "YESCRYPT")) ++ && (0 == getlong(optarg, &yescrypt_cost)))) { ++ bad_s = 1; ++ } ++#endif /* USE_YESCRYPT */ ++ if (bad_s != 0) { + fprintf (stderr, + _("%s: invalid numeric argument '%s'\n"), + Prog, optarg); + usage (E_USAGE); + } + break; +-#elif defined(USE_SHA_CRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &sha_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (E_USAGE); +- } +- break; +-#elif defined(USE_BCRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &bcrypt_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (E_USAGE); +- } +- break; +-#endif ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + + default: + usage (E_USAGE); +@@ -258,7 +261,7 @@ static void process_flags (int argc, cha + */ + static void check_flags (void) + { +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg && !cflg) { + fprintf (stderr, + _("%s: %s flag is only allowed with the %s flag\n"), +@@ -282,10 +285,13 @@ static void check_flags (void) + #ifdef USE_SHA_CRYPT + && (0 != strcmp (crypt_method, "SHA256")) + && (0 != strcmp (crypt_method, "SHA512")) +-#endif ++#endif /* USE_SHA_CRYPT */ + #ifdef USE_BCRYPT + && (0 != strcmp (crypt_method, "BCRYPT")) +-#endif ++#endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++ && (0 != strcmp (crypt_method, "YESCRYPT")) ++#endif /* USE_YESCRYPT */ + ) { + fprintf (stderr, + _("%s: unsupported crypt method: %s\n"), +@@ -592,23 +598,24 @@ int main (int argc, char **argv) + if (md5flg) { + crypt_method = "MD5"; + } +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg) { ++#if defined(USE_SHA_CRYPT) + if ( (0 == strcmp (crypt_method, "SHA256")) + || (0 == strcmp (crypt_method, "SHA512"))) { + arg = &sha_rounds; + } +- else if (0 == strcmp (crypt_method, "BCRYPT")) { ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) ++ if (0 == strcmp (crypt_method, "BCRYPT")) { + arg = &bcrypt_rounds; + } +- } +-#elif defined(USE_SHA_CRYPT) +- if (sflg) { +- arg = &sha_rounds; +- } +-#elif defined(USE_BCRYPT) +- if (sflg) { +- arg = &bcrypt_rounds; ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) ++ if (0 == strcmp (crypt_method, "YESCRYPT")) { ++ arg = &yescrypt_cost; ++ } ++#endif /* USE_YESCRYPT */ + } + #endif + salt = crypt_make_salt (crypt_method, arg); +Index: shadow-4.8.1/src/chpasswd.c +=================================================================== +--- shadow-4.8.1.orig/src/chpasswd.c ++++ shadow-4.8.1/src/chpasswd.c +@@ -66,7 +66,7 @@ const char *Prog; + FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + static bool sflg = false; + #endif + +@@ -78,6 +78,9 @@ static long sha_rounds = 5000; + #ifdef USE_BCRYPT + static long bcrypt_rounds = 13; + #endif ++#ifdef USE_YESCRYPT ++static long yescrypt_cost = 5; ++#endif + + static bool is_shadow_pwd; + static bool pw_locked = false; +@@ -129,14 +132,15 @@ static /*@noreturn@*/void usage (int sta + Prog); + (void) fprintf (usageout, + _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), +-#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) + "NONE DES MD5" +-#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +- "NONE DES MD5 SHA256 SHA512 BCRYPT" +-#elif defined(USE_SHA_CRYPT) +- "NONE DES MD5 SHA256 SHA512" +-#else +- "NONE DES MD5 BCRYPT" ++#if defined(USE_SHA_CRYPT) ++ " SHA256 SHA512" ++#endif ++#if defined(USE_BCRYPT) ++ " BCRYPT" ++#endif ++#if defined(USE_YESCRYPT) ++ " YESCRYPT" + #endif + ); + (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); +@@ -145,11 +149,11 @@ static /*@noreturn@*/void usage (int sta + " the MD5 algorithm\n"), + usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" +- " crypt algorithms\n"), ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" ++ " or YESCRYPT crypt algorithms\n"), + usageout); +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + (void) fputs ("\n", usageout); + + exit (status); +@@ -163,20 +167,23 @@ static /*@noreturn@*/void usage (int sta + static void process_flags (int argc, char **argv) + { + int c; ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ int bad_s; ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + static struct option long_options[] = { + {"crypt-method", required_argument, NULL, 'c'}, + {"encrypted", no_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {"md5", no_argument, NULL, 'm'}, + {"root", required_argument, NULL, 'R'}, +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + {"sha-rounds", required_argument, NULL, 's'}, +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + {NULL, 0, NULL, '\0'} + }; + + while ((c = getopt_long (argc, argv, +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + "c:ehmR:s:", + #else + "c:ehmR:", +@@ -197,40 +204,36 @@ static void process_flags (int argc, cha + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': + sflg = true; ++ bad_s = 0; ++#if defined(USE_SHA_CRYPT) + if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) +- && (0 == getlong(optarg, &sha_rounds))) +- || ( (0 == strcmp (crypt_method, "BCRYPT")) ++ && (0 == getlong(optarg, &sha_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) ++ if (( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &bcrypt_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) ++ if (( (0 == strcmp (crypt_method, "YESCRYPT")) ++ && (0 == getlong(optarg, &yescrypt_cost)))) { ++ bad_s = 1; ++ } ++#endif /* USE_YESCRYPT */ ++ if (bad_s != 0) { + fprintf (stderr, + _("%s: invalid numeric argument '%s'\n"), + Prog, optarg); + usage (E_USAGE); + } + break; +-#elif defined(USE_SHA_CRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &sha_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (E_USAGE); +- } +- break; +-#elif defined(USE_BCRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &bcrypt_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (E_USAGE); +- } +- break; +-#endif ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + + default: + usage (E_USAGE); +@@ -249,7 +252,7 @@ static void process_flags (int argc, cha + */ + static void check_flags (void) + { +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg && !cflg) { + fprintf (stderr, + _("%s: %s flag is only allowed with the %s flag\n"), +@@ -277,6 +280,9 @@ static void check_flags (void) + #ifdef USE_BCRYPT + && (0 != strcmp (crypt_method, "BCRYPT")) + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++ && (0 != strcmp (crypt_method, "YESCRYPT")) ++#endif /* USE_YESCRYPT */ + ) { + fprintf (stderr, + _("%s: unsupported crypt method: %s\n"), +@@ -604,23 +610,24 @@ int main (int argc, char **argv) + if (md5flg) { + crypt_method = "MD5"; + } +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg) { ++#if defined(USE_SHA_CRYPT) + if ( (0 == strcmp (crypt_method, "SHA256")) + || (0 == strcmp (crypt_method, "SHA512"))) { + arg = &sha_rounds; + } +- else if (0 == strcmp (crypt_method, "BCRYPT")) { ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) ++ if (0 == strcmp (crypt_method, "BCRYPT")) { + arg = &bcrypt_rounds; + } +- } +-#elif defined(USE_SHA_CRYPT) +- if (sflg) { +- arg = &sha_rounds; +- } +-#elif defined(USE_BCRYPT) +- if (sflg) { +- arg = &bcrypt_rounds; ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) ++ if (0 == strcmp (crypt_method, "YESCRYPT")) { ++ arg = &yescrypt_cost; ++ } ++#endif /* USE_YESCRYPT */ + } + #endif + salt = crypt_make_salt (crypt_method, arg); +Index: shadow-4.8.1/src/newusers.c +=================================================================== +--- shadow-4.8.1.orig/src/newusers.c ++++ shadow-4.8.1/src/newusers.c +@@ -90,6 +90,9 @@ static long sha_rounds = 5000; + #ifdef USE_BCRYPT + static long bcrypt_rounds = 13; + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++static long yescrypt_cost = 5; ++#endif /* USE_YESCRYPT */ + #endif /* !USE_PAM */ + + static bool is_shadow; +@@ -140,14 +143,15 @@ static void usage (int status) + #ifndef USE_PAM + (void) fprintf (usageout, + _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), +-#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) +- "NONE DES MD5" +-#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) +- "NONE DES MD5 SHA256 SHA512 BCRYPT" +-#elif defined(USE_SHA_CRYPT) +- "NONE DES MD5 SHA256 SHA512" +-#else +- "NONE DES MD5 BCRYPT" ++ "NONE DES MD5" ++#if defined(USE_SHA_CRYPT) ++ " SHA256 SHA512" ++#endif ++#if defined(USE_BCRYPT) ++ " BCRYPT" ++#endif ++#if defined(USE_YESCRYPT) ++ " YESCRYPT" + #endif + ); + #endif /* !USE_PAM */ +@@ -155,11 +159,11 @@ static void usage (int status) + (void) fputs (_(" -r, --system create system accounts\n"), usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); + #ifndef USE_PAM +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" +- " crypt algorithms\n"), ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" ++ " or YESCRYPT crypt algorithms\n"), + usageout); +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ + (void) fputs ("\n", usageout); + +@@ -434,25 +438,28 @@ static int update_passwd (struct passwd + void *crypt_arg = NULL; + char *cp; + if (NULL != crypt_method) { +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) + if (sflg) { + if ( (0 == strcmp (crypt_method, "SHA256")) + || (0 == strcmp (crypt_method, "SHA512"))) { + crypt_arg = &sha_rounds; + } +- else if (0 == strcmp (crypt_method, "BCRYPT")) { +- crypt_arg = &bcrypt_rounds; +- } + } +-#elif defined(USE_SHA_CRYPT) ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) + if (sflg) { +- crypt_arg = &sha_rounds; ++ if (0 == strcmp (crypt_method, "BCRYPT")) { ++ crypt_arg = &bcrypt_rounds; ++ } + } +-#elif defined(USE_BCRYPT) ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) + if (sflg) { +- crypt_arg = &bcrypt_rounds; ++ if (0 == strcmp (crypt_method, "YESCRYPT")) { ++ crypt_arg = &yescrypt_cost; ++ } + } +-#endif ++#endif /* USE_YESCRYPT */ + } + + if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) { +@@ -485,25 +492,28 @@ static int add_passwd (struct passwd *pw + #ifndef USE_PAM + void *crypt_arg = NULL; + if (NULL != crypt_method) { +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) + if (sflg) { + if ( (0 == strcmp (crypt_method, "SHA256")) + || (0 == strcmp (crypt_method, "SHA512"))) { + crypt_arg = &sha_rounds; + } +- else if (0 == strcmp (crypt_method, "BCRYPT")) { +- crypt_arg = &bcrypt_rounds; +- } + } +-#elif defined(USE_SHA_CRYPT) ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) + if (sflg) { +- crypt_arg = &sha_rounds; ++ if (0 == strcmp (crypt_method, "BCRYPT")) { ++ crypt_arg = &bcrypt_rounds; ++ } + } +-#elif defined(USE_BCRYPT) ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) + if (sflg) { +- crypt_arg = &bcrypt_rounds; ++ if (0 == strcmp (crypt_method, "YESCRYPT")) { ++ crypt_arg = &yescrypt_cost; ++ } + } +-#endif ++#endif /* USE_PAM */ + } + + /* +@@ -620,6 +630,9 @@ static int add_passwd (struct passwd *pw + static void process_flags (int argc, char **argv) + { + int c; ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) ++ int bad_s; ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + static struct option long_options[] = { + {"badnames", no_argument, NULL, 'b'}, + #ifndef USE_PAM +@@ -629,20 +642,20 @@ static void process_flags (int argc, cha + {"system", no_argument, NULL, 'r'}, + {"root", required_argument, NULL, 'R'}, + #ifndef USE_PAM +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + {"sha-rounds", required_argument, NULL, 's'}, +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ + {NULL, 0, NULL, '\0'} + }; + + while ((c = getopt_long (argc, argv, + #ifndef USE_PAM +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + "c:bhrs:", +-#else /* !USE_SHA_CRYPT && !USE_BCRYPT */ ++#else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ + "c:bhr", +-#endif /* USE_SHA_CRYPT || USE_BCRYPT */ ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #else /* USE_PAM */ + "bhr", + #endif +@@ -665,40 +678,36 @@ static void process_flags (int argc, cha + case 'R': /* no-op, handled in process_root_flag () */ + break; + #ifndef USE_PAM +-#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': + sflg = true; ++ bad_s = 0; ++#if defined(USE_SHA_CRYPT) + if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) +- && (0 == getlong(optarg, &sha_rounds))) +- || ( (0 == strcmp (crypt_method, "BCRYPT")) ++ && (0 == getlong(optarg, &sha_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_SHA_CRYPT */ ++#if defined(USE_BCRYPT) ++ if (( (0 == strcmp (crypt_method, "BCRYPT")) + && (0 == getlong(optarg, &bcrypt_rounds)))) { ++ bad_s = 1; ++ } ++#endif /* USE_BCRYPT */ ++#if defined(USE_YESCRYPT) ++ if (( (0 == strcmp (crypt_method, "YESCRYPT")) ++ && (0 == getlong(optarg, &yescrypt_cost)))) { ++ bad_s = 1; ++ } ++#endif /* USE_YESCRYPT */ ++ if (bad_s != 0) { + fprintf (stderr, + _("%s: invalid numeric argument '%s'\n"), + Prog, optarg); + usage (EXIT_FAILURE); + } + break; +-#elif defined(USE_SHA_CRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &sha_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (EXIT_FAILURE); +- } +- break; +-#elif defined(USE_BCRYPT) +- case 's': +- sflg = true; +- if (0 == getlong(optarg, &bcrypt_rounds)) { +- fprintf (stderr, +- _("%s: invalid numeric argument '%s'\n"), +- Prog, optarg); +- usage (EXIT_FAILURE); +- } +- break; +-#endif ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ + default: + usage (EXIT_FAILURE); +@@ -732,14 +741,14 @@ static void process_flags (int argc, cha + static void check_flags (void) + { + #ifndef USE_PAM +-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) ++#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg && !cflg) { + fprintf (stderr, + _("%s: %s flag is only allowed with the %s flag\n"), + Prog, "-s", "-c"); + usage (EXIT_FAILURE); + } +-#endif ++#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + + if (cflg) { + if ( (0 != strcmp (crypt_method, "DES")) +@@ -752,6 +761,9 @@ static void check_flags (void) + #ifdef USE_BCRYPT + && (0 != strcmp (crypt_method, "BCRYPT")) + #endif /* USE_BCRYPT */ ++#ifdef USE_YESCRYPT ++ && (0 != strcmp (crypt_method, "YESCRYPT")) ++#endif /* USE_YESCRYPT */ + ) { + fprintf (stderr, + _("%s: unsupported crypt method: %s\n"), +Index: shadow-4.8.1/src/passwd.c +=================================================================== +--- shadow-4.8.1.orig/src/passwd.c ++++ shadow-4.8.1/src/passwd.c +@@ -283,7 +283,10 @@ static int new_password (const struct pa + #endif /* USE_SHA_CRYPT */ + #ifdef USE_BCRYPT + || (strcmp (method, "BCRYPT") == 0) +-#endif /* USE_SHA_CRYPT */ ++#endif /* USE_BCRYPT*/ ++#ifdef USE_YESCRYPT ++ || (strcmp (method, "YESCRYPT") == 0) ++#endif /* USE_YESCRYPT*/ + + ) { + pass_max_len = -1; diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index 7f1c0e4..67845ce 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -198,10 +198,11 @@ SUB_GID_COUNT 65536 # If set to MD5, MD5-based algorithm will be used for encrypting password # If set to SHA256, SHA256-based algorithm will be used for encrypting password # If set to SHA512, SHA512-based algorithm will be used for encrypting password -# If set to BLOWFISH, BLOWFISH-based algorithm will be used for encrypting password +# If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password +# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password # If set to DES, DES-based algorithm will be used for encrypting password (default) # -ENCRYPT_METHOD SHA512 +ENCRYPT_METHOD YESCRYPT # # Only works if ENCRYPT_METHOD is set to SHA256 or SHA512. @@ -220,6 +221,19 @@ ENCRYPT_METHOD SHA512 # Currently BCRYPT_MIN_ROUNDS and BCRYPT_MAX_ROUNDS are not supported +# +# Only works if ENCRYPT_METHOD is set to YESCRYPT. +# +# Define the YESCRYPT cost factor. +# With a higher cost factor, it is more difficult to brute-force the password. +# However, more CPU time and more memory will be needed to authenticate users +# if this value is increased. +# +# If not specified, a cost factor of 5 will be used. +# The value must be within the 1-11 range. +# +#YESCRYPT_COST_FACTOR 5 + # Currently CONSOLE_GROUPS is not supported # diff --git a/shadow-utils.spec b/shadow-utils.spec index 164c0d7..5511d03 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.8.1 -Release: 11%{?dist} +Release: 12%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -95,6 +95,8 @@ Patch55: shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch Patch56: shadow-4.8.1-man_clarify_subid_delegation.patch # https://github.com/shadow-maint/shadow/commit/bd920ab36a6c641e4a8769f8c7f8ca738ec61820 Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch +# https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531 +Patch58: shadow-4.8.1-yescrypt-support.patch License: BSD and GPLv2+ BuildRequires: make @@ -177,6 +179,7 @@ Development files for shadow-utils-subid. %patch55 -p1 -b .libsubid_fix_newusers_nss_provides_subids %patch56 -p1 -b .man_clarify_subid_delegation %patch57 -p1 -b .libsubid_make_logfd_not_extern +%patch58 -p1 -b .yescrypt iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -203,6 +206,7 @@ autoreconf --enable-man \ --with-audit \ --with-sha-crypt \ + --with-yescrypt \ --with-selinux \ --without-libcrack \ --without-libpam \ @@ -345,6 +349,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jun 21 2021 Björn Esser - 2:4.8.1-12 +- Backport support for yescrypt hash method + * Mon Jun 21 2021 Iker Pedrosa - 2:4.8.1-11 - libsubid: don't print error messages on stderr by default - libsubid: libsubid_init return false if out of memory From 0946f2a3b0a425180b61fceda0d763b55baf9949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Mon, 21 Jun 2021 14:49:14 +0200 Subject: [PATCH 015/118] Add a patch to fix the parameter type of YESCRYPT_salt_cost() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- ....1-fix_YESCRYPT_salt_cost_param_type.patch | 39 +++++++++++++++++++ shadow-utils.spec | 4 ++ 2 files changed, 43 insertions(+) create mode 100644 shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch diff --git a/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch b/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch new file mode 100644 index 0000000..a3aadd2 --- /dev/null +++ b/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch @@ -0,0 +1,39 @@ +From 8d987bc55ccb65a3ef3a541cc5e351cfcbef0c90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 12 Jun 2021 19:05:07 +0200 +Subject: [PATCH] libmisc/salt.c: Use int pointer for YESCRYPT_salt_cost(). +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The corresponding functions for the other hash methods all take +a pointer to an integer value as the only paramater, so this +particular function should do so as well. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index c35c6797..1bfa015b 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -34,7 +34,7 @@ static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rou + #endif /* USE_BCRYPT */ + #ifdef USE_YESCRYPT + static /*@observer@*/const char *gensalt_yescrypt (void); +-static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_rounds); ++static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost); + #endif /* USE_YESCRYPT */ + + #ifndef HAVE_L64A +@@ -277,7 +277,7 @@ static /*@observer@*/const char *gensalt_bcrypt (void) + /* + * Return a salt prefix specifying the cost for the YESCRYPT method. + */ +-static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_cost) ++static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost) + { + static char cost_prefix[5]; + long cost; diff --git a/shadow-utils.spec b/shadow-utils.spec index 5511d03..0f8a51e 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -97,6 +97,8 @@ Patch56: shadow-4.8.1-man_clarify_subid_delegation.patch Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch # https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531 Patch58: shadow-4.8.1-yescrypt-support.patch +# https://github.com/shadow-maint/shadow/pull/358 +Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch License: BSD and GPLv2+ BuildRequires: make @@ -180,6 +182,7 @@ Development files for shadow-utils-subid. %patch56 -p1 -b .man_clarify_subid_delegation %patch57 -p1 -b .libsubid_make_logfd_not_extern %patch58 -p1 -b .yescrypt +%patch59 -p1 -b .YESCRYPT_salt_cost_param_type iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -351,6 +354,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %changelog * Mon Jun 21 2021 Björn Esser - 2:4.8.1-12 - Backport support for yescrypt hash method +- Add a patch to fix the parameter type of YESCRYPT_salt_cost() * Mon Jun 21 2021 Iker Pedrosa - 2:4.8.1-11 - libsubid: don't print error messages on stderr by default From e967948ce81e6d64b718d32ead16ece478536b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Tue, 22 Jun 2021 21:59:30 +0200 Subject: [PATCH 016/118] Reference actual upstream commit for Patch59 --- shadow-utils.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 0f8a51e..2817429 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -97,7 +97,7 @@ Patch56: shadow-4.8.1-man_clarify_subid_delegation.patch Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch # https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531 Patch58: shadow-4.8.1-yescrypt-support.patch -# https://github.com/shadow-maint/shadow/pull/358 +# https://github.com/shadow-maint/shadow/commit/7a3bb4d0ea8166acc539c788a8ce943acf4a6aa7 Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch License: BSD and GPLv2+ From c5fd8d4a0a703f07b39e23909e7e5a4b4ef30592 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 28 Jun 2021 10:53:45 +0200 Subject: [PATCH 017/118] Covscan fixes --- shadow-4.8.1-covscan_fixes.patch | 802 +++++++++++++++++++++++++++++++ shadow-utils.spec | 13 +- 2 files changed, 814 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-covscan_fixes.patch diff --git a/shadow-4.8.1-covscan_fixes.patch b/shadow-4.8.1-covscan_fixes.patch new file mode 100644 index 0000000..ea78ced --- /dev/null +++ b/shadow-4.8.1-covscan_fixes.patch @@ -0,0 +1,802 @@ +From fd9d79a1a3438ba7703939cfcd45fc266782c64e Mon Sep 17 00:00:00 2001 +From: whzhe +Date: Thu, 17 Dec 2020 03:27:15 -0500 +Subject: [PATCH] useradd.c:fix memleak in get_groups + +Signed-off-by: whzhe +--- + src/useradd.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 107e65f8..822b67f5 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -793,6 +793,7 @@ static int get_groups (char *list) + fprintf (stderr, + _("%s: group '%s' is a NIS group.\n"), + Prog, grp->gr_name); ++ gr_free(grp); + continue; + } + #endif +@@ -801,6 +802,7 @@ static int get_groups (char *list) + fprintf (stderr, + _("%s: too many groups specified (max %d).\n"), + Prog, ngroups); ++ gr_free(grp); + break; + } + +@@ -808,6 +810,7 @@ static int get_groups (char *list) + * Add the group name to the user's list of groups. + */ + user_groups[ngroups++] = xstrdup (grp->gr_name); ++ gr_free (grp); + } while (NULL != list); + + close_group_files (); +-- +2.31.1 + +From c44b71cec25d60efc51aec9de3abce1f6efbfcf5 Mon Sep 17 00:00:00 2001 +From: whzhe51 +Date: Sat, 19 Dec 2020 04:29:06 -0500 +Subject: [PATCH] useradd.c:fix memleaks of grp Signed-off-by: whzhe51 + + +--- + src/useradd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/useradd.c b/src/useradd.c +index 107e65f8..29c54e44 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -411,6 +411,7 @@ static void get_defaults (void) + } else { + def_group = grp->gr_gid; + def_gname = xstrdup (grp->gr_name); ++ gr_free(grp); + } + } + +-- +2.31.1 + +From 1aed7ae945aafaeb253fc89a7ecedeaedf72654e Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 10 Jun 2021 13:05:03 +0200 +Subject: [PATCH] useradd.c: fix covscan RESOURCE_LEAK + +Error: RESOURCE_LEAK (CWE-772): [#def28] +shadow-4.8.1/src/useradd.c:1905: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/src/useradd.c:1905: var_assign: Assigning: "fd" = handle returned from "open("/var/log/faillog", 2)". +shadow-4.8.1/src/useradd.c:1906: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/useradd.c:1917: leaked_handle: Handle variable "fd" going out of scope leaks the handle. + 1915| /* continue */ + 1916| } + 1917|-> } + 1918| + 1919| static void lastlog_reset (uid_t uid) + +Error: RESOURCE_LEAK (CWE-772): [#def29] +shadow-4.8.1/src/useradd.c:1938: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/src/useradd.c:1938: var_assign: Assigning: "fd" = handle returned from "open("/var/log/lastlog", 2)". +shadow-4.8.1/src/useradd.c:1939: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/useradd.c:1950: leaked_handle: Handle variable "fd" going out of scope leaks the handle. + 1948| /* continue */ + 1949| } + 1950|-> } + 1951| + 1952| static void tallylog_reset (const char *user_name) + +Error: RESOURCE_LEAK (CWE-772): [#def30] +shadow-4.8.1/src/useradd.c:2109: alloc_fn: Storage is returned from allocation function "strdup". +shadow-4.8.1/src/useradd.c:2109: var_assign: Assigning: "bhome" = storage returned from "strdup(prefix_user_home)". +shadow-4.8.1/src/useradd.c:2131: noescape: Resource "bhome" is not freed or pointed-to in "strtok". +shadow-4.8.1/src/useradd.c:2207: leaked_storage: Variable "bhome" going out of scope leaks the storage it points to. + 2205| } + 2206| #endif + 2207|-> } + 2208| } + 2209| +--- + src/useradd.c | 41 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 32 insertions(+), 9 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 4248b62c..127177e2 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1964,16 +1964,26 @@ static void faillog_reset (uid_t uid) + memzero (&fl, sizeof (fl)); + + fd = open (FAILLOG_FILE, O_RDWR); +- if ( (-1 == fd) +- || (lseek (fd, offset_uid, SEEK_SET) != offset_uid) ++ if (-1 == fd) { ++ fprintf (stderr, ++ _("%s: failed to open the faillog file for UID %lu: %s\n"), ++ Prog, (unsigned long) uid, strerror (errno)); ++ SYSLOG ((LOG_WARN, "failed to open the faillog file for UID %lu", (unsigned long) uid)); ++ return; ++ } ++ if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) + || (write (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl)) +- || (fsync (fd) != 0) +- || (close (fd) != 0)) { ++ || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to reset the faillog entry of UID %lu: %s\n"), + Prog, (unsigned long) uid, strerror (errno)); + SYSLOG ((LOG_WARN, "failed to reset the faillog entry of UID %lu", (unsigned long) uid)); +- /* continue */ ++ } ++ if (close (fd) != 0) { ++ fprintf (stderr, ++ _("%s: failed to close the faillog file for UID %lu: %s\n"), ++ Prog, (unsigned long) uid, strerror (errno)); ++ SYSLOG ((LOG_WARN, "failed to close the faillog file for UID %lu", (unsigned long) uid)); + } + } + +@@ -1997,17 +2007,29 @@ static void lastlog_reset (uid_t uid) + memzero (&ll, sizeof (ll)); + + fd = open (LASTLOG_FILE, O_RDWR); +- if ( (-1 == fd) +- || (lseek (fd, offset_uid, SEEK_SET) != offset_uid) ++ if (-1 == fd) { ++ fprintf (stderr, ++ _("%s: failed to open the lastlog file for UID %lu: %s\n"), ++ Prog, (unsigned long) uid, strerror (errno)); ++ SYSLOG ((LOG_WARN, "failed to open the lastlog file for UID %lu", (unsigned long) uid)); ++ return; ++ } ++ if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) + || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) +- || (fsync (fd) != 0) +- || (close (fd) != 0)) { ++ || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), + Prog, (unsigned long) uid, strerror (errno)); + SYSLOG ((LOG_WARN, "failed to reset the lastlog entry of UID %lu", (unsigned long) uid)); + /* continue */ + } ++ if (close (fd) != 0) { ++ fprintf (stderr, ++ _("%s: failed to close the lastlog file for UID %lu: %s\n"), ++ Prog, (unsigned long) uid, strerror (errno)); ++ SYSLOG ((LOG_WARN, "failed to close the lastlog file for UID %lu", (unsigned long) uid)); ++ /* continue */ ++ } + } + + static void tallylog_reset (const char *user_name) +@@ -2254,6 +2276,7 @@ static void create_home (void) + } + cp = strtok (NULL, "/"); + } ++ free (bhome); + + (void) chown (prefix_user_home, user_id, user_gid); + mode_t mode = getdef_num ("HOME_MODE", +-- +2.31.1 + +From 8281c82e324b57b3a4b520afad26b43ce128d521 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 11 Jun 2021 11:50:49 +0200 +Subject: [PATCH] usermod.c: fix covscan RESOURCE_LEAK + +Error: RESOURCE_LEAK (CWE-772): [#def31] +shadow-4.8.1/src/usermod.c:813: alloc_fn: Storage is returned from allocation function "__gr_dup". +shadow-4.8.1/src/usermod.c:813: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)". +shadow-4.8.1/src/usermod.c:892: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to. + 890| } + 891| } + 892|-> } + 893| + 894| #ifdef SHADOWGRP + +Error: RESOURCE_LEAK (CWE-772): [#def32] +shadow-4.8.1/src/usermod.c:933: alloc_fn: Storage is returned from allocation function "__sgr_dup". +shadow-4.8.1/src/usermod.c:933: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)". +shadow-4.8.1/src/usermod.c:1031: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to. + 1029| } + 1030| } + 1031|-> } + 1032| #endif /* SHADOWGRP */ + 1033| + +Error: RESOURCE_LEAK (CWE-772): [#def34] +shadow-4.8.1/src/usermod.c:1161: alloc_fn: Storage is returned from allocation function "getgr_nam_gid". +shadow-4.8.1/src/usermod.c:1161: var_assign: Assigning: "grp" = storage returned from "getgr_nam_gid(optarg)". +shadow-4.8.1/src/usermod.c:1495: leaked_storage: Variable "grp" going out of scope leaks the storage it points to. + 1493| } + 1494| #endif /* ENABLE_SUBIDS */ + 1495|-> } + 1496| + 1497| /* + +Error: RESOURCE_LEAK (CWE-772): [#def35] +shadow-4.8.1/src/usermod.c:1991: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/src/usermod.c:1991: var_assign: Assigning: "fd" = handle returned from "open("/var/log/lastlog", 2)". +shadow-4.8.1/src/usermod.c:2000: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/usermod.c:2000: noescape: Resource "fd" is not freed or pointed-to in "read". [Note: The source code implementation of the function has been overridden by a builtin model.] +shadow-4.8.1/src/usermod.c:2003: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/usermod.c:2032: leaked_handle: Handle variable "fd" going out of scope leaks the handle. + 2030| } + 2031| } + 2032|-> } + 2033| + 2034| /* + +Error: RESOURCE_LEAK (CWE-772): [#def36] +shadow-4.8.1/src/usermod.c:2052: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/src/usermod.c:2052: var_assign: Assigning: "fd" = handle returned from "open("/var/log/faillog", 2)". +shadow-4.8.1/src/usermod.c:2061: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/usermod.c:2061: noescape: Resource "fd" is not freed or pointed-to in "read". [Note: The source code implementation of the function has been overridden by a builtin model.] +shadow-4.8.1/src/usermod.c:2064: noescape: Resource "fd" is not freed or pointed-to in "lseek". +shadow-4.8.1/src/usermod.c:2092: leaked_handle: Handle variable "fd" going out of scope leaks the handle. + 2090| } + 2091| } + 2092|-> } + 2093| + 2094| #ifndef NO_MOVE_MAILBOX +--- + src/usermod.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 7870ba57..03bb9b9d 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -871,6 +871,8 @@ static void update_group (void) + SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); + fail_exit (E_GRP_UPDATE); + } ++ ++ gr_free(ngrp); + } + } + +@@ -1006,6 +1008,8 @@ static void update_gshadow (void) + sgr_dbname (), nsgrp->sg_name)); + fail_exit (E_GRP_UPDATE); + } ++ ++ free (nsgrp); + } + } + #endif /* SHADOWGRP */ +@@ -1152,6 +1156,7 @@ static void process_flags (int argc, char **argv) + } + user_newgid = grp->gr_gid; + gflg = true; ++ gr_free (grp); + break; + case 'G': + if (get_groups (optarg) != 0) { +@@ -1995,8 +2000,7 @@ static void update_lastlog (void) + /* Copy the old entry to its new location */ + if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) + || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll) +- || (fsync (fd) != 0) +- || (close (fd) != 0)) { ++ || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"), + Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); +@@ -2012,16 +2016,15 @@ static void update_lastlog (void) + memzero (&ll, sizeof (ll)); + if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) + || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll) +- || (fsync (fd) != 0) +- || (close (fd) != 0)) { ++ || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"), + Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); + } +- } else { +- (void) close (fd); + } + } ++ ++ (void) close (fd); + } + + /* +@@ -2056,8 +2059,7 @@ static void update_faillog (void) + /* Copy the old entry to its new location */ + if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) + || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl) +- || (fsync (fd) != 0) +- || (close (fd) != 0)) { ++ || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"), + Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); +@@ -2072,16 +2074,15 @@ static void update_faillog (void) + /* Reset the new uid's faillog entry */ + memzero (&fl, sizeof (fl)); + if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) +- || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl) +- || (close (fd) != 0)) { ++ || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) { + fprintf (stderr, + _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"), + Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); + } +- } else { +- (void) close (fd); + } + } ++ ++ (void) close (fd); + } + + #ifndef NO_MOVE_MAILBOX +-- +2.31.1 + +From 5d0d7841971cc53d9a9d1aefe12f00204115bf6a Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Wed, 16 Jun 2021 09:50:53 +0200 +Subject: [PATCH] Fix covscan BUFFER_SIZE + +Error: BUFFER_SIZE (CWE-170): [#def6] +shadow-4.8.1/libmisc/failure.c:101: buffer_size_warning: Calling "strncpy" with a maximum size argument of 12 bytes on destination array "fl->fail_line" of size 12 bytes might leave the destination string unterminated. + 99| } + 100| + 101|-> strncpy (fl->fail_line, tty, sizeof fl->fail_line); + 102| (void) time (&fl->fail_time); + 103| + +Error: BUFFER_SIZE (CWE-170): [#def9] +shadow-4.8.1/libmisc/log.c:103: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "newlog.ll_line" of size 32 bytes might leave the destination string unterminated. + 101| (void) time (&ll_time); + 102| newlog.ll_time = ll_time; + 103|-> strncpy (newlog.ll_line, line, sizeof newlog.ll_line); + 104| #if HAVE_LL_HOST + 105| strncpy (newlog.ll_host, host, sizeof newlog.ll_host); + +Error: BUFFER_SIZE (CWE-170): [#def10] +shadow-4.8.1/libmisc/log.c:105: buffer_size_warning: Calling "strncpy" with a maximum size argument of 256 bytes on destination array "newlog.ll_host" of size 256 bytes might leave the destination string unterminated. + 103| strncpy (newlog.ll_line, line, sizeof newlog.ll_line); + 104| #if HAVE_LL_HOST + 105|-> strncpy (newlog.ll_host, host, sizeof newlog.ll_host); + 106| #endif + 107| if ( (lseek (fd, offset, SEEK_SET) != offset) + +Error: BUFFER_SIZE (CWE-170): [#def13] +shadow-4.8.1/libmisc/utmp.c:260: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "utent->ut_line" of size 32 bytes might leave the destination string unterminated. + 258| #endif /* HAVE_STRUCT_UTMP_UT_TYPE */ + 259| utent->ut_pid = getpid (); + 260|-> strncpy (utent->ut_line, line, sizeof (utent->ut_line)); + 261| #ifdef HAVE_STRUCT_UTMP_UT_ID + 262| if (NULL != ut) { + +Error: BUFFER_SIZE (CWE-170): [#def14] +shadow-4.8.1/libmisc/utmp.c:266: buffer_size_warning: Calling "strncpy" with a maximum size argument of 4 bytes on destination array "utent->ut_id" of size 4 bytes might leave the destination string unterminated. + 264| } else { + 265| /* XXX - assumes /dev/tty?? */ + 266|-> strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id)); + 267| } + 268| #endif /* HAVE_STRUCT_UTMP_UT_ID */ + +Error: BUFFER_SIZE (CWE-170): [#def15] +shadow-4.8.1/libmisc/utmp.c:273: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "utent->ut_user" of size 32 bytes might leave the destination string unterminated. + 271| #endif /* HAVE_STRUCT_UTMP_UT_NAME */ + 272| #ifdef HAVE_STRUCT_UTMP_UT_USER + 273|-> strncpy (utent->ut_user, name, sizeof (utent->ut_user)); + 274| #endif /* HAVE_STRUCT_UTMP_UT_USER */ + 275| if (NULL != hostname) { + +Error: BUFFER_SIZE (CWE-170): [#def16] +shadow-4.8.1/libmisc/utmp.c:278: buffer_size_warning: Calling "strncpy" with a maximum size argument of 256 bytes on destination array "utent->ut_host" of size 256 bytes might leave the destination string unterminated. + 276| struct addrinfo *info = NULL; + 277| #ifdef HAVE_STRUCT_UTMP_UT_HOST + 278|-> strncpy (utent->ut_host, hostname, sizeof (utent->ut_host)); + 279| #endif /* HAVE_STRUCT_UTMP_UT_HOST */ + 280| #ifdef HAVE_STRUCT_UTMP_UT_SYSLEN + +Signed-off-by: Iker Pedrosa +--- + libmisc/failure.c | 2 +- + libmisc/log.c | 4 ++-- + libmisc/utmp.c | 8 ++++---- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/libmisc/failure.c b/libmisc/failure.c +index f6390a79..a1f3ec79 100644 +--- a/libmisc/failure.c ++++ b/libmisc/failure.c +@@ -98,7 +98,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl) + fl->fail_cnt++; + } + +- strncpy (fl->fail_line, tty, sizeof fl->fail_line); ++ strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1); + (void) time (&fl->fail_time); + + /* +diff --git a/libmisc/log.c b/libmisc/log.c +index eb84859e..68a9d7e2 100644 +--- a/libmisc/log.c ++++ b/libmisc/log.c +@@ -100,9 +100,9 @@ void dolastlog ( + ll_time = newlog.ll_time; + (void) time (&ll_time); + newlog.ll_time = ll_time; +- strncpy (newlog.ll_line, line, sizeof newlog.ll_line); ++ strncpy (newlog.ll_line, line, sizeof (newlog.ll_line) - 1); + #if HAVE_LL_HOST +- strncpy (newlog.ll_host, host, sizeof newlog.ll_host); ++ strncpy (newlog.ll_host, host, sizeof (newlog.ll_host) - 1); + #endif + if ( (lseek (fd, offset, SEEK_SET) != offset) + || (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog) +diff --git a/libmisc/utmp.c b/libmisc/utmp.c +index ba69cf61..5dcd419f 100644 +--- a/libmisc/utmp.c ++++ b/libmisc/utmp.c +@@ -257,25 +257,25 @@ static void updwtmpx (const char *filename, const struct utmpx *utx) + utent->ut_type = USER_PROCESS; + #endif /* HAVE_STRUCT_UTMP_UT_TYPE */ + utent->ut_pid = getpid (); +- strncpy (utent->ut_line, line, sizeof (utent->ut_line)); ++ strncpy (utent->ut_line, line, sizeof (utent->ut_line) - 1); + #ifdef HAVE_STRUCT_UTMP_UT_ID + if (NULL != ut) { + strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id)); + } else { + /* XXX - assumes /dev/tty?? */ +- strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id)); ++ strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id) - 1); + } + #endif /* HAVE_STRUCT_UTMP_UT_ID */ + #ifdef HAVE_STRUCT_UTMP_UT_NAME + strncpy (utent->ut_name, name, sizeof (utent->ut_name)); + #endif /* HAVE_STRUCT_UTMP_UT_NAME */ + #ifdef HAVE_STRUCT_UTMP_UT_USER +- strncpy (utent->ut_user, name, sizeof (utent->ut_user)); ++ strncpy (utent->ut_user, name, sizeof (utent->ut_user) - 1); + #endif /* HAVE_STRUCT_UTMP_UT_USER */ + if (NULL != hostname) { + struct addrinfo *info = NULL; + #ifdef HAVE_STRUCT_UTMP_UT_HOST +- strncpy (utent->ut_host, hostname, sizeof (utent->ut_host)); ++ strncpy (utent->ut_host, hostname, sizeof (utent->ut_host) - 1); + #endif /* HAVE_STRUCT_UTMP_UT_HOST */ + #ifdef HAVE_STRUCT_UTMP_UT_SYSLEN + utent->ut_syslen = MIN (strlen (hostname), +-- +2.31.1 + +From e65cc6aebcb4132fa413f00a905216a5b35b3d57 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 14 Jun 2021 12:39:48 +0200 +Subject: [PATCH] Fix covscan RESOURCE_LEAK + +Error: RESOURCE_LEAK (CWE-772): [#def1] +shadow-4.8.1/lib/commonio.c:320: alloc_fn: Storage is returned from allocation function "fopen_set_perms". +shadow-4.8.1/lib/commonio.c:320: var_assign: Assigning: "bkfp" = storage returned from "fopen_set_perms(backup, "w", &sb)". +shadow-4.8.1/lib/commonio.c:329: noescape: Resource "bkfp" is not freed or pointed-to in "putc". +shadow-4.8.1/lib/commonio.c:334: noescape: Resource "bkfp" is not freed or pointed-to in "fflush". +shadow-4.8.1/lib/commonio.c:339: noescape: Resource "bkfp" is not freed or pointed-to in "fileno". +shadow-4.8.1/lib/commonio.c:342: leaked_storage: Variable "bkfp" going out of scope leaks the storage it points to. + 340| || (fclose (bkfp) != 0)) { + 341| /* FIXME: unlink the backup file? */ + 342|-> return -1; + 343| } + 344| + +Error: RESOURCE_LEAK (CWE-772): [#def2] +shadow-4.8.1/libmisc/addgrps.c:69: alloc_fn: Storage is returned from allocation function "malloc". +shadow-4.8.1/libmisc/addgrps.c:69: var_assign: Assigning: "grouplist" = storage returned from "malloc(i * 4UL)". +shadow-4.8.1/libmisc/addgrps.c:73: noescape: Resource "grouplist" is not freed or pointed-to in "getgroups". [Note: The source code implementation of the function has been overridden by a builtin model.] +shadow-4.8.1/libmisc/addgrps.c:126: leaked_storage: Variable "grouplist" going out of scope leaks the storage it points to. + 124| } + 125| + 126|-> return 0; + 127| } + 128| #else /* HAVE_SETGROUPS && !USE_PAM */ + +Error: RESOURCE_LEAK (CWE-772): [#def3] +shadow-4.8.1/libmisc/chowntty.c:62: alloc_fn: Storage is returned from allocation function "getgr_nam_gid". +shadow-4.8.1/libmisc/chowntty.c:62: var_assign: Assigning: "grent" = storage returned from "getgr_nam_gid(getdef_str("TTYGROUP"))". +shadow-4.8.1/libmisc/chowntty.c:98: leaked_storage: Variable "grent" going out of scope leaks the storage it points to. + 96| */ + 97| #endif + 98|-> } + 99| + +Error: RESOURCE_LEAK (CWE-772): [#def4] +shadow-4.8.1/libmisc/copydir.c:742: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/libmisc/copydir.c:742: var_assign: Assigning: "ifd" = handle returned from "open(src, 0)". +shadow-4.8.1/libmisc/copydir.c:748: leaked_handle: Handle variable "ifd" going out of scope leaks the handle. + 746| #ifdef WITH_SELINUX + 747| if (set_selinux_file_context (dst, NULL) != 0) { + 748|-> return -1; + 749| } + 750| #endif /* WITH_SELINUX */ + +Error: RESOURCE_LEAK (CWE-772): [#def5] +shadow-4.8.1/libmisc/copydir.c:751: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] +shadow-4.8.1/libmisc/copydir.c:751: var_assign: Assigning: "ofd" = handle returned from "open(dst, 577, statp->st_mode & 0xfffU)". +shadow-4.8.1/libmisc/copydir.c:752: noescape: Resource "ofd" is not freed or pointed-to in "fchown_if_needed". +shadow-4.8.1/libmisc/copydir.c:775: leaked_handle: Handle variable "ofd" going out of scope leaks the handle. + 773| ) { + 774| (void) close (ifd); + 775|-> return -1; + 776| } + 777| + +Error: RESOURCE_LEAK (CWE-772): [#def7] +shadow-4.8.1/libmisc/idmapping.c:188: alloc_fn: Storage is returned from allocation function "xmalloc". +shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "buf" = storage returned from "xmalloc(bufsize)". +shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "pos" = "buf". +shadow-4.8.1/libmisc/idmapping.c:213: noescape: Resource "buf" is not freed or pointed-to in "write". +shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "pos" going out of scope leaks the storage it points to. +shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "buf" going out of scope leaks the storage it points to. + 217| } + 218| close(fd); + 219|-> } + +Error: RESOURCE_LEAK (CWE-772): [#def8] +shadow-4.8.1/libmisc/list.c:211: alloc_fn: Storage is returned from allocation function "xstrdup". +shadow-4.8.1/libmisc/list.c:211: var_assign: Assigning: "members" = storage returned from "xstrdup(comma)". +shadow-4.8.1/libmisc/list.c:217: var_assign: Assigning: "cp" = "members". +shadow-4.8.1/libmisc/list.c:218: noescape: Resource "cp" is not freed or pointed-to in "strchr". +shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "cp" going out of scope leaks the storage it points to. +shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "members" going out of scope leaks the storage it points to. + 242| if ('\0' == *members) { + 243| *array = (char *) 0; + 244|-> return array; + 245| } + 246| + +Error: RESOURCE_LEAK (CWE-772): [#def11] +shadow-4.8.1/libmisc/myname.c:61: alloc_fn: Storage is returned from allocation function "xgetpwnam". +shadow-4.8.1/libmisc/myname.c:61: var_assign: Assigning: "pw" = storage returned from "xgetpwnam(cp)". +shadow-4.8.1/libmisc/myname.c:67: leaked_storage: Variable "pw" going out of scope leaks the storage it points to. + 65| } + 66| + 67|-> return xgetpwuid (ruid); + 68| } + 69| + +Error: RESOURCE_LEAK (CWE-772): [#def12] +shadow-4.8.1/libmisc/user_busy.c:260: alloc_fn: Storage is returned from allocation function "opendir". +shadow-4.8.1/libmisc/user_busy.c:260: var_assign: Assigning: "task_dir" = storage returned from "opendir(task_path)". +shadow-4.8.1/libmisc/user_busy.c:262: noescape: Resource "task_dir" is not freed or pointed-to in "readdir". +shadow-4.8.1/libmisc/user_busy.c:278: leaked_storage: Variable "task_dir" going out of scope leaks the storage it points to. + 276| _("%s: user %s is currently used by process %d\n"), + 277| Prog, name, pid); + 278|-> return 1; + 279| } + 280| } + +Error: RESOURCE_LEAK (CWE-772): [#def20] +shadow-4.8.1/src/newgrp.c:162: alloc_fn: Storage is returned from allocation function "xgetspnam". +shadow-4.8.1/src/newgrp.c:162: var_assign: Assigning: "spwd" = storage returned from "xgetspnam(pwd->pw_name)". +shadow-4.8.1/src/newgrp.c:234: leaked_storage: Variable "spwd" going out of scope leaks the storage it points to. + 232| } + 233| + 234|-> return; + 235| + 236| failure: + +Error: RESOURCE_LEAK (CWE-772): [#def21] +shadow-4.8.1/src/passwd.c:530: alloc_fn: Storage is returned from allocation function "xstrdup". +shadow-4.8.1/src/passwd.c:530: var_assign: Assigning: "cp" = storage returned from "xstrdup(crypt_passwd)". +shadow-4.8.1/src/passwd.c:551: noescape: Resource "cp" is not freed or pointed-to in "strlen". +shadow-4.8.1/src/passwd.c:554: noescape: Resource "cp" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] +shadow-4.8.1/src/passwd.c:555: overwrite_var: Overwriting "cp" in "cp = newpw" leaks the storage that "cp" points to. + 553| strcpy (newpw, "!"); + 554| strcat (newpw, cp); + 555|-> cp = newpw; + 556| } + 557| return cp; +--- + lib/commonio.c | 8 ++++++-- + libmisc/addgrps.c | 6 +++++- + libmisc/chowntty.c | 1 + + libmisc/copydir.c | 6 ++++++ + libmisc/idmapping.c | 1 + + libmisc/list.c | 3 +++ + libmisc/myname.c | 3 +++ + libmisc/user_busy.c | 1 + + src/newgrp.c | 3 ++- + src/passwd.c | 5 +++++ + 10 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/lib/commonio.c b/lib/commonio.c +index 23ac91f9..cef404b9 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -336,8 +336,12 @@ static int create_backup (const char *backup, FILE * fp) + /* FIXME: unlink the backup file? */ + return -1; + } +- if ( (fsync (fileno (bkfp)) != 0) +- || (fclose (bkfp) != 0)) { ++ if (fsync (fileno (bkfp)) != 0) { ++ (void) fclose (bkfp); ++ /* FIXME: unlink the backup file? */ ++ return -1; ++ } ++ if (fclose (bkfp) != 0) { + /* FIXME: unlink the backup file? */ + return -1; + } +diff --git a/libmisc/addgrps.c b/libmisc/addgrps.c +index 2e38e340..76c172a5 100644 +--- a/libmisc/addgrps.c ++++ b/libmisc/addgrps.c +@@ -57,6 +57,7 @@ int add_groups (const char *list) + bool added; + char *token; + char buf[1024]; ++ int ret; + + if (strlen (list) >= sizeof (buf)) { + errno = EINVAL; +@@ -120,9 +121,12 @@ int add_groups (const char *list) + } + + if (added) { +- return setgroups ((size_t)ngroups, grouplist); ++ ret = setgroups ((size_t)ngroups, grouplist); ++ free (grouplist); ++ return ret; + } + ++ free (grouplist); + return 0; + } + #else /* HAVE_SETGROUPS && !USE_PAM */ +diff --git a/libmisc/chowntty.c b/libmisc/chowntty.c +index ea706c4f..a42ab622 100644 +--- a/libmisc/chowntty.c ++++ b/libmisc/chowntty.c +@@ -62,6 +62,7 @@ void chown_tty (const struct passwd *info) + grent = getgr_nam_gid (getdef_str ("TTYGROUP")); + if (NULL != grent) { + gid = grent->gr_gid; ++ gr_free (grent); + } else { + gid = info->pw_gid; + } +diff --git a/libmisc/copydir.c b/libmisc/copydir.c +index 91d391f8..015e1b68 100644 +--- a/libmisc/copydir.c ++++ b/libmisc/copydir.c +@@ -745,6 +745,7 @@ static int copy_file (const char *src, const char *dst, + } + #ifdef WITH_SELINUX + if (set_selinux_file_context (dst, NULL) != 0) { ++ (void) close (ifd); + return -1; + } + #endif /* WITH_SELINUX */ +@@ -771,12 +772,16 @@ static int copy_file (const char *src, const char *dst, + && (errno != 0)) + #endif /* WITH_ATTR */ + ) { ++ if (ofd >= 0) { ++ (void) close (ofd); ++ } + (void) close (ifd); + return -1; + } + + while ((cnt = read (ifd, buf, sizeof buf)) > 0) { + if (write (ofd, buf, (size_t)cnt) != cnt) { ++ (void) close (ofd); + (void) close (ifd); + return -1; + } +@@ -786,6 +791,7 @@ static int copy_file (const char *src, const char *dst, + + #ifdef HAVE_FUTIMES + if (futimes (ofd, mt) != 0) { ++ (void) close (ofd); + return -1; + } + #endif /* HAVE_FUTIMES */ +diff --git a/libmisc/idmapping.c b/libmisc/idmapping.c +index b0ae488c..3324f671 100644 +--- a/libmisc/idmapping.c ++++ b/libmisc/idmapping.c +@@ -241,4 +241,5 @@ void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings, + exit(EXIT_FAILURE); + } + close(fd); ++ free(buf); + } +diff --git a/libmisc/list.c b/libmisc/list.c +index 2da734a7..d85d5f20 100644 +--- a/libmisc/list.c ++++ b/libmisc/list.c +@@ -241,6 +241,7 @@ bool is_on_list (char *const *list, const char *member) + + if ('\0' == *members) { + *array = (char *) 0; ++ free (members); + return array; + } + +@@ -262,6 +263,8 @@ bool is_on_list (char *const *list, const char *member) + } + } + ++ free (members); ++ + /* + * Return the new array of pointers + */ +diff --git a/libmisc/myname.c b/libmisc/myname.c +index 05efdad3..e1b7f702 100644 +--- a/libmisc/myname.c ++++ b/libmisc/myname.c +@@ -62,6 +62,9 @@ + if ((NULL != pw) && (pw->pw_uid == ruid)) { + return pw; + } ++ if (NULL != pw) { ++ pw_free (pw); ++ } + } + + return xgetpwuid (ruid); +diff --git a/libmisc/user_busy.c b/libmisc/user_busy.c +index 4b507fe2..3deebfc3 100644 +--- a/libmisc/user_busy.c ++++ b/libmisc/user_busy.c +@@ -269,6 +269,7 @@ static int user_busy_processes (const char *name, uid_t uid) + } + if (check_status (name, task_path+6, uid) != 0) { + (void) closedir (proc); ++ (void) closedir (task_dir); + #ifdef ENABLE_SUBIDS + sub_uid_close(); + #endif +diff --git a/src/newgrp.c b/src/newgrp.c +index 2aa28b87..2b9293b4 100644 +--- a/src/newgrp.c ++++ b/src/newgrp.c +@@ -162,8 +162,9 @@ static void check_perms (const struct group *grp, + */ + spwd = xgetspnam (pwd->pw_name); + if (NULL != spwd) { +- pwd->pw_passwd = spwd->sp_pwdp; ++ pwd->pw_passwd = xstrdup (spwd->sp_pwdp); + } ++ spw_free (spwd); + + if ((pwd->pw_passwd[0] == '\0') && (grp->gr_passwd[0] != '\0')) { + needspasswd = true; +diff --git a/src/passwd.c b/src/passwd.c +index 3d4206f4..9d7df331 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -553,6 +553,11 @@ static char *update_crypt_pw (char *cp) + + strcpy (newpw, "!"); + strcat (newpw, cp); ++#ifndef USE_PAM ++ if (do_update_pwd) { ++ free (cp); ++ } ++#endif /* USE_PAM */ + cp = newpw; + } + return cp; +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 2817429..bde69bc 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.8.1 -Release: 12%{?dist} +Release: 13%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -99,6 +99,13 @@ Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch Patch58: shadow-4.8.1-yescrypt-support.patch # https://github.com/shadow-maint/shadow/commit/7a3bb4d0ea8166acc539c788a8ce943acf4a6aa7 Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch +# https://github.com/shadow-maint/shadow/commit/c44b71cec25d60efc51aec9de3abce1f6efbfcf5 +# https://github.com/shadow-maint/shadow/commit/fd9d79a1a3438ba7703939cfcd45fc266782c64e +# https://github.com/shadow-maint/shadow/commit/8281c82e324b57b3a4b520afad26b43ce128d521 +# https://github.com/shadow-maint/shadow/commit/1aed7ae945aafaeb253fc89a7ecedeaedf72654e +# https://github.com/shadow-maint/shadow/commit/5d0d7841971cc53d9a9d1aefe12f00204115bf6a +# https://github.com/shadow-maint/shadow/commit/e65cc6aebcb4132fa413f00a905216a5b35b3d57 +Patch60: shadow-4.8.1-covscan_fixes.patch License: BSD and GPLv2+ BuildRequires: make @@ -183,6 +190,7 @@ Development files for shadow-utils-subid. %patch57 -p1 -b .libsubid_make_logfd_not_extern %patch58 -p1 -b .yescrypt %patch59 -p1 -b .YESCRYPT_salt_cost_param_type +%patch60 -p1 -b .covscan_fixes iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -352,6 +360,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13 +- Covscan fixes + * Mon Jun 21 2021 Björn Esser - 2:4.8.1-12 - Backport support for yescrypt hash method - Add a patch to fix the parameter type of YESCRYPT_salt_cost() From c0e594d3c5c5162e622a66700fbfccced5777b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Mon, 21 Jun 2021 14:57:16 +0200 Subject: [PATCH 018/118] Add a patch to fix the used prefix for the bcrypt hash method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-fix_bcrypt_prefix.patch | 35 ++++++++++++++++++++++++++++ shadow-utils.spec | 8 ++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-fix_bcrypt_prefix.patch diff --git a/shadow-4.8.1-fix_bcrypt_prefix.patch b/shadow-4.8.1-fix_bcrypt_prefix.patch new file mode 100644 index 0000000..e8ac3bc --- /dev/null +++ b/shadow-4.8.1-fix_bcrypt_prefix.patch @@ -0,0 +1,35 @@ +From 738d92a4bd99a2038aa5f97b2fc85daa7011e403 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 12 Jun 2021 13:54:14 +0200 +Subject: [PATCH] libmisc/salt.c: bcrypt should use $2b$ as prefix for setting. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This prefix is the recommended one for new bcrypt hashes +for a long time. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 1bfa015b..5dc521ef 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -90,12 +90,8 @@ static void seedRNG (void) + */ + #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' + #ifdef USE_BCRYPT +-/* +- * Using the Prefix $2a$ to enable an anti-collision safety measure in musl libc. +- * Negatively affects a subset of passwords containing the '\xff' character, +- * which is not valid UTF-8 (so "unlikely to cause much annoyance"). +- */ +-#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='a',(array)[4]='\0' ++/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ ++#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' + #endif /* USE_BCRYPT */ + + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) diff --git a/shadow-utils.spec b/shadow-utils.spec index bde69bc..1e1366a 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.8.1 -Release: 13%{?dist} +Release: 14%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -106,6 +106,8 @@ Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch # https://github.com/shadow-maint/shadow/commit/5d0d7841971cc53d9a9d1aefe12f00204115bf6a # https://github.com/shadow-maint/shadow/commit/e65cc6aebcb4132fa413f00a905216a5b35b3d57 Patch60: shadow-4.8.1-covscan_fixes.patch +# https://github.com/shadow-maint/shadow/commit/738d92a4bd99a2038aa5f97b2fc85daa7011e403 +Patch61: shadow-4.8.1-fix_bcrypt_prefix.patch License: BSD and GPLv2+ BuildRequires: make @@ -191,6 +193,7 @@ Development files for shadow-utils-subid. %patch58 -p1 -b .yescrypt %patch59 -p1 -b .YESCRYPT_salt_cost_param_type %patch60 -p1 -b .covscan_fixes +%patch61 -p1 -b .bcrypt_prefix iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -360,6 +363,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jun 28 2021 Björn Esser - 2:4.8.1-14 +- Add a patch to fix the used prefix for the bcrypt hash method + * Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13 - Covscan fixes From 2615b08c3119e52e40081724aac621c0f99cbe03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Mon, 21 Jun 2021 15:01:46 +0200 Subject: [PATCH 019/118] Add a patch to cleanup the code in libmisc/salt.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-salt_c_sanitize_code.patch | 555 ++++++++++++++++++++++++ shadow-utils.spec | 4 + 2 files changed, 559 insertions(+) create mode 100644 shadow-4.8.1-salt_c_sanitize_code.patch diff --git a/shadow-4.8.1-salt_c_sanitize_code.patch b/shadow-4.8.1-salt_c_sanitize_code.patch new file mode 100644 index 0000000..1ca1d3b --- /dev/null +++ b/shadow-4.8.1-salt_c_sanitize_code.patch @@ -0,0 +1,555 @@ +From 14b108728a5d55c3d478a170c39f0e2ffd4de1b0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Mon, 14 Jun 2021 23:28:28 +0200 +Subject: [PATCH] libmisc/salt.c: Sanitize code. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +* Move all pre-processor defines to the top of the file. +* Unify the gensalt() function to be useable for all supported + hash methods. +* Drop the gensalt_{b,yes}crypt() functions in favor of the + previous change. +* Refactor the functions converting the rounds number into + a string for use with the crypt() function, to not require + any static buffer anymore. +* Clarify the comment about how crypt_make_salt() chooses the used + hash method from the settings in the login.defs file. +* Use memset() to fill static buffers with zero before using them. +* Use a fixed amount of 16 random base64-chars for the + sha{256,512}crypt hash methods, which is effectively still less + than the recommendation from NIST (>= 128 bits), but the maximum + those methods can effectively use (approx. 90 bits). +* Rename ROUNDS_{MIN,MAX} to SHA_ROUNDS_{MIN,MAX}. +* Bugfixes in the logic of setting rounds in BCRYPT_salt_rounds(). +* Likewise for YESCRYPT_salt_cost(). +* Fix formatting and white-space errors. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 332 ++++++++++++++++++++++--------------------------- + 1 file changed, 147 insertions(+), 185 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 5dc521ef..98982ed1 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -12,6 +12,7 @@ + #ident "$Id$" + + #include ++#include + #include + #include + #include +@@ -19,6 +20,59 @@ + #include "defines.h" + #include "getdef.h" + ++/* Add the salt prefix. */ ++#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' ++ ++#ifdef USE_BCRYPT ++/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ ++#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' ++#define BCRYPT_SALT_SIZE 22 ++/* Default number of rounds if not explicitly specified. */ ++#define B_ROUNDS_DEFAULT 13 ++/* Minimum number of rounds. */ ++#define B_ROUNDS_MIN 4 ++/* Maximum number of rounds. */ ++#define B_ROUNDS_MAX 31 ++#endif /* USE_BCRYPT */ ++ ++#ifdef USE_SHA_CRYPT ++/* Fixed salt len for sha{256,512}crypt. */ ++#define SHA_CRYPT_SALT_SIZE 16 ++/* Default number of rounds if not explicitly specified. */ ++#define SHA_ROUNDS_DEFAULT 5000 ++/* Minimum number of rounds. */ ++#define SHA_ROUNDS_MIN 1000 ++/* Maximum number of rounds. */ ++#define SHA_ROUNDS_MAX 999999999 ++#endif ++ ++#ifdef USE_YESCRYPT ++/* ++ * Default number of base64 characters used for the salt. ++ * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more ++ * traditional 128 bits (16 bytes) salt, this 144 bits salt is always ++ * represented by the same number of base64 characters without padding ++ * issue, even with a non-standard base64 encoding scheme. ++ */ ++#define YESCRYPT_SALT_SIZE 24 ++/* Default cost if not explicitly specified. */ ++#define Y_COST_DEFAULT 5 ++/* Minimum cost. */ ++#define Y_COST_MIN 1 ++/* Maximum cost. */ ++#define Y_COST_MAX 11 ++#endif ++ ++/* Fixed salt len for md5crypt. */ ++#define MD5_CRYPT_SALT_SIZE 8 ++ ++/* Generate salt of size salt_size. */ ++#define MAX_SALT_SIZE 44 ++#define MIN_SALT_SIZE 8 ++ ++/* Maximum size of the generated salt string. */ ++#define GENSALT_SETTING_SIZE 100 ++ + /* local function prototypes */ + static void seedRNG (void); + static /*@observer@*/const char *gensalt (size_t salt_size); +@@ -26,19 +80,17 @@ static /*@observer@*/const char *gensalt (size_t salt_size); + static long shadow_random (long min, long max); + #endif /* USE_SHA_CRYPT || USE_BCRYPT */ + #ifdef USE_SHA_CRYPT +-static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds); ++static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); + #endif /* USE_SHA_CRYPT */ + #ifdef USE_BCRYPT +-static /*@observer@*/const char *gensalt_bcrypt (void); +-static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds); ++static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); + #endif /* USE_BCRYPT */ + #ifdef USE_YESCRYPT +-static /*@observer@*/const char *gensalt_yescrypt (void); +-static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost); ++static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost); + #endif /* USE_YESCRYPT */ + + #ifndef HAVE_L64A +-static /*@observer@*/char *l64a(long value) ++static /*@observer@*/char *l64a (long value) + { + static char buf[8]; + char *s = buf; +@@ -69,7 +121,7 @@ static /*@observer@*/char *l64a(long value) + + *s = '\0'; + +- return(buf); ++ return buf; + } + #endif /* !HAVE_L64A */ + +@@ -85,15 +137,6 @@ static void seedRNG (void) + } + } + +-/* +- * Add the salt prefix. +- */ +-#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' +-#ifdef USE_BCRYPT +-/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ +-#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' +-#endif /* USE_BCRYPT */ +- + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) + /* It is not clear what is the maximum value of random(). + * We assume 2^31-1.*/ +@@ -122,26 +165,21 @@ static long shadow_random (long min, long max) + #endif /* USE_SHA_CRYPT || USE_BCRYPT */ + + #ifdef USE_SHA_CRYPT +-/* Default number of rounds if not explicitly specified. */ +-#define ROUNDS_DEFAULT 5000 +-/* Minimum number of rounds. */ +-#define ROUNDS_MIN 1000 +-/* Maximum number of rounds. */ +-#define ROUNDS_MAX 999999999 + /* +- * Return a salt prefix specifying the rounds number for the SHA crypt methods. ++ * Fill a salt prefix specifying the rounds number for the SHA crypt methods ++ * to a buffer. + */ +-static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds) ++static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) + { +- static char rounds_prefix[18]; /* Max size: rounds=999999999$ */ +- long rounds; ++ unsigned long rounds; ++ const size_t buf_begin = strlen (buf); + + if (NULL == prefered_rounds) { + long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); + long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1); + + if ((-1 == min_rounds) && (-1 == max_rounds)) { +- return ""; ++ rounds = SHA_ROUNDS_DEFAULT; + } + + if (-1 == min_rounds) { +@@ -156,196 +194,142 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds + max_rounds = min_rounds; + } + +- rounds = shadow_random (min_rounds, max_rounds); ++ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); + } else if (0 == *prefered_rounds) { +- return ""; ++ rounds = SHA_ROUNDS_DEFAULT; + } else { +- rounds = *prefered_rounds; ++ rounds = (unsigned long) *prefered_rounds; + } + + /* Sanity checks. The libc should also check this, but this + * protects against a rounds_prefix overflow. */ +- if (rounds < ROUNDS_MIN) { +- rounds = ROUNDS_MIN; ++ if (rounds < SHA_ROUNDS_MIN) { ++ rounds = SHA_ROUNDS_MIN; ++ } ++ ++ if (rounds > SHA_ROUNDS_MAX) { ++ rounds = SHA_ROUNDS_MAX; + } + +- if (rounds > ROUNDS_MAX) { +- rounds = ROUNDS_MAX; ++ /* Nothing to do here if SHA_ROUNDS_DEFAULT is used. */ ++ if (rounds == SHA_ROUNDS_DEFAULT) { ++ return; + } + +- (void) snprintf (rounds_prefix, sizeof rounds_prefix, +- "rounds=%ld$", rounds); ++ /* Check if the result buffer is long enough. */ ++ assert (GENSALT_SETTING_SIZE > buf_begin + 17); + +- return rounds_prefix; ++ (void) snprintf (buf + buf_begin, 18, "rounds=%lu$", rounds); + } + #endif /* USE_SHA_CRYPT */ + + #ifdef USE_BCRYPT +-/* Default number of rounds if not explicitly specified. */ +-#define B_ROUNDS_DEFAULT 13 +-/* Minimum number of rounds. */ +-#define B_ROUNDS_MIN 4 +-/* Maximum number of rounds. */ +-#define B_ROUNDS_MAX 31 + /* +- * Return a salt prefix specifying the rounds number for the BCRYPT method. ++ * Fill a salt prefix specifying the rounds number for the BCRYPT method ++ * to a buffer. + */ +-static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds) ++static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) + { +- static char rounds_prefix[4]; /* Max size: 31$ */ +- long rounds; ++ unsigned long rounds; ++ const size_t buf_begin = strlen (buf); + + if (NULL == prefered_rounds) { + long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1); + long max_rounds = getdef_long ("BCRYPT_MAX_ROUNDS", -1); + +- if (((-1 == min_rounds) && (-1 == max_rounds)) || (0 == *prefered_rounds)) { ++ if ((-1 == min_rounds) && (-1 == max_rounds)) { + rounds = B_ROUNDS_DEFAULT; +- } +- else { ++ } else { + if (-1 == min_rounds) { + min_rounds = max_rounds; + } +- ++ + if (-1 == max_rounds) { + max_rounds = min_rounds; + } +- ++ + if (min_rounds > max_rounds) { + max_rounds = min_rounds; + } +- +- rounds = shadow_random (min_rounds, max_rounds); ++ ++ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); + } ++ } else if (0 == *prefered_rounds) { ++ rounds = B_ROUNDS_DEFAULT; + } else { +- rounds = *prefered_rounds; ++ rounds = (unsigned long) *prefered_rounds; + } + +- /* +- * Sanity checks. +- * Use 19 as an upper bound for now, +- * because musl doesn't allow rounds >= 20. +- */ ++ /* Sanity checks. */ + if (rounds < B_ROUNDS_MIN) { + rounds = B_ROUNDS_MIN; + } + ++ /* ++ * Use 19 as an upper bound for now, ++ * because musl doesn't allow rounds >= 20. ++ */ + if (rounds > 19) { + /* rounds = B_ROUNDS_MAX; */ + rounds = 19; + } + +- (void) snprintf (rounds_prefix, sizeof rounds_prefix, +- "%2.2ld$", rounds); +- +- return rounds_prefix; +-} +- +-#define BCRYPT_SALT_SIZE 22 +-/* +- * Generate a 22 character salt string for bcrypt. +- */ +-static /*@observer@*/const char *gensalt_bcrypt (void) +-{ +- static char salt[32]; +- +- salt[0] = '\0'; ++ /* Check if the result buffer is long enough. */ ++ assert (GENSALT_SETTING_SIZE > buf_begin + 3); + +- seedRNG (); +- strcat (salt, l64a (random())); +- do { +- strcat (salt, l64a (random())); +- } while (strlen (salt) < BCRYPT_SALT_SIZE); +- +- salt[BCRYPT_SALT_SIZE] = '\0'; +- +- return salt; ++ (void) snprintf (buf + buf_begin, 4, "%2.2lu$", rounds); + } + #endif /* USE_BCRYPT */ + + #ifdef USE_YESCRYPT +-/* Default cost if not explicitly specified. */ +-#define Y_COST_DEFAULT 5 +-/* Minimum cost. */ +-#define Y_COST_MIN 1 +-/* Maximum cost. */ +-#define Y_COST_MAX 11 + /* +- * Return a salt prefix specifying the cost for the YESCRYPT method. ++ * Fill a salt prefix specifying the cost for the YESCRYPT method ++ * to a buffer. + */ +-static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost) ++static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost) + { +- static char cost_prefix[5]; +- long cost; ++ unsigned long cost; ++ const size_t buf_begin = strlen (buf); + + if (NULL == prefered_cost) { + cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); ++ } else if (0 == *prefered_cost) { ++ cost = Y_COST_DEFAULT; + } else { +- cost = *prefered_cost; ++ cost = (unsigned long) *prefered_cost; + } + ++ /* Sanity checks. */ + if (cost < Y_COST_MIN) { + cost = Y_COST_MIN; + } ++ + if (cost > Y_COST_MAX) { + cost = Y_COST_MAX; + } + +- cost_prefix[0] = 'j'; ++ /* Check if the result buffer is long enough. */ ++ assert (GENSALT_SETTING_SIZE > buf_begin + 3); ++ ++ buf[buf_begin + 0] = 'j'; + if (cost < 3) { +- cost_prefix[1] = 0x36 + cost; ++ buf[buf_begin + 1] = 0x36 + cost; + } else if (cost < 6) { +- cost_prefix[1] = 0x34 + cost; ++ buf[buf_begin + 1] = 0x34 + cost; + } else { +- cost_prefix[1] = 0x3b + cost; ++ buf[buf_begin + 1] = 0x3b + cost; + } +- cost_prefix[2] = cost >= 3 ? 'T' : '5'; +- cost_prefix[3] = '$'; +- cost_prefix[4] = 0; +- +- return cost_prefix; +-} +- +-/* +- * Default number of base64 characters used for the salt. +- * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more +- * traditional 128 bits (16 bytes) salt, this 144 bits salt is always +- * represented by the same number of base64 characters without padding +- * issue, even with a non-standard base64 encoding scheme. +- */ +-#define YESCRYPT_SALT_SIZE 24 +-/* +- * Generate a 22 character salt string for yescrypt. +- */ +-static /*@observer@*/const char *gensalt_yescrypt (void) +-{ +- static char salt[32]; +- +- salt[0] = '\0'; +- +- seedRNG (); +- strcat (salt, l64a (random())); +- do { +- strcat (salt, l64a (random())); +- } while (strlen (salt) < YESCRYPT_SALT_SIZE); +- +- salt[YESCRYPT_SALT_SIZE] = '\0'; +- +- return salt; ++ buf[buf_begin + 2] = cost >= 3 ? 'T' : '5'; ++ buf[buf_begin + 3] = '$'; ++ buf[buf_begin + 4] = '\0'; + } + #endif /* USE_YESCRYPT */ + +-/* +- * Generate salt of size salt_size. +- */ +-#define MAX_SALT_SIZE 16 +-#define MIN_SALT_SIZE 8 +- + static /*@observer@*/const char *gensalt (size_t salt_size) + { +- static char salt[32]; ++ static char salt[MAX_SALT_SIZE + 6]; + +- salt[0] = '\0'; ++ memset (salt, '\0', MAX_SALT_SIZE + 6); + + assert (salt_size >= MIN_SALT_SIZE && + salt_size <= MAX_SALT_SIZE); +@@ -368,8 +352,9 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + * Other methods can be set with ENCRYPT_METHOD + * + * The method can be forced with the meth parameter. +- * If NULL, the method will be defined according to the MD5_CRYPT_ENAB and +- * ENCRYPT_METHOD login.defs variables. ++ * If NULL, the method will be defined according to the ENCRYPT_METHOD ++ * variable, and if not set according to the MD5_CRYPT_ENAB variable, ++ * which can both be set inside the login.defs file. + * + * If meth is specified, an additional parameter can be provided. + * * For the SHA256 and SHA512 method, this specifies the number of rounds +@@ -378,17 +363,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + */ + /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg) + { +- /* Max result size for the SHA methods: +- * +3 $5$ +- * +17 rounds=999999999$ +- * +16 salt +- * +1 \0 +- */ +- static char result[40]; +- size_t salt_len = 8; ++ static char result[GENSALT_SETTING_SIZE]; ++ size_t salt_len = MAX_SALT_SIZE; + const char *method; + +- result[0] = '\0'; ++ memset (result, '\0', GENSALT_SETTING_SIZE); + + if (NULL != meth) + method = meth; +@@ -401,61 +380,44 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + + if (0 == strcmp (method, "MD5")) { + MAGNUM(result, '1'); ++ salt_len = MD5_CRYPT_SALT_SIZE; + #ifdef USE_BCRYPT + } else if (0 == strcmp (method, "BCRYPT")) { + BCRYPTMAGNUM(result); +- strcat(result, BCRYPT_salt_rounds((int *)arg)); ++ salt_len = BCRYPT_SALT_SIZE; ++ BCRYPT_salt_rounds_to_buf (result, (int *) arg); + #endif /* USE_BCRYPT */ + #ifdef USE_YESCRYPT + } else if (0 == strcmp (method, "YESCRYPT")) { + MAGNUM(result, 'y'); +- strcat(result, YESCRYPT_salt_cost((int *)arg)); ++ salt_len = YESCRYPT_SALT_SIZE; ++ YESCRYPT_salt_cost_to_buf (result, (int *) arg); + #endif /* USE_YESCRYPT */ + #ifdef USE_SHA_CRYPT + } else if (0 == strcmp (method, "SHA256")) { + MAGNUM(result, '5'); +- strcat(result, SHA_salt_rounds((int *)arg)); +- salt_len = (size_t) shadow_random (8, 16); ++ salt_len = SHA_CRYPT_SALT_SIZE; ++ SHA_salt_rounds_to_buf (result, (int *) arg); + } else if (0 == strcmp (method, "SHA512")) { + MAGNUM(result, '6'); +- strcat(result, SHA_salt_rounds((int *)arg)); +- salt_len = (size_t) shadow_random (8, 16); ++ salt_len = SHA_CRYPT_SALT_SIZE; ++ SHA_salt_rounds_to_buf (result, (int *) arg); + #endif /* USE_SHA_CRYPT */ + } else if (0 != strcmp (method, "DES")) { + fprintf (shadow_logfd, + _("Invalid ENCRYPT_METHOD value: '%s'.\n" + "Defaulting to DES.\n"), + method); +- result[0] = '\0'; ++ salt_len = MAX_SALT_SIZE; ++ memset (result, '\0', GENSALT_SETTING_SIZE); + } + +- /* +- * Concatenate a pseudo random salt. +- */ +- assert (sizeof (result) > strlen (result) + salt_len); +-#ifdef USE_BCRYPT +- if (0 == strcmp (method, "BCRYPT")) { +- strncat (result, gensalt_bcrypt (), +- sizeof (result) - strlen (result) - 1); +- return result; +- } else { +-#endif /* USE_BCRYPT */ +-#ifdef USE_YESCRYPT +- if (0 == strcmp (method, "YESCRYPT")) { +- strncat (result, gensalt_yescrypt (), +- sizeof (result) - strlen (result) - 1); +- return result; +- } else { +-#endif /* USE_YESCRYPT */ +- strncat (result, gensalt (salt_len), +- sizeof (result) - strlen (result) - 1); +-#ifdef USE_YESCRYPT +- } +-#endif /* USE_YESCRYPT */ +-#ifdef USE_BCRYPT +- } +-#endif /* USE_BCRYPT */ ++ /* Check if the result buffer is long enough. */ ++ assert (GENSALT_SETTING_SIZE > strlen (result) + salt_len); ++ ++ /* Concatenate a pseudo random salt. */ ++ strncat (result, gensalt (salt_len), ++ GENSALT_SETTING_SIZE - strlen (result) - 1); + + return result; + } +- diff --git a/shadow-utils.spec b/shadow-utils.spec index 1e1366a..928798c 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -108,6 +108,8 @@ Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch Patch60: shadow-4.8.1-covscan_fixes.patch # https://github.com/shadow-maint/shadow/commit/738d92a4bd99a2038aa5f97b2fc85daa7011e403 Patch61: shadow-4.8.1-fix_bcrypt_prefix.patch +# https://github.com/shadow-maint/shadow/commit/14b108728a5d55c3d478a170c39f0e2ffd4de1b0 +Patch62: shadow-4.8.1-salt_c_sanitize_code.patch License: BSD and GPLv2+ BuildRequires: make @@ -194,6 +196,7 @@ Development files for shadow-utils-subid. %patch59 -p1 -b .YESCRYPT_salt_cost_param_type %patch60 -p1 -b .covscan_fixes %patch61 -p1 -b .bcrypt_prefix +%patch62 -p1 -b .sanitize_code iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -365,6 +368,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %changelog * Mon Jun 28 2021 Björn Esser - 2:4.8.1-14 - Add a patch to fix the used prefix for the bcrypt hash method +- Add a patch to cleanup the code in libmisc/salt.c * Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13 - Covscan fixes From 1b6e097b0e73a509cb80585983b8ac600b1734a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Wed, 23 Jun 2021 22:19:36 +0200 Subject: [PATCH 020/118] Add a patch adding some clarifying comments in libmisc/salt.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-salt_c_comments.patch | 75 ++++++++++++++++++++++++++++++ shadow-utils.spec | 4 ++ 2 files changed, 79 insertions(+) create mode 100644 shadow-4.8.1-salt_c_comments.patch diff --git a/shadow-4.8.1-salt_c_comments.patch b/shadow-4.8.1-salt_c_comments.patch new file mode 100644 index 0000000..1ec77e4 --- /dev/null +++ b/shadow-4.8.1-salt_c_comments.patch @@ -0,0 +1,75 @@ +From dbf230e4cf823dd6b6a3bad6d29dfad4f0ffa8fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Mon, 14 Jun 2021 23:28:28 +0200 +Subject: [PATCH] libmisc/salt.c: Add comments how the minmum buffer length is + computed. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In the previous commit we refactored the functions converting the +rounds number into a string for use with the crypt() function, to +not require any static buffer anymore. + +Add some clarifying comments about how the minimum required buffer +length is computed inside of these functions. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 98982ed1..e17093fc 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -216,7 +216,14 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref + return; + } + +- /* Check if the result buffer is long enough. */ ++ /* ++ * Check if the result buffer is long enough. ++ * We are going to write a maximum of 17 bytes, ++ * plus one byte for the terminator. ++ * rounds=XXXXXXXXX$ ++ * 00000000011111111 ++ * 12345678901234567 ++ */ + assert (GENSALT_SETTING_SIZE > buf_begin + 17); + + (void) snprintf (buf + buf_begin, 18, "rounds=%lu$", rounds); +@@ -274,7 +281,14 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p + rounds = 19; + } + +- /* Check if the result buffer is long enough. */ ++ /* ++ * Check if the result buffer is long enough. ++ * We are going to write three bytes, ++ * plus one byte for the terminator. ++ * XX$ ++ * 000 ++ * 123 ++ */ + assert (GENSALT_SETTING_SIZE > buf_begin + 3); + + (void) snprintf (buf + buf_begin, 4, "%2.2lu$", rounds); +@@ -308,8 +322,15 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p + cost = Y_COST_MAX; + } + +- /* Check if the result buffer is long enough. */ +- assert (GENSALT_SETTING_SIZE > buf_begin + 3); ++ /* ++ * Check if the result buffer is long enough. ++ * We are going to write four bytes, ++ * plus one byte for the terminator. ++ * jXX$ ++ * 0000 ++ * 1234 ++ */ ++ assert (GENSALT_SETTING_SIZE > buf_begin + 4); + + buf[buf_begin + 0] = 'j'; + if (cost < 3) { diff --git a/shadow-utils.spec b/shadow-utils.spec index 928798c..5145b38 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -110,6 +110,8 @@ Patch60: shadow-4.8.1-covscan_fixes.patch Patch61: shadow-4.8.1-fix_bcrypt_prefix.patch # https://github.com/shadow-maint/shadow/commit/14b108728a5d55c3d478a170c39f0e2ffd4de1b0 Patch62: shadow-4.8.1-salt_c_sanitize_code.patch +# https://github.com/shadow-maint/shadow/commit/dbf230e4cf823dd6b6a3bad6d29dfad4f0ffa8fc +Patch63: shadow-4.8.1-salt_c_comments.patch License: BSD and GPLv2+ BuildRequires: make @@ -197,6 +199,7 @@ Development files for shadow-utils-subid. %patch60 -p1 -b .covscan_fixes %patch61 -p1 -b .bcrypt_prefix %patch62 -p1 -b .sanitize_code +%patch63 -p1 -b .comments iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -369,6 +372,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la * Mon Jun 28 2021 Björn Esser - 2:4.8.1-14 - Add a patch to fix the used prefix for the bcrypt hash method - Add a patch to cleanup the code in libmisc/salt.c +- Add a patch adding some clarifying comments in libmisc/salt.c * Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13 - Covscan fixes From bace2f8c6b021981f73395c46dac0989f4d494c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Wed, 23 Jun 2021 22:22:04 +0200 Subject: [PATCH 021/118] Add a patch to obtain random bytes from /dev/urandom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-salt_c_use_dev_urandom.patch | 114 ++++++++++++++++++++++ shadow-utils.spec | 4 + 2 files changed, 118 insertions(+) create mode 100644 shadow-4.8.1-salt_c_use_dev_urandom.patch diff --git a/shadow-4.8.1-salt_c_use_dev_urandom.patch b/shadow-4.8.1-salt_c_use_dev_urandom.patch new file mode 100644 index 0000000..ba37b77 --- /dev/null +++ b/shadow-4.8.1-salt_c_use_dev_urandom.patch @@ -0,0 +1,114 @@ +From bc8257cf73328e450511b13cbd35e1994feccb30 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Wed, 23 Jun 2021 16:06:47 +0200 +Subject: [PATCH] libmisc/salt.c: Obtain random bytes from /dev/urandom. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Using the random() function to obtain pseudo-random bytes +for generating salt strings is considered to be dangerous. +See CWE-327. + +We really should use a more reliable source for obtaining +pseudo-random bytes like /dev/urandom. + +Fixes #376. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 45 ++++++++++++++++++++++++--------------------- + 1 file changed, 24 insertions(+), 21 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index e17093fc..af9f011f 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -11,11 +11,10 @@ + + #ident "$Id$" + +-#include +-#include +-#include +-#include + #include ++#include ++#include ++#include + #include "prototypes.h" + #include "defines.h" + #include "getdef.h" +@@ -74,7 +73,7 @@ + #define GENSALT_SETTING_SIZE 100 + + /* local function prototypes */ +-static void seedRNG (void); ++static long read_random_bytes (void); + static /*@observer@*/const char *gensalt (size_t salt_size); + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) + static long shadow_random (long min, long max); +@@ -125,23 +124,27 @@ static /*@observer@*/char *l64a (long value) + } + #endif /* !HAVE_L64A */ + +-static void seedRNG (void) ++/* Read sizeof (long) random bytes from /dev/urandom. */ ++static long read_random_bytes (void) + { +- struct timeval tv; +- static int seeded = 0; ++ long randval = 0; ++ FILE *f = fopen ("/dev/urandom", "r"); + +- if (0 == seeded) { +- (void) gettimeofday (&tv, NULL); +- srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ()); +- seeded = 1; ++ if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) ++ { ++ fprintf (shadow_logfd, ++ _("Unable to read from /dev/urandom.\n")); ++ ++ fclose(f); ++ exit (1); + } ++ ++ fclose(f); ++ ++ return randval; + } + + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +-/* It is not clear what is the maximum value of random(). +- * We assume 2^31-1.*/ +-#define RANDOM_MAX 0x7FFFFFFF +- + /* + * Return a random number between min and max (both included). + * +@@ -151,8 +154,9 @@ static long shadow_random (long min, long max) + { + double drand; + long ret; +- seedRNG (); +- drand = (double) (max - min + 1) * random () / RANDOM_MAX; ++ ++ drand = (double) (read_random_bytes () & RAND_MAX) / (double) RAND_MAX; ++ drand *= (double) (max - min + 1); + /* On systems were this is not random() range is lower, we favor + * higher numbers of salt. */ + ret = (long) (max + 1 - drand); +@@ -354,10 +358,9 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + + assert (salt_size >= MIN_SALT_SIZE && + salt_size <= MAX_SALT_SIZE); +- seedRNG (); +- strcat (salt, l64a (random())); ++ strcat (salt, l64a (read_random_bytes ())); + do { +- strcat (salt, l64a (random())); ++ strcat (salt, l64a (read_random_bytes ())); + } while (strlen (salt) < salt_size); + + salt[salt_size] = '\0'; diff --git a/shadow-utils.spec b/shadow-utils.spec index 5145b38..a5badbb 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -112,6 +112,8 @@ Patch61: shadow-4.8.1-fix_bcrypt_prefix.patch Patch62: shadow-4.8.1-salt_c_sanitize_code.patch # https://github.com/shadow-maint/shadow/commit/dbf230e4cf823dd6b6a3bad6d29dfad4f0ffa8fc Patch63: shadow-4.8.1-salt_c_comments.patch +# https://github.com/shadow-maint/shadow/commit/bc8257cf73328e450511b13cbd35e1994feccb30 +Patch64: shadow-4.8.1-salt_c_use_dev_urandom.patch License: BSD and GPLv2+ BuildRequires: make @@ -200,6 +202,7 @@ Development files for shadow-utils-subid. %patch61 -p1 -b .bcrypt_prefix %patch62 -p1 -b .sanitize_code %patch63 -p1 -b .comments +%patch64 -p1 -b .use_dev_urandom iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -373,6 +376,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la - Add a patch to fix the used prefix for the bcrypt hash method - Add a patch to cleanup the code in libmisc/salt.c - Add a patch adding some clarifying comments in libmisc/salt.c +- Add a patch to obtain random bytes from /dev/urandom * Mon Jun 28 2021 Iker Pedrosa - 2:4.8.1-13 - Covscan fixes From 2b6f7135243105d4526c3e9b4eddb4b745081a90 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 29 Jun 2021 08:53:22 +0200 Subject: [PATCH 022/118] useradd: free correct pointer (#1976809) --- ..._create_relative_home_path_correctly.patch | 24 +++++++++++++++++++ shadow-utils.spec | 8 ++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-useradd_create_relative_home_path_correctly.patch diff --git a/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch b/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch new file mode 100644 index 0000000..a318f7a --- /dev/null +++ b/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch @@ -0,0 +1,24 @@ +diff -up shadow-4.8.1/src/useradd.c.useradd_create_relative_home_path_correctly shadow-4.8.1/src/useradd.c +--- shadow-4.8.1/src/useradd.c.useradd_create_relative_home_path_correctly 2021-06-28 16:10:23.928435372 +0200 ++++ shadow-4.8.1/src/useradd.c 2021-06-28 16:11:30.784495046 +0200 +@@ -2140,7 +2140,6 @@ static void create_home (void) + Prog, user_home); + fail_exit (E_HOMEDIR); + } +- ++bhome; + + #ifdef WITH_SELINUX + if (set_selinux_file_context (prefix_user_home, NULL) != 0) { +@@ -2157,7 +2156,11 @@ static void create_home (void) + */ + cp = strtok (bhome, "/"); + while (cp) { +- strcat (path, "/"); ++ /* Avoid turning a relative path into an absolute path. ++ */ ++ if (bhome[0] == '/' || strlen (path) != 0) { ++ strcat (path, "/"); ++ } + strcat (path, cp); + if (access (path, F_OK) != 0) { + /* Check if parent directory is BTRFS, fail if requesting diff --git a/shadow-utils.spec b/shadow-utils.spec index a5badbb..20830e6 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.8.1 -Release: 14%{?dist} +Release: 15%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -114,6 +114,8 @@ Patch62: shadow-4.8.1-salt_c_sanitize_code.patch Patch63: shadow-4.8.1-salt_c_comments.patch # https://github.com/shadow-maint/shadow/commit/bc8257cf73328e450511b13cbd35e1994feccb30 Patch64: shadow-4.8.1-salt_c_use_dev_urandom.patch +# https://github.com/shadow-maint/shadow/commit/2c542f6c65f858b3dba20f58db4da56572f67a54 +Patch65: shadow-4.8.1-useradd_create_relative_home_path_correctly.patch License: BSD and GPLv2+ BuildRequires: make @@ -203,6 +205,7 @@ Development files for shadow-utils-subid. %patch62 -p1 -b .sanitize_code %patch63 -p1 -b .comments %patch64 -p1 -b .use_dev_urandom +%patch65 -p1 -b .useradd_create_relative_home_path_correctly iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -372,6 +375,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Tue Jun 29 2021 Iker Pedrosa - 2:4.8.1-15 +- useradd: free correct pointer (#1976809) + * Mon Jun 28 2021 Björn Esser - 2:4.8.1-14 - Add a patch to fix the used prefix for the bcrypt hash method - Add a patch to cleanup the code in libmisc/salt.c From a6d57fc8a3234d8e2321cdf0b81afbffc7f37987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sun, 4 Jul 2021 12:34:22 +0200 Subject: [PATCH 023/118] Add a patch to obtain random bytes using getentropy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-getentropy_random_bytes.patch | 123 +++++++++++++++++++++ shadow-utils.spec | 8 +- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-getentropy_random_bytes.patch diff --git a/shadow-4.8.1-getentropy_random_bytes.patch b/shadow-4.8.1-getentropy_random_bytes.patch new file mode 100644 index 0000000..c1affce --- /dev/null +++ b/shadow-4.8.1-getentropy_random_bytes.patch @@ -0,0 +1,123 @@ +From c82ed0c15e0e9e47df0b4c22672b72e35f061a9d +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sun, 4 Jul 2021 12:10:11 +0200 +Subject: [PATCH] libmisc/salt.c: Use secure system ressources to obtain random + bytes. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In a previous commit we introduced /dev/urandom as a source to obtain +random bytes from. This may not be available on all systems, or when +operating inside of a chroot. + +Almost all systems provide functions to obtain random bytes from +secure system ressources. Thus we should prefer to use these, and +fall back to /dev/urandom, if there is no such function present, as +a last resort. + +Signed-off-by: Björn Esser +--- + configure.ac | 17 +++++++++-------- + libmisc/salt.c | 42 ++++++++++++++++++++++++++++++++++++------ + 2 files changed, 45 insertions(+), 14 deletions(-) + +Index: shadow-4.8.1/configure.ac +=================================================================== +--- shadow-4.8.1.orig/configure.ac ++++ shadow-4.8.1/configure.ac +@@ -44,18 +44,19 @@ AC_HEADER_STDBOOL + + AC_CHECK_HEADERS(crypt.h errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ + utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ +- utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \ +- locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ +- attr/error_context.h) ++ utime.h ulimit.h sys/capability.h sys/random.h sys/resource.h \ ++ gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \ ++ attr/libattr.h attr/error_context.h) + + dnl shadow now uses the libc's shadow implementation + AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])]) + +-AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ +- gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ +- lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ +- getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ +- ruserok dlopen) ++AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \ ++ gethostname getentropy getrandom getspnam gettimeofday getusershell \ ++ getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \ ++ setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \ ++ getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \ ++ dlopen) + AC_SYS_LARGEFILE + + dnl Checks for typedefs, structures, and compiler characteristics. +Index: shadow-4.8.1/libmisc/salt.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/salt.c ++++ shadow-4.8.1/libmisc/salt.c +@@ -15,6 +15,9 @@ + #include + #include + #include ++#if HAVE_SYS_RANDOM_H ++#include ++#endif + #include "prototypes.h" + #include "defines.h" + #include "getdef.h" +@@ -128,19 +131,46 @@ static /*@observer@*/char *l64a (long va + static long read_random_bytes (void) + { + long randval = 0; +- FILE *f = fopen ("/dev/urandom", "r"); + +- if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) +- { +- fprintf (shadow_logfd, +- _("Unable to read from /dev/urandom.\n")); ++#ifdef HAVE_ARC4RANDOM_BUF ++ /* arc4random_buf, if it exists, can never fail. */ ++ arc4random_buf (&randval, sizeof (randval)); ++ goto end; ++ ++#elif defined(HAVE_GETENTROPY) ++ /* getentropy may exist but lack kernel support. */ ++ if (getentropy (&randval, sizeof (randval))) { ++ goto fail; ++ } ++ ++ goto end; ++ ++#elif defined(HAVE_GETRANDOM) ++ /* Likewise getrandom. */ ++ if ((size_t) getrandom (&randval, sizeof (randval), 0) != sizeof (randval)) { ++ goto fail; ++ } + ++ goto end; ++ ++#else ++ FILE *f = fopen ("/dev/urandom", "r"); ++ ++ if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) { + fclose(f); +- exit (1); ++ goto fail; + } + + fclose(f); ++ goto end; ++#endif ++ ++fail: ++ fprintf (shadow_logfd, ++ _("Unable to obtain random bytes.\n")); ++ exit (1); + ++end: + return randval; + } + diff --git a/shadow-utils.spec b/shadow-utils.spec index 20830e6..7923c7b 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.8.1 -Release: 15%{?dist} +Release: 16%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -116,6 +116,8 @@ Patch63: shadow-4.8.1-salt_c_comments.patch Patch64: shadow-4.8.1-salt_c_use_dev_urandom.patch # https://github.com/shadow-maint/shadow/commit/2c542f6c65f858b3dba20f58db4da56572f67a54 Patch65: shadow-4.8.1-useradd_create_relative_home_path_correctly.patch +# https://github.com/shadow-maint/shadow/commit/c82ed0c15e0e9e47df0b4c22672b72e35f061a9d +Patch66: shadow-4.8.1-getentropy_random_bytes.patch License: BSD and GPLv2+ BuildRequires: make @@ -206,6 +208,7 @@ Development files for shadow-utils-subid. %patch63 -p1 -b .comments %patch64 -p1 -b .use_dev_urandom %patch65 -p1 -b .useradd_create_relative_home_path_correctly +%patch66 -p1 -b .getentropy_random_bytes iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -375,6 +378,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Sun Jul 04 2021 Björn Esser - 2:4.8.1-16 +- Add a patch to obtain random bytes using getentropy() + * Tue Jun 29 2021 Iker Pedrosa - 2:4.8.1-15 - useradd: free correct pointer (#1976809) From a4f9def9dd72b299fd4a036f399bb8510c4ae252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Thu, 24 Jun 2021 12:47:17 +0200 Subject: [PATCH 024/118] Update shadow-4.8-crypt_h.patch with the upstreamed version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8-crypt_h.patch | 39 +++- shadow-4.8.1-crypt_gensalt.patch | 310 +++++++++++++++++++++++++++++++ shadow-utils.spec | 9 +- 3 files changed, 348 insertions(+), 10 deletions(-) create mode 100644 shadow-4.8.1-crypt_gensalt.patch diff --git a/shadow-4.8-crypt_h.patch b/shadow-4.8-crypt_h.patch index e2704e8..6d36376 100644 --- a/shadow-4.8-crypt_h.patch +++ b/shadow-4.8-crypt_h.patch @@ -1,6 +1,24 @@ -diff -up shadow-4.8/configure.ac.crypt_h shadow-4.8/configure.ac ---- shadow-4.8/configure.ac.crypt_h 2020-01-13 10:26:17.400481712 +0100 -+++ shadow-4.8/configure.ac 2020-01-13 10:29:11.563529093 +0100 +From c93897a8d71b9b1790caf3b2dee38dbe62518ae3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Thu, 24 Jun 2021 12:39:27 +0200 +Subject: [PATCH] lib/defines.h: Include if present on the system. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The functions crypt(3), crypt_gensalt(3), and their +feature test macros may be defined in there. + +Signed-off-by: Björn Esser +--- + configure.ac | 2 +- + lib/defines.h | 10 ++++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +Index: shadow-4.8.1/configure.ac +=================================================================== +--- shadow-4.8.1.orig/configure.ac ++++ shadow-4.8.1/configure.ac @@ -32,7 +32,7 @@ AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_HEADER_STDBOOL @@ -10,9 +28,10 @@ diff -up shadow-4.8/configure.ac.crypt_h shadow-4.8/configure.ac utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \ locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ -diff -up shadow-4.8/lib/defines.h.crypt_h shadow-4.8/lib/defines.h ---- shadow-4.8/lib/defines.h.crypt_h 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/defines.h 2020-01-13 10:26:17.400481712 +0100 +Index: shadow-4.8.1/lib/defines.h +=================================================================== +--- shadow-4.8.1.orig/lib/defines.h ++++ shadow-4.8.1/lib/defines.h @@ -4,6 +4,8 @@ #ifndef _DEFINES_H_ #define _DEFINES_H_ @@ -22,12 +41,16 @@ diff -up shadow-4.8/lib/defines.h.crypt_h shadow-4.8/lib/defines.h #if HAVE_STDBOOL_H # include #else -@@ -94,6 +96,10 @@ char *strchr (), *strrchr (), *strtok () +@@ -94,6 +96,14 @@ char *strchr (), *strrchr (), *strtok (); # include #endif ++/* ++ * crypt(3), crypt_gensalt(3), and their ++ * feature test macros may be defined in here. ++ */ +#if HAVE_CRYPT_H -+# include /* crypt(3) may be defined in here */ ++# include +#endif + #if TIME_WITH_SYS_TIME diff --git a/shadow-4.8.1-crypt_gensalt.patch b/shadow-4.8.1-crypt_gensalt.patch new file mode 100644 index 0000000..25198e6 --- /dev/null +++ b/shadow-4.8.1-crypt_gensalt.patch @@ -0,0 +1,310 @@ +From ea04eb301d08c0c58f1120f87d4ec184d3983ce5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Tue, 15 Jun 2021 14:23:42 +0200 +Subject: [PATCH] libmisc/salt.c: Use crypt_gensalt(), if available in + libcrypt. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most Linux distributions, including Fedora and RHEL 8, are shipping +with libxcrypt >= 4.0. + +Since that version of libxcrypt the provided family of crypt_gensalt() +functions are able to use automatic entropy drawn from secure system +ressources, like arc4random(), getentropy() or getrandom(). + +Anyways, the settings generated by crypt_gensalt() are always +guaranteed to works with the crypt() function. + +Using crypt_gensalt() is also needed to make proper use of newer +hashing methods, like yescrypt, provided by libxcrypt. + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 132 +++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 105 insertions(+), 27 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 13408a53..9fd34332 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -22,6 +22,13 @@ + #include "defines.h" + #include "getdef.h" + ++#if (defined CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY && \ ++ CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) ++#define USE_XCRYPT_GENSALT 1 ++#else ++#define USE_XCRYPT_GENSALT 0 ++#endif ++ + /* Add the salt prefix. */ + #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' + +@@ -77,21 +84,26 @@ + + /* local function prototypes */ + static long read_random_bytes (void); ++#if !USE_XCRYPT_GENSALT + static /*@observer@*/const char *gensalt (size_t salt_size); ++#endif /* !USE_XCRYPT_GENSALT */ + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) + static long shadow_random (long min, long max); + #endif /* USE_SHA_CRYPT || USE_BCRYPT */ + #ifdef USE_SHA_CRYPT +-static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); ++static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds); ++static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, unsigned long rounds); + #endif /* USE_SHA_CRYPT */ + #ifdef USE_BCRYPT +-static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); ++static /*@observer@*/const unsigned long BCRYPT_get_salt_rounds (/*@null@*/int *prefered_rounds); ++static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, unsigned long rounds); + #endif /* USE_BCRYPT */ + #ifdef USE_YESCRYPT +-static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost); ++static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost); ++static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost); + #endif /* USE_YESCRYPT */ + +-#ifndef HAVE_L64A ++#if !USE_XCRYPT_GENSALT && !defined(HAVE_L64A) + static /*@observer@*/char *l64a (long value) + { + static char buf[8]; +@@ -125,7 +137,7 @@ static /*@observer@*/char *l64a (long value) + + return buf; + } +-#endif /* !HAVE_L64A */ ++#endif /* !USE_XCRYPT_GENSALT && !defined(HAVE_L64A) */ + + /* Read sizeof (long) random bytes from /dev/urandom. */ + static long read_random_bytes (void) +@@ -199,14 +211,10 @@ static long shadow_random (long min, long max) + #endif /* USE_SHA_CRYPT || USE_BCRYPT */ + + #ifdef USE_SHA_CRYPT +-/* +- * Fill a salt prefix specifying the rounds number for the SHA crypt methods +- * to a buffer. +- */ +-static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) ++/* Return the the rounds number for the SHA crypt methods. */ ++static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds) + { + unsigned long rounds; +- const size_t buf_begin = strlen (buf); + + if (NULL == prefered_rounds) { + long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); +@@ -245,6 +253,17 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref + rounds = SHA_ROUNDS_MAX; + } + ++ return rounds; ++} ++ ++/* ++ * Fill a salt prefix specifying the rounds number for the SHA crypt methods ++ * to a buffer. ++ */ ++static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, unsigned long rounds) ++{ ++ const size_t buf_begin = strlen (buf); ++ + /* Nothing to do here if SHA_ROUNDS_DEFAULT is used. */ + if (rounds == SHA_ROUNDS_DEFAULT) { + return; +@@ -265,14 +284,10 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref + #endif /* USE_SHA_CRYPT */ + + #ifdef USE_BCRYPT +-/* +- * Fill a salt prefix specifying the rounds number for the BCRYPT method +- * to a buffer. +- */ +-static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) ++/* Return the the rounds number for the BCRYPT method. */ ++static /*@observer@*/const unsigned long BCRYPT_get_salt_rounds (/*@null@*/int *prefered_rounds) + { + unsigned long rounds; +- const size_t buf_begin = strlen (buf); + + if (NULL == prefered_rounds) { + long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1); +@@ -306,6 +321,11 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p + rounds = B_ROUNDS_MIN; + } + ++#if USE_XCRYPT_GENSALT ++ if (rounds > B_ROUNDS_MAX) { ++ rounds = B_ROUNDS_MAX; ++ } ++#else /* USE_XCRYPT_GENSALT */ + /* + * Use 19 as an upper bound for now, + * because musl doesn't allow rounds >= 20. +@@ -314,6 +334,18 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p + /* rounds = B_ROUNDS_MAX; */ + rounds = 19; + } ++#endif /* USE_XCRYPT_GENSALT */ ++ ++ return rounds; ++} ++ ++/* ++ * Fill a salt prefix specifying the rounds number for the BCRYPT method ++ * to a buffer. ++ */ ++static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, unsigned long rounds) ++{ ++ const size_t buf_begin = strlen (buf); + + /* + * Check if the result buffer is long enough. +@@ -330,14 +362,10 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p + #endif /* USE_BCRYPT */ + + #ifdef USE_YESCRYPT +-/* +- * Fill a salt prefix specifying the cost for the YESCRYPT method +- * to a buffer. +- */ +-static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost) ++/* Return the the cost number for the YESCRYPT method. */ ++static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost) + { + unsigned long cost; +- const size_t buf_begin = strlen (buf); + + if (NULL == prefered_cost) { + cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); +@@ -356,6 +384,17 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p + cost = Y_COST_MAX; + } + ++ return cost; ++} ++ ++/* ++ * Fill a salt prefix specifying the cost for the YESCRYPT method ++ * to a buffer. ++ */ ++static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost) ++{ ++ const size_t buf_begin = strlen (buf); ++ + /* + * Check if the result buffer is long enough. + * We are going to write four bytes, +@@ -380,6 +419,7 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p + } + #endif /* USE_YESCRYPT */ + ++#if !USE_XCRYPT_GENSALT + static /*@observer@*/const char *gensalt (size_t salt_size) + { + static char salt[MAX_SALT_SIZE + 6]; +@@ -397,6 +437,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + + return salt; + } ++#endif /* !USE_XCRYPT_GENSALT */ + + /* + * Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB +@@ -420,6 +461,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + static char result[GENSALT_SETTING_SIZE]; + size_t salt_len = MAX_SALT_SIZE; + const char *method; ++ unsigned long rounds = 0; + + memset (result, '\0', GENSALT_SETTING_SIZE); + +@@ -435,27 +477,32 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + if (0 == strcmp (method, "MD5")) { + MAGNUM(result, '1'); + salt_len = MD5_CRYPT_SALT_SIZE; ++ rounds = 0; + #ifdef USE_BCRYPT + } else if (0 == strcmp (method, "BCRYPT")) { + BCRYPTMAGNUM(result); + salt_len = BCRYPT_SALT_SIZE; +- BCRYPT_salt_rounds_to_buf (result, (int *) arg); ++ rounds = BCRYPT_get_salt_rounds ((int *) arg); ++ BCRYPT_salt_rounds_to_buf (result, rounds); + #endif /* USE_BCRYPT */ + #ifdef USE_YESCRYPT + } else if (0 == strcmp (method, "YESCRYPT")) { + MAGNUM(result, 'y'); + salt_len = YESCRYPT_SALT_SIZE; +- YESCRYPT_salt_cost_to_buf (result, (int *) arg); ++ rounds = YESCRYPT_get_salt_cost ((int *) arg); ++ YESCRYPT_salt_cost_to_buf (result, rounds); + #endif /* USE_YESCRYPT */ + #ifdef USE_SHA_CRYPT + } else if (0 == strcmp (method, "SHA256")) { + MAGNUM(result, '5'); + salt_len = SHA_CRYPT_SALT_SIZE; +- SHA_salt_rounds_to_buf (result, (int *) arg); ++ rounds = SHA_get_salt_rounds ((int *) arg); ++ SHA_salt_rounds_to_buf (result, rounds); + } else if (0 == strcmp (method, "SHA512")) { + MAGNUM(result, '6'); + salt_len = SHA_CRYPT_SALT_SIZE; +- SHA_salt_rounds_to_buf (result, (int *) arg); ++ rounds = SHA_get_salt_rounds ((int *) arg); ++ SHA_salt_rounds_to_buf (result, rounds); + #endif /* USE_SHA_CRYPT */ + } else if (0 != strcmp (method, "DES")) { + fprintf (shadow_logfd, +@@ -463,9 +510,39 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + "Defaulting to DES.\n"), + method); + salt_len = MAX_SALT_SIZE; ++ rounds = 0; + memset (result, '\0', GENSALT_SETTING_SIZE); + } + ++#if USE_XCRYPT_GENSALT ++ /* ++ * Prepare DES setting for crypt_gensalt(), if result ++ * has not been filled with anything previously. ++ */ ++ if ('\0' == result[0]) { ++ /* Avoid -Wunused-but-set-variable. */ ++ salt_len = GENSALT_SETTING_SIZE - 1; ++ rounds = 0; ++ memset (result, '.', salt_len); ++ result[salt_len] = '\0'; ++ } ++ ++ char *retval = crypt_gensalt (result, rounds, NULL, 0); ++ ++ /* Should not happen, but... */ ++ if (NULL == retval) { ++ fprintf (shadow_logfd, ++ _("Unable to generate a salt from setting " ++ "\"%s\", check your settings in " ++ "ENCRYPT_METHOD and the corresponding " ++ "configuration for your selected hash " ++ "method.\n"), result); ++ ++ exit (1); ++ } ++ ++ return retval; ++#else /* USE_XCRYPT_GENSALT */ + /* Check if the result buffer is long enough. */ + assert (GENSALT_SETTING_SIZE > strlen (result) + salt_len); + +@@ -474,4 +551,5 @@ static /*@observer@*/const char *gensalt (size_t salt_size) + GENSALT_SETTING_SIZE - strlen (result) - 1); + + return result; ++#endif /* USE_XCRYPT_GENSALT */ + } diff --git a/shadow-utils.spec b/shadow-utils.spec index 7923c7b..7e5b216 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.8.1 -Release: 16%{?dist} +Release: 17%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -48,7 +48,7 @@ Patch28: shadow-4.8-selinux-perms.patch Patch29: shadow-4.2.1-null-tm.patch # SElinux related - upstreamability unknown Patch31: shadow-4.6-getenforce.patch -# Handle include of crypt.h - could be upstreamed +# https://github.com/shadow-maint/shadow/commit/c93897a8d71b9b1790caf3b2dee38dbe62518ae3 Patch32: shadow-4.8-crypt_h.patch # Handle /etc/passwd corruption - could be upstreamed Patch33: shadow-4.8-long-entry.patch @@ -118,6 +118,8 @@ Patch64: shadow-4.8.1-salt_c_use_dev_urandom.patch Patch65: shadow-4.8.1-useradd_create_relative_home_path_correctly.patch # https://github.com/shadow-maint/shadow/commit/c82ed0c15e0e9e47df0b4c22672b72e35f061a9d Patch66: shadow-4.8.1-getentropy_random_bytes.patch +# https://github.com/shadow-maint/shadow/commit/ea04eb301d08c0c58f1120f87d4ec184d3983ce5 +Patch67: shadow-4.8.1-crypt_gensalt.patch License: BSD and GPLv2+ BuildRequires: make @@ -209,6 +211,7 @@ Development files for shadow-utils-subid. %patch64 -p1 -b .use_dev_urandom %patch65 -p1 -b .useradd_create_relative_home_path_correctly %patch66 -p1 -b .getentropy_random_bytes +%patch67 -p1 -b .crypt_gensalt iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -380,6 +383,8 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %changelog * Sun Jul 04 2021 Björn Esser - 2:4.8.1-16 - Add a patch to obtain random bytes using getentropy() +- Update shadow-4.8-crypt_h.patch with the upstreamed version +- Add a patch to make use of crypt_gensalt() from libxcrypt * Tue Jun 29 2021 Iker Pedrosa - 2:4.8.1-15 - useradd: free correct pointer (#1976809) From 90349359e4198987255c007060106575cf6452a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Mon, 5 Jul 2021 12:08:36 +0200 Subject: [PATCH 025/118] Fix release tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-utils.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 7e5b216..a78e1a3 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.8.1 -Release: 17%{?dist} +Release: 16%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz From 08a62b5fa3ab4570e3b6e810737b033133d94c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Mon, 12 Jul 2021 09:59:19 +0200 Subject: [PATCH 026/118] Enable bcrypt support, as libxcrypt supports it well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-utils.login.defs | 15 ++++++++++++++- shadow-utils.spec | 6 +++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index 67845ce..486203b 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -219,7 +219,20 @@ ENCRYPT_METHOD YESCRYPT # Currently SHA_CRYPT_MIN_ROUNDS is not supported -# Currently BCRYPT_MIN_ROUNDS and BCRYPT_MAX_ROUNDS are not supported +# +# Only works if ENCRYPT_METHOD is set to BCRYPT. +# +# Define the number of BCRYPT rounds. +# With a lot of rounds, it is more difficult to brute-force the password. +# However, more CPU resources will be needed to authenticate users if +# this value is increased. +# +# If not specified, 13 rounds will be attempted. +# If only one of the MIN or MAX values is set, then this value will be used. +# If MIN > MAX, the highest value will be used. +# +#BCRYPT_MIN_ROUNDS 13 +#BCRYPT_MAX_ROUNDS 31 # # Only works if ENCRYPT_METHOD is set to YESCRYPT. diff --git a/shadow-utils.spec b/shadow-utils.spec index a78e1a3..75898fd 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.8.1 -Release: 16%{?dist} +Release: 17%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -238,6 +238,7 @@ autoreconf --enable-man \ --with-audit \ --with-sha-crypt \ + --with-bcrypt \ --with-yescrypt \ --with-selinux \ --without-libcrack \ @@ -381,6 +382,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jul 12 2021 Björn Esser - 2:4.8.1-17 +- Enable bcrypt support, as libxcrypt supports it well + * Sun Jul 04 2021 Björn Esser - 2:4.8.1-16 - Add a patch to obtain random bytes using getentropy() - Update shadow-4.8-crypt_h.patch with the upstreamed version From fbe143d1bd6f5cdd0c936d1fb61fd236550ddb49 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 14 Jul 2021 11:30:45 +0200 Subject: [PATCH 027/118] Fix regression issues detected in rhbz#667593 and rhbz#672510 Signed-off-by: Iker Pedrosa --- shadow-4.8.1-covscan_fixes.patch | 9 --------- shadow-utils.spec | 5 ++++- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/shadow-4.8.1-covscan_fixes.patch b/shadow-4.8.1-covscan_fixes.patch index ea78ced..daca69f 100644 --- a/shadow-4.8.1-covscan_fixes.patch +++ b/shadow-4.8.1-covscan_fixes.patch @@ -731,15 +731,6 @@ index 2da734a7..d85d5f20 100644 return array; } -@@ -262,6 +263,8 @@ bool is_on_list (char *const *list, const char *member) - } - } - -+ free (members); -+ - /* - * Return the new array of pointers - */ diff --git a/libmisc/myname.c b/libmisc/myname.c index 05efdad3..e1b7f702 100644 --- a/libmisc/myname.c diff --git a/shadow-utils.spec b/shadow-utils.spec index 75898fd..a8be8ee 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.8.1 -Release: 17%{?dist} +Release: 18%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -382,6 +382,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Wed Jul 14 2021 Iker Pedrosa - 2:4.8.1-18 +- Fix regression issues detected in rhbz#667593 and rhbz#672510 + * Mon Jul 12 2021 Björn Esser - 2:4.8.1-17 - Enable bcrypt support, as libxcrypt supports it well From 0d2b677f8f44352f8ce0fa62e9230e6f4b431842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Wed, 14 Jul 2021 16:52:12 +0200 Subject: [PATCH 028/118] Add patch to fix 'fread returns element count, not element size' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-4.8.1-salt_c_fix_fread.patch | 29 +++++++++++++++++++++++++++++ shadow-utils.spec | 8 +++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 shadow-4.8.1-salt_c_fix_fread.patch diff --git a/shadow-4.8.1-salt_c_fix_fread.patch b/shadow-4.8.1-salt_c_fix_fread.patch new file mode 100644 index 0000000..754b292 --- /dev/null +++ b/shadow-4.8.1-salt_c_fix_fread.patch @@ -0,0 +1,29 @@ +From ffd35d89021a9b8375a9246082afc6fc270a93ee Mon Sep 17 00:00:00 2001 +From: steven Y Gui +Date: Wed, 14 Jul 2021 16:17:48 +0800 +Subject: [PATCH] fread returns element count, not element size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Björn Esser +--- + libmisc/salt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 9fd34332..91d528fd 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -168,7 +168,7 @@ static long read_random_bytes (void) + #else + FILE *f = fopen ("/dev/urandom", "r"); + +- if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) { ++ if (fread (&randval, sizeof (randval), 1, f) != 1) { + fclose(f); + goto fail; + } +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index a8be8ee..10efca9 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.8.1 -Release: 18%{?dist} +Release: 19%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -120,6 +120,8 @@ Patch65: shadow-4.8.1-useradd_create_relative_home_path_correctly.patch Patch66: shadow-4.8.1-getentropy_random_bytes.patch # https://github.com/shadow-maint/shadow/commit/ea04eb301d08c0c58f1120f87d4ec184d3983ce5 Patch67: shadow-4.8.1-crypt_gensalt.patch +# https://github.com/shadow-maint/shadow/commit/ffd35d89021a9b8375a9246082afc6fc270a93ee +Patch68: shadow-4.8.1-salt_c_fix_fread.patch License: BSD and GPLv2+ BuildRequires: make @@ -212,6 +214,7 @@ Development files for shadow-utils-subid. %patch65 -p1 -b .useradd_create_relative_home_path_correctly %patch66 -p1 -b .getentropy_random_bytes %patch67 -p1 -b .crypt_gensalt +%patch68 -p1 -b .fix_fread iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -382,6 +385,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Wed Jul 14 2021 Björn Esser - 2:4.8.1-19 +- Add patch to fix 'fread returns element count, not element size' + * Wed Jul 14 2021 Iker Pedrosa - 2:4.8.1-18 - Fix regression issues detected in rhbz#667593 and rhbz#672510 From 58090e11f17c64d21363adf09c72def050d2e303 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 23 Jul 2021 17:27:44 +0000 Subject: [PATCH 029/118] - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 10efca9..c6caf48 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.8.1 -Release: 19%{?dist} +Release: 20%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -385,6 +385,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Fri Jul 23 2021 Fedora Release Engineering - 2:4.8.1-20 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + * Wed Jul 14 2021 Björn Esser - 2:4.8.1-19 - Add patch to fix 'fread returns element count, not element size' From 94f04f9e715426f7cd7df6959ac76ddc5a00e4a1 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 4 Aug 2021 10:14:14 +0200 Subject: [PATCH 030/118] Rebase to version 4.9 usermod: allow all group types with -G option (#1975327) Clean spec file Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.1.5.1-info-parent-dir.patch | 21 - shadow-4.1.5.1-logmsg.patch | 13 - shadow-4.1.5.1-userdel-helpfix.patch | 16 - shadow-4.6-getenforce.patch | 21 - shadow-4.8-crypt_h.patch | 58 - shadow-4.8-selinux.patch | 241 -- shadow-4.8-useradd-selinux-mail.patch | 61 - shadow-4.8.1-check-local-groups.patch | 642 ----- ...-4.8.1-commonio-force-lock-file-sync.patch | 39 - shadow-4.8.1-covscan_fixes.patch | 793 ------ shadow-4.8.1-crypt_gensalt.patch | 310 --- ....1-fix_YESCRYPT_salt_cost_param_type.patch | 39 - shadow-4.8.1-fix_bcrypt_prefix.patch | 35 - shadow-4.8.1-getentropy_random_bytes.patch | 123 - shadow-4.8.1-libsubid_creation.patch | 1522 ---------- ...bid_fix_newusers_nss_provides_subids.patch | 151 - ...bsubid_init_not_print_error_messages.patch | 40 - shadow-4.8.1-libsubid_init_return_false.patch | 37 - ...4.8.1-libsubid_make_logfd_not_extern.patch | 41 - ....1-libsubid_not_print_error_messages.patch | 2443 ----------------- shadow-4.8.1-libsubid_nsswitch_support.patch | 2107 -------------- ....1-libsubid_simplify_ranges_variable.patch | 264 -- ....8.1-man-include-lastlog-file-caveat.patch | 33 - ...w-4.8.1-man-mention-nss-in-newuidmap.patch | 44 - ...w-4.8.1-man_clarify_subid_delegation.patch | 246 -- shadow-4.8.1-manfix.patch | 341 --- shadow-4.8.1-salt_c_comments.patch | 75 - shadow-4.8.1-salt_c_fix_fread.patch | 29 - shadow-4.8.1-salt_c_sanitize_code.patch | 555 ---- shadow-4.8.1-salt_c_use_dev_urandom.patch | 114 - shadow-4.8.1-useradd-man-clarification.patch | 35 - shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch | 44 - ..._create_relative_home_path_correctly.patch | 24 - shadow-4.8.1-yescrypt-support.patch | 960 ------- ...ate.patch => shadow-4.9-audit-update.patch | 24 +- ...ge.patch => shadow-4.9-default-range.patch | 11 +- shadow-4.9-manfix.patch | 180 ++ shadow-4.9-move-create-home.patch | 64 + ...ow-4.9-newuidmap-libeconf-dependency.patch | 15 + ...-null-tm.patch => shadow-4.9-null-tm.patch | 21 - ....6-redhat.patch => shadow-4.9-redhat.patch | 20 +- ...ow-4.9-usermod-allow-all-group-types.patch | 322 +++ shadow-utils.spec | 179 +- sources | 4 +- 45 files changed, 643 insertions(+), 11716 deletions(-) delete mode 100644 shadow-4.1.5.1-info-parent-dir.patch delete mode 100644 shadow-4.1.5.1-logmsg.patch delete mode 100644 shadow-4.1.5.1-userdel-helpfix.patch delete mode 100644 shadow-4.6-getenforce.patch delete mode 100644 shadow-4.8-crypt_h.patch delete mode 100644 shadow-4.8-selinux.patch delete mode 100644 shadow-4.8-useradd-selinux-mail.patch delete mode 100644 shadow-4.8.1-check-local-groups.patch delete mode 100644 shadow-4.8.1-commonio-force-lock-file-sync.patch delete mode 100644 shadow-4.8.1-covscan_fixes.patch delete mode 100644 shadow-4.8.1-crypt_gensalt.patch delete mode 100644 shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch delete mode 100644 shadow-4.8.1-fix_bcrypt_prefix.patch delete mode 100644 shadow-4.8.1-getentropy_random_bytes.patch delete mode 100644 shadow-4.8.1-libsubid_creation.patch delete mode 100644 shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch delete mode 100644 shadow-4.8.1-libsubid_init_not_print_error_messages.patch delete mode 100644 shadow-4.8.1-libsubid_init_return_false.patch delete mode 100644 shadow-4.8.1-libsubid_make_logfd_not_extern.patch delete mode 100644 shadow-4.8.1-libsubid_not_print_error_messages.patch delete mode 100644 shadow-4.8.1-libsubid_nsswitch_support.patch delete mode 100644 shadow-4.8.1-libsubid_simplify_ranges_variable.patch delete mode 100644 shadow-4.8.1-man-include-lastlog-file-caveat.patch delete mode 100644 shadow-4.8.1-man-mention-nss-in-newuidmap.patch delete mode 100644 shadow-4.8.1-man_clarify_subid_delegation.patch delete mode 100644 shadow-4.8.1-manfix.patch delete mode 100644 shadow-4.8.1-salt_c_comments.patch delete mode 100644 shadow-4.8.1-salt_c_fix_fread.patch delete mode 100644 shadow-4.8.1-salt_c_sanitize_code.patch delete mode 100644 shadow-4.8.1-salt_c_use_dev_urandom.patch delete mode 100644 shadow-4.8.1-useradd-man-clarification.patch delete mode 100644 shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch delete mode 100644 shadow-4.8.1-useradd_create_relative_home_path_correctly.patch delete mode 100644 shadow-4.8.1-yescrypt-support.patch rename shadow-4.8.1-audit-update.patch => shadow-4.9-audit-update.patch (99%) rename shadow-4.1.5.1-default-range.patch => shadow-4.9-default-range.patch (72%) create mode 100644 shadow-4.9-manfix.patch create mode 100644 shadow-4.9-move-create-home.patch create mode 100644 shadow-4.9-newuidmap-libeconf-dependency.patch rename shadow-4.2.1-null-tm.patch => shadow-4.9-null-tm.patch (75%) rename shadow-4.6-redhat.patch => shadow-4.9-redhat.patch (65%) create mode 100644 shadow-4.9-usermod-allow-all-group-types.patch diff --git a/.gitignore b/.gitignore index de3b420..cc68ade 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.8.tar.xz.asc /shadow-4.8.1.tar.xz /shadow-4.8.1.tar.xz.asc +/shadow-4.9.tar.xz +/shadow-4.9.tar.xz.asc diff --git a/shadow-4.1.5.1-info-parent-dir.patch b/shadow-4.1.5.1-info-parent-dir.patch deleted file mode 100644 index b3a525b..0000000 --- a/shadow-4.1.5.1-info-parent-dir.patch +++ /dev/null @@ -1,21 +0,0 @@ -Index: shadow-4.5/man/newusers.8.xml -=================================================================== ---- shadow-4.5.orig/man/newusers.8.xml -+++ shadow-4.5/man/newusers.8.xml -@@ -218,7 +218,15 @@ - - If this field does not specify an existing directory, the - specified directory is created, with ownership set to the -- user being created or updated and its primary group. -+ user being created or updated and its primary group. Note -+ that newusers does not create parent directories of the new -+ user's home directory. The newusers command will fail to -+ create the home directory if the parent directories do not -+ exist, and will send a message to stderr informing the user -+ of the failure. The newusers command will not halt or return -+ a failure to the calling shell if it fails to create the home -+ directory, it will continue to process the batch of new users -+ specified. - - - If the home directory of an existing user is changed, diff --git a/shadow-4.1.5.1-logmsg.patch b/shadow-4.1.5.1-logmsg.patch deleted file mode 100644 index ca7e57b..0000000 --- a/shadow-4.1.5.1-logmsg.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: shadow-4.5/src/useradd.c -=================================================================== ---- shadow-4.5.orig/src/useradd.c -+++ shadow-4.5/src/useradd.c -@@ -323,7 +323,7 @@ static void fail_exit (int code) - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -- SYSLOG ((LOG_INFO, "failed adding user '%s', data deleted", user_name)); -+ SYSLOG ((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); - exit (code); - } - diff --git a/shadow-4.1.5.1-userdel-helpfix.patch b/shadow-4.1.5.1-userdel-helpfix.patch deleted file mode 100644 index 075f482..0000000 --- a/shadow-4.1.5.1-userdel-helpfix.patch +++ /dev/null @@ -1,16 +0,0 @@ -Index: shadow-4.5/src/userdel.c -=================================================================== ---- shadow-4.5.orig/src/userdel.c -+++ shadow-4.5/src/userdel.c -@@ -143,8 +143,9 @@ static void usage (int status) - "\n" - "Options:\n"), - Prog); -- (void) fputs (_(" -f, --force force removal of files,\n" -- " even if not owned by user\n"), -+ (void) fputs (_(" -f, --force force some actions that would fail otherwise\n" -+ " e.g. removal of user still logged in\n" -+ " or files, even if not owned by the user\n"), - usageout); - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -r, --remove remove home directory and mail spool\n"), usageout); diff --git a/shadow-4.6-getenforce.patch b/shadow-4.6-getenforce.patch deleted file mode 100644 index 8a55bf5..0000000 --- a/shadow-4.6-getenforce.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up shadow-4.6/lib/selinux.c.getenforce shadow-4.6/lib/selinux.c ---- shadow-4.6/lib/selinux.c.getenforce 2018-05-28 15:10:15.870315221 +0200 -+++ shadow-4.6/lib/selinux.c 2018-05-28 15:10:15.894315731 +0200 -@@ -75,7 +75,7 @@ int set_selinux_file_context (const char - } - return 0; - error: -- if (security_getenforce () != 0) { -+ if (security_getenforce () > 0) { - return 1; - } - return 0; -@@ -95,7 +95,7 @@ int reset_selinux_file_context (void) - selinux_checked = true; - } - if (selinux_enabled) { -- if (setfscreatecon (NULL) != 0) { -+ if (setfscreatecon (NULL) != 0 && security_getenforce () > 0) { - return 1; - } - } diff --git a/shadow-4.8-crypt_h.patch b/shadow-4.8-crypt_h.patch deleted file mode 100644 index 6d36376..0000000 --- a/shadow-4.8-crypt_h.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c93897a8d71b9b1790caf3b2dee38dbe62518ae3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Thu, 24 Jun 2021 12:39:27 +0200 -Subject: [PATCH] lib/defines.h: Include if present on the system. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The functions crypt(3), crypt_gensalt(3), and their -feature test macros may be defined in there. - -Signed-off-by: Björn Esser ---- - configure.ac | 2 +- - lib/defines.h | 10 ++++++++++ - 2 files changed, 11 insertions(+), 1 deletion(-) - -Index: shadow-4.8.1/configure.ac -=================================================================== ---- shadow-4.8.1.orig/configure.ac -+++ shadow-4.8.1/configure.ac -@@ -32,7 +32,7 @@ AC_HEADER_STDC - AC_HEADER_SYS_WAIT - AC_HEADER_STDBOOL - --AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ -+AC_CHECK_HEADERS(crypt.h errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ - utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ - utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \ - locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ -Index: shadow-4.8.1/lib/defines.h -=================================================================== ---- shadow-4.8.1.orig/lib/defines.h -+++ shadow-4.8.1/lib/defines.h -@@ -4,6 +4,8 @@ - #ifndef _DEFINES_H_ - #define _DEFINES_H_ - -+#include "config.h" -+ - #if HAVE_STDBOOL_H - # include - #else -@@ -94,6 +96,14 @@ char *strchr (), *strrchr (), *strtok (); - # include - #endif - -+/* -+ * crypt(3), crypt_gensalt(3), and their -+ * feature test macros may be defined in here. -+ */ -+#if HAVE_CRYPT_H -+# include -+#endif -+ - #if TIME_WITH_SYS_TIME - # include - # include diff --git a/shadow-4.8-selinux.patch b/shadow-4.8-selinux.patch deleted file mode 100644 index 7b2177b..0000000 --- a/shadow-4.8-selinux.patch +++ /dev/null @@ -1,241 +0,0 @@ -diff -up shadow-4.8/lib/commonio.c.selinux shadow-4.8/lib/commonio.c ---- shadow-4.8/lib/commonio.c.selinux 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/commonio.c 2020-01-13 10:08:53.769101131 +0100 -@@ -964,7 +964,7 @@ int commonio_close (struct commonio_db * - snprintf (buf, sizeof buf, "%s-", db->filename); - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (buf) != 0) { -+ if (set_selinux_file_context (buf, db->filename) != 0) { - errors++; - } - #endif -@@ -997,7 +997,7 @@ int commonio_close (struct commonio_db * - snprintf (buf, sizeof buf, "%s+", db->filename); - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (buf) != 0) { -+ if (set_selinux_file_context (buf, db->filename) != 0) { - errors++; - } - #endif -diff -up shadow-4.8/libmisc/copydir.c.selinux shadow-4.8/libmisc/copydir.c ---- shadow-4.8/libmisc/copydir.c.selinux 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/libmisc/copydir.c 2020-01-13 10:08:53.769101131 +0100 -@@ -484,7 +484,7 @@ static int copy_dir (const char *src, co - */ - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -@@ -605,7 +605,7 @@ static int copy_symlink (const char *src - } - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - free (oldlink); - return -1; - } -@@ -684,7 +684,7 @@ static int copy_special (const char *src - int err = 0; - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -@@ -744,7 +744,7 @@ static int copy_file (const char *src, c - return -1; - } - #ifdef WITH_SELINUX -- if (set_selinux_file_context (dst) != 0) { -+ if (set_selinux_file_context (dst, NULL) != 0) { - return -1; - } - #endif /* WITH_SELINUX */ -diff -up shadow-4.8/lib/prototypes.h.selinux shadow-4.8/lib/prototypes.h ---- shadow-4.8/lib/prototypes.h.selinux 2020-01-13 10:08:53.769101131 +0100 -+++ shadow-4.8/lib/prototypes.h 2020-01-13 10:11:20.914627399 +0100 -@@ -334,7 +334,7 @@ extern /*@observer@*/const char *crypt_m - - /* selinux.c */ - #ifdef WITH_SELINUX --extern int set_selinux_file_context (const char *dst_name); -+extern int set_selinux_file_context (const char *dst_name, const char *orig_name); - extern int reset_selinux_file_context (void); - extern int check_selinux_permit (const char *perm_name); - #endif -diff -up shadow-4.8/lib/selinux.c.selinux shadow-4.8/lib/selinux.c ---- shadow-4.8/lib/selinux.c.selinux 2019-11-12 01:18:25.000000000 +0100 -+++ shadow-4.8/lib/selinux.c 2020-01-13 10:08:53.769101131 +0100 -@@ -51,7 +51,7 @@ static bool selinux_enabled; - * Callers may have to Reset SELinux to create files with default - * contexts with reset_selinux_file_context - */ --int set_selinux_file_context (const char *dst_name) -+int set_selinux_file_context (const char *dst_name, const char *orig_name) - { - /*@null@*/security_context_t scontext = NULL; - -@@ -63,19 +63,23 @@ int set_selinux_file_context (const char - if (selinux_enabled) { - /* Get the default security context for this file */ - if (matchpathcon (dst_name, 0, &scontext) < 0) { -- if (security_getenforce () != 0) { -- return 1; -- } -+ /* We could not get the default, copy the original */ -+ if (orig_name == NULL) -+ goto error; -+ if (getfilecon (orig_name, &scontext) < 0) -+ goto error; - } - /* Set the security context for the next created file */ -- if (setfscreatecon (scontext) < 0) { -- if (security_getenforce () != 0) { -- return 1; -- } -- } -+ if (setfscreatecon (scontext) < 0) -+ goto error; - freecon (scontext); - } - return 0; -+ error: -+ if (security_getenforce () != 0) { -+ return 1; -+ } -+ return 0; - } - - /* -diff -up shadow-4.8/lib/semanage.c.selinux shadow-4.8/lib/semanage.c ---- shadow-4.8/lib/semanage.c.selinux 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/semanage.c 2020-01-13 10:08:53.766101181 +0100 -@@ -294,6 +294,9 @@ int set_seuser (const char *login_name, - - ret = 0; - -+ /* drop obsolete matchpathcon cache */ -+ matchpathcon_fini(); -+ - done: - semanage_seuser_key_free (key); - semanage_handle_destroy (handle); -@@ -369,6 +372,10 @@ int del_seuser (const char *login_name) - } - - ret = 0; -+ -+ /* drop obsolete matchpathcon cache */ -+ matchpathcon_fini(); -+ - done: - semanage_handle_destroy (handle); - return ret; -diff -up shadow-4.8/src/useradd.c.selinux shadow-4.8/src/useradd.c ---- shadow-4.8/src/useradd.c.selinux 2020-01-13 10:08:53.762101248 +0100 -+++ shadow-4.8/src/useradd.c 2020-01-13 10:08:53.767101164 +0100 -@@ -2078,7 +2078,7 @@ static void create_home (void) - ++bhome; - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (prefix_user_home) != 0) { -+ if (set_selinux_file_context (prefix_user_home, NULL) != 0) { - fprintf (stderr, - _("%s: cannot set SELinux context for home directory %s\n"), - Prog, user_home); -@@ -2232,6 +2232,7 @@ static void create_mail (void) - */ - int main (int argc, char **argv) - { -+ int rv = E_SUCCESS; - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - pam_handle_t *pamh = NULL; -@@ -2454,27 +2455,12 @@ int main (int argc, char **argv) - - usr_update (); - -- if (mflg) { -- create_home (); -- if (home_added) { -- copy_tree (def_template, prefix_user_home, false, false, -- (uid_t)-1, user_id, (gid_t)-1, user_gid); -- } else { -- fprintf (stderr, -- _("%s: warning: the home directory %s already exists.\n" -- "%s: Not copying any file from skel directory into it.\n"), -- Prog, user_home, Prog); -- } -- -- } -- -- /* Do not create mail directory for system accounts */ -- if (!rflg) { -- create_mail (); -- } -- - close_files (); - -+ nscd_flush_cache ("passwd"); -+ nscd_flush_cache ("group"); -+ sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); -+ - /* - * tallylog_reset needs to be able to lookup - * a valid existing user name, -@@ -2485,8 +2471,9 @@ int main (int argc, char **argv) - } - - #ifdef WITH_SELINUX -- if (Zflg) { -- if (set_seuser (user_name, user_selinux) != 0) { -+ if (Zflg && *user_selinux) { -+ if (is_selinux_enabled () > 0) { -+ if (set_seuser (user_name, user_selinux) != 0) { - fprintf (stderr, - _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), - Prog, user_name, user_selinux); -@@ -2495,15 +2482,31 @@ int main (int argc, char **argv) - "adding SELinux user mapping", - user_name, (unsigned int) user_id, 0); - #endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -+ rv = E_SE_UPDATE; -+ } - } - } - #endif /* WITH_SELINUX */ - -- nscd_flush_cache ("passwd"); -- nscd_flush_cache ("group"); -- sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); -+ if (mflg) { -+ create_home (); -+ if (home_added) { -+ copy_tree (def_template, prefix_user_home, false, true, -+ (uid_t)-1, user_id, (gid_t)-1, user_gid); -+ } else { -+ fprintf (stderr, -+ _("%s: warning: the home directory %s already exists.\n" -+ "%s: Not copying any file from skel directory into it.\n"), -+ Prog, user_home, Prog); -+ } -+ -+ } -+ -+ /* Do not create mail directory for system accounts */ -+ if (!rflg) { -+ create_mail (); -+ } - -- return E_SUCCESS; -+ return rv; - } - diff --git a/shadow-4.8-useradd-selinux-mail.patch b/shadow-4.8-useradd-selinux-mail.patch deleted file mode 100644 index 1777f2d..0000000 --- a/shadow-4.8-useradd-selinux-mail.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 4dc62ebcf37d7568be1d4ca54367215eba8b8a28 Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Wed, 5 Feb 2020 15:04:39 +0100 -Subject: [PATCH] useradd: doesn't generate /var/spool/mail/$USER with the - proper SELinux user identity - -Explanation: use set_selinux_file_context() and reset_selinux_file_context() for create_mail() just as is done for create_home() - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1690527 ---- - src/useradd.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/src/useradd.c b/src/useradd.c -index a679392d..645d4a40 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -190,6 +190,7 @@ static bool home_added = false; - #define E_NAME_IN_USE 9 /* username already in use */ - #define E_GRP_UPDATE 10 /* can't update group file */ - #define E_HOMEDIR 12 /* can't create home directory */ -+#define E_MAILBOXFILE 13 /* can't create mailbox file */ - #define E_SE_UPDATE 14 /* can't update SELinux user mapping */ - #ifdef ENABLE_SUBIDS - #define E_SUB_UID_UPDATE 16 /* can't update the subordinate uid file */ -@@ -2210,6 +2211,16 @@ static void create_mail (void) - sprintf (file, "%s/%s/%s", prefix, spool, user_name); - else - sprintf (file, "%s/%s", spool, user_name); -+ -+#ifdef WITH_SELINUX -+ if (set_selinux_file_context (file, NULL) != 0) { -+ fprintf (stderr, -+ _("%s: cannot set SELinux context for mailbox file %s\n"), -+ Prog, file); -+ fail_exit (E_MAILBOXFILE); -+ } -+#endif -+ - fd = open (file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0); - if (fd < 0) { - perror (_("Creating mailbox file")); -@@ -2234,6 +2245,15 @@ static void create_mail (void) - - fsync (fd); - close (fd); -+#ifdef WITH_SELINUX -+ /* Reset SELinux to create files with default contexts */ -+ if (reset_selinux_file_context () != 0) { -+ fprintf (stderr, -+ _("%s: cannot reset SELinux file creation context\n"), -+ Prog); -+ fail_exit (E_MAILBOXFILE); -+ } -+#endif - } - } - --- -2.24.1 - diff --git a/shadow-4.8.1-check-local-groups.patch b/shadow-4.8.1-check-local-groups.patch deleted file mode 100644 index 6e9d2bf..0000000 --- a/shadow-4.8.1-check-local-groups.patch +++ /dev/null @@ -1,642 +0,0 @@ -From 140510de9de4771feb3af1d859c09604043a4c9b Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Fri, 27 Mar 2020 14:23:02 +0100 -Subject: [PATCH 1/2] usermod: check only local groups with -G option - -Check only local groups when adding new supplementary groups to a user - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1727236 ---- - src/usermod.c | 220 ++++++++++++++++++++++++++++++++------------------ - 1 file changed, 143 insertions(+), 77 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 05b98715..ef430296 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -183,6 +183,7 @@ static bool sub_gid_locked = false; - static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, - long int date); - static int get_groups (char *); -+static struct group * get_local_group (char * grp_name); - static /*@noreturn@*/void usage (int status); - static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); -@@ -196,7 +197,9 @@ static void grp_update (void); - - static void process_flags (int, char **); - static void close_files (void); -+static void close_group_files (void); - static void open_files (void); -+static void open_group_files (void); - static void usr_update (void); - static void move_home (void); - static void update_lastlog (void); -@@ -253,6 +256,11 @@ static int get_groups (char *list) - return 0; - } - -+ /* -+ * Open the group files -+ */ -+ open_group_files (); -+ - /* - * So long as there is some data to be converted, strip off each - * name and look it up. A mix of numerical and string values for -@@ -272,7 +280,7 @@ static int get_groups (char *list) - * Names starting with digits are treated as numerical GID - * values, otherwise the string is looked up as is. - */ -- grp = prefix_getgr_nam_gid (list); -+ grp = get_local_group (list); - - /* - * There must be a match, either by GID value or by -@@ -322,6 +330,8 @@ static int get_groups (char *list) - gr_free ((struct group *)grp); - } while (NULL != list); - -+ close_group_files (); -+ - user_groups[ngroups] = (char *) 0; - - /* -@@ -334,6 +344,44 @@ static int get_groups (char *list) - return 0; - } - -+/* -+ * get_local_group - checks if a given group name exists locally -+ * -+ * get_local_group() checks if a given group name exists locally. -+ * If the name exists the group information is returned, otherwise NULL is -+ * returned. -+ */ -+static struct group * get_local_group(char * grp_name) -+{ -+ const struct group *grp; -+ struct group *result_grp = NULL; -+ long long int gid; -+ char *endptr; -+ -+ gid = strtoll (grp_name, &endptr, 10); -+ if ( ('\0' != *grp_name) -+ && ('\0' == *endptr) -+ && (ERANGE != errno) -+ && (gid == (gid_t)gid)) { -+ grp = gr_locate_gid ((gid_t) gid); -+ } -+ else { -+ grp = gr_locate(grp_name); -+ } -+ -+ if (grp != NULL) { -+ result_grp = __gr_dup (grp); -+ if (NULL == result_grp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot find group '%s'.\n"), -+ Prog, grp_name); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+ -+ return result_grp; -+} -+ - #ifdef ENABLE_SUBIDS - struct ulong_range - { -@@ -1447,50 +1495,7 @@ static void close_files (void) - } - - if (Gflg || lflg) { -- if (gr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } -- } --#endif --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- sgr_dbname ())); -- /* continue */ -- } -- } --#endif -- if (gr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- gr_dbname ())); -- /* continue */ -- } -+ close_group_files (); - } - - if (is_shadow_pwd) { -@@ -1559,6 +1564,60 @@ static void close_files (void) - #endif - } - -+/* -+ * close_group_files - close all of the files that were opened -+ * -+ * close_group_files() closes all of the files that were opened related -+ * with groups. This causes any modified entries to be written out. -+ */ -+static void close_group_files (void) -+{ -+ if (gr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ gr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ sgr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+#endif -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ sgr_dbname ())); -+ /* continue */ -+ } -+ } -+#endif -+ if (gr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ gr_dbname ())); -+ /* continue */ -+ } -+} -+ - /* - * open_files - lock and open the password files - * -@@ -1594,38 +1653,7 @@ static void open_files (void) - } - - if (Gflg || lflg) { -- /* -- * Lock and open the group file. This will load all of the -- * group entries. -- */ -- if (gr_lock () == 0) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- gr_locked = true; -- if (gr_open (O_CREAT | O_RDWR) == 0) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp && (sgr_lock () == 0)) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- sgr_locked = true; -- if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#endif -+ open_group_files (); - } - #ifdef ENABLE_SUBIDS - if (vflg || Vflg) { -@@ -1661,6 +1689,44 @@ static void open_files (void) - #endif /* ENABLE_SUBIDS */ - } - -+/* -+ * open_group_files - lock and open the group files -+ * -+ * open_group_files() loads all of the group entries. -+ */ -+static void open_group_files (void) -+{ -+ if (gr_lock () == 0) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ gr_locked = true; -+ if (gr_open (O_CREAT | O_RDWR) == 0) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+#ifdef SHADOWGRP -+ if (is_shadow_grp && (sgr_lock () == 0)) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ sgr_locked = true; -+ if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+#endif -+} -+ - /* - * usr_update - create the user entries - * --- -2.25.4 - - -From 8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Mon, 30 Mar 2020 09:08:23 +0200 -Subject: [PATCH 2/2] useradd: check only local groups with -G option - -Check only local groups when adding new supplementary groups to a user - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1727236 ---- - src/useradd.c | 234 +++++++++++++++++++++++++++++++++----------------- - 1 file changed, 157 insertions(+), 77 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 645d4a40..90210233 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -211,6 +211,7 @@ static void get_defaults (void); - static void show_defaults (void); - static int set_defaults (void); - static int get_groups (char *); -+static struct group * get_local_group (char * grp_name); - static void usage (int status); - static void new_pwent (struct passwd *); - -@@ -220,7 +221,10 @@ static void grp_update (void); - - static void process_flags (int argc, char **argv); - static void close_files (void); -+static void close_group_files (void); -+static void unlock_group_files (void); - static void open_files (void); -+static void open_group_files (void); - static void open_shadow (void); - static void faillog_reset (uid_t); - static void lastlog_reset (uid_t); -@@ -731,6 +735,11 @@ static int get_groups (char *list) - return 0; - } - -+ /* -+ * Open the group files -+ */ -+ open_group_files (); -+ - /* - * So long as there is some data to be converted, strip off - * each name and look it up. A mix of numerical and string -@@ -749,7 +758,7 @@ static int get_groups (char *list) - * Names starting with digits are treated as numerical - * GID values, otherwise the string is looked up as is. - */ -- grp = prefix_getgr_nam_gid (list); -+ grp = get_local_group (list); - - /* - * There must be a match, either by GID value or by -@@ -799,6 +808,9 @@ static int get_groups (char *list) - user_groups[ngroups++] = xstrdup (grp->gr_name); - } while (NULL != list); - -+ close_group_files (); -+ unlock_group_files (); -+ - user_groups[ngroups] = (char *) 0; - - /* -@@ -811,6 +823,44 @@ static int get_groups (char *list) - return 0; - } - -+/* -+ * get_local_group - checks if a given group name exists locally -+ * -+ * get_local_group() checks if a given group name exists locally. -+ * If the name exists the group information is returned, otherwise NULL is -+ * returned. -+ */ -+static struct group * get_local_group(char * grp_name) -+{ -+ const struct group *grp; -+ struct group *result_grp = NULL; -+ long long int gid; -+ char *endptr; -+ -+ gid = strtoll (grp_name, &endptr, 10); -+ if ( ('\0' != *grp_name) -+ && ('\0' == *endptr) -+ && (ERANGE != errno) -+ && (gid == (gid_t)gid)) { -+ grp = gr_locate_gid ((gid_t) gid); -+ } -+ else { -+ grp = gr_locate(grp_name); -+ } -+ -+ if (grp != NULL) { -+ result_grp = __gr_dup (grp); -+ if (NULL == result_grp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot find group '%s'.\n"), -+ Prog, grp_name); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+ -+ return result_grp; -+} -+ - /* - * usage - display usage message and exit - */ -@@ -1530,23 +1580,9 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_PW_UPDATE); - } -- if (do_grp_update) { -- if (gr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp && (sgr_close () == 0)) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } --#endif -- } -+ -+ close_group_files (); -+ - #ifdef ENABLE_SUBIDS - if (is_sub_uid && (sub_uid_close () == 0)) { - fprintf (stderr, -@@ -1587,34 +1623,9 @@ static void close_files (void) - /* continue */ - } - pw_locked = false; -- if (gr_unlock () == 0) { -- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking-group-file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif -- /* continue */ -- } -- gr_locked = false; --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -- fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking-gshadow-file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif -- /* continue */ -- } -- sgr_locked = false; -- } --#endif -+ -+ unlock_group_files (); -+ - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { - if (sub_uid_unlock () == 0) { -@@ -1647,6 +1658,71 @@ static void close_files (void) - #endif /* ENABLE_SUBIDS */ - } - -+/* -+ * close_group_files - close all of the files that were opened -+ * -+ * close_group_files() closes all of the files that were opened related -+ * with groups. This causes any modified entries to be written out. -+ */ -+static void close_group_files (void) -+{ -+ if (do_grp_update) { -+ if (gr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+#ifdef SHADOWGRP -+ if (is_shadow_grp && (sgr_close () == 0)) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+#endif /* SHADOWGRP */ -+ } -+} -+ -+/* -+ * unlock_group_files - unlock all of the files that were locked -+ * -+ * unlock_group_files() unlocks all of the files that were locked related -+ * with groups. This causes any modified entries to be written out. -+ */ -+static void unlock_group_files (void) -+{ -+ if (gr_unlock () == 0) { -+ fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_ADD_USER, Prog, -+ "unlocking-group-file", -+ user_name, AUDIT_NO_ID, -+ SHADOW_AUDIT_FAILURE); -+#endif /* WITH_AUDIT */ -+ /* continue */ -+ } -+ gr_locked = false; -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_unlock () == 0) { -+ fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_ADD_USER, Prog, -+ "unlocking-gshadow-file", -+ user_name, AUDIT_NO_ID, -+ SHADOW_AUDIT_FAILURE); -+#endif /* WITH_AUDIT */ -+ /* continue */ -+ } -+ sgr_locked = false; -+ } -+#endif /* SHADOWGRP */ -+} -+ - /* - * open_files - lock and open the password files - * -@@ -1668,37 +1744,8 @@ static void open_files (void) - - /* shadow file will be opened by open_shadow(); */ - -- /* -- * Lock and open the group file. -- */ -- if (gr_lock () == 0) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- gr_locked = true; -- if (gr_open (O_CREAT | O_RDWR) == 0) { -- fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_lock () == 0) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- sgr_locked = true; -- if (sgr_open (O_CREAT | O_RDWR) == 0) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- } --#endif -+ open_group_files (); -+ - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { - if (sub_uid_lock () == 0) { -@@ -1733,6 +1780,39 @@ static void open_files (void) - #endif /* ENABLE_SUBIDS */ - } - -+static void open_group_files (void) -+{ -+ if (gr_lock () == 0) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ gr_locked = true; -+ if (gr_open (O_CREAT | O_RDWR) == 0) { -+ fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_lock () == 0) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ sgr_locked = true; -+ if (sgr_open (O_CREAT | O_RDWR) == 0) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+#endif /* SHADOWGRP */ -+} -+ - static void open_shadow (void) - { - if (!is_shadow_pwd) { --- -2.25.4 - diff --git a/shadow-4.8.1-commonio-force-lock-file-sync.patch b/shadow-4.8.1-commonio-force-lock-file-sync.patch deleted file mode 100644 index 5ca7b53..0000000 --- a/shadow-4.8.1-commonio-force-lock-file-sync.patch +++ /dev/null @@ -1,39 +0,0 @@ -From fb0f702cbf958a5ee9097c1611212c9880b347ce Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Mon, 2 Nov 2020 17:08:55 +0100 -Subject: [PATCH] commonio: force lock file sync - -lib/commonio.c: after writing to the lock file, force a file sync to -the storage system. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1862056 ---- - lib/commonio.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/lib/commonio.c b/lib/commonio.c -index 16fa7e75..c5b3d104 100644 ---- a/lib/commonio.c -+++ b/lib/commonio.c -@@ -157,7 +157,17 @@ static int do_lock_file (const char *file, const char *lock, bool log) - if (write (fd, buf, (size_t) len) != len) { - if (log) { - (void) fprintf (stderr, -- "%s: %s: %s\n", -+ "%s: %s file write error: %s\n", -+ Prog, file, strerror (errno)); -+ } -+ (void) close (fd); -+ unlink (file); -+ return 0; -+ } -+ if (fdatasync (fd) == -1) { -+ if (log) { -+ (void) fprintf (stderr, -+ "%s: %s file sync error: %s\n", - Prog, file, strerror (errno)); - } - (void) close (fd); --- -2.26.2 - diff --git a/shadow-4.8.1-covscan_fixes.patch b/shadow-4.8.1-covscan_fixes.patch deleted file mode 100644 index daca69f..0000000 --- a/shadow-4.8.1-covscan_fixes.patch +++ /dev/null @@ -1,793 +0,0 @@ -From fd9d79a1a3438ba7703939cfcd45fc266782c64e Mon Sep 17 00:00:00 2001 -From: whzhe -Date: Thu, 17 Dec 2020 03:27:15 -0500 -Subject: [PATCH] useradd.c:fix memleak in get_groups - -Signed-off-by: whzhe ---- - src/useradd.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 107e65f8..822b67f5 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -793,6 +793,7 @@ static int get_groups (char *list) - fprintf (stderr, - _("%s: group '%s' is a NIS group.\n"), - Prog, grp->gr_name); -+ gr_free(grp); - continue; - } - #endif -@@ -801,6 +802,7 @@ static int get_groups (char *list) - fprintf (stderr, - _("%s: too many groups specified (max %d).\n"), - Prog, ngroups); -+ gr_free(grp); - break; - } - -@@ -808,6 +810,7 @@ static int get_groups (char *list) - * Add the group name to the user's list of groups. - */ - user_groups[ngroups++] = xstrdup (grp->gr_name); -+ gr_free (grp); - } while (NULL != list); - - close_group_files (); --- -2.31.1 - -From c44b71cec25d60efc51aec9de3abce1f6efbfcf5 Mon Sep 17 00:00:00 2001 -From: whzhe51 -Date: Sat, 19 Dec 2020 04:29:06 -0500 -Subject: [PATCH] useradd.c:fix memleaks of grp Signed-off-by: whzhe51 - - ---- - src/useradd.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/useradd.c b/src/useradd.c -index 107e65f8..29c54e44 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -411,6 +411,7 @@ static void get_defaults (void) - } else { - def_group = grp->gr_gid; - def_gname = xstrdup (grp->gr_name); -+ gr_free(grp); - } - } - --- -2.31.1 - -From 1aed7ae945aafaeb253fc89a7ecedeaedf72654e Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 10 Jun 2021 13:05:03 +0200 -Subject: [PATCH] useradd.c: fix covscan RESOURCE_LEAK - -Error: RESOURCE_LEAK (CWE-772): [#def28] -shadow-4.8.1/src/useradd.c:1905: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/src/useradd.c:1905: var_assign: Assigning: "fd" = handle returned from "open("/var/log/faillog", 2)". -shadow-4.8.1/src/useradd.c:1906: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/useradd.c:1917: leaked_handle: Handle variable "fd" going out of scope leaks the handle. - 1915| /* continue */ - 1916| } - 1917|-> } - 1918| - 1919| static void lastlog_reset (uid_t uid) - -Error: RESOURCE_LEAK (CWE-772): [#def29] -shadow-4.8.1/src/useradd.c:1938: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/src/useradd.c:1938: var_assign: Assigning: "fd" = handle returned from "open("/var/log/lastlog", 2)". -shadow-4.8.1/src/useradd.c:1939: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/useradd.c:1950: leaked_handle: Handle variable "fd" going out of scope leaks the handle. - 1948| /* continue */ - 1949| } - 1950|-> } - 1951| - 1952| static void tallylog_reset (const char *user_name) - -Error: RESOURCE_LEAK (CWE-772): [#def30] -shadow-4.8.1/src/useradd.c:2109: alloc_fn: Storage is returned from allocation function "strdup". -shadow-4.8.1/src/useradd.c:2109: var_assign: Assigning: "bhome" = storage returned from "strdup(prefix_user_home)". -shadow-4.8.1/src/useradd.c:2131: noescape: Resource "bhome" is not freed or pointed-to in "strtok". -shadow-4.8.1/src/useradd.c:2207: leaked_storage: Variable "bhome" going out of scope leaks the storage it points to. - 2205| } - 2206| #endif - 2207|-> } - 2208| } - 2209| ---- - src/useradd.c | 41 ++++++++++++++++++++++++++++++++--------- - 1 file changed, 32 insertions(+), 9 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 4248b62c..127177e2 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1964,16 +1964,26 @@ static void faillog_reset (uid_t uid) - memzero (&fl, sizeof (fl)); - - fd = open (FAILLOG_FILE, O_RDWR); -- if ( (-1 == fd) -- || (lseek (fd, offset_uid, SEEK_SET) != offset_uid) -+ if (-1 == fd) { -+ fprintf (stderr, -+ _("%s: failed to open the faillog file for UID %lu: %s\n"), -+ Prog, (unsigned long) uid, strerror (errno)); -+ SYSLOG ((LOG_WARN, "failed to open the faillog file for UID %lu", (unsigned long) uid)); -+ return; -+ } -+ if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (write (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl)) -- || (fsync (fd) != 0) -- || (close (fd) != 0)) { -+ || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to reset the faillog entry of UID %lu: %s\n"), - Prog, (unsigned long) uid, strerror (errno)); - SYSLOG ((LOG_WARN, "failed to reset the faillog entry of UID %lu", (unsigned long) uid)); -- /* continue */ -+ } -+ if (close (fd) != 0) { -+ fprintf (stderr, -+ _("%s: failed to close the faillog file for UID %lu: %s\n"), -+ Prog, (unsigned long) uid, strerror (errno)); -+ SYSLOG ((LOG_WARN, "failed to close the faillog file for UID %lu", (unsigned long) uid)); - } - } - -@@ -1997,17 +2007,29 @@ static void lastlog_reset (uid_t uid) - memzero (&ll, sizeof (ll)); - - fd = open (LASTLOG_FILE, O_RDWR); -- if ( (-1 == fd) -- || (lseek (fd, offset_uid, SEEK_SET) != offset_uid) -+ if (-1 == fd) { -+ fprintf (stderr, -+ _("%s: failed to open the lastlog file for UID %lu: %s\n"), -+ Prog, (unsigned long) uid, strerror (errno)); -+ SYSLOG ((LOG_WARN, "failed to open the lastlog file for UID %lu", (unsigned long) uid)); -+ return; -+ } -+ if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) -- || (fsync (fd) != 0) -- || (close (fd) != 0)) { -+ || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), - Prog, (unsigned long) uid, strerror (errno)); - SYSLOG ((LOG_WARN, "failed to reset the lastlog entry of UID %lu", (unsigned long) uid)); - /* continue */ - } -+ if (close (fd) != 0) { -+ fprintf (stderr, -+ _("%s: failed to close the lastlog file for UID %lu: %s\n"), -+ Prog, (unsigned long) uid, strerror (errno)); -+ SYSLOG ((LOG_WARN, "failed to close the lastlog file for UID %lu", (unsigned long) uid)); -+ /* continue */ -+ } - } - - static void tallylog_reset (const char *user_name) -@@ -2254,6 +2276,7 @@ static void create_home (void) - } - cp = strtok (NULL, "/"); - } -+ free (bhome); - - (void) chown (prefix_user_home, user_id, user_gid); - mode_t mode = getdef_num ("HOME_MODE", --- -2.31.1 - -From 8281c82e324b57b3a4b520afad26b43ce128d521 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 11 Jun 2021 11:50:49 +0200 -Subject: [PATCH] usermod.c: fix covscan RESOURCE_LEAK - -Error: RESOURCE_LEAK (CWE-772): [#def31] -shadow-4.8.1/src/usermod.c:813: alloc_fn: Storage is returned from allocation function "__gr_dup". -shadow-4.8.1/src/usermod.c:813: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)". -shadow-4.8.1/src/usermod.c:892: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to. - 890| } - 891| } - 892|-> } - 893| - 894| #ifdef SHADOWGRP - -Error: RESOURCE_LEAK (CWE-772): [#def32] -shadow-4.8.1/src/usermod.c:933: alloc_fn: Storage is returned from allocation function "__sgr_dup". -shadow-4.8.1/src/usermod.c:933: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)". -shadow-4.8.1/src/usermod.c:1031: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to. - 1029| } - 1030| } - 1031|-> } - 1032| #endif /* SHADOWGRP */ - 1033| - -Error: RESOURCE_LEAK (CWE-772): [#def34] -shadow-4.8.1/src/usermod.c:1161: alloc_fn: Storage is returned from allocation function "getgr_nam_gid". -shadow-4.8.1/src/usermod.c:1161: var_assign: Assigning: "grp" = storage returned from "getgr_nam_gid(optarg)". -shadow-4.8.1/src/usermod.c:1495: leaked_storage: Variable "grp" going out of scope leaks the storage it points to. - 1493| } - 1494| #endif /* ENABLE_SUBIDS */ - 1495|-> } - 1496| - 1497| /* - -Error: RESOURCE_LEAK (CWE-772): [#def35] -shadow-4.8.1/src/usermod.c:1991: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/src/usermod.c:1991: var_assign: Assigning: "fd" = handle returned from "open("/var/log/lastlog", 2)". -shadow-4.8.1/src/usermod.c:2000: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/usermod.c:2000: noescape: Resource "fd" is not freed or pointed-to in "read". [Note: The source code implementation of the function has been overridden by a builtin model.] -shadow-4.8.1/src/usermod.c:2003: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/usermod.c:2032: leaked_handle: Handle variable "fd" going out of scope leaks the handle. - 2030| } - 2031| } - 2032|-> } - 2033| - 2034| /* - -Error: RESOURCE_LEAK (CWE-772): [#def36] -shadow-4.8.1/src/usermod.c:2052: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/src/usermod.c:2052: var_assign: Assigning: "fd" = handle returned from "open("/var/log/faillog", 2)". -shadow-4.8.1/src/usermod.c:2061: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/usermod.c:2061: noescape: Resource "fd" is not freed or pointed-to in "read". [Note: The source code implementation of the function has been overridden by a builtin model.] -shadow-4.8.1/src/usermod.c:2064: noescape: Resource "fd" is not freed or pointed-to in "lseek". -shadow-4.8.1/src/usermod.c:2092: leaked_handle: Handle variable "fd" going out of scope leaks the handle. - 2090| } - 2091| } - 2092|-> } - 2093| - 2094| #ifndef NO_MOVE_MAILBOX ---- - src/usermod.c | 25 +++++++++++++------------ - 1 file changed, 13 insertions(+), 12 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 7870ba57..03bb9b9d 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -871,6 +871,8 @@ static void update_group (void) - SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); - fail_exit (E_GRP_UPDATE); - } -+ -+ gr_free(ngrp); - } - } - -@@ -1006,6 +1008,8 @@ static void update_gshadow (void) - sgr_dbname (), nsgrp->sg_name)); - fail_exit (E_GRP_UPDATE); - } -+ -+ free (nsgrp); - } - } - #endif /* SHADOWGRP */ -@@ -1152,6 +1156,7 @@ static void process_flags (int argc, char **argv) - } - user_newgid = grp->gr_gid; - gflg = true; -+ gr_free (grp); - break; - case 'G': - if (get_groups (optarg) != 0) { -@@ -1995,8 +2000,7 @@ static void update_lastlog (void) - /* Copy the old entry to its new location */ - if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) - || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll) -- || (fsync (fd) != 0) -- || (close (fd) != 0)) { -+ || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"), - Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); -@@ -2012,16 +2016,15 @@ static void update_lastlog (void) - memzero (&ll, sizeof (ll)); - if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) - || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll) -- || (fsync (fd) != 0) -- || (close (fd) != 0)) { -+ || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"), - Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); - } -- } else { -- (void) close (fd); - } - } -+ -+ (void) close (fd); - } - - /* -@@ -2056,8 +2059,7 @@ static void update_faillog (void) - /* Copy the old entry to its new location */ - if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) - || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl) -- || (fsync (fd) != 0) -- || (close (fd) != 0)) { -+ || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"), - Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); -@@ -2072,16 +2074,15 @@ static void update_faillog (void) - /* Reset the new uid's faillog entry */ - memzero (&fl, sizeof (fl)); - if ( (lseek (fd, off_newuid, SEEK_SET) != off_newuid) -- || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl) -- || (close (fd) != 0)) { -+ || (write (fd, &fl, sizeof fl) != (ssize_t) sizeof fl)) { - fprintf (stderr, - _("%s: failed to copy the faillog entry of user %lu to user %lu: %s\n"), - Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno)); - } -- } else { -- (void) close (fd); - } - } -+ -+ (void) close (fd); - } - - #ifndef NO_MOVE_MAILBOX --- -2.31.1 - -From 5d0d7841971cc53d9a9d1aefe12f00204115bf6a Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Wed, 16 Jun 2021 09:50:53 +0200 -Subject: [PATCH] Fix covscan BUFFER_SIZE - -Error: BUFFER_SIZE (CWE-170): [#def6] -shadow-4.8.1/libmisc/failure.c:101: buffer_size_warning: Calling "strncpy" with a maximum size argument of 12 bytes on destination array "fl->fail_line" of size 12 bytes might leave the destination string unterminated. - 99| } - 100| - 101|-> strncpy (fl->fail_line, tty, sizeof fl->fail_line); - 102| (void) time (&fl->fail_time); - 103| - -Error: BUFFER_SIZE (CWE-170): [#def9] -shadow-4.8.1/libmisc/log.c:103: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "newlog.ll_line" of size 32 bytes might leave the destination string unterminated. - 101| (void) time (&ll_time); - 102| newlog.ll_time = ll_time; - 103|-> strncpy (newlog.ll_line, line, sizeof newlog.ll_line); - 104| #if HAVE_LL_HOST - 105| strncpy (newlog.ll_host, host, sizeof newlog.ll_host); - -Error: BUFFER_SIZE (CWE-170): [#def10] -shadow-4.8.1/libmisc/log.c:105: buffer_size_warning: Calling "strncpy" with a maximum size argument of 256 bytes on destination array "newlog.ll_host" of size 256 bytes might leave the destination string unterminated. - 103| strncpy (newlog.ll_line, line, sizeof newlog.ll_line); - 104| #if HAVE_LL_HOST - 105|-> strncpy (newlog.ll_host, host, sizeof newlog.ll_host); - 106| #endif - 107| if ( (lseek (fd, offset, SEEK_SET) != offset) - -Error: BUFFER_SIZE (CWE-170): [#def13] -shadow-4.8.1/libmisc/utmp.c:260: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "utent->ut_line" of size 32 bytes might leave the destination string unterminated. - 258| #endif /* HAVE_STRUCT_UTMP_UT_TYPE */ - 259| utent->ut_pid = getpid (); - 260|-> strncpy (utent->ut_line, line, sizeof (utent->ut_line)); - 261| #ifdef HAVE_STRUCT_UTMP_UT_ID - 262| if (NULL != ut) { - -Error: BUFFER_SIZE (CWE-170): [#def14] -shadow-4.8.1/libmisc/utmp.c:266: buffer_size_warning: Calling "strncpy" with a maximum size argument of 4 bytes on destination array "utent->ut_id" of size 4 bytes might leave the destination string unterminated. - 264| } else { - 265| /* XXX - assumes /dev/tty?? */ - 266|-> strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id)); - 267| } - 268| #endif /* HAVE_STRUCT_UTMP_UT_ID */ - -Error: BUFFER_SIZE (CWE-170): [#def15] -shadow-4.8.1/libmisc/utmp.c:273: buffer_size_warning: Calling "strncpy" with a maximum size argument of 32 bytes on destination array "utent->ut_user" of size 32 bytes might leave the destination string unterminated. - 271| #endif /* HAVE_STRUCT_UTMP_UT_NAME */ - 272| #ifdef HAVE_STRUCT_UTMP_UT_USER - 273|-> strncpy (utent->ut_user, name, sizeof (utent->ut_user)); - 274| #endif /* HAVE_STRUCT_UTMP_UT_USER */ - 275| if (NULL != hostname) { - -Error: BUFFER_SIZE (CWE-170): [#def16] -shadow-4.8.1/libmisc/utmp.c:278: buffer_size_warning: Calling "strncpy" with a maximum size argument of 256 bytes on destination array "utent->ut_host" of size 256 bytes might leave the destination string unterminated. - 276| struct addrinfo *info = NULL; - 277| #ifdef HAVE_STRUCT_UTMP_UT_HOST - 278|-> strncpy (utent->ut_host, hostname, sizeof (utent->ut_host)); - 279| #endif /* HAVE_STRUCT_UTMP_UT_HOST */ - 280| #ifdef HAVE_STRUCT_UTMP_UT_SYSLEN - -Signed-off-by: Iker Pedrosa ---- - libmisc/failure.c | 2 +- - libmisc/log.c | 4 ++-- - libmisc/utmp.c | 8 ++++---- - 3 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/libmisc/failure.c b/libmisc/failure.c -index f6390a79..a1f3ec79 100644 ---- a/libmisc/failure.c -+++ b/libmisc/failure.c -@@ -98,7 +98,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl) - fl->fail_cnt++; - } - -- strncpy (fl->fail_line, tty, sizeof fl->fail_line); -+ strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1); - (void) time (&fl->fail_time); - - /* -diff --git a/libmisc/log.c b/libmisc/log.c -index eb84859e..68a9d7e2 100644 ---- a/libmisc/log.c -+++ b/libmisc/log.c -@@ -100,9 +100,9 @@ void dolastlog ( - ll_time = newlog.ll_time; - (void) time (&ll_time); - newlog.ll_time = ll_time; -- strncpy (newlog.ll_line, line, sizeof newlog.ll_line); -+ strncpy (newlog.ll_line, line, sizeof (newlog.ll_line) - 1); - #if HAVE_LL_HOST -- strncpy (newlog.ll_host, host, sizeof newlog.ll_host); -+ strncpy (newlog.ll_host, host, sizeof (newlog.ll_host) - 1); - #endif - if ( (lseek (fd, offset, SEEK_SET) != offset) - || (write (fd, (const void *) &newlog, sizeof newlog) != (ssize_t) sizeof newlog) -diff --git a/libmisc/utmp.c b/libmisc/utmp.c -index ba69cf61..5dcd419f 100644 ---- a/libmisc/utmp.c -+++ b/libmisc/utmp.c -@@ -257,25 +257,25 @@ static void updwtmpx (const char *filename, const struct utmpx *utx) - utent->ut_type = USER_PROCESS; - #endif /* HAVE_STRUCT_UTMP_UT_TYPE */ - utent->ut_pid = getpid (); -- strncpy (utent->ut_line, line, sizeof (utent->ut_line)); -+ strncpy (utent->ut_line, line, sizeof (utent->ut_line) - 1); - #ifdef HAVE_STRUCT_UTMP_UT_ID - if (NULL != ut) { - strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id)); - } else { - /* XXX - assumes /dev/tty?? */ -- strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id)); -+ strncpy (utent->ut_id, line + 3, sizeof (utent->ut_id) - 1); - } - #endif /* HAVE_STRUCT_UTMP_UT_ID */ - #ifdef HAVE_STRUCT_UTMP_UT_NAME - strncpy (utent->ut_name, name, sizeof (utent->ut_name)); - #endif /* HAVE_STRUCT_UTMP_UT_NAME */ - #ifdef HAVE_STRUCT_UTMP_UT_USER -- strncpy (utent->ut_user, name, sizeof (utent->ut_user)); -+ strncpy (utent->ut_user, name, sizeof (utent->ut_user) - 1); - #endif /* HAVE_STRUCT_UTMP_UT_USER */ - if (NULL != hostname) { - struct addrinfo *info = NULL; - #ifdef HAVE_STRUCT_UTMP_UT_HOST -- strncpy (utent->ut_host, hostname, sizeof (utent->ut_host)); -+ strncpy (utent->ut_host, hostname, sizeof (utent->ut_host) - 1); - #endif /* HAVE_STRUCT_UTMP_UT_HOST */ - #ifdef HAVE_STRUCT_UTMP_UT_SYSLEN - utent->ut_syslen = MIN (strlen (hostname), --- -2.31.1 - -From e65cc6aebcb4132fa413f00a905216a5b35b3d57 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 14 Jun 2021 12:39:48 +0200 -Subject: [PATCH] Fix covscan RESOURCE_LEAK - -Error: RESOURCE_LEAK (CWE-772): [#def1] -shadow-4.8.1/lib/commonio.c:320: alloc_fn: Storage is returned from allocation function "fopen_set_perms". -shadow-4.8.1/lib/commonio.c:320: var_assign: Assigning: "bkfp" = storage returned from "fopen_set_perms(backup, "w", &sb)". -shadow-4.8.1/lib/commonio.c:329: noescape: Resource "bkfp" is not freed or pointed-to in "putc". -shadow-4.8.1/lib/commonio.c:334: noescape: Resource "bkfp" is not freed or pointed-to in "fflush". -shadow-4.8.1/lib/commonio.c:339: noescape: Resource "bkfp" is not freed or pointed-to in "fileno". -shadow-4.8.1/lib/commonio.c:342: leaked_storage: Variable "bkfp" going out of scope leaks the storage it points to. - 340| || (fclose (bkfp) != 0)) { - 341| /* FIXME: unlink the backup file? */ - 342|-> return -1; - 343| } - 344| - -Error: RESOURCE_LEAK (CWE-772): [#def2] -shadow-4.8.1/libmisc/addgrps.c:69: alloc_fn: Storage is returned from allocation function "malloc". -shadow-4.8.1/libmisc/addgrps.c:69: var_assign: Assigning: "grouplist" = storage returned from "malloc(i * 4UL)". -shadow-4.8.1/libmisc/addgrps.c:73: noescape: Resource "grouplist" is not freed or pointed-to in "getgroups". [Note: The source code implementation of the function has been overridden by a builtin model.] -shadow-4.8.1/libmisc/addgrps.c:126: leaked_storage: Variable "grouplist" going out of scope leaks the storage it points to. - 124| } - 125| - 126|-> return 0; - 127| } - 128| #else /* HAVE_SETGROUPS && !USE_PAM */ - -Error: RESOURCE_LEAK (CWE-772): [#def3] -shadow-4.8.1/libmisc/chowntty.c:62: alloc_fn: Storage is returned from allocation function "getgr_nam_gid". -shadow-4.8.1/libmisc/chowntty.c:62: var_assign: Assigning: "grent" = storage returned from "getgr_nam_gid(getdef_str("TTYGROUP"))". -shadow-4.8.1/libmisc/chowntty.c:98: leaked_storage: Variable "grent" going out of scope leaks the storage it points to. - 96| */ - 97| #endif - 98|-> } - 99| - -Error: RESOURCE_LEAK (CWE-772): [#def4] -shadow-4.8.1/libmisc/copydir.c:742: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/libmisc/copydir.c:742: var_assign: Assigning: "ifd" = handle returned from "open(src, 0)". -shadow-4.8.1/libmisc/copydir.c:748: leaked_handle: Handle variable "ifd" going out of scope leaks the handle. - 746| #ifdef WITH_SELINUX - 747| if (set_selinux_file_context (dst, NULL) != 0) { - 748|-> return -1; - 749| } - 750| #endif /* WITH_SELINUX */ - -Error: RESOURCE_LEAK (CWE-772): [#def5] -shadow-4.8.1/libmisc/copydir.c:751: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] -shadow-4.8.1/libmisc/copydir.c:751: var_assign: Assigning: "ofd" = handle returned from "open(dst, 577, statp->st_mode & 0xfffU)". -shadow-4.8.1/libmisc/copydir.c:752: noescape: Resource "ofd" is not freed or pointed-to in "fchown_if_needed". -shadow-4.8.1/libmisc/copydir.c:775: leaked_handle: Handle variable "ofd" going out of scope leaks the handle. - 773| ) { - 774| (void) close (ifd); - 775|-> return -1; - 776| } - 777| - -Error: RESOURCE_LEAK (CWE-772): [#def7] -shadow-4.8.1/libmisc/idmapping.c:188: alloc_fn: Storage is returned from allocation function "xmalloc". -shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "buf" = storage returned from "xmalloc(bufsize)". -shadow-4.8.1/libmisc/idmapping.c:188: var_assign: Assigning: "pos" = "buf". -shadow-4.8.1/libmisc/idmapping.c:213: noescape: Resource "buf" is not freed or pointed-to in "write". -shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "pos" going out of scope leaks the storage it points to. -shadow-4.8.1/libmisc/idmapping.c:219: leaked_storage: Variable "buf" going out of scope leaks the storage it points to. - 217| } - 218| close(fd); - 219|-> } - -Error: RESOURCE_LEAK (CWE-772): [#def8] -shadow-4.8.1/libmisc/list.c:211: alloc_fn: Storage is returned from allocation function "xstrdup". -shadow-4.8.1/libmisc/list.c:211: var_assign: Assigning: "members" = storage returned from "xstrdup(comma)". -shadow-4.8.1/libmisc/list.c:217: var_assign: Assigning: "cp" = "members". -shadow-4.8.1/libmisc/list.c:218: noescape: Resource "cp" is not freed or pointed-to in "strchr". -shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "cp" going out of scope leaks the storage it points to. -shadow-4.8.1/libmisc/list.c:244: leaked_storage: Variable "members" going out of scope leaks the storage it points to. - 242| if ('\0' == *members) { - 243| *array = (char *) 0; - 244|-> return array; - 245| } - 246| - -Error: RESOURCE_LEAK (CWE-772): [#def11] -shadow-4.8.1/libmisc/myname.c:61: alloc_fn: Storage is returned from allocation function "xgetpwnam". -shadow-4.8.1/libmisc/myname.c:61: var_assign: Assigning: "pw" = storage returned from "xgetpwnam(cp)". -shadow-4.8.1/libmisc/myname.c:67: leaked_storage: Variable "pw" going out of scope leaks the storage it points to. - 65| } - 66| - 67|-> return xgetpwuid (ruid); - 68| } - 69| - -Error: RESOURCE_LEAK (CWE-772): [#def12] -shadow-4.8.1/libmisc/user_busy.c:260: alloc_fn: Storage is returned from allocation function "opendir". -shadow-4.8.1/libmisc/user_busy.c:260: var_assign: Assigning: "task_dir" = storage returned from "opendir(task_path)". -shadow-4.8.1/libmisc/user_busy.c:262: noescape: Resource "task_dir" is not freed or pointed-to in "readdir". -shadow-4.8.1/libmisc/user_busy.c:278: leaked_storage: Variable "task_dir" going out of scope leaks the storage it points to. - 276| _("%s: user %s is currently used by process %d\n"), - 277| Prog, name, pid); - 278|-> return 1; - 279| } - 280| } - -Error: RESOURCE_LEAK (CWE-772): [#def20] -shadow-4.8.1/src/newgrp.c:162: alloc_fn: Storage is returned from allocation function "xgetspnam". -shadow-4.8.1/src/newgrp.c:162: var_assign: Assigning: "spwd" = storage returned from "xgetspnam(pwd->pw_name)". -shadow-4.8.1/src/newgrp.c:234: leaked_storage: Variable "spwd" going out of scope leaks the storage it points to. - 232| } - 233| - 234|-> return; - 235| - 236| failure: - -Error: RESOURCE_LEAK (CWE-772): [#def21] -shadow-4.8.1/src/passwd.c:530: alloc_fn: Storage is returned from allocation function "xstrdup". -shadow-4.8.1/src/passwd.c:530: var_assign: Assigning: "cp" = storage returned from "xstrdup(crypt_passwd)". -shadow-4.8.1/src/passwd.c:551: noescape: Resource "cp" is not freed or pointed-to in "strlen". -shadow-4.8.1/src/passwd.c:554: noescape: Resource "cp" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] -shadow-4.8.1/src/passwd.c:555: overwrite_var: Overwriting "cp" in "cp = newpw" leaks the storage that "cp" points to. - 553| strcpy (newpw, "!"); - 554| strcat (newpw, cp); - 555|-> cp = newpw; - 556| } - 557| return cp; ---- - lib/commonio.c | 8 ++++++-- - libmisc/addgrps.c | 6 +++++- - libmisc/chowntty.c | 1 + - libmisc/copydir.c | 6 ++++++ - libmisc/idmapping.c | 1 + - libmisc/list.c | 3 +++ - libmisc/myname.c | 3 +++ - libmisc/user_busy.c | 1 + - src/newgrp.c | 3 ++- - src/passwd.c | 5 +++++ - 10 files changed, 33 insertions(+), 4 deletions(-) - -diff --git a/lib/commonio.c b/lib/commonio.c -index 23ac91f9..cef404b9 100644 ---- a/lib/commonio.c -+++ b/lib/commonio.c -@@ -336,8 +336,12 @@ static int create_backup (const char *backup, FILE * fp) - /* FIXME: unlink the backup file? */ - return -1; - } -- if ( (fsync (fileno (bkfp)) != 0) -- || (fclose (bkfp) != 0)) { -+ if (fsync (fileno (bkfp)) != 0) { -+ (void) fclose (bkfp); -+ /* FIXME: unlink the backup file? */ -+ return -1; -+ } -+ if (fclose (bkfp) != 0) { - /* FIXME: unlink the backup file? */ - return -1; - } -diff --git a/libmisc/addgrps.c b/libmisc/addgrps.c -index 2e38e340..76c172a5 100644 ---- a/libmisc/addgrps.c -+++ b/libmisc/addgrps.c -@@ -57,6 +57,7 @@ int add_groups (const char *list) - bool added; - char *token; - char buf[1024]; -+ int ret; - - if (strlen (list) >= sizeof (buf)) { - errno = EINVAL; -@@ -120,9 +121,12 @@ int add_groups (const char *list) - } - - if (added) { -- return setgroups ((size_t)ngroups, grouplist); -+ ret = setgroups ((size_t)ngroups, grouplist); -+ free (grouplist); -+ return ret; - } - -+ free (grouplist); - return 0; - } - #else /* HAVE_SETGROUPS && !USE_PAM */ -diff --git a/libmisc/chowntty.c b/libmisc/chowntty.c -index ea706c4f..a42ab622 100644 ---- a/libmisc/chowntty.c -+++ b/libmisc/chowntty.c -@@ -62,6 +62,7 @@ void chown_tty (const struct passwd *info) - grent = getgr_nam_gid (getdef_str ("TTYGROUP")); - if (NULL != grent) { - gid = grent->gr_gid; -+ gr_free (grent); - } else { - gid = info->pw_gid; - } -diff --git a/libmisc/copydir.c b/libmisc/copydir.c -index 91d391f8..015e1b68 100644 ---- a/libmisc/copydir.c -+++ b/libmisc/copydir.c -@@ -745,6 +745,7 @@ static int copy_file (const char *src, const char *dst, - } - #ifdef WITH_SELINUX - if (set_selinux_file_context (dst, NULL) != 0) { -+ (void) close (ifd); - return -1; - } - #endif /* WITH_SELINUX */ -@@ -771,12 +772,16 @@ static int copy_file (const char *src, const char *dst, - && (errno != 0)) - #endif /* WITH_ATTR */ - ) { -+ if (ofd >= 0) { -+ (void) close (ofd); -+ } - (void) close (ifd); - return -1; - } - - while ((cnt = read (ifd, buf, sizeof buf)) > 0) { - if (write (ofd, buf, (size_t)cnt) != cnt) { -+ (void) close (ofd); - (void) close (ifd); - return -1; - } -@@ -786,6 +791,7 @@ static int copy_file (const char *src, const char *dst, - - #ifdef HAVE_FUTIMES - if (futimes (ofd, mt) != 0) { -+ (void) close (ofd); - return -1; - } - #endif /* HAVE_FUTIMES */ -diff --git a/libmisc/idmapping.c b/libmisc/idmapping.c -index b0ae488c..3324f671 100644 ---- a/libmisc/idmapping.c -+++ b/libmisc/idmapping.c -@@ -241,4 +241,5 @@ void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings, - exit(EXIT_FAILURE); - } - close(fd); -+ free(buf); - } -diff --git a/libmisc/list.c b/libmisc/list.c -index 2da734a7..d85d5f20 100644 ---- a/libmisc/list.c -+++ b/libmisc/list.c -@@ -241,6 +241,7 @@ bool is_on_list (char *const *list, const char *member) - - if ('\0' == *members) { - *array = (char *) 0; -+ free (members); - return array; - } - -diff --git a/libmisc/myname.c b/libmisc/myname.c -index 05efdad3..e1b7f702 100644 ---- a/libmisc/myname.c -+++ b/libmisc/myname.c -@@ -62,6 +62,9 @@ - if ((NULL != pw) && (pw->pw_uid == ruid)) { - return pw; - } -+ if (NULL != pw) { -+ pw_free (pw); -+ } - } - - return xgetpwuid (ruid); -diff --git a/libmisc/user_busy.c b/libmisc/user_busy.c -index 4b507fe2..3deebfc3 100644 ---- a/libmisc/user_busy.c -+++ b/libmisc/user_busy.c -@@ -269,6 +269,7 @@ static int user_busy_processes (const char *name, uid_t uid) - } - if (check_status (name, task_path+6, uid) != 0) { - (void) closedir (proc); -+ (void) closedir (task_dir); - #ifdef ENABLE_SUBIDS - sub_uid_close(); - #endif -diff --git a/src/newgrp.c b/src/newgrp.c -index 2aa28b87..2b9293b4 100644 ---- a/src/newgrp.c -+++ b/src/newgrp.c -@@ -162,8 +162,9 @@ static void check_perms (const struct group *grp, - */ - spwd = xgetspnam (pwd->pw_name); - if (NULL != spwd) { -- pwd->pw_passwd = spwd->sp_pwdp; -+ pwd->pw_passwd = xstrdup (spwd->sp_pwdp); - } -+ spw_free (spwd); - - if ((pwd->pw_passwd[0] == '\0') && (grp->gr_passwd[0] != '\0')) { - needspasswd = true; -diff --git a/src/passwd.c b/src/passwd.c -index 3d4206f4..9d7df331 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -553,6 +553,11 @@ static char *update_crypt_pw (char *cp) - - strcpy (newpw, "!"); - strcat (newpw, cp); -+#ifndef USE_PAM -+ if (do_update_pwd) { -+ free (cp); -+ } -+#endif /* USE_PAM */ - cp = newpw; - } - return cp; --- -2.31.1 - diff --git a/shadow-4.8.1-crypt_gensalt.patch b/shadow-4.8.1-crypt_gensalt.patch deleted file mode 100644 index 25198e6..0000000 --- a/shadow-4.8.1-crypt_gensalt.patch +++ /dev/null @@ -1,310 +0,0 @@ -From ea04eb301d08c0c58f1120f87d4ec184d3983ce5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Tue, 15 Jun 2021 14:23:42 +0200 -Subject: [PATCH] libmisc/salt.c: Use crypt_gensalt(), if available in - libcrypt. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Most Linux distributions, including Fedora and RHEL 8, are shipping -with libxcrypt >= 4.0. - -Since that version of libxcrypt the provided family of crypt_gensalt() -functions are able to use automatic entropy drawn from secure system -ressources, like arc4random(), getentropy() or getrandom(). - -Anyways, the settings generated by crypt_gensalt() are always -guaranteed to works with the crypt() function. - -Using crypt_gensalt() is also needed to make proper use of newer -hashing methods, like yescrypt, provided by libxcrypt. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 132 +++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 105 insertions(+), 27 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 13408a53..9fd34332 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -22,6 +22,13 @@ - #include "defines.h" - #include "getdef.h" - -+#if (defined CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY && \ -+ CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) -+#define USE_XCRYPT_GENSALT 1 -+#else -+#define USE_XCRYPT_GENSALT 0 -+#endif -+ - /* Add the salt prefix. */ - #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' - -@@ -77,21 +84,26 @@ - - /* local function prototypes */ - static long read_random_bytes (void); -+#if !USE_XCRYPT_GENSALT - static /*@observer@*/const char *gensalt (size_t salt_size); -+#endif /* !USE_XCRYPT_GENSALT */ - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - static long shadow_random (long min, long max); - #endif /* USE_SHA_CRYPT || USE_BCRYPT */ - #ifdef USE_SHA_CRYPT --static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); -+static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds); -+static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, unsigned long rounds); - #endif /* USE_SHA_CRYPT */ - #ifdef USE_BCRYPT --static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); -+static /*@observer@*/const unsigned long BCRYPT_get_salt_rounds (/*@null@*/int *prefered_rounds); -+static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, unsigned long rounds); - #endif /* USE_BCRYPT */ - #ifdef USE_YESCRYPT --static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost); -+static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost); -+static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost); - #endif /* USE_YESCRYPT */ - --#ifndef HAVE_L64A -+#if !USE_XCRYPT_GENSALT && !defined(HAVE_L64A) - static /*@observer@*/char *l64a (long value) - { - static char buf[8]; -@@ -125,7 +137,7 @@ static /*@observer@*/char *l64a (long value) - - return buf; - } --#endif /* !HAVE_L64A */ -+#endif /* !USE_XCRYPT_GENSALT && !defined(HAVE_L64A) */ - - /* Read sizeof (long) random bytes from /dev/urandom. */ - static long read_random_bytes (void) -@@ -199,14 +211,10 @@ static long shadow_random (long min, long max) - #endif /* USE_SHA_CRYPT || USE_BCRYPT */ - - #ifdef USE_SHA_CRYPT --/* -- * Fill a salt prefix specifying the rounds number for the SHA crypt methods -- * to a buffer. -- */ --static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) -+/* Return the the rounds number for the SHA crypt methods. */ -+static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds) - { - unsigned long rounds; -- const size_t buf_begin = strlen (buf); - - if (NULL == prefered_rounds) { - long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); -@@ -245,6 +253,17 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref - rounds = SHA_ROUNDS_MAX; - } - -+ return rounds; -+} -+ -+/* -+ * Fill a salt prefix specifying the rounds number for the SHA crypt methods -+ * to a buffer. -+ */ -+static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, unsigned long rounds) -+{ -+ const size_t buf_begin = strlen (buf); -+ - /* Nothing to do here if SHA_ROUNDS_DEFAULT is used. */ - if (rounds == SHA_ROUNDS_DEFAULT) { - return; -@@ -265,14 +284,10 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref - #endif /* USE_SHA_CRYPT */ - - #ifdef USE_BCRYPT --/* -- * Fill a salt prefix specifying the rounds number for the BCRYPT method -- * to a buffer. -- */ --static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) -+/* Return the the rounds number for the BCRYPT method. */ -+static /*@observer@*/const unsigned long BCRYPT_get_salt_rounds (/*@null@*/int *prefered_rounds) - { - unsigned long rounds; -- const size_t buf_begin = strlen (buf); - - if (NULL == prefered_rounds) { - long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1); -@@ -306,6 +321,11 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p - rounds = B_ROUNDS_MIN; - } - -+#if USE_XCRYPT_GENSALT -+ if (rounds > B_ROUNDS_MAX) { -+ rounds = B_ROUNDS_MAX; -+ } -+#else /* USE_XCRYPT_GENSALT */ - /* - * Use 19 as an upper bound for now, - * because musl doesn't allow rounds >= 20. -@@ -314,6 +334,18 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p - /* rounds = B_ROUNDS_MAX; */ - rounds = 19; - } -+#endif /* USE_XCRYPT_GENSALT */ -+ -+ return rounds; -+} -+ -+/* -+ * Fill a salt prefix specifying the rounds number for the BCRYPT method -+ * to a buffer. -+ */ -+static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, unsigned long rounds) -+{ -+ const size_t buf_begin = strlen (buf); - - /* - * Check if the result buffer is long enough. -@@ -330,14 +362,10 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p - #endif /* USE_BCRYPT */ - - #ifdef USE_YESCRYPT --/* -- * Fill a salt prefix specifying the cost for the YESCRYPT method -- * to a buffer. -- */ --static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost) -+/* Return the the cost number for the YESCRYPT method. */ -+static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost) - { - unsigned long cost; -- const size_t buf_begin = strlen (buf); - - if (NULL == prefered_cost) { - cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); -@@ -356,6 +384,17 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p - cost = Y_COST_MAX; - } - -+ return cost; -+} -+ -+/* -+ * Fill a salt prefix specifying the cost for the YESCRYPT method -+ * to a buffer. -+ */ -+static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, unsigned long cost) -+{ -+ const size_t buf_begin = strlen (buf); -+ - /* - * Check if the result buffer is long enough. - * We are going to write four bytes, -@@ -380,6 +419,7 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p - } - #endif /* USE_YESCRYPT */ - -+#if !USE_XCRYPT_GENSALT - static /*@observer@*/const char *gensalt (size_t salt_size) - { - static char salt[MAX_SALT_SIZE + 6]; -@@ -397,6 +437,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - - return salt; - } -+#endif /* !USE_XCRYPT_GENSALT */ - - /* - * Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB -@@ -420,6 +461,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - static char result[GENSALT_SETTING_SIZE]; - size_t salt_len = MAX_SALT_SIZE; - const char *method; -+ unsigned long rounds = 0; - - memset (result, '\0', GENSALT_SETTING_SIZE); - -@@ -435,27 +477,32 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - if (0 == strcmp (method, "MD5")) { - MAGNUM(result, '1'); - salt_len = MD5_CRYPT_SALT_SIZE; -+ rounds = 0; - #ifdef USE_BCRYPT - } else if (0 == strcmp (method, "BCRYPT")) { - BCRYPTMAGNUM(result); - salt_len = BCRYPT_SALT_SIZE; -- BCRYPT_salt_rounds_to_buf (result, (int *) arg); -+ rounds = BCRYPT_get_salt_rounds ((int *) arg); -+ BCRYPT_salt_rounds_to_buf (result, rounds); - #endif /* USE_BCRYPT */ - #ifdef USE_YESCRYPT - } else if (0 == strcmp (method, "YESCRYPT")) { - MAGNUM(result, 'y'); - salt_len = YESCRYPT_SALT_SIZE; -- YESCRYPT_salt_cost_to_buf (result, (int *) arg); -+ rounds = YESCRYPT_get_salt_cost ((int *) arg); -+ YESCRYPT_salt_cost_to_buf (result, rounds); - #endif /* USE_YESCRYPT */ - #ifdef USE_SHA_CRYPT - } else if (0 == strcmp (method, "SHA256")) { - MAGNUM(result, '5'); - salt_len = SHA_CRYPT_SALT_SIZE; -- SHA_salt_rounds_to_buf (result, (int *) arg); -+ rounds = SHA_get_salt_rounds ((int *) arg); -+ SHA_salt_rounds_to_buf (result, rounds); - } else if (0 == strcmp (method, "SHA512")) { - MAGNUM(result, '6'); - salt_len = SHA_CRYPT_SALT_SIZE; -- SHA_salt_rounds_to_buf (result, (int *) arg); -+ rounds = SHA_get_salt_rounds ((int *) arg); -+ SHA_salt_rounds_to_buf (result, rounds); - #endif /* USE_SHA_CRYPT */ - } else if (0 != strcmp (method, "DES")) { - fprintf (shadow_logfd, -@@ -463,9 +510,39 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - "Defaulting to DES.\n"), - method); - salt_len = MAX_SALT_SIZE; -+ rounds = 0; - memset (result, '\0', GENSALT_SETTING_SIZE); - } - -+#if USE_XCRYPT_GENSALT -+ /* -+ * Prepare DES setting for crypt_gensalt(), if result -+ * has not been filled with anything previously. -+ */ -+ if ('\0' == result[0]) { -+ /* Avoid -Wunused-but-set-variable. */ -+ salt_len = GENSALT_SETTING_SIZE - 1; -+ rounds = 0; -+ memset (result, '.', salt_len); -+ result[salt_len] = '\0'; -+ } -+ -+ char *retval = crypt_gensalt (result, rounds, NULL, 0); -+ -+ /* Should not happen, but... */ -+ if (NULL == retval) { -+ fprintf (shadow_logfd, -+ _("Unable to generate a salt from setting " -+ "\"%s\", check your settings in " -+ "ENCRYPT_METHOD and the corresponding " -+ "configuration for your selected hash " -+ "method.\n"), result); -+ -+ exit (1); -+ } -+ -+ return retval; -+#else /* USE_XCRYPT_GENSALT */ - /* Check if the result buffer is long enough. */ - assert (GENSALT_SETTING_SIZE > strlen (result) + salt_len); - -@@ -474,4 +551,5 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - GENSALT_SETTING_SIZE - strlen (result) - 1); - - return result; -+#endif /* USE_XCRYPT_GENSALT */ - } diff --git a/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch b/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch deleted file mode 100644 index a3aadd2..0000000 --- a/shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 8d987bc55ccb65a3ef3a541cc5e351cfcbef0c90 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Sat, 12 Jun 2021 19:05:07 +0200 -Subject: [PATCH] libmisc/salt.c: Use int pointer for YESCRYPT_salt_cost(). -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The corresponding functions for the other hash methods all take -a pointer to an integer value as the only paramater, so this -particular function should do so as well. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index c35c6797..1bfa015b 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -34,7 +34,7 @@ static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rou - #endif /* USE_BCRYPT */ - #ifdef USE_YESCRYPT - static /*@observer@*/const char *gensalt_yescrypt (void); --static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_rounds); -+static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost); - #endif /* USE_YESCRYPT */ - - #ifndef HAVE_L64A -@@ -277,7 +277,7 @@ static /*@observer@*/const char *gensalt_bcrypt (void) - /* - * Return a salt prefix specifying the cost for the YESCRYPT method. - */ --static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_cost) -+static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost) - { - static char cost_prefix[5]; - long cost; diff --git a/shadow-4.8.1-fix_bcrypt_prefix.patch b/shadow-4.8.1-fix_bcrypt_prefix.patch deleted file mode 100644 index e8ac3bc..0000000 --- a/shadow-4.8.1-fix_bcrypt_prefix.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 738d92a4bd99a2038aa5f97b2fc85daa7011e403 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Sat, 12 Jun 2021 13:54:14 +0200 -Subject: [PATCH] libmisc/salt.c: bcrypt should use $2b$ as prefix for setting. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This prefix is the recommended one for new bcrypt hashes -for a long time. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 1bfa015b..5dc521ef 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -90,12 +90,8 @@ static void seedRNG (void) - */ - #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' - #ifdef USE_BCRYPT --/* -- * Using the Prefix $2a$ to enable an anti-collision safety measure in musl libc. -- * Negatively affects a subset of passwords containing the '\xff' character, -- * which is not valid UTF-8 (so "unlikely to cause much annoyance"). -- */ --#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='a',(array)[4]='\0' -+/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ -+#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' - #endif /* USE_BCRYPT */ - - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) diff --git a/shadow-4.8.1-getentropy_random_bytes.patch b/shadow-4.8.1-getentropy_random_bytes.patch deleted file mode 100644 index c1affce..0000000 --- a/shadow-4.8.1-getentropy_random_bytes.patch +++ /dev/null @@ -1,123 +0,0 @@ -From c82ed0c15e0e9e47df0b4c22672b72e35f061a9d -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Sun, 4 Jul 2021 12:10:11 +0200 -Subject: [PATCH] libmisc/salt.c: Use secure system ressources to obtain random - bytes. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In a previous commit we introduced /dev/urandom as a source to obtain -random bytes from. This may not be available on all systems, or when -operating inside of a chroot. - -Almost all systems provide functions to obtain random bytes from -secure system ressources. Thus we should prefer to use these, and -fall back to /dev/urandom, if there is no such function present, as -a last resort. - -Signed-off-by: Björn Esser ---- - configure.ac | 17 +++++++++-------- - libmisc/salt.c | 42 ++++++++++++++++++++++++++++++++++++------ - 2 files changed, 45 insertions(+), 14 deletions(-) - -Index: shadow-4.8.1/configure.ac -=================================================================== ---- shadow-4.8.1.orig/configure.ac -+++ shadow-4.8.1/configure.ac -@@ -44,18 +44,19 @@ AC_HEADER_STDBOOL - - AC_CHECK_HEADERS(crypt.h errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ - utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \ -- utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \ -- locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \ -- attr/error_context.h) -+ utime.h ulimit.h sys/capability.h sys/random.h sys/resource.h \ -+ gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \ -+ attr/libattr.h attr/error_context.h) - - dnl shadow now uses the libc's shadow implementation - AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])]) - --AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ -- gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ -- lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ -- getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ -- ruserok dlopen) -+AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \ -+ gethostname getentropy getrandom getspnam gettimeofday getusershell \ -+ getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \ -+ setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \ -+ getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \ -+ dlopen) - AC_SYS_LARGEFILE - - dnl Checks for typedefs, structures, and compiler characteristics. -Index: shadow-4.8.1/libmisc/salt.c -=================================================================== ---- shadow-4.8.1.orig/libmisc/salt.c -+++ shadow-4.8.1/libmisc/salt.c -@@ -15,6 +15,9 @@ - #include - #include - #include -+#if HAVE_SYS_RANDOM_H -+#include -+#endif - #include "prototypes.h" - #include "defines.h" - #include "getdef.h" -@@ -128,19 +131,46 @@ static /*@observer@*/char *l64a (long va - static long read_random_bytes (void) - { - long randval = 0; -- FILE *f = fopen ("/dev/urandom", "r"); - -- if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) -- { -- fprintf (shadow_logfd, -- _("Unable to read from /dev/urandom.\n")); -+#ifdef HAVE_ARC4RANDOM_BUF -+ /* arc4random_buf, if it exists, can never fail. */ -+ arc4random_buf (&randval, sizeof (randval)); -+ goto end; -+ -+#elif defined(HAVE_GETENTROPY) -+ /* getentropy may exist but lack kernel support. */ -+ if (getentropy (&randval, sizeof (randval))) { -+ goto fail; -+ } -+ -+ goto end; -+ -+#elif defined(HAVE_GETRANDOM) -+ /* Likewise getrandom. */ -+ if ((size_t) getrandom (&randval, sizeof (randval), 0) != sizeof (randval)) { -+ goto fail; -+ } - -+ goto end; -+ -+#else -+ FILE *f = fopen ("/dev/urandom", "r"); -+ -+ if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) { - fclose(f); -- exit (1); -+ goto fail; - } - - fclose(f); -+ goto end; -+#endif -+ -+fail: -+ fprintf (shadow_logfd, -+ _("Unable to obtain random bytes.\n")); -+ exit (1); - -+end: - return randval; - } - diff --git a/shadow-4.8.1-libsubid_creation.patch b/shadow-4.8.1-libsubid_creation.patch deleted file mode 100644 index 072ed2e..0000000 --- a/shadow-4.8.1-libsubid_creation.patch +++ /dev/null @@ -1,1522 +0,0 @@ -From 0a7888b1fad613a052b988b01a71933b67296e68 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sat, 18 Apr 2020 18:03:54 -0500 -Subject: [PATCH] Create a new libsubid - -Closes #154 - -Currently this has three functions: one which returns the -list of subuid ranges for a user, one returning the subgids, -and one which frees the ranges lists. - -I might be mistaken about what -disable-man means; some of -the code suggests it means just don't re-generate them, but -not totally ignore them. But that doesn't seem to really work, -so let's just ignore man/ when -disable-man. - -Remove --disable-shared. I'm not sure why it was there, but it stems -from long, long ago, and I suspect it comes from some ancient -toolchain bug. - -Create a tests/run_some, a shorter version of run_all. I'll -slowly add tests to this as I verify they work, then I can -work on fixing the once which don't. - -Also, don't touch man/ if not -enable-man. - -Changelog: - Apr 22: change the subid list api as recomended by Dan Walsh. - Apr 23: implement get_subid_owner - Apr 24: implement range add/release - Apr 25: finish tests and rebase - May 10: make @owner const - -Signed-off-by: Serge Hallyn ---- - Makefile.am | 13 +- - configure.ac | 3 +- - lib/subordinateio.c | 204 +++++++++++++++- - lib/subordinateio.h | 7 + - libsubid/Makefile.am | 25 ++ - libsubid/api.c | 231 ++++++++++++++++++ - libsubid/api.h | 17 ++ - libsubid/subid.h | 17 ++ - src/Makefile.am | 60 +++++ - src/free_subid_range.c | 50 ++++ - src/get_subid_owners.c | 40 +++ - src/list_subid_ranges.c | 41 ++++ - src/new_subid_range.c | 57 +++++ - tests/libsubid/01_list_ranges/config.txt | 0 - .../libsubid/01_list_ranges/config/etc/subgid | 2 + - .../libsubid/01_list_ranges/config/etc/subuid | 3 + - .../libsubid/01_list_ranges/list_ranges.test | 38 +++ - tests/libsubid/02_get_subid_owners/config.txt | 0 - .../02_get_subid_owners/config/etc/passwd | 20 ++ - .../02_get_subid_owners/config/etc/subgid | 2 + - .../02_get_subid_owners/config/etc/subuid | 4 + - .../02_get_subid_owners/get_subid_owners.test | 52 ++++ - .../03_add_remove/add_remove_subids.test | 59 +++++ - tests/libsubid/03_add_remove/config.txt | 0 - .../libsubid/03_add_remove/config/etc/passwd | 20 ++ - .../libsubid/03_add_remove/config/etc/subgid | 2 + - .../libsubid/03_add_remove/config/etc/subuid | 1 + - tests/run_some | 136 +++++++++++ - 31 files changed, 1105 insertions(+), 17 deletions(-) - create mode 100644 libsubid/Makefile.am - create mode 100644 libsubid/api.c - create mode 100644 libsubid/api.h - create mode 100644 libsubid/subid.h - create mode 100644 src/free_subid_range.c - create mode 100644 src/get_subid_owners.c - create mode 100644 src/list_subid_ranges.c - create mode 100644 src/new_subid_range.c - create mode 100644 tests/libsubid/01_list_ranges/config.txt - create mode 100644 tests/libsubid/01_list_ranges/config/etc/subgid - create mode 100644 tests/libsubid/01_list_ranges/config/etc/subuid - create mode 100755 tests/libsubid/01_list_ranges/list_ranges.test - create mode 100644 tests/libsubid/02_get_subid_owners/config.txt - create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/passwd - create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/subgid - create mode 100644 tests/libsubid/02_get_subid_owners/config/etc/subuid - create mode 100755 tests/libsubid/02_get_subid_owners/get_subid_owners.test - create mode 100755 tests/libsubid/03_add_remove/add_remove_subids.test - create mode 100644 tests/libsubid/03_add_remove/config.txt - create mode 100644 tests/libsubid/03_add_remove/config/etc/passwd - create mode 100644 tests/libsubid/03_add_remove/config/etc/subgid - create mode 100644 tests/libsubid/03_add_remove/config/etc/subuid - create mode 100755 tests/run_some - -diff --git a/Makefile.am b/Makefile.am -index 8851f5d6..b6456cf9 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -2,5 +2,14 @@ - - EXTRA_DIST = NEWS README TODO shadow.spec.in - --SUBDIRS = po man libmisc lib src \ -- contrib doc etc -+SUBDIRS = libmisc lib -+ -+if ENABLE_SUBIDS -+SUBDIRS += libsubid -+endif -+ -+SUBDIRS += src po contrib doc etc -+ -+if ENABLE_REGENERATE_MAN -+SUBDIRS += man -+endif -diff --git a/configure.ac b/configure.ac -index b8bc2b7a..b766eff0 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -22,8 +22,8 @@ test "$prefix" = "/usr" && exec_prefix="" - - AC_GNU_SOURCE - --AM_DISABLE_SHARED - AM_ENABLE_STATIC -+AM_ENABLE_SHARED - - AM_MAINTAINER_MODE - -@@ -725,6 +725,7 @@ AC_CONFIG_FILES([ - man/zh_TW/Makefile - libmisc/Makefile - lib/Makefile -+ libsubid/Makefile - src/Makefile - contrib/Makefile - etc/Makefile -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 0d89a64e..67202c98 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -13,14 +13,7 @@ - #include "subordinateio.h" - #include - #include -- --struct subordinate_range { -- const char *owner; -- unsigned long start; -- unsigned long count; --}; -- --#define NFIELDS 3 -+#include - - /* - * subordinate_dup: create a duplicate range -@@ -78,7 +71,7 @@ static void *subordinate_parse (const char *line) - static char rangebuf[1024]; - int i; - char *cp; -- char *fields[NFIELDS]; -+ char *fields[SUBID_NFIELDS]; - - /* - * Copy the string to a temporary buffer so the substrings can -@@ -93,7 +86,7 @@ static void *subordinate_parse (const char *line) - * field. The fields are converted into NUL terminated strings. - */ - -- for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) { -+ for (cp = rangebuf, i = 0; (i < SUBID_NFIELDS) && (NULL != cp); i++) { - fields[i] = cp; - while (('\0' != *cp) && (':' != *cp)) { - cp++; -@@ -108,10 +101,10 @@ static void *subordinate_parse (const char *line) - } - - /* -- * There must be exactly NFIELDS colon separated fields or -+ * There must be exactly SUBID_NFIELDS colon separated fields or - * the entry is invalid. Also, fields must be non-blank. - */ -- if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0') -+ if (i != SUBID_NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0') - return NULL; - range.owner = fields[0]; - if (getulong (fields[1], &range.start) == 0) -@@ -314,6 +307,39 @@ static bool have_range(struct commonio_db *db, - return false; - } - -+static bool append_range(struct subordinate_range ***ranges, const struct subordinate_range *new, int n) -+{ -+ struct subordinate_range *tmp; -+ if (!*ranges) { -+ *ranges = malloc(2 * sizeof(struct subordinate_range **)); -+ if (!*ranges) -+ return false; -+ } else { -+ struct subordinate_range **new; -+ new = realloc(*ranges, (n + 2) * (sizeof(struct subordinate_range **))); -+ if (!new) -+ return false; -+ *ranges = new; -+ } -+ (*ranges)[n] = (*ranges)[n+1] = NULL; -+ tmp = subordinate_dup(new); -+ if (!tmp) -+ return false; -+ (*ranges)[n] = tmp; -+ return true; -+} -+ -+void free_subordinate_ranges(struct subordinate_range **ranges) -+{ -+ int i; -+ -+ if (!ranges) -+ return; -+ for (i = 0; ranges[i]; i++) -+ subordinate_free(ranges[i]); -+ free(ranges); -+} -+ - /* - * subordinate_range_cmp: compare uid ranges - * -@@ -692,6 +718,160 @@ gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) - start = find_free_range (&subordinate_gid_db, min, max, count); - return start == ULONG_MAX ? (gid_t) -1 : start; - } -+ -+/* -+ struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) -+ * -+ * @owner: username -+ * @id_type: UID or GUID -+ * -+ * Returns the subuid or subgid ranges which are owned by the specified -+ * user. Username may be a username or a string representation of a -+ * UID number. If id_type is UID, then subuids are returned, else -+ * subgids are returned. If there is an error, < 0 is returned. -+ * -+ * The caller must free the subordinate range list. -+ */ -+struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) -+{ -+ // TODO - need to handle owner being either uid or username -+ const struct subordinate_range *range; -+ struct subordinate_range **ranges = NULL; -+ struct commonio_db *db; -+ int size = 0; -+ -+ if (id_type == ID_TYPE_UID) -+ db = &subordinate_uid_db; -+ else -+ db = &subordinate_gid_db; -+ -+ commonio_rewind(db); -+ while ((range = commonio_next(db)) != NULL) { -+ if (0 == strcmp(range->owner, owner)) { -+ if (!append_range(&ranges, range, size++)) { -+ free_subordinate_ranges(ranges); -+ return NULL; -+ } -+ } -+ } -+ -+ return ranges; -+} -+ -+static bool all_digits(const char *str) -+{ -+ int i; -+ -+ for (i = 0; str[i] != '\0'; i++) -+ if (!isdigit(str[i])) -+ return false; -+ return true; -+} -+ -+static int append_uids(uid_t **uids, const char *owner, int n) -+{ -+ uid_t owner_uid; -+ uid_t *ret; -+ int i; -+ -+ if (all_digits(owner)) { -+ i = sscanf(owner, "%d", &owner_uid); -+ if (i != 1) { -+ // should not happen -+ free(*uids); -+ *uids = NULL; -+ return -1; -+ } -+ } else { -+ struct passwd *pwd = getpwnam(owner); -+ if (NULL == pwd) { -+ /* Username not defined in /etc/passwd, or error occured during lookup */ -+ free(*uids); -+ *uids = NULL; -+ return -1; -+ } -+ owner_uid = pwd->pw_uid; -+ } -+ -+ for (i = 0; i < n; i++) { -+ if (owner_uid == (*uids)[i]) -+ return n; -+ } -+ -+ ret = realloc(*uids, (n + 1) * sizeof(uid_t)); -+ if (!ret) { -+ free(*uids); -+ return -1; -+ } -+ ret[n] = owner_uid; -+ *uids = ret; -+ return n+1; -+} -+ -+int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) -+{ -+ const struct subordinate_range *range; -+ struct commonio_db *db; -+ int n = 0; -+ -+ *uids = NULL; -+ if (id_type == ID_TYPE_UID) -+ db = &subordinate_uid_db; -+ else -+ db = &subordinate_gid_db; -+ -+ commonio_rewind(db); -+ while ((range = commonio_next(db)) != NULL) { -+ if (id >= range->start && id < range->start + range-> count) { -+ n = append_uids(uids, range->owner, n); -+ if (n < 0) -+ break; -+ } -+ } -+ -+ return n; -+} -+ -+bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse) -+{ -+ struct commonio_db *db; -+ const struct subordinate_range *r; -+ -+ if (id_type == ID_TYPE_UID) -+ db = &subordinate_uid_db; -+ else -+ db = &subordinate_gid_db; -+ commonio_rewind(db); -+ if (reuse) { -+ while ((r = commonio_next(db)) != NULL) { -+ // TODO account for username vs uid_t -+ if (0 != strcmp(r->owner, range->owner)) -+ continue; -+ if (r->count >= range->count) { -+ range->count = r->count; -+ range->start = r->start; -+ return true; -+ } -+ } -+ } -+ -+ range->start = find_free_range(db, range->start, ULONG_MAX, range->count); -+ if (range->start == ULONG_MAX) -+ return false; -+ -+ return add_range(db, range->owner, range->start, range->count) == 1; -+} -+ -+bool release_subid_range(struct subordinate_range *range, enum subid_type id_type) -+{ -+ struct commonio_db *db; -+ if (id_type == ID_TYPE_UID) -+ db = &subordinate_uid_db; -+ else -+ db = &subordinate_gid_db; -+ return remove_range(db, range->owner, range->start, range->count) == 1; -+} -+ - #else /* !ENABLE_SUBIDS */ - extern int errno; /* warning: ANSI C forbids an empty source file */ - #endif /* !ENABLE_SUBIDS */ -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index a21d72b8..13a21341 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -11,6 +11,8 @@ - - #include - -+#include "../libsubid/subid.h" -+ - extern int sub_uid_close(void); - extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); - extern bool sub_uid_file_present (void); -@@ -23,6 +25,11 @@ extern int sub_uid_unlock (void); - extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); - extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); - extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); -+extern struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type); -+extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); -+extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); -+extern int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type); -+extern void free_subordinate_ranges(struct subordinate_range **ranges); - - extern int sub_gid_close(void); - extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); -diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am -new file mode 100644 -index 00000000..bdbc52c3 ---- /dev/null -+++ b/libsubid/Makefile.am -@@ -0,0 +1,25 @@ -+lib_LTLIBRARIES = libsubid.la -+libsubid_la_LDFLAGS = -Wl,-soname,libsubid.so.@LIBSUBID_ABI@ \ -+ -shared -version-info @LIBSUBID_ABI_MAJOR@ -+libsubid_la_SOURCES = api.c -+ -+MISCLIBS = \ -+ $(LIBAUDIT) \ -+ $(LIBSELINUX) \ -+ $(LIBSEMANAGE) \ -+ $(LIBCRYPT_NOPAM) \ -+ $(LIBSKEY) \ -+ $(LIBMD) \ -+ $(LIBECONF) \ -+ $(LIBCRYPT) \ -+ $(LIBTCB) -+ -+libsubid_la_LIBADD = \ -+ $(top_srcdir)/lib/libshadow.la \ -+ $(top_srcdir)/libmisc/libmisc.a \ -+ $(MISCLIBS) -+ -+AM_CPPFLAGS = \ -+ -I${top_srcdir}/lib \ -+ -I${top_srcdir}/libmisc \ -+ -DLOCALEDIR=\"$(datadir)/locale\" -diff --git a/libsubid/api.c b/libsubid/api.c -new file mode 100644 -index 00000000..91d73bed ---- /dev/null -+++ b/libsubid/api.c -@@ -0,0 +1,231 @@ -+/* -+ * Copyright (c) 2020 Serge Hallyn -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the copyright holders or contributors may not be used to -+ * endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "subordinateio.h" -+#include "idmapping.h" -+#include "api.h" -+ -+static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type) -+{ -+ struct subordinate_range **ranges = NULL; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_open(O_RDONLY)) { -+ return NULL; -+ } -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_open(O_RDONLY)) { -+ return NULL; -+ } -+ break; -+ default: -+ return NULL; -+ } -+ -+ ranges = list_owner_ranges(owner, id_type); -+ -+ if (id_type == ID_TYPE_UID) -+ sub_uid_close(); -+ else -+ sub_gid_close(); -+ -+ return ranges; -+} -+ -+struct subordinate_range **get_subuid_ranges(const char *owner) -+{ -+ return get_subid_ranges(owner, ID_TYPE_UID); -+} -+ -+struct subordinate_range **get_subgid_ranges(const char *owner) -+{ -+ return get_subid_ranges(owner, ID_TYPE_GID); -+} -+ -+void subid_free_ranges(struct subordinate_range **ranges) -+{ -+ return free_subordinate_ranges(ranges); -+} -+ -+int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type) -+{ -+ int ret = -1; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_open(O_RDONLY)) { -+ return -1; -+ } -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_open(O_RDONLY)) { -+ return -1; -+ } -+ break; -+ default: -+ return -1; -+ } -+ -+ ret = find_subid_owners(id, owner, id_type); -+ -+ if (id_type == ID_TYPE_UID) -+ sub_uid_close(); -+ else -+ sub_gid_close(); -+ -+ return ret; -+} -+ -+int get_subuid_owners(uid_t uid, uid_t **owner) -+{ -+ return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID); -+} -+ -+int get_subgid_owners(gid_t gid, uid_t **owner) -+{ -+ return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID); -+} -+ -+bool grant_subid_range(struct subordinate_range *range, bool reuse, -+ enum subid_type id_type) -+{ -+ bool ret; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_lock()) { -+ printf("Failed loging subuids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_uid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subuids (errno %d)\n", errno); -+ sub_uid_unlock(); -+ return false; -+ } -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_lock()) { -+ printf("Failed loging subgids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_gid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subgids (errno %d)\n", errno); -+ sub_gid_unlock(); -+ return false; -+ } -+ break; -+ default: -+ return false; -+ } -+ -+ ret = new_subid_range(range, id_type, reuse); -+ -+ if (id_type == ID_TYPE_UID) { -+ sub_uid_close(); -+ sub_uid_unlock(); -+ } else { -+ sub_gid_close(); -+ sub_gid_unlock(); -+ } -+ -+ return ret; -+} -+ -+bool grant_subuid_range(struct subordinate_range *range, bool reuse) -+{ -+ return grant_subid_range(range, reuse, ID_TYPE_UID); -+} -+ -+bool grant_subgid_range(struct subordinate_range *range, bool reuse) -+{ -+ return grant_subid_range(range, reuse, ID_TYPE_GID); -+} -+ -+bool free_subid_range(struct subordinate_range *range, enum subid_type id_type) -+{ -+ bool ret; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_lock()) { -+ printf("Failed loging subuids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_uid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subuids (errno %d)\n", errno); -+ sub_uid_unlock(); -+ return false; -+ } -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_lock()) { -+ printf("Failed loging subgids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_gid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subgids (errno %d)\n", errno); -+ sub_gid_unlock(); -+ return false; -+ } -+ break; -+ default: -+ return false; -+ } -+ -+ ret = release_subid_range(range, id_type); -+ -+ if (id_type == ID_TYPE_UID) { -+ sub_uid_close(); -+ sub_uid_unlock(); -+ } else { -+ sub_gid_close(); -+ sub_gid_unlock(); -+ } -+ -+ return ret; -+} -+ -+bool free_subuid_range(struct subordinate_range *range) -+{ -+ return free_subid_range(range, ID_TYPE_UID); -+} -+ -+bool free_subgid_range(struct subordinate_range *range) -+{ -+ return free_subid_range(range, ID_TYPE_GID); -+} -diff --git a/libsubid/api.h b/libsubid/api.h -new file mode 100644 -index 00000000..f65e3ec9 ---- /dev/null -+++ b/libsubid/api.h -@@ -0,0 +1,17 @@ -+#include "subid.h" -+#include -+ -+struct subordinate_range **get_subuid_ranges(const char *owner); -+struct subordinate_range **get_subgid_ranges(const char *owner); -+void subid_free_ranges(struct subordinate_range **ranges); -+ -+int get_subuid_owners(uid_t uid, uid_t **owner); -+int get_subgid_owners(uid_t uid, uid_t **owner); -+ -+/* range should be pre-allocated with owner and count filled in, start is -+ * ignored, can be 0 */ -+bool grant_subuid_range(struct subordinate_range *range, bool reuse); -+bool grant_subgid_range(struct subordinate_range *range, bool reuse); -+ -+bool free_subuid_range(struct subordinate_range *range); -+bool free_subgid_range(struct subordinate_range *range); -diff --git a/libsubid/subid.h b/libsubid/subid.h -new file mode 100644 -index 00000000..ba9a2f6f ---- /dev/null -+++ b/libsubid/subid.h -@@ -0,0 +1,17 @@ -+#include -+ -+#ifndef SUBID_RANGE_DEFINED -+#define SUBID_RANGE_DEFINED 1 -+struct subordinate_range { -+ const char *owner; -+ unsigned long start; -+ unsigned long count; -+}; -+ -+enum subid_type { -+ ID_TYPE_UID = 1, -+ ID_TYPE_GID = 2 -+}; -+ -+#define SUBID_NFIELDS 3 -+#endif -diff --git a/src/Makefile.am b/src/Makefile.am -index f175928a..8499ce08 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -156,4 +156,64 @@ if FCAPS - setcap cap_setuid+ep $(DESTDIR)$(ubindir)/newuidmap - setcap cap_setgid+ep $(DESTDIR)$(ubindir)/newgidmap - endif -+ -+noinst_PROGRAMS += list_subid_ranges \ -+ get_subid_owners \ -+ new_subid_range \ -+ free_subid_range -+ -+MISCLIBS = \ -+ $(LIBAUDIT) \ -+ $(LIBSELINUX) \ -+ $(LIBSEMANAGE) \ -+ $(LIBCRYPT_NOPAM) \ -+ $(LIBSKEY) \ -+ $(LIBMD) \ -+ $(LIBECONF) \ -+ $(LIBCRYPT) \ -+ $(LIBTCB) -+ -+list_subid_ranges_LDADD = \ -+ $(top_builddir)/lib/libshadow.la \ -+ $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libsubid/libsubid.la \ -+ $(MISCLIBS) -+ -+list_subid_ranges_CPPFLAGS = \ -+ -I$(top_srcdir)/lib \ -+ -I$(top_srcdir)/libmisc \ -+ -I$(top_srcdir)/libsubid -+ -+get_subid_owners_LDADD = \ -+ $(top_builddir)/lib/libshadow.la \ -+ $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libsubid/libsubid.la \ -+ $(MISCLIBS) -+ -+get_subid_owners_CPPFLAGS = \ -+ -I$(top_srcdir)/lib \ -+ -I$(top_srcdir)/libmisc \ -+ -I$(top_srcdir)/libsubid -+ -+new_subid_range_CPPFLAGS = \ -+ -I$(top_srcdir)/lib \ -+ -I$(top_srcdir)/libmisc \ -+ -I$(top_srcdir)/libsubid -+ -+new_subid_range_LDADD = \ -+ $(top_builddir)/lib/libshadow.la \ -+ $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libsubid/libsubid.la \ -+ $(MISCLIBS) -+ -+free_subid_range_CPPFLAGS = \ -+ -I$(top_srcdir)/lib \ -+ -I$(top_srcdir)/libmisc \ -+ -I$(top_srcdir)/libsubid -+ -+free_subid_range_LDADD = \ -+ $(top_builddir)/lib/libshadow.la \ -+ $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libsubid/libsubid.la \ -+ $(MISCLIBS) - endif -diff --git a/src/free_subid_range.c b/src/free_subid_range.c -new file mode 100644 -index 00000000..36858875 ---- /dev/null -+++ b/src/free_subid_range.c -@@ -0,0 +1,50 @@ -+#include -+#include -+#include "api.h" -+#include "stdlib.h" -+#include "prototypes.h" -+ -+/* Test program for the subid freeing routine */ -+ -+const char *Prog; -+ -+void usage(void) -+{ -+ fprintf(stderr, "Usage: %s [-g] user start count\n", Prog); -+ fprintf(stderr, " Release a user's subuid (or with -g, subgid) range\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int c; -+ bool ok; -+ struct subordinate_range range; -+ bool group = false; // get subuids by default -+ -+ Prog = Basename (argv[0]); -+ while ((c = getopt(argc, argv, "g")) != EOF) { -+ switch(c) { -+ case 'g': group = true; break; -+ default: usage(); -+ } -+ } -+ argv = &argv[optind]; -+ argc = argc - optind; -+ if (argc < 3) -+ usage(); -+ range.owner = argv[0]; -+ range.start = atoi(argv[1]); -+ range.count = atoi(argv[2]); -+ if (group) -+ ok = free_subgid_range(&range); -+ else -+ ok = free_subuid_range(&range); -+ -+ if (!ok) { -+ fprintf(stderr, "Failed freeing id range\n"); -+ exit(EXIT_FAILURE); -+ } -+ -+ return 0; -+} -diff --git a/src/get_subid_owners.c b/src/get_subid_owners.c -new file mode 100644 -index 00000000..a4385540 ---- /dev/null -+++ b/src/get_subid_owners.c -@@ -0,0 +1,40 @@ -+#include -+#include "api.h" -+#include "stdlib.h" -+#include "prototypes.h" -+ -+const char *Prog; -+ -+void usage(void) -+{ -+ fprintf(stderr, "Usage: [-g] %s subuid\n", Prog); -+ fprintf(stderr, " list uids who own the given subuid\n"); -+ fprintf(stderr, " pass -g to query a subgid\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int i, n; -+ uid_t *uids; -+ -+ Prog = Basename (argv[0]); -+ if (argc < 2) { -+ usage(); -+ } -+ if (argc == 3 && strcmp(argv[1], "-g") == 0) -+ n = get_subgid_owners(atoi(argv[2]), &uids); -+ else if (argc == 2 && strcmp(argv[1], "-h") == 0) -+ usage(); -+ else -+ n = get_subuid_owners(atoi(argv[1]), &uids); -+ if (n < 0) { -+ fprintf(stderr, "No owners found\n"); -+ exit(1); -+ } -+ for (i = 0; i < n; i++) { -+ printf("%d\n", uids[i]); -+ } -+ free(uids); -+ return 0; -+} -diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c -new file mode 100644 -index 00000000..cdba610e ---- /dev/null -+++ b/src/list_subid_ranges.c -@@ -0,0 +1,41 @@ -+#include -+#include "api.h" -+#include "stdlib.h" -+#include "prototypes.h" -+ -+const char *Prog; -+ -+void usage(void) -+{ -+ fprintf(stderr, "Usage: %s [-g] user\n", Prog); -+ fprintf(stderr, " list subuid ranges for user\n"); -+ fprintf(stderr, " pass -g to list subgid ranges\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int i; -+ struct subordinate_range **ranges; -+ -+ Prog = Basename (argv[0]); -+ if (argc < 2) { -+ usage(); -+ } -+ if (argc == 3 && strcmp(argv[1], "-g") == 0) -+ ranges = get_subgid_ranges(argv[2]); -+ else if (argc == 2 && strcmp(argv[1], "-h") == 0) -+ usage(); -+ else -+ ranges = get_subuid_ranges(argv[1]); -+ if (!ranges) { -+ fprintf(stderr, "Error fetching ranges\n"); -+ exit(1); -+ } -+ for (i = 0; ranges[i]; i++) { -+ printf("%d: %s %lu %lu\n", i, ranges[i]->owner, -+ ranges[i]->start, ranges[i]->count); -+ } -+ subid_free_ranges(ranges); -+ return 0; -+} -diff --git a/src/new_subid_range.c b/src/new_subid_range.c -new file mode 100644 -index 00000000..6d7b033b ---- /dev/null -+++ b/src/new_subid_range.c -@@ -0,0 +1,57 @@ -+#include -+#include -+#include "api.h" -+#include "stdlib.h" -+#include "prototypes.h" -+ -+/* Test program for the subid creation routine */ -+ -+const char *Prog; -+ -+void usage(void) -+{ -+ fprintf(stderr, "Usage: %s [-g] [-n] user count\n", Prog); -+ fprintf(stderr, " Find a subuid (or with -g, subgid) range for user\n"); -+ fprintf(stderr, " If -n is given, a new range will be created even if one exists\n"); -+ fprintf(stderr, " count defaults to 65536\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int c; -+ struct subordinate_range range; -+ bool makenew = false; // reuse existing by default -+ bool group = false; // get subuids by default -+ bool ok; -+ -+ Prog = Basename (argv[0]); -+ while ((c = getopt(argc, argv, "gn")) != EOF) { -+ switch(c) { -+ case 'n': makenew = true; break; -+ case 'g': group = true; break; -+ default: usage(); -+ } -+ } -+ argv = &argv[optind]; -+ argc = argc - optind; -+ if (argc == 0) -+ usage(); -+ range.owner = argv[0]; -+ range.start = 0; -+ range.count = 65536; -+ if (argc > 1) -+ range.count = atoi(argv[1]); -+ if (group) -+ ok = grant_subgid_range(&range, !makenew); -+ else -+ ok = grant_subuid_range(&range, !makenew); -+ -+ if (!ok) { -+ fprintf(stderr, "Failed creating new id range\n"); -+ exit(EXIT_FAILURE); -+ } -+ printf("Subuid range %lu:%lu\n", range.start, range.count); -+ -+ return 0; -+} -diff --git a/tests/libsubid/01_list_ranges/config.txt b/tests/libsubid/01_list_ranges/config.txt -new file mode 100644 -index 00000000..e69de29b -diff --git a/tests/libsubid/01_list_ranges/config/etc/subgid b/tests/libsubid/01_list_ranges/config/etc/subgid -new file mode 100644 -index 00000000..b9495cfc ---- /dev/null -+++ b/tests/libsubid/01_list_ranges/config/etc/subgid -@@ -0,0 +1,2 @@ -+foo:200000:10000 -+root:500000:1000 -diff --git a/tests/libsubid/01_list_ranges/config/etc/subuid b/tests/libsubid/01_list_ranges/config/etc/subuid -new file mode 100644 -index 00000000..e5c537be ---- /dev/null -+++ b/tests/libsubid/01_list_ranges/config/etc/subuid -@@ -0,0 +1,3 @@ -+foo:300000:10000 -+foo:400000:10000 -+root:500000:1000 -diff --git a/tests/libsubid/01_list_ranges/list_ranges.test b/tests/libsubid/01_list_ranges/list_ranges.test -new file mode 100755 -index 00000000..b131303b ---- /dev/null -+++ b/tests/libsubid/01_list_ranges/list_ranges.test -@@ -0,0 +1,38 @@ -+#!/bin/sh -+ -+set -e -+ -+cd $(dirname $0) -+ -+. ../../common/config.sh -+. ../../common/log.sh -+ -+log_start "$0" "list_ranges shows subid ranges" -+ -+save_config -+ -+# restore the files on exit -+trap 'log_status "$0" "FAILURE"; restore_config' 0 -+ -+change_config -+ -+echo -n "list foo's ranges..." -+${build_path}/src/list_subid_ranges foo > /tmp/subuidlistout -+${build_path}/src/list_subid_ranges -g foo > /tmp/subgidlistout -+echo "OK" -+ -+echo -n "Check the subuid ranges..." -+[ $(wc -l /tmp/subuidlistout | awk '{ print $1 }') -eq 2 ] -+grep "0: foo 300000 10000" /tmp/subuidlistout -+grep "1: foo 400000 10000" /tmp/subuidlistout -+echo "OK" -+ -+echo -n "Check the subgid ranges..." -+[ $(wc -l /tmp/subgidlistout | awk '{ print $1 }') -eq 1 ] -+grep "0: foo 200000 10000" /tmp/subgidlistout -+echo "OK" -+ -+log_status "$0" "SUCCESS" -+restore_config -+trap '' 0 -+ -diff --git a/tests/libsubid/02_get_subid_owners/config.txt b/tests/libsubid/02_get_subid_owners/config.txt -new file mode 100644 -index 00000000..e69de29b -diff --git a/tests/libsubid/02_get_subid_owners/config/etc/passwd b/tests/libsubid/02_get_subid_owners/config/etc/passwd -new file mode 100644 -index 00000000..bf52df00 ---- /dev/null -+++ b/tests/libsubid/02_get_subid_owners/config/etc/passwd -@@ -0,0 +1,20 @@ -+root:x:0:0:root:/root:/bin/bash -+daemon:x:1:1:daemon:/usr/sbin:/bin/sh -+bin:x:2:2:bin:/bin:/bin/sh -+sys:x:3:3:sys:/dev:/bin/sh -+sync:x:4:65534:sync:/bin:/bin/sync -+games:x:5:60:games:/usr/games:/bin/sh -+man:x:6:12:man:/var/cache/man:/bin/sh -+lp:x:7:7:lp:/var/spool/lpd:/bin/sh -+mail:x:8:8:mail:/var/mail:/bin/sh -+news:x:9:9:news:/var/spool/news:/bin/sh -+uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh -+proxy:x:13:13:proxy:/bin:/bin/sh -+www-data:x:33:33:www-data:/var/www:/bin/sh -+backup:x:34:34:backup:/var/backups:/bin/sh -+list:x:38:38:Mailing List Manager:/var/list:/bin/sh -+irc:x:39:39:ircd:/var/run/ircd:/bin/sh -+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh -+nobody:x:65534:65534:nobody:/nonexistent:/bin/sh -+Debian-exim:x:102:102::/var/spool/exim4:/bin/false -+foo:x:1000:1000::/home/foo:/bin/false -diff --git a/tests/libsubid/02_get_subid_owners/config/etc/subgid b/tests/libsubid/02_get_subid_owners/config/etc/subgid -new file mode 100644 -index 00000000..b9495cfc ---- /dev/null -+++ b/tests/libsubid/02_get_subid_owners/config/etc/subgid -@@ -0,0 +1,2 @@ -+foo:200000:10000 -+root:500000:1000 -diff --git a/tests/libsubid/02_get_subid_owners/config/etc/subuid b/tests/libsubid/02_get_subid_owners/config/etc/subuid -new file mode 100644 -index 00000000..dd11875a ---- /dev/null -+++ b/tests/libsubid/02_get_subid_owners/config/etc/subuid -@@ -0,0 +1,4 @@ -+foo:300000:10000 -+foo:400000:10000 -+foo:500000:10000 -+root:500000:1000 -diff --git a/tests/libsubid/02_get_subid_owners/get_subid_owners.test b/tests/libsubid/02_get_subid_owners/get_subid_owners.test -new file mode 100755 -index 00000000..145477cb ---- /dev/null -+++ b/tests/libsubid/02_get_subid_owners/get_subid_owners.test -@@ -0,0 +1,52 @@ -+#!/bin/sh -+ -+set -e -+ -+cd $(dirname $0) -+ -+. ../../common/config.sh -+. ../../common/log.sh -+ -+log_start "$0" "get subid owners" -+ -+save_config -+ -+# restore the files on exit -+trap 'log_status "$0" "FAILURE"; restore_config' 0 -+ -+change_config -+ -+echo -n "Noone owns 0 as a subid..." -+[ -z "$(${build_path}/src/get_subid_owners 0)" ] -+echo "OK" -+ -+echo -n "foo owns subuid 300000..." -+[ "$(${build_path}/src/get_subid_owners 300000)" = "1000" ] -+echo "OK" -+ -+echo -n "foo owns subgid 200000..." -+[ "$(${build_path}/src/get_subid_owners -g 200000)" = "1000" ] -+echo "OK" -+ -+echo -n "Noone owns subuid 200000..." -+[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ] -+echo "OK" -+ -+echo -n "Noone owns subgid 300000..." -+[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ] -+echo "OK" -+ -+echo -n "Both foo and root own subuid 500000..." -+cat > /tmp/expected << EOF -+1000 -+0 -+EOF -+${build_path}/src/get_subid_owners 500000 > /tmp/actual -+diff /tmp/expected /tmp/actual -+ -+echo "OK" -+ -+log_status "$0" "SUCCESS" -+restore_config -+trap '' 0 -+ -diff --git a/tests/libsubid/03_add_remove/add_remove_subids.test b/tests/libsubid/03_add_remove/add_remove_subids.test -new file mode 100755 -index 00000000..a24a9752 ---- /dev/null -+++ b/tests/libsubid/03_add_remove/add_remove_subids.test -@@ -0,0 +1,59 @@ -+#!/bin/sh -+ -+set -e -+ -+cd $(dirname $0) -+ -+. ../../common/config.sh -+. ../../common/log.sh -+ -+log_start "$0" "add and remove subid ranges" -+ -+save_config -+ -+# restore the files on exit -+trap 'log_status "$0" "FAILURE"; restore_config' 0 -+ -+change_config -+ -+echo -n "Existing ranges returned when possible..." -+res=$(${build_path}/src/new_subid_range foo 500) -+echo "debug" -+echo "res is $res" -+echo "wanted Subuid range 300000:10000" -+echo "end debug" -+[ "$res" = "Subuid range 300000:10000" ] -+[ $(grep -c foo /etc/subuid) -eq 1 ] -+echo "OK" -+ -+echo -n "New range returned if requested..." -+res=$(${build_path}/src/new_subid_range foo 500 -n) -+[ "$res" = "Subuid range 310000:500" ] -+[ $(grep -c foo /etc/subuid) -eq 2 ] -+echo "OK" -+ -+echo -n "Free works..." -+res=$(${build_path}/src/free_subid_range foo 310000 500) -+[ $(grep -c foo /etc/subuid) -eq 1 ] -+echo "OK" -+ -+echo -n "Subgids work too..." -+res=$(${build_path}/src/new_subid_range -g foo 100000) -+echo "DEBUG: res is ${res}" -+[ "$res" = "Subuid range 501000:100000" ] -+echo "DEBUG: subgid is:" -+cat /etc/subgid -+[ $(grep -c foo /etc/subgid) -eq 2 ] -+ -+echo -n "Subgid free works..." -+res=$(${build_path}/src/free_subid_range -g foo 501000 100000) -+echo "DEBUG: res is ${res}" -+echo "DEBUG: subgid is:" -+cat /etc/subgid -+[ $(grep -c foo /etc/subgid) -eq 1 ] -+echo "OK" -+ -+log_status "$0" "SUCCESS" -+restore_config -+trap '' 0 -+ -diff --git a/tests/libsubid/03_add_remove/config.txt b/tests/libsubid/03_add_remove/config.txt -new file mode 100644 -index 00000000..e69de29b -diff --git a/tests/libsubid/03_add_remove/config/etc/passwd b/tests/libsubid/03_add_remove/config/etc/passwd -new file mode 100644 -index 00000000..bf52df00 ---- /dev/null -+++ b/tests/libsubid/03_add_remove/config/etc/passwd -@@ -0,0 +1,20 @@ -+root:x:0:0:root:/root:/bin/bash -+daemon:x:1:1:daemon:/usr/sbin:/bin/sh -+bin:x:2:2:bin:/bin:/bin/sh -+sys:x:3:3:sys:/dev:/bin/sh -+sync:x:4:65534:sync:/bin:/bin/sync -+games:x:5:60:games:/usr/games:/bin/sh -+man:x:6:12:man:/var/cache/man:/bin/sh -+lp:x:7:7:lp:/var/spool/lpd:/bin/sh -+mail:x:8:8:mail:/var/mail:/bin/sh -+news:x:9:9:news:/var/spool/news:/bin/sh -+uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh -+proxy:x:13:13:proxy:/bin:/bin/sh -+www-data:x:33:33:www-data:/var/www:/bin/sh -+backup:x:34:34:backup:/var/backups:/bin/sh -+list:x:38:38:Mailing List Manager:/var/list:/bin/sh -+irc:x:39:39:ircd:/var/run/ircd:/bin/sh -+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh -+nobody:x:65534:65534:nobody:/nonexistent:/bin/sh -+Debian-exim:x:102:102::/var/spool/exim4:/bin/false -+foo:x:1000:1000::/home/foo:/bin/false -diff --git a/tests/libsubid/03_add_remove/config/etc/subgid b/tests/libsubid/03_add_remove/config/etc/subgid -new file mode 100644 -index 00000000..b9495cfc ---- /dev/null -+++ b/tests/libsubid/03_add_remove/config/etc/subgid -@@ -0,0 +1,2 @@ -+foo:200000:10000 -+root:500000:1000 -diff --git a/tests/libsubid/03_add_remove/config/etc/subuid b/tests/libsubid/03_add_remove/config/etc/subuid -new file mode 100644 -index 00000000..cf80c2f7 ---- /dev/null -+++ b/tests/libsubid/03_add_remove/config/etc/subuid -@@ -0,0 +1 @@ -+foo:300000:10000 -diff --git a/tests/run_some b/tests/run_some -new file mode 100755 -index 00000000..2d085d59 ---- /dev/null -+++ b/tests/run_some -@@ -0,0 +1,136 @@ -+#!/bin/sh -+ -+set -e -+ -+export LC_ALL=C -+unset LANG -+unset LANGUAGE -+. common/config.sh -+ -+USE_PAM="yes" -+FAILURE_TESTS="yes" -+ -+succeeded=0 -+failed=0 -+failed_tests="" -+ -+run_test() -+{ -+ [ -f RUN_TEST.STOP ] && exit 1 -+ -+ if $1 > $1.log -+ then -+ succeeded=$((succeeded+1)) -+ echo -n "+" -+ else -+ failed=$((failed+1)) -+ failed_tests="$failed_tests $1" -+ echo -n "-" -+ fi -+ cat $1.log >> testsuite.log -+ [ -f /etc/passwd.lock ] && echo $1 /etc/passwd.lock || true -+ [ -f /etc/group.lock ] && echo $1 /etc/group.lock || true -+ [ -f /etc/shadow.lock ] && echo $1 /etc/shadow.lock || true -+ [ -f /etc/gshadow.lock ] && echo $1 /etc/gshadow.lock || true -+ if [ "$(stat -c"%G" /etc/shadow)" != "shadow" ] -+ then -+ echo $1 -+ ls -l /etc/shadow -+ chgrp shadow /etc/shadow -+ fi -+ if [ -d /nonexistent ] -+ then -+ echo $1 /nonexistent -+ rmdir /nonexistent -+ fi -+} -+ -+echo "+: test passed" -+echo "-: test failed" -+ -+# Empty the complete log. -+> testsuite.log -+ -+find ${build_path} -name "*.gcda" -delete -+run_test ./su/01/su_root.test -+run_test ./su/01/su_user.test -+find ${build_path} -name "*.gcda" -exec chmod a+rw {} \; -+run_test ./su/02/env_FOO-options_--login -+run_test ./su/02/env_FOO-options_--login_bash -+run_test ./su/02/env_FOO-options_--preserve-environment -+run_test ./su/02/env_FOO-options_--preserve-environment_bash -+run_test ./su/02/env_FOO-options_- -+run_test ./su/02/env_FOO-options_-_bash -+run_test ./su/02/env_FOO-options_-l-m -+run_test ./su/02/env_FOO-options_-l-m_bash -+run_test ./su/02/env_FOO-options_-l -+run_test ./su/02/env_FOO-options_-l_bash -+run_test ./su/02/env_FOO-options_-m_bash -+run_test ./su/02/env_FOO-options_-m -+run_test ./su/02/env_FOO-options_-p -+run_test ./su/02/env_FOO-options_-p_bash -+run_test ./su/02/env_FOO-options__bash -+run_test ./su/02/env_FOO-options_ -+run_test ./su/02/env_FOO-options_-p- -+run_test ./su/02/env_FOO-options_-p-_bash -+run_test ./su/02/env_special-options_-l-p -+run_test ./su/02/env_special-options_-l -+run_test ./su/02/env_special-options_-l-p_bash -+run_test ./su/02/env_special-options_-l_bash -+run_test ./su/02/env_special-options_-p -+run_test ./su/02/env_special-options_-p_bash -+run_test ./su/02/env_special-options_ -+run_test ./su/02/env_special-options__bash -+run_test ./su/02/env_special_root-options_-l-p -+run_test ./su/02/env_special_root-options_-l-p_bash -+run_test ./su/02/env_special_root-options_-l -+run_test ./su/02/env_special_root-options_-l_bash -+run_test ./su/02/env_special_root-options_-p -+run_test ./su/02/env_special_root-options_-p_bash -+run_test ./su/02/env_special_root-options_ -+run_test ./su/02/env_special_root-options__bash -+run_test ./su/03/su_run_command01.test -+run_test ./su/03/su_run_command02.test -+run_test ./su/03/su_run_command03.test -+run_test ./su/03/su_run_command04.test -+run_test ./su/03/su_run_command05.test -+run_test ./su/03/su_run_command06.test -+run_test ./su/03/su_run_command07.test -+run_test ./su/03/su_run_command08.test -+run_test ./su/03/su_run_command09.test -+run_test ./su/03/su_run_command10.test -+run_test ./su/03/su_run_command11.test -+run_test ./su/03/su_run_command12.test -+run_test ./su/03/su_run_command13.test -+run_test ./su/03/su_run_command14.test -+run_test ./su/03/su_run_command15.test -+run_test ./su/03/su_run_command16.test -+run_test ./su/03/su_run_command17.test -+run_test ./su/04/su_wrong_user.test -+run_test ./su/04/su_user_wrong_passwd.test -+run_test ./su/04/su_user_wrong_passwd_syslog.test -+run_test ./su/05/su_user_wrong_passwd_syslog.test -+run_test ./su/06/su_user_syslog.test -+run_test ./su/07/su_user_syslog.test -+run_test ./su/08/env_special-options_ -+run_test ./su/08/env_special_root-options_ -+run_test ./su/09/env_special-options_ -+run_test ./su/09/env_special_root-options_ -+run_test ./su/10_su_sulog_success/su.test -+run_test ./su/11_su_sulog_failure/su.test -+run_test ./su/12_su_child_failure/su.test -+run_test ./su/13_su_child_success/su.test -+run_test ./libsubid/01_list_ranges/list_ranges.test -+run_test ./libsubid/02_get_subid_owners/get_subid_owners.test -+run_test ./libsubid/03_add_remove/add_remove_subids.test -+ -+echo -+echo "$succeeded test(s) passed" -+echo "$failed test(s) failed" -+echo "log written in 'testsuite.log'" -+if [ "$failed" != "0" ] -+then -+ echo "the following tests failed:" -+ echo $failed_tests -+fi -+ --- -2.30.2 - -From 607f1dd549cf9abc87af1cf29275f0d2d11eea29 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 19 Jun 2020 22:09:20 -0500 -Subject: [PATCH] libsubid: fix a prototype in api.h - -Signed-off-by: Serge Hallyn ---- - libsubid/api.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libsubid/api.h b/libsubid/api.h -index f65e3ec9..fbdf0f9e 100644 ---- a/libsubid/api.h -+++ b/libsubid/api.h -@@ -6,7 +6,7 @@ struct subordinate_range **get_subgid_ranges(const char *owner); - void subid_free_ranges(struct subordinate_range **ranges); - - int get_subuid_owners(uid_t uid, uid_t **owner); --int get_subgid_owners(uid_t uid, uid_t **owner); -+int get_subgid_owners(gid_t gid, uid_t **owner); - - /* range should be pre-allocated with owner and count filled in, start is - * ignored, can be 0 */ --- -2.30.2 - -From b5fb1b38eea2fb0489ed088c82daf6700e72363e Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 1 Jan 2021 13:01:54 -0600 -Subject: [PATCH] libsubid: move libmisc.a to last LIBADD entry - -Closes #297 - -Signed-off-by: Serge Hallyn ---- - libsubid/Makefile.am | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am -index bdbc52c3..8bef1ecc 100644 ---- a/libsubid/Makefile.am -+++ b/libsubid/Makefile.am -@@ -16,8 +16,8 @@ MISCLIBS = \ - - libsubid_la_LIBADD = \ - $(top_srcdir)/lib/libshadow.la \ -- $(top_srcdir)/libmisc/libmisc.a \ -- $(MISCLIBS) -+ $(MISCLIBS) \ -+ $(top_srcdir)/libmisc/libmisc.a - - AM_CPPFLAGS = \ - -I${top_srcdir}/lib \ --- -2.30.2 - -From 43a917cce54019799a8de037fd63780a2b640afc Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sat, 18 Apr 2020 14:57:56 -0500 -Subject: [PATCH] configure: define abi versions - -Signed-off-by: Serge Hallyn ---- - configure.ac | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index e4c6aaec..b8bc2b7a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1,11 +1,21 @@ - dnl Process this file with autoconf to produce a configure script. --AC_PREREQ([2.64]) -+AC_PREREQ([2.69]) -+m4_define([libsubid_abi_major], 1) -+m4_define([libsubid_abi_minor], 0) -+m4_define([libsubid_abi_micro], 0) -+m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) - AC_INIT([shadow], [4.8.1], [pkg-shadow-devel@lists.alioth.debian.org], [], - [https://github.com/shadow-maint/shadow]) - AM_INIT_AUTOMAKE([1.11 foreign dist-xz]) -+AC_CONFIG_MACRO_DIRS([m4]) - AM_SILENT_RULES([yes]) - AC_CONFIG_HEADERS([config.h]) - -+AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major]) -+AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor]) -+AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro]) -+AC_SUBST([LIBSUBID_ABI], [libsubid_abi]) -+ - dnl Some hacks... - test "$prefix" = "NONE" && prefix="/usr" - test "$prefix" = "/usr" && exec_prefix="" --- -2.30.2 - diff --git a/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch b/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch deleted file mode 100644 index c0ca905..0000000 --- a/shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch +++ /dev/null @@ -1,151 +0,0 @@ -diff -up shadow-4.8.1/lib/nss.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/nss.c ---- shadow-4.8.1/lib/nss.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.772741048 +0200 -+++ shadow-4.8.1/lib/nss.c 2021-05-25 09:37:14.782741188 +0200 -@@ -116,14 +116,6 @@ void nss_init(char *nsswitch_path) { - subid_nss = NULL; - goto done; - } -- subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); -- if (!subid_nss->has_any_range) { -- fprintf(shadow_logfd, "%s did not provide @has_any_range@\n", libname); -- dlclose(h); -- free(subid_nss); -- subid_nss = NULL; -- goto done; -- } - subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); - if (!subid_nss->find_subid_owners) { - fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname); -diff -up shadow-4.8.1/lib/prototypes.h.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/prototypes.h ---- shadow-4.8.1/lib/prototypes.h.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 -+++ shadow-4.8.1/lib/prototypes.h 2021-05-25 09:37:14.782741188 +0200 -@@ -279,18 +279,6 @@ extern bool nss_is_initialized(); - - struct subid_nss_ops { - /* -- * nss_has_any_range: does a user own any subid range -- * -- * @owner: username -- * @idtype: subuid or subgid -- * @result: true if a subid allocation was found for @owner -- * -- * returns success if the module was able to determine an answer (true or false), -- * else an error status. -- */ -- enum subid_status (*has_any_range)(const char *owner, enum subid_type idtype, bool *result); -- -- /* - * nss_has_range: does a user own a given subid range - * - * @owner: username -diff -up shadow-4.8.1/lib/subordinateio.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/subordinateio.c ---- shadow-4.8.1/lib/subordinateio.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 -+++ shadow-4.8.1/lib/subordinateio.c 2021-05-25 09:37:14.782741188 +0200 -@@ -598,19 +598,8 @@ int sub_uid_open (int mode) - return commonio_open (&subordinate_uid_db, mode); - } - --bool sub_uid_assigned(const char *owner) -+bool local_sub_uid_assigned(const char *owner) - { -- struct subid_nss_ops *h; -- bool found; -- enum subid_status status; -- h = get_subid_nss_handle(); -- if (h) { -- status = h->has_any_range(owner, ID_TYPE_UID, &found); -- if (status == SUBID_STATUS_SUCCESS && found) -- return true; -- return false; -- } -- - return range_exists (&subordinate_uid_db, owner); - } - -@@ -720,18 +709,8 @@ bool have_sub_gids(const char *owner, gi - return have_range(&subordinate_gid_db, owner, start, count); - } - --bool sub_gid_assigned(const char *owner) -+bool local_sub_gid_assigned(const char *owner) - { -- struct subid_nss_ops *h; -- bool found; -- enum subid_status status; -- h = get_subid_nss_handle(); -- if (h) { -- status = h->has_any_range(owner, ID_TYPE_GID, &found); -- if (status == SUBID_STATUS_SUCCESS && found) -- return true; -- return false; -- } - return range_exists (&subordinate_gid_db, owner); - } - -diff -up shadow-4.8.1/lib/subordinateio.h.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/lib/subordinateio.h ---- shadow-4.8.1/lib/subordinateio.h.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.780741160 +0200 -+++ shadow-4.8.1/lib/subordinateio.h 2021-05-25 09:37:14.782741188 +0200 -@@ -16,7 +16,7 @@ - extern int sub_uid_close(void); - extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); - extern bool sub_uid_file_present (void); --extern bool sub_uid_assigned(const char *owner); -+extern bool local_sub_uid_assigned(const char *owner); - extern int sub_uid_lock (void); - extern int sub_uid_setdbname (const char *filename); - extern /*@observer@*/const char *sub_uid_dbname (void); -@@ -34,7 +34,7 @@ extern void free_subordinate_ranges(stru - extern int sub_gid_close(void); - extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); - extern bool sub_gid_file_present (void); --extern bool sub_gid_assigned(const char *owner); -+extern bool local_sub_gid_assigned(const char *owner); - extern int sub_gid_lock (void); - extern int sub_gid_setdbname (const char *filename); - extern /*@observer@*/const char *sub_gid_dbname (void); -diff -up shadow-4.8.1/src/newusers.c.libsubid_fix_newusers_nss_provides_subids shadow-4.8.1/src/newusers.c ---- shadow-4.8.1/src/newusers.c.libsubid_fix_newusers_nss_provides_subids 2021-05-25 09:37:14.776741104 +0200 -+++ shadow-4.8.1/src/newusers.c 2021-05-25 09:37:25.955897160 +0200 -@@ -1021,6 +1021,24 @@ static void close_files (void) - #endif /* ENABLE_SUBIDS */ - } - -+static bool want_subuids(void) -+{ -+ if (get_subid_nss_handle() != NULL) -+ return false; -+ if (getdef_ulong ("SUB_UID_COUNT", 65536) == 0) -+ return false; -+ return true; -+} -+ -+static bool want_subgids(void) -+{ -+ if (get_subid_nss_handle() != NULL) -+ return false; -+ if (getdef_ulong ("SUB_GID_COUNT", 65536) == 0) -+ return false; -+ return true; -+} -+ - int main (int argc, char **argv) - { - char buf[BUFSIZ]; -@@ -1250,7 +1268,7 @@ int main (int argc, char **argv) - /* - * Add subordinate uids if the user does not have them. - */ -- if (is_sub_uid && !sub_uid_assigned(fields[0])) { -+ if (is_sub_uid && want_subuids() && !local_sub_uid_assigned(fields[0])) { - uid_t sub_uid_start = 0; - unsigned long sub_uid_count = 0; - if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) { -@@ -1270,7 +1288,7 @@ int main (int argc, char **argv) - /* - * Add subordinate gids if the user does not have them. - */ -- if (is_sub_gid && !sub_gid_assigned(fields[0])) { -+ if (is_sub_gid && want_subgids() && !local_sub_gid_assigned(fields[0])) { - gid_t sub_gid_start = 0; - unsigned long sub_gid_count = 0; - if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) { diff --git a/shadow-4.8.1-libsubid_init_not_print_error_messages.patch b/shadow-4.8.1-libsubid_init_not_print_error_messages.patch deleted file mode 100644 index 820a043..0000000 --- a/shadow-4.8.1-libsubid_init_not_print_error_messages.patch +++ /dev/null @@ -1,40 +0,0 @@ -From b0e86b959fe5c086ffb5e7eaf3c1b1e9219411e9 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sun, 23 May 2021 08:03:10 -0500 -Subject: [PATCH] libsubid_init: don't print messages on error - -Signed-off-by: Serge Hallyn ---- - libsubid/api.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - -diff --git a/libsubid/api.c b/libsubid/api.c -index c4848142..b477b271 100644 ---- a/libsubid/api.c -+++ b/libsubid/api.c -@@ -46,12 +46,10 @@ bool libsubid_init(const char *progname, FILE * logfd) - { - if (progname) { - progname = strdup(progname); -- if (progname) { -+ if (progname) - Prog = progname; -- } else { -- fprintf(stderr, "Out of memory"); -+ else - return false; -- } - } - - if (logfd) { -@@ -60,7 +58,6 @@ bool libsubid_init(const char *progname, FILE * logfd) - } - shadow_logfd = fopen("/dev/null", "w"); - if (!shadow_logfd) { -- fprintf(stderr, "ERROR opening /dev/null for error messages. Using stderr."); - shadow_logfd = stderr; - return false; - } --- -2.30.2 - diff --git a/shadow-4.8.1-libsubid_init_return_false.patch b/shadow-4.8.1-libsubid_init_return_false.patch deleted file mode 100644 index 4d02d0d..0000000 --- a/shadow-4.8.1-libsubid_init_return_false.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e34f49c1966fcaa9390a544a0136ec189a3c870e Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Mon, 17 May 2021 08:48:03 -0500 -Subject: [PATCH] libsubid_init: return false if out of memory - -The rest of the run isn't likely to get much better, is it? - -Thanks to Alexey for pointing this out. - -Signed-off-by: Serge Hallyn -Cc: Alexey Tikhonov ---- - libsubid/api.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/libsubid/api.c b/libsubid/api.c -index 8ca09859..8618e500 100644 ---- a/libsubid/api.c -+++ b/libsubid/api.c -@@ -46,10 +46,12 @@ bool libsubid_init(const char *progname, FILE * logfd) - { - if (progname) { - progname = strdup(progname); -- if (progname) -+ if (progname) { - Prog = progname; -- else -+ } else { - fprintf(stderr, "Out of memory"); -+ return false; -+ } - } - - if (logfd) { --- -2.30.2 - diff --git a/shadow-4.8.1-libsubid_make_logfd_not_extern.patch b/shadow-4.8.1-libsubid_make_logfd_not_extern.patch deleted file mode 100644 index 2994442..0000000 --- a/shadow-4.8.1-libsubid_make_logfd_not_extern.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 1d767fb779d7b203ad609540d1dc605cf62d1050 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 28 May 2021 22:02:16 -0500 -Subject: [PATCH] libsubid/api.c: make shadow_logfd not extern - -Closes #346 - -Also #include stdio.h - -Signed-off-by: Serge Hallyn ---- - libsubid/api.c | 2 +- - libsubid/subid.h | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/libsubid/api.c b/libsubid/api.c -index b477b271..a7b904d0 100644 ---- a/libsubid/api.c -+++ b/libsubid/api.c -@@ -40,7 +40,7 @@ - #include "subid.h" - - const char *Prog = "(libsubid)"; --extern FILE * shadow_logfd; -+FILE *shadow_logfd; - - bool libsubid_init(const char *progname, FILE * logfd) - { -diff --git a/libsubid/subid.h b/libsubid/subid.h -index 5fef2572..eabafe4d 100644 ---- a/libsubid/subid.h -+++ b/libsubid/subid.h -@@ -1,4 +1,5 @@ - #include -+#include - #include - - #ifndef SUBID_RANGE_DEFINED --- -2.31.1 - diff --git a/shadow-4.8.1-libsubid_not_print_error_messages.patch b/shadow-4.8.1-libsubid_not_print_error_messages.patch deleted file mode 100644 index 3cef98c..0000000 --- a/shadow-4.8.1-libsubid_not_print_error_messages.patch +++ /dev/null @@ -1,2443 +0,0 @@ -diff -up shadow-4.8.1/lib/commonio.c.libsubid_not_print_error_messages shadow-4.8.1/lib/commonio.c ---- shadow-4.8.1/lib/commonio.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.919268967 +0200 -+++ shadow-4.8.1/lib/commonio.c 2021-05-24 13:04:19.928269091 +0200 -@@ -144,7 +144,7 @@ static int do_lock_file (const char *fil - fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600); - if (-1 == fd) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s: %s\n", - Prog, file, strerror (errno)); - } -@@ -156,7 +156,7 @@ static int do_lock_file (const char *fil - len = (ssize_t) strlen (buf) + 1; - if (write (fd, buf, (size_t) len) != len) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s file write error: %s\n", - Prog, file, strerror (errno)); - } -@@ -166,7 +166,7 @@ static int do_lock_file (const char *fil - } - if (fdatasync (fd) == -1) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s file sync error: %s\n", - Prog, file, strerror (errno)); - } -@@ -179,7 +179,7 @@ static int do_lock_file (const char *fil - if (link (file, lock) == 0) { - retval = check_link_count (file); - if ((0==retval) && log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s: lock file already used\n", - Prog, file); - } -@@ -190,7 +190,7 @@ static int do_lock_file (const char *fil - fd = open (lock, O_RDWR); - if (-1 == fd) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s: %s\n", - Prog, lock, strerror (errno)); - } -@@ -202,7 +202,7 @@ static int do_lock_file (const char *fil - close (fd); - if (len <= 0) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: existing lock file %s without a PID\n", - Prog, lock); - } -@@ -213,7 +213,7 @@ static int do_lock_file (const char *fil - buf[len] = '\0'; - if (get_pid (buf, &pid) == 0) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: existing lock file %s with an invalid PID '%s'\n", - Prog, lock, buf); - } -@@ -223,7 +223,7 @@ static int do_lock_file (const char *fil - } - if (kill (pid, 0) == 0) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: lock %s already used by PID %lu\n", - Prog, lock, (unsigned long) pid); - } -@@ -233,7 +233,7 @@ static int do_lock_file (const char *fil - } - if (unlink (lock) != 0) { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: cannot get lock %s: %s\n", - Prog, lock, strerror (errno)); - } -@@ -245,13 +245,13 @@ static int do_lock_file (const char *fil - if (link (file, lock) == 0) { - retval = check_link_count (file); - if ((0==retval) && log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: %s: lock file already used\n", - Prog, file); - } - } else { - if (log) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: cannot get lock %s: %s\n", - Prog, lock, strerror (errno)); - } -@@ -442,7 +442,7 @@ int commonio_lock (struct commonio_db *d - if (0 == lock_count) { - if (lckpwdf () == -1) { - if (geteuid () != 0) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - "%s: Permission denied.\n", - Prog); - } -@@ -478,7 +478,7 @@ int commonio_lock (struct commonio_db *d - } - /* no unnecessary retries on "permission denied" errors */ - if (geteuid () != 0) { -- (void) fprintf (stderr, "%s: Permission denied.\n", -+ (void) fprintf (shadow_logfd, "%s: Permission denied.\n", - Prog); - return 0; - } -@@ -1109,7 +1109,7 @@ int commonio_update (struct commonio_db - p = find_entry_by_name (db, db->ops->getname (eptr)); - if (NULL != p) { - if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) { -- fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename); -+ fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename); - db->ops->free (nentry); - return 0; - } -@@ -1214,7 +1214,7 @@ int commonio_remove (struct commonio_db - return 0; - } - if (next_entry_by_name (db, p->next, name) != NULL) { -- fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename); -+ fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename); - return 0; - } - -diff -up shadow-4.8.1/lib/encrypt.c.libsubid_not_print_error_messages shadow-4.8.1/lib/encrypt.c ---- shadow-4.8.1/lib/encrypt.c.libsubid_not_print_error_messages 2019-12-01 18:02:43.000000000 +0100 -+++ shadow-4.8.1/lib/encrypt.c 2021-05-24 13:04:19.928269091 +0200 -@@ -81,7 +81,7 @@ - method = &nummethod[0]; - } - } -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("crypt method not supported by libcrypt? (%s)\n"), - method); - exit (EXIT_FAILURE); -diff -up shadow-4.8.1/lib/getdef.c.libsubid_not_print_error_messages shadow-4.8.1/lib/getdef.c ---- shadow-4.8.1/lib/getdef.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.915268912 +0200 -+++ shadow-4.8.1/lib/getdef.c 2021-05-24 13:04:19.928269091 +0200 -@@ -250,7 +250,7 @@ int getdef_num (const char *item, int df - if ( (getlong (d->value, &val) == 0) - || (val > INT_MAX) - || (val < INT_MIN)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("configuration error - cannot parse %s value: '%s'"), - item, d->value); - return dflt; -@@ -285,7 +285,7 @@ unsigned int getdef_unum (const char *it - if ( (getlong (d->value, &val) == 0) - || (val < 0) - || (val > INT_MAX)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("configuration error - cannot parse %s value: '%s'"), - item, d->value); - return dflt; -@@ -318,7 +318,7 @@ long getdef_long (const char *item, long - } - - if (getlong (d->value, &val) == 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("configuration error - cannot parse %s value: '%s'"), - item, d->value); - return dflt; -@@ -351,7 +351,7 @@ unsigned long getdef_ulong (const char * - - if (getulong (d->value, &val) == 0) { - /* FIXME: we should have a getulong */ -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("configuration error - cannot parse %s value: '%s'"), - item, d->value); - return dflt; -@@ -389,7 +389,7 @@ int putdef_str (const char *name, const - cp = strdup (value); - if (NULL == cp) { - (void) fputs (_("Could not allocate space for config info.\n"), -- stderr); -+ shadow_logfd); - SYSLOG ((LOG_ERR, "could not allocate space for config info")); - return -1; - } -@@ -434,7 +434,7 @@ static /*@observer@*/ /*@null@*/struct i - goto out; - } - } -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("configuration error - unknown item '%s' (notify administrator)\n"), - name); - SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name)); -diff -up shadow-4.8.1/libmisc/addgrps.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/addgrps.c ---- shadow-4.8.1/libmisc/addgrps.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/addgrps.c 2021-05-24 13:04:19.929269104 +0200 -@@ -93,7 +93,7 @@ int add_groups (const char *list) - - grp = getgrnam (token); /* local, no need for xgetgrnam */ - if (NULL == grp) { -- fprintf (stderr, _("Warning: unknown group %s\n"), -+ fprintf (shadow_logfd, _("Warning: unknown group %s\n"), - token); - continue; - } -@@ -105,7 +105,7 @@ int add_groups (const char *list) - } - - if (ngroups >= sysconf (_SC_NGROUPS_MAX)) { -- fputs (_("Warning: too many groups\n"), stderr); -+ fputs (_("Warning: too many groups\n"), shadow_logfd); - break; - } - tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T)); -diff -up shadow-4.8.1/libmisc/audit_help.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/audit_help.c ---- shadow-4.8.1/libmisc/audit_help.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 -+++ shadow-4.8.1/libmisc/audit_help.c 2021-05-24 13:04:19.929269104 +0200 -@@ -59,7 +59,7 @@ void audit_help_open (void) - return; - } - (void) fputs (_("Cannot open audit interface - aborting.\n"), -- stderr); -+ shadow_logfd); - exit (EXIT_FAILURE); - } - } -diff -up shadow-4.8.1/libmisc/chowntty.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/chowntty.c ---- shadow-4.8.1/libmisc/chowntty.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/chowntty.c 2021-05-24 13:04:19.929269104 +0200 -@@ -75,7 +75,7 @@ void chown_tty (const struct passwd *inf - || (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) { - int err = errno; - -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Unable to change owner or mode of tty stdin: %s"), - strerror (err)); - SYSLOG ((LOG_WARN, -diff -up shadow-4.8.1/libmisc/cleanup_group.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/cleanup_group.c ---- shadow-4.8.1/libmisc/cleanup_group.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 -+++ shadow-4.8.1/libmisc/cleanup_group.c 2021-05-24 13:04:19.929269104 +0200 -@@ -203,7 +203,7 @@ void cleanup_report_del_group_gshadow (v - void cleanup_unlock_group (unused void *arg) - { - if (gr_unlock () == 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); -@@ -223,7 +223,7 @@ void cleanup_unlock_group (unused void * - void cleanup_unlock_gshadow (unused void *arg) - { - if (sgr_unlock () == 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); -diff -up shadow-4.8.1/libmisc/cleanup_user.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/cleanup_user.c ---- shadow-4.8.1/libmisc/cleanup_user.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.905268774 +0200 -+++ shadow-4.8.1/libmisc/cleanup_user.c 2021-05-24 13:04:19.929269104 +0200 -@@ -120,7 +120,7 @@ void cleanup_report_add_user_shadow (voi - void cleanup_unlock_passwd (unused void *arg) - { - if (pw_unlock () == 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); -@@ -139,7 +139,7 @@ void cleanup_unlock_passwd (unused void - void cleanup_unlock_shadow (unused void *arg) - { - if (spw_unlock () == 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); -diff -up shadow-4.8.1/libmisc/copydir.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/copydir.c ---- shadow-4.8.1/libmisc/copydir.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.898268677 +0200 -+++ shadow-4.8.1/libmisc/copydir.c 2021-05-24 13:04:19.929269104 +0200 -@@ -125,11 +125,11 @@ static void error_acl (struct error_cont - } - - va_start (ap, fmt); -- (void) fprintf (stderr, _("%s: "), Prog); -- if (vfprintf (stderr, fmt, ap) != 0) { -- (void) fputs (_(": "), stderr); -+ (void) fprintf (shadow_logfd, _("%s: "), Prog); -+ if (vfprintf (shadow_logfd, fmt, ap) != 0) { -+ (void) fputs (_(": "), shadow_logfd); - } -- (void) fprintf (stderr, "%s\n", strerror (errno)); -+ (void) fprintf (shadow_logfd, "%s\n", strerror (errno)); - va_end (ap); - } - -@@ -248,7 +248,7 @@ int copy_tree (const char *src_root, con - } - - if (!S_ISDIR (sb.st_mode)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - "%s: %s is not a directory", - Prog, src_root); - return -1; -diff -up shadow-4.8.1/libmisc/env.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/env.c ---- shadow-4.8.1/libmisc/env.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/env.c 2021-05-24 13:04:19.929269104 +0200 -@@ -171,7 +171,7 @@ void addenv (const char *string, /*@null - } - newenvp = __newenvp; - } else { -- (void) fputs (_("Environment overflow\n"), stderr); -+ (void) fputs (_("Environment overflow\n"), shadow_logfd); - newenvc--; - free (newenvp[newenvc]); - } -diff -up shadow-4.8.1/libmisc/find_new_gid.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_gid.c ---- shadow-4.8.1/libmisc/find_new_gid.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.914268898 +0200 -+++ shadow-4.8.1/libmisc/find_new_gid.c 2021-05-24 13:04:19.929269104 +0200 -@@ -74,7 +74,7 @@ static int get_ranges (bool sys_group, g - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: SYS_GID_MIN (%lu), " - "GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), - Prog, (unsigned long) *min_id, -@@ -104,7 +104,7 @@ static int get_ranges (bool sys_group, g - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: GID_MIN (%lu), " - "GID_MAX (%lu)\n"), - Prog, (unsigned long) *min_id, -@@ -220,7 +220,7 @@ int find_new_gid (bool sys_group, - * more likely to want to stop and address the - * issue. - */ -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Encountered error attempting to use " - "preferred GID: %s\n"), - Prog, strerror (result)); -@@ -250,7 +250,7 @@ int find_new_gid (bool sys_group, - /* Create an array to hold all of the discovered GIDs */ - used_gids = malloc (sizeof (bool) * (gid_max +1)); - if (NULL == used_gids) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to allocate memory: %s\n"), - Prog, strerror (errno)); - return -1; -@@ -330,7 +330,7 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique system GID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -373,7 +373,7 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique system GID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -433,7 +433,7 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique GID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -476,7 +476,7 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique GID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -495,7 +495,7 @@ int find_new_gid (bool sys_group, - } - - /* The code reached here and found no available IDs in the range */ -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique GID (no more available GIDs)\n"), - Prog); - SYSLOG ((LOG_WARN, "no more available GIDs on the system")); -diff -up shadow-4.8.1/libmisc/find_new_sub_gids.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_sub_gids.c ---- shadow-4.8.1/libmisc/find_new_sub_gids.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/find_new_sub_gids.c 2021-05-24 13:04:19.930269118 +0200 -@@ -61,7 +61,7 @@ int find_new_sub_gids (const char *owner - count = getdef_ulong ("SUB_GID_COUNT", 65536); - - if (min > max || count >= max || (min + count - 1) > max) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: SUB_GID_MIN (%lu)," - " SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"), - Prog, min, max, count); -@@ -70,7 +70,7 @@ int find_new_sub_gids (const char *owner - - start = sub_gid_find_free_range(min, max, count); - if (start == (gid_t)-1) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique subordinate GID range\n"), - Prog); - SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system")); -diff -up shadow-4.8.1/libmisc/find_new_sub_uids.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_sub_uids.c ---- shadow-4.8.1/libmisc/find_new_sub_uids.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/find_new_sub_uids.c 2021-05-24 13:04:19.930269118 +0200 -@@ -61,7 +61,7 @@ int find_new_sub_uids (const char *owner - count = getdef_ulong ("SUB_UID_COUNT", 65536); - - if (min > max || count >= max || (min + count - 1) > max) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: SUB_UID_MIN (%lu)," - " SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"), - Prog, min, max, count); -@@ -70,7 +70,7 @@ int find_new_sub_uids (const char *owner - - start = sub_uid_find_free_range(min, max, count); - if (start == (uid_t)-1) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique subordinate UID range\n"), - Prog); - SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system")); -diff -up shadow-4.8.1/libmisc/find_new_uid.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/find_new_uid.c ---- shadow-4.8.1/libmisc/find_new_uid.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.914268898 +0200 -+++ shadow-4.8.1/libmisc/find_new_uid.c 2021-05-24 13:04:19.930269118 +0200 -@@ -74,7 +74,7 @@ static int get_ranges (bool sys_user, ui - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: SYS_UID_MIN (%lu), " - "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), - Prog, (unsigned long) *min_id, -@@ -104,7 +104,7 @@ static int get_ranges (bool sys_user, ui - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: Invalid configuration: UID_MIN (%lu), " - "UID_MAX (%lu)\n"), - Prog, (unsigned long) *min_id, -@@ -220,7 +220,7 @@ int find_new_uid(bool sys_user, - * more likely to want to stop and address the - * issue. - */ -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Encountered error attempting to use " - "preferred UID: %s\n"), - Prog, strerror (result)); -@@ -250,7 +250,7 @@ int find_new_uid(bool sys_user, - /* Create an array to hold all of the discovered UIDs */ - used_uids = malloc (sizeof (bool) * (uid_max +1)); - if (NULL == used_uids) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: failed to allocate memory: %s\n"), - Prog, strerror (errno)); - return -1; -@@ -330,7 +330,7 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique system UID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -373,7 +373,7 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique system UID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -433,7 +433,7 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique UID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -476,7 +476,7 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique UID (%s). " - "Suppressing additional messages.\n"), - Prog, strerror (result)); -@@ -495,7 +495,7 @@ int find_new_uid(bool sys_user, - } - - /* The code reached here and found no available IDs in the range */ -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Can't get unique UID (no more available UIDs)\n"), - Prog); - SYSLOG ((LOG_WARN, "no more available UIDs on the system")); -diff -up shadow-4.8.1/libmisc/gettime.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/gettime.c ---- shadow-4.8.1/libmisc/gettime.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/gettime.c 2021-05-24 13:04:19.930269118 +0200 -@@ -61,23 +61,23 @@ - epoch = strtoull (source_date_epoch, &endptr, 10); - if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) - || (errno != 0 && epoch == 0)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n"), - strerror(errno)); - } else if (endptr == source_date_epoch) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n"), - endptr); - } else if (*endptr != '\0') { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n"), - endptr); - } else if (epoch > ULONG_MAX) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu\n"), - ULONG_MAX, epoch); - } else if (epoch > fallback) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to the current time (%lu) but was found to be: %llu\n"), - fallback, epoch); - } else { -diff -up shadow-4.8.1/libmisc/idmapping.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/idmapping.c ---- shadow-4.8.1/libmisc/idmapping.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/idmapping.c 2021-05-24 13:20:06.679312187 +0200 -@@ -47,19 +47,19 @@ struct map_range *get_map_ranges(int ran - int idx, argidx; - - if (ranges < 0 || argc < 0) { -- fprintf(stderr, "%s: error calculating number of arguments\n", Prog); -+ fprintf(shadow_logfd, "%s: error calculating number of arguments\n", Prog); - return NULL; - } - - if (ranges != ((argc + 2) / 3)) { -- fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); -+ fprintf(shadow_logfd, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); - return NULL; - } - - if ((ranges * 3) > argc) { -- fprintf(stderr, "ranges: %u argc: %d\n", -+ fprintf(shadow_logfd, "ranges: %u argc: %d\n", - ranges, argc); -- fprintf(stderr, -+ fprintf(shadow_logfd, - _( "%s: Not enough arguments to form %u mappings\n"), - Prog, ranges); - return NULL; -@@ -67,7 +67,7 @@ struct map_range *get_map_ranges(int ran - - mappings = calloc(ranges, sizeof(*mappings)); - if (!mappings) { -- fprintf(stderr, _( "%s: Memory allocation failure\n"), -+ fprintf(shadow_logfd, _( "%s: Memory allocation failure\n"), - Prog); - exit(EXIT_FAILURE); - } -@@ -88,24 +88,24 @@ struct map_range *get_map_ranges(int ran - return NULL; - } - if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) { -- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); - exit(EXIT_FAILURE); - } - if (mapping->upper > UINT_MAX || - mapping->lower > UINT_MAX || - mapping->count > UINT_MAX) { -- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); - exit(EXIT_FAILURE); - } - if (mapping->lower + mapping->count > UINT_MAX || - mapping->upper + mapping->count > UINT_MAX) { -- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); - exit(EXIT_FAILURE); - } - if (mapping->lower + mapping->count < mapping->lower || - mapping->upper + mapping->count < mapping->upper) { - /* this one really shouldn't be possible given previous checks */ -- fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); - exit(EXIT_FAILURE); - } - } -@@ -157,19 +157,19 @@ void write_mapping(int proc_dir_fd, int - } else if (strcmp(map_file, "gid_map") == 0) { - cap = CAP_SETGID; - } else { -- fprintf(stderr, _("%s: Invalid map file %s specified\n"), Prog, map_file); -+ fprintf(shadow_logfd, _("%s: Invalid map file %s specified\n"), Prog, map_file); - exit(EXIT_FAILURE); - } - - /* Align setuid- and fscaps-based new{g,u}idmap behavior. */ - if (geteuid() == 0 && geteuid() != ruid) { - if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { -- fprintf(stderr, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); -+ fprintf(shadow_logfd, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); - exit(EXIT_FAILURE); - } - - if (seteuid(ruid) < 0) { -- fprintf(stderr, _("%s: Could not seteuid to %d\n"), Prog, ruid); -+ fprintf(shadow_logfd, _("%s: Could not seteuid to %d\n"), Prog, ruid); - exit(EXIT_FAILURE); - } - } -@@ -179,7 +179,7 @@ void write_mapping(int proc_dir_fd, int - data[0].effective = CAP_TO_MASK(cap); - data[0].permitted = data[0].effective; - if (capset(&hdr, data) < 0) { -- fprintf(stderr, _("%s: Could not set caps\n"), Prog); -+ fprintf(shadow_logfd, _("%s: Could not set caps\n"), Prog); - exit(EXIT_FAILURE); - } - #endif -@@ -197,7 +197,7 @@ void write_mapping(int proc_dir_fd, int - mapping->lower, - mapping->count); - if ((written <= 0) || (written >= (bufsize - (pos - buf)))) { -- fprintf(stderr, _("%s: snprintf failed!\n"), Prog); -+ fprintf(shadow_logfd, _("%s: snprintf failed!\n"), Prog); - exit(EXIT_FAILURE); - } - pos += written; -@@ -206,12 +206,12 @@ void write_mapping(int proc_dir_fd, int - /* Write the mapping to the mapping file */ - fd = openat(proc_dir_fd, map_file, O_WRONLY); - if (fd < 0) { -- fprintf(stderr, _("%s: open of %s failed: %s\n"), -+ fprintf(shadow_logfd, _("%s: open of %s failed: %s\n"), - Prog, map_file, strerror(errno)); - exit(EXIT_FAILURE); - } - if (write(fd, buf, pos - buf) != (pos - buf)) { -- fprintf(stderr, _("%s: write to %s failed: %s\n"), -+ fprintf(shadow_logfd, _("%s: write to %s failed: %s\n"), - Prog, map_file, strerror(errno)); - exit(EXIT_FAILURE); - } -diff -up shadow-4.8.1/libmisc/limits.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/limits.c ---- shadow-4.8.1/libmisc/limits.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/limits.c 2021-05-24 13:04:19.930269118 +0200 -@@ -548,7 +548,7 @@ void setup_limits (const struct passwd * - #ifdef LIMITS - if (info->pw_uid != 0) { - if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) { -- (void) fputs (_("Too many logins.\n"), stderr); -+ (void) fputs (_("Too many logins.\n"), shadow_logfd); - (void) sleep (2); /* XXX: Should be FAIL_DELAY */ - exit (EXIT_FAILURE); - } -diff -up shadow-4.8.1/libmisc/pam_pass.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pam_pass.c ---- shadow-4.8.1/libmisc/pam_pass.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/pam_pass.c 2021-05-24 13:04:19.930269118 +0200 -@@ -59,20 +59,20 @@ void do_pam_passwd (const char *user, bo - - ret = pam_start ("passwd", user, &conv, &pamh); - if (ret != PAM_SUCCESS) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("passwd: pam_start() failed, error %d\n"), ret); - exit (10); /* XXX */ - } - - ret = pam_chauthtok (pamh, flags); - if (ret != PAM_SUCCESS) { -- fprintf (stderr, _("passwd: %s\n"), pam_strerror (pamh, ret)); -- fputs (_("passwd: password unchanged\n"), stderr); -+ fprintf (shadow_logfd, _("passwd: %s\n"), pam_strerror (pamh, ret)); -+ fputs (_("passwd: password unchanged\n"), shadow_logfd); - pam_end (pamh, ret); - exit (10); /* XXX */ - } - -- fputs (_("passwd: password updated successfully\n"), stderr); -+ fputs (_("passwd: password updated successfully\n"), shadow_logfd); - (void) pam_end (pamh, PAM_SUCCESS); - } - #else /* !USE_PAM */ -diff -up shadow-4.8.1/libmisc/pam_pass_non_interactive.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pam_pass_non_interactive.c ---- shadow-4.8.1/libmisc/pam_pass_non_interactive.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/pam_pass_non_interactive.c 2021-05-24 13:04:19.930269118 +0200 -@@ -76,7 +76,7 @@ static int ni_conv (int num_msg, - - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: PAM modules requesting echoing are not supported.\n"), - Prog); - goto failed_conversation; -@@ -88,7 +88,7 @@ static int ni_conv (int num_msg, - break; - case PAM_ERROR_MSG: - if ( (NULL == msg[count]->msg) -- || (fprintf (stderr, "%s\n", msg[count]->msg) <0)) { -+ || (fprintf (shadow_logfd, "%s\n", msg[count]->msg) <0)) { - goto failed_conversation; - } - responses[count].resp = NULL; -@@ -101,7 +101,7 @@ static int ni_conv (int num_msg, - responses[count].resp = NULL; - break; - default: -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: conversation type %d not supported.\n"), - Prog, msg[count]->msg_style); - goto failed_conversation; -@@ -143,7 +143,7 @@ int do_pam_passwd_non_interactive (const - - ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh); - if (ret != PAM_SUCCESS) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: (user %s) pam_start failure %d\n"), - Prog, username, ret); - return 1; -@@ -152,7 +152,7 @@ int do_pam_passwd_non_interactive (const - non_interactive_password = password; - ret = pam_chauthtok (pamh, 0); - if (ret != PAM_SUCCESS) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: (user %s) pam_chauthtok() failed, error:\n" - "%s\n"), - Prog, username, pam_strerror (pamh, ret)); -diff -up shadow-4.8.1/libmisc/prefix_flag.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/prefix_flag.c ---- shadow-4.8.1/libmisc/prefix_flag.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.930269118 +0200 -+++ shadow-4.8.1/libmisc/prefix_flag.c 2021-05-24 13:21:11.538205727 +0200 -@@ -80,14 +80,14 @@ extern const char* process_prefix_flag ( - if ( (strcmp (argv[i], "--prefix") == 0) - || (strcmp (argv[i], short_opt) == 0)) { - if (NULL != prefix) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: multiple --prefix options\n"), - Prog); - exit (E_BAD_ARG); - } - - if (i + 1 == argc) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: option '%s' requires an argument\n"), - Prog, argv[i]); - exit (E_BAD_ARG); -diff -up shadow-4.8.1/libmisc/pwdcheck.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/pwdcheck.c ---- shadow-4.8.1/libmisc/pwdcheck.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/pwdcheck.c 2021-05-24 13:04:19.930269118 +0200 -@@ -51,7 +51,7 @@ void passwd_check (const char *user, con - if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) { - SYSLOG ((LOG_WARN, "incorrect password for `%s'", user)); - (void) sleep (1); -- fprintf (stderr, _("Incorrect password for %s.\n"), user); -+ fprintf (shadow_logfd, _("Incorrect password for %s.\n"), user); - exit (EXIT_FAILURE); - } - } -diff -up shadow-4.8.1/libmisc/root_flag.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/root_flag.c ---- shadow-4.8.1/libmisc/root_flag.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/root_flag.c 2021-05-24 14:39:04.286481468 +0200 -@@ -62,14 +62,14 @@ extern void process_root_flag (const cha - if ( (strcmp (argv[i], "--root") == 0) - || (strcmp (argv[i], short_opt) == 0)) { - if (NULL != newroot) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: multiple --root options\n"), - Prog); - exit (E_BAD_ARG); - } - - if (i + 1 == argc) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: option '%s' requires an argument\n"), - Prog, argv[i]); - exit (E_BAD_ARG); -@@ -88,34 +88,34 @@ static void change_root (const char* new - /* Drop privileges */ - if ( (setregid (getgid (), getgid ()) != 0) - || (setreuid (getuid (), getuid ()) != 0)) { -- fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), -+ fprintf (shadow_logfd, _("%s: failed to drop privileges (%s)\n"), - Prog, strerror (errno)); - exit (EXIT_FAILURE); - } - - if ('/' != newroot[0]) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: invalid chroot path '%s'\n"), - Prog, newroot); - exit (E_BAD_ARG); - } - - if (access (newroot, F_OK) != 0) { -- fprintf(stderr, -+ fprintf(shadow_logfd, - _("%s: cannot access chroot directory %s: %s\n"), - Prog, newroot, strerror (errno)); - exit (E_BAD_ARG); - } - - if (chdir (newroot) != 0) { -- fprintf(stderr, -+ fprintf(shadow_logfd, - _("%s: cannot chdir to chroot directory %s: %s\n"), - Prog, newroot, strerror (errno)); - exit (E_BAD_ARG); - } - - if (chroot (newroot) != 0) { -- fprintf(stderr, -+ fprintf(shadow_logfd, - _("%s: unable to chroot to directory %s: %s\n"), - Prog, newroot, strerror (errno)); - exit (E_BAD_ARG); -diff -up shadow-4.8.1/libmisc/salt.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/salt.c ---- shadow-4.8.1/libmisc/salt.c.libsubid_not_print_error_messages 2019-12-01 18:02:43.000000000 +0100 -+++ shadow-4.8.1/libmisc/salt.c 2021-05-24 13:04:19.930269118 +0200 -@@ -344,7 +344,7 @@ static /*@observer@*/const char *gensalt - salt_len = (size_t) shadow_random (8, 16); - #endif /* USE_SHA_CRYPT */ - } else if (0 != strcmp (method, "DES")) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Invalid ENCRYPT_METHOD value: '%s'.\n" - "Defaulting to DES.\n"), - method); -diff -up shadow-4.8.1/libmisc/setupenv.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/setupenv.c ---- shadow-4.8.1/libmisc/setupenv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/setupenv.c 2021-05-24 13:04:19.930269118 +0200 -@@ -219,7 +219,7 @@ void setup_env (struct passwd *info) - static char temp_pw_dir[] = "/"; - - if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) { -- fprintf (stderr, _("Unable to cd to '%s'\n"), -+ fprintf (shadow_logfd, _("Unable to cd to '%s'\n"), - info->pw_dir); - SYSLOG ((LOG_WARN, - "unable to cd to `%s' for user `%s'\n", -diff -up shadow-4.8.1/libmisc/user_busy.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/user_busy.c ---- shadow-4.8.1/libmisc/user_busy.c.libsubid_not_print_error_messages 2020-01-23 19:04:44.000000000 +0100 -+++ shadow-4.8.1/libmisc/user_busy.c 2021-05-24 13:04:19.931269132 +0200 -@@ -96,7 +96,7 @@ static int user_busy_utmp (const char *n - continue; - } - -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: user %s is currently logged in\n"), - Prog, name); - return 1; -@@ -249,7 +249,7 @@ static int user_busy_processes (const ch - #ifdef ENABLE_SUBIDS - sub_uid_close(); - #endif -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: user %s is currently used by process %d\n"), - Prog, name, pid); - return 1; -@@ -272,7 +272,7 @@ static int user_busy_processes (const ch - #ifdef ENABLE_SUBIDS - sub_uid_close(); - #endif -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: user %s is currently used by process %d\n"), - Prog, name, pid); - return 1; -diff -up shadow-4.8.1/libmisc/xgetXXbyYY.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/xgetXXbyYY.c ---- shadow-4.8.1/libmisc/xgetXXbyYY.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/xgetXXbyYY.c 2021-05-24 13:04:19.931269132 +0200 -@@ -74,7 +74,7 @@ - - result = malloc(sizeof(LOOKUP_TYPE)); - if (NULL == result) { -- fprintf (stderr, _("%s: out of memory\n"), -+ fprintf (shadow_logfd, _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -@@ -84,7 +84,7 @@ - LOOKUP_TYPE *resbuf = NULL; - buffer = (char *)realloc (buffer, length); - if (NULL == buffer) { -- fprintf (stderr, _("%s: out of memory\n"), -+ fprintf (shadow_logfd, _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -@@ -132,7 +132,7 @@ - if (result) { - result = DUP_FUNCTION(result); - if (NULL == result) { -- fprintf (stderr, _("%s: out of memory\n"), -+ fprintf (shadow_logfd, _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -diff -up shadow-4.8.1/libmisc/xmalloc.c.libsubid_not_print_error_messages shadow-4.8.1/libmisc/xmalloc.c ---- shadow-4.8.1/libmisc/xmalloc.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/xmalloc.c 2021-05-24 13:04:19.931269132 +0200 -@@ -54,7 +54,7 @@ - - ptr = (char *) malloc (size); - if (NULL == ptr) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: failed to allocate memory: %s\n"), - Prog, strerror (errno)); - exit (13); -diff -up shadow-4.8.1/lib/nscd.c.libsubid_not_print_error_messages shadow-4.8.1/lib/nscd.c ---- shadow-4.8.1/lib/nscd.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/lib/nscd.c 2021-05-24 13:04:19.928269091 +0200 -@@ -25,13 +25,13 @@ int nscd_flush_cache (const char *servic - - if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) { - /* run_command writes its own more detailed message. */ -- (void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); -+ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); - return -1; - } - - code = WEXITSTATUS (status); - if (!WIFEXITED (status)) { -- (void) fprintf (stderr, -+ (void) fprintf (shadow_logfd, - _("%s: nscd did not terminate normally (signal %d)\n"), - Prog, WTERMSIG (status)); - return -1; -@@ -43,9 +43,9 @@ int nscd_flush_cache (const char *servic - /* nscd is installed, but it isn't active. */ - return 0; - } else if (code != 0) { -- (void) fprintf (stderr, _("%s: nscd exited with status %d\n"), -+ (void) fprintf (shadow_logfd, _("%s: nscd exited with status %d\n"), - Prog, code); -- (void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); -+ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); - return -1; - } - -diff -up shadow-4.8.1/lib/nss.c.libsubid_not_print_error_messages shadow-4.8.1/lib/nss.c ---- shadow-4.8.1/lib/nss.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.924269036 +0200 -+++ shadow-4.8.1/lib/nss.c 2021-05-24 13:04:19.928269091 +0200 -@@ -56,7 +56,7 @@ void nss_init(char *nsswitch_path) { - // subid: files - nssfp = fopen(nsswitch_path, "r"); - if (!nssfp) { -- fprintf(stderr, "Failed opening %s: %m", nsswitch_path); -+ fprintf(shadow_logfd, "Failed opening %s: %m", nsswitch_path); - atomic_store(&nss_init_completed, true); - return; - } -@@ -82,16 +82,16 @@ void nss_init(char *nsswitch_path) { - goto done; - } - if (strlen(token) > 50) { -- fprintf(stderr, "Subid NSS module name too long (longer than 50 characters): %s\n", token); -- fprintf(stderr, "Using files\n"); -+ fprintf(shadow_logfd, "Subid NSS module name too long (longer than 50 characters): %s\n", token); -+ fprintf(shadow_logfd, "Using files\n"); - subid_nss = NULL; - goto done; - } - snprintf(libname, 64, "libsubid_%s.so", token); - h = dlopen(libname, RTLD_LAZY); - if (!h) { -- fprintf(stderr, "Error opening %s: %s\n", libname, dlerror()); -- fprintf(stderr, "Using files\n"); -+ fprintf(shadow_logfd, "Error opening %s: %s\n", libname, dlerror()); -+ fprintf(shadow_logfd, "Using files\n"); - subid_nss = NULL; - goto done; - } -@@ -102,7 +102,7 @@ void nss_init(char *nsswitch_path) { - } - subid_nss->has_range = dlsym(h, "shadow_subid_has_range"); - if (!subid_nss->has_range) { -- fprintf(stderr, "%s did not provide @has_range@\n", libname); -+ fprintf(shadow_logfd, "%s did not provide @has_range@\n", libname); - dlclose(h); - free(subid_nss); - subid_nss = NULL; -@@ -110,7 +110,7 @@ void nss_init(char *nsswitch_path) { - } - subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges"); - if (!subid_nss->list_owner_ranges) { -- fprintf(stderr, "%s did not provide @list_owner_ranges@\n", libname); -+ fprintf(shadow_logfd, "%s did not provide @list_owner_ranges@\n", libname); - dlclose(h); - free(subid_nss); - subid_nss = NULL; -@@ -118,7 +118,7 @@ void nss_init(char *nsswitch_path) { - } - subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); - if (!subid_nss->has_any_range) { -- fprintf(stderr, "%s did not provide @has_any_range@\n", libname); -+ fprintf(shadow_logfd, "%s did not provide @has_any_range@\n", libname); - dlclose(h); - free(subid_nss); - subid_nss = NULL; -@@ -126,7 +126,7 @@ void nss_init(char *nsswitch_path) { - } - subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); - if (!subid_nss->find_subid_owners) { -- fprintf(stderr, "%s did not provide @find_subid_owners@\n", libname); -+ fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname); - dlclose(h); - free(subid_nss); - subid_nss = NULL; -@@ -135,7 +135,7 @@ void nss_init(char *nsswitch_path) { - subid_nss->handle = h; - goto done; - } -- fprintf(stderr, "No usable subid NSS module found, using files\n"); -+ fprintf(shadow_logfd, "No usable subid NSS module found, using files\n"); - // subid_nss has to be null here, but to ease reviews: - free(subid_nss); - subid_nss = NULL; -diff -up shadow-4.8.1/lib/prototypes.h.libsubid_not_print_error_messages shadow-4.8.1/lib/prototypes.h ---- shadow-4.8.1/lib/prototypes.h.libsubid_not_print_error_messages 2021-05-24 13:04:19.924269036 +0200 -+++ shadow-4.8.1/lib/prototypes.h 2021-05-24 13:04:19.928269091 +0200 -@@ -59,7 +59,8 @@ - #include "defines.h" - #include "commonio.h" - --extern /*@observer@*/ const char *Prog; -+extern /*@observer@*/ const char *Prog; /* Program name showed in error messages */ -+extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ - - /* addgrps.c */ - #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) -diff -up shadow-4.8.1/lib/selinux.c.libsubid_not_print_error_messages shadow-4.8.1/lib/selinux.c ---- shadow-4.8.1/lib/selinux.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.911268857 +0200 -+++ shadow-4.8.1/lib/selinux.c 2021-05-24 13:04:32.746445679 +0200 -@@ -135,7 +135,7 @@ static int selinux_log_cb (int type, con - && (errno != EAFNOSUPPORT)) { - - (void) fputs (_("Cannot open audit interface.\n"), -- stderr); -+ shadow_logfd); - SYSLOG ((LOG_WARN, "Cannot open audit interface.")); - } - } -@@ -188,7 +188,7 @@ int check_selinux_permit (const char *pe - selinux_set_callback (SELINUX_CB_LOG, (union selinux_callback) selinux_log_cb); - - if (getprevcon (&user_context_str) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: can not get previous SELinux process context: %s\n"), - Prog, strerror (errno)); - SYSLOG ((LOG_WARN, -diff -up shadow-4.8.1/lib/semanage.c.libsubid_not_print_error_messages shadow-4.8.1/lib/semanage.c ---- shadow-4.8.1/lib/semanage.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.900268705 +0200 -+++ shadow-4.8.1/lib/semanage.c 2021-05-24 13:05:24.747162090 +0200 -@@ -69,7 +69,7 @@ static void semanage_error_callback (unu - switch (semanage_msg_get_level (handle)) { - case SEMANAGE_MSG_ERR: - case SEMANAGE_MSG_WARN: -- fprintf (stderr, _("[libsemanage]: %s\n"), message); -+ fprintf (shadow_logfd, _("[libsemanage]: %s\n"), message); - break; - case SEMANAGE_MSG_INFO: - /* nop */ -@@ -87,7 +87,7 @@ static semanage_handle_t *semanage_init - - handle = semanage_handle_create (); - if (NULL == handle) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Cannot create SELinux management handle\n")); - return NULL; - } -@@ -96,26 +96,26 @@ static semanage_handle_t *semanage_init - - ret = semanage_is_managed (handle); - if (ret != 1) { -- fprintf (stderr, _("SELinux policy not managed\n")); -+ fprintf (shadow_logfd, _("SELinux policy not managed\n")); - goto fail; - } - - ret = semanage_access_check (handle); - if (ret < SEMANAGE_CAN_READ) { -- fprintf (stderr, _("Cannot read SELinux policy store\n")); -+ fprintf (shadow_logfd, _("Cannot read SELinux policy store\n")); - goto fail; - } - - ret = semanage_connect (handle); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Cannot establish SELinux management connection\n")); - goto fail; - } - - ret = semanage_begin_transaction (handle); - if (ret != 0) { -- fprintf (stderr, _("Cannot begin SELinux transaction\n")); -+ fprintf (shadow_logfd, _("Cannot begin SELinux transaction\n")); - goto fail; - } - -@@ -137,7 +137,7 @@ static int semanage_user_mod (semanage_h - - semanage_seuser_query (handle, key, &seuser); - if (NULL == seuser) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not query seuser for %s\n"), login_name); - ret = 1; - goto done; -@@ -146,7 +146,7 @@ static int semanage_user_mod (semanage_h - #if 0 - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not set serange for %s\n"), login_name); - ret = 1; - goto done; -@@ -155,7 +155,7 @@ static int semanage_user_mod (semanage_h - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not set sename for %s\n"), - login_name); - ret = 1; -@@ -164,7 +164,7 @@ static int semanage_user_mod (semanage_h - - ret = semanage_seuser_modify_local (handle, key, seuser); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not modify login mapping for %s\n"), - login_name); - ret = 1; -@@ -188,7 +188,7 @@ static int semanage_user_add (semanage_h - - ret = semanage_seuser_create (handle, &seuser); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Cannot create SELinux login mapping for %s\n"), - login_name); - ret = 1; -@@ -197,7 +197,7 @@ static int semanage_user_add (semanage_h - - ret = semanage_seuser_set_name (handle, seuser, login_name); - if (ret != 0) { -- fprintf (stderr, _("Could not set name for %s\n"), login_name); -+ fprintf (shadow_logfd, _("Could not set name for %s\n"), login_name); - ret = 1; - goto done; - } -@@ -205,7 +205,7 @@ static int semanage_user_add (semanage_h - #if 0 - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not set serange for %s\n"), - login_name); - ret = 1; -@@ -215,7 +215,7 @@ static int semanage_user_add (semanage_h - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not set SELinux user for %s\n"), - login_name); - ret = 1; -@@ -224,7 +224,7 @@ static int semanage_user_add (semanage_h - - ret = semanage_seuser_modify_local (handle, key, seuser); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not add login mapping for %s\n"), - login_name); - ret = 1; -@@ -252,21 +252,21 @@ int set_seuser (const char *login_name, - - handle = semanage_init (); - if (NULL == handle) { -- fprintf (stderr, _("Cannot init SELinux management\n")); -+ fprintf (shadow_logfd, _("Cannot init SELinux management\n")); - ret = 1; - goto done; - } - - ret = semanage_seuser_key_create (handle, login_name, &key); - if (ret != 0) { -- fprintf (stderr, _("Cannot create SELinux user key\n")); -+ fprintf (shadow_logfd, _("Cannot create SELinux user key\n")); - ret = 1; - goto done; - } - - ret = semanage_seuser_exists (handle, key, &seuser_exists); - if (ret < 0) { -- fprintf (stderr, _("Cannot verify the SELinux user\n")); -+ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); - ret = 1; - goto done; - } -@@ -274,7 +274,7 @@ int set_seuser (const char *login_name, - if (0 != seuser_exists) { - ret = semanage_user_mod (handle, key, login_name, seuser_name); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Cannot modify SELinux user mapping\n")); - ret = 1; - goto done; -@@ -282,7 +282,7 @@ int set_seuser (const char *login_name, - } else { - ret = semanage_user_add (handle, key, login_name, seuser_name); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Cannot add SELinux user mapping\n")); - ret = 1; - goto done; -@@ -291,7 +291,7 @@ int set_seuser (const char *login_name, - - ret = semanage_commit (handle); - if (ret < 0) { -- fprintf (stderr, _("Cannot commit SELinux transaction\n")); -+ fprintf (shadow_logfd, _("Cannot commit SELinux transaction\n")); - ret = 1; - goto done; - } -@@ -317,27 +317,27 @@ int del_seuser (const char *login_name) - - handle = semanage_init (); - if (NULL == handle) { -- fprintf (stderr, _("Cannot init SELinux management\n")); -+ fprintf (shadow_logfd, _("Cannot init SELinux management\n")); - ret = 1; - goto done; - } - - ret = semanage_seuser_key_create (handle, login_name, &key); - if (ret != 0) { -- fprintf (stderr, _("Cannot create SELinux user key\n")); -+ fprintf (shadow_logfd, _("Cannot create SELinux user key\n")); - ret = 1; - goto done; - } - - ret = semanage_seuser_exists (handle, key, &exists); - if (ret < 0) { -- fprintf (stderr, _("Cannot verify the SELinux user\n")); -+ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); - ret = 1; - goto done; - } - - if (0 == exists) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Login mapping for %s is not defined, OK if default mapping was used\n"), - login_name); - ret = 0; /* probably default mapping */ -@@ -346,13 +346,13 @@ int del_seuser (const char *login_name) - - ret = semanage_seuser_exists_local (handle, key, &exists); - if (ret < 0) { -- fprintf (stderr, _("Cannot verify the SELinux user\n")); -+ fprintf (shadow_logfd, _("Cannot verify the SELinux user\n")); - ret = 1; - goto done; - } - - if (0 == exists) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Login mapping for %s is defined in policy, cannot be deleted\n"), - login_name); - ret = 0; /* Login mapping defined in policy can't be deleted */ -@@ -361,7 +361,7 @@ int del_seuser (const char *login_name) - - ret = semanage_seuser_del_local (handle, key); - if (ret != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("Could not delete login mapping for %s"), - login_name); - ret = 1; -@@ -370,7 +370,7 @@ int del_seuser (const char *login_name) - - ret = semanage_commit (handle); - if (ret < 0) { -- fprintf (stderr, _("Cannot commit SELinux transaction\n")); -+ fprintf (shadow_logfd, _("Cannot commit SELinux transaction\n")); - ret = 1; - goto done; - } -diff -up shadow-4.8.1/lib/spawn.c.libsubid_not_print_error_messages shadow-4.8.1/lib/spawn.c ---- shadow-4.8.1/lib/spawn.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/lib/spawn.c 2021-05-24 13:04:19.929269104 +0200 -@@ -48,7 +48,7 @@ int run_command (const char *cmd, const - } - - (void) fflush (stdout); -- (void) fflush (stderr); -+ (void) fflush (shadow_logfd); - - pid = fork (); - if (0 == pid) { -@@ -57,11 +57,11 @@ int run_command (const char *cmd, const - if (ENOENT == errno) { - exit (E_CMD_NOTFOUND); - } -- fprintf (stderr, "%s: cannot execute %s: %s\n", -+ fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", - Prog, cmd, strerror (errno)); - exit (E_CMD_NOEXEC); - } else if ((pid_t)-1 == pid) { -- fprintf (stderr, "%s: cannot execute %s: %s\n", -+ fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", - Prog, cmd, strerror (errno)); - return -1; - } -@@ -74,7 +74,7 @@ int run_command (const char *cmd, const - || ((pid_t)-1 != wpid && wpid != pid)); - - if ((pid_t)-1 == wpid) { -- fprintf (stderr, "%s: waitpid (status: %d): %s\n", -+ fprintf (shadow_logfd, "%s: waitpid (status: %d): %s\n", - Prog, *status, strerror (errno)); - return -1; - } -diff -up shadow-4.8.1/libsubid/api.c.libsubid_not_print_error_messages shadow-4.8.1/libsubid/api.c ---- shadow-4.8.1/libsubid/api.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/libsubid/api.c 2021-05-24 13:04:19.931269132 +0200 -@@ -32,12 +32,39 @@ - #include - #include - #include -+#include - #include - #include - #include "subordinateio.h" - #include "idmapping.h" - #include "subid.h" - -+const char *Prog = "(libsubid)"; -+extern FILE * shadow_logfd; -+ -+bool libsubid_init(const char *progname, FILE * logfd) -+{ -+ if (progname) { -+ progname = strdup(progname); -+ if (progname) -+ Prog = progname; -+ else -+ fprintf(stderr, "Out of memory"); -+ } -+ -+ if (logfd) { -+ shadow_logfd = logfd; -+ return true; -+ } -+ shadow_logfd = fopen("/dev/null", "w"); -+ if (!shadow_logfd) { -+ fprintf(stderr, "ERROR opening /dev/null for error messages. Using stderr."); -+ shadow_logfd = stderr; -+ return false; -+ } -+ return true; -+} -+ - static - int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) - { -diff -up shadow-4.8.1/libsubid/subid.h.libsubid_not_print_error_messages shadow-4.8.1/libsubid/subid.h ---- shadow-4.8.1/libsubid/subid.h.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/libsubid/subid.h 2021-05-24 13:04:19.931269132 +0200 -@@ -22,6 +22,22 @@ enum subid_status { - }; - - /* -+ * libsubid_init: initialize libsubid -+ * -+ * @progname: Name to display as program. If NULL, then "(libsubid)" will be -+ * shown in error messages. -+ * @logfd: Open file pointer to pass error messages to. If NULL, then -+ * /dev/null will be opened and messages will be sent there. The -+ * default if libsubid_init() is not called is stderr (2). -+ * -+ * This function does not need to be called. If not called, then the defaults -+ * will be used. -+ * -+ * Returns false if an error occurred. -+ */ -+bool libsubid_init(const char *progname, FILE *logfd); -+ -+/* - * get_subuid_ranges: return a list of UID ranges for a user - * - * @owner: username being queried -diff -up shadow-4.8.1/lib/tcbfuncs.c.libsubid_not_print_error_messages shadow-4.8.1/lib/tcbfuncs.c ---- shadow-4.8.1/lib/tcbfuncs.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/lib/tcbfuncs.c 2021-05-24 13:04:19.929269104 +0200 -@@ -72,8 +72,8 @@ shadowtcb_status shadowtcb_gain_priv (vo - * to exit soon. - */ - #define OUT_OF_MEMORY do { \ -- fprintf (stderr, _("%s: out of memory\n"), Prog); \ -- (void) fflush (stderr); \ -+ fprintf (shadow_logfd, _("%s: out of memory\n"), Prog); \ -+ (void) fflush (shadow_logfd); \ - } while (false) - - /* Returns user's tcb directory path relative to TCB_DIR. */ -@@ -116,7 +116,7 @@ static /*@null@*/ char *shadowtcb_path_r - return NULL; - } - if (lstat (path, &st) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), - Prog, path, strerror (errno)); - free (path); -@@ -132,7 +132,7 @@ static /*@null@*/ char *shadowtcb_path_r - return rval; - } - if (!S_ISLNK (st.st_mode)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: %s is neither a directory, nor a symlink.\n"), - Prog, path); - free (path); -@@ -140,7 +140,7 @@ static /*@null@*/ char *shadowtcb_path_r - } - ret = readlink (path, link, sizeof (link) - 1); - if (-1 == ret) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot read symbolic link %s: %s\n"), - Prog, path, strerror (errno)); - free (path); -@@ -149,7 +149,7 @@ static /*@null@*/ char *shadowtcb_path_r - free (path); - if ((size_t)ret >= sizeof(link) - 1) { - link[sizeof(link) - 1] = '\0'; -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Suspiciously long symlink: %s\n"), - Prog, link); - return NULL; -@@ -207,7 +207,7 @@ static shadowtcb_status mkdir_leading (c - } - ptr = path; - if (stat (TCB_DIR, &st) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), - Prog, TCB_DIR, strerror (errno)); - goto out_free_path; -@@ -219,19 +219,19 @@ static shadowtcb_status mkdir_leading (c - return SHADOWTCB_FAILURE; - } - if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot create directory %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free_dir; - } - if (chown (dir, 0, st.st_gid) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free_dir; - } - if (chmod (dir, 0711) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free_dir; -@@ -261,7 +261,7 @@ static shadowtcb_status unlink_suffs (co - return SHADOWTCB_FAILURE; - } - if ((unlink (tmp) != 0) && (errno != ENOENT)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: unlink: %s: %s\n"), - Prog, tmp, strerror (errno)); - free (tmp); -@@ -286,7 +286,7 @@ static shadowtcb_status rmdir_leading (c - } - if (rmdir (dir) != 0) { - if (errno != ENOTEMPTY) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot remove directory %s: %s\n"), - Prog, dir, strerror (errno)); - ret = SHADOWTCB_FAILURE; -@@ -315,7 +315,7 @@ static shadowtcb_status move_dir (const - goto out_free_nomem; - } - if (stat (olddir, &oldmode) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), - Prog, olddir, strerror (errno)); - goto out_free; -@@ -342,7 +342,7 @@ static shadowtcb_status move_dir (const - goto out_free; - } - if (rename (real_old_dir, real_new_dir) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot rename %s to %s: %s\n"), - Prog, real_old_dir, real_new_dir, strerror (errno)); - goto out_free; -@@ -351,7 +351,7 @@ static shadowtcb_status move_dir (const - goto out_free; - } - if ((unlink (olddir) != 0) && (errno != ENOENT)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot remove %s: %s\n"), - Prog, olddir, strerror (errno)); - goto out_free; -@@ -365,7 +365,7 @@ static shadowtcb_status move_dir (const - } - if ( (strcmp (real_new_dir, newdir) != 0) - && (symlink (real_new_dir_rel, newdir) != 0)) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot create symbolic link %s: %s\n"), - Prog, real_new_dir_rel, strerror (errno)); - goto out_free; -@@ -464,37 +464,37 @@ shadowtcb_status shadowtcb_move (/*@NULL - return SHADOWTCB_FAILURE; - } - if (stat (tcbdir, &dirmode) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), - Prog, tcbdir, strerror (errno)); - goto out_free; - } - if (chown (tcbdir, 0, 0) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owners of %s: %s\n"), - Prog, tcbdir, strerror (errno)); - goto out_free; - } - if (chmod (tcbdir, 0700) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), - Prog, tcbdir, strerror (errno)); - goto out_free; - } - if (lstat (shadow, &filemode) != 0) { - if (errno != ENOENT) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot lstat %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; - } -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Warning, user %s has no tcb shadow file.\n"), - Prog, user_newname); - } else { - if (!S_ISREG (filemode.st_mode) || - filemode.st_nlink != 1) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Emergency: %s's tcb shadow is not a " - "regular file with st_nlink=1.\n" - "The account is left locked.\n"), -@@ -502,13 +502,13 @@ shadowtcb_status shadowtcb_move (/*@NULL - goto out_free; - } - if (chown (shadow, user_newid, filemode.st_gid) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; - } - if (chmod (shadow, filemode.st_mode & 07777) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; -@@ -518,7 +518,7 @@ shadowtcb_status shadowtcb_move (/*@NULL - goto out_free; - } - if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), - Prog, tcbdir, strerror (errno)); - goto out_free; -@@ -543,7 +543,7 @@ shadowtcb_status shadowtcb_create (const - return SHADOWTCB_SUCCESS; - } - if (stat (TCB_DIR, &tcbdir_stat) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), - Prog, TCB_DIR, strerror (errno)); - return SHADOWTCB_FAILURE; -@@ -563,39 +563,39 @@ shadowtcb_status shadowtcb_create (const - return SHADOWTCB_FAILURE; - } - if (mkdir (dir, 0700) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: mkdir: %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free; - } - fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot open %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; - } - close (fd); - if (chown (shadow, 0, authgid) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; - } - if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), - Prog, shadow, strerror (errno)); - goto out_free; - } - if (chown (dir, 0, authgid) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free; - } - if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) { -- fprintf (stderr, -+ fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), - Prog, dir, strerror (errno)); - goto out_free; -diff -up shadow-4.8.1/src/chage.c.libsubid_not_print_error_messages shadow-4.8.1/src/chage.c ---- shadow-4.8.1/src/chage.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 -+++ shadow-4.8.1/src/chage.c 2021-05-24 13:04:19.931269132 +0200 -@@ -62,6 +62,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool - dflg = false, /* set last password change date */ -@@ -816,6 +817,7 @@ int main (int argc, char **argv) - * Get the program name so that error messages can use it. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - sanitize_env (); - (void) setlocale (LC_ALL, ""); -diff -up shadow-4.8.1/src/check_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/check_subid_range.c ---- shadow-4.8.1/src/check_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.925269050 +0200 -+++ shadow-4.8.1/src/check_subid_range.c 2021-05-24 13:04:19.931269132 +0200 -@@ -18,6 +18,7 @@ - #include "idmapping.h" - - const char *Prog; -+FILE *shadow_logfd = NULL; - - int main(int argc, char **argv) - { -@@ -25,6 +26,7 @@ int main(int argc, char **argv) - unsigned long start, count; - bool check_uids; - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - if (argc != 5) - exit(1); -diff -up shadow-4.8.1/src/chfn.c.libsubid_not_print_error_messages shadow-4.8.1/src/chfn.c ---- shadow-4.8.1/src/chfn.c.libsubid_not_print_error_messages 2019-11-12 01:18:25.000000000 +0100 -+++ shadow-4.8.1/src/chfn.c 2021-05-24 13:04:19.931269132 +0200 -@@ -57,6 +57,7 @@ - * Global variables. - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - static char fullnm[BUFSIZ]; - static char roomno[BUFSIZ]; - static char workph[BUFSIZ]; -@@ -634,6 +635,7 @@ int main (int argc, char **argv) - * prefix to most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - sanitize_env (); - (void) setlocale (LC_ALL, ""); -diff -up shadow-4.8.1/src/chgpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/chgpasswd.c ---- shadow-4.8.1/src/chgpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.909268829 +0200 -+++ shadow-4.8.1/src/chgpasswd.c 2021-05-24 14:40:13.975427046 +0200 -@@ -66,6 +66,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -@@ -499,6 +500,7 @@ int main (int argc, char **argv) - int line = 0; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/chpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/chpasswd.c ---- shadow-4.8.1/src/chpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.909268829 +0200 -+++ shadow-4.8.1/src/chpasswd.c 2021-05-24 14:43:57.102454551 +0200 -@@ -63,6 +63,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -@@ -487,6 +488,7 @@ int main (int argc, char **argv) - int line = 0; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/chsh.c.libsubid_not_print_error_messages shadow-4.8.1/src/chsh.c ---- shadow-4.8.1/src/chsh.c.libsubid_not_print_error_messages 2019-11-12 01:18:25.000000000 +0100 -+++ shadow-4.8.1/src/chsh.c 2021-05-24 13:04:19.931269132 +0200 -@@ -59,6 +59,7 @@ - * Global variables - */ - const char *Prog; /* Program name */ -+FILE *shadow_logfd = NULL; - static bool amroot; /* Real UID is root */ - static char loginsh[BUFSIZ]; /* Name of new login shell */ - /* command line options */ -@@ -441,6 +442,7 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/expiry.c.libsubid_not_print_error_messages shadow-4.8.1/src/expiry.c ---- shadow-4.8.1/src/expiry.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/expiry.c 2021-05-24 13:04:19.931269132 +0200 -@@ -46,6 +46,7 @@ - - /* Global variables */ - const char *Prog; -+FILE *shadow_logfd = NULL; - static bool cflg = false; - - /* local function prototypes */ -@@ -144,6 +145,7 @@ int main (int argc, char **argv) - struct spwd *spwd; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - sanitize_env (); - -diff -up shadow-4.8.1/src/faillog.c.libsubid_not_print_error_messages shadow-4.8.1/src/faillog.c ---- shadow-4.8.1/src/faillog.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 -+++ shadow-4.8.1/src/faillog.c 2021-05-24 13:04:19.932269146 +0200 -@@ -62,6 +62,7 @@ static void reset (void); - * Global variables - */ - const char *Prog; /* Program name */ -+FILE *shadow_logfd = NULL; - static FILE *fail; /* failure file stream */ - static time_t seconds; /* that number of days in seconds */ - static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ -@@ -573,6 +574,7 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/free_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/free_subid_range.c ---- shadow-4.8.1/src/free_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/src/free_subid_range.c 2021-05-24 13:04:19.932269146 +0200 -@@ -7,6 +7,7 @@ - /* Test program for the subid freeing routine */ - - const char *Prog; -+FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -23,6 +24,7 @@ int main(int argc, char *argv[]) - bool group = false; // get subuids by default - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - while ((c = getopt(argc, argv, "g")) != EOF) { - switch(c) { - case 'g': group = true; break; -diff -up shadow-4.8.1/src/get_subid_owners.c.libsubid_not_print_error_messages shadow-4.8.1/src/get_subid_owners.c ---- shadow-4.8.1/src/get_subid_owners.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/src/get_subid_owners.c 2021-05-24 13:04:19.932269146 +0200 -@@ -4,6 +4,7 @@ - #include "prototypes.h" - - const char *Prog; -+FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -19,6 +20,7 @@ int main(int argc, char *argv[]) - uid_t *uids; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - if (argc < 2) { - usage(); - } -diff -up shadow-4.8.1/src/gpasswd.c.libsubid_not_print_error_messages shadow-4.8.1/src/gpasswd.c ---- shadow-4.8.1/src/gpasswd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 -+++ shadow-4.8.1/src/gpasswd.c 2021-05-24 13:04:19.932269146 +0200 -@@ -58,6 +58,7 @@ - */ - /* The name of this command, as it is invoked */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - #ifdef SHADOWGRP - /* Indicate if shadow groups are enabled on the system -@@ -926,6 +927,7 @@ int main (int argc, char **argv) - */ - bywho = getuid (); - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - OPENLOG ("gpasswd"); - setbuf (stdout, NULL); -diff -up shadow-4.8.1/src/groupadd.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupadd.c ---- shadow-4.8.1/src/groupadd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 -+++ shadow-4.8.1/src/groupadd.c 2021-05-24 13:04:19.932269146 +0200 -@@ -72,6 +72,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static /*@null@*/char *group_name; - static gid_t group_id; -@@ -582,6 +583,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/groupdel.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupdel.c ---- shadow-4.8.1/src/groupdel.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 -+++ shadow-4.8.1/src/groupdel.c 2021-05-24 13:04:19.932269146 +0200 -@@ -58,6 +58,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static char *group_name; - static gid_t group_id = -1; -@@ -377,6 +378,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/groupmems.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupmems.c ---- shadow-4.8.1/src/groupmems.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/groupmems.c 2021-05-24 13:04:19.932269146 +0200 -@@ -65,6 +65,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static char *adduser = NULL; - static char *deluser = NULL; -@@ -595,6 +596,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/groupmod.c.libsubid_not_print_error_messages shadow-4.8.1/src/groupmod.c ---- shadow-4.8.1/src/groupmod.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 -+++ shadow-4.8.1/src/groupmod.c 2021-05-24 13:04:19.932269146 +0200 -@@ -76,6 +76,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - #ifdef SHADOWGRP - static bool is_shadow_grp; -@@ -799,6 +800,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/groups.c.libsubid_not_print_error_messages shadow-4.8.1/src/groups.c ---- shadow-4.8.1/src/groups.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/groups.c 2021-05-24 13:04:19.932269146 +0200 -@@ -43,6 +43,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - /* local function prototypes */ - static void print_groups (const char *member); -@@ -126,6 +127,7 @@ int main (int argc, char **argv) - * Get the program name so that error messages can use it. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - if (argc == 1) { - -diff -up shadow-4.8.1/src/grpck.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpck.c ---- shadow-4.8.1/src/grpck.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/grpck.c 2021-05-24 13:04:19.932269146 +0200 -@@ -68,6 +68,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static const char *grp_file = GROUP_FILE; - static bool use_system_grp_file = true; -@@ -836,6 +837,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/grpconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpconv.c ---- shadow-4.8.1/src/grpconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/grpconv.c 2021-05-24 13:04:19.932269146 +0200 -@@ -59,6 +59,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool gr_locked = false; - static bool sgr_locked = false; -@@ -146,6 +147,7 @@ int main (int argc, char **argv) - struct sgrp sgent; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/grpunconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/grpunconv.c ---- shadow-4.8.1/src/grpunconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/grpunconv.c 2021-05-24 13:04:19.932269146 +0200 -@@ -59,6 +59,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool gr_locked = false; - static bool sgr_locked = false; -@@ -145,6 +146,7 @@ int main (int argc, char **argv) - const struct sgrp *sg; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/lastlog.c.libsubid_not_print_error_messages shadow-4.8.1/src/lastlog.c ---- shadow-4.8.1/src/lastlog.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 -+++ shadow-4.8.1/src/lastlog.c 2021-05-24 13:04:19.932269146 +0200 -@@ -59,6 +59,7 @@ - * Global variables - */ - const char *Prog; /* Program name */ -+FILE *shadow_logfd = NULL; - static FILE *lastlogfile; /* lastlog file stream */ - static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ - static bool has_umin = false; -@@ -304,6 +305,7 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/list_subid_ranges.c.libsubid_not_print_error_messages shadow-4.8.1/src/list_subid_ranges.c ---- shadow-4.8.1/src/list_subid_ranges.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/src/list_subid_ranges.c 2021-05-24 13:04:19.932269146 +0200 -@@ -4,6 +4,7 @@ - #include "prototypes.h" - - const char *Prog; -+FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -19,6 +20,7 @@ int main(int argc, char *argv[]) - struct subordinate_range **ranges; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - if (argc < 2) { - usage(); - } -diff -up shadow-4.8.1/src/login.c.libsubid_not_print_error_messages shadow-4.8.1/src/login.c ---- shadow-4.8.1/src/login.c.libsubid_not_print_error_messages 2020-01-12 14:58:49.000000000 +0100 -+++ shadow-4.8.1/src/login.c 2021-05-24 13:04:19.933269160 +0200 -@@ -83,6 +83,7 @@ static pam_handle_t *pamh = NULL; - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static const char *hostname = ""; - static /*@null@*/ /*@only@*/char *username = NULL; -@@ -577,6 +578,7 @@ int main (int argc, char **argv) - - amroot = (getuid () == 0); - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - if (geteuid() != 0) { - fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog); -diff -up shadow-4.8.1/src/logoutd.c.libsubid_not_print_error_messages shadow-4.8.1/src/logoutd.c ---- shadow-4.8.1/src/logoutd.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/logoutd.c 2021-05-24 13:04:19.933269160 +0200 -@@ -44,6 +44,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - #ifndef DEFAULT_HUP_MESG - #define DEFAULT_HUP_MESG _("login time exceeded\n\n") -@@ -187,6 +188,7 @@ int main (int argc, char **argv) - * Start syslogging everything - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - OPENLOG ("logoutd"); - -diff -up shadow-4.8.1/src/newgidmap.c.libsubid_not_print_error_messages shadow-4.8.1/src/newgidmap.c ---- shadow-4.8.1/src/newgidmap.c.libsubid_not_print_error_messages 2019-10-13 04:52:08.000000000 +0200 -+++ shadow-4.8.1/src/newgidmap.c 2021-05-24 13:04:19.933269160 +0200 -@@ -45,6 +45,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - - static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups) -@@ -175,6 +176,7 @@ int main(int argc, char **argv) - bool allow_setgroups = false; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - /* - * The valid syntax are -diff -up shadow-4.8.1/src/newgrp.c.libsubid_not_print_error_messages shadow-4.8.1/src/newgrp.c ---- shadow-4.8.1/src/newgrp.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.906268788 +0200 -+++ shadow-4.8.1/src/newgrp.c 2021-05-24 14:45:30.372720097 +0200 -@@ -49,6 +49,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - extern char **newenvp; - extern char **environ; -@@ -444,6 +445,7 @@ int main (int argc, char **argv) - * don't need to re-exec anything. -- JWP - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - is_newgrp = (strcmp (Prog, "newgrp") == 0); - OPENLOG (is_newgrp ? "newgrp" : "sg"); - gid = getgid (); -diff -up shadow-4.8.1/src/new_subid_range.c.libsubid_not_print_error_messages shadow-4.8.1/src/new_subid_range.c ---- shadow-4.8.1/src/new_subid_range.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.926269063 +0200 -+++ shadow-4.8.1/src/new_subid_range.c 2021-05-24 13:04:19.933269160 +0200 -@@ -7,6 +7,7 @@ - /* Test program for the subid creation routine */ - - const char *Prog; -+FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -26,6 +27,7 @@ int main(int argc, char *argv[]) - bool ok; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - while ((c = getopt(argc, argv, "gn")) != EOF) { - switch(c) { - case 'n': makenew = true; break; -diff -up shadow-4.8.1/src/newuidmap.c.libsubid_not_print_error_messages shadow-4.8.1/src/newuidmap.c ---- shadow-4.8.1/src/newuidmap.c.libsubid_not_print_error_messages 2019-10-13 04:52:08.000000000 +0200 -+++ shadow-4.8.1/src/newuidmap.c 2021-05-24 13:04:19.933269160 +0200 -@@ -45,6 +45,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool verify_range(struct passwd *pw, struct map_range *range) - { -@@ -105,6 +106,7 @@ int main(int argc, char **argv) - int written; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - /* - * The valid syntax are -diff -up shadow-4.8.1/src/newusers.c.libsubid_not_print_error_messages shadow-4.8.1/src/newusers.c ---- shadow-4.8.1/src/newusers.c.libsubid_not_print_error_messages 2020-01-17 16:47:56.000000000 +0100 -+++ shadow-4.8.1/src/newusers.c 2021-05-24 13:04:19.933269160 +0200 -@@ -75,6 +75,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool rflg = false; /* create a system account */ - #ifndef USE_PAM -@@ -1040,6 +1041,7 @@ int main (int argc, char **argv) - #endif /* USE_PAM */ - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/passwd.c.libsubid_not_print_error_messages shadow-4.8.1/src/passwd.c ---- shadow-4.8.1/src/passwd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.910268843 +0200 -+++ shadow-4.8.1/src/passwd.c 2021-05-24 13:04:19.933269160 +0200 -@@ -66,6 +66,7 @@ - * Global variables - */ - const char *Prog; /* Program name */ -+FILE *shadow_logfd = NULL; - - static char *name; /* The name of user whose password is being changed */ - static char *myname; /* The current user's name */ -@@ -752,6 +753,7 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/pwck.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwck.c ---- shadow-4.8.1/src/pwck.c.libsubid_not_print_error_messages 2019-10-13 02:56:08.000000000 +0200 -+++ shadow-4.8.1/src/pwck.c 2021-05-24 13:04:19.933269160 +0200 -@@ -70,6 +70,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool use_system_pw_file = true; - static bool use_system_spw_file = true; -diff -up shadow-4.8.1/src/pwconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwconv.c ---- shadow-4.8.1/src/pwconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/pwconv.c 2021-05-24 13:04:19.933269160 +0200 -@@ -89,6 +89,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool spw_locked = false; - static bool pw_locked = false; -@@ -176,6 +177,7 @@ int main (int argc, char **argv) - struct spwd spent; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/pwunconv.c.libsubid_not_print_error_messages shadow-4.8.1/src/pwunconv.c ---- shadow-4.8.1/src/pwunconv.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/pwunconv.c 2021-05-24 13:04:19.933269160 +0200 -@@ -53,6 +53,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static bool spw_locked = false; - static bool pw_locked = false; -@@ -137,6 +138,7 @@ int main (int argc, char **argv) - const struct spwd *spwd; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/su.c.libsubid_not_print_error_messages shadow-4.8.1/src/su.c ---- shadow-4.8.1/src/su.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/su.c 2021-05-24 13:04:19.934269173 +0200 -@@ -82,6 +82,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */ - static bool caller_is_root = false; - static uid_t caller_uid; -@@ -699,6 +700,7 @@ static void save_caller_context (char ** - * most error messages. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - caller_uid = getuid (); - caller_is_root = (caller_uid == 0); -diff -up shadow-4.8.1/src/sulogin.c.libsubid_not_print_error_messages shadow-4.8.1/src/sulogin.c ---- shadow-4.8.1/src/sulogin.c.libsubid_not_print_error_messages 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/sulogin.c 2021-05-24 13:04:19.934269173 +0200 -@@ -50,6 +50,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static char name[BUFSIZ]; - static char pass[BUFSIZ]; -@@ -106,6 +107,7 @@ static RETSIGTYPE catch_signals (unused - #endif - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); -diff -up shadow-4.8.1/src/useradd.c.libsubid_not_print_error_messages shadow-4.8.1/src/useradd.c ---- shadow-4.8.1/src/useradd.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.918268953 +0200 -+++ shadow-4.8.1/src/useradd.c 2021-05-24 13:04:19.934269173 +0200 -@@ -92,6 +92,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - /* - * These defaults are used if there is no defaults file. -@@ -2301,6 +2302,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/userdel.c.libsubid_not_print_error_messages shadow-4.8.1/src/userdel.c ---- shadow-4.8.1/src/userdel.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.907268801 +0200 -+++ shadow-4.8.1/src/userdel.c 2021-05-24 13:04:19.934269173 +0200 -@@ -89,6 +89,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static char *user_name; - static uid_t user_id; -@@ -941,6 +942,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); -diff -up shadow-4.8.1/src/usermod.c.libsubid_not_print_error_messages shadow-4.8.1/src/usermod.c ---- shadow-4.8.1/src/usermod.c.libsubid_not_print_error_messages 2021-05-24 13:04:19.917268939 +0200 -+++ shadow-4.8.1/src/usermod.c 2021-05-24 13:04:19.934269173 +0200 -@@ -102,6 +102,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static char *user_name; - static char *user_newname; -@@ -2214,6 +2215,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.8.1/src/vipw.c.libsubid_not_print_error_messages shadow-4.8.1/src/vipw.c ---- shadow-4.8.1/src/vipw.c.libsubid_not_print_error_messages 2019-12-01 17:52:32.000000000 +0100 -+++ shadow-4.8.1/src/vipw.c 2021-05-24 13:04:19.934269173 +0200 -@@ -63,6 +63,7 @@ - * Global variables - */ - const char *Prog; -+FILE *shadow_logfd = NULL; - - static const char *filename, *fileeditname; - static bool filelocked = false; -@@ -481,6 +482,7 @@ int main (int argc, char **argv) - bool do_vipw; - - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); diff --git a/shadow-4.8.1-libsubid_nsswitch_support.patch b/shadow-4.8.1-libsubid_nsswitch_support.patch deleted file mode 100644 index eafa7c1..0000000 --- a/shadow-4.8.1-libsubid_nsswitch_support.patch +++ /dev/null @@ -1,2107 +0,0 @@ -From 514c1328b6c90d817ae0a9f7addfb3c9a11a275a Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sun, 31 Jan 2021 22:44:09 -0600 -Subject: [PATCH 1/6] try again to fix libmisc sharing problem - -Issue #297 reported seeing - -*** Warning: Linking the shared library libsubid.la against the -*** static library ../libmisc/libmisc.a is not portable! - -which commit b5fb1b38eea2fb0489ed088c82daf6700e72363e was supposed -to fix. But a few commits later it's back. So try to fix it -in the way the bug reporter suggested. This broke builds some -other ways, namely a few missing library specifications, so add -those. - -Signed-off-by: Serge Hallyn ---- - configure.ac | 2 +- - libmisc/Makefile.am | 6 +++--- - libsubid/Makefile.am | 6 ++++-- - src/Makefile.am | 37 +++++++++++++++++++++++-------------- - 4 files changed, 31 insertions(+), 20 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 6aaae6b7..7884bfb6 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -55,7 +55,7 @@ AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ - gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ - lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ - getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \ -- ruserok) -+ ruserok dlopen) - AC_SYS_LARGEFILE - - dnl Checks for typedefs, structures, and compiler characteristics. -diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am -index 7f43161f..9766a7ec 100644 ---- a/libmisc/Makefile.am -+++ b/libmisc/Makefile.am -@@ -3,9 +3,9 @@ EXTRA_DIST = .indent.pro xgetXXbyYY.c - - AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECONF_CPPFLAGS) - --noinst_LIBRARIES = libmisc.a -+noinst_LTLIBRARIES = libmisc.la - --libmisc_a_SOURCES = \ -+libmisc_la_SOURCES = \ - addgrps.c \ - age.c \ - audit_help.c \ -@@ -74,6 +74,6 @@ libmisc_a_SOURCES = \ - yesno.c - - if WITH_BTRFS --libmisc_a_SOURCES += btrfs.c -+libmisc_la_SOURCES += btrfs.c - endif - -diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am -index 8bef1ecc..f24dbb94 100644 ---- a/libsubid/Makefile.am -+++ b/libsubid/Makefile.am -@@ -12,12 +12,14 @@ MISCLIBS = \ - $(LIBMD) \ - $(LIBECONF) \ - $(LIBCRYPT) \ -+ $(LIBACL) \ -+ $(LIBATTR) \ - $(LIBTCB) - - libsubid_la_LIBADD = \ - $(top_srcdir)/lib/libshadow.la \ -- $(MISCLIBS) \ -- $(top_srcdir)/libmisc/libmisc.a -+ $(top_srcdir)/libmisc/libmisc.la \ -+ $(MISCLIBS) - - AM_CPPFLAGS = \ - -I${top_srcdir}/lib \ -diff --git a/src/Makefile.am b/src/Makefile.am -index 8499ce08..e9d354fd 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -78,7 +78,7 @@ shadowsgidubins = passwd - endif - - LDADD = $(INTLLIBS) \ -- $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/lib/libshadow.la \ - $(LIBTCB) - -@@ -95,28 +95,37 @@ LIBCRYPT_NOPAM = $(LIBCRYPT) - endif - - chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) --newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) --newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -+newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl -+newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl - chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) - chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) - chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) - chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) - expiry_LDADD = $(LDADD) $(LIBECONF) - gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) --groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) --groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -+groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl -+groupdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl - groupmems_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) --groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -+groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl - grpck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - grpconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - grpunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF) -+newuidmap_SOURCES = newuidmap.c ../libmisc/nss.c -+newgidmap_SOURCES = newgidmap.c ../libmisc/nss.c -+groupadd_SOURCES = groupadd.c ../libmisc/nss.c -+groupmod_SOURCES = groupmod.c ../libmisc/nss.c -+groupdel_SOURCES = groupdel.c ../libmisc/nss.c -+newusers_SOURCES = newusers.c ../libmisc/nss.c -+useradd_SOURCES = useradd.c ../libmisc/nss.c -+usermod_SOURCES = usermod.c ../libmisc/nss.c -+userdel_SOURCES = userdel.c ../libmisc/nss.c - login_SOURCES = \ - login.c \ - login_nopam.c - login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) - newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF) --newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -+newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl - nologin_LDADD = - passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) - pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -@@ -127,9 +136,9 @@ su_SOURCES = \ - suauth.c - su_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) - sulogin_LDADD = $(LDADD) $(LIBCRYPT) $(LIBECONF) --useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) --userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) --usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -+useradd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl -+userdel_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBECONF) -ldl -+usermod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBSEMANAGE) $(LIBACL) $(LIBATTR) $(LIBECONF) -ldl - vipw_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - - install-am: all-am -@@ -175,7 +184,7 @@ MISCLIBS = \ - - list_subid_ranges_LDADD = \ - $(top_builddir)/lib/libshadow.la \ -- $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ - $(MISCLIBS) - -@@ -186,7 +195,7 @@ list_subid_ranges_CPPFLAGS = \ - - get_subid_owners_LDADD = \ - $(top_builddir)/lib/libshadow.la \ -- $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ - $(MISCLIBS) - -@@ -202,7 +211,7 @@ new_subid_range_CPPFLAGS = \ - - new_subid_range_LDADD = \ - $(top_builddir)/lib/libshadow.la \ -- $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ - $(MISCLIBS) - -@@ -213,7 +222,7 @@ free_subid_range_CPPFLAGS = \ - - free_subid_range_LDADD = \ - $(top_builddir)/lib/libshadow.la \ -- $(top_builddir)/libmisc/libmisc.a \ -+ $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ - $(MISCLIBS) - endif --- -2.30.2 - - -From 8492dee6632e340dee76eee895c3e30877bebf45 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sun, 31 Jan 2021 17:38:20 -0600 -Subject: [PATCH 2/6] subids: support nsswitch - -Closes #154 - -When starting any operation to do with subuid delegation, check -nsswitch for a module to use. If none is specified, then use -the traditional /etc/subuid and /etc/subgid files. - -Currently only one module is supported, and there is no fallback -to the files on errors. Several possibilities could be considered: - -1. in case of connection error, fall back to files -2. in case of unknown user, also fall back to files - -etc... - -When non-files nss module is used, functions to edit the range -are not supported. It may make sense to support it, but it also -may make sense to require another tool to be used. - -libsubordinateio also uses the nss_ helpers. This is how for instance -lxc could easily be converted to supporting nsswitch. - -Add a set of test cases, including a dummy libsubid_zzz module. This -hardcodes values such that: - -'ubuntu' gets 200000 - 300000 -'user1' gets 100000 - 165536 -'error' emulates an nss module error -'unknown' emulates a user unknown to the nss module -'conn' emulates a connection error ot the nss module - -Changes to libsubid: - -Change the list_owner_ranges api: return a count instead of making the array -null terminated. - -This is a breaking change, so bump the libsubid abi major number. - -Rename free_subuid_range and free_subgid_range to ungrant_subuid_range, -because otherwise it's confusing with free_subid_ranges which frees - memory. - -Run libsubid tests in jenkins - -Switch argument order in find_subid_owners - -Move the db locking into subordinateio.c - -Signed-off-by: Serge Hallyn ---- - configure.ac | 2 +- - lib/Makefile.am | 1 + - lib/nss.c | 157 ++++++++++++++++ - lib/prototypes.h | 69 ++++++++ - lib/subordinateio.c | 256 ++++++++++++++++++++++++--- - lib/subordinateio.h | 6 +- - libmisc/idmapping.h | 2 + - libsubid/Makefile.am | 2 +- - libsubid/api.c | 168 +++--------------- - libsubid/api.h | 10 +- - libsubid/subid.h | 8 + - src/Makefile.am | 29 +-- - src/check_subid_range.c | 48 +++++ - src/free_subid_range.c | 4 +- - src/list_subid_ranges.c | 10 +- - tests/libsubid/04_nss/Makefile | 12 ++ - tests/libsubid/04_nss/empty | 0 - tests/libsubid/04_nss/libsubid_zzz.c | 146 +++++++++++++++ - tests/libsubid/04_nss/nsswitch1.conf | 20 +++ - tests/libsubid/04_nss/nsswitch2.conf | 22 +++ - tests/libsubid/04_nss/nsswitch3.conf | 22 +++ - tests/libsubid/04_nss/subidnss.test | 22 +++ - tests/libsubid/04_nss/test_nss.c | 72 ++++++++ - tests/libsubid/04_nss/test_range | 50 ++++++ - tests/run_some | 1 + - 26 files changed, 935 insertions(+), 205 deletions(-) - create mode 100644 lib/nss.c - create mode 100644 src/check_subid_range.c - create mode 100644 tests/libsubid/04_nss/Makefile - create mode 100644 tests/libsubid/04_nss/empty - create mode 100644 tests/libsubid/04_nss/libsubid_zzz.c - create mode 100644 tests/libsubid/04_nss/nsswitch1.conf - create mode 100644 tests/libsubid/04_nss/nsswitch2.conf - create mode 100644 tests/libsubid/04_nss/nsswitch3.conf - create mode 100755 tests/libsubid/04_nss/subidnss.test - create mode 100644 tests/libsubid/04_nss/test_nss.c - create mode 100755 tests/libsubid/04_nss/test_range - -diff --git a/configure.ac b/configure.ac -index 7884bfb6..7f7e8784 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1,6 +1,6 @@ - dnl Process this file with autoconf to produce a configure script. - AC_PREREQ([2.69]) --m4_define([libsubid_abi_major], 1) -+m4_define([libsubid_abi_major], 2) - m4_define([libsubid_abi_minor], 0) - m4_define([libsubid_abi_micro], 0) - m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) -diff --git a/lib/Makefile.am b/lib/Makefile.am -index bd9d6bfb..ecf3ee25 100644 ---- a/lib/Makefile.am -+++ b/lib/Makefile.am -@@ -31,6 +31,7 @@ libshadow_la_SOURCES = \ - groupio.h \ - gshadow.c \ - lockpw.c \ -+ nss.c \ - nscd.c \ - nscd.h \ - sssd.c \ -diff --git a/lib/nss.c b/lib/nss.c -new file mode 100644 -index 00000000..2f924740 ---- /dev/null -+++ b/lib/nss.c -@@ -0,0 +1,157 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "prototypes.h" -+#include "../libsubid/subid.h" -+ -+#define NSSWITCH "/etc/nsswitch.conf" -+ -+// NSS plugin handling for subids -+// If nsswitch has a line like -+// subid: sssd -+// then sssd will be consulted for subids. Unlike normal NSS dbs, -+// only one db is supported at a time. That's open to debate, but -+// the subids are a pretty limited resource, and local files seem -+// bound to step on any other allocations leading to insecure -+// conditions. -+static atomic_flag nss_init_started; -+static atomic_bool nss_init_completed; -+ -+static struct subid_nss_ops *subid_nss; -+ -+bool nss_is_initialized() { -+ return atomic_load(&nss_init_completed); -+} -+ -+void nss_exit() { -+ if (nss_is_initialized() && subid_nss) { -+ dlclose(subid_nss->handle); -+ free(subid_nss); -+ subid_nss = NULL; -+ } -+} -+ -+// nsswitch_path is an argument only to support testing. -+void nss_init(char *nsswitch_path) { -+ FILE *nssfp = NULL; -+ char *line = NULL, *p, *token, *saveptr; -+ size_t len = 0; -+ -+ if (atomic_flag_test_and_set(&nss_init_started)) { -+ // Another thread has started nss_init, wait for it to complete -+ while (!atomic_load(&nss_init_completed)) -+ usleep(100); -+ return; -+ } -+ -+ if (!nsswitch_path) -+ nsswitch_path = NSSWITCH; -+ -+ // read nsswitch.conf to check for a line like: -+ // subid: files -+ nssfp = fopen(nsswitch_path, "r"); -+ if (!nssfp) { -+ fprintf(stderr, "Failed opening %s: %m", nsswitch_path); -+ atomic_store(&nss_init_completed, true); -+ return; -+ } -+ while ((getline(&line, &len, nssfp)) != -1) { -+ if (line[0] == '\0' || line[0] == '#') -+ continue; -+ if (strlen(line) < 8) -+ continue; -+ if (strncasecmp(line, "subid:", 6) != 0) -+ continue; -+ p = &line[6]; -+ while ((*p) && isspace(*p)) -+ p++; -+ if (!*p) -+ continue; -+ for (token = strtok_r(p, " \n\t", &saveptr); -+ token; -+ token = strtok_r(NULL, " \n\t", &saveptr)) { -+ char libname[65]; -+ void *h; -+ if (strcmp(token, "files") == 0) { -+ subid_nss = NULL; -+ goto done; -+ } -+ if (strlen(token) > 50) { -+ fprintf(stderr, "Subid NSS module name too long (longer than 50 characters): %s\n", token); -+ fprintf(stderr, "Using files\n"); -+ subid_nss = NULL; -+ goto done; -+ } -+ snprintf(libname, 64, "libsubid_%s.so", token); -+ h = dlopen(libname, RTLD_LAZY); -+ if (!h) { -+ fprintf(stderr, "Error opening %s: %s\n", libname, dlerror()); -+ fprintf(stderr, "Using files\n"); -+ subid_nss = NULL; -+ goto done; -+ } -+ subid_nss = malloc(sizeof(*subid_nss)); -+ if (!subid_nss) { -+ dlclose(h); -+ goto done; -+ } -+ subid_nss->has_range = dlsym(h, "shadow_subid_has_range"); -+ if (!subid_nss->has_range) { -+ fprintf(stderr, "%s did not provide @has_range@\n", libname); -+ dlclose(h); -+ free(subid_nss); -+ subid_nss = NULL; -+ goto done; -+ } -+ subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges"); -+ if (!subid_nss->list_owner_ranges) { -+ fprintf(stderr, "%s did not provide @list_owner_ranges@\n", libname); -+ dlclose(h); -+ free(subid_nss); -+ subid_nss = NULL; -+ goto done; -+ } -+ subid_nss->has_any_range = dlsym(h, "shadow_subid_has_any_range"); -+ if (!subid_nss->has_any_range) { -+ fprintf(stderr, "%s did not provide @has_any_range@\n", libname); -+ dlclose(h); -+ free(subid_nss); -+ subid_nss = NULL; -+ goto done; -+ } -+ subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners"); -+ if (!subid_nss->find_subid_owners) { -+ fprintf(stderr, "%s did not provide @find_subid_owners@\n", libname); -+ dlclose(h); -+ free(subid_nss); -+ subid_nss = NULL; -+ goto done; -+ } -+ subid_nss->handle = h; -+ goto done; -+ } -+ fprintf(stderr, "No usable subid NSS module found, using files\n"); -+ // subid_nss has to be null here, but to ease reviews: -+ free(subid_nss); -+ subid_nss = NULL; -+ goto done; -+ } -+ -+done: -+ atomic_store(&nss_init_completed, true); -+ free(line); -+ if (nssfp) { -+ atexit(nss_exit); -+ fclose(nssfp); -+ } -+} -+ -+struct subid_nss_ops *get_subid_nss_handle() { -+ nss_init(NULL); -+ return subid_nss; -+} -diff --git a/lib/prototypes.h b/lib/prototypes.h -index ac9ad274..0c42bcc2 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -262,6 +262,75 @@ extern void motd (void); - /* myname.c */ - extern /*@null@*//*@only@*/struct passwd *get_my_pwent (void); - -+/* nss.c */ -+#include -+extern void nss_init(char *nsswitch_path); -+extern bool nss_is_initialized(); -+ -+struct subid_nss_ops { -+ /* -+ * nss_has_any_range: does a user own any subid range -+ * -+ * @owner: username -+ * @idtype: subuid or subgid -+ * @result: true if a subid allocation was found for @owner -+ * -+ * returns success if the module was able to determine an answer (true or false), -+ * else an error status. -+ */ -+ enum subid_status (*has_any_range)(const char *owner, enum subid_type idtype, bool *result); -+ -+ /* -+ * nss_has_range: does a user own a given subid range -+ * -+ * @owner: username -+ * @start: first subid in queried range -+ * @count: number of subids in queried range -+ * @idtype: subuid or subgid -+ * @result: true if @owner has been allocated the subid range. -+ * -+ * returns success if the module was able to determine an answer (true or false), -+ * else an error status. -+ */ -+ enum subid_status (*has_range)(const char *owner, unsigned long start, unsigned long count, enum subid_type idtype, bool *result); -+ -+ /* -+ * nss_list_owner_ranges: list the subid ranges delegated to a user. -+ * -+ * @owner - string representing username being queried -+ * @id_type - subuid or subgid -+ * @ranges - pointer to an array of struct subordinate_range pointers, or -+ * NULL. The returned array of struct subordinate_range and its -+ * members must be freed by the caller. -+ * @count - pointer to an integer into which the number of returned ranges -+ * is written. -+ -+ * returns success if the module was able to determine an answer, -+ * else an error status. -+ */ -+ enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges, int *count); -+ -+ /* -+ * nss_find_subid_owners: find uids who own a given subuid or subgid. -+ * -+ * @id - the delegated id (subuid or subgid) being queried -+ * @id_type - subuid or subgid -+ * @uids - pointer to an array of uids which will be allocated by -+ * nss_find_subid_owners() -+ * @count - number of uids found -+ * -+ * returns success if the module was able to determine an answer, -+ * else an error status. -+ */ -+ enum subid_status (*find_subid_owners)(unsigned long id, enum subid_type id_type, uid_t **uids, int *count); -+ -+ /* The dlsym handle to close */ -+ void *handle; -+}; -+ -+extern struct subid_nss_ops *get_subid_nss_handle(); -+ -+ - /* pam_pass_non_interactive.c */ - #ifdef USE_PAM - extern int do_pam_passwd_non_interactive (const char *pam_service, -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 67202c98..0bb29958 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - /* - * subordinate_dup: create a duplicate range -@@ -311,17 +312,17 @@ static bool append_range(struct subordinate_range ***ranges, const struct subord - { - struct subordinate_range *tmp; - if (!*ranges) { -- *ranges = malloc(2 * sizeof(struct subordinate_range **)); -+ *ranges = malloc(sizeof(struct subordinate_range *)); - if (!*ranges) - return false; - } else { - struct subordinate_range **new; -- new = realloc(*ranges, (n + 2) * (sizeof(struct subordinate_range **))); -+ new = realloc(*ranges, (n + 1) * (sizeof(struct subordinate_range *))); - if (!new) - return false; - *ranges = new; - } -- (*ranges)[n] = (*ranges)[n+1] = NULL; -+ (*ranges)[n] = NULL; - tmp = subordinate_dup(new); - if (!tmp) - return false; -@@ -329,13 +330,13 @@ static bool append_range(struct subordinate_range ***ranges, const struct subord - return true; - } - --void free_subordinate_ranges(struct subordinate_range **ranges) -+void free_subordinate_ranges(struct subordinate_range **ranges, int count) - { - int i; - - if (!ranges) - return; -- for (i = 0; ranges[i]; i++) -+ for (i = 0; i < count; i++) - subordinate_free(ranges[i]); - free(ranges); - } -@@ -602,21 +603,46 @@ int sub_uid_open (int mode) - - bool sub_uid_assigned(const char *owner) - { -+ struct subid_nss_ops *h; -+ bool found; -+ enum subid_status status; -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->has_any_range(owner, ID_TYPE_UID, &found); -+ if (status == SUBID_STATUS_SUCCESS && found) -+ return true; -+ return false; -+ } -+ - return range_exists (&subordinate_uid_db, owner); - } - - bool have_sub_uids(const char *owner, uid_t start, unsigned long count) - { -+ struct subid_nss_ops *h; -+ bool found; -+ enum subid_status status; -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->has_range(owner, start, count, ID_TYPE_UID, &found); -+ if (status == SUBID_STATUS_SUCCESS && found) -+ return true; -+ return false; -+ } - return have_range (&subordinate_uid_db, owner, start, count); - } - - int sub_uid_add (const char *owner, uid_t start, unsigned long count) - { -+ if (get_subid_nss_handle()) -+ return -EOPNOTSUPP; - return add_range (&subordinate_uid_db, owner, start, count); - } - - int sub_uid_remove (const char *owner, uid_t start, unsigned long count) - { -+ if (get_subid_nss_handle()) -+ return -EOPNOTSUPP; - return remove_range (&subordinate_uid_db, owner, start, count); - } - -@@ -684,21 +710,45 @@ int sub_gid_open (int mode) - - bool have_sub_gids(const char *owner, gid_t start, unsigned long count) - { -+ struct subid_nss_ops *h; -+ bool found; -+ enum subid_status status; -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->has_range(owner, start, count, ID_TYPE_GID, &found); -+ if (status == SUBID_STATUS_SUCCESS && found) -+ return true; -+ return false; -+ } - return have_range(&subordinate_gid_db, owner, start, count); - } - - bool sub_gid_assigned(const char *owner) - { -+ struct subid_nss_ops *h; -+ bool found; -+ enum subid_status status; -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->has_any_range(owner, ID_TYPE_GID, &found); -+ if (status == SUBID_STATUS_SUCCESS && found) -+ return true; -+ return false; -+ } - return range_exists (&subordinate_gid_db, owner); - } - - int sub_gid_add (const char *owner, gid_t start, unsigned long count) - { -+ if (get_subid_nss_handle()) -+ return -EOPNOTSUPP; - return add_range (&subordinate_gid_db, owner, start, count); - } - - int sub_gid_remove (const char *owner, gid_t start, unsigned long count) - { -+ if (get_subid_nss_handle()) -+ return -EOPNOTSUPP; - return remove_range (&subordinate_gid_db, owner, start, count); - } - -@@ -720,42 +770,78 @@ gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) - } - - /* -- struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) -+ * int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) - * - * @owner: username - * @id_type: UID or GUID -+ * @ranges: pointer to array of ranges into which results will be placed. - * -- * Returns the subuid or subgid ranges which are owned by the specified -+ * Fills in the subuid or subgid ranges which are owned by the specified - * user. Username may be a username or a string representation of a - * UID number. If id_type is UID, then subuids are returned, else -- * subgids are returned. If there is an error, < 0 is returned. -+ * subgids are given. -+ -+ * Returns the number of ranges found, or < 0 on error. - * - * The caller must free the subordinate range list. - */ --struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type) -+int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges) - { - // TODO - need to handle owner being either uid or username -- const struct subordinate_range *range; - struct subordinate_range **ranges = NULL; -+ const struct subordinate_range *range; - struct commonio_db *db; -- int size = 0; -+ enum subid_status status; -+ int count = 0; -+ struct subid_nss_ops *h; - -- if (id_type == ID_TYPE_UID) -+ *in_ranges = NULL; -+ -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->list_owner_ranges(owner, id_type, in_ranges, &count); -+ if (status == SUBID_STATUS_SUCCESS) -+ return count; -+ return -1; -+ } -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_open(O_RDONLY)) { -+ return -1; -+ } - db = &subordinate_uid_db; -- else -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_open(O_RDONLY)) { -+ return -1; -+ } - db = &subordinate_gid_db; -+ break; -+ default: -+ return -1; -+ } - - commonio_rewind(db); - while ((range = commonio_next(db)) != NULL) { - if (0 == strcmp(range->owner, owner)) { -- if (!append_range(&ranges, range, size++)) { -- free_subordinate_ranges(ranges); -- return NULL; -+ if (!append_range(&ranges, range, count++)) { -+ free_subordinate_ranges(ranges, count-1); -+ ranges = NULL; -+ count = -1; -+ goto out; - } - } - } - -- return ranges; -+out: -+ if (id_type == ID_TYPE_UID) -+ sub_uid_close(); -+ else -+ sub_gid_close(); -+ -+ *in_ranges = ranges; -+ return count; - } - - static bool all_digits(const char *str) -@@ -808,17 +894,41 @@ static int append_uids(uid_t **uids, const char *owner, int n) - return n+1; - } - --int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) -+int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) - { - const struct subordinate_range *range; -+ struct subid_nss_ops *h; -+ enum subid_status status; - struct commonio_db *db; - int n = 0; - -- *uids = NULL; -- if (id_type == ID_TYPE_UID) -+ h = get_subid_nss_handle(); -+ if (h) { -+ status = h->find_subid_owners(id, id_type, uids, &n); -+ // Several ways we could handle the error cases here. -+ if (status != SUBID_STATUS_SUCCESS) -+ return -1; -+ return n; -+ } -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_open(O_RDONLY)) { -+ return -1; -+ } - db = &subordinate_uid_db; -- else -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_open(O_RDONLY)) { -+ return -1; -+ } - db = &subordinate_gid_db; -+ break; -+ default: -+ return -1; -+ } -+ -+ *uids = NULL; - - commonio_rewind(db); - while ((range = commonio_next(db)) != NULL) { -@@ -829,6 +939,11 @@ int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type) - } - } - -+ if (id_type == ID_TYPE_UID) -+ sub_uid_close(); -+ else -+ sub_gid_close(); -+ - return n; - } - -@@ -836,11 +951,40 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - { - struct commonio_db *db; - const struct subordinate_range *r; -+ bool ret; - -- if (id_type == ID_TYPE_UID) -+ if (get_subid_nss_handle()) -+ return false; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_lock()) { -+ printf("Failed loging subuids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_uid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subuids (errno %d)\n", errno); -+ sub_uid_unlock(); -+ return false; -+ } - db = &subordinate_uid_db; -- else -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_lock()) { -+ printf("Failed loging subgids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_gid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subgids (errno %d)\n", errno); -+ sub_gid_unlock(); -+ return false; -+ } - db = &subordinate_gid_db; -+ break; -+ default: -+ return false; -+ } -+ - commonio_rewind(db); - if (reuse) { - while ((r = commonio_next(db)) != NULL) { -@@ -856,20 +1000,74 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - } - - range->start = find_free_range(db, range->start, ULONG_MAX, range->count); -- if (range->start == ULONG_MAX) -- return false; - -- return add_range(db, range->owner, range->start, range->count) == 1; -+ if (range->start == ULONG_MAX) { -+ ret = false; -+ goto out; -+ } -+ -+ ret = add_range(db, range->owner, range->start, range->count) == 1; -+ -+out: -+ if (id_type == ID_TYPE_UID) { -+ sub_uid_close(); -+ sub_uid_unlock(); -+ } else { -+ sub_gid_close(); -+ sub_gid_unlock(); -+ } -+ -+ return ret; - } - - bool release_subid_range(struct subordinate_range *range, enum subid_type id_type) - { - struct commonio_db *db; -- if (id_type == ID_TYPE_UID) -+ bool ret; -+ -+ if (get_subid_nss_handle()) -+ return false; -+ -+ switch (id_type) { -+ case ID_TYPE_UID: -+ if (!sub_uid_lock()) { -+ printf("Failed loging subuids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_uid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subuids (errno %d)\n", errno); -+ sub_uid_unlock(); -+ return false; -+ } - db = &subordinate_uid_db; -- else -+ break; -+ case ID_TYPE_GID: -+ if (!sub_gid_lock()) { -+ printf("Failed loging subgids (errno %d)\n", errno); -+ return false; -+ } -+ if (!sub_gid_open(O_CREAT | O_RDWR)) { -+ printf("Failed opening subgids (errno %d)\n", errno); -+ sub_gid_unlock(); -+ return false; -+ } - db = &subordinate_gid_db; -- return remove_range(db, range->owner, range->start, range->count) == 1; -+ break; -+ default: -+ return false; -+ } -+ -+ ret = remove_range(db, range->owner, range->start, range->count) == 1; -+ -+ if (id_type == ID_TYPE_UID) { -+ sub_uid_close(); -+ sub_uid_unlock(); -+ } else { -+ sub_gid_close(); -+ sub_gid_unlock(); -+ } -+ -+ return ret; - } - - #else /* !ENABLE_SUBIDS */ -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index 13a21341..e4be482c 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -25,11 +25,11 @@ extern int sub_uid_unlock (void); - extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); - extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); - extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); --extern struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type); -+extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges); - extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); - extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); --extern int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type); --extern void free_subordinate_ranges(struct subordinate_range **ranges); -+extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); -+extern void free_subordinate_ranges(struct subordinate_range **ranges, int count); - - extern int sub_gid_close(void); - extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); -diff --git a/libmisc/idmapping.h b/libmisc/idmapping.h -index 3f32db68..1a8efe68 100644 ---- a/libmisc/idmapping.h -+++ b/libmisc/idmapping.h -@@ -40,5 +40,7 @@ extern struct map_range *get_map_ranges(int ranges, int argc, char **argv); - extern void write_mapping(int proc_dir_fd, int ranges, - struct map_range *mappings, const char *map_file, uid_t ruid); - -+extern void nss_init(char *nsswitch_path); -+ - #endif /* _ID_MAPPING_H_ */ - -diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am -index f24dbb94..f543b5eb 100644 ---- a/libsubid/Makefile.am -+++ b/libsubid/Makefile.am -@@ -19,7 +19,7 @@ MISCLIBS = \ - libsubid_la_LIBADD = \ - $(top_srcdir)/lib/libshadow.la \ - $(top_srcdir)/libmisc/libmisc.la \ -- $(MISCLIBS) -+ $(MISCLIBS) -ldl - - AM_CPPFLAGS = \ - -I${top_srcdir}/lib \ -diff --git a/libsubid/api.c b/libsubid/api.c -index 91d73bed..737e1c8b 100644 ---- a/libsubid/api.c -+++ b/libsubid/api.c -@@ -38,132 +38,48 @@ - #include "idmapping.h" - #include "api.h" - --static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type) -+static -+int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) - { -- struct subordinate_range **ranges = NULL; -- -- switch (id_type) { -- case ID_TYPE_UID: -- if (!sub_uid_open(O_RDONLY)) { -- return NULL; -- } -- break; -- case ID_TYPE_GID: -- if (!sub_gid_open(O_RDONLY)) { -- return NULL; -- } -- break; -- default: -- return NULL; -- } -- -- ranges = list_owner_ranges(owner, id_type); -- -- if (id_type == ID_TYPE_UID) -- sub_uid_close(); -- else -- sub_gid_close(); -- -- return ranges; -+ return list_owner_ranges(owner, id_type, ranges); - } - --struct subordinate_range **get_subuid_ranges(const char *owner) -+int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges) - { -- return get_subid_ranges(owner, ID_TYPE_UID); -+ return get_subid_ranges(owner, ID_TYPE_UID, ranges); - } - --struct subordinate_range **get_subgid_ranges(const char *owner) -+int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges) - { -- return get_subid_ranges(owner, ID_TYPE_GID); -+ return get_subid_ranges(owner, ID_TYPE_GID, ranges); - } - --void subid_free_ranges(struct subordinate_range **ranges) -+void subid_free_ranges(struct subordinate_range **ranges, int count) - { -- return free_subordinate_ranges(ranges); -+ return free_subordinate_ranges(ranges, count); - } - --int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type) -+static -+int get_subid_owner(unsigned long id, enum subid_type id_type, uid_t **owner) - { -- int ret = -1; -- -- switch (id_type) { -- case ID_TYPE_UID: -- if (!sub_uid_open(O_RDONLY)) { -- return -1; -- } -- break; -- case ID_TYPE_GID: -- if (!sub_gid_open(O_RDONLY)) { -- return -1; -- } -- break; -- default: -- return -1; -- } -- -- ret = find_subid_owners(id, owner, id_type); -- -- if (id_type == ID_TYPE_UID) -- sub_uid_close(); -- else -- sub_gid_close(); -- -- return ret; -+ return find_subid_owners(id, id_type, owner); - } - - int get_subuid_owners(uid_t uid, uid_t **owner) - { -- return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID); -+ return get_subid_owner((unsigned long)uid, ID_TYPE_UID, owner); - } - - int get_subgid_owners(gid_t gid, uid_t **owner) - { -- return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID); -+ return get_subid_owner((unsigned long)gid, ID_TYPE_GID, owner); - } - -+static - bool grant_subid_range(struct subordinate_range *range, bool reuse, - enum subid_type id_type) - { -- bool ret; -- -- switch (id_type) { -- case ID_TYPE_UID: -- if (!sub_uid_lock()) { -- printf("Failed loging subuids (errno %d)\n", errno); -- return false; -- } -- if (!sub_uid_open(O_CREAT | O_RDWR)) { -- printf("Failed opening subuids (errno %d)\n", errno); -- sub_uid_unlock(); -- return false; -- } -- break; -- case ID_TYPE_GID: -- if (!sub_gid_lock()) { -- printf("Failed loging subgids (errno %d)\n", errno); -- return false; -- } -- if (!sub_gid_open(O_CREAT | O_RDWR)) { -- printf("Failed opening subgids (errno %d)\n", errno); -- sub_gid_unlock(); -- return false; -- } -- break; -- default: -- return false; -- } -- -- ret = new_subid_range(range, id_type, reuse); -- -- if (id_type == ID_TYPE_UID) { -- sub_uid_close(); -- sub_uid_unlock(); -- } else { -- sub_gid_close(); -- sub_gid_unlock(); -- } -- -- return ret; -+ return new_subid_range(range, id_type, reuse); - } - - bool grant_subuid_range(struct subordinate_range *range, bool reuse) -@@ -176,56 +92,18 @@ bool grant_subgid_range(struct subordinate_range *range, bool reuse) - return grant_subid_range(range, reuse, ID_TYPE_GID); - } - --bool free_subid_range(struct subordinate_range *range, enum subid_type id_type) -+static -+bool ungrant_subid_range(struct subordinate_range *range, enum subid_type id_type) - { -- bool ret; -- -- switch (id_type) { -- case ID_TYPE_UID: -- if (!sub_uid_lock()) { -- printf("Failed loging subuids (errno %d)\n", errno); -- return false; -- } -- if (!sub_uid_open(O_CREAT | O_RDWR)) { -- printf("Failed opening subuids (errno %d)\n", errno); -- sub_uid_unlock(); -- return false; -- } -- break; -- case ID_TYPE_GID: -- if (!sub_gid_lock()) { -- printf("Failed loging subgids (errno %d)\n", errno); -- return false; -- } -- if (!sub_gid_open(O_CREAT | O_RDWR)) { -- printf("Failed opening subgids (errno %d)\n", errno); -- sub_gid_unlock(); -- return false; -- } -- break; -- default: -- return false; -- } -- -- ret = release_subid_range(range, id_type); -- -- if (id_type == ID_TYPE_UID) { -- sub_uid_close(); -- sub_uid_unlock(); -- } else { -- sub_gid_close(); -- sub_gid_unlock(); -- } -- -- return ret; -+ return release_subid_range(range, id_type); - } - --bool free_subuid_range(struct subordinate_range *range) -+bool ungrant_subuid_range(struct subordinate_range *range) - { -- return free_subid_range(range, ID_TYPE_UID); -+ return ungrant_subid_range(range, ID_TYPE_UID); - } - --bool free_subgid_range(struct subordinate_range *range) -+bool ungrant_subgid_range(struct subordinate_range *range) - { -- return free_subid_range(range, ID_TYPE_GID); -+ return ungrant_subid_range(range, ID_TYPE_GID); - } -diff --git a/libsubid/api.h b/libsubid/api.h -index fbdf0f9e..97b04e25 100644 ---- a/libsubid/api.h -+++ b/libsubid/api.h -@@ -1,9 +1,9 @@ - #include "subid.h" - #include - --struct subordinate_range **get_subuid_ranges(const char *owner); --struct subordinate_range **get_subgid_ranges(const char *owner); --void subid_free_ranges(struct subordinate_range **ranges); -+int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); -+int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); -+void subid_free_ranges(struct subordinate_range **ranges, int count); - - int get_subuid_owners(uid_t uid, uid_t **owner); - int get_subgid_owners(gid_t gid, uid_t **owner); -@@ -13,5 +13,5 @@ int get_subgid_owners(gid_t gid, uid_t **owner); - bool grant_subuid_range(struct subordinate_range *range, bool reuse); - bool grant_subgid_range(struct subordinate_range *range, bool reuse); - --bool free_subuid_range(struct subordinate_range *range); --bool free_subgid_range(struct subordinate_range *range); -+bool ungrant_subuid_range(struct subordinate_range *range); -+bool ungrant_subgid_range(struct subordinate_range *range); -diff --git a/libsubid/subid.h b/libsubid/subid.h -index ba9a2f6f..2f27ad8a 100644 ---- a/libsubid/subid.h -+++ b/libsubid/subid.h -@@ -1,4 +1,5 @@ - #include -+#include - - #ifndef SUBID_RANGE_DEFINED - #define SUBID_RANGE_DEFINED 1 -@@ -13,5 +14,12 @@ enum subid_type { - ID_TYPE_GID = 2 - }; - -+enum subid_status { -+ SUBID_STATUS_SUCCESS = 0, -+ SUBID_STATUS_UNKNOWN_USER = 1, -+ SUBID_STATUS_ERROR_CONN = 2, -+ SUBID_STATUS_ERROR = 3, -+}; -+ - #define SUBID_NFIELDS 3 - #endif -diff --git a/src/Makefile.am b/src/Makefile.am -index e9d354fd..35027013 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -111,15 +111,6 @@ grpck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - grpconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - grpunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - lastlog_LDADD = $(LDADD) $(LIBAUDIT) $(LIBECONF) --newuidmap_SOURCES = newuidmap.c ../libmisc/nss.c --newgidmap_SOURCES = newgidmap.c ../libmisc/nss.c --groupadd_SOURCES = groupadd.c ../libmisc/nss.c --groupmod_SOURCES = groupmod.c ../libmisc/nss.c --groupdel_SOURCES = groupdel.c ../libmisc/nss.c --newusers_SOURCES = newusers.c ../libmisc/nss.c --useradd_SOURCES = useradd.c ../libmisc/nss.c --usermod_SOURCES = usermod.c ../libmisc/nss.c --userdel_SOURCES = userdel.c ../libmisc/nss.c - login_SOURCES = \ - login.c \ - login_nopam.c -@@ -169,7 +160,8 @@ endif - noinst_PROGRAMS += list_subid_ranges \ - get_subid_owners \ - new_subid_range \ -- free_subid_range -+ free_subid_range \ -+ check_subid_range - - MISCLIBS = \ - $(LIBAUDIT) \ -@@ -186,7 +178,7 @@ list_subid_ranges_LDADD = \ - $(top_builddir)/lib/libshadow.la \ - $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ -- $(MISCLIBS) -+ $(MISCLIBS) -ldl - - list_subid_ranges_CPPFLAGS = \ - -I$(top_srcdir)/lib \ -@@ -197,7 +189,7 @@ get_subid_owners_LDADD = \ - $(top_builddir)/lib/libshadow.la \ - $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ -- $(MISCLIBS) -+ $(MISCLIBS) -ldl - - get_subid_owners_CPPFLAGS = \ - -I$(top_srcdir)/lib \ -@@ -213,7 +205,7 @@ new_subid_range_LDADD = \ - $(top_builddir)/lib/libshadow.la \ - $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ -- $(MISCLIBS) -+ $(MISCLIBS) -ldl - - free_subid_range_CPPFLAGS = \ - -I$(top_srcdir)/lib \ -@@ -224,5 +216,14 @@ free_subid_range_LDADD = \ - $(top_builddir)/lib/libshadow.la \ - $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ -- $(MISCLIBS) -+ $(MISCLIBS) -ldl -+ -+check_subid_range_CPPFLAGS = \ -+ -I$(top_srcdir)/lib \ -+ -I$(top_srcdir)/libmisc -+ -+check_subid_range_LDADD = \ -+ $(top_builddir)/lib/libshadow.la \ -+ $(top_builddir)/libmisc/libmisc.la \ -+ $(MISCLIBS) -ldl - endif -diff --git a/src/check_subid_range.c b/src/check_subid_range.c -new file mode 100644 -index 00000000..fb1c2cfc ---- /dev/null -+++ b/src/check_subid_range.c -@@ -0,0 +1,48 @@ -+// This program is for testing purposes only. -+// usage is "[program] owner [u|g] start count -+// Exits 0 if owner has subid range starting start, of size count -+// Exits 1 otherwise. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "defines.h" -+#include "prototypes.h" -+#include "subordinateio.h" -+#include "idmapping.h" -+ -+const char *Prog; -+ -+int main(int argc, char **argv) -+{ -+ char *owner; -+ unsigned long start, count; -+ bool check_uids; -+ Prog = Basename (argv[0]); -+ -+ if (argc != 5) -+ exit(1); -+ -+ owner = argv[1]; -+ check_uids = argv[2][0] == 'u'; -+ start = strtoul(argv[3], NULL, 10); -+ if (start == ULONG_MAX && errno == ERANGE) -+ exit(1); -+ count = strtoul(argv[4], NULL, 10); -+ if (count == ULONG_MAX && errno == ERANGE) -+ exit(1); -+ if (check_uids) { -+ if (have_sub_uids(owner, start, count)) -+ exit(0); -+ exit(1); -+ } -+ if (have_sub_gids(owner, start, count)) -+ exit(0); -+ exit(1); -+} -diff --git a/src/free_subid_range.c b/src/free_subid_range.c -index 36858875..de6bc58f 100644 ---- a/src/free_subid_range.c -+++ b/src/free_subid_range.c -@@ -37,9 +37,9 @@ int main(int argc, char *argv[]) - range.start = atoi(argv[1]); - range.count = atoi(argv[2]); - if (group) -- ok = free_subgid_range(&range); -+ ok = ungrant_subgid_range(&range); - else -- ok = free_subuid_range(&range); -+ ok = ungrant_subuid_range(&range); - - if (!ok) { - fprintf(stderr, "Failed freeing id range\n"); -diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c -index cdba610e..440ef911 100644 ---- a/src/list_subid_ranges.c -+++ b/src/list_subid_ranges.c -@@ -15,7 +15,7 @@ void usage(void) - - int main(int argc, char *argv[]) - { -- int i; -+ int i, count=0; - struct subordinate_range **ranges; - - Prog = Basename (argv[0]); -@@ -23,19 +23,19 @@ int main(int argc, char *argv[]) - usage(); - } - if (argc == 3 && strcmp(argv[1], "-g") == 0) -- ranges = get_subgid_ranges(argv[2]); -+ count = get_subgid_ranges(argv[2], &ranges); - else if (argc == 2 && strcmp(argv[1], "-h") == 0) - usage(); - else -- ranges = get_subuid_ranges(argv[1]); -+ count = get_subuid_ranges(argv[1], &ranges); - if (!ranges) { - fprintf(stderr, "Error fetching ranges\n"); - exit(1); - } -- for (i = 0; ranges[i]; i++) { -+ for (i = 0; i < count; i++) { - printf("%d: %s %lu %lu\n", i, ranges[i]->owner, - ranges[i]->start, ranges[i]->count); - } -- subid_free_ranges(ranges); -+ subid_free_ranges(ranges, count); - return 0; - } -diff --git a/tests/libsubid/04_nss/Makefile b/tests/libsubid/04_nss/Makefile -new file mode 100644 -index 00000000..6cd3225f ---- /dev/null -+++ b/tests/libsubid/04_nss/Makefile -@@ -0,0 +1,12 @@ -+all: test_nss libsubid_zzz.so -+ -+test_nss: test_nss.c ../../../lib/nss.c -+ gcc -c -I../../../lib/ -I../../.. -o test_nss.o test_nss.c -+ gcc -o test_nss test_nss.o ../../../libmisc/.libs/libmisc.a ../../../lib/.libs/libshadow.a -ldl -+ -+libsubid_zzz.so: libsubid_zzz.c -+ gcc -c -I../../../lib/ -I../../.. -I../../../libmisc -I../../../libsubid libsubid_zzz.c -+ gcc -L../../../libsubid -shared -o libsubid_zzz.so libsubid_zzz.o ../../../lib/.libs/libshadow.a -ldl -+ -+clean: -+ rm -f *.o *.so test_nss -diff --git a/tests/libsubid/04_nss/empty b/tests/libsubid/04_nss/empty -new file mode 100644 -index 00000000..e69de29b -diff --git a/tests/libsubid/04_nss/libsubid_zzz.c b/tests/libsubid/04_nss/libsubid_zzz.c -new file mode 100644 -index 00000000..b56a4bae ---- /dev/null -+++ b/tests/libsubid/04_nss/libsubid_zzz.c -@@ -0,0 +1,146 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+enum subid_status shadow_subid_has_any_range(const char *owner, enum subid_type t, bool *result) -+{ -+ if (strcmp(owner, "ubuntu") == 0) { -+ *result = true; -+ return SUBID_STATUS_SUCCESS; -+ } -+ if (strcmp(owner, "error") == 0) { -+ *result = false; -+ return SUBID_STATUS_ERROR; -+ } -+ if (strcmp(owner, "unknown") == 0) { -+ *result = false; -+ return SUBID_STATUS_UNKNOWN_USER; -+ } -+ if (strcmp(owner, "conn") == 0) { -+ *result = false; -+ return SUBID_STATUS_ERROR_CONN; -+ } -+ if (t == ID_TYPE_UID) { -+ *result = strcmp(owner, "user1") == 0; -+ return SUBID_STATUS_SUCCESS; -+ } -+ -+ *result = strcmp(owner, "group1") == 0; -+ return SUBID_STATUS_SUCCESS; -+} -+ -+enum subid_status shadow_subid_has_range(const char *owner, unsigned long start, unsigned long count, enum subid_type t, bool *result) -+{ -+ if (strcmp(owner, "ubuntu") == 0 && -+ start >= 200000 && -+ count <= 100000) { -+ *result = true; -+ return SUBID_STATUS_SUCCESS; -+ } -+ *result = false; -+ if (strcmp(owner, "error") == 0) -+ return SUBID_STATUS_ERROR; -+ if (strcmp(owner, "unknown") == 0) -+ return SUBID_STATUS_UNKNOWN_USER; -+ if (strcmp(owner, "conn") == 0) -+ return SUBID_STATUS_ERROR_CONN; -+ -+ if (t == ID_TYPE_UID && strcmp(owner, "user1") != 0) -+ return SUBID_STATUS_SUCCESS; -+ if (t == ID_TYPE_GID && strcmp(owner, "group1") != 0) -+ return SUBID_STATUS_SUCCESS; -+ -+ if (start < 100000) -+ return SUBID_STATUS_SUCCESS; -+ if (count >= 65536) -+ return SUBID_STATUS_SUCCESS; -+ *result = true; -+ return SUBID_STATUS_SUCCESS; -+} -+ -+// So if 'user1' or 'ubuntu' is defined in passwd, we'll return those values, -+// to ease manual testing. For automated testing, if you return those values, -+// we'll return 1000 for ubuntu and 1001 otherwise. -+static uid_t getnamuid(const char *name) { -+ struct passwd *pw; -+ -+ pw = getpwnam(name); -+ if (pw) -+ return pw->pw_uid; -+ -+ // For testing purposes -+ return strcmp(name, "ubuntu") == 0 ? (uid_t)1000 : (uid_t)1001; -+} -+ -+static int alloc_uid(uid_t **uids, uid_t id) { -+ *uids = malloc(sizeof(uid_t)); -+ if (!*uids) -+ return -1; -+ *uids[0] = id; -+ return 1; -+} -+ -+enum subid_status shadow_subid_find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids, int *count) -+{ -+ if (id >= 100000 && id < 165536) { -+ *count = alloc_uid(uids, getnamuid("user1")); -+ if (*count == 1) -+ return SUBID_STATUS_SUCCESS; -+ return SUBID_STATUS_ERROR; // out of memory -+ } -+ if (id >= 200000 && id < 300000) { -+ *count = alloc_uid(uids, getnamuid("ubuntu")); -+ if (*count == 1) -+ return SUBID_STATUS_SUCCESS; -+ return SUBID_STATUS_ERROR; // out of memory -+ } -+ *count = 0; // nothing found -+ return SUBID_STATUS_SUCCESS; -+} -+ -+enum subid_status shadow_subid_list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges, int *count) -+{ -+ struct subordinate_range **ranges; -+ -+ *count = 0; -+ if (strcmp(owner, "error") == 0) -+ return SUBID_STATUS_ERROR; -+ if (strcmp(owner, "unknown") == 0) -+ return SUBID_STATUS_UNKNOWN_USER; -+ if (strcmp(owner, "conn") == 0) -+ return SUBID_STATUS_ERROR_CONN; -+ -+ *ranges = NULL; -+ if (strcmp(owner, "user1") != 0 && strcmp(owner, "ubuntu") != 0 && -+ strcmp(owner, "group1") != 0) -+ return SUBID_STATUS_SUCCESS; -+ if (id_type == ID_TYPE_GID && strcmp(owner, "user1") == 0) -+ return SUBID_STATUS_SUCCESS; -+ if (id_type == ID_TYPE_UID && strcmp(owner, "group1") == 0) -+ return SUBID_STATUS_SUCCESS; -+ ranges = (struct subordinate_range **)malloc(sizeof(struct subordinate_range *)); -+ if (!*ranges) -+ return SUBID_STATUS_ERROR; -+ ranges[0] = (struct subordinate_range *)malloc(sizeof(struct subordinate_range)); -+ if (!ranges[0]) { -+ free(*ranges); -+ *ranges = NULL; -+ return SUBID_STATUS_ERROR; -+ } -+ ranges[0]->owner = strdup(owner); -+ if (strcmp(owner, "user1") == 0 || strcmp(owner, "group1") == 0) { -+ ranges[0]->start = 100000; -+ ranges[0]->count = 65536; -+ } else { -+ ranges[0]->start = 200000; -+ ranges[0]->count = 100000; -+ } -+ -+ *count = 1; -+ *in_ranges = ranges; -+ -+ return SUBID_STATUS_SUCCESS; -+} -diff --git a/tests/libsubid/04_nss/nsswitch1.conf b/tests/libsubid/04_nss/nsswitch1.conf -new file mode 100644 -index 00000000..43764a39 ---- /dev/null -+++ b/tests/libsubid/04_nss/nsswitch1.conf -@@ -0,0 +1,20 @@ -+# /etc/nsswitch.conf -+# -+# Example configuration of GNU Name Service Switch functionality. -+# If you have the `glibc-doc-reference' and `info' packages installed, try: -+# `info libc "Name Service Switch"' for information about this file. -+ -+passwd: files systemd -+group: files systemd -+shadow: files -+gshadow: files -+ -+hosts: files mdns4_minimal [NOTFOUND=return] dns -+networks: files -+ -+protocols: db files -+services: db files -+ethers: db files -+rpc: db files -+ -+netgroup: nis -diff --git a/tests/libsubid/04_nss/nsswitch2.conf b/tests/libsubid/04_nss/nsswitch2.conf -new file mode 100644 -index 00000000..d371a36c ---- /dev/null -+++ b/tests/libsubid/04_nss/nsswitch2.conf -@@ -0,0 +1,22 @@ -+# /etc/nsswitch.conf -+# -+# Example configuration of GNU Name Service Switch functionality. -+# If you have the `glibc-doc-reference' and `info' packages installed, try: -+# `info libc "Name Service Switch"' for information about this file. -+ -+passwd: files systemd -+group: files systemd -+shadow: files -+gshadow: files -+ -+hosts: files mdns4_minimal [NOTFOUND=return] dns -+networks: files -+ -+protocols: db files -+services: db files -+ethers: db files -+rpc: db files -+ -+netgroup: nis -+ -+subid: files -diff --git a/tests/libsubid/04_nss/nsswitch3.conf b/tests/libsubid/04_nss/nsswitch3.conf -new file mode 100644 -index 00000000..19f2d934 ---- /dev/null -+++ b/tests/libsubid/04_nss/nsswitch3.conf -@@ -0,0 +1,22 @@ -+# /etc/nsswitch.conf -+# -+# Example configuration of GNU Name Service Switch functionality. -+# If you have the `glibc-doc-reference' and `info' packages installed, try: -+# `info libc "Name Service Switch"' for information about this file. -+ -+passwd: files systemd -+group: files systemd -+shadow: files -+gshadow: files -+ -+hosts: files mdns4_minimal [NOTFOUND=return] dns -+networks: files -+ -+protocols: db files -+services: db files -+ethers: db files -+rpc: db files -+ -+netgroup: nis -+ -+subid: zzz -diff --git a/tests/libsubid/04_nss/subidnss.test b/tests/libsubid/04_nss/subidnss.test -new file mode 100755 -index 00000000..3d40dc8c ---- /dev/null -+++ b/tests/libsubid/04_nss/subidnss.test -@@ -0,0 +1,22 @@ -+#!/bin/sh -+ -+set -e -+ -+cd $(dirname $0) -+ -+. ../../common/config.sh -+. ../../common/log.sh -+ -+make -+ -+export LD_LIBRARY_PATH=.:../../../lib/.libs:$LD_LIBRARY_PATH -+ -+./test_nss 1 -+./test_nss 2 -+./test_nss 3 -+ -+unshare -Urm ./test_range -+ -+log_status "$0" "SUCCESS" -+ -+trap '' 0 -diff --git a/tests/libsubid/04_nss/test_nss.c b/tests/libsubid/04_nss/test_nss.c -new file mode 100644 -index 00000000..5d903ab4 ---- /dev/null -+++ b/tests/libsubid/04_nss/test_nss.c -@@ -0,0 +1,72 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+extern bool nss_is_initialized(); -+extern struct subid_nss_ops *get_subid_nss_handle(); -+ -+void test1() { -+ // nsswitch1 has no subid: entry -+ setenv("LD_LIBRARY_PATH", ".", 1); -+ printf("Test with no subid entry\n"); -+ nss_init("./nsswitch1.conf"); -+ if (!nss_is_initialized() || get_subid_nss_handle()) -+ exit(1); -+ // second run should change nothing -+ printf("Test with no subid entry, second run\n"); -+ nss_init("./nsswitch1.conf"); -+ if (!nss_is_initialized() || get_subid_nss_handle()) -+ exit(1); -+} -+ -+void test2() { -+ // nsswitch2 has a subid: files entry -+ printf("test with 'files' subid entry\n"); -+ nss_init("./nsswitch2.conf"); -+ if (!nss_is_initialized() || get_subid_nss_handle()) -+ exit(1); -+ // second run should change nothing -+ printf("test with 'files' subid entry, second run\n"); -+ nss_init("./nsswitch2.conf"); -+ if (!nss_is_initialized() || get_subid_nss_handle()) -+ exit(1); -+} -+ -+void test3() { -+ // nsswitch3 has a subid: testnss entry -+ printf("test with 'test' subid entry\n"); -+ nss_init("./nsswitch3.conf"); -+ if (!nss_is_initialized() || !get_subid_nss_handle()) -+ exit(1); -+ // second run should change nothing -+ printf("test with 'test' subid entry, second run\n"); -+ nss_init("./nsswitch3.conf"); -+ if (!nss_is_initialized() || !get_subid_nss_handle()) -+ exit(1); -+} -+ -+const char *Prog; -+ -+int main(int argc, char *argv[]) -+{ -+ int which; -+ -+ Prog = Basename(argv[0]); -+ -+ if (argc < 1) -+ exit(1); -+ -+ which = atoi(argv[1]); -+ switch(which) { -+ case 1: test1(); break; -+ case 2: test2(); break; -+ case 3: test3(); break; -+ default: exit(1); -+ } -+ -+ printf("nss parsing tests done\n"); -+ exit(0); -+} -diff --git a/tests/libsubid/04_nss/test_range b/tests/libsubid/04_nss/test_range -new file mode 100755 -index 00000000..356764fb ---- /dev/null -+++ b/tests/libsubid/04_nss/test_range -@@ -0,0 +1,50 @@ -+#!/bin/sh -+ -+set -x -+ -+echo "starting check_range tests" -+ -+export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH -+mount --bind ./nsswitch3.conf /etc/nsswitch.conf -+cleanup1() { -+ umount /etc/nsswitch.conf -+} -+trap cleanup1 EXIT HUP INT TERM -+../../../src/check_subid_range user1 u 100000 65535 -+if [ $? -ne 0 ]; then -+ exit 1 -+fi -+../../../src/check_subid_range user2 u 100000 65535 -+if [ $? -eq 0 ]; then -+ exit 1 -+fi -+../../../src/check_subid_range unknown u 100000 65535 -+if [ $? -eq 0 ]; then -+ exit 1 -+fi -+../../../src/check_subid_range error u 100000 65535 -+if [ $? -eq 0 ]; then -+ exit 1 -+fi -+../../../src/check_subid_range user1 u 1000 65535 -+if [ $? -eq 0 ]; then -+ exit 1 -+fi -+ -+umount /etc/nsswitch.conf -+ -+mount --bind ./nsswitch1.conf /etc/nsswitch.conf -+mount --bind ./empty /etc/subuid -+ -+cleanup2() { -+ umount /etc/subuid -+ umount /etc/nsswitch.conf -+} -+trap cleanup2 EXIT HUP INT TERM -+../../../src/check_subid_range user1 u 100000 65535 -+if [ $? -eq 0 ]; then -+ exit 1 -+fi -+ -+echo "check_range tests complete" -+exit 0 -diff --git a/tests/run_some b/tests/run_some -index 15b4816a..e6f6eb5a 100755 ---- a/tests/run_some -+++ b/tests/run_some -@@ -127,6 +127,7 @@ run_test ./newuidmap/01_newuidmap/newuidmap.test - run_test ./libsubid/01_list_ranges/list_ranges.test - run_test ./libsubid/02_get_subid_owners/get_subid_owners.test - run_test ./libsubid/03_add_remove/add_remove_subids.test -+run_test ./libsubid/04_nss/subidnss.test - - echo - echo "$succeeded test(s) passed" --- -2.30.2 - - -From 0f4347d1483191b2142546416a9eefe0c9459600 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Thu, 15 Apr 2021 09:52:29 -0500 -Subject: [PATCH 3/6] clean up libsubid headers - -Move libsubid/api.h into libsubid/subid.h, and document the api in subid.h - -Signed-off-by: Serge Hallyn ---- - libsubid/api.c | 2 +- - libsubid/api.h | 17 ------- - libsubid/subid.h | 105 ++++++++++++++++++++++++++++++++++++++++ - src/free_subid_range.c | 2 +- - src/get_subid_owners.c | 2 +- - src/list_subid_ranges.c | 2 +- - src/new_subid_range.c | 2 +- - 7 files changed, 110 insertions(+), 22 deletions(-) - delete mode 100644 libsubid/api.h - -diff --git a/libsubid/api.c b/libsubid/api.c -index 737e1c8b..a1b5bb3f 100644 ---- a/libsubid/api.c -+++ b/libsubid/api.c -@@ -36,7 +36,7 @@ - #include - #include "subordinateio.h" - #include "idmapping.h" --#include "api.h" -+#include "subid.h" - - static - int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) -diff --git a/libsubid/api.h b/libsubid/api.h -deleted file mode 100644 -index 97b04e25..00000000 ---- a/libsubid/api.h -+++ /dev/null -@@ -1,17 +0,0 @@ --#include "subid.h" --#include -- --int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); --int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); --void subid_free_ranges(struct subordinate_range **ranges, int count); -- --int get_subuid_owners(uid_t uid, uid_t **owner); --int get_subgid_owners(gid_t gid, uid_t **owner); -- --/* range should be pre-allocated with owner and count filled in, start is -- * ignored, can be 0 */ --bool grant_subuid_range(struct subordinate_range *range, bool reuse); --bool grant_subgid_range(struct subordinate_range *range, bool reuse); -- --bool ungrant_subuid_range(struct subordinate_range *range); --bool ungrant_subgid_range(struct subordinate_range *range); -diff --git a/libsubid/subid.h b/libsubid/subid.h -index 2f27ad8a..769463f6 100644 ---- a/libsubid/subid.h -+++ b/libsubid/subid.h -@@ -21,5 +21,110 @@ enum subid_status { - SUBID_STATUS_ERROR = 3, - }; - -+/* -+ * get_subuid_ranges: return a list of UID ranges for a user -+ * -+ * @owner: username being queried -+ * @ranges: a pointer to a subordinate range ** in which the result will be -+ * returned. -+ * -+ * returns: number of ranges found, ir < 0 on error. -+ */ -+int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); -+ -+/* -+ * get_subgid_ranges: return a list of GID ranges for a user -+ * -+ * @owner: username being queried -+ * @ranges: a pointer to a subordinate range ** in which the result will be -+ * returned. -+ * -+ * returns: number of ranges found, ir < 0 on error. -+ */ -+int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); -+ -+/* -+ * subid_free_ranges: free an array of subordinate_ranges returned by either -+ * get_subuid_ranges() or get_subgid_ranges(). -+ * -+ * @ranges: the ranges to free -+ * @count: the number of ranges in @ranges -+ */ -+void subid_free_ranges(struct subordinate_range **ranges, int count); -+ -+/* -+ * get_subuid_owners: return a list of uids to which the given uid has been -+ * delegated. -+ * -+ * @uid: The subuid being queried -+ * @owners: a pointer to an array of uids into which the results are placed. -+ * The returned array must be freed by the caller. -+ * -+ * Returns the number of uids returned, or < 0 on error. -+ */ -+int get_subuid_owners(uid_t uid, uid_t **owner); -+ -+/* -+ * get_subgid_owners: return a list of uids to which the given gid has been -+ * delegated. -+ * -+ * @uid: The subgid being queried -+ * @owners: a pointer to an array of uids into which the results are placed. -+ * The returned array must be freed by the caller. -+ * -+ * Returns the number of uids returned, or < 0 on error. -+ */ -+int get_subgid_owners(gid_t gid, uid_t **owner); -+ -+/* -+ * grant_subuid_range: assign a subuid range to a user -+ * -+ * @range: pointer to a struct subordinate_range detailing the UID range -+ * to allocate. ->owner must be the username, and ->count must be -+ * filled in. ->start is ignored, and will contain the start -+ * of the newly allocated range, upon success. -+ * -+ * Returns true if the delegation succeeded, false otherwise. If true, -+ * then the range from (range->start, range->start + range->count) will -+ * be delegated to range->owner. -+ */ -+bool grant_subuid_range(struct subordinate_range *range, bool reuse); -+ -+/* -+ * grant_subsid_range: assign a subgid range to a user -+ * -+ * @range: pointer to a struct subordinate_range detailing the GID range -+ * to allocate. ->owner must be the username, and ->count must be -+ * filled in. ->start is ignored, and will contain the start -+ * of the newly allocated range, upon success. -+ * -+ * Returns true if the delegation succeeded, false otherwise. If true, -+ * then the range from (range->start, range->start + range->count) will -+ * be delegated to range->owner. -+ */ -+bool grant_subgid_range(struct subordinate_range *range, bool reuse); -+ -+/* -+ * ungrant_subuid_range: remove a subuid allocation. -+ * -+ * @range: pointer to a struct subordinate_range detailing the UID allocation -+ * to remove. -+ * -+ * Returns true if successful, false if it failed, for instance if the -+ * delegation did not exist. -+ */ -+bool ungrant_subuid_range(struct subordinate_range *range); -+ -+/* -+ * ungrant_subuid_range: remove a subgid allocation. -+ * -+ * @range: pointer to a struct subordinate_range detailing the GID allocation -+ * to remove. -+ * -+ * Returns true if successful, false if it failed, for instance if the -+ * delegation did not exist. -+ */ -+bool ungrant_subgid_range(struct subordinate_range *range); -+ - #define SUBID_NFIELDS 3 - #endif -diff --git a/src/free_subid_range.c b/src/free_subid_range.c -index de6bc58f..3701a262 100644 ---- a/src/free_subid_range.c -+++ b/src/free_subid_range.c -@@ -1,6 +1,6 @@ - #include - #include --#include "api.h" -+#include "subid.h" - #include "stdlib.h" - #include "prototypes.h" - -diff --git a/src/get_subid_owners.c b/src/get_subid_owners.c -index a4385540..409e3fea 100644 ---- a/src/get_subid_owners.c -+++ b/src/get_subid_owners.c -@@ -1,5 +1,5 @@ - #include --#include "api.h" -+#include "subid.h" - #include "stdlib.h" - #include "prototypes.h" - -diff --git a/src/list_subid_ranges.c b/src/list_subid_ranges.c -index 440ef911..21b2c192 100644 ---- a/src/list_subid_ranges.c -+++ b/src/list_subid_ranges.c -@@ -1,5 +1,5 @@ - #include --#include "api.h" -+#include "subid.h" - #include "stdlib.h" - #include "prototypes.h" - -diff --git a/src/new_subid_range.c b/src/new_subid_range.c -index 6d7b033b..dde196b3 100644 ---- a/src/new_subid_range.c -+++ b/src/new_subid_range.c -@@ -1,6 +1,6 @@ - #include - #include --#include "api.h" -+#include "subid.h" - #include "stdlib.h" - #include "prototypes.h" - --- -2.30.2 - diff --git a/shadow-4.8.1-libsubid_simplify_ranges_variable.patch b/shadow-4.8.1-libsubid_simplify_ranges_variable.patch deleted file mode 100644 index 4cd848b..0000000 --- a/shadow-4.8.1-libsubid_simplify_ranges_variable.patch +++ /dev/null @@ -1,264 +0,0 @@ -diff -up shadow-4.8.1/configure.ac.libsubid_simplify_ranges_variable shadow-4.8.1/configure.ac ---- shadow-4.8.1/configure.ac.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.165917066 +0200 -+++ shadow-4.8.1/configure.ac 2021-05-24 15:02:56.184917324 +0200 -@@ -1,6 +1,6 @@ - dnl Process this file with autoconf to produce a configure script. - AC_PREREQ([2.69]) --m4_define([libsubid_abi_major], 2) -+m4_define([libsubid_abi_major], 3) - m4_define([libsubid_abi_minor], 0) - m4_define([libsubid_abi_micro], 0) - m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro]) -diff -up shadow-4.8.1/lib/prototypes.h.libsubid_simplify_ranges_variable shadow-4.8.1/lib/prototypes.h ---- shadow-4.8.1/lib/prototypes.h.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.184917324 +0200 -+++ shadow-4.8.1/lib/prototypes.h 2021-05-24 16:38:57.610619467 +0200 -@@ -309,16 +309,15 @@ struct subid_nss_ops { - * - * @owner - string representing username being queried - * @id_type - subuid or subgid -- * @ranges - pointer to an array of struct subordinate_range pointers, or -- * NULL. The returned array of struct subordinate_range and its -- * members must be freed by the caller. -+ * @ranges - pointer to an array of struct subid_range, or NULL. The -+ * returned array must be freed by the caller. - * @count - pointer to an integer into which the number of returned ranges - * is written. - - * returns success if the module was able to determine an answer, - * else an error status. - */ -- enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges, int *count); -+ enum subid_status (*list_owner_ranges)(const char *owner, enum subid_type id_type, struct subid_range **ranges, int *count); - - /* - * nss_find_subid_owners: find uids who own a given subuid or subgid. -diff -up shadow-4.8.1/libsubid/api.c.libsubid_simplify_ranges_variable shadow-4.8.1/libsubid/api.c ---- shadow-4.8.1/libsubid/api.c.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.467989079 +0200 -+++ shadow-4.8.1/libsubid/api.c 2021-05-24 16:42:32.091584531 +0200 -@@ -68,26 +68,21 @@ bool libsubid_init(const char *progname, - } - - static --int get_subid_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges) -+int get_subid_ranges(const char *owner, enum subid_type id_type, struct subid_range **ranges) - { - return list_owner_ranges(owner, id_type, ranges); - } - --int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges) -+int get_subuid_ranges(const char *owner, struct subid_range **ranges) - { - return get_subid_ranges(owner, ID_TYPE_UID, ranges); - } - --int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges) -+int get_subgid_ranges(const char *owner, struct subid_range **ranges) - { - return get_subid_ranges(owner, ID_TYPE_GID, ranges); - } - --void subid_free_ranges(struct subordinate_range **ranges, int count) --{ -- return free_subordinate_ranges(ranges, count); --} -- - static - int get_subid_owner(unsigned long id, enum subid_type id_type, uid_t **owner) - { -diff -up shadow-4.8.1/libsubid/subid.h.libsubid_simplify_ranges_variable shadow-4.8.1/libsubid/subid.h ---- shadow-4.8.1/libsubid/subid.h.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.468989093 +0200 -+++ shadow-4.8.1/libsubid/subid.h 2021-05-24 16:43:49.697657383 +0200 -@@ -3,6 +3,15 @@ - - #ifndef SUBID_RANGE_DEFINED - #define SUBID_RANGE_DEFINED 1 -+ -+/* subid_range is just a starting point and size of a range */ -+struct subid_range { -+ unsigned long start; -+ unsigned long count; -+}; -+ -+/* subordinage_range is a subid_range plus an owner, representing -+ * a range in /etc/subuid or /etc/subgid */ - struct subordinate_range { - const char *owner; - unsigned long start; -@@ -41,32 +50,27 @@ bool libsubid_init(const char *progname, - * get_subuid_ranges: return a list of UID ranges for a user - * - * @owner: username being queried -- * @ranges: a pointer to a subordinate range ** in which the result will be -- * returned. -+ * @ranges: a pointer to an array of subid_range structs in which the result -+ * will be returned. -+ * -+ * The caller must free(ranges) when done. - * - * returns: number of ranges found, ir < 0 on error. - */ --int get_subuid_ranges(const char *owner, struct subordinate_range ***ranges); -+int get_subuid_ranges(const char *owner, struct subid_range **ranges); - - /* - * get_subgid_ranges: return a list of GID ranges for a user - * - * @owner: username being queried -- * @ranges: a pointer to a subordinate range ** in which the result will be -- * returned. -+ * @ranges: a pointer to an array of subid_range structs in which the result -+ * will be returned. - * -- * returns: number of ranges found, ir < 0 on error. -- */ --int get_subgid_ranges(const char *owner, struct subordinate_range ***ranges); -- --/* -- * subid_free_ranges: free an array of subordinate_ranges returned by either -- * get_subuid_ranges() or get_subgid_ranges(). -+ * The caller must free(ranges) when done. - * -- * @ranges: the ranges to free -- * @count: the number of ranges in @ranges -+ * returns: number of ranges found, ir < 0 on error. - */ --void subid_free_ranges(struct subordinate_range **ranges, int count); -+int get_subgid_ranges(const char *owner, struct subid_range **ranges); - - /* - * get_subuid_owners: return a list of uids to which the given uid has been -diff -up shadow-4.8.1/lib/subordinateio.c.libsubid-simplify shadow-4.8.1/lib/subordinateio.c ---- shadow-4.8.1/lib/subordinateio.c.libsubid-simplify 2021-05-24 17:27:38.721035241 +0200 -+++ shadow-4.8.1/lib/subordinateio.c 2021-05-24 17:28:06.481420946 +0200 -@@ -11,6 +11,7 @@ - #include - #include "commonio.h" - #include "subordinateio.h" -+#include "../libsubid/subid.h" - #include - #include - #include -@@ -308,25 +309,21 @@ static bool have_range(struct commonio_d - return false; - } - --static bool append_range(struct subordinate_range ***ranges, const struct subordinate_range *new, int n) -+static bool append_range(struct subid_range **ranges, const struct subordinate_range *new, int n) - { -- struct subordinate_range *tmp; - if (!*ranges) { -- *ranges = malloc(sizeof(struct subordinate_range *)); -+ *ranges = malloc(sizeof(struct subid_range)); - if (!*ranges) - return false; - } else { -- struct subordinate_range **new; -- new = realloc(*ranges, (n + 1) * (sizeof(struct subordinate_range *))); -- if (!new) -+ struct subid_range *alloced; -+ alloced = realloc(*ranges, (n + 1) * (sizeof(struct subid_range))); -+ if (!alloced) - return false; -- *ranges = new; -+ *ranges = alloced; - } -- (*ranges)[n] = NULL; -- tmp = subordinate_dup(new); -- if (!tmp) -- return false; -- (*ranges)[n] = tmp; -+ (*ranges)[n].start = new->start; -+ (*ranges)[n].count = new->count; - return true; - } - -@@ -785,10 +782,10 @@ gid_t sub_gid_find_free_range(gid_t min, - * - * The caller must free the subordinate range list. - */ --int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***in_ranges) -+int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_range **in_ranges) - { - // TODO - need to handle owner being either uid or username -- struct subordinate_range **ranges = NULL; -+ struct subid_range *ranges = NULL; - const struct subordinate_range *range; - struct commonio_db *db; - enum subid_status status; -@@ -826,7 +823,7 @@ int list_owner_ranges(const char *owner, - while ((range = commonio_next(db)) != NULL) { - if (0 == strcmp(range->owner, owner)) { - if (!append_range(&ranges, range, count++)) { -- free_subordinate_ranges(ranges, count-1); -+ free(ranges); - ranges = NULL; - count = -1; - goto out; -diff -up shadow-4.8.1/lib/subordinateio.h.libsubid_simplify_ranges_variable shadow-4.8.1/lib/subordinateio.h ---- shadow-4.8.1/lib/subordinateio.h.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.467989079 +0200 -+++ shadow-4.8.1/lib/subordinateio.h 2021-05-24 16:40:56.978269647 +0200 -@@ -25,7 +25,7 @@ extern int sub_uid_unlock (void); - extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); - extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); - extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); --extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subordinate_range ***ranges); -+extern int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_range **ranges); - extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse); - extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type); - extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); -diff -up shadow-4.8.1/src/list_subid_ranges.c.libsubid_simplify_ranges_variable shadow-4.8.1/src/list_subid_ranges.c ---- shadow-4.8.1/src/list_subid_ranges.c.libsubid_simplify_ranges_variable 2021-05-24 15:03:01.468989093 +0200 -+++ shadow-4.8.1/src/list_subid_ranges.c 2021-05-24 16:45:10.884779740 +0200 -@@ -17,27 +17,29 @@ void usage(void) - int main(int argc, char *argv[]) - { - int i, count=0; -- struct subordinate_range **ranges; -+ struct subid_range *ranges; -+ const char *owner; - - Prog = Basename (argv[0]); - shadow_logfd = stderr; -- if (argc < 2) { -+ if (argc < 2) - usage(); -- } -- if (argc == 3 && strcmp(argv[1], "-g") == 0) -- count = get_subgid_ranges(argv[2], &ranges); -- else if (argc == 2 && strcmp(argv[1], "-h") == 0) -+ owner = argv[1]; -+ if (argc == 3 && strcmp(argv[1], "-g") == 0) { -+ owner = argv[2]; -+ count = get_subgid_ranges(owner, &ranges); -+ } else if (argc == 2 && strcmp(argv[1], "-h") == 0) { - usage(); -- else -- count = get_subuid_ranges(argv[1], &ranges); -+ } else { -+ count = get_subuid_ranges(owner, &ranges); -+ } - if (!ranges) { - fprintf(stderr, "Error fetching ranges\n"); - exit(1); - } - for (i = 0; i < count; i++) { -- printf("%d: %s %lu %lu\n", i, ranges[i]->owner, -- ranges[i]->start, ranges[i]->count); -+ printf("%d: %s %lu %lu\n", i, owner, -+ ranges[i].start, ranges[i].count); - } -- subid_free_ranges(ranges, count); - return 0; - } -diff -up shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c.libsubid_simplify_ranges_variable shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c ---- shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c.libsubid_simplify_ranges_variable 2021-05-24 15:02:56.166917079 +0200 -+++ shadow-4.8.1/tests/libsubid/04_nss/libsubid_zzz.c 2021-05-24 15:03:01.469989106 +0200 -@@ -113,7 +113,7 @@ enum subid_status shadow_subid_list_owne - if (strcmp(owner, "conn") == 0) - return SUBID_STATUS_ERROR_CONN; - -- *ranges = NULL; -+ *in_ranges = NULL; - if (strcmp(owner, "user1") != 0 && strcmp(owner, "ubuntu") != 0 && - strcmp(owner, "group1") != 0) - return SUBID_STATUS_SUCCESS; diff --git a/shadow-4.8.1-man-include-lastlog-file-caveat.patch b/shadow-4.8.1-man-include-lastlog-file-caveat.patch deleted file mode 100644 index 7be60c5..0000000 --- a/shadow-4.8.1-man-include-lastlog-file-caveat.patch +++ /dev/null @@ -1,33 +0,0 @@ -From df6ec1d1693c8c80c323b40d6fc82bb549363db3 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 29 Mar 2021 05:26:28 +0200 -Subject: [PATCH] man: include lastlog file caveat (#313) - -man/lastlog.8.xml: add another point to the caveats section regarding -the handling of the lastlog file by external tools. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=951564 ---- - man/lastlog.8.xml | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml -index fc096c8f..7e68282f 100644 ---- a/man/lastlog.8.xml -+++ b/man/lastlog.8.xml -@@ -233,5 +233,12 @@ - is no entries for users with UID between 170 and 800 lastlog will appear - to hang as it processes entries with UIDs 171-799). - -+ -+ Having high UIDs can create problems when handling the -+ /var/log/lastlog with external tools. Although the -+ actual file is sparse and does not use too much space, certain -+ applications are not designed to identify sparse files by default and may -+ require a specific option to handle them. -+ - - --- -2.30.2 - diff --git a/shadow-4.8.1-man-mention-nss-in-newuidmap.patch b/shadow-4.8.1-man-mention-nss-in-newuidmap.patch deleted file mode 100644 index e26cfa7..0000000 --- a/shadow-4.8.1-man-mention-nss-in-newuidmap.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 186b1b7ac1a68d0fcc618a22da1a99232b420911 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Tue, 4 May 2021 14:39:26 -0500 -Subject: [PATCH] manpages: mention NSS in new[ug]idmap manpages - -Closes #328 - -Signed-off-by: Serge Hallyn ---- - man/newgidmap.1.xml | 3 ++- - man/newuidmap.1.xml | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml -index 71b03e56..76fc1e30 100644 ---- a/man/newgidmap.1.xml -+++ b/man/newgidmap.1.xml -@@ -88,7 +88,8 @@ - DESCRIPTION - - The newgidmap sets /proc/[pid]/gid_map based on its -- command line arguments and the gids allowed in /etc/subgid. -+ command line arguments and the gids allowed (either in /etc/subgid or -+ through the configured NSS subid module). - Note that the root user is not exempted from the requirement for a valid - /etc/subgid entry. - -diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml -index a6f1f085..44eca50a 100644 ---- a/man/newuidmap.1.xml -+++ b/man/newuidmap.1.xml -@@ -88,7 +88,8 @@ - DESCRIPTION - - The newuidmap sets /proc/[pid]/uid_map based on its -- command line arguments and the uids allowed in /etc/subuid. -+ command line arguments and the uids allowed (either in /etc/subuid or -+ through the configured NSS subid module). - Note that the root user is not exempted from the requirement for a valid - /etc/subuid entry. - --- -2.30.2 - diff --git a/shadow-4.8.1-man_clarify_subid_delegation.patch b/shadow-4.8.1-man_clarify_subid_delegation.patch deleted file mode 100644 index b7d01b8..0000000 --- a/shadow-4.8.1-man_clarify_subid_delegation.patch +++ /dev/null @@ -1,246 +0,0 @@ -From d5b15f8633d0eabed885cd16feda224ec2d59072 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 24 May 2021 12:14:43 +0200 -Subject: [PATCH] man: clarify subid delegation - -Clarify that the subid delegation can only come from one source. -Moreover, add an example of what might happen if the subid source is NSS -and useradd is executed. - -Related: https://github.com/shadow-maint/shadow/issues/331 ---- - man/newgidmap.1.xml | 12 +++++++++--- - man/newuidmap.1.xml | 10 ++++++++-- - 2 files changed, 17 insertions(+), 5 deletions(-) - -diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml -index 76fc1e30..7aaf34bf 100644 ---- a/man/newgidmap.1.xml -+++ b/man/newgidmap.1.xml -@@ -88,9 +88,15 @@ - DESCRIPTION - - The newgidmap sets /proc/[pid]/gid_map based on its -- command line arguments and the gids allowed (either in /etc/subgid or -- through the configured NSS subid module). -- Note that the root user is not exempted from the requirement for a valid -+ command line arguments and the gids allowed. The subid delegation can come either from files -+ (/etc/subgid) or from the configured NSS subid module. Only one of them -+ can be chosen at a time. So, for example, if the subid source is configured as NSS and -+ groupadd is executed, then the command will fail and the entry will not be -+ created in /etc/subgid. -+ -+ -+ -+ Note that the root group is not exempted from the requirement for a valid - /etc/subgid entry. - - -diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml -index 44eca50a..4bc1ef7a 100644 ---- a/man/newuidmap.1.xml -+++ b/man/newuidmap.1.xml -@@ -88,8 +88,14 @@ - DESCRIPTION - - The newuidmap sets /proc/[pid]/uid_map based on its -- command line arguments and the uids allowed (either in /etc/subuid or -- through the configured NSS subid module). -+ command line arguments and the uids allowed. The subid delegation can come either from files -+ (/etc/subuid) or from the configured NSS subid module. Only one of them -+ can be chosen at a time. So, for example, if the subid source is configured as NSS and -+ useradd is executed, then the command will fail and the entry will not be -+ created in /etc/subuid. -+ -+ -+ - Note that the root user is not exempted from the requirement for a valid - /etc/subuid entry. - --- -2.30.2 - -From 68ebbf936038e4e4c8b5105bd3246ef9709b6354 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 7 Jun 2021 11:50:56 +0200 -Subject: [PATCH 1/2] man: clarify subid delegation behaviour - -Following the discussion https://github.com/shadow-maint/shadow/pull/345 -I have changed the documentation to clarify the behaviour of subid -delegation when any subid source except files is configured. ---- - man/newgidmap.1.xml | 11 +++++------ - man/newuidmap.1.xml | 11 +++++------ - 2 files changed, 10 insertions(+), 12 deletions(-) - -diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml -index 7aaf34bf..681aefcb 100644 ---- a/man/newgidmap.1.xml -+++ b/man/newgidmap.1.xml -@@ -87,12 +87,11 @@ - - DESCRIPTION - -- The newgidmap sets /proc/[pid]/gid_map based on its -- command line arguments and the gids allowed. The subid delegation can come either from files -- (/etc/subgid) or from the configured NSS subid module. Only one of them -- can be chosen at a time. So, for example, if the subid source is configured as NSS and -- groupadd is executed, then the command will fail and the entry will not be -- created in /etc/subgid. -+ The newgidmap sets /proc/[pid]/gid_map -+ based on its command line arguments and the gids allowed. Subgid -+ delegation can either be managed via /etc/subgid -+ or through the configured NSS subid module. These options are mutually -+ exclusive. - - - -diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml -index 4bc1ef7a..09e65d80 100644 ---- a/man/newuidmap.1.xml -+++ b/man/newuidmap.1.xml -@@ -87,12 +87,11 @@ - - DESCRIPTION - -- The newuidmap sets /proc/[pid]/uid_map based on its -- command line arguments and the uids allowed. The subid delegation can come either from files -- (/etc/subuid) or from the configured NSS subid module. Only one of them -- can be chosen at a time. So, for example, if the subid source is configured as NSS and -- useradd is executed, then the command will fail and the entry will not be -- created in /etc/subuid. -+ The newuidmap sets /proc/[pid]/uid_map -+ based on its command line arguments and the uids allowed. Subuid -+ delegation can either be managed via /etc/subuid or -+ through the configured NSS subid module. These options are mutually -+ exclusive. - - - --- -2.31.1 - - -From 0faec51bf0ec24e6e3d098cc55ed42584dd24efe Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 11 Jun 2021 15:25:42 +0200 -Subject: [PATCH 2/2] man: definition and configuration of subid - -Define the subid functionality and explain the way to configure its -delegation. ---- - man/subgid.5.xml | 32 +++++++++++++++++++++++++++++++- - man/subuid.5.xml | 32 +++++++++++++++++++++++++++++++- - 2 files changed, 62 insertions(+), 2 deletions(-) - -diff --git a/man/subgid.5.xml b/man/subgid.5.xml -index 70c561c4..02f421ab 100644 ---- a/man/subgid.5.xml -+++ b/man/subgid.5.xml -@@ -38,6 +38,11 @@ - Biederman - Creation, 2013 - -+ -+ Iker -+ Pedrosa -+ Developer, 2021 -+ - - - subgid -@@ -48,11 +53,36 @@ - - - subgid -- the subordinate gid file -+ the configuration for subordinate group ids - - - - DESCRIPTION -+ -+ Subgid authorizes a group id to map ranges of group ids from its namespace -+ into child namespaces. -+ -+ -+ The delegation of the subordinate gids can be configured via the -+ subid field in -+ /etc/nsswitch.conf file. Only one value can be set -+ as the delegation source. Setting this field to -+ files configures the delegation of gids to -+ /etc/subgid. Setting any other value treats -+ the delegation as a plugin following with a name of the form -+ libsubid_$value.so. If the value or plugin is -+ missing, then the subordinate gid delegation falls back to -+ files. -+ -+ -+ Note, that groupadd will only create entries in -+ /etc/subgid if subid delegation is managed via subid -+ files. -+ -+ -+ -+ -+ LOCAL SUBORDINATE DELEGATION - - Each line in /etc/subgid contains - a user name and a range of subordinate group ids that user -diff --git a/man/subuid.5.xml b/man/subuid.5.xml -index ec6a85f5..990d162e 100644 ---- a/man/subuid.5.xml -+++ b/man/subuid.5.xml -@@ -38,6 +38,11 @@ - Biederman - Creation, 2013 - -+ -+ Iker -+ Pedrosa -+ Developer, 2021 -+ - - - subuid -@@ -48,11 +53,36 @@ - - - subuid -- the subordinate uid file -+ the configuration for subordinate user ids - - - - DESCRIPTION -+ -+ Subuid authorizes a user id to map ranges of user ids from its namespace -+ into child namespaces. -+ -+ -+ The delegation of the subordinate uids can be configured via the -+ subid field in -+ /etc/nsswitch.conf file. Only one value can be set -+ as the delegation source. Setting this field to -+ files configures the delegation of uids to -+ /etc/subuid. Setting any other value treats -+ the delegation as a plugin following with a name of the form -+ libsubid_$value.so. If the value or plugin is -+ missing, then the subordinate uid delegation falls back to -+ files. -+ -+ -+ Note, that useradd will only create entries in -+ /etc/subuid if subid delegation is managed via subid -+ files. -+ -+ -+ -+ -+ LOCAL SUBORDINATE DELEGATION - - Each line in /etc/subuid contains - a user name and a range of subordinate user ids that user --- -2.31.1 - diff --git a/shadow-4.8.1-manfix.patch b/shadow-4.8.1-manfix.patch deleted file mode 100644 index 29f06a7..0000000 --- a/shadow-4.8.1-manfix.patch +++ /dev/null @@ -1,341 +0,0 @@ -diff -up shadow-4.8.1/man/chage.1.xml.manfix shadow-4.8.1/man/chage.1.xml ---- shadow-4.8.1/man/chage.1.xml.manfix 2019-10-05 01:28:34.000000000 +0200 -+++ shadow-4.8.1/man/chage.1.xml 2020-03-17 15:34:48.750414984 +0100 -@@ -102,6 +102,9 @@ - Set the number of days since January 1st, 1970 when the password - was last changed. The date may also be expressed in the format - YYYY-MM-DD (or the format more commonly used in your area). -+ If the LAST_DAY is set to -+ 0 the user is forced to change his password -+ on the next log on. - - - -@@ -119,6 +122,13 @@ - system again. - - -+ For example the following can be used to set an account to expire -+ in 180 days: -+ -+ -+ chage -E $(date -d +180days +%Y-%m-%d) -+ -+ - Passing the number -1 as the - EXPIRE_DATE will remove an account - expiration date. -@@ -239,6 +249,18 @@ - The chage program requires a shadow password file to - be available. - -+ -+ The chage program will report only the information from the shadow -+ password file. This implies that configuration from other sources -+ (e.g. LDAP or empty password hash field from the passwd file) that -+ affect the user's login will not be shown in the chage output. -+ -+ -+ The chage program will also not report any -+ inconsistency between the shadow and passwd files (e.g. missing x in -+ the passwd file). The pwck can be used to check -+ for this kind of inconsistencies. -+ - The chage command is restricted to the root - user, except for the option, which may be used by - an unprivileged user to determine when their password or account is due -diff -up shadow-4.8.1/man/groupadd.8.xml.manfix shadow-4.8.1/man/groupadd.8.xml ---- shadow-4.8.1/man/groupadd.8.xml.manfix 2020-03-17 15:34:48.745414917 +0100 -+++ shadow-4.8.1/man/groupadd.8.xml 2020-03-17 15:34:48.750414984 +0100 -@@ -320,13 +320,13 @@ - - 4 - -- GID not unique (when not used) -+ GID is already used (when called without ) - - - - 9 - -- group name not unique -+ group name is already used - - - -diff -up shadow-4.8.1/man/groupmems.8.xml.manfix shadow-4.8.1/man/groupmems.8.xml ---- shadow-4.8.1/man/groupmems.8.xml.manfix 2020-03-17 15:34:48.750414984 +0100 -+++ shadow-4.8.1/man/groupmems.8.xml 2020-03-17 15:41:13.383588722 +0100 -@@ -179,20 +179,10 @@ - - SETUP - -- The groupmems executable should be in mode -- 2710 as user root and in group -- groups. The system administrator can add users to -- group groups to allow or disallow them using the -- groupmems utility to manage their own group -- membership list. -+ In this operating system the groupmems executable -+ is not setuid and regular users cannot use it to manipulate -+ the membership of their own group. - -- -- -- $ groupadd -r groups -- $ chmod 2710 groupmems -- $ chown root.groups groupmems -- $ groupmems -g groups -a gk4 -- - - - -diff -up shadow-4.8.1/man/ja/man5/login.defs.5.manfix shadow-4.8.1/man/ja/man5/login.defs.5 ---- shadow-4.8.1/man/ja/man5/login.defs.5.manfix 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/man/ja/man5/login.defs.5 2020-03-17 15:34:48.750414984 +0100 -@@ -147,10 +147,6 @@ 以下の参照表は、 - shadow パスワード機能のどのプログラムが - どのパラメータを使用するかを示したものである。 - .na --.IP chfn 12 --CHFN_AUTH CHFN_RESTRICT --.IP chsh 12 --CHFN_AUTH - .IP groupadd 12 - GID_MAX GID_MIN - .IP newusers 12 -diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5.xml ---- shadow-4.8.1/man/login.defs.5.xml.manfix 2020-01-17 16:47:56.000000000 +0100 -+++ shadow-4.8.1/man/login.defs.5.xml 2020-03-17 15:34:48.750414984 +0100 -@@ -164,6 +164,17 @@ - long numeric parameters is machine-dependent. - - -+ -+ Please note that the parameters in this configuration file control the -+ behavior of the tools from the shadow-utils component. None of these -+ tools uses the PAM mechanism, and the utilities that use PAM (such as the -+ passwd command) should be configured elsewhere. The only values that -+ affect PAM modules are ENCRYPT_METHOD and SHA_CRYPT_MAX_ROUNDS -+ for pam_unix module, FAIL_DELAY for pam_faildelay module, -+ and UMASK for pam_umask module. Refer to -+ pam(8) for more information. -+ -+ - The following configuration items are provided: - - -@@ -256,16 +267,6 @@ - - - -- chfn -- -- -- CHFN_AUTH -- CHFN_RESTRICT -- LOGIN_STRING -- -- -- -- - chgpasswd - - -@@ -286,14 +287,6 @@ - - - -- -- chsh -- -- -- CHSH_AUTH LOGIN_STRING -- -- -- - - - -@@ -359,34 +352,6 @@ - LASTLOG_UID_MAX - - -- -- login -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENV_PATH ENV_SUPATH -- ENV_TZ ENVIRON_FILE -- ERASECHAR FAIL_DELAY -- FAILLOG_ENAB -- FAKE_SHELL -- FTMP_FILE -- HUSHLOGIN_FILE -- ISSUE_FILE -- KILLCHAR -- LASTLOG_ENAB LASTLOG_UID_MAX -- LOGIN_RETRIES -- LOGIN_STRING -- LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB -- MAIL_CHECK_ENAB MAIL_DIR MAIL_FILE -- MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB -- QUOTAS_ENAB -- TTYGROUP TTYPERM TTYTYPE_FILE -- ULIMIT UMASK -- USERGROUPS_ENAB -- -- -- - - - newgrp / sg -@@ -415,17 +380,6 @@ - - - -- -- passwd -- -- -- ENCRYPT_METHOD MD5_CRYPT_ENAB OBSCURE_CHECKS_ENAB -- PASS_ALWAYS_WARN PASS_CHANGE_TRIES PASS_MAX_LEN PASS_MIN_LEN -- SHA_CRYPT_MAX_ROUNDS -- SHA_CRYPT_MIN_ROUNDS -- -- -- - - pwck - -@@ -452,32 +406,6 @@ - - - -- -- su -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENVIRON_FILE -- ENV_PATH ENV_SUPATH -- ENV_TZ LOGIN_STRING MAIL_CHECK_ENAB -- MAIL_DIR MAIL_FILE QUOTAS_ENAB -- SULOG_FILE SU_NAME -- SU_WHEEL_ONLY -- SYSLOG_SU_ENAB -- USERGROUPS_ENAB -- -- -- -- -- sulogin -- -- -- ENV_HZ -- ENV_TZ -- -- -- - - useradd - -diff -up shadow-4.8.1/man/shadow.5.xml.manfix shadow-4.8.1/man/shadow.5.xml ---- shadow-4.8.1/man/shadow.5.xml.manfix 2019-12-01 17:52:32.000000000 +0100 -+++ shadow-4.8.1/man/shadow.5.xml 2020-03-17 15:34:48.750414984 +0100 -@@ -129,7 +129,7 @@ - - - The date of the last password change, expressed as the number -- of days since Jan 1, 1970. -+ of days since Jan 1, 1970 00:00 UTC. - - - The value 0 has a special meaning, which is that the user -@@ -208,8 +208,8 @@ - - - After expiration of the password and this expiration period is -- elapsed, no login is possible using the current user's -- password. The user should contact her administrator. -+ elapsed, no login is possible for the user. -+ The user should contact her administrator. - - - An empty field means that there are no enforcement of an -@@ -224,7 +224,7 @@ - - - The date of expiration of the account, expressed as the number -- of days since Jan 1, 1970. -+ of days since Jan 1, 1970 00:00 UTC. - - - Note that an account expiration differs from a password -diff -up shadow-4.8.1/man/useradd.8.xml.manfix shadow-4.8.1/man/useradd.8.xml ---- shadow-4.8.1/man/useradd.8.xml.manfix 2020-03-17 15:34:48.745414917 +0100 -+++ shadow-4.8.1/man/useradd.8.xml 2020-03-17 15:34:48.751414997 +0100 -@@ -359,6 +359,11 @@ - is not enabled, no home - directories are created. - -+ -+ The directory where the user's home directory is created must -+ exist and have proper SELinux context and permissions. Otherwise -+ the user's home directory cannot be created or accessed. -+ - - - -diff -up shadow-4.8.1/man/usermod.8.xml.manfix shadow-4.8.1/man/usermod.8.xml ---- shadow-4.8.1/man/usermod.8.xml.manfix 2019-12-20 06:58:23.000000000 +0100 -+++ shadow-4.8.1/man/usermod.8.xml 2020-03-17 15:34:48.751414997 +0100 -@@ -143,7 +143,8 @@ - If the - option is given, the contents of the current home directory will - be moved to the new home directory, which is created if it does -- not already exist. -+ not already exist. If the current home directory does not exist -+ the new home directory will not be created. - - - -@@ -205,6 +206,12 @@ - The group ownership of files outside of the user's home directory - must be fixed manually. - -+ -+ The change of the group ownership of files inside of the user's -+ home directory is also not done if the home dir owner uid is -+ different from the current or new user id. This is safety measure -+ for special home directories such as /. -+ - - - -@@ -267,7 +274,8 @@ - - - Move the content of the user's home directory to the new -- location. -+ location. If the current home directory does not exist -+ the new home directory will not be created. - - - This option is only valid in combination with the -@@ -381,6 +389,12 @@ - must be fixed manually. - - -+ The change of the user ownership of files inside of the user's -+ home directory is also not done if the home dir owner uid is -+ different from the current or new user id. This is safety measure -+ for special home directories such as /. -+ -+ - No checks will be performed with regard to the - , , - , or diff --git a/shadow-4.8.1-salt_c_comments.patch b/shadow-4.8.1-salt_c_comments.patch deleted file mode 100644 index 1ec77e4..0000000 --- a/shadow-4.8.1-salt_c_comments.patch +++ /dev/null @@ -1,75 +0,0 @@ -From dbf230e4cf823dd6b6a3bad6d29dfad4f0ffa8fc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Mon, 14 Jun 2021 23:28:28 +0200 -Subject: [PATCH] libmisc/salt.c: Add comments how the minmum buffer length is - computed. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In the previous commit we refactored the functions converting the -rounds number into a string for use with the crypt() function, to -not require any static buffer anymore. - -Add some clarifying comments about how the minimum required buffer -length is computed inside of these functions. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 29 +++++++++++++++++++++++++---- - 1 file changed, 25 insertions(+), 4 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 98982ed1..e17093fc 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -216,7 +216,14 @@ static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *pref - return; - } - -- /* Check if the result buffer is long enough. */ -+ /* -+ * Check if the result buffer is long enough. -+ * We are going to write a maximum of 17 bytes, -+ * plus one byte for the terminator. -+ * rounds=XXXXXXXXX$ -+ * 00000000011111111 -+ * 12345678901234567 -+ */ - assert (GENSALT_SETTING_SIZE > buf_begin + 17); - - (void) snprintf (buf + buf_begin, 18, "rounds=%lu$", rounds); -@@ -274,7 +281,14 @@ static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *p - rounds = 19; - } - -- /* Check if the result buffer is long enough. */ -+ /* -+ * Check if the result buffer is long enough. -+ * We are going to write three bytes, -+ * plus one byte for the terminator. -+ * XX$ -+ * 000 -+ * 123 -+ */ - assert (GENSALT_SETTING_SIZE > buf_begin + 3); - - (void) snprintf (buf + buf_begin, 4, "%2.2lu$", rounds); -@@ -308,8 +322,15 @@ static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *p - cost = Y_COST_MAX; - } - -- /* Check if the result buffer is long enough. */ -- assert (GENSALT_SETTING_SIZE > buf_begin + 3); -+ /* -+ * Check if the result buffer is long enough. -+ * We are going to write four bytes, -+ * plus one byte for the terminator. -+ * jXX$ -+ * 0000 -+ * 1234 -+ */ -+ assert (GENSALT_SETTING_SIZE > buf_begin + 4); - - buf[buf_begin + 0] = 'j'; - if (cost < 3) { diff --git a/shadow-4.8.1-salt_c_fix_fread.patch b/shadow-4.8.1-salt_c_fix_fread.patch deleted file mode 100644 index 754b292..0000000 --- a/shadow-4.8.1-salt_c_fix_fread.patch +++ /dev/null @@ -1,29 +0,0 @@ -From ffd35d89021a9b8375a9246082afc6fc270a93ee Mon Sep 17 00:00:00 2001 -From: steven Y Gui -Date: Wed, 14 Jul 2021 16:17:48 +0800 -Subject: [PATCH] fread returns element count, not element size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 9fd34332..91d528fd 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -168,7 +168,7 @@ static long read_random_bytes (void) - #else - FILE *f = fopen ("/dev/urandom", "r"); - -- if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) { -+ if (fread (&randval, sizeof (randval), 1, f) != 1) { - fclose(f); - goto fail; - } --- -2.31.1 - diff --git a/shadow-4.8.1-salt_c_sanitize_code.patch b/shadow-4.8.1-salt_c_sanitize_code.patch deleted file mode 100644 index 1ca1d3b..0000000 --- a/shadow-4.8.1-salt_c_sanitize_code.patch +++ /dev/null @@ -1,555 +0,0 @@ -From 14b108728a5d55c3d478a170c39f0e2ffd4de1b0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Mon, 14 Jun 2021 23:28:28 +0200 -Subject: [PATCH] libmisc/salt.c: Sanitize code. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -* Move all pre-processor defines to the top of the file. -* Unify the gensalt() function to be useable for all supported - hash methods. -* Drop the gensalt_{b,yes}crypt() functions in favor of the - previous change. -* Refactor the functions converting the rounds number into - a string for use with the crypt() function, to not require - any static buffer anymore. -* Clarify the comment about how crypt_make_salt() chooses the used - hash method from the settings in the login.defs file. -* Use memset() to fill static buffers with zero before using them. -* Use a fixed amount of 16 random base64-chars for the - sha{256,512}crypt hash methods, which is effectively still less - than the recommendation from NIST (>= 128 bits), but the maximum - those methods can effectively use (approx. 90 bits). -* Rename ROUNDS_{MIN,MAX} to SHA_ROUNDS_{MIN,MAX}. -* Bugfixes in the logic of setting rounds in BCRYPT_salt_rounds(). -* Likewise for YESCRYPT_salt_cost(). -* Fix formatting and white-space errors. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 332 ++++++++++++++++++++++--------------------------- - 1 file changed, 147 insertions(+), 185 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 5dc521ef..98982ed1 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -12,6 +12,7 @@ - #ident "$Id$" - - #include -+#include - #include - #include - #include -@@ -19,6 +20,59 @@ - #include "defines.h" - #include "getdef.h" - -+/* Add the salt prefix. */ -+#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' -+ -+#ifdef USE_BCRYPT -+/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ -+#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' -+#define BCRYPT_SALT_SIZE 22 -+/* Default number of rounds if not explicitly specified. */ -+#define B_ROUNDS_DEFAULT 13 -+/* Minimum number of rounds. */ -+#define B_ROUNDS_MIN 4 -+/* Maximum number of rounds. */ -+#define B_ROUNDS_MAX 31 -+#endif /* USE_BCRYPT */ -+ -+#ifdef USE_SHA_CRYPT -+/* Fixed salt len for sha{256,512}crypt. */ -+#define SHA_CRYPT_SALT_SIZE 16 -+/* Default number of rounds if not explicitly specified. */ -+#define SHA_ROUNDS_DEFAULT 5000 -+/* Minimum number of rounds. */ -+#define SHA_ROUNDS_MIN 1000 -+/* Maximum number of rounds. */ -+#define SHA_ROUNDS_MAX 999999999 -+#endif -+ -+#ifdef USE_YESCRYPT -+/* -+ * Default number of base64 characters used for the salt. -+ * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more -+ * traditional 128 bits (16 bytes) salt, this 144 bits salt is always -+ * represented by the same number of base64 characters without padding -+ * issue, even with a non-standard base64 encoding scheme. -+ */ -+#define YESCRYPT_SALT_SIZE 24 -+/* Default cost if not explicitly specified. */ -+#define Y_COST_DEFAULT 5 -+/* Minimum cost. */ -+#define Y_COST_MIN 1 -+/* Maximum cost. */ -+#define Y_COST_MAX 11 -+#endif -+ -+/* Fixed salt len for md5crypt. */ -+#define MD5_CRYPT_SALT_SIZE 8 -+ -+/* Generate salt of size salt_size. */ -+#define MAX_SALT_SIZE 44 -+#define MIN_SALT_SIZE 8 -+ -+/* Maximum size of the generated salt string. */ -+#define GENSALT_SETTING_SIZE 100 -+ - /* local function prototypes */ - static void seedRNG (void); - static /*@observer@*/const char *gensalt (size_t salt_size); -@@ -26,19 +80,17 @@ static /*@observer@*/const char *gensalt (size_t salt_size); - static long shadow_random (long min, long max); - #endif /* USE_SHA_CRYPT || USE_BCRYPT */ - #ifdef USE_SHA_CRYPT --static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds); -+static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); - #endif /* USE_SHA_CRYPT */ - #ifdef USE_BCRYPT --static /*@observer@*/const char *gensalt_bcrypt (void); --static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds); -+static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds); - #endif /* USE_BCRYPT */ - #ifdef USE_YESCRYPT --static /*@observer@*/const char *gensalt_yescrypt (void); --static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost); -+static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost); - #endif /* USE_YESCRYPT */ - - #ifndef HAVE_L64A --static /*@observer@*/char *l64a(long value) -+static /*@observer@*/char *l64a (long value) - { - static char buf[8]; - char *s = buf; -@@ -69,7 +121,7 @@ static /*@observer@*/char *l64a(long value) - - *s = '\0'; - -- return(buf); -+ return buf; - } - #endif /* !HAVE_L64A */ - -@@ -85,15 +137,6 @@ static void seedRNG (void) - } - } - --/* -- * Add the salt prefix. -- */ --#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' --#ifdef USE_BCRYPT --/* Use $2b$ as prefix for compatibility with OpenBSD's bcrypt. */ --#define BCRYPTMAGNUM(array) (array)[0]=(array)[3]='$',(array)[1]='2',(array)[2]='b',(array)[4]='\0' --#endif /* USE_BCRYPT */ -- - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - /* It is not clear what is the maximum value of random(). - * We assume 2^31-1.*/ -@@ -122,26 +165,21 @@ static long shadow_random (long min, long max) - #endif /* USE_SHA_CRYPT || USE_BCRYPT */ - - #ifdef USE_SHA_CRYPT --/* Default number of rounds if not explicitly specified. */ --#define ROUNDS_DEFAULT 5000 --/* Minimum number of rounds. */ --#define ROUNDS_MIN 1000 --/* Maximum number of rounds. */ --#define ROUNDS_MAX 999999999 - /* -- * Return a salt prefix specifying the rounds number for the SHA crypt methods. -+ * Fill a salt prefix specifying the rounds number for the SHA crypt methods -+ * to a buffer. - */ --static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds) -+static /*@observer@*/void SHA_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) - { -- static char rounds_prefix[18]; /* Max size: rounds=999999999$ */ -- long rounds; -+ unsigned long rounds; -+ const size_t buf_begin = strlen (buf); - - if (NULL == prefered_rounds) { - long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); - long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1); - - if ((-1 == min_rounds) && (-1 == max_rounds)) { -- return ""; -+ rounds = SHA_ROUNDS_DEFAULT; - } - - if (-1 == min_rounds) { -@@ -156,196 +194,142 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds - max_rounds = min_rounds; - } - -- rounds = shadow_random (min_rounds, max_rounds); -+ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); - } else if (0 == *prefered_rounds) { -- return ""; -+ rounds = SHA_ROUNDS_DEFAULT; - } else { -- rounds = *prefered_rounds; -+ rounds = (unsigned long) *prefered_rounds; - } - - /* Sanity checks. The libc should also check this, but this - * protects against a rounds_prefix overflow. */ -- if (rounds < ROUNDS_MIN) { -- rounds = ROUNDS_MIN; -+ if (rounds < SHA_ROUNDS_MIN) { -+ rounds = SHA_ROUNDS_MIN; -+ } -+ -+ if (rounds > SHA_ROUNDS_MAX) { -+ rounds = SHA_ROUNDS_MAX; - } - -- if (rounds > ROUNDS_MAX) { -- rounds = ROUNDS_MAX; -+ /* Nothing to do here if SHA_ROUNDS_DEFAULT is used. */ -+ if (rounds == SHA_ROUNDS_DEFAULT) { -+ return; - } - -- (void) snprintf (rounds_prefix, sizeof rounds_prefix, -- "rounds=%ld$", rounds); -+ /* Check if the result buffer is long enough. */ -+ assert (GENSALT_SETTING_SIZE > buf_begin + 17); - -- return rounds_prefix; -+ (void) snprintf (buf + buf_begin, 18, "rounds=%lu$", rounds); - } - #endif /* USE_SHA_CRYPT */ - - #ifdef USE_BCRYPT --/* Default number of rounds if not explicitly specified. */ --#define B_ROUNDS_DEFAULT 13 --/* Minimum number of rounds. */ --#define B_ROUNDS_MIN 4 --/* Maximum number of rounds. */ --#define B_ROUNDS_MAX 31 - /* -- * Return a salt prefix specifying the rounds number for the BCRYPT method. -+ * Fill a salt prefix specifying the rounds number for the BCRYPT method -+ * to a buffer. - */ --static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds) -+static /*@observer@*/void BCRYPT_salt_rounds_to_buf (char *buf, /*@null@*/int *prefered_rounds) - { -- static char rounds_prefix[4]; /* Max size: 31$ */ -- long rounds; -+ unsigned long rounds; -+ const size_t buf_begin = strlen (buf); - - if (NULL == prefered_rounds) { - long min_rounds = getdef_long ("BCRYPT_MIN_ROUNDS", -1); - long max_rounds = getdef_long ("BCRYPT_MAX_ROUNDS", -1); - -- if (((-1 == min_rounds) && (-1 == max_rounds)) || (0 == *prefered_rounds)) { -+ if ((-1 == min_rounds) && (-1 == max_rounds)) { - rounds = B_ROUNDS_DEFAULT; -- } -- else { -+ } else { - if (-1 == min_rounds) { - min_rounds = max_rounds; - } -- -+ - if (-1 == max_rounds) { - max_rounds = min_rounds; - } -- -+ - if (min_rounds > max_rounds) { - max_rounds = min_rounds; - } -- -- rounds = shadow_random (min_rounds, max_rounds); -+ -+ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); - } -+ } else if (0 == *prefered_rounds) { -+ rounds = B_ROUNDS_DEFAULT; - } else { -- rounds = *prefered_rounds; -+ rounds = (unsigned long) *prefered_rounds; - } - -- /* -- * Sanity checks. -- * Use 19 as an upper bound for now, -- * because musl doesn't allow rounds >= 20. -- */ -+ /* Sanity checks. */ - if (rounds < B_ROUNDS_MIN) { - rounds = B_ROUNDS_MIN; - } - -+ /* -+ * Use 19 as an upper bound for now, -+ * because musl doesn't allow rounds >= 20. -+ */ - if (rounds > 19) { - /* rounds = B_ROUNDS_MAX; */ - rounds = 19; - } - -- (void) snprintf (rounds_prefix, sizeof rounds_prefix, -- "%2.2ld$", rounds); -- -- return rounds_prefix; --} -- --#define BCRYPT_SALT_SIZE 22 --/* -- * Generate a 22 character salt string for bcrypt. -- */ --static /*@observer@*/const char *gensalt_bcrypt (void) --{ -- static char salt[32]; -- -- salt[0] = '\0'; -+ /* Check if the result buffer is long enough. */ -+ assert (GENSALT_SETTING_SIZE > buf_begin + 3); - -- seedRNG (); -- strcat (salt, l64a (random())); -- do { -- strcat (salt, l64a (random())); -- } while (strlen (salt) < BCRYPT_SALT_SIZE); -- -- salt[BCRYPT_SALT_SIZE] = '\0'; -- -- return salt; -+ (void) snprintf (buf + buf_begin, 4, "%2.2lu$", rounds); - } - #endif /* USE_BCRYPT */ - - #ifdef USE_YESCRYPT --/* Default cost if not explicitly specified. */ --#define Y_COST_DEFAULT 5 --/* Minimum cost. */ --#define Y_COST_MIN 1 --/* Maximum cost. */ --#define Y_COST_MAX 11 - /* -- * Return a salt prefix specifying the cost for the YESCRYPT method. -+ * Fill a salt prefix specifying the cost for the YESCRYPT method -+ * to a buffer. - */ --static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/int *prefered_cost) -+static /*@observer@*/void YESCRYPT_salt_cost_to_buf (char *buf, /*@null@*/int *prefered_cost) - { -- static char cost_prefix[5]; -- long cost; -+ unsigned long cost; -+ const size_t buf_begin = strlen (buf); - - if (NULL == prefered_cost) { - cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); -+ } else if (0 == *prefered_cost) { -+ cost = Y_COST_DEFAULT; - } else { -- cost = *prefered_cost; -+ cost = (unsigned long) *prefered_cost; - } - -+ /* Sanity checks. */ - if (cost < Y_COST_MIN) { - cost = Y_COST_MIN; - } -+ - if (cost > Y_COST_MAX) { - cost = Y_COST_MAX; - } - -- cost_prefix[0] = 'j'; -+ /* Check if the result buffer is long enough. */ -+ assert (GENSALT_SETTING_SIZE > buf_begin + 3); -+ -+ buf[buf_begin + 0] = 'j'; - if (cost < 3) { -- cost_prefix[1] = 0x36 + cost; -+ buf[buf_begin + 1] = 0x36 + cost; - } else if (cost < 6) { -- cost_prefix[1] = 0x34 + cost; -+ buf[buf_begin + 1] = 0x34 + cost; - } else { -- cost_prefix[1] = 0x3b + cost; -+ buf[buf_begin + 1] = 0x3b + cost; - } -- cost_prefix[2] = cost >= 3 ? 'T' : '5'; -- cost_prefix[3] = '$'; -- cost_prefix[4] = 0; -- -- return cost_prefix; --} -- --/* -- * Default number of base64 characters used for the salt. -- * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more -- * traditional 128 bits (16 bytes) salt, this 144 bits salt is always -- * represented by the same number of base64 characters without padding -- * issue, even with a non-standard base64 encoding scheme. -- */ --#define YESCRYPT_SALT_SIZE 24 --/* -- * Generate a 22 character salt string for yescrypt. -- */ --static /*@observer@*/const char *gensalt_yescrypt (void) --{ -- static char salt[32]; -- -- salt[0] = '\0'; -- -- seedRNG (); -- strcat (salt, l64a (random())); -- do { -- strcat (salt, l64a (random())); -- } while (strlen (salt) < YESCRYPT_SALT_SIZE); -- -- salt[YESCRYPT_SALT_SIZE] = '\0'; -- -- return salt; -+ buf[buf_begin + 2] = cost >= 3 ? 'T' : '5'; -+ buf[buf_begin + 3] = '$'; -+ buf[buf_begin + 4] = '\0'; - } - #endif /* USE_YESCRYPT */ - --/* -- * Generate salt of size salt_size. -- */ --#define MAX_SALT_SIZE 16 --#define MIN_SALT_SIZE 8 -- - static /*@observer@*/const char *gensalt (size_t salt_size) - { -- static char salt[32]; -+ static char salt[MAX_SALT_SIZE + 6]; - -- salt[0] = '\0'; -+ memset (salt, '\0', MAX_SALT_SIZE + 6); - - assert (salt_size >= MIN_SALT_SIZE && - salt_size <= MAX_SALT_SIZE); -@@ -368,8 +352,9 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - * Other methods can be set with ENCRYPT_METHOD - * - * The method can be forced with the meth parameter. -- * If NULL, the method will be defined according to the MD5_CRYPT_ENAB and -- * ENCRYPT_METHOD login.defs variables. -+ * If NULL, the method will be defined according to the ENCRYPT_METHOD -+ * variable, and if not set according to the MD5_CRYPT_ENAB variable, -+ * which can both be set inside the login.defs file. - * - * If meth is specified, an additional parameter can be provided. - * * For the SHA256 and SHA512 method, this specifies the number of rounds -@@ -378,17 +363,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - */ - /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg) - { -- /* Max result size for the SHA methods: -- * +3 $5$ -- * +17 rounds=999999999$ -- * +16 salt -- * +1 \0 -- */ -- static char result[40]; -- size_t salt_len = 8; -+ static char result[GENSALT_SETTING_SIZE]; -+ size_t salt_len = MAX_SALT_SIZE; - const char *method; - -- result[0] = '\0'; -+ memset (result, '\0', GENSALT_SETTING_SIZE); - - if (NULL != meth) - method = meth; -@@ -401,61 +380,44 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - - if (0 == strcmp (method, "MD5")) { - MAGNUM(result, '1'); -+ salt_len = MD5_CRYPT_SALT_SIZE; - #ifdef USE_BCRYPT - } else if (0 == strcmp (method, "BCRYPT")) { - BCRYPTMAGNUM(result); -- strcat(result, BCRYPT_salt_rounds((int *)arg)); -+ salt_len = BCRYPT_SALT_SIZE; -+ BCRYPT_salt_rounds_to_buf (result, (int *) arg); - #endif /* USE_BCRYPT */ - #ifdef USE_YESCRYPT - } else if (0 == strcmp (method, "YESCRYPT")) { - MAGNUM(result, 'y'); -- strcat(result, YESCRYPT_salt_cost((int *)arg)); -+ salt_len = YESCRYPT_SALT_SIZE; -+ YESCRYPT_salt_cost_to_buf (result, (int *) arg); - #endif /* USE_YESCRYPT */ - #ifdef USE_SHA_CRYPT - } else if (0 == strcmp (method, "SHA256")) { - MAGNUM(result, '5'); -- strcat(result, SHA_salt_rounds((int *)arg)); -- salt_len = (size_t) shadow_random (8, 16); -+ salt_len = SHA_CRYPT_SALT_SIZE; -+ SHA_salt_rounds_to_buf (result, (int *) arg); - } else if (0 == strcmp (method, "SHA512")) { - MAGNUM(result, '6'); -- strcat(result, SHA_salt_rounds((int *)arg)); -- salt_len = (size_t) shadow_random (8, 16); -+ salt_len = SHA_CRYPT_SALT_SIZE; -+ SHA_salt_rounds_to_buf (result, (int *) arg); - #endif /* USE_SHA_CRYPT */ - } else if (0 != strcmp (method, "DES")) { - fprintf (shadow_logfd, - _("Invalid ENCRYPT_METHOD value: '%s'.\n" - "Defaulting to DES.\n"), - method); -- result[0] = '\0'; -+ salt_len = MAX_SALT_SIZE; -+ memset (result, '\0', GENSALT_SETTING_SIZE); - } - -- /* -- * Concatenate a pseudo random salt. -- */ -- assert (sizeof (result) > strlen (result) + salt_len); --#ifdef USE_BCRYPT -- if (0 == strcmp (method, "BCRYPT")) { -- strncat (result, gensalt_bcrypt (), -- sizeof (result) - strlen (result) - 1); -- return result; -- } else { --#endif /* USE_BCRYPT */ --#ifdef USE_YESCRYPT -- if (0 == strcmp (method, "YESCRYPT")) { -- strncat (result, gensalt_yescrypt (), -- sizeof (result) - strlen (result) - 1); -- return result; -- } else { --#endif /* USE_YESCRYPT */ -- strncat (result, gensalt (salt_len), -- sizeof (result) - strlen (result) - 1); --#ifdef USE_YESCRYPT -- } --#endif /* USE_YESCRYPT */ --#ifdef USE_BCRYPT -- } --#endif /* USE_BCRYPT */ -+ /* Check if the result buffer is long enough. */ -+ assert (GENSALT_SETTING_SIZE > strlen (result) + salt_len); -+ -+ /* Concatenate a pseudo random salt. */ -+ strncat (result, gensalt (salt_len), -+ GENSALT_SETTING_SIZE - strlen (result) - 1); - - return result; - } -- diff --git a/shadow-4.8.1-salt_c_use_dev_urandom.patch b/shadow-4.8.1-salt_c_use_dev_urandom.patch deleted file mode 100644 index ba37b77..0000000 --- a/shadow-4.8.1-salt_c_use_dev_urandom.patch +++ /dev/null @@ -1,114 +0,0 @@ -From bc8257cf73328e450511b13cbd35e1994feccb30 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Wed, 23 Jun 2021 16:06:47 +0200 -Subject: [PATCH] libmisc/salt.c: Obtain random bytes from /dev/urandom. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Using the random() function to obtain pseudo-random bytes -for generating salt strings is considered to be dangerous. -See CWE-327. - -We really should use a more reliable source for obtaining -pseudo-random bytes like /dev/urandom. - -Fixes #376. - -Signed-off-by: Björn Esser ---- - libmisc/salt.c | 45 ++++++++++++++++++++++++--------------------- - 1 file changed, 24 insertions(+), 21 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index e17093fc..af9f011f 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -11,11 +11,10 @@ - - #ident "$Id$" - --#include --#include --#include --#include - #include -+#include -+#include -+#include - #include "prototypes.h" - #include "defines.h" - #include "getdef.h" -@@ -74,7 +73,7 @@ - #define GENSALT_SETTING_SIZE 100 - - /* local function prototypes */ --static void seedRNG (void); -+static long read_random_bytes (void); - static /*@observer@*/const char *gensalt (size_t salt_size); - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) - static long shadow_random (long min, long max); -@@ -125,23 +124,27 @@ static /*@observer@*/char *l64a (long value) - } - #endif /* !HAVE_L64A */ - --static void seedRNG (void) -+/* Read sizeof (long) random bytes from /dev/urandom. */ -+static long read_random_bytes (void) - { -- struct timeval tv; -- static int seeded = 0; -+ long randval = 0; -+ FILE *f = fopen ("/dev/urandom", "r"); - -- if (0 == seeded) { -- (void) gettimeofday (&tv, NULL); -- srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ()); -- seeded = 1; -+ if (fread (&randval, sizeof (randval), 1, f) != sizeof (randval)) -+ { -+ fprintf (shadow_logfd, -+ _("Unable to read from /dev/urandom.\n")); -+ -+ fclose(f); -+ exit (1); - } -+ -+ fclose(f); -+ -+ return randval; - } - - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) --/* It is not clear what is the maximum value of random(). -- * We assume 2^31-1.*/ --#define RANDOM_MAX 0x7FFFFFFF -- - /* - * Return a random number between min and max (both included). - * -@@ -151,8 +154,9 @@ static long shadow_random (long min, long max) - { - double drand; - long ret; -- seedRNG (); -- drand = (double) (max - min + 1) * random () / RANDOM_MAX; -+ -+ drand = (double) (read_random_bytes () & RAND_MAX) / (double) RAND_MAX; -+ drand *= (double) (max - min + 1); - /* On systems were this is not random() range is lower, we favor - * higher numbers of salt. */ - ret = (long) (max + 1 - drand); -@@ -354,10 +358,9 @@ static /*@observer@*/const char *gensalt (size_t salt_size) - - assert (salt_size >= MIN_SALT_SIZE && - salt_size <= MAX_SALT_SIZE); -- seedRNG (); -- strcat (salt, l64a (random())); -+ strcat (salt, l64a (read_random_bytes ())); - do { -- strcat (salt, l64a (random())); -+ strcat (salt, l64a (read_random_bytes ())); - } while (strlen (salt) < salt_size); - - salt[salt_size] = '\0'; diff --git a/shadow-4.8.1-useradd-man-clarification.patch b/shadow-4.8.1-useradd-man-clarification.patch deleted file mode 100644 index 9fdb652..0000000 --- a/shadow-4.8.1-useradd-man-clarification.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6543c600d841e4f7779269412d470e50eae25b13 Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Wed, 4 Mar 2020 14:50:04 +0100 -Subject: [PATCH] useradd: clarify the useradd -d parameter behavior in man - page - -Explanation: clarify the useradd -d parameter as it does create directory HOME_DIR if it doesn't exit. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1677005 - -Changelog: [serge] minor tweak to the text ---- - man/useradd.8.xml | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/man/useradd.8.xml b/man/useradd.8.xml -index 03612ce8..023c0d69 100644 ---- a/man/useradd.8.xml -+++ b/man/useradd.8.xml -@@ -181,8 +181,10 @@ - login directory. The default is to append the - LOGIN name to - BASE_DIR and use that as the login -- directory name. The directory HOME_DIR -- does not have to exist but will not be created if it is missing. -+ directory name. If the directory -+ HOME_DIR does not exist, then it -+ will be created unless the option is -+ specified. - - - --- -2.25.1 - diff --git a/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch b/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch deleted file mode 100644 index f393368..0000000 --- a/shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 663824ef4ca927aa2b4319b69e0bfa68282ec719 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sat, 22 May 2021 11:42:02 -0500 -Subject: [PATCH] Fix useradd with SUB_UID_COUNT=0 - -Closes #298 - -Fix useradd when SUB_UID_COUNT=0 in login.defs. - -Signed-off-by: Serge Hallyn ---- - src/useradd.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 06accb2f..9862ae55 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2386,6 +2386,8 @@ int main (int argc, char **argv) - #ifdef ENABLE_SUBIDS - uid_t uid_min; - uid_t uid_max; -+ unsigned long subuid_count; -+ unsigned long subgid_count; - #endif - - /* -@@ -2427,9 +2429,11 @@ int main (int argc, char **argv) - #ifdef ENABLE_SUBIDS - uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); - uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); -- is_sub_uid = sub_uid_file_present () && !rflg && -+ subuid_count = getdef_ulong ("SUB_UID_COUNT", 65536); -+ subgid_count = getdef_ulong ("SUB_GID_COUNT", 65536); -+ is_sub_uid = subuid_count > 0 && sub_uid_file_present () && !rflg && - (!user_id || (user_id <= uid_max && user_id >= uid_min)); -- is_sub_gid = sub_gid_file_present () && !rflg && -+ is_sub_gid = subgid_count > 0 && sub_gid_file_present () && !rflg && - (!user_id || (user_id <= uid_max && user_id >= uid_min)); - #endif /* ENABLE_SUBIDS */ - --- -2.30.2 - diff --git a/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch b/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch deleted file mode 100644 index a318f7a..0000000 --- a/shadow-4.8.1-useradd_create_relative_home_path_correctly.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff -up shadow-4.8.1/src/useradd.c.useradd_create_relative_home_path_correctly shadow-4.8.1/src/useradd.c ---- shadow-4.8.1/src/useradd.c.useradd_create_relative_home_path_correctly 2021-06-28 16:10:23.928435372 +0200 -+++ shadow-4.8.1/src/useradd.c 2021-06-28 16:11:30.784495046 +0200 -@@ -2140,7 +2140,6 @@ static void create_home (void) - Prog, user_home); - fail_exit (E_HOMEDIR); - } -- ++bhome; - - #ifdef WITH_SELINUX - if (set_selinux_file_context (prefix_user_home, NULL) != 0) { -@@ -2157,7 +2156,11 @@ static void create_home (void) - */ - cp = strtok (bhome, "/"); - while (cp) { -- strcat (path, "/"); -+ /* Avoid turning a relative path into an absolute path. -+ */ -+ if (bhome[0] == '/' || strlen (path) != 0) { -+ strcat (path, "/"); -+ } - strcat (path, cp); - if (access (path, F_OK) != 0) { - /* Check if parent directory is BTRFS, fail if requesting diff --git a/shadow-4.8.1-yescrypt-support.patch b/shadow-4.8.1-yescrypt-support.patch deleted file mode 100644 index aff941b..0000000 --- a/shadow-4.8.1-yescrypt-support.patch +++ /dev/null @@ -1,960 +0,0 @@ -From 5cd04d03f94622c12220d4a6352824af081b8531 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= -Date: Sun, 27 Dec 2020 21:09:25 +0100 -Subject: [PATCH] Add yescrypt support - ---- - configure.ac | 13 +++++ - etc/login.defs | 14 +++++ - lib/encrypt.c | 3 ++ - lib/getdef.c | 3 ++ - libmisc/obscure.c | 3 ++ - libmisc/salt.c | 94 +++++++++++++++++++++++++++++++- - src/chgpasswd.c | 113 ++++++++++++++++++++------------------ - src/chpasswd.c | 107 +++++++++++++++++++----------------- - src/newusers.c | 134 +++++++++++++++++++++++++--------------------- - src/passwd.c | 3 ++ - 10 files changed, 322 insertions(+), 165 deletions(-) - -Index: shadow-4.8.1/configure.ac -=================================================================== ---- shadow-4.8.1.orig/configure.ac -+++ shadow-4.8.1/configure.ac -@@ -290,6 +290,9 @@ AC_ARG_WITH(sha-crypt, - AC_ARG_WITH(bcrypt, - [AC_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])], - [with_bcrypt=$withval], [with_bcrypt=no]) -+AC_ARG_WITH(yescrypt, -+ [AC_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])], -+ [with_yescrypt=$withval], [with_yescrypt=no]) - AC_ARG_WITH(nscd, - [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])], - [with_nscd=$withval], [with_nscd=yes]) -@@ -322,6 +325,11 @@ if test "$with_bcrypt" = "yes"; then - AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm]) - fi - -+AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes") -+if test "$with_yescrypt" = "yes"; then -+ AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm]) -+fi -+ - if test "$with_nscd" = "yes"; then - AC_CHECK_FUNC(posix_spawn, - [AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])], -@@ -402,6 +410,10 @@ AC_SUBST(LIBCRYPT) - AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], - [AC_MSG_ERROR([crypt() not found])]) - -+AC_SUBST(LIYESCRYPT) -+AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt], -+ [AC_MSG_ERROR([crypt() not found])]) -+ - AC_SUBST(LIBACL) - if test "$with_acl" != "no"; then - AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"]) -@@ -752,6 +764,7 @@ echo " shadow group support: $enable_sh - echo " S/Key support: $with_skey" - echo " SHA passwords encryption: $with_sha_crypt" - echo " bcrypt passwords encryption: $with_bcrypt" -+echo " yescrypt passwords encryption: $with_yescrypt" - echo " nscd support: $with_nscd" - echo " sssd support: $with_sssd" - echo " subordinate IDs support: $enable_subids" -Index: shadow-4.8.1/etc/login.defs -=================================================================== ---- shadow-4.8.1.orig/etc/login.defs -+++ shadow-4.8.1/etc/login.defs -@@ -326,6 +326,7 @@ CHFN_RESTRICT rwh - # If set to SHA256, SHA256-based algorithm will be used for encrypting password - # If set to SHA512, SHA512-based algorithm will be used for encrypting password - # If set to BCRYPT, BCRYPT-based algorithm will be used for encrypting password -+# If set to YESCRYPT, YESCRYPT-based algorithm will be used for encrypting password - # If set to DES, DES-based algorithm will be used for encrypting password (default) - # Overrides the MD5_CRYPT_ENAB option - # -@@ -366,6 +367,19 @@ CHFN_RESTRICT rwh - #BCRYPT_MAX_ROUNDS 13 - - # -+# Only works if ENCRYPT_METHOD is set to YESCRYPT. -+# -+# Define the YESCRYPT cost factor. -+# With a higher cost factor, it is more difficult to brute-force the password. -+# However, more CPU time and more memory will be needed to authenticate users -+# if this value is increased. -+# -+# If not specified, a cost factor of 5 will be used. -+# The value must be within the 1-11 range. -+# -+#YESCRYPT_COST_FACTOR 5 -+ -+# - # List of groups to add to the user's supplementary group set - # when logging in from the console (as determined by the CONSOLE - # setting). Default is none. -Index: shadow-4.8.1/lib/encrypt.c -=================================================================== ---- shadow-4.8.1.orig/lib/encrypt.c -+++ shadow-4.8.1/lib/encrypt.c -@@ -74,6 +74,9 @@ - case '6': - method = "SHA512"; - break; -+ case 'y': -+ method = "YESCRYPT"; -+ break; - default: - { - static char nummethod[4] = "$x$"; -Index: shadow-4.8.1/lib/getdef.c -=================================================================== ---- shadow-4.8.1.orig/lib/getdef.c -+++ shadow-4.8.1/lib/getdef.c -@@ -117,6 +117,9 @@ static struct itemdef def_table[] = { - {"BCRYPT_MAX_ROUNDS", NULL}, - {"BCRYPT_MIN_ROUNDS", NULL}, - #endif -+#ifdef USE_YESCRYPT -+ {"YESCRYPT_COST_FACTOR", NULL}, -+#endif - {"SUB_GID_COUNT", NULL}, - {"SUB_GID_MAX", NULL}, - {"SUB_GID_MIN", NULL}, -Index: shadow-4.8.1/libmisc/obscure.c -=================================================================== ---- shadow-4.8.1.orig/libmisc/obscure.c -+++ shadow-4.8.1/libmisc/obscure.c -@@ -272,6 +272,9 @@ static /*@observer@*//*@null@*/const cha - #ifdef USE_BCRYPT - || (strcmp (result, "BCRYPT") == 0) - #endif -+#ifdef USE_YESCRYPT -+ || (strcmp (result, "YESCRYPT") == 0) -+#endif - ) { - return NULL; - } -Index: shadow-4.8.1/libmisc/salt.c -=================================================================== ---- shadow-4.8.1.orig/libmisc/salt.c -+++ shadow-4.8.1/libmisc/salt.c -@@ -32,6 +32,10 @@ static /*@observer@*/const char *SHA_sal - static /*@observer@*/const char *gensalt_bcrypt (void); - static /*@observer@*/const char *BCRYPT_salt_rounds (/*@null@*/int *prefered_rounds); - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+static /*@observer@*/const char *gensalt_yescrypt (void); -+static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_rounds); -+#endif /* USE_YESCRYPT */ - - #ifndef HAVE_L64A - static /*@observer@*/char *l64a(long value) -@@ -263,6 +267,78 @@ static /*@observer@*/const char *gensalt - } - #endif /* USE_BCRYPT */ - -+#ifdef USE_YESCRYPT -+/* Default cost if not explicitly specified. */ -+#define Y_COST_DEFAULT 5 -+/* Minimum cost. */ -+#define Y_COST_MIN 1 -+/* Maximum cost. */ -+#define Y_COST_MAX 11 -+/* -+ * Return a salt prefix specifying the cost for the YESCRYPT method. -+ */ -+static /*@observer@*/const char *YESCRYPT_salt_cost (/*@null@*/long *prefered_cost) -+{ -+ static char cost_prefix[5]; -+ long cost; -+ -+ if (NULL == prefered_cost) { -+ cost = getdef_num ("YESCRYPT_COST_FACTOR", Y_COST_DEFAULT); -+ } else { -+ cost = *prefered_cost; -+ } -+ -+ if (cost < Y_COST_MIN) { -+ cost = Y_COST_MIN; -+ } -+ if (cost > Y_COST_MAX) { -+ cost = Y_COST_MAX; -+ } -+ -+ cost_prefix[0] = 'j'; -+ if (cost < 3) { -+ cost_prefix[1] = 0x36 + cost; -+ } else if (cost < 6) { -+ cost_prefix[1] = 0x34 + cost; -+ } else { -+ cost_prefix[1] = 0x3b + cost; -+ } -+ cost_prefix[2] = cost >= 3 ? 'T' : '5'; -+ cost_prefix[3] = '$'; -+ cost_prefix[4] = 0; -+ -+ return cost_prefix; -+} -+ -+/* -+ * Default number of base64 characters used for the salt. -+ * 24 characters gives a 144 bits (18 bytes) salt. Unlike the more -+ * traditional 128 bits (16 bytes) salt, this 144 bits salt is always -+ * represented by the same number of base64 characters without padding -+ * issue, even with a non-standard base64 encoding scheme. -+ */ -+#define YESCRYPT_SALT_SIZE 24 -+/* -+ * Generate a 22 character salt string for yescrypt. -+ */ -+static /*@observer@*/const char *gensalt_yescrypt (void) -+{ -+ static char salt[32]; -+ -+ salt[0] = '\0'; -+ -+ seedRNG (); -+ strcat (salt, l64a (random())); -+ do { -+ strcat (salt, l64a (random())); -+ } while (strlen (salt) < YESCRYPT_SALT_SIZE); -+ -+ salt[YESCRYPT_SALT_SIZE] = '\0'; -+ -+ return salt; -+} -+#endif /* USE_YESCRYPT */ -+ - /* - * Generate salt of size salt_size. - */ -@@ -302,6 +378,7 @@ static /*@observer@*/const char *gensalt - * If meth is specified, an additional parameter can be provided. - * * For the SHA256 and SHA512 method, this specifies the number of rounds - * (if not NULL). -+ * * For the YESCRYPT method, this specifies the cost factor (if not NULL). - */ - /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg) - { -@@ -333,6 +410,11 @@ static /*@observer@*/const char *gensalt - BCRYPTMAGNUM(result); - strcat(result, BCRYPT_salt_rounds((int *)arg)); - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+ } else if (0 == strcmp (method, "YESCRYPT")) { -+ MAGNUM(result, 'y'); -+ strcat(result, YESCRYPT_salt_cost((int *)arg)); -+#endif /* USE_YESCRYPT */ - #ifdef USE_SHA_CRYPT - } else if (0 == strcmp (method, "SHA256")) { - MAGNUM(result, '5'); -@@ -362,11 +444,21 @@ static /*@observer@*/const char *gensalt - return result; - } else { - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+ if (0 == strcmp (method, "YESCRYPT")) { -+ strncat (result, gensalt_yescrypt (), -+ sizeof (result) - strlen (result) - 1); -+ return result; -+ } else { -+#endif /* USE_YESCRYPT */ - strncat (result, gensalt (salt_len), - sizeof (result) - strlen (result) - 1); -+#ifdef USE_YESCRYPT -+ } -+#endif /* USE_YESCRYPT */ - #ifdef USE_BCRYPT - } --#endif /* USE_BCRYPT */ -+#endif /* USE_BCRYPT */ - - return result; - } -Index: shadow-4.8.1/src/chgpasswd.c -=================================================================== ---- shadow-4.8.1.orig/src/chgpasswd.c -+++ shadow-4.8.1/src/chgpasswd.c -@@ -69,9 +69,9 @@ const char *Prog; - FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - static bool sflg = false; --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - - static /*@null@*//*@observer@*/const char *crypt_method = NULL; - #define cflg (NULL != crypt_method) -@@ -81,6 +81,9 @@ static long sha_rounds = 5000; - #ifdef USE_BCRYPT - static long bcrypt_rounds = 13; - #endif -+#ifdef USE_YESCRYPT -+static long yescrypt_cost = 5; -+#endif - - #ifdef SHADOWGRP - static bool is_shadow_grp; -@@ -139,14 +142,15 @@ static /*@noreturn@*/void usage (int sta - Prog); - (void) fprintf (usageout, - _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), --#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) - "NONE DES MD5" --#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -- "NONE DES MD5 SHA256 SHA512 BCRYPT" --#elif defined(USE_SHA_CRYPT) -- "NONE DES MD5 SHA256 SHA512" --#else -- "NONE DES MD5 BCRYPT" -+#if defined(USE_SHA_CRYPT) -+ " SHA256 SHA512" -+#endif -+#if defined(USE_BCRYPT) -+ " BCRYPT" -+#endif -+#if defined(USE_YESCRYPT) -+ " YESCRYPT" - #endif - ); - (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); -@@ -155,11 +159,11 @@ static /*@noreturn@*/void usage (int sta - " the MD5 algorithm\n"), - usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" -- " crypt algorithms\n"), -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -+ " or YESCRYPT crypt algorithms\n"), - usageout); --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - (void) fputs ("\n", usageout); - - exit (status); -@@ -173,19 +177,22 @@ static /*@noreturn@*/void usage (int sta - static void process_flags (int argc, char **argv) - { - int c; -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ int bad_s; -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - static struct option long_options[] = { - {"crypt-method", required_argument, NULL, 'c'}, - {"encrypted", no_argument, NULL, 'e'}, - {"help", no_argument, NULL, 'h'}, - {"md5", no_argument, NULL, 'm'}, - {"root", required_argument, NULL, 'R'}, --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - {"sha-rounds", required_argument, NULL, 's'}, --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - {NULL, 0, NULL, '\0'} - }; - while ((c = getopt_long (argc, argv, --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:ehmR:s:", - #else - "c:ehmR:", -@@ -206,40 +213,36 @@ static void process_flags (int argc, cha - break; - case 'R': /* no-op, handled in process_root_flag () */ - break; --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': - sflg = true; -+ bad_s = 0; -+#if defined(USE_SHA_CRYPT) - if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) -- && (0 == getlong(optarg, &sha_rounds))) -- || ( (0 == strcmp (crypt_method, "BCRYPT")) -+ && (0 == getlong(optarg, &sha_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) -+ if (( (0 == strcmp (crypt_method, "BCRYPT")) - && (0 == getlong(optarg, &bcrypt_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) -+ if (( (0 == strcmp (crypt_method, "YESCRYPT")) -+ && (0 == getlong(optarg, &yescrypt_cost)))) { -+ bad_s = 1; -+ } -+#endif /* USE_YESCRYPT */ -+ if (bad_s != 0) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; --#elif defined(USE_SHA_CRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &sha_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (E_USAGE); -- } -- break; --#elif defined(USE_BCRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &bcrypt_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (E_USAGE); -- } -- break; --#endif -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - - default: - usage (E_USAGE); -@@ -258,7 +261,7 @@ static void process_flags (int argc, cha - */ - static void check_flags (void) - { --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg && !cflg) { - fprintf (stderr, - _("%s: %s flag is only allowed with the %s flag\n"), -@@ -282,10 +285,13 @@ static void check_flags (void) - #ifdef USE_SHA_CRYPT - && (0 != strcmp (crypt_method, "SHA256")) - && (0 != strcmp (crypt_method, "SHA512")) --#endif -+#endif /* USE_SHA_CRYPT */ - #ifdef USE_BCRYPT - && (0 != strcmp (crypt_method, "BCRYPT")) --#endif -+#endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+ && (0 != strcmp (crypt_method, "YESCRYPT")) -+#endif /* USE_YESCRYPT */ - ) { - fprintf (stderr, - _("%s: unsupported crypt method: %s\n"), -@@ -592,23 +598,24 @@ int main (int argc, char **argv) - if (md5flg) { - crypt_method = "MD5"; - } --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg) { -+#if defined(USE_SHA_CRYPT) - if ( (0 == strcmp (crypt_method, "SHA256")) - || (0 == strcmp (crypt_method, "SHA512"))) { - arg = &sha_rounds; - } -- else if (0 == strcmp (crypt_method, "BCRYPT")) { -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) -+ if (0 == strcmp (crypt_method, "BCRYPT")) { - arg = &bcrypt_rounds; - } -- } --#elif defined(USE_SHA_CRYPT) -- if (sflg) { -- arg = &sha_rounds; -- } --#elif defined(USE_BCRYPT) -- if (sflg) { -- arg = &bcrypt_rounds; -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) -+ if (0 == strcmp (crypt_method, "YESCRYPT")) { -+ arg = &yescrypt_cost; -+ } -+#endif /* USE_YESCRYPT */ - } - #endif - salt = crypt_make_salt (crypt_method, arg); -Index: shadow-4.8.1/src/chpasswd.c -=================================================================== ---- shadow-4.8.1.orig/src/chpasswd.c -+++ shadow-4.8.1/src/chpasswd.c -@@ -66,7 +66,7 @@ const char *Prog; - FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - static bool sflg = false; - #endif - -@@ -78,6 +78,9 @@ static long sha_rounds = 5000; - #ifdef USE_BCRYPT - static long bcrypt_rounds = 13; - #endif -+#ifdef USE_YESCRYPT -+static long yescrypt_cost = 5; -+#endif - - static bool is_shadow_pwd; - static bool pw_locked = false; -@@ -129,14 +132,15 @@ static /*@noreturn@*/void usage (int sta - Prog); - (void) fprintf (usageout, - _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), --#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) - "NONE DES MD5" --#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -- "NONE DES MD5 SHA256 SHA512 BCRYPT" --#elif defined(USE_SHA_CRYPT) -- "NONE DES MD5 SHA256 SHA512" --#else -- "NONE DES MD5 BCRYPT" -+#if defined(USE_SHA_CRYPT) -+ " SHA256 SHA512" -+#endif -+#if defined(USE_BCRYPT) -+ " BCRYPT" -+#endif -+#if defined(USE_YESCRYPT) -+ " YESCRYPT" - #endif - ); - (void) fputs (_(" -e, --encrypted supplied passwords are encrypted\n"), usageout); -@@ -145,11 +149,11 @@ static /*@noreturn@*/void usage (int sta - " the MD5 algorithm\n"), - usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" -- " crypt algorithms\n"), -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -+ " or YESCRYPT crypt algorithms\n"), - usageout); --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - (void) fputs ("\n", usageout); - - exit (status); -@@ -163,20 +167,23 @@ static /*@noreturn@*/void usage (int sta - static void process_flags (int argc, char **argv) - { - int c; -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ int bad_s; -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - static struct option long_options[] = { - {"crypt-method", required_argument, NULL, 'c'}, - {"encrypted", no_argument, NULL, 'e'}, - {"help", no_argument, NULL, 'h'}, - {"md5", no_argument, NULL, 'm'}, - {"root", required_argument, NULL, 'R'}, --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - {"sha-rounds", required_argument, NULL, 's'}, --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - {NULL, 0, NULL, '\0'} - }; - - while ((c = getopt_long (argc, argv, --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:ehmR:s:", - #else - "c:ehmR:", -@@ -197,40 +204,36 @@ static void process_flags (int argc, cha - break; - case 'R': /* no-op, handled in process_root_flag () */ - break; --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': - sflg = true; -+ bad_s = 0; -+#if defined(USE_SHA_CRYPT) - if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) -- && (0 == getlong(optarg, &sha_rounds))) -- || ( (0 == strcmp (crypt_method, "BCRYPT")) -+ && (0 == getlong(optarg, &sha_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) -+ if (( (0 == strcmp (crypt_method, "BCRYPT")) - && (0 == getlong(optarg, &bcrypt_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) -+ if (( (0 == strcmp (crypt_method, "YESCRYPT")) -+ && (0 == getlong(optarg, &yescrypt_cost)))) { -+ bad_s = 1; -+ } -+#endif /* USE_YESCRYPT */ -+ if (bad_s != 0) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (E_USAGE); - } - break; --#elif defined(USE_SHA_CRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &sha_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (E_USAGE); -- } -- break; --#elif defined(USE_BCRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &bcrypt_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (E_USAGE); -- } -- break; --#endif -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - - default: - usage (E_USAGE); -@@ -249,7 +252,7 @@ static void process_flags (int argc, cha - */ - static void check_flags (void) - { --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg && !cflg) { - fprintf (stderr, - _("%s: %s flag is only allowed with the %s flag\n"), -@@ -277,6 +280,9 @@ static void check_flags (void) - #ifdef USE_BCRYPT - && (0 != strcmp (crypt_method, "BCRYPT")) - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+ && (0 != strcmp (crypt_method, "YESCRYPT")) -+#endif /* USE_YESCRYPT */ - ) { - fprintf (stderr, - _("%s: unsupported crypt method: %s\n"), -@@ -604,23 +610,24 @@ int main (int argc, char **argv) - if (md5flg) { - crypt_method = "MD5"; - } --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg) { -+#if defined(USE_SHA_CRYPT) - if ( (0 == strcmp (crypt_method, "SHA256")) - || (0 == strcmp (crypt_method, "SHA512"))) { - arg = &sha_rounds; - } -- else if (0 == strcmp (crypt_method, "BCRYPT")) { -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) -+ if (0 == strcmp (crypt_method, "BCRYPT")) { - arg = &bcrypt_rounds; - } -- } --#elif defined(USE_SHA_CRYPT) -- if (sflg) { -- arg = &sha_rounds; -- } --#elif defined(USE_BCRYPT) -- if (sflg) { -- arg = &bcrypt_rounds; -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) -+ if (0 == strcmp (crypt_method, "YESCRYPT")) { -+ arg = &yescrypt_cost; -+ } -+#endif /* USE_YESCRYPT */ - } - #endif - salt = crypt_make_salt (crypt_method, arg); -Index: shadow-4.8.1/src/newusers.c -=================================================================== ---- shadow-4.8.1.orig/src/newusers.c -+++ shadow-4.8.1/src/newusers.c -@@ -90,6 +90,9 @@ static long sha_rounds = 5000; - #ifdef USE_BCRYPT - static long bcrypt_rounds = 13; - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+static long yescrypt_cost = 5; -+#endif /* USE_YESCRYPT */ - #endif /* !USE_PAM */ - - static bool is_shadow; -@@ -140,14 +143,15 @@ static void usage (int status) - #ifndef USE_PAM - (void) fprintf (usageout, - _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), --#if !defined(USE_SHA_CRYPT) && !defined(USE_BCRYPT) -- "NONE DES MD5" --#elif defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -- "NONE DES MD5 SHA256 SHA512 BCRYPT" --#elif defined(USE_SHA_CRYPT) -- "NONE DES MD5 SHA256 SHA512" --#else -- "NONE DES MD5 BCRYPT" -+ "NONE DES MD5" -+#if defined(USE_SHA_CRYPT) -+ " SHA256 SHA512" -+#endif -+#if defined(USE_BCRYPT) -+ " BCRYPT" -+#endif -+#if defined(USE_YESCRYPT) -+ " YESCRYPT" - #endif - ); - #endif /* !USE_PAM */ -@@ -155,11 +159,11 @@ static void usage (int status) - (void) fputs (_(" -r, --system create system accounts\n"), usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); - #ifndef USE_PAM --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -- (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" -- " crypt algorithms\n"), -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -+ " or YESCRYPT crypt algorithms\n"), - usageout); --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ - (void) fputs ("\n", usageout); - -@@ -434,25 +438,28 @@ static int update_passwd (struct passwd - void *crypt_arg = NULL; - char *cp; - if (NULL != crypt_method) { --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) - if (sflg) { - if ( (0 == strcmp (crypt_method, "SHA256")) - || (0 == strcmp (crypt_method, "SHA512"))) { - crypt_arg = &sha_rounds; - } -- else if (0 == strcmp (crypt_method, "BCRYPT")) { -- crypt_arg = &bcrypt_rounds; -- } - } --#elif defined(USE_SHA_CRYPT) -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) - if (sflg) { -- crypt_arg = &sha_rounds; -+ if (0 == strcmp (crypt_method, "BCRYPT")) { -+ crypt_arg = &bcrypt_rounds; -+ } - } --#elif defined(USE_BCRYPT) -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) - if (sflg) { -- crypt_arg = &bcrypt_rounds; -+ if (0 == strcmp (crypt_method, "YESCRYPT")) { -+ crypt_arg = &yescrypt_cost; -+ } - } --#endif -+#endif /* USE_YESCRYPT */ - } - - if ((NULL != crypt_method) && (0 == strcmp(crypt_method, "NONE"))) { -@@ -485,25 +492,28 @@ static int add_passwd (struct passwd *pw - #ifndef USE_PAM - void *crypt_arg = NULL; - if (NULL != crypt_method) { --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) - if (sflg) { - if ( (0 == strcmp (crypt_method, "SHA256")) - || (0 == strcmp (crypt_method, "SHA512"))) { - crypt_arg = &sha_rounds; - } -- else if (0 == strcmp (crypt_method, "BCRYPT")) { -- crypt_arg = &bcrypt_rounds; -- } - } --#elif defined(USE_SHA_CRYPT) -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) - if (sflg) { -- crypt_arg = &sha_rounds; -+ if (0 == strcmp (crypt_method, "BCRYPT")) { -+ crypt_arg = &bcrypt_rounds; -+ } - } --#elif defined(USE_BCRYPT) -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) - if (sflg) { -- crypt_arg = &bcrypt_rounds; -+ if (0 == strcmp (crypt_method, "YESCRYPT")) { -+ crypt_arg = &yescrypt_cost; -+ } - } --#endif -+#endif /* USE_PAM */ - } - - /* -@@ -620,6 +630,9 @@ static int add_passwd (struct passwd *pw - static void process_flags (int argc, char **argv) - { - int c; -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -+ int bad_s; -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - static struct option long_options[] = { - {"badnames", no_argument, NULL, 'b'}, - #ifndef USE_PAM -@@ -629,20 +642,20 @@ static void process_flags (int argc, cha - {"system", no_argument, NULL, 'r'}, - {"root", required_argument, NULL, 'R'}, - #ifndef USE_PAM --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - {"sha-rounds", required_argument, NULL, 's'}, --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ - {NULL, 0, NULL, '\0'} - }; - - while ((c = getopt_long (argc, argv, - #ifndef USE_PAM --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:bhrs:", --#else /* !USE_SHA_CRYPT && !USE_BCRYPT */ -+#else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ - "c:bhr", --#endif /* USE_SHA_CRYPT || USE_BCRYPT */ -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #else /* USE_PAM */ - "bhr", - #endif -@@ -665,40 +678,36 @@ static void process_flags (int argc, cha - case 'R': /* no-op, handled in process_root_flag () */ - break; - #ifndef USE_PAM --#if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': - sflg = true; -+ bad_s = 0; -+#if defined(USE_SHA_CRYPT) - if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512"))) -- && (0 == getlong(optarg, &sha_rounds))) -- || ( (0 == strcmp (crypt_method, "BCRYPT")) -+ && (0 == getlong(optarg, &sha_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_SHA_CRYPT */ -+#if defined(USE_BCRYPT) -+ if (( (0 == strcmp (crypt_method, "BCRYPT")) - && (0 == getlong(optarg, &bcrypt_rounds)))) { -+ bad_s = 1; -+ } -+#endif /* USE_BCRYPT */ -+#if defined(USE_YESCRYPT) -+ if (( (0 == strcmp (crypt_method, "YESCRYPT")) -+ && (0 == getlong(optarg, &yescrypt_cost)))) { -+ bad_s = 1; -+ } -+#endif /* USE_YESCRYPT */ -+ if (bad_s != 0) { - fprintf (stderr, - _("%s: invalid numeric argument '%s'\n"), - Prog, optarg); - usage (EXIT_FAILURE); - } - break; --#elif defined(USE_SHA_CRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &sha_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (EXIT_FAILURE); -- } -- break; --#elif defined(USE_BCRYPT) -- case 's': -- sflg = true; -- if (0 == getlong(optarg, &bcrypt_rounds)) { -- fprintf (stderr, -- _("%s: invalid numeric argument '%s'\n"), -- Prog, optarg); -- usage (EXIT_FAILURE); -- } -- break; --#endif -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ - default: - usage (EXIT_FAILURE); -@@ -732,14 +741,14 @@ static void process_flags (int argc, cha - static void check_flags (void) - { - #ifndef USE_PAM --#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) -+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg && !cflg) { - fprintf (stderr, - _("%s: %s flag is only allowed with the %s flag\n"), - Prog, "-s", "-c"); - usage (EXIT_FAILURE); - } --#endif -+#endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - - if (cflg) { - if ( (0 != strcmp (crypt_method, "DES")) -@@ -752,6 +761,9 @@ static void check_flags (void) - #ifdef USE_BCRYPT - && (0 != strcmp (crypt_method, "BCRYPT")) - #endif /* USE_BCRYPT */ -+#ifdef USE_YESCRYPT -+ && (0 != strcmp (crypt_method, "YESCRYPT")) -+#endif /* USE_YESCRYPT */ - ) { - fprintf (stderr, - _("%s: unsupported crypt method: %s\n"), -Index: shadow-4.8.1/src/passwd.c -=================================================================== ---- shadow-4.8.1.orig/src/passwd.c -+++ shadow-4.8.1/src/passwd.c -@@ -283,7 +283,10 @@ static int new_password (const struct pa - #endif /* USE_SHA_CRYPT */ - #ifdef USE_BCRYPT - || (strcmp (method, "BCRYPT") == 0) --#endif /* USE_SHA_CRYPT */ -+#endif /* USE_BCRYPT*/ -+#ifdef USE_YESCRYPT -+ || (strcmp (method, "YESCRYPT") == 0) -+#endif /* USE_YESCRYPT*/ - - ) { - pass_max_len = -1; diff --git a/shadow-4.8.1-audit-update.patch b/shadow-4.9-audit-update.patch similarity index 99% rename from shadow-4.8.1-audit-update.patch rename to shadow-4.9-audit-update.patch index 1b9586a..99513ef 100644 --- a/shadow-4.8.1-audit-update.patch +++ b/shadow-4.9-audit-update.patch @@ -1537,24 +1537,6 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1592,7 +1540,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking group file", -+ "unlocking-group-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1606,7 +1554,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking gshadow file", -+ "unlocking-gshadow-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif @@ -1622,7 +1570,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT @@ -1644,7 +1626,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c } if (chown (path, 0, 0) < 0) { @@ -2168,8 +2109,8 @@ static void create_home (void) - chmod (prefix_user_home, mode); + } home_added = true; #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, @@ -1705,8 +1687,8 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c + user_name, (unsigned int) user_id, + SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ - rv = E_SE_UPDATE; - } + fail_exit (E_SE_UPDATE); + } diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c --- shadow-4.8.1/src/userdel.c.audit-update 2020-03-17 16:53:44.368943259 +0100 +++ shadow-4.8.1/src/userdel.c 2020-03-17 16:53:44.373943325 +0100 diff --git a/shadow-4.1.5.1-default-range.patch b/shadow-4.9-default-range.patch similarity index 72% rename from shadow-4.1.5.1-default-range.patch rename to shadow-4.9-default-range.patch index 2a9d640..f6e0427 100644 --- a/shadow-4.1.5.1-default-range.patch +++ b/shadow-4.9-default-range.patch @@ -1,7 +1,6 @@ -Index: shadow-4.5/lib/semanage.c -=================================================================== ---- shadow-4.5.orig/lib/semanage.c -+++ shadow-4.5/lib/semanage.c +diff -up shadow-4.9/lib/semanage.c.default-range shadow-4.9/lib/semanage.c +--- shadow-4.9/lib/semanage.c.default-range 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/semanage.c 2021-08-02 12:43:16.822817392 +0200 @@ -143,6 +143,7 @@ static int semanage_user_mod (semanage_h goto done; } @@ -9,7 +8,7 @@ Index: shadow-4.5/lib/semanage.c +#if 0 ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); if (ret != 0) { - fprintf (stderr, + fprintf (shadow_logfd, @@ -150,6 +151,7 @@ static int semanage_user_mod (semanage_h ret = 1; goto done; @@ -25,7 +24,7 @@ Index: shadow-4.5/lib/semanage.c +#if 0 ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); if (ret != 0) { - fprintf (stderr, + fprintf (shadow_logfd, @@ -208,6 +211,7 @@ static int semanage_user_add (semanage_h ret = 1; goto done; diff --git a/shadow-4.9-manfix.patch b/shadow-4.9-manfix.patch new file mode 100644 index 0000000..46cba1a --- /dev/null +++ b/shadow-4.9-manfix.patch @@ -0,0 +1,180 @@ +diff -up shadow-4.8.1/man/groupmems.8.xml.manfix shadow-4.8.1/man/groupmems.8.xml +--- shadow-4.8.1/man/groupmems.8.xml.manfix 2020-03-17 15:34:48.750414984 +0100 ++++ shadow-4.8.1/man/groupmems.8.xml 2020-03-17 15:41:13.383588722 +0100 +@@ -179,20 +179,10 @@ + + SETUP + +- The groupmems executable should be in mode +- 2710 as user root and in group +- groups. The system administrator can add users to +- group groups to allow or disallow them using the +- groupmems utility to manage their own group +- membership list. ++ In this operating system the groupmems executable ++ is not setuid and regular users cannot use it to manipulate ++ the membership of their own group. + +- +- +- $ groupadd -r groups +- $ chmod 2710 groupmems +- $ chown root.groups groupmems +- $ groupmems -g groups -a gk4 +- + + + +diff -up shadow-4.8.1/man/ja/man5/login.defs.5.manfix shadow-4.8.1/man/ja/man5/login.defs.5 +--- shadow-4.8.1/man/ja/man5/login.defs.5.manfix 2019-07-23 17:26:08.000000000 +0200 ++++ shadow-4.8.1/man/ja/man5/login.defs.5 2020-03-17 15:34:48.750414984 +0100 +@@ -147,10 +147,6 @@ 以下の参照表は、 + shadow パスワード機能のどのプログラムが + どのパラメータを使用するかを示したものである。 + .na +-.IP chfn 12 +-CHFN_AUTH CHFN_RESTRICT +-.IP chsh 12 +-CHFN_AUTH + .IP groupadd 12 + GID_MAX GID_MIN + .IP newusers 12 +diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5.xml +--- shadow-4.8.1/man/login.defs.5.xml.manfix 2020-01-17 16:47:56.000000000 +0100 ++++ shadow-4.8.1/man/login.defs.5.xml 2020-03-17 15:34:48.750414984 +0100 +@@ -164,6 +164,17 @@ + long numeric parameters is machine-dependent. + + ++ ++ Please note that the parameters in this configuration file control the ++ behavior of the tools from the shadow-utils component. None of these ++ tools uses the PAM mechanism, and the utilities that use PAM (such as the ++ passwd command) should be configured elsewhere. The only values that ++ affect PAM modules are ENCRYPT_METHOD and SHA_CRYPT_MAX_ROUNDS ++ for pam_unix module, FAIL_DELAY for pam_faildelay module, ++ and UMASK for pam_umask module. Refer to ++ pam(8) for more information. ++ ++ + The following configuration items are provided: + + +@@ -256,16 +267,6 @@ + + + +- chfn +- +- +- CHFN_AUTH +- CHFN_RESTRICT +- LOGIN_STRING +- +- +- +- + chgpasswd + + +@@ -286,14 +287,6 @@ + + + +- +- chsh +- +- +- CHSH_AUTH LOGIN_STRING +- +- +- + + + +@@ -359,34 +352,6 @@ + LASTLOG_UID_MAX + + +- +- login +- +- +- CONSOLE +- CONSOLE_GROUPS DEFAULT_HOME +- ENV_HZ ENV_PATH ENV_SUPATH +- ENV_TZ ENVIRON_FILE +- ERASECHAR FAIL_DELAY +- FAILLOG_ENAB +- FAKE_SHELL +- FTMP_FILE +- HUSHLOGIN_FILE +- ISSUE_FILE +- KILLCHAR +- LASTLOG_ENAB LASTLOG_UID_MAX +- LOGIN_RETRIES +- LOGIN_STRING +- LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB +- MAIL_CHECK_ENAB MAIL_DIR MAIL_FILE +- MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB +- QUOTAS_ENAB +- TTYGROUP TTYPERM TTYTYPE_FILE +- ULIMIT UMASK +- USERGROUPS_ENAB +- +- +- + + + newgrp / sg +@@ -415,17 +380,6 @@ + + + +- +- passwd +- +- +- ENCRYPT_METHOD MD5_CRYPT_ENAB OBSCURE_CHECKS_ENAB +- PASS_ALWAYS_WARN PASS_CHANGE_TRIES PASS_MAX_LEN PASS_MIN_LEN +- SHA_CRYPT_MAX_ROUNDS +- SHA_CRYPT_MIN_ROUNDS +- +- +- + + pwck + +@@ -452,32 +406,6 @@ + + + +- +- su +- +- +- CONSOLE +- CONSOLE_GROUPS DEFAULT_HOME +- ENV_HZ ENVIRON_FILE +- ENV_PATH ENV_SUPATH +- ENV_TZ LOGIN_STRING MAIL_CHECK_ENAB +- MAIL_DIR MAIL_FILE QUOTAS_ENAB +- SULOG_FILE SU_NAME +- SU_WHEEL_ONLY +- SYSLOG_SU_ENAB +- USERGROUPS_ENAB +- +- +- +- +- sulogin +- +- +- ENV_HZ +- ENV_TZ +- +- +- + + useradd + diff --git a/shadow-4.9-move-create-home.patch b/shadow-4.9-move-create-home.patch new file mode 100644 index 0000000..94bb84c --- /dev/null +++ b/shadow-4.9-move-create-home.patch @@ -0,0 +1,64 @@ +diff --git a/src/useradd.c b/src/useradd.c +index baeffb35..02e1402c 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2644,27 +2644,12 @@ int main (int argc, char **argv) + + usr_update (); + +- if (mflg) { +- create_home (); +- if (home_added) { +- copy_tree (def_template, prefix_user_home, false, false, +- (uid_t)-1, user_id, (gid_t)-1, user_gid); +- } else { +- fprintf (stderr, +- _("%s: warning: the home directory %s already exists.\n" +- "%s: Not copying any file from skel directory into it.\n"), +- Prog, user_home, Prog); +- } +- +- } +- +- /* Do not create mail directory for system accounts */ +- if (!rflg) { +- create_mail (); +- } +- + close_files (); + ++ nscd_flush_cache ("passwd"); ++ nscd_flush_cache ("group"); ++ sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); ++ + /* + * tallylog_reset needs to be able to lookup + * a valid existing user name, +@@ -2695,9 +2680,24 @@ int main (int argc, char **argv) + exit(1); + } + +- nscd_flush_cache ("passwd"); +- nscd_flush_cache ("group"); +- sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); ++ if (mflg) { ++ create_home (); ++ if (home_added) { ++ copy_tree (def_template, prefix_user_home, false, true, ++ (uid_t)-1, user_id, (gid_t)-1, user_gid); ++ } else { ++ fprintf (stderr, ++ _("%s: warning: the home directory %s already exists.\n" ++ "%s: Not copying any file from skel directory into it.\n"), ++ Prog, user_home, Prog); ++ } ++ ++ } ++ ++ /* Do not create mail directory for system accounts */ ++ if (!rflg) { ++ create_mail (); ++ } + + return E_SUCCESS; + } diff --git a/shadow-4.9-newuidmap-libeconf-dependency.patch b/shadow-4.9-newuidmap-libeconf-dependency.patch new file mode 100644 index 0000000..a1907a6 --- /dev/null +++ b/shadow-4.9-newuidmap-libeconf-dependency.patch @@ -0,0 +1,15 @@ +diff --git a/src/Makefile.am b/src/Makefile.am +index 7c1a3491..6cc873be 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -96,8 +96,8 @@ LIBCRYPT_NOPAM = $(LIBCRYPT) + endif + + chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +-newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl +-newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl ++newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl ++newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl + chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) diff --git a/shadow-4.2.1-null-tm.patch b/shadow-4.9-null-tm.patch similarity index 75% rename from shadow-4.2.1-null-tm.patch rename to shadow-4.9-null-tm.patch index b1dd1c4..249b27b 100644 --- a/shadow-4.2.1-null-tm.patch +++ b/shadow-4.9-null-tm.patch @@ -1,24 +1,3 @@ -Index: shadow-4.5/src/faillog.c -=================================================================== ---- shadow-4.5.orig/src/faillog.c -+++ shadow-4.5/src/faillog.c -@@ -163,10 +163,14 @@ static void print_one (/*@null@*/const s - } - - tm = localtime (&fl.fail_time); -+ if (tm == NULL) { -+ cp = "(unknown)"; -+ } else { - #ifdef HAVE_STRFTIME -- strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); -- cp = ptime; -+ strftime (ptime, sizeof (ptime), "%D %H:%M:%S %z", tm); -+ cp = ptime; - #endif -+ } - printf ("%-9s %5d %5d ", - pw->pw_name, fl.fail_cnt, fl.fail_max); - /* FIXME: cp is not defined ifndef HAVE_STRFTIME */ Index: shadow-4.5/src/chage.c =================================================================== --- shadow-4.5.orig/src/chage.c diff --git a/shadow-4.6-redhat.patch b/shadow-4.9-redhat.patch similarity index 65% rename from shadow-4.6-redhat.patch rename to shadow-4.9-redhat.patch index 7a8be2e..9dfb3e8 100644 --- a/shadow-4.6-redhat.patch +++ b/shadow-4.9-redhat.patch @@ -1,16 +1,16 @@ -diff -up shadow-4.6/src/useradd.c.redhat shadow-4.6/src/useradd.c ---- shadow-4.6/src/useradd.c.redhat 2018-04-29 18:42:37.000000000 +0200 -+++ shadow-4.6/src/useradd.c 2018-05-28 13:37:16.695651258 +0200 -@@ -98,7 +98,7 @@ const char *Prog; - static gid_t def_group = 100; +diff -up shadow-4.9/src/useradd.c.redhat shadow-4.9/src/useradd.c +--- shadow-4.9/src/useradd.c.redhat 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/useradd.c 2021-08-02 11:45:11.942867250 +0200 +@@ -104,7 +104,7 @@ FILE *shadow_logfd = NULL; + static gid_t def_group = 1000; static const char *def_gname = "other"; static const char *def_home = "/home"; --static const char *def_shell = ""; +-static const char *def_shell = "/bin/bash"; +static const char *def_shell = "/sbin/nologin"; static const char *def_template = SKEL_DIR; - static const char *def_create_mail_spool = "no"; + static const char *def_create_mail_spool = "yes"; -@@ -108,7 +108,7 @@ static const char *def_expire = ""; +@@ -114,7 +114,7 @@ static const char *def_expire = ""; #define VALID(s) (strcspn (s, ":\n") == strlen (s)) static const char *user_name = ""; @@ -19,7 +19,7 @@ diff -up shadow-4.6/src/useradd.c.redhat shadow-4.6/src/useradd.c static uid_t user_id; static gid_t user_gid; static const char *user_comment = ""; -@@ -1114,9 +1114,9 @@ static void process_flags (int argc, cha +@@ -1204,9 +1204,9 @@ static void process_flags (int argc, cha }; while ((c = getopt_long (argc, argv, #ifdef WITH_SELINUX @@ -31,7 +31,7 @@ diff -up shadow-4.6/src/useradd.c.redhat shadow-4.6/src/useradd.c #endif /* !WITH_SELINUX */ long_options, NULL)) != -1) { switch (c) { -@@ -1267,6 +1267,7 @@ static void process_flags (int argc, cha +@@ -1363,6 +1363,7 @@ static void process_flags (int argc, cha case 'M': Mflg = true; break; diff --git a/shadow-4.9-usermod-allow-all-group-types.patch b/shadow-4.9-usermod-allow-all-group-types.patch new file mode 100644 index 0000000..fada15e --- /dev/null +++ b/shadow-4.9-usermod-allow-all-group-types.patch @@ -0,0 +1,322 @@ +From e481437ab9ebe9a8bf8fbaabe986d42b2f765991 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Tue, 3 Aug 2021 08:57:20 +0200 +Subject: [PATCH] usermod: allow all group types with -G option + +The only way of removing a group from the supplementary list is to use +-G option, and list all groups that the user is a member of except for +the one that wants to be removed. The problem lies when there's a user +that contains both local and remote groups, and the group to be removed +is a local one. As we need to include the remote group with -G option +the command will fail. + +This reverts commit 140510de9de4771feb3af1d859c09604043a4c9b. This way, +it would be possible to remove the remote groups from the supplementary +list. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1967641 +Resolves: https://github.com/shadow-maint/shadow/issues/338 + +Signed-off-by: Iker Pedrosa +--- + src/usermod.c | 220 ++++++++++++++++++-------------------------------- + 1 file changed, 77 insertions(+), 143 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 03bb9b9d..a0c03afa 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -187,7 +187,6 @@ static bool sub_gid_locked = false; + static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, + long int date); + static int get_groups (char *); +-static struct group * get_local_group (char * grp_name); + static /*@noreturn@*/void usage (int status); + static void new_pwent (struct passwd *); + static void new_spent (struct spwd *); +@@ -201,9 +200,7 @@ static void grp_update (void); + + static void process_flags (int, char **); + static void close_files (void); +-static void close_group_files (void); + static void open_files (void); +-static void open_group_files (void); + static void usr_update (void); + static void move_home (void); + static void update_lastlog (void); +@@ -260,11 +257,6 @@ static int get_groups (char *list) + return 0; + } + +- /* +- * Open the group files +- */ +- open_group_files (); +- + /* + * So long as there is some data to be converted, strip off each + * name and look it up. A mix of numerical and string values for +@@ -284,7 +276,7 @@ static int get_groups (char *list) + * Names starting with digits are treated as numerical GID + * values, otherwise the string is looked up as is. + */ +- grp = get_local_group (list); ++ grp = prefix_getgr_nam_gid (list); + + /* + * There must be a match, either by GID value or by +@@ -334,8 +326,6 @@ static int get_groups (char *list) + gr_free ((struct group *)grp); + } while (NULL != list); + +- close_group_files (); +- + user_groups[ngroups] = (char *) 0; + + /* +@@ -348,44 +338,6 @@ static int get_groups (char *list) + return 0; + } + +-/* +- * get_local_group - checks if a given group name exists locally +- * +- * get_local_group() checks if a given group name exists locally. +- * If the name exists the group information is returned, otherwise NULL is +- * returned. +- */ +-static struct group * get_local_group(char * grp_name) +-{ +- const struct group *grp; +- struct group *result_grp = NULL; +- long long int gid; +- char *endptr; +- +- gid = strtoll (grp_name, &endptr, 10); +- if ( ('\0' != *grp_name) +- && ('\0' == *endptr) +- && (ERANGE != errno) +- && (gid == (gid_t)gid)) { +- grp = gr_locate_gid ((gid_t) gid); +- } +- else { +- grp = gr_locate(grp_name); +- } +- +- if (grp != NULL) { +- result_grp = __gr_dup (grp); +- if (NULL == result_grp) { +- fprintf (stderr, +- _("%s: Out of memory. Cannot find group '%s'.\n"), +- Prog, grp_name); +- fail_exit (E_GRP_UPDATE); +- } +- } +- +- return result_grp; +-} +- + #ifdef ENABLE_SUBIDS + struct ulong_range + { +@@ -1523,7 +1475,50 @@ static void close_files (void) + } + + if (Gflg || lflg) { +- close_group_files (); ++ if (gr_close () == 0) { ++ fprintf (stderr, ++ _("%s: failure while writing changes to %s\n"), ++ Prog, gr_dbname ()); ++ SYSLOG ((LOG_ERR, ++ "failure while writing changes to %s", ++ gr_dbname ())); ++ fail_exit (E_GRP_UPDATE); ++ } ++#ifdef SHADOWGRP ++ if (is_shadow_grp) { ++ if (sgr_close () == 0) { ++ fprintf (stderr, ++ _("%s: failure while writing changes to %s\n"), ++ Prog, sgr_dbname ()); ++ SYSLOG ((LOG_ERR, ++ "failure while writing changes to %s", ++ sgr_dbname ())); ++ fail_exit (E_GRP_UPDATE); ++ } ++ } ++#endif ++#ifdef SHADOWGRP ++ if (is_shadow_grp) { ++ if (sgr_unlock () == 0) { ++ fprintf (stderr, ++ _("%s: failed to unlock %s\n"), ++ Prog, sgr_dbname ()); ++ SYSLOG ((LOG_ERR, ++ "failed to unlock %s", ++ sgr_dbname ())); ++ /* continue */ ++ } ++ } ++#endif ++ if (gr_unlock () == 0) { ++ fprintf (stderr, ++ _("%s: failed to unlock %s\n"), ++ Prog, gr_dbname ()); ++ SYSLOG ((LOG_ERR, ++ "failed to unlock %s", ++ gr_dbname ())); ++ /* continue */ ++ } + } + + if (is_shadow_pwd) { +@@ -1592,60 +1587,6 @@ static void close_files (void) + #endif + } + +-/* +- * close_group_files - close all of the files that were opened +- * +- * close_group_files() closes all of the files that were opened related +- * with groups. This causes any modified entries to be written out. +- */ +-static void close_group_files (void) +-{ +- if (gr_close () == 0) { +- fprintf (stderr, +- _("%s: failure while writing changes to %s\n"), +- Prog, gr_dbname ()); +- SYSLOG ((LOG_ERR, +- "failure while writing changes to %s", +- gr_dbname ())); +- fail_exit (E_GRP_UPDATE); +- } +-#ifdef SHADOWGRP +- if (is_shadow_grp) { +- if (sgr_close () == 0) { +- fprintf (stderr, +- _("%s: failure while writing changes to %s\n"), +- Prog, sgr_dbname ()); +- SYSLOG ((LOG_ERR, +- "failure while writing changes to %s", +- sgr_dbname ())); +- fail_exit (E_GRP_UPDATE); +- } +- } +-#endif +-#ifdef SHADOWGRP +- if (is_shadow_grp) { +- if (sgr_unlock () == 0) { +- fprintf (stderr, +- _("%s: failed to unlock %s\n"), +- Prog, sgr_dbname ()); +- SYSLOG ((LOG_ERR, +- "failed to unlock %s", +- sgr_dbname ())); +- /* continue */ +- } +- } +-#endif +- if (gr_unlock () == 0) { +- fprintf (stderr, +- _("%s: failed to unlock %s\n"), +- Prog, gr_dbname ()); +- SYSLOG ((LOG_ERR, +- "failed to unlock %s", +- gr_dbname ())); +- /* continue */ +- } +-} +- + /* + * open_files - lock and open the password files + * +@@ -1681,7 +1622,38 @@ static void open_files (void) + } + + if (Gflg || lflg) { +- open_group_files (); ++ /* ++ * Lock and open the group file. This will load all of the ++ * group entries. ++ */ ++ if (gr_lock () == 0) { ++ fprintf (stderr, ++ _("%s: cannot lock %s; try again later.\n"), ++ Prog, gr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++ gr_locked = true; ++ if (gr_open (O_CREAT | O_RDWR) == 0) { ++ fprintf (stderr, ++ _("%s: cannot open %s\n"), ++ Prog, gr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++#ifdef SHADOWGRP ++ if (is_shadow_grp && (sgr_lock () == 0)) { ++ fprintf (stderr, ++ _("%s: cannot lock %s; try again later.\n"), ++ Prog, sgr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++ sgr_locked = true; ++ if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { ++ fprintf (stderr, ++ _("%s: cannot open %s\n"), ++ Prog, sgr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++#endif + } + #ifdef ENABLE_SUBIDS + if (vflg || Vflg) { +@@ -1717,44 +1689,6 @@ static void open_files (void) + #endif /* ENABLE_SUBIDS */ + } + +-/* +- * open_group_files - lock and open the group files +- * +- * open_group_files() loads all of the group entries. +- */ +-static void open_group_files (void) +-{ +- if (gr_lock () == 0) { +- fprintf (stderr, +- _("%s: cannot lock %s; try again later.\n"), +- Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } +- gr_locked = true; +- if (gr_open (O_CREAT | O_RDWR) == 0) { +- fprintf (stderr, +- _("%s: cannot open %s\n"), +- Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } +- +-#ifdef SHADOWGRP +- if (is_shadow_grp && (sgr_lock () == 0)) { +- fprintf (stderr, +- _("%s: cannot lock %s; try again later.\n"), +- Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } +- sgr_locked = true; +- if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { +- fprintf (stderr, +- _("%s: cannot open %s\n"), +- Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } +-#endif +-} +- + /* + * usr_update - create the user entries + * +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index c6caf48..c1becdd 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.8.1 -Release: 20%{?dist} +Version: 4.9 +Release: 1%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -17,111 +17,37 @@ Source6: shadow-utils.HOME_MODE.xml ### Patches ### # Misc small changes - most probably non-upstreamable -Patch0: shadow-4.6-redhat.patch +Patch0: shadow-4.9-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable Patch1: shadow-4.8-goodname.patch -# https://github.com/shadow-maint/shadow/commit/7384865775b0203b9cf5337a047744f0a4555868 -Patch2: shadow-4.1.5.1-info-parent-dir.patch -# Misc SElinux related changes - upstreamability unknown -Patch6: shadow-4.8-selinux.patch -# https://github.com/shadow-maint/shadow/commit/a8361e741040cd926c9c93aac89820052531b1a3 -Patch11: shadow-4.1.5.1-logmsg.patch +# Move create home to the end of main - upstreamability unknown +Patch2: shadow-4.9-move-create-home.patch # SElinux related - upstreamability unknown -Patch14: shadow-4.1.5.1-default-range.patch -# Misc manual page changes -# https://github.com/shadow-maint/shadow/commit/c0818ab01d1896784245eedec9495e1e6e0260af -# Changes in man/groupmems.8.xml, man/ja/man5/login.defs.5 and man/login.defs.5.xml not upstreamed -Patch15: shadow-4.8.1-manfix.patch -# https://github.com/shadow-maint/shadow/commit/f4cbf38ad7801bab6fae50e9b5a2effc3c48a1ea -Patch17: shadow-4.1.5.1-userdel-helpfix.patch +Patch3: shadow-4.9-default-range.patch +# Misc manual page changes - non-upstreamable +Patch4: shadow-4.9-manfix.patch # Date parsing improvement - could be upstreamed -Patch19: shadow-4.2.1-date-parsing.patch +Patch5: shadow-4.2.1-date-parsing.patch # Additional error message - could be upstreamed -Patch21: shadow-4.6-move-home.patch +Patch6: shadow-4.6-move-home.patch # Audit message changes - upstreamability unknown -Patch22: shadow-4.8.1-audit-update.patch +Patch7: shadow-4.9-audit-update.patch # Changes related to password unlocking - could be upstreamed -Patch23: shadow-4.5-usermod-unlock.patch +Patch8: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown -Patch28: shadow-4.8-selinux-perms.patch +Patch9: shadow-4.8-selinux-perms.patch # Handle NULL return from *time funcs - could be upstreamed -Patch29: shadow-4.2.1-null-tm.patch -# SElinux related - upstreamability unknown -Patch31: shadow-4.6-getenforce.patch -# https://github.com/shadow-maint/shadow/commit/c93897a8d71b9b1790caf3b2dee38dbe62518ae3 -Patch32: shadow-4.8-crypt_h.patch +Patch10: shadow-4.9-null-tm.patch # Handle /etc/passwd corruption - could be upstreamed -Patch33: shadow-4.8-long-entry.patch +Patch11: shadow-4.8-long-entry.patch # Limit uid/gid allocation to non-zero - could be upstreamed -Patch38: shadow-4.6-sysugid-min-limit.patch +Patch12: shadow-4.6-sysugid-min-limit.patch # Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown -Patch40: shadow-4.8-ignore-login-prompt.patch -# Generate /var/spool/mail/$USER with the proper SELinux user identity - already upstreamed -Patch42: shadow-4.8-useradd-selinux-mail.patch -# Clarify useradd man regarding "-d" parameter - already upstreamed -Patch43: shadow-4.8.1-useradd-man-clarification.patch -# https://github.com/shadow-maint/shadow/commit/140510de9de4771feb3af1d859c09604043a4c9b -# https://github.com/shadow-maint/shadow/commit/8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 -Patch44: shadow-4.8.1-check-local-groups.patch -# https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 -Patch45: shadow-4.8.1-commonio-force-lock-file-sync.patch -# https://github.com/shadow-maint/shadow/commit/df6ec1d1693c8c80c323b40d6fc82bb549363db3 -Patch46: shadow-4.8.1-man-include-lastlog-file-caveat.patch -# https://github.com/shadow-maint/shadow/commit/0a7888b1fad613a052b988b01a71933b67296e68 -# https://github.com/shadow-maint/shadow/commit/607f1dd549cf9abc87af1cf29275f0d2d11eea29 -# https://github.com/shadow-maint/shadow/commit/b5fb1b38eea2fb0489ed088c82daf6700e72363e -# https://github.com/shadow-maint/shadow/commit/43a917cce54019799a8de037fd63780a2b640afc -Patch47: shadow-4.8.1-libsubid_creation.patch -# https://github.com/shadow-maint/shadow/commit/514c1328b6c90d817ae0a9f7addfb3c9a11a275a -# https://github.com/shadow-maint/shadow/commit/8492dee6632e340dee76eee895c3e30877bebf45 -# https://github.com/shadow-maint/shadow/commit/0f4347d1483191b2142546416a9eefe0c9459600 -Patch48: shadow-4.8.1-libsubid_nsswitch_support.patch -# https://github.com/shadow-maint/shadow/commit/186b1b7ac1a68d0fcc618a22da1a99232b420911 -Patch49: shadow-4.8.1-man-mention-nss-in-newuidmap.patch -# https://github.com/shadow-maint/shadow/commit/f9831a4a1a20b0e8fe47cc72ec20018ec04dbb90 -Patch50: shadow-4.8.1-libsubid_not_print_error_messages.patch -# https://github.com/shadow-maint/shadow/commit/c6cab4a7bafa18d9d65a333cac1261e7b5e32bc9 -Patch51: shadow-4.8.1-libsubid_init_return_false.patch -# https://github.com/shadow-maint/shadow/commit/2f1f45d64fc7c10e7a3cbe00e89f63714343e526 -Patch52: shadow-4.8.1-useradd_SUB_UID_COUNT-0.patch -# https://github.com/shadow-maint/shadow/commit/ea7af4e1543c63590d4107ae075fea385028997d -Patch53: shadow-4.8.1-libsubid_simplify_ranges_variable.patch -# https://github.com/shadow-maint/shadow/commit/0fe42f571c69f0105d31305f995c9887aeb9525e -Patch54: shadow-4.8.1-libsubid_init_not_print_error_messages.patch -# https://github.com/shadow-maint/shadow/commit/ec1951c181faed188464396b2cfdd2efb726c7f3 -Patch55: shadow-4.8.1-libsubid_fix_newusers_nss_provides_subids.patch -# https://github.com/shadow-maint/shadow/commit/087112244327be50abc24f9ec8afbf60ae8b2dec -# https://github.com/shadow-maint/shadow/pull/353 -Patch56: shadow-4.8.1-man_clarify_subid_delegation.patch -# https://github.com/shadow-maint/shadow/commit/bd920ab36a6c641e4a8769f8c7f8ca738ec61820 -Patch57: shadow-4.8.1-libsubid_make_logfd_not_extern.patch -# https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531 -Patch58: shadow-4.8.1-yescrypt-support.patch -# https://github.com/shadow-maint/shadow/commit/7a3bb4d0ea8166acc539c788a8ce943acf4a6aa7 -Patch59: shadow-4.8.1-fix_YESCRYPT_salt_cost_param_type.patch -# https://github.com/shadow-maint/shadow/commit/c44b71cec25d60efc51aec9de3abce1f6efbfcf5 -# https://github.com/shadow-maint/shadow/commit/fd9d79a1a3438ba7703939cfcd45fc266782c64e -# https://github.com/shadow-maint/shadow/commit/8281c82e324b57b3a4b520afad26b43ce128d521 -# https://github.com/shadow-maint/shadow/commit/1aed7ae945aafaeb253fc89a7ecedeaedf72654e -# https://github.com/shadow-maint/shadow/commit/5d0d7841971cc53d9a9d1aefe12f00204115bf6a -# https://github.com/shadow-maint/shadow/commit/e65cc6aebcb4132fa413f00a905216a5b35b3d57 -Patch60: shadow-4.8.1-covscan_fixes.patch -# https://github.com/shadow-maint/shadow/commit/738d92a4bd99a2038aa5f97b2fc85daa7011e403 -Patch61: shadow-4.8.1-fix_bcrypt_prefix.patch -# https://github.com/shadow-maint/shadow/commit/14b108728a5d55c3d478a170c39f0e2ffd4de1b0 -Patch62: shadow-4.8.1-salt_c_sanitize_code.patch -# https://github.com/shadow-maint/shadow/commit/dbf230e4cf823dd6b6a3bad6d29dfad4f0ffa8fc -Patch63: shadow-4.8.1-salt_c_comments.patch -# https://github.com/shadow-maint/shadow/commit/bc8257cf73328e450511b13cbd35e1994feccb30 -Patch64: shadow-4.8.1-salt_c_use_dev_urandom.patch -# https://github.com/shadow-maint/shadow/commit/2c542f6c65f858b3dba20f58db4da56572f67a54 -Patch65: shadow-4.8.1-useradd_create_relative_home_path_correctly.patch -# https://github.com/shadow-maint/shadow/commit/c82ed0c15e0e9e47df0b4c22672b72e35f061a9d -Patch66: shadow-4.8.1-getentropy_random_bytes.patch -# https://github.com/shadow-maint/shadow/commit/ea04eb301d08c0c58f1120f87d4ec184d3983ce5 -Patch67: shadow-4.8.1-crypt_gensalt.patch -# https://github.com/shadow-maint/shadow/commit/ffd35d89021a9b8375a9246082afc6fc270a93ee -Patch68: shadow-4.8.1-salt_c_fix_fread.patch +Patch13: shadow-4.8-ignore-login-prompt.patch +# https://github.com/shadow-maint/shadow/pull/395 +Patch14: shadow-4.9-newuidmap-libeconf-dependency.patch +# https://github.com/shadow-maint/shadow/pull/397 +Patch15: shadow-4.9-usermod-allow-all-group-types.patch License: BSD and GPLv2+ BuildRequires: make @@ -171,50 +97,20 @@ Development files for shadow-utils-subid. %setup -q -n shadow-%{version} %patch0 -p1 -b .redhat %patch1 -p1 -b .goodname -%patch2 -p1 -b .info-parent-dir -%patch6 -p1 -b .selinux -%patch11 -p1 -b .logmsg -%patch14 -p1 -b .default-range -%patch15 -p1 -b .manfix -%patch17 -p1 -b .userdel -%patch19 -p1 -b .date-parsing -%patch21 -p1 -b .move-home -%patch22 -p1 -b .audit-update -%patch23 -p1 -b .unlock -%patch28 -p1 -b .selinux-perms -%patch29 -p1 -b .null-tm -%patch31 -p1 -b .getenforce -%patch32 -p1 -b .crypt_h -%patch33 -p1 -b .long-entry -%patch38 -p1 -b .sysugid-min-limit -%patch40 -p1 -b .login-prompt -%patch42 -p1 -b .useradd-selinux-mail -%patch43 -p1 -b .useradd-man-clarification -%patch44 -p1 -b .check-local-groups -%patch45 -p1 -b .commonio-force-lock-file-sync -%patch46 -p1 -b .man-include-lastlog-file-caveat -%patch47 -p1 -b .libsubid_creation -%patch48 -p1 -b .libsubid_nsswitch_support -%patch49 -p1 -b .man-mention-nss-in-newuidmap -%patch50 -p1 -b .libsubid_not_print_error_messages -%patch51 -p1 -b .libsubid_init_return_false -%patch52 -p1 -b .useradd_SUB_UID_COUNT-0 -%patch53 -p1 -b .libsubid_simplify_ranges_variable -%patch54 -p1 -b .libsubid_init_not_print_error_messages -%patch55 -p1 -b .libsubid_fix_newusers_nss_provides_subids -%patch56 -p1 -b .man_clarify_subid_delegation -%patch57 -p1 -b .libsubid_make_logfd_not_extern -%patch58 -p1 -b .yescrypt -%patch59 -p1 -b .YESCRYPT_salt_cost_param_type -%patch60 -p1 -b .covscan_fixes -%patch61 -p1 -b .bcrypt_prefix -%patch62 -p1 -b .sanitize_code -%patch63 -p1 -b .comments -%patch64 -p1 -b .use_dev_urandom -%patch65 -p1 -b .useradd_create_relative_home_path_correctly -%patch66 -p1 -b .getentropy_random_bytes -%patch67 -p1 -b .crypt_gensalt -%patch68 -p1 -b .fix_fread +%patch2 -p1 -b .move-create-home +%patch3 -p1 -b .default-range +%patch4 -p1 -b .manfix +%patch5 -p1 -b .date-parsing +%patch6 -p1 -b .move-home +%patch7 -p1 -b .audit-update +%patch8 -p1 -b .unlock +%patch9 -p1 -b .selinux-perms +%patch10 -p1 -b .null-tm +%patch11 -p1 -b .long-entry +%patch12 -p1 -b .sysugid-min-limit +%patch13 -p1 -b .login-prompt +%patch14 -p1 -b .newuidmap-libeconf-dependency +%patch15 -p1 -b .usermod-allow-all-group-types iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -385,6 +281,11 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Wed Aug 4 2021 Iker Pedrosa - 2:4.9-1 +- Rebase to version 4.9 +- usermod: allow all group types with -G option (#1975327) +- Clean spec file + * Fri Jul 23 2021 Fedora Release Engineering - 2:4.8.1-20 - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild diff --git a/sources b/sources index 0e0c57a..803fac0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.8.1.tar.xz) = 780a983483d847ed3c91c82064a0fa902b6f4185225978241bc3bc03fcc3aa143975b46aee43151c6ba43efcfdb1819516b76ba7ad3d1d3c34fcc38ea42e917b -SHA512 (shadow-4.8.1.tar.xz.asc) = ec7686263c81d3feb8ee4314c3323a9a3ada74aafaaf99f4f0d9af9b1341f8c5ff5477ecf98dd94dbb7d921f532d655b0b6a87d94c71893f35dc9bc54c84dd42 +SHA512 (shadow-4.9.tar.xz) = 254cda49bb14505a7604821e7fa898bf4bf317d648e9ddc881ab80a6860d52053dfffacad6feab87c7d16608c35ed6b6cee99e7757eac930da3a7b31cdcd4b95 +SHA512 (shadow-4.9.tar.xz.asc) = 16c0ff7be263c9d471b05656c9a1d14da8ec9b17544910323ca6ab854126d1a03ece221e0caf610e65a9b1d080b4cd1b8b46973f20e3ae45ea0e5581ce6c90d9 From 3a328328567ec0e4ec8f6e3dacdba36022b121a2 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 11 Aug 2021 14:58:12 +0200 Subject: [PATCH 031/118] useradd: avoid generating an empty subid range (#1990653) Signed-off-by: Iker Pedrosa --- ...d-avoid-generating-empty-subid-range.patch | 79 +++++++++++++++++++ shadow-utils.spec | 12 ++- 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 shadow-4.9-useradd-avoid-generating-empty-subid-range.patch diff --git a/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch b/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch new file mode 100644 index 0000000..b94fd60 --- /dev/null +++ b/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch @@ -0,0 +1,79 @@ +diff --git a/src/useradd.c b/src/useradd.c +index baeffb35..9abeea6e 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -142,9 +142,7 @@ static bool is_sub_gid = false; + static bool sub_uid_locked = false; + static bool sub_gid_locked = false; + static uid_t sub_uid_start; /* New subordinate uid range */ +-static unsigned long sub_uid_count; + static gid_t sub_gid_start; /* New subordinate gid range */ +-static unsigned long sub_gid_count; + #endif /* ENABLE_SUBIDS */ + static bool pw_locked = false; + static bool gr_locked = false; +@@ -234,7 +232,7 @@ static void open_shadow (void); + static void faillog_reset (uid_t); + static void lastlog_reset (uid_t); + static void tallylog_reset (const char *); +-static void usr_update (void); ++static void usr_update (unsigned long subuid_count, unsigned long subgid_count); + static void create_home (void); + static void create_mail (void); + static void check_uid_range(int rflg, uid_t user_id); +@@ -2092,7 +2090,7 @@ static void tallylog_reset (const char *user_name) + * usr_update() creates the password file entries for this user + * and will update the group entries if required. + */ +-static void usr_update (void) ++static void usr_update (unsigned long subuid_count, unsigned long subgid_count) + { + struct passwd pwent; + struct spwd spent; +@@ -2155,14 +2153,14 @@ static void usr_update (void) + } + #ifdef ENABLE_SUBIDS + if (is_sub_uid && +- (sub_uid_add(user_name, sub_uid_start, sub_uid_count) == 0)) { ++ (sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry\n"), + Prog, sub_uid_dbname ()); + fail_exit (E_SUB_UID_UPDATE); + } + if (is_sub_gid && +- (sub_gid_add(user_name, sub_gid_start, sub_gid_count) == 0)) { ++ (sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry\n"), + Prog, sub_uid_dbname ()); +@@ -2624,16 +2622,16 @@ int main (int argc, char **argv) + } + + #ifdef ENABLE_SUBIDS +- if (is_sub_uid && sub_uid_count != 0) { +- if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) < 0) { ++ if (is_sub_uid && subuid_count != 0) { ++ if (find_new_sub_uids(&sub_uid_start, &subuid_count) < 0) { + fprintf (stderr, + _("%s: can't create subordinate user IDs\n"), + Prog); + fail_exit(E_SUB_UID_UPDATE); + } + } +- if (is_sub_gid && sub_gid_count != 0) { +- if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) < 0) { ++ if (is_sub_gid && subgid_count != 0) { ++ if (find_new_sub_gids(&sub_gid_start, &subgid_count) < 0) { + fprintf (stderr, + _("%s: can't create subordinate group IDs\n"), + Prog); +@@ -2642,7 +2640,7 @@ int main (int argc, char **argv) + } + #endif /* ENABLE_SUBIDS */ + +- usr_update (); ++ usr_update (subuid_count, subgid_count); + + close_files (); + diff --git a/shadow-utils.spec b/shadow-utils.spec index c1becdd..47d61e0 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.9 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -44,10 +44,12 @@ Patch11: shadow-4.8-long-entry.patch Patch12: shadow-4.6-sysugid-min-limit.patch # Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown Patch13: shadow-4.8-ignore-login-prompt.patch -# https://github.com/shadow-maint/shadow/pull/395 +# https://github.com/shadow-maint/shadow/commit/c6847011e8b656adacd9a0d2a78418cad0de34cb Patch14: shadow-4.9-newuidmap-libeconf-dependency.patch -# https://github.com/shadow-maint/shadow/pull/397 +# https://github.com/shadow-maint/shadow/commit/e481437ab9ebe9a8bf8fbaabe986d42b2f765991 Patch15: shadow-4.9-usermod-allow-all-group-types.patch +# https://github.com/shadow-maint/shadow/pull/399 +Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch License: BSD and GPLv2+ BuildRequires: make @@ -111,6 +113,7 @@ Development files for shadow-utils-subid. %patch13 -p1 -b .login-prompt %patch14 -p1 -b .newuidmap-libeconf-dependency %patch15 -p1 -b .usermod-allow-all-group-types +%patch16 -p1 -b .useradd-avoid-generating-empty-subid-range iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -281,6 +284,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Aug 9 2021 Iker Pedrosa - 2:4.9-2 +- useradd: avoid generating an empty subid range (#1990653) + * Wed Aug 4 2021 Iker Pedrosa - 2:4.9-1 - Rebase to version 4.9 - usermod: allow all group types with -G option (#1975327) From ad630e5c8e7951ce7cb0e98e7499294a04b98be3 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 16 Aug 2021 09:53:32 +0200 Subject: [PATCH 032/118] allow all types of groups when modifying supplementary groups (#1975327) Signed-off-by: Iker Pedrosa --- shadow-4.8.1-check-local-groups.patch | 311 -------------------------- shadow-utils.spec | 6 +- 2 files changed, 4 insertions(+), 313 deletions(-) diff --git a/shadow-4.8.1-check-local-groups.patch b/shadow-4.8.1-check-local-groups.patch index 6e9d2bf..26608b2 100644 --- a/shadow-4.8.1-check-local-groups.patch +++ b/shadow-4.8.1-check-local-groups.patch @@ -1,314 +1,3 @@ -From 140510de9de4771feb3af1d859c09604043a4c9b Mon Sep 17 00:00:00 2001 -From: ikerexxe -Date: Fri, 27 Mar 2020 14:23:02 +0100 -Subject: [PATCH 1/2] usermod: check only local groups with -G option - -Check only local groups when adding new supplementary groups to a user - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1727236 ---- - src/usermod.c | 220 ++++++++++++++++++++++++++++++++------------------ - 1 file changed, 143 insertions(+), 77 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 05b98715..ef430296 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -183,6 +183,7 @@ static bool sub_gid_locked = false; - static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, - long int date); - static int get_groups (char *); -+static struct group * get_local_group (char * grp_name); - static /*@noreturn@*/void usage (int status); - static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); -@@ -196,7 +197,9 @@ static void grp_update (void); - - static void process_flags (int, char **); - static void close_files (void); -+static void close_group_files (void); - static void open_files (void); -+static void open_group_files (void); - static void usr_update (void); - static void move_home (void); - static void update_lastlog (void); -@@ -253,6 +256,11 @@ static int get_groups (char *list) - return 0; - } - -+ /* -+ * Open the group files -+ */ -+ open_group_files (); -+ - /* - * So long as there is some data to be converted, strip off each - * name and look it up. A mix of numerical and string values for -@@ -272,7 +280,7 @@ static int get_groups (char *list) - * Names starting with digits are treated as numerical GID - * values, otherwise the string is looked up as is. - */ -- grp = prefix_getgr_nam_gid (list); -+ grp = get_local_group (list); - - /* - * There must be a match, either by GID value or by -@@ -322,6 +330,8 @@ static int get_groups (char *list) - gr_free ((struct group *)grp); - } while (NULL != list); - -+ close_group_files (); -+ - user_groups[ngroups] = (char *) 0; - - /* -@@ -334,6 +344,44 @@ static int get_groups (char *list) - return 0; - } - -+/* -+ * get_local_group - checks if a given group name exists locally -+ * -+ * get_local_group() checks if a given group name exists locally. -+ * If the name exists the group information is returned, otherwise NULL is -+ * returned. -+ */ -+static struct group * get_local_group(char * grp_name) -+{ -+ const struct group *grp; -+ struct group *result_grp = NULL; -+ long long int gid; -+ char *endptr; -+ -+ gid = strtoll (grp_name, &endptr, 10); -+ if ( ('\0' != *grp_name) -+ && ('\0' == *endptr) -+ && (ERANGE != errno) -+ && (gid == (gid_t)gid)) { -+ grp = gr_locate_gid ((gid_t) gid); -+ } -+ else { -+ grp = gr_locate(grp_name); -+ } -+ -+ if (grp != NULL) { -+ result_grp = __gr_dup (grp); -+ if (NULL == result_grp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot find group '%s'.\n"), -+ Prog, grp_name); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+ -+ return result_grp; -+} -+ - #ifdef ENABLE_SUBIDS - struct ulong_range - { -@@ -1447,50 +1495,7 @@ static void close_files (void) - } - - if (Gflg || lflg) { -- if (gr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } -- } --#endif --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- sgr_dbname ())); -- /* continue */ -- } -- } --#endif -- if (gr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- gr_dbname ())); -- /* continue */ -- } -+ close_group_files (); - } - - if (is_shadow_pwd) { -@@ -1559,6 +1564,60 @@ static void close_files (void) - #endif - } - -+/* -+ * close_group_files - close all of the files that were opened -+ * -+ * close_group_files() closes all of the files that were opened related -+ * with groups. This causes any modified entries to be written out. -+ */ -+static void close_group_files (void) -+{ -+ if (gr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ gr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ sgr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+#endif -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ sgr_dbname ())); -+ /* continue */ -+ } -+ } -+#endif -+ if (gr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ gr_dbname ())); -+ /* continue */ -+ } -+} -+ - /* - * open_files - lock and open the password files - * -@@ -1594,38 +1653,7 @@ static void open_files (void) - } - - if (Gflg || lflg) { -- /* -- * Lock and open the group file. This will load all of the -- * group entries. -- */ -- if (gr_lock () == 0) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- gr_locked = true; -- if (gr_open (O_CREAT | O_RDWR) == 0) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp && (sgr_lock () == 0)) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- sgr_locked = true; -- if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#endif -+ open_group_files (); - } - #ifdef ENABLE_SUBIDS - if (vflg || Vflg) { -@@ -1661,6 +1689,44 @@ static void open_files (void) - #endif /* ENABLE_SUBIDS */ - } - -+/* -+ * open_group_files - lock and open the group files -+ * -+ * open_group_files() loads all of the group entries. -+ */ -+static void open_group_files (void) -+{ -+ if (gr_lock () == 0) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ gr_locked = true; -+ if (gr_open (O_CREAT | O_RDWR) == 0) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+#ifdef SHADOWGRP -+ if (is_shadow_grp && (sgr_lock () == 0)) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ sgr_locked = true; -+ if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+#endif -+} -+ - /* - * usr_update - create the user entries - * --- -2.25.4 - - From 8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 Mon Sep 17 00:00:00 2001 From: ikerexxe Date: Mon, 30 Mar 2020 09:08:23 +0200 diff --git a/shadow-utils.spec b/shadow-utils.spec index 87d7138..a317e27 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.8.1 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 URL: http://pkg-shadow.alioth.debian.org/ Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -55,7 +55,6 @@ Patch40: shadow-4.8-ignore-login-prompt.patch Patch42: shadow-4.8-useradd-selinux-mail.patch # Clarify useradd man regarding "-d" parameter - already upstreamed Patch43: shadow-4.8.1-useradd-man-clarification.patch -# https://github.com/shadow-maint/shadow/commit/140510de9de4771feb3af1d859c09604043a4c9b # https://github.com/shadow-maint/shadow/commit/8762f465d487a52bf68f9c0b7c3c1eb3caea7bc9 Patch44: shadow-4.8.1-check-local-groups.patch # https://github.com/shadow-maint/shadow/commit/599cc003daf833bffdc9cbe0d33dc8b3e7ec74c8 @@ -270,6 +269,9 @@ done %{_mandir}/man8/vigr.8* %changelog +* Mon Aug 16 2021 Iker Pedrosa - 2:4.8.1-7 +- allow all types of groups when modifying supplementary groups (#1975327) + * Mon Apr 26 2021 Iker Pedrosa - 2:4.8.1-6 - man: include lastlog file caveat (#951564) - Upstream links to several patches From fbc8eba072226a39bbe8dc9008e43428ce595900 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 17 Aug 2021 09:49:01 +0200 Subject: [PATCH 033/118] libmisc: fix default value in SHA_get_salt_rounds() Signed-off-by: Iker Pedrosa --- ...default-value-in-SHA_get_salt_rounds.patch | 60 +++++++++++++++++++ shadow-utils.spec | 10 +++- 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch diff --git a/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch b/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch new file mode 100644 index 0000000..5eaaec9 --- /dev/null +++ b/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch @@ -0,0 +1,60 @@ +From 234e8fa7b134d1ebabfdad980a3ae5b63c046c62 Mon Sep 17 00:00:00 2001 +From: Mike Gilbert +Date: Sat, 14 Aug 2021 13:24:34 -0400 +Subject: [PATCH] libmisc: fix default value in SHA_get_salt_rounds() + +If SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS are both unspecified, +use SHA_ROUNDS_DEFAULT. + +Previously, the code fell through, calling shadow_random(-1, -1). This +ultimately set rounds = (unsigned long) -1, which ends up being a very +large number! This then got capped to SHA_ROUNDS_MAX later in the +function. + +The new behavior matches BCRYPT_get_salt_rounds(). + +Bug: https://bugs.gentoo.org/808195 +Fixes: https://github.com/shadow-maint/shadow/issues/393 +--- + libmisc/salt.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/libmisc/salt.c b/libmisc/salt.c +index 91d528fd..30eefb9c 100644 +--- a/libmisc/salt.c ++++ b/libmisc/salt.c +@@ -223,20 +223,21 @@ static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *pre + if ((-1 == min_rounds) && (-1 == max_rounds)) { + rounds = SHA_ROUNDS_DEFAULT; + } ++ else { ++ if (-1 == min_rounds) { ++ min_rounds = max_rounds; ++ } + +- if (-1 == min_rounds) { +- min_rounds = max_rounds; +- } ++ if (-1 == max_rounds) { ++ max_rounds = min_rounds; ++ } + +- if (-1 == max_rounds) { +- max_rounds = min_rounds; +- } ++ if (min_rounds > max_rounds) { ++ max_rounds = min_rounds; ++ } + +- if (min_rounds > max_rounds) { +- max_rounds = min_rounds; ++ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); + } +- +- rounds = (unsigned long) shadow_random (min_rounds, max_rounds); + } else if (0 == *prefered_rounds) { + rounds = SHA_ROUNDS_DEFAULT; + } else { +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 47d61e0..f753ae7 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.9 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz @@ -48,8 +48,10 @@ Patch13: shadow-4.8-ignore-login-prompt.patch Patch14: shadow-4.9-newuidmap-libeconf-dependency.patch # https://github.com/shadow-maint/shadow/commit/e481437ab9ebe9a8bf8fbaabe986d42b2f765991 Patch15: shadow-4.9-usermod-allow-all-group-types.patch -# https://github.com/shadow-maint/shadow/pull/399 +# https://github.com/shadow-maint/shadow/commit/9dd720a28578eef5be8171697aae0906e4c53249 Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch +# https://github.com/shadow-maint/shadow/commit/234e8fa7b134d1ebabfdad980a3ae5b63c046c62 +Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch License: BSD and GPLv2+ BuildRequires: make @@ -114,6 +116,7 @@ Development files for shadow-utils-subid. %patch14 -p1 -b .newuidmap-libeconf-dependency %patch15 -p1 -b .usermod-allow-all-group-types %patch16 -p1 -b .useradd-avoid-generating-empty-subid-range +%patch17 -p1 -b .libmisc-fix-default-value-in-SHA_get_salt_rounds iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -284,6 +287,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Tue Aug 17 2021 Iker Pedrosa - 2:4.9-3 +- libmisc: fix default value in SHA_get_salt_rounds() + * Mon Aug 9 2021 Iker Pedrosa - 2:4.9-2 - useradd: avoid generating an empty subid range (#1990653) From 981bd7a0930fc16277f0149fe6054a5f49c5bdfe Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 21 Sep 2021 10:37:43 +0200 Subject: [PATCH 034/118] - login.defs: include HMAC_CRYPTO_ALGO key - Clean spec file: organize dependencies and move License location Signed-off-by: Iker Pedrosa --- shadow-utils.login.defs | 10 ++++++++++ shadow-utils.spec | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index 486203b..a6c34a1 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -293,3 +293,13 @@ CREATE_HOME yes # missing. # #FORCE_SHADOW yes + +# +# Select the HMAC cryptography algorithm. +# Used in pam_timestamp module to calculate the keyed-hash message +# authentication code. +# +# Note: It is recommended to check hmac(3) to see the possible algorithms +# that are available in your system. +# +HMAC_CRYPTO_ALGO SHA512 diff --git a/shadow-utils.spec b/shadow-utils.spec index f753ae7..051708d 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,8 +1,9 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils Version: 4.9 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 +License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz Source1: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz.asc @@ -53,19 +54,31 @@ Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch # https://github.com/shadow-maint/shadow/commit/234e8fa7b134d1ebabfdad980a3ae5b63c046c62 Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch -License: BSD and GPLv2+ -BuildRequires: make -BuildRequires: gcc -BuildRequires: libselinux-devel >= 1.25.2-1 -BuildRequires: audit-libs-devel >= 1.6.5 -BuildRequires: libsemanage-devel -BuildRequires: libacl-devel, libattr-devel -BuildRequires: bison, flex, docbook-style-xsl, docbook-dtds -BuildRequires: autoconf, automake, libtool, gettext-devel -BuildRequires: /usr/bin/xsltproc, /usr/bin/itstool -Requires: libselinux >= 1.25.2-1 +### Dependencies ### Requires: audit-libs >= 1.6.5 +Requires: libselinux >= 1.25.2-1 Requires: setup + +### Build Dependencies ### +BuildRequires: audit-libs-devel >= 1.6.5 +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: bison +BuildRequires: docbook-dtds +BuildRequires: docbook-style-xsl +BuildRequires: flex +BuildRequires: gcc +BuildRequires: gettext-devel +BuildRequires: itstool +BuildRequires: libacl-devel +BuildRequires: libattr-devel +BuildRequires: libselinux-devel >= 1.25.2-1 +BuildRequires: libsemanage-devel +BuildRequires: libtool +BuildRequires: libxslt +BuildRequires: make + +### Provides ### Provides: shadow = %{epoch}:%{version}-%{release} %description @@ -287,6 +300,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Thu Sep 23 2021 Iker Pedrosa - 2:4.9-4 +- login.defs: include HMAC_CRYPTO_ALGO key +- Clean spec file: organize dependencies and move License location + * Tue Aug 17 2021 Iker Pedrosa - 2:4.9-3 - libmisc: fix default value in SHA_get_salt_rounds() From 11164c2c0a8816d49e94ca0343e421016e606603 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 27 Oct 2021 12:02:57 +0200 Subject: [PATCH 035/118] useradd: generate home and mail directories with selinux user attribute Signed-off-by: Iker Pedrosa --- shadow-4.9-move-create-home.patch | 40 +++++++++--- ....9-semanage-close-the-selabel-handle.patch | 61 +++++++++++++++++++ shadow-utils.spec | 10 ++- 3 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 shadow-4.9-semanage-close-the-selabel-handle.patch diff --git a/shadow-4.9-move-create-home.patch b/shadow-4.9-move-create-home.patch index 94bb84c..0ed6ea7 100644 --- a/shadow-4.9-move-create-home.patch +++ b/shadow-4.9-move-create-home.patch @@ -1,8 +1,22 @@ +From 09c752f00f9dfc610f66d68be38c9e5be8ca7f15 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 8 Oct 2021 13:09:59 +0200 +Subject: [PATCH] useradd: create directories after the SELinux user + +Create the home and mail folders after the SELinux user has been set for +the added user. This will allow the folders to be created with the +SELinux user label. + +Signed-off-by: Iker Pedrosa +--- + src/useradd.c | 46 +++++++++++++++++++++++----------------------- + 1 file changed, 23 insertions(+), 23 deletions(-) + diff --git a/src/useradd.c b/src/useradd.c -index baeffb35..02e1402c 100644 +index 6269c01c..b463a170 100644 --- a/src/useradd.c +++ b/src/useradd.c -@@ -2644,27 +2644,12 @@ int main (int argc, char **argv) +@@ -2670,27 +2670,12 @@ int main (int argc, char **argv) usr_update (); @@ -34,17 +48,14 @@ index baeffb35..02e1402c 100644 /* * tallylog_reset needs to be able to lookup * a valid existing user name, -@@ -2695,9 +2680,24 @@ int main (int argc, char **argv) - exit(1); +@@ -2716,15 +2701,30 @@ int main (int argc, char **argv) } + #endif /* WITH_SELINUX */ -- nscd_flush_cache ("passwd"); -- nscd_flush_cache ("group"); -- sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); + if (mflg) { + create_home (); + if (home_added) { -+ copy_tree (def_template, prefix_user_home, false, true, ++ copy_tree (def_template, prefix_user_home, false, false, + (uid_t)-1, user_id, (gid_t)-1, user_gid); + } else { + fprintf (stderr, @@ -59,6 +70,19 @@ index baeffb35..02e1402c 100644 + if (!rflg) { + create_mail (); + } ++ + if (run_parts ("/etc/shadow-maint/useradd-post.d", (char*)user_name, + "useradd")) { + exit(1); + } +- nscd_flush_cache ("passwd"); +- nscd_flush_cache ("group"); +- sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); +- return E_SUCCESS; } + +-- +2.31.1 + diff --git a/shadow-4.9-semanage-close-the-selabel-handle.patch b/shadow-4.9-semanage-close-the-selabel-handle.patch new file mode 100644 index 0000000..11a23e4 --- /dev/null +++ b/shadow-4.9-semanage-close-the-selabel-handle.patch @@ -0,0 +1,61 @@ +From 234af5cf67fc1a3ba99fc246ba65869a3c416545 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 8 Oct 2021 13:13:13 +0200 +Subject: [PATCH] semanage: close the selabel handle + +Close the selabel handle to update the file_context. This means that the +file_context will be remmaped and used by selabel_lookup() to return +the appropriate context to label the home folder. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1993081 + +Signed-off-by: Iker Pedrosa +--- + lib/prototypes.h | 1 + + lib/selinux.c | 5 +++++ + lib/semanage.c | 1 + + 3 files changed, 7 insertions(+) + +diff --git a/lib/prototypes.h b/lib/prototypes.h +index 1d1586d4..b697e0ec 100644 +--- a/lib/prototypes.h ++++ b/lib/prototypes.h +@@ -392,6 +392,7 @@ extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const + /* selinux.c */ + #ifdef WITH_SELINUX + extern int set_selinux_file_context (const char *dst_name, mode_t mode); ++extern void reset_selinux_handle (void); + extern int reset_selinux_file_context (void); + extern int check_selinux_permit (const char *perm_name); + #endif +diff --git a/lib/selinux.c b/lib/selinux.c +index c83545f9..b075d4c0 100644 +--- a/lib/selinux.c ++++ b/lib/selinux.c +@@ -50,6 +50,11 @@ static void cleanup(void) + } + } + ++void reset_selinux_handle (void) ++{ ++ cleanup(); ++} ++ + /* + * set_selinux_file_context - Set the security context before any file or + * directory creation. +diff --git a/lib/semanage.c b/lib/semanage.c +index 0d30456a..a5bf9218 100644 +--- a/lib/semanage.c ++++ b/lib/semanage.c +@@ -293,6 +293,7 @@ int set_seuser (const char *login_name, const char *seuser_name) + } + + ret = 0; ++ reset_selinux_handle(); + + done: + semanage_seuser_key_free (key); +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 051708d..871a2e1 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.9 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -21,7 +21,7 @@ Source6: shadow-utils.HOME_MODE.xml Patch0: shadow-4.9-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable Patch1: shadow-4.8-goodname.patch -# Move create home to the end of main - upstreamability unknown +# https://github.com/shadow-maint/shadow/commit/09c752f00f9dfc610f66d68be38c9e5be8ca7f15 Patch2: shadow-4.9-move-create-home.patch # SElinux related - upstreamability unknown Patch3: shadow-4.9-default-range.patch @@ -53,6 +53,8 @@ Patch15: shadow-4.9-usermod-allow-all-group-types.patch Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch # https://github.com/shadow-maint/shadow/commit/234e8fa7b134d1ebabfdad980a3ae5b63c046c62 Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch +# https://github.com/shadow-maint/shadow/commit/234af5cf67fc1a3ba99fc246ba65869a3c416545 +Patch18: shadow-4.9-semanage-close-the-selabel-handle.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -130,6 +132,7 @@ Development files for shadow-utils-subid. %patch15 -p1 -b .usermod-allow-all-group-types %patch16 -p1 -b .useradd-avoid-generating-empty-subid-range %patch17 -p1 -b .libmisc-fix-default-value-in-SHA_get_salt_rounds +%patch18 -p1 -b .semanage-close-the-selabel-handle iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -300,6 +303,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Wed Oct 27 2021 Iker Pedrosa - 2:4.9-5 +- useradd: generate home and mail directories with selinux user attribute + * Thu Sep 23 2021 Iker Pedrosa - 2:4.9-4 - login.defs: include HMAC_CRYPTO_ALGO key - Clean spec file: organize dependencies and move License location From 4a03ec740c3bfa806e27fe66994d41827063eb2e Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 4 Nov 2021 12:47:10 +0100 Subject: [PATCH 036/118] useradd: revert fix memleak of grp (#2018697) Signed-off-by: Iker Pedrosa --- shadow-4.9-revert-useradd-fix-memleak.patch | 30 +++++++++++++++++++++ shadow-utils.spec | 8 +++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 shadow-4.9-revert-useradd-fix-memleak.patch diff --git a/shadow-4.9-revert-useradd-fix-memleak.patch b/shadow-4.9-revert-useradd-fix-memleak.patch new file mode 100644 index 0000000..e8251f2 --- /dev/null +++ b/shadow-4.9-revert-useradd-fix-memleak.patch @@ -0,0 +1,30 @@ +From 4624e9fca1b02b64e25e8b2280a0186182ab73ba Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Sat, 14 Aug 2021 19:37:24 -0500 +Subject: [PATCH] Revert "useradd.c:fix memleaks of grp" + +In some cases, the value which was being freed is not actually +safe to free. + +Closes #394 + +This reverts commit c44b71cec25d60efc51aec9de3abce1f6efbfcf5. +--- + src/useradd.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index f90127cd..0d3f390d 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -413,7 +413,6 @@ static void get_defaults (void) + } else { + def_group = grp->gr_gid; + def_gname = xstrdup (grp->gr_name); +- gr_free(grp); + } + } + +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 871a2e1..d4a715a 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.9 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -55,6 +55,8 @@ Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch # https://github.com/shadow-maint/shadow/commit/234af5cf67fc1a3ba99fc246ba65869a3c416545 Patch18: shadow-4.9-semanage-close-the-selabel-handle.patch +# https://github.com/shadow-maint/shadow/commit/4624e9fca1b02b64e25e8b2280a0186182ab73ba +Patch19: shadow-4.9-revert-useradd-fix-memleak.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -133,6 +135,7 @@ Development files for shadow-utils-subid. %patch16 -p1 -b .useradd-avoid-generating-empty-subid-range %patch17 -p1 -b .libmisc-fix-default-value-in-SHA_get_salt_rounds %patch18 -p1 -b .semanage-close-the-selabel-handle +%patch19 -p1 -b .revert-useradd-fix-memleak iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -303,6 +306,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Thu Nov 4 2021 Iker Pedrosa - 2:4.9-6 +- useradd: revert fix memleak of grp (#2018697) + * Wed Oct 27 2021 Iker Pedrosa - 2:4.9-5 - useradd: generate home and mail directories with selinux user attribute From a2d5d3dbdafbbe5adcf8c987ab6441684596d033 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 12 Nov 2021 15:47:43 +0100 Subject: [PATCH 037/118] useradd: change SELinux labels for home files (#2022658) Signed-off-by: Iker Pedrosa --- shadow-4.9-useradd-copy-tree-argument.patch | 13 +++++++++++++ shadow-utils.spec | 8 +++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 shadow-4.9-useradd-copy-tree-argument.patch diff --git a/shadow-4.9-useradd-copy-tree-argument.patch b/shadow-4.9-useradd-copy-tree-argument.patch new file mode 100644 index 0000000..f6b9827 --- /dev/null +++ b/shadow-4.9-useradd-copy-tree-argument.patch @@ -0,0 +1,13 @@ +diff --git a/src/useradd.c b/src/useradd.c +index b463a170..f7c97958 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2704,7 +2704,7 @@ int main (int argc, char **argv) + if (mflg) { + create_home (); + if (home_added) { +- copy_tree (def_template, prefix_user_home, false, false, ++ copy_tree (def_template, prefix_user_home, false, true, + (uid_t)-1, user_id, (gid_t)-1, user_gid); + } else { + fprintf (stderr, diff --git a/shadow-utils.spec b/shadow-utils.spec index d4a715a..44e89c1 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.9 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -57,6 +57,8 @@ Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch Patch18: shadow-4.9-semanage-close-the-selabel-handle.patch # https://github.com/shadow-maint/shadow/commit/4624e9fca1b02b64e25e8b2280a0186182ab73ba Patch19: shadow-4.9-revert-useradd-fix-memleak.patch +# https://github.com/shadow-maint/shadow/pull/439 +Patch20: shadow-4.9-useradd-copy-tree-argument.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -136,6 +138,7 @@ Development files for shadow-utils-subid. %patch17 -p1 -b .libmisc-fix-default-value-in-SHA_get_salt_rounds %patch18 -p1 -b .semanage-close-the-selabel-handle %patch19 -p1 -b .revert-useradd-fix-memleak +%patch20 -p1 -b .useradd-copy-tree-argument iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -306,6 +309,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Fri Nov 12 2021 Iker Pedrosa - 2:4.9-7 +- useradd: change SELinux labels for home files (#2022658) + * Thu Nov 4 2021 Iker Pedrosa - 2:4.9-6 - useradd: revert fix memleak of grp (#2018697) From 957f0eb09e9fa1983f1723f459739412b566a232 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 19 Nov 2021 09:44:08 +0100 Subject: [PATCH 038/118] - getsubids: provide system binary and man page (#1980780) - pwck: fix segfault when calling fprintf() (#2021339) - newgrp: fix segmentation fault (#2019553) - groupdel: fix SIGSEGV when passwd does not exist (#1986111) Signed-off-by: Iker Pedrosa --- shadow-4.9-getsubids.patch | 245 ++++++++++++++++++ ...x-sigsegv-when-passwd-does-not-exist.patch | 13 + ...ow-4.9-newgrp-fix-segmentation-fault.patch | 35 +++ ...ck-fix-segfault-when-calling-fprintf.patch | 30 +++ shadow-utils.spec | 24 +- 5 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 shadow-4.9-getsubids.patch create mode 100644 shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch create mode 100644 shadow-4.9-newgrp-fix-segmentation-fault.patch create mode 100644 shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch diff --git a/shadow-4.9-getsubids.patch b/shadow-4.9-getsubids.patch new file mode 100644 index 0000000..b9f2449 --- /dev/null +++ b/shadow-4.9-getsubids.patch @@ -0,0 +1,245 @@ +diff -up shadow-4.9/man/getsubids.1.xml.getsubids shadow-4.9/man/getsubids.1.xml +--- shadow-4.9/man/getsubids.1.xml.getsubids 2021-11-18 16:27:33.951053120 +0100 ++++ shadow-4.9/man/getsubids.1.xml 2021-11-18 16:27:33.951053120 +0100 +@@ -0,0 +1,141 @@ ++ ++ ++ ++]> ++ ++ ++ ++ ++ Iker ++ Pedrosa ++ Creation, 2021 ++ ++ ++ ++ getsubids ++ 1 ++ User Commands ++ shadow-utils ++ &SHADOW_UTILS_VERSION; ++ ++ ++ getsubids ++ get the subordinate id ranges for a user ++ ++ ++ ++ ++ getsubids ++ ++ options ++ ++ ++ USER ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ The getsubids command lists the subordinate user ID ++ ranges for a given user. The subordinate group IDs can be listed using ++ the option. ++ ++ ++ ++ ++ OPTIONS ++ ++ The options which apply to the getsubids command are: ++ ++ ++ ++ ++ ++ ++ ++ ++ List the subordinate group ID ranges. ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLE ++ ++ For example, to obtain the subordinate UIDs of the testuser: ++ ++ ++ ++$ getsubids testuser ++0: testuser 100000 65536 ++ ++ ++ ++ This command output provides (in order from left to right) the list ++ index, username, UID range start, and number of UIDs in range. ++ ++ ++ ++ ++ SEE ALSO ++ ++ ++ login.defs5 ++ , ++ ++ newgidmap1 ++ , ++ ++ newuidmap1 ++ , ++ ++ subgid5 ++ , ++ ++ subuid5 ++ , ++ ++ useradd8 ++ , ++ ++ userdel8 ++ . ++ ++ usermod8 ++ , ++ ++ ++ +diff -up shadow-4.9/man/Makefile.am.getsubids shadow-4.9/man/Makefile.am +--- shadow-4.9/man/Makefile.am.getsubids 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/man/Makefile.am 2021-11-18 16:27:33.951053120 +0100 +@@ -62,6 +62,7 @@ man_MANS += $(man_nopam) + endif + + man_subids = \ ++ man1/getsubids.1 \ + man1/newgidmap.1 \ + man1/newuidmap.1 \ + man5/subgid.5 \ +@@ -80,6 +81,7 @@ man_XMANS = \ + expiry.1.xml \ + faillog.5.xml \ + faillog.8.xml \ ++ getsubids.1.xml \ + gpasswd.1.xml \ + groupadd.8.xml \ + groupdel.8.xml \ +diff -up shadow-4.9/src/getsubids.c.getsubids shadow-4.9/src/getsubids.c +--- shadow-4.9/src/getsubids.c.getsubids 2021-11-18 16:27:33.951053120 +0100 ++++ shadow-4.9/src/getsubids.c 2021-11-18 16:27:33.951053120 +0100 +@@ -0,0 +1,46 @@ ++#include ++#include ++#include ++#include "subid.h" ++#include "prototypes.h" ++ ++const char *Prog; ++FILE *shadow_logfd = NULL; ++ ++void usage(void) ++{ ++ fprintf(stderr, "Usage: %s [-g] user\n", Prog); ++ fprintf(stderr, " list subuid ranges for user\n"); ++ fprintf(stderr, " pass -g to list subgid ranges\n"); ++ exit(EXIT_FAILURE); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int i, count=0; ++ struct subid_range *ranges; ++ const char *owner; ++ ++ Prog = Basename (argv[0]); ++ shadow_logfd = stderr; ++ if (argc < 2) ++ usage(); ++ owner = argv[1]; ++ if (argc == 3 && strcmp(argv[1], "-g") == 0) { ++ owner = argv[2]; ++ count = get_subgid_ranges(owner, &ranges); ++ } else if (argc == 2 && strcmp(argv[1], "-h") == 0) { ++ usage(); ++ } else { ++ count = get_subuid_ranges(owner, &ranges); ++ } ++ if (!ranges) { ++ fprintf(stderr, "Error fetching ranges\n"); ++ exit(1); ++ } ++ for (i = 0; i < count; i++) { ++ printf("%d: %s %lu %lu\n", i, owner, ++ ranges[i].start, ranges[i].count); ++ } ++ return 0; ++} +diff -up shadow-4.9/src/list_subid_ranges.c.getsubids shadow-4.9/src/list_subid_ranges.c +diff -up shadow-4.9/src/Makefile.am.getsubids shadow-4.9/src/Makefile.am +--- shadow-4.9/src/Makefile.am.getsubids 2021-11-18 16:27:33.943053061 +0100 ++++ shadow-4.9/src/Makefile.am 2021-11-18 16:28:03.647272392 +0100 +@@ -157,8 +157,8 @@ if FCAPS + setcap cap_setgid+ep $(DESTDIR)$(ubindir)/newgidmap + endif + +-noinst_PROGRAMS += list_subid_ranges \ +- get_subid_owners \ ++bin_PROGRAMS += getsubids ++noinst_PROGRAMS += get_subid_owners \ + new_subid_range \ + free_subid_range \ + check_subid_range +@@ -174,13 +174,13 @@ MISCLIBS = \ + $(LIBCRYPT) \ + $(LIBTCB) + +-list_subid_ranges_LDADD = \ ++getsubids_LDADD = \ + $(top_builddir)/lib/libshadow.la \ + $(top_builddir)/libmisc/libmisc.la \ + $(top_builddir)/libsubid/libsubid.la \ + $(MISCLIBS) -ldl + +-list_subid_ranges_CPPFLAGS = \ ++getsubids_CPPFLAGS = \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/libmisc \ + -I$(top_srcdir)/libsubid diff --git a/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch b/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch new file mode 100644 index 0000000..658156a --- /dev/null +++ b/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch @@ -0,0 +1,13 @@ +diff -up shadow-4.9/libmisc/prefix_flag.c.groupdel-fix-sigsegv-when-passwd-does-not-exist shadow-4.9/libmisc/prefix_flag.c +--- shadow-4.9/libmisc/prefix_flag.c.groupdel-fix-sigsegv-when-passwd-does-not-exist 2021-11-19 09:21:36.997091941 +0100 ++++ shadow-4.9/libmisc/prefix_flag.c 2021-11-19 09:22:19.001341010 +0100 +@@ -288,6 +288,9 @@ extern struct passwd* prefix_getpwent() + if(!passwd_db_file) { + return getpwent(); + } ++ if (!fp_pwent) { ++ return NULL; ++ } + return fgetpwent(fp_pwent); + } + extern void prefix_endpwent() diff --git a/shadow-4.9-newgrp-fix-segmentation-fault.patch b/shadow-4.9-newgrp-fix-segmentation-fault.patch new file mode 100644 index 0000000..49332a1 --- /dev/null +++ b/shadow-4.9-newgrp-fix-segmentation-fault.patch @@ -0,0 +1,35 @@ +From 497e90751bc0d95cc998b0f06305040563903948 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Wed, 10 Nov 2021 12:02:04 +0100 +Subject: [PATCH] newgrp: fix segmentation fault + +Fix segmentation fault in newgrp when xgetspnam() returns a NULL value +that is immediately freed. + +The error was committed in +https://github.com/shadow-maint/shadow/commit/e65cc6aebcb4132fa413f00a905216a5b35b3d57 + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2019553 + +Signed-off-by: Iker Pedrosa +--- + src/newgrp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/newgrp.c b/src/newgrp.c +index 730f47e8..566f1c89 100644 +--- a/src/newgrp.c ++++ b/src/newgrp.c +@@ -163,8 +163,8 @@ static void check_perms (const struct group *grp, + spwd = xgetspnam (pwd->pw_name); + if (NULL != spwd) { + pwd->pw_passwd = xstrdup (spwd->sp_pwdp); ++ spw_free (spwd); + } +- spw_free (spwd); + + if ((pwd->pw_passwd[0] == '\0') && (grp->gr_passwd[0] != '\0')) { + needspasswd = true; +-- +2.31.1 + diff --git a/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch b/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch new file mode 100644 index 0000000..e7761b7 --- /dev/null +++ b/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch @@ -0,0 +1,30 @@ +From d8e54618feea201987c1f3cb402ed50d1d8b604f Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 15 Nov 2021 12:40:15 +0100 +Subject: [PATCH] pwck: fix segfault when calling fprintf() + +As shadow_logfd variable is not set at the beginning of the program if +something fails and fprintf() is called a segmentation fault happens. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2021339 + +Signed-off-by: Iker Pedrosa +--- + src/pwck.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/pwck.c b/src/pwck.c +index 4248944a..4ce86af2 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -857,6 +857,7 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); ++ shadow_logfd = stderr; + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +-- +2.31.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 44e89c1..e7e2970 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.9 -Release: 7%{?dist} +Release: 8%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -57,8 +57,16 @@ Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch Patch18: shadow-4.9-semanage-close-the-selabel-handle.patch # https://github.com/shadow-maint/shadow/commit/4624e9fca1b02b64e25e8b2280a0186182ab73ba Patch19: shadow-4.9-revert-useradd-fix-memleak.patch -# https://github.com/shadow-maint/shadow/pull/439 +# https://github.com/shadow-maint/shadow/commit/06eb4e4d76ac7f1ac86e68a89b2dc9be7c7323a2 Patch20: shadow-4.9-useradd-copy-tree-argument.patch +# https://github.com/shadow-maint/shadow/commit/d8e54618feea201987c1f3cb402ed50d1d8b604f +Patch21: shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch +# https://github.com/shadow-maint/shadow/commit/497e90751bc0d95cc998b0f06305040563903948 +Patch22: shadow-4.9-newgrp-fix-segmentation-fault.patch +# https://github.com/shadow-maint/shadow/commit/3b6ccf642c6bb2b7db087f09ee563ae9318af734 +Patch23: shadow-4.9-getsubids.patch +# https://github.com/shadow-maint/shadow/commit/a757b458ffb4fb9a40bcbb4f7869449431c67f83 +Patch24: shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -139,6 +147,10 @@ Development files for shadow-utils-subid. %patch18 -p1 -b .semanage-close-the-selabel-handle %patch19 -p1 -b .revert-useradd-fix-memleak %patch20 -p1 -b .useradd-copy-tree-argument +%patch21 -p1 -b .pwck-fix-segfault-when-calling-fprintf +%patch22 -p1 -b .newgrp-fix-segmentation-fault +%patch23 -p1 -b .getsubids +%patch24 -p1 -b .groupdel-fix-sigsegv-when-passwd-does-not-exist iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -303,12 +315,20 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %files subid %{_libdir}/libsubid.so.* +%{_bindir}/getsubids +%{_mandir}/man1/getsubids.1* %files subid-devel %{includesubiddir}/subid.h %{_libdir}/libsubid.so %changelog +* Fri Nov 19 2021 Iker Pedrosa - 2:4.9-8 +- getsubids: provide system binary and man page (#1980780) +- pwck: fix segfault when calling fprintf() (#2021339) +- newgrp: fix segmentation fault (#2019553) +- groupdel: fix SIGSEGV when passwd does not exist (#1986111) + * Fri Nov 12 2021 Iker Pedrosa - 2:4.9-7 - useradd: change SELinux labels for home files (#2022658) From 77cc4a7c14037e8425c5c38c502c5ac521e5a4b6 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 17 Jan 2022 10:00:50 +0100 Subject: [PATCH 039/118] - nss: get shadow_logfd with log_get_logfd() (#2038811) - lib: make shadow_logfd and Prog not extern - lib: rename Prog to shadow_progname - lib: provide default values for shadow_progname - libsubid: use log_set_progname in subid_init Signed-off-by: Iker Pedrosa --- ...ake-shadow-logfd-and-prog-not-extern.patch | 2497 +++++++++++++++++ ...-get-shadow-logfd-with-log-get-logfd.patch | 48 + ...w-4.9-rename-prog-to-shadow-progname.patch | 507 ++++ shadow-4.9-shadow-progname-default-init.patch | 39 + shadow-utils.spec | 22 +- 5 files changed, 3112 insertions(+), 1 deletion(-) create mode 100644 shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch create mode 100644 shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch create mode 100644 shadow-4.9-rename-prog-to-shadow-progname.patch create mode 100644 shadow-4.9-shadow-progname-default-init.patch diff --git a/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch b/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch new file mode 100644 index 0000000..d0b7059 --- /dev/null +++ b/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch @@ -0,0 +1,2497 @@ +diff -up shadow-4.9/lib/commonio.c.debug1 shadow-4.9/lib/commonio.c +--- shadow-4.9/lib/commonio.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/commonio.c 2022-01-10 10:45:52.202132937 +0100 +@@ -51,6 +51,7 @@ + #endif /* WITH_TCB */ + #include "prototypes.h" + #include "commonio.h" ++#include "shadowlog_internal.h" + + /* local function prototypes */ + static int lrename (const char *, const char *); +diff -up shadow-4.9/lib/encrypt.c.debug1 shadow-4.9/lib/encrypt.c +--- shadow-4.9/lib/encrypt.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/encrypt.c 2022-01-10 10:45:52.202132937 +0100 +@@ -39,6 +39,7 @@ + + #include "prototypes.h" + #include "defines.h" ++#include "shadowlog_internal.h" + + /*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt) + { +diff -up shadow-4.9/lib/getdef.c.debug1 shadow-4.9/lib/getdef.c +--- shadow-4.9/lib/getdef.c.debug1 2022-01-10 10:45:52.191132858 +0100 ++++ shadow-4.9/lib/getdef.c 2022-01-10 10:45:52.202132937 +0100 +@@ -44,6 +44,7 @@ + #include + #endif + #include "getdef.h" ++#include "shadowlog_internal.h" + /* + * A configuration item definition. + */ +diff -up shadow-4.9/lib/Makefile.am.debug1 shadow-4.9/lib/Makefile.am +--- shadow-4.9/lib/Makefile.am.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/Makefile.am 2022-01-10 10:45:52.202132937 +0100 +@@ -34,6 +34,8 @@ libshadow_la_SOURCES = \ + nss.c \ + nscd.c \ + nscd.h \ ++ shadowlog.c \ ++ shadowlog.h \ + sssd.c \ + sssd.h \ + pam_defs.h \ +diff -up shadow-4.9/libmisc/addgrps.c.debug1 shadow-4.9/libmisc/addgrps.c +--- shadow-4.9/libmisc/addgrps.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/addgrps.c 2022-01-10 10:45:52.203132944 +0100 +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include "shadowlog.h" + + #ident "$Id$" + +@@ -58,6 +59,7 @@ int add_groups (const char *list) + char *token; + char buf[1024]; + int ret; ++ FILE *shadow_logfd = log_get_logfd(); + + if (strlen (list) >= sizeof (buf)) { + errno = EINVAL; +diff -up shadow-4.9/libmisc/audit_help.c.debug1 shadow-4.9/libmisc/audit_help.c +--- shadow-4.9/libmisc/audit_help.c.debug1 2022-01-10 10:45:52.184132808 +0100 ++++ shadow-4.9/libmisc/audit_help.c 2022-01-10 10:45:52.203132944 +0100 +@@ -45,6 +45,7 @@ + #include + #include + #include "prototypes.h" ++#include "shadowlog.h" + int audit_fd; + + void audit_help_open (void) +@@ -59,7 +60,7 @@ void audit_help_open (void) + return; + } + (void) fputs (_("Cannot open audit interface - aborting.\n"), +- shadow_logfd); ++ log_get_logfd()); + exit (EXIT_FAILURE); + } + } +diff -up shadow-4.9/libmisc/chowntty.c.debug1 shadow-4.9/libmisc/chowntty.c +--- shadow-4.9/libmisc/chowntty.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/chowntty.c 2022-01-10 10:45:52.203132944 +0100 +@@ -43,6 +43,7 @@ + #include "defines.h" + #include + #include "getdef.h" ++#include "shadowlog.h" + + /* + * chown_tty() sets the login tty to be owned by the new user ID +@@ -75,6 +76,7 @@ void chown_tty (const struct passwd *inf + if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0) + || (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) { + int err = errno; ++ FILE *shadow_logfd = log_get_logfd(); + + fprintf (shadow_logfd, + _("Unable to change owner or mode of tty stdin: %s"), +diff -up shadow-4.9/libmisc/cleanup_group.c.debug1 shadow-4.9/libmisc/cleanup_group.c +--- shadow-4.9/libmisc/cleanup_group.c.debug1 2022-01-10 10:45:52.184132808 +0100 ++++ shadow-4.9/libmisc/cleanup_group.c 2022-01-10 10:47:02.241632844 +0100 +@@ -36,6 +36,7 @@ + #include "groupio.h" + #include "sgroupio.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /* + * cleanup_report_add_group - Report failure to add a group to the system +@@ -48,7 +49,7 @@ void cleanup_report_add_group (void *gro + + SYSLOG ((LOG_ERR, "failed to add group %s", name)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, ++ audit_logger (AUDIT_ADD_GROUP, log_get_progname(), + "", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -66,7 +67,7 @@ void cleanup_report_del_group (void *gro + + SYSLOG ((LOG_ERR, "failed to remove group %s", name)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, ++ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), + "", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -83,7 +84,7 @@ void cleanup_report_mod_group (void *cle + gr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -101,7 +102,7 @@ void cleanup_report_mod_gshadow (void *c + sgr_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -121,7 +122,7 @@ void cleanup_report_add_group_group (voi + + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_GROUP, Prog, ++ audit_logger (AUDIT_ADD_GROUP, log_get_progname(), + "adding-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -141,7 +142,7 @@ void cleanup_report_add_group_gshadow (v + + SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + "adding-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -164,7 +165,7 @@ void cleanup_report_del_group_group (voi + "failed to remove group %s from %s", + name, gr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_DEL_GROUP, Prog, ++ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), + "removing-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -187,7 +188,7 @@ void cleanup_report_del_group_gshadow (v + "failed to remove group %s from %s", + name, sgr_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + "removing-shadow-group", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -203,9 +204,9 @@ void cleanup_report_del_group_gshadow (v + void cleanup_unlock_group (unused void *arg) + { + if (gr_unlock () == 0) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), +- Prog, gr_dbname ()); ++ log_get_progname(), gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT + audit_logger_message ("unlocking-group", +@@ -223,9 +224,9 @@ void cleanup_unlock_group (unused void * + void cleanup_unlock_gshadow (unused void *arg) + { + if (sgr_unlock () == 0) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), +- Prog, sgr_dbname ()); ++ log_get_progname(), sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT + audit_logger_message ("unlocking-gshadow", +diff -up shadow-4.9/libmisc/cleanup_user.c.debug1 shadow-4.9/libmisc/cleanup_user.c +--- shadow-4.9/libmisc/cleanup_user.c.debug1 2022-01-10 10:45:52.184132808 +0100 ++++ shadow-4.9/libmisc/cleanup_user.c 2022-01-10 10:47:49.539970421 +0100 +@@ -36,6 +36,7 @@ + #include "pwio.h" + #include "shadowio.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /* + * cleanup_report_add_user - Report failure to add an user to the system +@@ -48,7 +49,7 @@ void cleanup_report_add_user (void *user + + SYSLOG ((LOG_ERR, "failed to add user %s", name)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, ++ audit_logger (AUDIT_ADD_USER, log_get_progname(), + "", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -65,7 +66,7 @@ void cleanup_report_mod_passwd (void *cl + pw_dbname (), + info->action)); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_MGMT, Prog, ++ audit_logger (AUDIT_USER_MGMT, log_get_progname(), + info->audit_msg, + info->name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -85,7 +86,7 @@ void cleanup_report_add_user_passwd (voi + + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_ADD_USER, Prog, ++ audit_logger (AUDIT_ADD_USER, log_get_progname(), + "adding-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -105,7 +106,7 @@ void cleanup_report_add_user_shadow (voi + + SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_MGMT, Prog, ++ audit_logger (AUDIT_USER_MGMT, log_get_progname(), + "adding-shadow-user", + name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); +@@ -120,9 +121,9 @@ void cleanup_report_add_user_shadow (voi + void cleanup_unlock_passwd (unused void *arg) + { + if (pw_unlock () == 0) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), +- Prog, pw_dbname ()); ++ log_get_progname(), pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT + audit_logger_message ("unlocking-passwd", +@@ -139,9 +140,9 @@ void cleanup_unlock_passwd (unused void + void cleanup_unlock_shadow (unused void *arg) + { + if (spw_unlock () == 0) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), +- Prog, spw_dbname ()); ++ log_get_progname(), spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT + audit_logger_message ("unlocking-shadow", +diff -up shadow-4.9/libmisc/copydir.c.debug1 shadow-4.9/libmisc/copydir.c +--- shadow-4.9/libmisc/copydir.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/copydir.c 2022-01-10 10:48:02.158060482 +0100 +@@ -55,6 +55,7 @@ + #ifdef WITH_ATTR + #include + #endif /* WITH_ATTR */ ++#include "shadowlog.h" + + + static /*@null@*/const char *src_orig; +@@ -116,6 +117,7 @@ static int fchown_if_needed (int fdst, c + static void error_acl (struct error_context *ctx, const char *fmt, ...) + { + va_list ap; ++ FILE *shadow_logfd = log_get_logfd(); + + /* ignore the case when destination does not support ACLs + * or extended attributes */ +@@ -125,7 +127,7 @@ static void error_acl (struct error_cont + } + + va_start (ap, fmt); +- (void) fprintf (shadow_logfd, _("%s: "), Prog); ++ (void) fprintf (shadow_logfd, _("%s: "), log_get_progname()); + if (vfprintf (shadow_logfd, fmt, ap) != 0) { + (void) fputs (_(": "), shadow_logfd); + } +@@ -248,9 +250,9 @@ int copy_tree (const char *src_root, con + } + + if (!S_ISDIR (sb.st_mode)) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + "%s: %s is not a directory", +- Prog, src_root); ++ log_get_progname(), src_root); + return -1; + } + +diff -up shadow-4.9/libmisc/env.c.debug1 shadow-4.9/libmisc/env.c +--- shadow-4.9/libmisc/env.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/env.c 2022-01-10 10:45:52.203132944 +0100 +@@ -40,6 +40,7 @@ + #include + #include "prototypes.h" + #include "defines.h" ++#include "shadowlog.h" + /* + * NEWENVP_STEP must be a power of two. This is the number + * of (char *) pointers to allocate at a time, to avoid using +@@ -171,7 +172,7 @@ void addenv (const char *string, /*@null + } + newenvp = __newenvp; + } else { +- (void) fputs (_("Environment overflow\n"), shadow_logfd); ++ (void) fputs (_("Environment overflow\n"), log_get_logfd()); + newenvc--; + free (newenvp[newenvc]); + } +diff -up shadow-4.9/libmisc/find_new_gid.c.debug1 shadow-4.9/libmisc/find_new_gid.c +--- shadow-4.9/libmisc/find_new_gid.c.debug1 2022-01-10 10:45:52.191132858 +0100 ++++ shadow-4.9/libmisc/find_new_gid.c 2022-01-10 10:45:52.203132944 +0100 +@@ -38,6 +38,7 @@ + #include "prototypes.h" + #include "groupio.h" + #include "getdef.h" ++#include "shadowlog.h" + + /* + * get_ranges - Get the minimum and maximum ID ranges for the search +@@ -74,10 +75,10 @@ static int get_ranges (bool sys_group, g + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: SYS_GID_MIN (%lu), " + "GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), +- Prog, (unsigned long) *min_id, ++ log_get_progname(), (unsigned long) *min_id, + getdef_ulong ("GID_MIN", 1000UL), + (unsigned long) *max_id); + return EINVAL; +@@ -104,10 +105,10 @@ static int get_ranges (bool sys_group, g + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: GID_MIN (%lu), " + "GID_MAX (%lu)\n"), +- Prog, (unsigned long) *min_id, ++ log_get_progname(), (unsigned long) *min_id, + (unsigned long) *max_id); + return EINVAL; + } +@@ -220,10 +221,10 @@ int find_new_gid (bool sys_group, + * more likely to want to stop and address the + * issue. + */ +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Encountered error attempting to use " + "preferred GID: %s\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + return -1; + } + } +@@ -250,9 +251,9 @@ int find_new_gid (bool sys_group, + /* Create an array to hold all of the discovered GIDs */ + used_gids = malloc (sizeof (bool) * (gid_max +1)); + if (NULL == used_gids) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to allocate memory: %s\n"), +- Prog, strerror (errno)); ++ log_get_progname(), strerror (errno)); + return -1; + } + memset (used_gids, false, sizeof (bool) * (gid_max + 1)); +@@ -330,10 +331,10 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique system GID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available GIDs: %s", + strerror (result))); +@@ -373,10 +374,10 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique system GID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available GIDs: %s", + strerror (result))); +@@ -433,10 +434,10 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique GID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available GIDs: %s", + strerror (result))); +@@ -476,10 +477,10 @@ int find_new_gid (bool sys_group, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique GID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available GIDs: %s", + strerror (result))); +@@ -495,9 +496,9 @@ int find_new_gid (bool sys_group, + } + + /* The code reached here and found no available IDs in the range */ +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique GID (no more available GIDs)\n"), +- Prog); ++ log_get_progname()); + SYSLOG ((LOG_WARN, "no more available GIDs on the system")); + free (used_gids); + return -1; +diff -up shadow-4.9/libmisc/find_new_sub_gids.c.debug1 shadow-4.9/libmisc/find_new_sub_gids.c +--- shadow-4.9/libmisc/find_new_sub_gids.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/find_new_sub_gids.c 2022-01-10 10:45:52.203132944 +0100 +@@ -37,6 +37,7 @@ + #include "prototypes.h" + #include "subordinateio.h" + #include "getdef.h" ++#include "shadowlog.h" + + /* + * find_new_sub_gids - Find a new unused range of GIDs. +@@ -60,18 +61,18 @@ int find_new_sub_gids (gid_t *range_star + count = getdef_ulong ("SUB_GID_COUNT", 65536); + + if (min > max || count >= max || (min + count - 1) > max) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: SUB_GID_MIN (%lu)," + " SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"), +- Prog, min, max, count); ++ log_get_progname(), min, max, count); + return -1; + } + + start = sub_gid_find_free_range(min, max, count); + if (start == (gid_t)-1) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique subordinate GID range\n"), +- Prog); ++ log_get_progname()); + SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system")); + return -1; + } +diff -up shadow-4.9/libmisc/find_new_sub_uids.c.debug1 shadow-4.9/libmisc/find_new_sub_uids.c +--- shadow-4.9/libmisc/find_new_sub_uids.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/find_new_sub_uids.c 2022-01-10 10:45:52.203132944 +0100 +@@ -37,6 +37,7 @@ + #include "prototypes.h" + #include "subordinateio.h" + #include "getdef.h" ++#include "shadowlog.h" + + /* + * find_new_sub_uids - Find a new unused range of UIDs. +@@ -60,18 +61,18 @@ int find_new_sub_uids (uid_t *range_star + count = getdef_ulong ("SUB_UID_COUNT", 65536); + + if (min > max || count >= max || (min + count - 1) > max) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: SUB_UID_MIN (%lu)," + " SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"), +- Prog, min, max, count); ++ log_get_progname(), min, max, count); + return -1; + } + + start = sub_uid_find_free_range(min, max, count); + if (start == (uid_t)-1) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique subordinate UID range\n"), +- Prog); ++ log_get_progname()); + SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system")); + return -1; + } +diff -up shadow-4.9/libmisc/find_new_uid.c.debug1 shadow-4.9/libmisc/find_new_uid.c +--- shadow-4.9/libmisc/find_new_uid.c.debug1 2022-01-10 10:45:52.191132858 +0100 ++++ shadow-4.9/libmisc/find_new_uid.c 2022-01-10 10:45:52.204132951 +0100 +@@ -38,6 +38,7 @@ + #include "prototypes.h" + #include "pwio.h" + #include "getdef.h" ++#include "shadowlog.h" + + /* + * get_ranges - Get the minimum and maximum ID ranges for the search +@@ -74,10 +75,10 @@ static int get_ranges (bool sys_user, ui + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: SYS_UID_MIN (%lu), " + "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), +- Prog, (unsigned long) *min_id, ++ log_get_progname(), (unsigned long) *min_id, + getdef_ulong ("UID_MIN", 1000UL), + (unsigned long) *max_id); + return EINVAL; +@@ -104,10 +105,10 @@ static int get_ranges (bool sys_user, ui + + /* Check that the ranges make sense */ + if (*max_id < *min_id) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: Invalid configuration: UID_MIN (%lu), " + "UID_MAX (%lu)\n"), +- Prog, (unsigned long) *min_id, ++ log_get_progname(), (unsigned long) *min_id, + (unsigned long) *max_id); + return EINVAL; + } +@@ -220,10 +221,10 @@ int find_new_uid(bool sys_user, + * more likely to want to stop and address the + * issue. + */ +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Encountered error attempting to use " + "preferred UID: %s\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + return -1; + } + } +@@ -250,9 +251,9 @@ int find_new_uid(bool sys_user, + /* Create an array to hold all of the discovered UIDs */ + used_uids = malloc (sizeof (bool) * (uid_max +1)); + if (NULL == used_uids) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: failed to allocate memory: %s\n"), +- Prog, strerror (errno)); ++ log_get_progname(), strerror (errno)); + return -1; + } + memset (used_uids, false, sizeof (bool) * (uid_max + 1)); +@@ -330,10 +331,10 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique system UID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available UIDs: %s", + strerror (result))); +@@ -373,10 +374,10 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique system UID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG((LOG_ERR, + "Error checking available UIDs: %s", + strerror (result))); +@@ -433,10 +434,10 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique UID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available UIDs: %s", + strerror (result))); +@@ -476,10 +477,10 @@ int find_new_uid(bool sys_user, + * + */ + if (!nospam) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique UID (%s). " + "Suppressing additional messages.\n"), +- Prog, strerror (result)); ++ log_get_progname(), strerror (result)); + SYSLOG ((LOG_ERR, + "Error checking available UIDs: %s", + strerror (result))); +@@ -495,9 +496,9 @@ int find_new_uid(bool sys_user, + } + + /* The code reached here and found no available IDs in the range */ +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: Can't get unique UID (no more available UIDs)\n"), +- Prog); ++ log_get_progname()); + SYSLOG ((LOG_WARN, "no more available UIDs on the system")); + free (used_uids); + return -1; +diff -up shadow-4.9/libmisc/gettime.c.debug1 shadow-4.9/libmisc/gettime.c +--- shadow-4.9/libmisc/gettime.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/gettime.c 2022-01-10 10:45:52.204132951 +0100 +@@ -36,6 +36,7 @@ + #include + #include "defines.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /* + * gettime() returns the time as the number of seconds since the Epoch +@@ -50,6 +51,7 @@ + char *source_date_epoch; + time_t fallback; + unsigned long long epoch; ++ FILE *shadow_logfd = log_get_logfd(); + + fallback = time (NULL); + source_date_epoch = shadow_getenv ("SOURCE_DATE_EPOCH"); +diff -up shadow-4.9/libmisc/idmapping.c.debug1 shadow-4.9/libmisc/idmapping.c +--- shadow-4.9/libmisc/idmapping.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/idmapping.c 2022-01-10 10:45:52.204132951 +0100 +@@ -40,6 +40,7 @@ + #include + #include + #endif ++#include "shadowlog.h" + + struct map_range *get_map_ranges(int ranges, int argc, char **argv) + { +@@ -47,28 +48,28 @@ struct map_range *get_map_ranges(int ran + int idx, argidx; + + if (ranges < 0 || argc < 0) { +- fprintf(shadow_logfd, "%s: error calculating number of arguments\n", Prog); ++ fprintf(log_get_logfd(), "%s: error calculating number of arguments\n", log_get_progname()); + return NULL; + } + + if (ranges != ((argc + 2) / 3)) { +- fprintf(shadow_logfd, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); ++ fprintf(log_get_logfd(), "%s: ranges: %u is wrong for argc: %d\n", log_get_progname(), ranges, argc); + return NULL; + } + + if ((ranges * 3) > argc) { +- fprintf(shadow_logfd, "ranges: %u argc: %d\n", ++ fprintf(log_get_logfd(), "ranges: %u argc: %d\n", + ranges, argc); +- fprintf(shadow_logfd, ++ fprintf(log_get_logfd(), + _( "%s: Not enough arguments to form %u mappings\n"), +- Prog, ranges); ++ log_get_progname(), ranges); + return NULL; + } + + mappings = calloc(ranges, sizeof(*mappings)); + if (!mappings) { +- fprintf(shadow_logfd, _( "%s: Memory allocation failure\n"), +- Prog); ++ fprintf(log_get_logfd(), _( "%s: Memory allocation failure\n"), ++ log_get_progname()); + exit(EXIT_FAILURE); + } + +@@ -88,24 +89,24 @@ struct map_range *get_map_ranges(int ran + return NULL; + } + if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) { +- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + if (mapping->upper > UINT_MAX || + mapping->lower > UINT_MAX || + mapping->count > UINT_MAX) { +- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + if (mapping->lower + mapping->count > UINT_MAX || + mapping->upper + mapping->count > UINT_MAX) { +- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + if (mapping->lower + mapping->count < mapping->lower || + mapping->upper + mapping->count < mapping->upper) { + /* this one really shouldn't be possible given previous checks */ +- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); ++ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + } +@@ -176,19 +177,19 @@ void write_mapping(int proc_dir_fd, int + } else if (strcmp(map_file, "gid_map") == 0) { + cap = CAP_SETGID; + } else { +- fprintf(shadow_logfd, _("%s: Invalid map file %s specified\n"), Prog, map_file); ++ fprintf(log_get_logfd(), _("%s: Invalid map file %s specified\n"), log_get_progname(), map_file); + exit(EXIT_FAILURE); + } + + /* Align setuid- and fscaps-based new{g,u}idmap behavior. */ + if (geteuid() == 0 && geteuid() != ruid) { + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { +- fprintf(shadow_logfd, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); ++ fprintf(log_get_logfd(), _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + + if (seteuid(ruid) < 0) { +- fprintf(shadow_logfd, _("%s: Could not seteuid to %d\n"), Prog, ruid); ++ fprintf(log_get_logfd(), _("%s: Could not seteuid to %d\n"), log_get_progname(), ruid); + exit(EXIT_FAILURE); + } + } +@@ -204,7 +205,7 @@ void write_mapping(int proc_dir_fd, int + data[0].effective |= CAP_TO_MASK(CAP_SETFCAP); + data[0].permitted = data[0].effective; + if (capset(&hdr, data) < 0) { +- fprintf(shadow_logfd, _("%s: Could not set caps\n"), Prog); ++ fprintf(log_get_logfd(), _("%s: Could not set caps\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + #endif +@@ -222,7 +223,7 @@ void write_mapping(int proc_dir_fd, int + mapping->lower, + mapping->count); + if ((written <= 0) || (written >= (bufsize - (pos - buf)))) { +- fprintf(shadow_logfd, _("%s: snprintf failed!\n"), Prog); ++ fprintf(log_get_logfd(), _("%s: snprintf failed!\n"), log_get_progname()); + exit(EXIT_FAILURE); + } + pos += written; +@@ -231,13 +232,13 @@ void write_mapping(int proc_dir_fd, int + /* Write the mapping to the mapping file */ + fd = openat(proc_dir_fd, map_file, O_WRONLY); + if (fd < 0) { +- fprintf(shadow_logfd, _("%s: open of %s failed: %s\n"), +- Prog, map_file, strerror(errno)); ++ fprintf(log_get_logfd(), _("%s: open of %s failed: %s\n"), ++ log_get_progname(), map_file, strerror(errno)); + exit(EXIT_FAILURE); + } + if (write(fd, buf, pos - buf) != (pos - buf)) { +- fprintf(shadow_logfd, _("%s: write to %s failed: %s\n"), +- Prog, map_file, strerror(errno)); ++ fprintf(log_get_logfd(), _("%s: write to %s failed: %s\n"), ++ log_get_progname(), map_file, strerror(errno)); + exit(EXIT_FAILURE); + } + close(fd); +diff -up shadow-4.9/libmisc/limits.c.debug1 shadow-4.9/libmisc/limits.c +--- shadow-4.9/libmisc/limits.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/limits.c 2022-01-10 10:45:52.204132951 +0100 +@@ -50,6 +50,7 @@ + #include "defines.h" + #include + #include "getdef.h" ++#include "shadowlog.h" + #ifdef HAVE_SYS_RESOURCE_H + #include + #define LIMITS +@@ -548,7 +549,7 @@ void setup_limits (const struct passwd * + #ifdef LIMITS + if (info->pw_uid != 0) { + if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) { +- (void) fputs (_("Too many logins.\n"), shadow_logfd); ++ (void) fputs (_("Too many logins.\n"), log_get_logfd()); + (void) sleep (2); /* XXX: Should be FAIL_DELAY */ + exit (EXIT_FAILURE); + } +diff -up shadow-4.9/libmisc/pam_pass.c.debug1 shadow-4.9/libmisc/pam_pass.c +--- shadow-4.9/libmisc/pam_pass.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/pam_pass.c 2022-01-10 10:45:52.204132951 +0100 +@@ -46,11 +46,13 @@ + #include "defines.h" + #include "pam_defs.h" + #include "prototypes.h" ++#include "shadowlog.h" + + void do_pam_passwd (const char *user, bool silent, bool change_expired) + { + pam_handle_t *pamh = NULL; + int flags = 0, ret; ++ FILE *shadow_logfd = log_get_logfd(); + + if (silent) + flags |= PAM_SILENT; +diff -up shadow-4.9/libmisc/pam_pass_non_interactive.c.debug1 shadow-4.9/libmisc/pam_pass_non_interactive.c +--- shadow-4.9/libmisc/pam_pass_non_interactive.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/pam_pass_non_interactive.c 2022-01-10 10:45:52.204132951 +0100 +@@ -38,6 +38,7 @@ + #include + #include + #include "prototypes.h" ++#include "shadowlog.h" + + /*@null@*/ /*@only@*/static const char *non_interactive_password = NULL; + static int ni_conv (int num_msg, +@@ -76,9 +77,9 @@ static int ni_conv (int num_msg, + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: PAM modules requesting echoing are not supported.\n"), +- Prog); ++ log_get_progname()); + goto failed_conversation; + case PAM_PROMPT_ECHO_OFF: + responses[count].resp = strdup (non_interactive_password); +@@ -88,7 +89,7 @@ static int ni_conv (int num_msg, + break; + case PAM_ERROR_MSG: + if ( (NULL == msg[count]->msg) +- || (fprintf (shadow_logfd, "%s\n", msg[count]->msg) <0)) { ++ || (fprintf (log_get_logfd(), "%s\n", msg[count]->msg) <0)) { + goto failed_conversation; + } + responses[count].resp = NULL; +@@ -101,9 +102,9 @@ static int ni_conv (int num_msg, + responses[count].resp = NULL; + break; + default: +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: conversation type %d not supported.\n"), +- Prog, msg[count]->msg_style); ++ log_get_progname(), msg[count]->msg_style); + goto failed_conversation; + } + } +@@ -143,19 +144,19 @@ int do_pam_passwd_non_interactive (const + + ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh); + if (ret != PAM_SUCCESS) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: (user %s) pam_start failure %d\n"), +- Prog, username, ret); ++ log_get_progname(), username, ret); + return 1; + } + + non_interactive_password = password; + ret = pam_chauthtok (pamh, 0); + if (ret != PAM_SUCCESS) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: (user %s) pam_chauthtok() failed, error:\n" + "%s\n"), +- Prog, username, pam_strerror (pamh, ret)); ++ log_get_progname(), username, pam_strerror (pamh, ret)); + } + + (void) pam_end (pamh, PAM_SUCCESS); +diff -up shadow-4.9/libmisc/prefix_flag.c.debug1 shadow-4.9/libmisc/prefix_flag.c +--- shadow-4.9/libmisc/prefix_flag.c.debug1 2022-01-10 10:45:52.201132929 +0100 ++++ shadow-4.9/libmisc/prefix_flag.c 2022-01-10 10:45:52.204132951 +0100 +@@ -48,6 +48,7 @@ + #include "subordinateio.h" + #endif /* ENABLE_SUBIDS */ + #include "getdef.h" ++#include "shadowlog.h" + + static char *passwd_db_file = NULL; + static char *spw_db_file = NULL; +@@ -83,18 +84,18 @@ extern const char* process_prefix_flag ( + && (val = argv[i] + 9)) + || (strcmp (argv[i], short_opt) == 0)) { + if (NULL != prefix) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: multiple --prefix options\n"), +- Prog); ++ log_get_progname()); + exit (E_BAD_ARG); + } + + if (val) { + prefix = val; + } else if (i + 1 == argc) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: option '%s' requires an argument\n"), +- Prog, argv[i]); ++ log_get_progname(), argv[i]); + exit (E_BAD_ARG); + } else { + prefix = argv[++ i]; +@@ -110,9 +111,9 @@ extern const char* process_prefix_flag ( + /* should we prevent symbolic link from being used as a prefix? */ + + if ( prefix[0] != '/') { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: prefix must be an absolute path\n"), +- Prog); ++ log_get_progname()); + exit (E_BAD_ARG); + } + size_t len; +diff -up shadow-4.9/libmisc/pwdcheck.c.debug1 shadow-4.9/libmisc/pwdcheck.c +--- shadow-4.9/libmisc/pwdcheck.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/pwdcheck.c 2022-01-10 10:45:52.204132951 +0100 +@@ -39,6 +39,7 @@ + #include "prototypes.h" + #include "defines.h" + #include "pwauth.h" ++#include "shadowlog.h" + + void passwd_check (const char *user, const char *passwd, unused const char *progname) + { +@@ -51,7 +52,7 @@ void passwd_check (const char *user, con + if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) { + SYSLOG ((LOG_WARN, "incorrect password for `%s'", user)); + (void) sleep (1); +- fprintf (shadow_logfd, _("Incorrect password for %s.\n"), user); ++ fprintf (log_get_logfd(), _("Incorrect password for %s.\n"), user); + exit (EXIT_FAILURE); + } + } +diff -up shadow-4.9/libmisc/root_flag.c.debug1 shadow-4.9/libmisc/root_flag.c +--- shadow-4.9/libmisc/root_flag.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/root_flag.c 2022-01-10 10:45:52.204132951 +0100 +@@ -38,6 +38,7 @@ + #include "prototypes.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + static void change_root (const char* newroot); + +@@ -65,18 +66,18 @@ extern void process_root_flag (const cha + && (val = argv[i] + 7)) + || (strcmp (argv[i], short_opt) == 0)) { + if (NULL != newroot) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: multiple --root options\n"), +- Prog); ++ log_get_progname()); + exit (E_BAD_ARG); + } + + if (val) { + newroot = val; + } else if (i + 1 == argc) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: option '%s' requires an argument\n"), +- Prog, argv[i]); ++ log_get_progname(), argv[i]); + exit (E_BAD_ARG); + } else { + newroot = argv[++ i]; +@@ -94,36 +95,36 @@ static void change_root (const char* new + /* Drop privileges */ + if ( (setregid (getgid (), getgid ()) != 0) + || (setreuid (getuid (), getuid ()) != 0)) { +- fprintf (shadow_logfd, _("%s: failed to drop privileges (%s)\n"), +- Prog, strerror (errno)); ++ fprintf (log_get_logfd(), _("%s: failed to drop privileges (%s)\n"), ++ log_get_progname(), strerror (errno)); + exit (EXIT_FAILURE); + } + + if ('/' != newroot[0]) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: invalid chroot path '%s'\n"), +- Prog, newroot); ++ log_get_progname(), newroot); + exit (E_BAD_ARG); + } + + if (access (newroot, F_OK) != 0) { +- fprintf(shadow_logfd, ++ fprintf(log_get_logfd(), + _("%s: cannot access chroot directory %s: %s\n"), +- Prog, newroot, strerror (errno)); ++ log_get_progname(), newroot, strerror (errno)); + exit (E_BAD_ARG); + } + + if (chdir (newroot) != 0) { +- fprintf(shadow_logfd, ++ fprintf(log_get_logfd(), + _("%s: cannot chdir to chroot directory %s: %s\n"), +- Prog, newroot, strerror (errno)); ++ log_get_progname(), newroot, strerror (errno)); + exit (E_BAD_ARG); + } + + if (chroot (newroot) != 0) { +- fprintf(shadow_logfd, ++ fprintf(log_get_logfd(), + _("%s: unable to chroot to directory %s: %s\n"), +- Prog, newroot, strerror (errno)); ++ log_get_progname(), newroot, strerror (errno)); + exit (E_BAD_ARG); + } + } +diff -up shadow-4.9/libmisc/salt.c.debug1 shadow-4.9/libmisc/salt.c +--- shadow-4.9/libmisc/salt.c.debug1 2022-01-10 10:45:52.195132887 +0100 ++++ shadow-4.9/libmisc/salt.c 2022-01-10 10:45:52.204132951 +0100 +@@ -21,6 +21,7 @@ + #include "prototypes.h" + #include "defines.h" + #include "getdef.h" ++#include "shadowlog.h" + + #if (defined CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY && \ + CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) +@@ -178,7 +179,7 @@ static long read_random_bytes (void) + #endif + + fail: +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("Unable to obtain random bytes.\n")); + exit (1); + +@@ -506,7 +507,7 @@ static /*@observer@*/const char *gensalt + SHA_salt_rounds_to_buf (result, rounds); + #endif /* USE_SHA_CRYPT */ + } else if (0 != strcmp (method, "DES")) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("Invalid ENCRYPT_METHOD value: '%s'.\n" + "Defaulting to DES.\n"), + method); +@@ -532,7 +533,7 @@ static /*@observer@*/const char *gensalt + + /* Should not happen, but... */ + if (NULL == retval) { +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("Unable to generate a salt from setting " + "\"%s\", check your settings in " + "ENCRYPT_METHOD and the corresponding " +diff -up shadow-4.9/libmisc/setupenv.c.debug1 shadow-4.9/libmisc/setupenv.c +--- shadow-4.9/libmisc/setupenv.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/setupenv.c 2022-01-10 10:45:52.204132951 +0100 +@@ -47,6 +47,7 @@ + #include "defines.h" + #include + #include "getdef.h" ++#include "shadowlog.h" + + #ifndef USE_PAM + static void +@@ -219,7 +220,7 @@ void setup_env (struct passwd *info) + static char temp_pw_dir[] = "/"; + + if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) { +- fprintf (shadow_logfd, _("Unable to cd to '%s'\n"), ++ fprintf (log_get_logfd(), _("Unable to cd to '%s'\n"), + info->pw_dir); + SYSLOG ((LOG_WARN, + "unable to cd to `%s' for user `%s'\n", +diff -up shadow-4.9/libmisc/user_busy.c.debug1 shadow-4.9/libmisc/user_busy.c +--- shadow-4.9/libmisc/user_busy.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/user_busy.c 2022-01-10 10:45:52.204132951 +0100 +@@ -45,6 +45,7 @@ + #ifdef ENABLE_SUBIDS + #include "subordinateio.h" + #endif /* ENABLE_SUBIDS */ ++#include "shadowlog.h" + + #ifdef __linux__ + static int check_status (const char *name, const char *sname, uid_t uid); +@@ -96,9 +97,9 @@ static int user_busy_utmp (const char *n + continue; + } + +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: user %s is currently logged in\n"), +- Prog, name); ++ log_get_progname(), name); + return 1; + } + +@@ -249,9 +250,9 @@ static int user_busy_processes (const ch + #ifdef ENABLE_SUBIDS + sub_uid_close(); + #endif +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: user %s is currently used by process %d\n"), +- Prog, name, pid); ++ log_get_progname(), name, pid); + return 1; + } + +@@ -273,9 +274,9 @@ static int user_busy_processes (const ch + #ifdef ENABLE_SUBIDS + sub_uid_close(); + #endif +- fprintf (shadow_logfd, ++ fprintf (log_get_logfd(), + _("%s: user %s is currently used by process %d\n"), +- Prog, name, pid); ++ log_get_progname(), name, pid); + return 1; + } + } +diff -up shadow-4.9/libmisc/xgetXXbyYY.c.debug1 shadow-4.9/libmisc/xgetXXbyYY.c +--- shadow-4.9/libmisc/xgetXXbyYY.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/xgetXXbyYY.c 2022-01-10 10:45:52.204132951 +0100 +@@ -54,6 +54,7 @@ + #include + #include + #include "prototypes.h" ++#include "shadowlog.h" + + #define XFUNCTION_NAME XPREFIX (FUNCTION_NAME) + #define XPREFIX(name) XPREFIX1 (name) +@@ -74,7 +75,7 @@ + + result = malloc(sizeof(LOOKUP_TYPE)); + if (NULL == result) { +- fprintf (shadow_logfd, _("%s: out of memory\n"), ++ fprintf (log_get_logfd(), _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +@@ -84,7 +85,7 @@ + LOOKUP_TYPE *resbuf = NULL; + buffer = (char *)realloc (buffer, length); + if (NULL == buffer) { +- fprintf (shadow_logfd, _("%s: out of memory\n"), ++ fprintf (log_get_logfd(), _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +@@ -132,7 +133,7 @@ + if (result) { + result = DUP_FUNCTION(result); + if (NULL == result) { +- fprintf (shadow_logfd, _("%s: out of memory\n"), ++ fprintf (log_get_logfd(), _("%s: out of memory\n"), + "x" STRINGIZE(FUNCTION_NAME)); + exit (13); + } +diff -up shadow-4.9/libmisc/xmalloc.c.debug1 shadow-4.9/libmisc/xmalloc.c +--- shadow-4.9/libmisc/xmalloc.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libmisc/xmalloc.c 2022-01-10 10:45:52.204132951 +0100 +@@ -47,6 +47,7 @@ + #include + #include "defines.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size) + { +@@ -54,9 +55,9 @@ + + ptr = (char *) malloc (size); + if (NULL == ptr) { +- (void) fprintf (shadow_logfd, ++ (void) fprintf (log_get_logfd(), + _("%s: failed to allocate memory: %s\n"), +- Prog, strerror (errno)); ++ log_get_progname(), strerror (errno)); + exit (13); + } + return ptr; +diff -up shadow-4.9/lib/nscd.c.debug1 shadow-4.9/lib/nscd.c +--- shadow-4.9/lib/nscd.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/nscd.c 2022-01-10 10:45:52.202132937 +0100 +@@ -10,6 +10,7 @@ + #include "defines.h" + #include "prototypes.h" + #include "nscd.h" ++#include "shadowlog_internal.h" + + #define MSG_NSCD_FLUSH_CACHE_FAILED "%s: Failed to flush the nscd cache.\n" + +diff -up shadow-4.9/lib/nss.c.debug1 shadow-4.9/lib/nss.c +--- shadow-4.9/lib/nss.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/nss.c 2022-01-10 10:45:52.202132937 +0100 +@@ -8,6 +8,7 @@ + #include + #include "prototypes.h" + #include "../libsubid/subid.h" ++#include "shadowlog_internal.h" + + #define NSSWITCH "/etc/nsswitch.conf" + +diff -up shadow-4.9/lib/prototypes.h.debug1 shadow-4.9/lib/prototypes.h +--- shadow-4.9/lib/prototypes.h.debug1 2022-01-10 10:45:52.195132887 +0100 ++++ shadow-4.9/lib/prototypes.h 2022-01-10 10:45:52.202132937 +0100 +@@ -59,9 +59,6 @@ + #include "defines.h" + #include "commonio.h" + +-extern /*@observer@*/ const char *Prog; /* Program name showed in error messages */ +-extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ +- + /* addgrps.c */ + #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) + extern int add_groups (const char *); +diff -up shadow-4.9/lib/run_part.c.debug1 shadow-4.9/lib/run_part.c +--- shadow-4.9/lib/run_part.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/run_part.c 2022-01-10 10:45:52.202132937 +0100 +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include "shadowlog_internal.h" + + int run_part (char *script_path, char *name, char *action) + { +diff -up shadow-4.9/lib/selinux.c.debug1 shadow-4.9/lib/selinux.c +--- shadow-4.9/lib/selinux.c.debug1 2022-01-10 10:45:52.196132894 +0100 ++++ shadow-4.9/lib/selinux.c 2022-01-10 10:45:52.202132937 +0100 +@@ -38,6 +38,8 @@ + #include + #include "prototypes.h" + ++#include "shadowlog_internal.h" ++ + static bool selinux_checked = false; + static bool selinux_enabled; + static /*@null@*/struct selabel_handle *selabel_hnd = NULL; +diff -up shadow-4.9/lib/semanage.c.debug1 shadow-4.9/lib/semanage.c +--- shadow-4.9/lib/semanage.c.debug1 2022-01-10 10:45:52.196132894 +0100 ++++ shadow-4.9/lib/semanage.c 2022-01-10 10:45:52.202132937 +0100 +@@ -43,6 +43,7 @@ + #include + #include "prototypes.h" + ++#include "shadowlog_internal.h" + + #ifndef DEFAULT_SERANGE + #define DEFAULT_SERANGE "s0" +diff -up shadow-4.9/lib/shadowlog.c.debug1 shadow-4.9/lib/shadowlog.c +--- shadow-4.9/lib/shadowlog.c.debug1 2022-01-10 10:45:52.202132937 +0100 ++++ shadow-4.9/lib/shadowlog.c 2022-01-10 10:45:52.202132937 +0100 +@@ -0,0 +1,28 @@ ++#include "shadowlog.h" ++ ++#include "lib/shadowlog_internal.h" ++ ++void log_set_progname(const char *progname) ++{ ++ Prog = progname; ++} ++ ++const char *log_get_progname(void) ++{ ++ return Prog; ++} ++ ++void log_set_logfd(FILE *fd) ++{ ++ if (NULL != fd) ++ shadow_logfd = fd; ++ else ++ shadow_logfd = stderr; ++} ++ ++FILE *log_get_logfd(void) ++{ ++ if (shadow_logfd != NULL) ++ return shadow_logfd; ++ return stderr; ++} +diff -up shadow-4.9/lib/shadowlog.h.debug1 shadow-4.9/lib/shadowlog.h +--- shadow-4.9/lib/shadowlog.h.debug1 2022-01-10 10:45:52.202132937 +0100 ++++ shadow-4.9/lib/shadowlog.h 2022-01-10 10:45:52.202132937 +0100 +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 2021 , Serge Hallyn ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the copyright holders or contributors may not be used to ++ * endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/* $Id$ */ ++#ifndef _LOG_H ++#define _LOG_H ++#include ++ ++extern void log_set_progname(const char *); ++extern const char *log_get_progname(void); ++extern void log_set_logfd(FILE *fd); ++extern FILE *log_get_logfd(void); ++extern void log_dolog(char *, ...); ++ ++#endif +diff -up shadow-4.9/lib/shadowlog_internal.h.debug1 shadow-4.9/lib/shadowlog_internal.h +--- shadow-4.9/lib/shadowlog_internal.h.debug1 2022-01-10 10:45:52.202132937 +0100 ++++ shadow-4.9/lib/shadowlog_internal.h 2022-01-10 10:45:52.202132937 +0100 +@@ -0,0 +1,2 @@ ++const char *Prog; /* Program name showed in error messages */ ++FILE *shadow_logfd; /* file descripter to which error messages are printed */ +diff -up shadow-4.9/lib/spawn.c.debug1 shadow-4.9/lib/spawn.c +--- shadow-4.9/lib/spawn.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/spawn.c 2022-01-10 10:45:52.202132937 +0100 +@@ -38,6 +38,8 @@ + #include "exitcodes.h" + #include "prototypes.h" + ++#include "shadowlog_internal.h" ++ + int run_command (const char *cmd, const char *argv[], + /*@null@*/const char *envp[], /*@out@*/int *status) + { +diff -up shadow-4.9/lib/sssd.c.debug1 shadow-4.9/lib/sssd.c +--- shadow-4.9/lib/sssd.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/sssd.c 2022-01-10 10:45:52.203132944 +0100 +@@ -11,6 +11,8 @@ + #include "prototypes.h" + #include "sssd.h" + ++#include "shadowlog_internal.h" ++ + #define MSG_SSSD_FLUSH_CACHE_FAILED "%s: Failed to flush the sssd cache." + + int sssd_flush_cache (int dbflags) +diff -up shadow-4.9/libsubid/api.c.debug1 shadow-4.9/libsubid/api.c +--- shadow-4.9/libsubid/api.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/libsubid/api.c 2022-01-10 10:48:14.913151522 +0100 +@@ -38,12 +38,13 @@ + #include "subordinateio.h" + #include "idmapping.h" + #include "subid.h" ++#include "shadowlog.h" + + const char *Prog = "(libsubid)"; +-FILE *shadow_logfd; + + bool libsubid_init(const char *progname, FILE * logfd) + { ++ FILE *shadow_logfd; + if (progname) { + progname = strdup(progname); + if (progname) +@@ -53,14 +54,15 @@ bool libsubid_init(const char *progname, + } + + if (logfd) { +- shadow_logfd = logfd; ++ log_set_logfd(logfd); + return true; + } + shadow_logfd = fopen("/dev/null", "w"); + if (!shadow_logfd) { +- shadow_logfd = stderr; ++ log_set_logfd(stderr); + return false; + } ++ log_set_logfd(shadow_logfd); + return true; + } + +diff -up shadow-4.9/lib/tcbfuncs.c.debug1 shadow-4.9/lib/tcbfuncs.c +--- shadow-4.9/lib/tcbfuncs.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/lib/tcbfuncs.c 2022-01-10 10:45:52.203132944 +0100 +@@ -38,6 +38,8 @@ + #include "shadowio.h" + #include "tcbfuncs.h" + ++#include "shadowlog_internal.h" ++ + #define SHADOWTCB_HASH_BY 1000 + #define SHADOWTCB_LOCK_SUFFIX ".lock" + +diff -up shadow-4.9/src/chage.c.debug1 shadow-4.9/src/chage.c +--- shadow-4.9/src/chage.c.debug1 2022-01-10 10:45:52.188132837 +0100 ++++ shadow-4.9/src/chage.c 2022-01-10 10:45:52.205132958 +0100 +@@ -52,6 +52,7 @@ + #include "defines.h" + #include "pwio.h" + #include "shadowio.h" ++#include "shadowlog.h" + #ifdef WITH_TCB + #include "tcbfuncs.h" + #endif +@@ -62,7 +63,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool + dflg = false, /* set last password change date */ +@@ -820,7 +820,8 @@ int main (int argc, char **argv) + * Get the program name so that error messages can use it. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + sanitize_env (); + (void) setlocale (LC_ALL, ""); +diff -up shadow-4.9/src/check_subid_range.c.debug1 shadow-4.9/src/check_subid_range.c +--- shadow-4.9/src/check_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/check_subid_range.c 2022-01-10 10:45:52.205132958 +0100 +@@ -16,9 +16,9 @@ + #include "prototypes.h" + #include "subordinateio.h" + #include "idmapping.h" ++#include "shadowlog.h" + + const char *Prog; +-FILE *shadow_logfd = NULL; + + int main(int argc, char **argv) + { +@@ -26,7 +26,8 @@ int main(int argc, char **argv) + unsigned long start, count; + bool check_uids; + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + if (argc != 5) + exit(1); +diff -up shadow-4.9/src/chfn.c.debug1 shadow-4.9/src/chfn.c +--- shadow-4.9/src/chfn.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/chfn.c 2022-01-10 10:45:52.205132958 +0100 +@@ -52,12 +52,12 @@ + #include "pwio.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables. + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + static char fullnm[BUFSIZ]; + static char roomno[BUFSIZ]; + static char workph[BUFSIZ]; +@@ -640,7 +640,8 @@ int main (int argc, char **argv) + * prefix to most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + sanitize_env (); + (void) setlocale (LC_ALL, ""); +diff -up shadow-4.9/src/chgpasswd.c.debug1 shadow-4.9/src/chgpasswd.c +--- shadow-4.9/src/chgpasswd.c.debug1 2022-01-10 10:45:52.188132837 +0100 ++++ shadow-4.9/src/chgpasswd.c 2022-01-10 10:45:52.205132958 +0100 +@@ -61,12 +61,12 @@ + #endif + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) +@@ -506,7 +506,8 @@ int main (int argc, char **argv) + int line = 0; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/chpasswd.c.debug1 shadow-4.9/src/chpasswd.c +--- shadow-4.9/src/chpasswd.c.debug1 2022-01-10 10:45:52.188132837 +0100 ++++ shadow-4.9/src/chpasswd.c 2022-01-10 10:45:52.205132958 +0100 +@@ -58,12 +58,12 @@ + #include "shadowio.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + static bool eflg = false; + static bool md5flg = false; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) +@@ -494,7 +494,8 @@ int main (int argc, char **argv) + int line = 0; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/chsh.c.debug1 shadow-4.9/src/chsh.c +--- shadow-4.9/src/chsh.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/chsh.c 2022-01-10 10:45:52.205132958 +0100 +@@ -51,6 +51,7 @@ + #endif + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + #ifndef SHELLS_FILE + #define SHELLS_FILE "/etc/shells" +@@ -59,7 +60,6 @@ + * Global variables + */ + const char *Prog; /* Program name */ +-FILE *shadow_logfd = NULL; + static bool amroot; /* Real UID is root */ + static char loginsh[BUFSIZ]; /* Name of new login shell */ + /* command line options */ +@@ -442,7 +442,8 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/expiry.c.debug1 shadow-4.9/src/expiry.c +--- shadow-4.9/src/expiry.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/expiry.c 2022-01-10 10:45:52.205132958 +0100 +@@ -43,10 +43,10 @@ + #include "prototypes.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* Global variables */ + const char *Prog; +-FILE *shadow_logfd = NULL; + static bool cflg = false; + + /* local function prototypes */ +@@ -145,7 +145,8 @@ int main (int argc, char **argv) + struct spwd *spwd; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + sanitize_env (); + +diff -up shadow-4.9/src/faillog.c.debug1 shadow-4.9/src/faillog.c +--- shadow-4.9/src/faillog.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/faillog.c 2022-01-10 10:45:52.205132958 +0100 +@@ -46,6 +46,7 @@ + #include "prototypes.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* local function prototypes */ + static /*@noreturn@*/void usage (int status); +@@ -62,7 +63,6 @@ static void reset (void); + * Global variables + */ + const char *Prog; /* Program name */ +-FILE *shadow_logfd = NULL; + static FILE *fail; /* failure file stream */ + static time_t seconds; /* that number of days in seconds */ + static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ +@@ -574,7 +574,8 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/free_subid_range.c.debug1 shadow-4.9/src/free_subid_range.c +--- shadow-4.9/src/free_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/free_subid_range.c 2022-01-10 10:45:52.205132958 +0100 +@@ -3,11 +3,11 @@ + #include "subid.h" + #include "stdlib.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /* Test program for the subid freeing routine */ + + const char *Prog; +-FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -24,7 +24,8 @@ int main(int argc, char *argv[]) + bool group = false; // get subuids by default + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + while ((c = getopt(argc, argv, "g")) != EOF) { + switch(c) { + case 'g': group = true; break; +diff -up shadow-4.9/src/get_subid_owners.c.debug1 shadow-4.9/src/get_subid_owners.c +--- shadow-4.9/src/get_subid_owners.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/get_subid_owners.c 2022-01-10 10:45:52.205132958 +0100 +@@ -2,9 +2,9 @@ + #include "subid.h" + #include "stdlib.h" + #include "prototypes.h" ++#include "shadowlog.h" + + const char *Prog; +-FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -20,7 +20,8 @@ int main(int argc, char *argv[]) + uid_t *uids; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + if (argc < 2) { + usage(); + } +diff -up shadow-4.9/src/getsubids.c.debug1 shadow-4.9/src/getsubids.c +--- shadow-4.9/src/getsubids.c.debug1 2022-01-10 10:45:52.200132922 +0100 ++++ shadow-4.9/src/getsubids.c 2022-01-10 10:45:52.205132958 +0100 +@@ -3,9 +3,9 @@ + #include + #include "subid.h" + #include "prototypes.h" ++#include "shadowlog.h" + + const char *Prog; +-FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -22,7 +22,8 @@ int main(int argc, char *argv[]) + const char *owner; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + if (argc < 2) + usage(); + owner = argv[1]; +diff -up shadow-4.9/src/gpasswd.c.debug1 shadow-4.9/src/gpasswd.c +--- shadow-4.9/src/gpasswd.c.debug1 2022-01-10 10:45:52.184132808 +0100 ++++ shadow-4.9/src/gpasswd.c 2022-01-10 10:45:52.205132958 +0100 +@@ -53,12 +53,12 @@ + /*@-exitarg@*/ + #include "exitcodes.h" + ++#include "shadowlog.h" + /* + * Global variables + */ + /* The name of this command, as it is invoked */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + #ifdef SHADOWGRP + /* Indicate if shadow groups are enabled on the system +@@ -927,7 +927,8 @@ int main (int argc, char **argv) + */ + bywho = getuid (); + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + OPENLOG ("gpasswd"); + setbuf (stdout, NULL); +diff -up shadow-4.9/src/groupadd.c.debug1 shadow-4.9/src/groupadd.c +--- shadow-4.9/src/groupadd.c.debug1 2022-01-10 10:45:52.184132808 +0100 ++++ shadow-4.9/src/groupadd.c 2022-01-10 10:45:52.205132958 +0100 +@@ -56,6 +56,7 @@ + #ifdef SHADOWGRP + #include "sgroupio.h" + #endif ++#include "shadowlog.h" + + /* + * exit status values +@@ -72,7 +73,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static /*@null@*/char *group_name; + static gid_t group_id; +@@ -602,7 +602,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/groupdel.c.debug1 shadow-4.9/src/groupdel.c +--- shadow-4.9/src/groupdel.c.debug1 2022-01-10 10:45:52.185132815 +0100 ++++ shadow-4.9/src/groupdel.c 2022-01-10 10:45:52.205132958 +0100 +@@ -54,11 +54,11 @@ + #ifdef SHADOWGRP + #include "sgroupio.h" + #endif ++#include "shadowlog.h" + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static char *group_name; + static gid_t group_id = -1; +@@ -379,7 +379,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/groupmems.c.debug1 shadow-4.9/src/groupmems.c +--- shadow-4.9/src/groupmems.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/groupmems.c 2022-01-10 10:45:52.206132965 +0100 +@@ -47,6 +47,7 @@ + #ifdef SHADOWGRP + #include "sgroupio.h" + #endif ++#include "shadowlog.h" + + /* Exit Status Values */ + /*@-exitarg@*/ +@@ -65,7 +66,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static char *adduser = NULL; + static char *deluser = NULL; +@@ -596,7 +596,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/groupmod.c.debug1 shadow-4.9/src/groupmod.c +--- shadow-4.9/src/groupmod.c.debug1 2022-01-10 10:45:52.185132815 +0100 ++++ shadow-4.9/src/groupmod.c 2022-01-10 10:45:52.206132965 +0100 +@@ -56,6 +56,7 @@ + #ifdef SHADOWGRP + #include "sgroupio.h" + #endif ++#include "shadowlog.h" + /* + * exit status values + */ +@@ -76,7 +77,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + #ifdef SHADOWGRP + static bool is_shadow_grp; +@@ -840,7 +840,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/groups.c.debug1 shadow-4.9/src/groups.c +--- shadow-4.9/src/groups.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/groups.c 2022-01-10 10:45:52.206132965 +0100 +@@ -39,11 +39,11 @@ + #include + #include "defines.h" + #include "prototypes.h" ++#include "shadowlog.h" + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + /* local function prototypes */ + static void print_groups (const char *member); +@@ -127,7 +127,8 @@ int main (int argc, char **argv) + * Get the program name so that error messages can use it. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + if (argc == 1) { + +diff -up shadow-4.9/src/grpck.c.debug1 shadow-4.9/src/grpck.c +--- shadow-4.9/src/grpck.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/grpck.c 2022-01-10 10:45:52.206132965 +0100 +@@ -45,6 +45,7 @@ + #include "nscd.h" + #include "sssd.h" + #include "prototypes.h" ++#include "shadowlog.h" + + #ifdef SHADOWGRP + #include "sgroupio.h" +@@ -66,7 +67,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static const char *grp_file = GROUP_FILE; + static bool use_system_grp_file = true; +@@ -841,7 +841,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/grpconv.c.debug1 shadow-4.9/src/grpconv.c +--- shadow-4.9/src/grpconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/grpconv.c 2022-01-10 10:45:52.206132965 +0100 +@@ -55,11 +55,11 @@ + #ifdef SHADOWGRP + #include "groupio.h" + #include "sgroupio.h" ++#include "shadowlog.h" + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool gr_locked = false; + static bool sgr_locked = false; +@@ -147,7 +147,8 @@ int main (int argc, char **argv) + struct sgrp sgent; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/grpunconv.c.debug1 shadow-4.9/src/grpunconv.c +--- shadow-4.9/src/grpunconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/grpunconv.c 2022-01-10 10:45:52.206132965 +0100 +@@ -55,11 +55,11 @@ + #ifdef SHADOWGRP + #include "groupio.h" + #include "sgroupio.h" ++#include "shadowlog.h" + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool gr_locked = false; + static bool sgr_locked = false; +@@ -146,7 +146,8 @@ int main (int argc, char **argv) + const struct sgrp *sg; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/lastlog.c.debug1 shadow-4.9/src/lastlog.c +--- shadow-4.9/src/lastlog.c.debug1 2022-01-10 10:45:52.189132844 +0100 ++++ shadow-4.9/src/lastlog.c 2022-01-10 10:45:52.206132965 +0100 +@@ -50,6 +50,7 @@ + #include "getdef.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Needed for MkLinux DR1/2/2.1 - J. +@@ -62,7 +63,6 @@ + * Global variables + */ + const char *Prog; /* Program name */ +-FILE *shadow_logfd = NULL; + static FILE *lastlogfile; /* lastlog file stream */ + static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ + static bool has_umin = false; +@@ -322,7 +322,8 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/login.c.debug1 shadow-4.9/src/login.c +--- shadow-4.9/src/login.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/login.c 2022-01-10 10:45:52.206132965 +0100 +@@ -53,6 +53,7 @@ + #include "pwauth.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + #ifdef USE_PAM + #include "pam_defs.h" +@@ -83,7 +84,6 @@ static pam_handle_t *pamh = NULL; + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static const char *hostname = ""; + static /*@null@*/ /*@only@*/char *username = NULL; +@@ -578,7 +578,8 @@ int main (int argc, char **argv) + + amroot = (getuid () == 0); + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + if (geteuid() != 0) { + fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog); +diff -up shadow-4.9/src/logoutd.c.debug1 shadow-4.9/src/logoutd.c +--- shadow-4.9/src/logoutd.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/logoutd.c 2022-01-10 10:45:52.206132965 +0100 +@@ -40,11 +40,11 @@ + #include + #include "defines.h" + #include "prototypes.h" ++#include "shadowlog.h" + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + #ifndef DEFAULT_HUP_MESG + #define DEFAULT_HUP_MESG _("login time exceeded\n\n") +@@ -188,7 +188,8 @@ int main (int argc, char **argv) + * Start syslogging everything + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + OPENLOG ("logoutd"); + +diff -up shadow-4.9/src/newgidmap.c.debug1 shadow-4.9/src/newgidmap.c +--- shadow-4.9/src/newgidmap.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/newgidmap.c 2022-01-10 10:45:52.206132965 +0100 +@@ -41,12 +41,12 @@ + #include "subordinateio.h" + #include "getdef.h" + #include "idmapping.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + + static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups) +@@ -177,7 +177,8 @@ int main(int argc, char **argv) + bool allow_setgroups = false; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + /* + * The valid syntax are +diff -up shadow-4.9/src/newgrp.c.debug1 shadow-4.9/src/newgrp.c +--- shadow-4.9/src/newgrp.c.debug1 2022-01-10 10:45:52.199132915 +0100 ++++ shadow-4.9/src/newgrp.c 2022-01-10 10:45:52.206132965 +0100 +@@ -44,12 +44,12 @@ + #include "prototypes.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + extern char **newenvp; + extern char **environ; +@@ -446,7 +446,8 @@ int main (int argc, char **argv) + * don't need to re-exec anything. -- JWP + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + is_newgrp = (strcmp (Prog, "newgrp") == 0); + OPENLOG (is_newgrp ? "newgrp" : "sg"); + argc--; +diff -up shadow-4.9/src/new_subid_range.c.debug1 shadow-4.9/src/new_subid_range.c +--- shadow-4.9/src/new_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/new_subid_range.c 2022-01-10 10:45:52.206132965 +0100 +@@ -3,11 +3,11 @@ + #include "subid.h" + #include "stdlib.h" + #include "prototypes.h" ++#include "shadowlog.h" + + /* Test program for the subid creation routine */ + + const char *Prog; +-FILE *shadow_logfd = NULL; + + void usage(void) + { +@@ -27,7 +27,8 @@ int main(int argc, char *argv[]) + bool ok; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + while ((c = getopt(argc, argv, "gn")) != EOF) { + switch(c) { + case 'n': makenew = true; break; +diff -up shadow-4.9/src/newuidmap.c.debug1 shadow-4.9/src/newuidmap.c +--- shadow-4.9/src/newuidmap.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/newuidmap.c 2022-01-10 10:45:52.206132965 +0100 +@@ -41,12 +41,12 @@ + #include "subordinateio.h" + #include "getdef.h" + #include "idmapping.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool verify_range(struct passwd *pw, struct map_range *range) + { +@@ -107,7 +107,8 @@ int main(int argc, char **argv) + int written; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + /* + * The valid syntax are +diff -up shadow-4.9/src/newusers.c.debug1 shadow-4.9/src/newusers.c +--- shadow-4.9/src/newusers.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/newusers.c 2022-01-10 10:45:52.207132972 +0100 +@@ -70,12 +70,12 @@ + #include "subordinateio.h" + #endif /* ENABLE_SUBIDS */ + #include "chkname.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool rflg = false; /* create a system account */ + #ifndef USE_PAM +@@ -1071,7 +1071,8 @@ int main (int argc, char **argv) + #endif /* USE_PAM */ + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/passwd.c.debug1 shadow-4.9/src/passwd.c +--- shadow-4.9/src/passwd.c.debug1 2022-01-10 10:45:52.189132844 +0100 ++++ shadow-4.9/src/passwd.c 2022-01-10 10:45:52.207132972 +0100 +@@ -50,6 +50,7 @@ + #include "pwauth.h" + #include "pwio.h" + #include "shadowio.h" ++#include "shadowlog.h" + + /* + * exit status values +@@ -66,7 +67,6 @@ + * Global variables + */ + const char *Prog; /* Program name */ +-FILE *shadow_logfd = NULL; + + static char *name; /* The name of user whose password is being changed */ + static char *myname; /* The current user's name */ +@@ -761,7 +761,8 @@ int main (int argc, char **argv) + * most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/pwck.c.debug1 shadow-4.9/src/pwck.c +--- shadow-4.9/src/pwck.c.debug1 2022-01-10 10:45:52.198132908 +0100 ++++ shadow-4.9/src/pwck.c 2022-01-10 10:45:52.207132972 +0100 +@@ -52,6 +52,7 @@ + #ifdef WITH_TCB + #include "tcbfuncs.h" + #endif /* WITH_TCB */ ++#include "shadowlog.h" + + /* + * Exit codes +@@ -70,7 +71,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool use_system_pw_file = true; + static bool use_system_spw_file = true; +@@ -857,7 +857,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/pwconv.c.debug1 shadow-4.9/src/pwconv.c +--- shadow-4.9/src/pwconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/pwconv.c 2022-01-10 10:45:52.207132972 +0100 +@@ -73,6 +73,7 @@ + #include "shadowio.h" + #include "nscd.h" + #include "sssd.h" ++#include "shadowlog.h" + + /* + * exit status values +@@ -89,7 +90,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool spw_locked = false; + static bool pw_locked = false; +@@ -177,7 +177,8 @@ int main (int argc, char **argv) + struct spwd spent; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/pwunconv.c.debug1 shadow-4.9/src/pwunconv.c +--- shadow-4.9/src/pwunconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/pwunconv.c 2022-01-10 10:45:52.207132972 +0100 +@@ -48,12 +48,12 @@ + #include "shadowio.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static bool spw_locked = false; + static bool pw_locked = false; +@@ -138,7 +138,8 @@ int main (int argc, char **argv) + const struct spwd *spwd; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/su.c.debug1 shadow-4.9/src/su.c +--- shadow-4.9/src/su.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/su.c 2022-01-10 10:45:52.207132972 +0100 +@@ -77,12 +77,12 @@ + #endif /* USE_PAM */ + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */ + static bool caller_is_root = false; + static uid_t caller_uid; +@@ -717,7 +717,8 @@ static void save_caller_context (char ** + * most error messages. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + caller_uid = getuid (); + caller_is_root = (caller_uid == 0); +diff -up shadow-4.9/src/sulogin.c.debug1 shadow-4.9/src/sulogin.c +--- shadow-4.9/src/sulogin.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/sulogin.c 2022-01-10 10:45:52.207132972 +0100 +@@ -45,12 +45,12 @@ + #include "pwauth.h" + /*@-exitarg@*/ + #include "exitcodes.h" ++#include "shadowlog.h" + + /* + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static char name[BUFSIZ]; + static char pass[BUFSIZ]; +@@ -107,7 +107,8 @@ static RETSIGTYPE catch_signals (unused + #endif + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); +diff -up shadow-4.9/src/useradd.c.debug1 shadow-4.9/src/useradd.c +--- shadow-4.9/src/useradd.c.debug1 2022-01-10 10:45:52.197132901 +0100 ++++ shadow-4.9/src/useradd.c 2022-01-10 10:45:52.207132972 +0100 +@@ -78,6 +78,7 @@ + #ifdef WITH_TCB + #include "tcbfuncs.h" + #endif ++#include "shadowlog.h" + + #ifndef SKEL_DIR + #define SKEL_DIR "/etc/skel" +@@ -96,7 +97,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + /* + * These defaults are used if there is no defaults file. +@@ -2359,7 +2359,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/userdel.c.debug1 shadow-4.9/src/userdel.c +--- shadow-4.9/src/userdel.c.debug1 2022-01-10 10:45:52.186132823 +0100 ++++ shadow-4.9/src/userdel.c 2022-01-10 10:45:52.208132979 +0100 +@@ -72,6 +72,7 @@ + #ifdef ENABLE_SUBIDS + #include "subordinateio.h" + #endif /* ENABLE_SUBIDS */ ++#include "shadowlog.h" + + /* + * exit status values +@@ -91,7 +92,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static char *user_name; + static uid_t user_id; +@@ -944,7 +944,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); +diff -up shadow-4.9/src/usermod.c.debug1 shadow-4.9/src/usermod.c +--- shadow-4.9/src/usermod.c.debug1 2022-01-10 10:45:52.193132872 +0100 ++++ shadow-4.9/src/usermod.c 2022-01-10 10:45:52.208132979 +0100 +@@ -74,6 +74,7 @@ + #ifdef WITH_TCB + #include "tcbfuncs.h" + #endif ++#include "shadowlog.h" + + /* + * exit status values +@@ -105,7 +106,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static char *user_name; + static char *user_newname; +@@ -2172,7 +2172,8 @@ int main (int argc, char **argv) + * Get my name so that I can use it to report errors. + */ + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); +diff -up shadow-4.9/src/vipw.c.debug1 shadow-4.9/src/vipw.c +--- shadow-4.9/src/vipw.c.debug1 2021-07-22 23:55:35.000000000 +0200 ++++ shadow-4.9/src/vipw.c 2022-01-10 10:45:52.208132979 +0100 +@@ -53,6 +53,7 @@ + #include + #include "tcbfuncs.h" + #endif /* WITH_TCB */ ++#include "shadowlog.h" + + #define MSG_WARN_EDIT_OTHER_FILE _( \ + "You have modified %s.\n"\ +@@ -63,7 +64,6 @@ + * Global variables + */ + const char *Prog; +-FILE *shadow_logfd = NULL; + + static const char *filename, *fileeditname; + static bool filelocked = false; +@@ -482,7 +482,8 @@ int main (int argc, char **argv) + bool do_vipw; + + Prog = Basename (argv[0]); +- shadow_logfd = stderr; ++ log_set_progname(Prog); ++ log_set_logfd(stderr); + + (void) setlocale (LC_ALL, ""); + (void) bindtextdomain (PACKAGE, LOCALEDIR); diff --git a/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch b/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch new file mode 100644 index 0000000..4d8e792 --- /dev/null +++ b/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch @@ -0,0 +1,48 @@ +From e101219ad71de11da3fdd1b3ec2620fd1a97b92c Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 10 Jan 2022 15:30:28 +0100 +Subject: [PATCH] nss: get shadow_logfd with log_get_logfd() + +If /etc/nsswitch.conf doesn't exist podman crashes because shadow_logfd +is NULL. In order to avoid that load the log file descriptor with the +log_get_logfd() helper function. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2038811 + +Signed-off-by: Iker Pedrosa +--- + lib/nss.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 02742902..06fa48e5 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -9,6 +9,7 @@ + #include "prototypes.h" + #include "../libsubid/subid.h" + #include "shadowlog_internal.h" ++#include "shadowlog.h" + + #define NSSWITCH "/etc/nsswitch.conf" + +@@ -42,6 +43,7 @@ void nss_init(const char *nsswitch_path) { + FILE *nssfp = NULL; + char *line = NULL, *p, *token, *saveptr; + size_t len = 0; ++ FILE *shadow_logfd = log_get_logfd(); + + if (atomic_flag_test_and_set(&nss_init_started)) { + // Another thread has started nss_init, wait for it to complete +@@ -57,7 +59,7 @@ void nss_init(const char *nsswitch_path) { + // subid: files + nssfp = fopen(nsswitch_path, "r"); + if (!nssfp) { +- fprintf(shadow_logfd, "Failed opening %s: %m", nsswitch_path); ++ fprintf(shadow_logfd, "Failed opening %s: %m\n", nsswitch_path); + atomic_store(&nss_init_completed, true); + return; + } +-- +2.34.1 + diff --git a/shadow-4.9-rename-prog-to-shadow-progname.patch b/shadow-4.9-rename-prog-to-shadow-progname.patch new file mode 100644 index 0000000..d3a73a3 --- /dev/null +++ b/shadow-4.9-rename-prog-to-shadow-progname.patch @@ -0,0 +1,507 @@ +diff -up shadow-4.9/lib/commonio.c.debug2 shadow-4.9/lib/commonio.c +--- shadow-4.9/lib/commonio.c.debug2 2022-01-10 10:57:47.535238522 +0100 ++++ shadow-4.9/lib/commonio.c 2022-01-10 10:57:47.544238586 +0100 +@@ -147,7 +147,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: %s: %s\n", +- Prog, file, strerror (errno)); ++ shadow_progname, file, strerror (errno)); + } + return 0; + } +@@ -159,7 +159,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: %s file write error: %s\n", +- Prog, file, strerror (errno)); ++ shadow_progname, file, strerror (errno)); + } + (void) close (fd); + unlink (file); +@@ -169,7 +169,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: %s file sync error: %s\n", +- Prog, file, strerror (errno)); ++ shadow_progname, file, strerror (errno)); + } + (void) close (fd); + unlink (file); +@@ -182,7 +182,7 @@ static int do_lock_file (const char *fil + if ((0==retval) && log) { + (void) fprintf (shadow_logfd, + "%s: %s: lock file already used\n", +- Prog, file); ++ shadow_progname, file); + } + unlink (file); + return retval; +@@ -193,7 +193,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: %s: %s\n", +- Prog, lock, strerror (errno)); ++ shadow_progname, lock, strerror (errno)); + } + unlink (file); + errno = EINVAL; +@@ -205,7 +205,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: existing lock file %s without a PID\n", +- Prog, lock); ++ shadow_progname, lock); + } + unlink (file); + errno = EINVAL; +@@ -216,7 +216,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: existing lock file %s with an invalid PID '%s'\n", +- Prog, lock, buf); ++ shadow_progname, lock, buf); + } + unlink (file); + errno = EINVAL; +@@ -226,7 +226,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: lock %s already used by PID %lu\n", +- Prog, lock, (unsigned long) pid); ++ shadow_progname, lock, (unsigned long) pid); + } + unlink (file); + errno = EEXIST; +@@ -236,7 +236,7 @@ static int do_lock_file (const char *fil + if (log) { + (void) fprintf (shadow_logfd, + "%s: cannot get lock %s: %s\n", +- Prog, lock, strerror (errno)); ++ shadow_progname, lock, strerror (errno)); + } + unlink (file); + return 0; +@@ -248,13 +248,13 @@ static int do_lock_file (const char *fil + if ((0==retval) && log) { + (void) fprintf (shadow_logfd, + "%s: %s: lock file already used\n", +- Prog, file); ++ shadow_progname, file); + } + } else { + if (log) { + (void) fprintf (shadow_logfd, + "%s: cannot get lock %s: %s\n", +- Prog, lock, strerror (errno)); ++ shadow_progname, lock, strerror (errno)); + } + } + +@@ -449,7 +449,7 @@ int commonio_lock (struct commonio_db *d + if (geteuid () != 0) { + (void) fprintf (shadow_logfd, + "%s: Permission denied.\n", +- Prog); ++ shadow_progname); + } + return 0; /* failure */ + } +@@ -484,7 +484,7 @@ int commonio_lock (struct commonio_db *d + /* no unnecessary retries on "permission denied" errors */ + if (geteuid () != 0) { + (void) fprintf (shadow_logfd, "%s: Permission denied.\n", +- Prog); ++ shadow_progname); + return 0; + } + } +diff -up shadow-4.9/lib/nscd.c.debug2 shadow-4.9/lib/nscd.c +--- shadow-4.9/lib/nscd.c.debug2 2022-01-10 10:57:47.537238536 +0100 ++++ shadow-4.9/lib/nscd.c 2022-01-10 10:57:47.544238586 +0100 +@@ -26,7 +26,7 @@ int nscd_flush_cache (const char *servic + + if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) { + /* run_command writes its own more detailed message. */ +- (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); ++ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), shadow_progname); + return -1; + } + +@@ -34,7 +34,7 @@ int nscd_flush_cache (const char *servic + if (!WIFEXITED (status)) { + (void) fprintf (shadow_logfd, + _("%s: nscd did not terminate normally (signal %d)\n"), +- Prog, WTERMSIG (status)); ++ shadow_progname, WTERMSIG (status)); + return -1; + } else if (code == E_CMD_NOTFOUND) { + /* nscd is not installed, or it is installed but uses an +@@ -45,8 +45,8 @@ int nscd_flush_cache (const char *servic + return 0; + } else if (code != 0) { + (void) fprintf (shadow_logfd, _("%s: nscd exited with status %d\n"), +- Prog, code); +- (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); ++ shadow_progname, code); ++ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), shadow_progname); + return -1; + } + +diff -up shadow-4.9/lib/selinux.c.debug2 shadow-4.9/lib/selinux.c +--- shadow-4.9/lib/selinux.c.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/selinux.c 2022-01-10 10:57:47.544238586 +0100 +@@ -216,7 +216,7 @@ int check_selinux_permit (const char *pe + if (getprevcon_raw (&user_context_raw) != 0) { + fprintf (shadow_logfd, + _("%s: can not get previous SELinux process context: %s\n"), +- Prog, strerror (errno)); ++ shadow_progname, strerror (errno)); + SYSLOG ((LOG_WARN, + "can not get previous SELinux process context: %s", + strerror (errno))); +diff -up shadow-4.9/lib/shadowlog.c.debug2 shadow-4.9/lib/shadowlog.c +--- shadow-4.9/lib/shadowlog.c.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/shadowlog.c 2022-01-10 10:57:47.544238586 +0100 +@@ -2,14 +2,17 @@ + + #include "lib/shadowlog_internal.h" + ++const char *shadow_progname; ++FILE *shadow_logfd; ++ + void log_set_progname(const char *progname) + { +- Prog = progname; ++ shadow_progname = progname; + } + + const char *log_get_progname(void) + { +- return Prog; ++ return shadow_progname; + } + + void log_set_logfd(FILE *fd) +diff -up shadow-4.9/lib/shadowlog_internal.h.debug2 shadow-4.9/lib/shadowlog_internal.h +--- shadow-4.9/lib/shadowlog_internal.h.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/shadowlog_internal.h 2022-01-10 10:57:47.544238586 +0100 +@@ -1,2 +1,2 @@ +-const char *Prog; /* Program name showed in error messages */ +-FILE *shadow_logfd; /* file descripter to which error messages are printed */ ++extern const char *shadow_progname; /* Program name showed in error messages */ ++extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ +diff -up shadow-4.9/lib/spawn.c.debug2 shadow-4.9/lib/spawn.c +--- shadow-4.9/lib/spawn.c.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/spawn.c 2022-01-10 10:57:47.544238586 +0100 +@@ -60,11 +60,11 @@ int run_command (const char *cmd, const + exit (E_CMD_NOTFOUND); + } + fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", +- Prog, cmd, strerror (errno)); ++ shadow_progname, cmd, strerror (errno)); + exit (E_CMD_NOEXEC); + } else if ((pid_t)-1 == pid) { + fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", +- Prog, cmd, strerror (errno)); ++ shadow_progname, cmd, strerror (errno)); + return -1; + } + +@@ -77,7 +77,7 @@ int run_command (const char *cmd, const + + if ((pid_t)-1 == wpid) { + fprintf (shadow_logfd, "%s: waitpid (status: %d): %s\n", +- Prog, *status, strerror (errno)); ++ shadow_progname, *status, strerror (errno)); + return -1; + } + +diff -up shadow-4.9/lib/sssd.c.debug2 shadow-4.9/lib/sssd.c +--- shadow-4.9/lib/sssd.c.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/sssd.c 2022-01-10 10:57:47.544238586 +0100 +@@ -48,22 +48,22 @@ int sssd_flush_cache (int dbflags) + free(sss_cache_args); + if (rv != 0) { + /* run_command writes its own more detailed message. */ +- SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog)); ++ SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, shadow_progname)); + return -1; + } + + code = WEXITSTATUS (status); + if (!WIFEXITED (status)) { + SYSLOG ((LOG_WARN, "%s: sss_cache did not terminate normally (signal %d)", +- Prog, WTERMSIG (status))); ++ shadow_progname, WTERMSIG (status))); + return -1; + } else if (code == E_CMD_NOTFOUND) { + /* sss_cache is not installed, or it is installed but uses an + interpreter that is missing. Probably the former. */ + return 0; + } else if (code != 0) { +- SYSLOG ((LOG_WARN, "%s: sss_cache exited with status %d", Prog, code)); +- SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog)); ++ SYSLOG ((LOG_WARN, "%s: sss_cache exited with status %d", shadow_progname, code)); ++ SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, shadow_progname)); + return -1; + } + +diff -up shadow-4.9/lib/tcbfuncs.c.debug2 shadow-4.9/lib/tcbfuncs.c +--- shadow-4.9/lib/tcbfuncs.c.debug2 2022-01-10 10:57:47.538238543 +0100 ++++ shadow-4.9/lib/tcbfuncs.c 2022-01-10 10:59:01.228764507 +0100 +@@ -74,7 +74,7 @@ shadowtcb_status shadowtcb_gain_priv (vo + * to exit soon. + */ + #define OUT_OF_MEMORY do { \ +- fprintf (shadow_logfd, _("%s: out of memory\n"), Prog); \ ++ fprintf (shadow_logfd, _("%s: out of memory\n"), shadow_progname); \ + (void) fflush (shadow_logfd); \ + } while (false) + +@@ -120,7 +120,7 @@ static /*@null@*/ char *shadowtcb_path_r + if (lstat (path, &st) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), +- Prog, path, strerror (errno)); ++ shadow_progname, path, strerror (errno)); + free (path); + return NULL; + } +@@ -136,7 +136,7 @@ static /*@null@*/ char *shadowtcb_path_r + if (!S_ISLNK (st.st_mode)) { + fprintf (shadow_logfd, + _("%s: %s is neither a directory, nor a symlink.\n"), +- Prog, path); ++ shadow_progname, path); + free (path); + return NULL; + } +@@ -144,7 +144,7 @@ static /*@null@*/ char *shadowtcb_path_r + if (-1 == ret) { + fprintf (shadow_logfd, + _("%s: Cannot read symbolic link %s: %s\n"), +- Prog, path, strerror (errno)); ++ shadow_progname, path, strerror (errno)); + free (path); + return NULL; + } +@@ -153,7 +153,7 @@ static /*@null@*/ char *shadowtcb_path_r + link[sizeof(link) - 1] = '\0'; + fprintf (shadow_logfd, + _("%s: Suspiciously long symlink: %s\n"), +- Prog, link); ++ shadow_progname, link); + return NULL; + } + link[(size_t)ret] = '\0'; +@@ -211,7 +211,7 @@ static shadowtcb_status mkdir_leading (c + if (stat (TCB_DIR, &st) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), +- Prog, TCB_DIR, strerror (errno)); ++ shadow_progname, TCB_DIR, strerror (errno)); + goto out_free_path; + } + while ((ind = strchr (ptr, '/'))) { +@@ -223,19 +223,19 @@ static shadowtcb_status mkdir_leading (c + if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) { + fprintf (shadow_logfd, + _("%s: Cannot create directory %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free_dir; + } + if (chown (dir, 0, st.st_gid) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free_dir; + } + if (chmod (dir, 0711) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free_dir; + } + free (dir); +@@ -265,7 +265,7 @@ static shadowtcb_status unlink_suffs (co + if ((unlink (tmp) != 0) && (errno != ENOENT)) { + fprintf (shadow_logfd, + _("%s: unlink: %s: %s\n"), +- Prog, tmp, strerror (errno)); ++ shadow_progname, tmp, strerror (errno)); + free (tmp); + return SHADOWTCB_FAILURE; + } +@@ -290,7 +290,7 @@ static shadowtcb_status rmdir_leading (c + if (errno != ENOTEMPTY) { + fprintf (shadow_logfd, + _("%s: Cannot remove directory %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + ret = SHADOWTCB_FAILURE; + } + free (dir); +@@ -319,7 +319,7 @@ static shadowtcb_status move_dir (const + if (stat (olddir, &oldmode) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), +- Prog, olddir, strerror (errno)); ++ shadow_progname, olddir, strerror (errno)); + goto out_free; + } + old_uid = oldmode.st_uid; +@@ -346,7 +346,7 @@ static shadowtcb_status move_dir (const + if (rename (real_old_dir, real_new_dir) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot rename %s to %s: %s\n"), +- Prog, real_old_dir, real_new_dir, strerror (errno)); ++ shadow_progname, real_old_dir, real_new_dir, strerror (errno)); + goto out_free; + } + if (rmdir_leading (real_old_dir_rel) == SHADOWTCB_FAILURE) { +@@ -355,7 +355,7 @@ static shadowtcb_status move_dir (const + if ((unlink (olddir) != 0) && (errno != ENOENT)) { + fprintf (shadow_logfd, + _("%s: Cannot remove %s: %s\n"), +- Prog, olddir, strerror (errno)); ++ shadow_progname, olddir, strerror (errno)); + goto out_free; + } + if (asprintf (&newdir, TCB_DIR "/%s", user_newname) == -1) { +@@ -369,7 +369,7 @@ static shadowtcb_status move_dir (const + && (symlink (real_new_dir_rel, newdir) != 0)) { + fprintf (shadow_logfd, + _("%s: Cannot create symbolic link %s: %s\n"), +- Prog, real_new_dir_rel, strerror (errno)); ++ shadow_progname, real_new_dir_rel, strerror (errno)); + goto out_free; + } + ret = SHADOWTCB_SUCCESS; +@@ -468,31 +468,31 @@ shadowtcb_status shadowtcb_move (/*@NULL + if (stat (tcbdir, &dirmode) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), +- Prog, tcbdir, strerror (errno)); ++ shadow_progname, tcbdir, strerror (errno)); + goto out_free; + } + if (chown (tcbdir, 0, 0) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owners of %s: %s\n"), +- Prog, tcbdir, strerror (errno)); ++ shadow_progname, tcbdir, strerror (errno)); + goto out_free; + } + if (chmod (tcbdir, 0700) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), +- Prog, tcbdir, strerror (errno)); ++ shadow_progname, tcbdir, strerror (errno)); + goto out_free; + } + if (lstat (shadow, &filemode) != 0) { + if (errno != ENOENT) { + fprintf (shadow_logfd, + _("%s: Cannot lstat %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + fprintf (shadow_logfd, + _("%s: Warning, user %s has no tcb shadow file.\n"), +- Prog, user_newname); ++ shadow_progname, user_newname); + } else { + if (!S_ISREG (filemode.st_mode) || + filemode.st_nlink != 1) { +@@ -500,19 +500,19 @@ shadowtcb_status shadowtcb_move (/*@NULL + _("%s: Emergency: %s's tcb shadow is not a " + "regular file with st_nlink=1.\n" + "The account is left locked.\n"), +- Prog, user_newname); ++ shadow_progname, user_newname); + goto out_free; + } + if (chown (shadow, user_newid, filemode.st_gid) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + if (chmod (shadow, filemode.st_mode & 07777) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + } +@@ -522,7 +522,7 @@ shadowtcb_status shadowtcb_move (/*@NULL + if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), +- Prog, tcbdir, strerror (errno)); ++ shadow_progname, tcbdir, strerror (errno)); + goto out_free; + } + ret = SHADOWTCB_SUCCESS; +@@ -547,7 +547,7 @@ shadowtcb_status shadowtcb_create (const + if (stat (TCB_DIR, &tcbdir_stat) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot stat %s: %s\n"), +- Prog, TCB_DIR, strerror (errno)); ++ shadow_progname, TCB_DIR, strerror (errno)); + return SHADOWTCB_FAILURE; + } + shadowgid = tcbdir_stat.st_gid; +@@ -567,39 +567,39 @@ shadowtcb_status shadowtcb_create (const + if (mkdir (dir, 0700) != 0) { + fprintf (shadow_logfd, + _("%s: mkdir: %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free; + } + fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + fprintf (shadow_logfd, + _("%s: Cannot open %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + close (fd); + if (chown (shadow, 0, authgid) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), +- Prog, shadow, strerror (errno)); ++ shadow_progname, shadow, strerror (errno)); + goto out_free; + } + if (chown (dir, 0, authgid) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change owner of %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free; + } + if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) { + fprintf (shadow_logfd, + _("%s: Cannot change mode of %s: %s\n"), +- Prog, dir, strerror (errno)); ++ shadow_progname, dir, strerror (errno)); + goto out_free; + } + if ( (shadowtcb_set_user (name) == SHADOWTCB_FAILURE) diff --git a/shadow-4.9-shadow-progname-default-init.patch b/shadow-4.9-shadow-progname-default-init.patch new file mode 100644 index 0000000..0c6d616 --- /dev/null +++ b/shadow-4.9-shadow-progname-default-init.patch @@ -0,0 +1,39 @@ +diff -up shadow-4.9/lib/shadowlog.c.debug3 shadow-4.9/lib/shadowlog.c +--- shadow-4.9/lib/shadowlog.c.debug3 2022-01-10 11:16:31.636261531 +0100 ++++ shadow-4.9/lib/shadowlog.c 2022-01-10 11:16:31.637261538 +0100 +@@ -2,8 +2,8 @@ + + #include "lib/shadowlog_internal.h" + +-const char *shadow_progname; +-FILE *shadow_logfd; ++const char *shadow_progname = "libshadow"; ++FILE *shadow_logfd = NULL; + + void log_set_progname(const char *progname) + { +diff -up shadow-4.9/libsubid/api.c.debug3 shadow-4.9/libsubid/api.c +--- shadow-4.9/libsubid/api.c.debug3 2022-01-10 11:16:31.637261538 +0100 ++++ shadow-4.9/libsubid/api.c 2022-01-10 11:17:15.431574120 +0100 +@@ -40,17 +40,16 @@ + #include "subid.h" + #include "shadowlog.h" + +-const char *Prog = "(libsubid)"; +- + bool libsubid_init(const char *progname, FILE * logfd) + { + FILE *shadow_logfd; + if (progname) { + progname = strdup(progname); +- if (progname) +- Prog = progname; +- else ++ if (!progname) + return false; ++ log_set_progname(progname); ++ } else { ++ log_set_progname("(libsubid)"); + } + + if (logfd) { diff --git a/shadow-utils.spec b/shadow-utils.spec index e7e2970..24ea670 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.9 -Release: 8%{?dist} +Release: 9%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -67,6 +67,15 @@ Patch22: shadow-4.9-newgrp-fix-segmentation-fault.patch Patch23: shadow-4.9-getsubids.patch # https://github.com/shadow-maint/shadow/commit/a757b458ffb4fb9a40bcbb4f7869449431c67f83 Patch24: shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch +# https://github.com/shadow-maint/shadow/commit/79157cbad87f42cdc2068d72e798488572c68bb2 +Patch25: shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch +# https://github.com/shadow-maint/shadow/commit/0e6fe5e728a45baff3977d73e81a27adb6ae30c6 +Patch26: shadow-4.9-rename-prog-to-shadow-progname.patch +# https://github.com/shadow-maint/shadow/commit/2b0bdef6f9a18382e92b0fb6d893c4339123ffac +# https://github.com/shadow-maint/shadow/commit/9750fd681919ed558a9b044248a284d567cddf1a +Patch27: shadow-4.9-shadow-progname-default-init.patch +# https://github.com/shadow-maint/shadow/commit/e101219ad71de11da3fdd1b3ec2620fd1a97b92c +Patch28: shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -151,6 +160,10 @@ Development files for shadow-utils-subid. %patch22 -p1 -b .newgrp-fix-segmentation-fault %patch23 -p1 -b .getsubids %patch24 -p1 -b .groupdel-fix-sigsegv-when-passwd-does-not-exist +%patch25 -p1 -b .make-shadow-logfd-and-prog-not-extern +%patch26 -p1 -b .rename-prog-to-shadow-progname +%patch27 -p1 -b .shadow-progname-default-init +%patch28 -p1 -b .nss-get-shadow-logfd-with-log-get-logfd iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -323,6 +336,13 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Mon Jan 17 2022 Iker Pedrosa - 2:4.9-9 +- nss: get shadow_logfd with log_get_logfd() (#2038811) +- lib: make shadow_logfd and Prog not extern +- lib: rename Prog to shadow_progname +- lib: provide default values for shadow_progname +- libsubid: use log_set_progname in subid_init + * Fri Nov 19 2021 Iker Pedrosa - 2:4.9-8 - getsubids: provide system binary and man page (#1980780) - pwck: fix segfault when calling fprintf() (#2021339) From bfa562aaf2cde4102fe65661cb55b41098b8c886 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 22 Jan 2022 00:46:50 +0000 Subject: [PATCH 040/118] - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 24ea670..bcbadf8 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.9 -Release: 9%{?dist} +Release: 10%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -336,6 +336,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Sat Jan 22 2022 Fedora Release Engineering - 2:4.9-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + * Mon Jan 17 2022 Iker Pedrosa - 2:4.9-9 - nss: get shadow_logfd with log_get_logfd() (#2038811) - lib: make shadow_logfd and Prog not extern From 2b851f7e96b3cafb7ec7b69cc24e37c0a601ef11 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 26 Jan 2022 09:29:37 +0100 Subject: [PATCH 041/118] - Rebase to version 4.11.1 (#2034038) - Fix release sources - Add explicit subid requirement for subid-devel Signed-off-by: Iker Pedrosa --- ....patch => shadow-4.11.1-audit-update.patch | 456 +-- shadow-4.11.1-null-tm.patch | 22 + ...redhat.patch => shadow-4.11.1-redhat.patch | 16 +- shadow-4.9-getsubids.patch | 245 -- ...x-sigsegv-when-passwd-does-not-exist.patch | 13 - ...default-value-in-SHA_get_salt_rounds.patch | 60 - ...ake-shadow-logfd-and-prog-not-extern.patch | 2497 ----------------- shadow-4.9-move-create-home.patch | 88 - ...ow-4.9-newgrp-fix-segmentation-fault.patch | 35 - ...ow-4.9-newuidmap-libeconf-dependency.patch | 15 - shadow-4.9-null-tm.patch | 70 - ...ck-fix-segfault-when-calling-fprintf.patch | 30 - ...w-4.9-rename-prog-to-shadow-progname.patch | 507 ---- shadow-4.9-revert-useradd-fix-memleak.patch | 30 - ....9-semanage-close-the-selabel-handle.patch | 61 - shadow-4.9-shadow-progname-default-init.patch | 39 - ...d-avoid-generating-empty-subid-range.patch | 79 - shadow-4.9-useradd-copy-tree-argument.patch | 13 - ...ow-4.9-usermod-allow-all-group-types.patch | 322 --- shadow-utils.spec | 75 +- 20 files changed, 276 insertions(+), 4397 deletions(-) rename shadow-4.9-audit-update.patch => shadow-4.11.1-audit-update.patch (84%) create mode 100644 shadow-4.11.1-null-tm.patch rename shadow-4.9-redhat.patch => shadow-4.11.1-redhat.patch (70%) delete mode 100644 shadow-4.9-getsubids.patch delete mode 100644 shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch delete mode 100644 shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch delete mode 100644 shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch delete mode 100644 shadow-4.9-move-create-home.patch delete mode 100644 shadow-4.9-newgrp-fix-segmentation-fault.patch delete mode 100644 shadow-4.9-newuidmap-libeconf-dependency.patch delete mode 100644 shadow-4.9-null-tm.patch delete mode 100644 shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch delete mode 100644 shadow-4.9-rename-prog-to-shadow-progname.patch delete mode 100644 shadow-4.9-revert-useradd-fix-memleak.patch delete mode 100644 shadow-4.9-semanage-close-the-selabel-handle.patch delete mode 100644 shadow-4.9-shadow-progname-default-init.patch delete mode 100644 shadow-4.9-useradd-avoid-generating-empty-subid-range.patch delete mode 100644 shadow-4.9-useradd-copy-tree-argument.patch delete mode 100644 shadow-4.9-usermod-allow-all-group-types.patch diff --git a/shadow-4.9-audit-update.patch b/shadow-4.11.1-audit-update.patch similarity index 84% rename from shadow-4.9-audit-update.patch rename to shadow-4.11.1-audit-update.patch index 99513ef..65acae0 100644 --- a/shadow-4.9-audit-update.patch +++ b/shadow-4.11.1-audit-update.patch @@ -1,16 +1,16 @@ -diff -up shadow-4.8.1/libmisc/audit_help.c.audit-update shadow-4.8.1/libmisc/audit_help.c ---- shadow-4.8.1/libmisc/audit_help.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/audit_help.c 2020-03-17 16:53:44.371943299 +0100 -@@ -68,7 +68,7 @@ void audit_help_open (void) +diff -up shadow-4.11.1/libmisc/audit_help.c.audit-update shadow-4.11.1/libmisc/audit_help.c +--- shadow-4.11.1/libmisc/audit_help.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/libmisc/audit_help.c 2022-01-03 15:15:38.946046192 +0100 +@@ -46,7 +46,7 @@ void audit_help_open (void) * This function will log a message to the audit system using a predefined * message format. Parameter usage is as follows: * -- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account -+ * type - type of message: AUDIT_USER_MGMT for changing any account +- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account ++ * type - type of message: AUDIT_USER_MGMT for changing any account * attributes. * pgname - program's name * op - operation. "adding user", "changing finger info", "deleting group" -@@ -88,6 +88,39 @@ void audit_logger (int type, unused cons +@@ -66,6 +66,39 @@ void audit_logger (int type, unused cons } } @@ -50,71 +50,71 @@ diff -up shadow-4.8.1/libmisc/audit_help.c.audit-update shadow-4.8.1/libmisc/aud void audit_logger_message (const char *message, shadow_audit_result result) { if (audit_fd < 0) { -diff -up shadow-4.8.1/libmisc/cleanup_group.c.audit-update shadow-4.8.1/libmisc/cleanup_group.c ---- shadow-4.8.1/libmisc/cleanup_group.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/cleanup_group.c 2020-03-17 16:53:44.371943299 +0100 -@@ -83,7 +83,7 @@ void cleanup_report_mod_group (void *cle +diff -up shadow-4.11.1/libmisc/cleanup_group.c.audit-update shadow-4.11.1/libmisc/cleanup_group.c +--- shadow-4.11.1/libmisc/cleanup_group.c.audit-update 2022-01-03 14:57:01.777006776 +0100 ++++ shadow-4.11.1/libmisc/cleanup_group.c 2022-01-03 15:22:27.438770608 +0100 +@@ -61,7 +61,7 @@ void cleanup_report_mod_group (void *cle gr_dbname (), info->action)); #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, +- audit_logger (AUDIT_USER_ACCT, log_get_progname(), ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -101,7 +101,7 @@ void cleanup_report_mod_gshadow (void *c +@@ -79,7 +79,7 @@ void cleanup_report_mod_gshadow (void *c sgr_dbname (), info->action)); #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, +- audit_logger (AUDIT_USER_ACCT, log_get_progname(), ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -122,7 +122,7 @@ void cleanup_report_add_group_group (voi +@@ -100,7 +100,7 @@ void cleanup_report_add_group_group (voi SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, + audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "adding group to /etc/group", + "adding-group", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -141,8 +141,8 @@ void cleanup_report_add_group_gshadow (v +@@ -119,8 +119,8 @@ void cleanup_report_add_group_gshadow (v SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, +- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + "adding-shadow-group", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -164,8 +164,8 @@ void cleanup_report_del_group_group (voi +@@ -142,8 +142,8 @@ void cleanup_report_del_group_group (voi "failed to remove group %s from %s", name, gr_dbname ())); #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, +- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "removing group from /etc/group", -+ audit_logger (AUDIT_DEL_GROUP, Prog, ++ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), + "removing-group", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -187,8 +187,8 @@ void cleanup_report_del_group_gshadow (v +@@ -165,8 +165,8 @@ void cleanup_report_del_group_gshadow (v "failed to remove group %s from %s", name, sgr_dbname ())); #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, +- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, ++ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), + "removing-shadow-group", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -208,7 +208,7 @@ void cleanup_unlock_group (unused void * - Prog, gr_dbname ()); +@@ -186,7 +186,7 @@ void cleanup_unlock_group (unused void * + log_get_progname(), gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); #ifdef WITH_AUDIT - audit_logger_message ("unlocking group file", @@ -122,8 +122,8 @@ diff -up shadow-4.8.1/libmisc/cleanup_group.c.audit-update shadow-4.8.1/libmisc/ SHADOW_AUDIT_FAILURE); #endif } -@@ -228,7 +228,7 @@ void cleanup_unlock_gshadow (unused void - Prog, sgr_dbname ()); +@@ -206,7 +206,7 @@ void cleanup_unlock_gshadow (unused void + log_get_progname(), sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); #ifdef WITH_AUDIT - audit_logger_message ("unlocking gshadow file", @@ -131,40 +131,40 @@ diff -up shadow-4.8.1/libmisc/cleanup_group.c.audit-update shadow-4.8.1/libmisc/ SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.8.1/libmisc/cleanup_user.c.audit-update shadow-4.8.1/libmisc/cleanup_user.c ---- shadow-4.8.1/libmisc/cleanup_user.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/libmisc/cleanup_user.c 2020-03-17 16:53:44.371943299 +0100 -@@ -65,7 +65,7 @@ void cleanup_report_mod_passwd (void *cl +diff -up shadow-4.11.1/libmisc/cleanup_user.c.audit-update shadow-4.11.1/libmisc/cleanup_user.c +--- shadow-4.11.1/libmisc/cleanup_user.c.audit-update 2022-01-03 14:57:01.777006776 +0100 ++++ shadow-4.11.1/libmisc/cleanup_user.c 2022-01-03 15:21:22.593338130 +0100 +@@ -43,7 +43,7 @@ void cleanup_report_mod_passwd (void *cl pw_dbname (), info->action)); #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_USER_MGMT, Prog, +- audit_logger (AUDIT_USER_ACCT, log_get_progname(), ++ audit_logger (AUDIT_USER_MGMT, log_get_progname(), info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -86,7 +86,7 @@ void cleanup_report_add_user_passwd (voi +@@ -64,7 +64,7 @@ void cleanup_report_add_user_passwd (voi SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, + audit_logger (AUDIT_ADD_USER, log_get_progname(), - "adding user to /etc/passwd", + "adding-user", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -105,8 +105,8 @@ void cleanup_report_add_user_shadow (voi +@@ -83,8 +83,8 @@ void cleanup_report_add_user_shadow (voi SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, +- audit_logger (AUDIT_ADD_USER, log_get_progname(), - "adding user to /etc/shadow", -+ audit_logger (AUDIT_USER_MGMT, Prog, ++ audit_logger (AUDIT_USER_MGMT, log_get_progname(), + "adding-shadow-user", name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -125,7 +125,7 @@ void cleanup_unlock_passwd (unused void - Prog, pw_dbname ()); +@@ -103,7 +103,7 @@ void cleanup_unlock_passwd (unused void + log_get_progname(), pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT - audit_logger_message ("unlocking passwd file", @@ -172,8 +172,8 @@ diff -up shadow-4.8.1/libmisc/cleanup_user.c.audit-update shadow-4.8.1/libmisc/c SHADOW_AUDIT_FAILURE); #endif } -@@ -144,7 +144,7 @@ void cleanup_unlock_shadow (unused void - Prog, spw_dbname ()); +@@ -122,7 +122,7 @@ void cleanup_unlock_shadow (unused void + log_get_progname(), spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT - audit_logger_message ("unlocking shadow file", @@ -181,10 +181,10 @@ diff -up shadow-4.8.1/libmisc/cleanup_user.c.audit-update shadow-4.8.1/libmisc/c SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.8.1/lib/prototypes.h.audit-update shadow-4.8.1/lib/prototypes.h ---- shadow-4.8.1/lib/prototypes.h.audit-update 2020-03-17 16:53:44.364943206 +0100 -+++ shadow-4.8.1/lib/prototypes.h 2020-03-17 16:53:44.371943299 +0100 -@@ -219,12 +219,21 @@ extern int audit_fd; +diff -up shadow-4.11.1/lib/prototypes.h.audit-update shadow-4.11.1/lib/prototypes.h +--- shadow-4.11.1/lib/prototypes.h.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/lib/prototypes.h 2022-01-03 14:57:01.777006776 +0100 +@@ -197,12 +197,21 @@ extern int audit_fd; extern void audit_help_open (void); /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ #define AUDIT_NO_ID ((unsigned int) -1) @@ -206,10 +206,10 @@ diff -up shadow-4.8.1/lib/prototypes.h.audit-update shadow-4.8.1/lib/prototypes. void audit_logger_message (const char *message, shadow_audit_result result); #endif -diff -up shadow-4.8.1/src/chage.c.audit-update shadow-4.8.1/src/chage.c ---- shadow-4.8.1/src/chage.c.audit-update 2019-11-12 01:18:25.000000000 +0100 -+++ shadow-4.8.1/src/chage.c 2020-03-17 16:53:44.371943299 +0100 -@@ -123,9 +123,10 @@ static /*@noreturn@*/void fail_exit (int +diff -up shadow-4.11.1/src/chage.c.audit-update shadow-4.11.1/src/chage.c +--- shadow-4.11.1/src/chage.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/chage.c 2022-01-03 14:57:01.777006776 +0100 +@@ -100,9 +100,10 @@ static /*@noreturn@*/void fail_exit (int #ifdef WITH_AUDIT if (E_SUCCESS != code) { @@ -223,7 +223,7 @@ diff -up shadow-4.8.1/src/chage.c.audit-update shadow-4.8.1/src/chage.c } #endif -@@ -883,11 +884,7 @@ int main (int argc, char **argv) +@@ -837,11 +838,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } @@ -236,7 +236,7 @@ diff -up shadow-4.8.1/src/chage.c.audit-update shadow-4.8.1/src/chage.c list_fields (); fail_exit (E_SUCCESS); } -@@ -906,41 +903,43 @@ int main (int argc, char **argv) +@@ -860,41 +857,43 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT else { @@ -296,10 +296,10 @@ diff -up shadow-4.8.1/src/chage.c.audit-update shadow-4.8.1/src/chage.c user_name, (unsigned int) user_uid, 1); } #endif -diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c ---- shadow-4.8.1/src/gpasswd.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/gpasswd.c 2020-03-17 16:53:44.371943299 +0100 -@@ -138,7 +138,7 @@ static void usage (int status) +diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c +--- shadow-4.11.1/src/gpasswd.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/gpasswd.c 2022-01-03 14:57:01.778006782 +0100 +@@ -116,7 +116,7 @@ static void usage (int status) (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); @@ -308,7 +308,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); #ifdef SHADOWGRP -@@ -397,21 +397,14 @@ static void open_files (void) +@@ -375,21 +375,14 @@ static void open_files (void) static void log_gpasswd_failure (const char *suffix) { @@ -333,7 +333,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (dflg) { -@@ -419,13 +412,9 @@ static void log_gpasswd_failure (const c +@@ -397,13 +390,9 @@ static void log_gpasswd_failure (const c "%s failed to remove user %s from group %s%s", myname, user, group, suffix)); #ifdef WITH_AUDIT @@ -350,7 +350,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (rflg) { -@@ -433,13 +422,9 @@ static void log_gpasswd_failure (const c +@@ -411,13 +400,9 @@ static void log_gpasswd_failure (const c "%s failed to remove password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -367,7 +367,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Rflg) { -@@ -447,13 +432,9 @@ static void log_gpasswd_failure (const c +@@ -425,13 +410,9 @@ static void log_gpasswd_failure (const c "%s failed to restrict access to group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -384,7 +384,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Aflg || Mflg) { -@@ -463,13 +444,9 @@ static void log_gpasswd_failure (const c +@@ -441,13 +422,9 @@ static void log_gpasswd_failure (const c "%s failed to set the administrators of group %s to %s%s", myname, group, admins, suffix)); #ifdef WITH_AUDIT @@ -401,7 +401,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -479,13 +456,9 @@ static void log_gpasswd_failure (const c +@@ -457,13 +434,9 @@ static void log_gpasswd_failure (const c "%s failed to set the members of group %s to %s%s", myname, group, members, suffix)); #ifdef WITH_AUDIT @@ -418,7 +418,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -494,13 +467,9 @@ static void log_gpasswd_failure (const c +@@ -472,13 +445,9 @@ static void log_gpasswd_failure (const c "%s failed to change password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -435,7 +435,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -531,21 +500,14 @@ static void log_gpasswd_failure_gshadow +@@ -509,21 +478,14 @@ static void log_gpasswd_failure_gshadow static void log_gpasswd_success (const char *suffix) { @@ -460,7 +460,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (dflg) { -@@ -553,13 +515,9 @@ static void log_gpasswd_success (const c +@@ -531,13 +493,9 @@ static void log_gpasswd_success (const c "user %s removed by %s from group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT @@ -477,7 +477,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (rflg) { -@@ -567,13 +525,9 @@ static void log_gpasswd_success (const c +@@ -545,13 +503,9 @@ static void log_gpasswd_success (const c "password of group %s removed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -494,7 +494,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Rflg) { -@@ -581,13 +535,9 @@ static void log_gpasswd_success (const c +@@ -559,13 +513,9 @@ static void log_gpasswd_success (const c "access to group %s restricted by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -511,7 +511,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Aflg || Mflg) { -@@ -597,13 +547,9 @@ static void log_gpasswd_success (const c +@@ -575,13 +525,9 @@ static void log_gpasswd_success (const c "administrators of group %s set by %s to %s%s", group, myname, admins, suffix)); #ifdef WITH_AUDIT @@ -528,7 +528,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -613,13 +559,9 @@ static void log_gpasswd_success (const c +@@ -591,13 +537,9 @@ static void log_gpasswd_success (const c "members of group %s set by %s to %s%s", group, myname, members, suffix)); #ifdef WITH_AUDIT @@ -545,7 +545,7 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -628,13 +570,9 @@ static void log_gpasswd_success (const c +@@ -606,13 +548,9 @@ static void log_gpasswd_success (const c "password of group %s changed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -562,10 +562,10 @@ diff -up shadow-4.8.1/src/gpasswd.c.audit-update shadow-4.8.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c ---- shadow-4.8.1/src/groupadd.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/groupadd.c 2020-03-17 16:53:44.372943312 +0100 -@@ -131,6 +131,15 @@ static /*@noreturn@*/void usage (int sta +diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c +--- shadow-4.11.1/src/groupadd.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/groupadd.c 2022-01-03 14:57:01.778006782 +0100 +@@ -111,6 +111,15 @@ static /*@noreturn@*/void usage (int sta exit (status); } @@ -581,7 +581,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c /* * new_grent - initialize the values in a group file entry * -@@ -214,7 +223,7 @@ static void grp_update (void) +@@ -207,7 +216,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), grp.gr_name); @@ -590,7 +590,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } #ifdef SHADOWGRP /* -@@ -224,7 +233,7 @@ static void grp_update (void) +@@ -217,7 +226,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), sgrp.sg_name); @@ -599,7 +599,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } #endif /* SHADOWGRP */ } -@@ -248,7 +257,7 @@ static void check_new_name (void) +@@ -241,7 +250,7 @@ static void check_new_name (void) fprintf (stderr, _("%s: '%s' is not a valid group name\n"), Prog, group_name); @@ -608,7 +608,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } /* -@@ -264,11 +273,11 @@ static void close_files (void) +@@ -257,11 +266,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); @@ -622,7 +622,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c group_name, (unsigned int) group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -286,11 +295,11 @@ static void close_files (void) +@@ -279,11 +288,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); @@ -637,7 +637,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c group_name, (unsigned int) group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -304,12 +313,6 @@ static void close_files (void) +@@ -297,12 +306,6 @@ static void close_files (void) #endif /* SHADOWGRP */ /* Report success at the system level */ @@ -650,7 +650,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", group_name, (unsigned int) group_id)); del_cleanup (cleanup_report_add_group); -@@ -327,7 +330,7 @@ static void open_files (void) +@@ -320,7 +323,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -659,7 +659,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } add_cleanup (cleanup_unlock_group, NULL); -@@ -337,7 +340,7 @@ static void open_files (void) +@@ -330,7 +333,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -668,7 +668,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } add_cleanup (cleanup_unlock_gshadow, NULL); } -@@ -353,7 +356,7 @@ static void open_files (void) +@@ -346,7 +349,7 @@ static void open_files (void) if (gr_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); @@ -677,7 +677,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } #ifdef SHADOWGRP -@@ -363,7 +366,7 @@ static void open_files (void) +@@ -356,7 +359,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); @@ -686,7 +686,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } } #endif /* SHADOWGRP */ -@@ -496,7 +499,7 @@ static void check_flags (void) +@@ -493,7 +496,7 @@ static void check_flags (void) fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_name); @@ -695,7 +695,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } if (gflg && (prefix_getgrgid (group_id) != NULL)) { -@@ -515,7 +518,7 @@ static void check_flags (void) +@@ -512,7 +515,7 @@ static void check_flags (void) fprintf (stderr, _("%s: GID '%lu' already exists\n"), Prog, (unsigned long int) group_id); @@ -704,7 +704,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } } } -@@ -543,7 +546,7 @@ static void check_perms (void) +@@ -540,7 +543,7 @@ static void check_perms (void) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -713,7 +713,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); -@@ -563,7 +566,7 @@ static void check_perms (void) +@@ -560,7 +563,7 @@ static void check_perms (void) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -722,7 +722,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -596,7 +599,7 @@ int main (int argc, char **argv) +@@ -595,7 +598,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -731,7 +731,7 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } /* -@@ -618,7 +621,7 @@ int main (int argc, char **argv) +@@ -617,7 +620,7 @@ int main (int argc, char **argv) if (!gflg) { if (find_new_gid (rflg, &group_id, NULL) < 0) { @@ -740,10 +740,10 @@ diff -up shadow-4.8.1/src/groupadd.c.audit-update shadow-4.8.1/src/groupadd.c } } -diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c ---- shadow-4.8.1/src/groupdel.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/groupdel.c 2020-03-17 16:53:44.372943312 +0100 -@@ -106,6 +106,15 @@ static /*@noreturn@*/void usage (int sta +diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c +--- shadow-4.11.1/src/groupdel.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/groupdel.c 2022-01-03 14:57:01.778006782 +0100 +@@ -84,6 +84,15 @@ static /*@noreturn@*/void usage (int sta exit (status); } @@ -759,7 +759,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c /* * grp_update - update group file entries * -@@ -132,7 +141,7 @@ static void grp_update (void) +@@ -110,7 +119,7 @@ static void grp_update (void) fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, group_name, gr_dbname ()); @@ -768,7 +768,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } #ifdef SHADOWGRP -@@ -144,7 +153,7 @@ static void grp_update (void) +@@ -122,7 +131,7 @@ static void grp_update (void) fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, group_name, sgr_dbname ()); @@ -777,7 +777,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } } #endif /* SHADOWGRP */ -@@ -163,12 +172,12 @@ static void close_files (void) +@@ -141,12 +150,12 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); @@ -792,7 +792,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c group_name, (unsigned int) group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -188,12 +197,12 @@ static void close_files (void) +@@ -166,12 +175,12 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); @@ -808,7 +808,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c group_name, (unsigned int) group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -207,13 +216,6 @@ static void close_files (void) +@@ -185,13 +194,6 @@ static void close_files (void) } #endif /* SHADOWGRP */ @@ -822,7 +822,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); del_cleanup (cleanup_report_del_group); } -@@ -230,7 +232,7 @@ static void open_files (void) +@@ -208,7 +210,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -831,7 +831,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } add_cleanup (cleanup_unlock_group, NULL); #ifdef SHADOWGRP -@@ -239,7 +241,7 @@ static void open_files (void) +@@ -217,7 +219,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -840,7 +840,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } add_cleanup (cleanup_unlock_gshadow, NULL); } -@@ -257,7 +259,7 @@ static void open_files (void) +@@ -235,7 +237,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); @@ -849,7 +849,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } #ifdef SHADOWGRP if (is_shadow_grp) { -@@ -266,7 +268,7 @@ static void open_files (void) +@@ -244,7 +246,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); @@ -858,7 +858,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } } #endif /* SHADOWGRP */ -@@ -307,7 +309,7 @@ static void group_busy (gid_t gid) +@@ -285,7 +287,7 @@ static void group_busy (gid_t gid) fprintf (stderr, _("%s: cannot remove the primary group of user '%s'\n"), Prog, pwd->pw_name); @@ -867,7 +867,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } /* -@@ -392,7 +394,7 @@ int main (int argc, char **argv) +@@ -373,7 +375,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -876,7 +876,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } process_flags (argc, argv); -@@ -406,7 +408,7 @@ int main (int argc, char **argv) +@@ -387,7 +389,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -885,7 +885,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); -@@ -427,7 +429,7 @@ int main (int argc, char **argv) +@@ -408,7 +410,7 @@ int main (int argc, char **argv) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -894,7 +894,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -447,7 +449,7 @@ int main (int argc, char **argv) +@@ -428,7 +430,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group '%s' does not exist\n"), Prog, group_name); @@ -903,7 +903,7 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } group_id = grp->gr_gid; -@@ -471,7 +473,7 @@ int main (int argc, char **argv) +@@ -452,7 +454,7 @@ int main (int argc, char **argv) _("%s: %s is the NIS master\n"), Prog, nis_master); } @@ -912,10 +912,10 @@ diff -up shadow-4.8.1/src/groupdel.c.audit-update shadow-4.8.1/src/groupdel.c } #endif -diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c ---- shadow-4.8.1/src/groupmod.c.audit-update 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/src/groupmod.c 2020-03-17 16:53:44.372943312 +0100 -@@ -450,7 +450,7 @@ static void close_files (void) +diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c +--- shadow-4.11.1/src/groupmod.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/groupmod.c 2022-01-03 14:57:01.778006782 +0100 +@@ -468,7 +468,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -924,7 +924,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c info_group.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -473,7 +473,14 @@ static void close_files (void) +@@ -491,7 +491,14 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -940,7 +940,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c info_gshadow.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -496,7 +503,7 @@ static void close_files (void) +@@ -514,7 +521,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -949,7 +949,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c info_passwd.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -511,8 +518,8 @@ static void close_files (void) +@@ -529,8 +536,8 @@ static void close_files (void) } #ifdef WITH_AUDIT @@ -960,7 +960,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -524,6 +531,8 @@ static void close_files (void) +@@ -542,6 +549,8 @@ static void close_files (void) */ static void prepare_failure_reports (void) { @@ -969,7 +969,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c info_group.name = group_name; #ifdef SHADOWGRP info_gshadow.name = group_name; -@@ -536,76 +545,109 @@ static void prepare_failure_reports (voi +@@ -554,76 +563,109 @@ static void prepare_failure_reports (voi #endif info_passwd.audit_msg = xmalloc (512); @@ -1106,7 +1106,7 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c "%lu", (unsigned long int) group_newid); } info_group.audit_msg[511] = '\0'; -@@ -613,6 +655,11 @@ static void prepare_failure_reports (voi +@@ -631,6 +673,11 @@ static void prepare_failure_reports (voi info_gshadow.audit_msg[511] = '\0'; #endif info_passwd.audit_msg[511] = '\0'; @@ -1118,10 +1118,10 @@ diff -up shadow-4.8.1/src/groupmod.c.audit-update shadow-4.8.1/src/groupmod.c // FIXME: add a system cleanup add_cleanup (cleanup_report_mod_group, &info_group); -diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c ---- shadow-4.8.1/src/newgrp.c.audit-update 2020-01-12 15:19:28.000000000 +0100 -+++ shadow-4.8.1/src/newgrp.c 2020-03-17 16:53:44.372943312 +0100 -@@ -206,11 +206,12 @@ static void check_perms (const struct gr +diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c +--- shadow-4.11.1/src/newgrp.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/newgrp.c 2022-01-03 15:25:39.407050922 +0100 +@@ -185,11 +185,12 @@ static void check_perms (const struct gr strcmp (cpasswd, grp->gr_passwd) != 0) { #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1136,7 +1136,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif SYSLOG ((LOG_INFO, "Invalid password for group '%s' from '%s'", -@@ -221,11 +222,12 @@ static void check_perms (const struct gr +@@ -200,11 +201,12 @@ static void check_perms (const struct gr } #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1151,7 +1151,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif } -@@ -236,19 +238,6 @@ failure: +@@ -215,19 +217,6 @@ failure: * harm. -- JWP */ closelog (); @@ -1171,7 +1171,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c exit (EXIT_FAILURE); } -@@ -320,15 +309,27 @@ static void syslog_sg (const char *name, +@@ -299,15 +288,27 @@ static void syslog_sg (const char *name, is_newgrp ? "newgrp" : "sg", strerror (errno)); #ifdef WITH_AUDIT if (group) { @@ -1203,7 +1203,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c } #endif exit (EXIT_FAILURE); -@@ -458,7 +459,7 @@ int main (int argc, char **argv) +@@ -438,7 +439,7 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT audit_logger (AUDIT_CHGRP_ID, Prog, "changing", NULL, @@ -1212,7 +1212,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); -@@ -574,15 +575,26 @@ int main (int argc, char **argv) +@@ -554,15 +555,26 @@ int main (int argc, char **argv) perror ("getgroups"); #ifdef WITH_AUDIT if (group) { @@ -1243,7 +1243,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c } #endif exit (EXIT_FAILURE); -@@ -739,10 +751,10 @@ int main (int argc, char **argv) +@@ -719,10 +731,10 @@ int main (int argc, char **argv) perror ("setgid"); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1256,7 +1256,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif exit (EXIT_FAILURE); } -@@ -751,10 +763,10 @@ int main (int argc, char **argv) +@@ -731,10 +743,10 @@ int main (int argc, char **argv) perror ("setuid"); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1269,7 +1269,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif exit (EXIT_FAILURE); } -@@ -768,10 +780,10 @@ int main (int argc, char **argv) +@@ -748,10 +760,10 @@ int main (int argc, char **argv) execl (SHELL, "sh", "-c", command, (char *) 0); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1282,7 +1282,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif perror (SHELL); exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -835,11 +847,11 @@ int main (int argc, char **argv) +@@ -815,11 +827,11 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT @@ -1296,7 +1296,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c #endif /* * Exec the login shell and go away. We are trying to get back to -@@ -863,15 +875,24 @@ int main (int argc, char **argv) +@@ -843,15 +855,24 @@ int main (int argc, char **argv) closelog (); #ifdef WITH_AUDIT if (NULL != group) { @@ -1313,7 +1313,7 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c + snprintf (audit_buf, sizeof(audit_buf), + "changing new_group=\"%s\"", group); + } - audit_logger (AUDIT_CHGRP_ID, Prog, + audit_logger (AUDIT_CHGRP_ID, Prog, audit_buf, NULL, - (unsigned int) getuid (), 0); + (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); @@ -1325,10 +1325,10 @@ diff -up shadow-4.8.1/src/newgrp.c.audit-update shadow-4.8.1/src/newgrp.c } #endif exit (EXIT_FAILURE); -diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c ---- shadow-4.8.1/src/useradd.c.audit-update 2020-03-17 16:53:44.365943219 +0100 -+++ shadow-4.8.1/src/useradd.c 2020-03-17 17:03:11.614503929 +0100 -@@ -233,6 +233,8 @@ static void create_mail (void); +diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c +--- shadow-4.11.1/src/useradd.c.audit-update 2022-01-03 14:57:01.772006744 +0100 ++++ shadow-4.11.1/src/useradd.c 2022-01-03 14:57:01.787006838 +0100 +@@ -222,6 +222,8 @@ static void check_uid_range(int rflg, ui */ static void fail_exit (int code) { @@ -1337,7 +1337,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c if (home_added) { if (rmdir (prefix_user_home) != 0) { fprintf (stderr, -@@ -246,12 +248,6 @@ static void fail_exit (int code) +@@ -235,12 +237,6 @@ static void fail_exit (int code) if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); @@ -1350,7 +1350,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c /* continue */ } } -@@ -259,12 +255,6 @@ static void fail_exit (int code) +@@ -248,12 +244,6 @@ static void fail_exit (int code) if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); @@ -1363,7 +1363,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c /* continue */ } } -@@ -272,12 +262,6 @@ static void fail_exit (int code) +@@ -261,12 +251,6 @@ static void fail_exit (int code) if (gr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); @@ -1376,7 +1376,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c /* continue */ } } -@@ -286,12 +270,6 @@ static void fail_exit (int code) +@@ -275,12 +259,6 @@ static void fail_exit (int code) if (sgr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); @@ -1389,7 +1389,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c /* continue */ } } -@@ -301,12 +279,6 @@ static void fail_exit (int code) +@@ -290,12 +268,6 @@ static void fail_exit (int code) if (sub_uid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); @@ -1402,7 +1402,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c /* continue */ } } -@@ -314,20 +286,19 @@ static void fail_exit (int code) +@@ -303,20 +275,19 @@ static void fail_exit (int code) if (sub_gid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); @@ -1430,7 +1430,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -692,7 +663,7 @@ static int set_defaults (void) +@@ -719,7 +690,7 @@ static int set_defaults (void) } #ifdef WITH_AUDIT audit_logger (AUDIT_USYS_CONFIG, Prog, @@ -1439,7 +1439,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c NULL, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -974,12 +945,6 @@ static void grp_update (void) +@@ -1050,12 +1021,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1452,7 +1452,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -993,18 +958,12 @@ static void grp_update (void) +@@ -1069,18 +1034,12 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1474,7 +1474,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1049,12 +1008,6 @@ static void grp_update (void) +@@ -1125,12 +1084,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1487,7 +1487,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1068,18 +1021,13 @@ static void grp_update (void) +@@ -1144,18 +1097,13 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1510,7 +1510,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1452,7 +1400,7 @@ static void process_flags (int argc, cha +@@ -1528,7 +1476,7 @@ static void process_flags (int argc, cha Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1519,7 +1519,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1567,7 +1515,7 @@ static void close_files (void) +@@ -1637,7 +1585,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1528,7 +1528,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1580,7 +1528,7 @@ static void close_files (void) +@@ -1650,7 +1598,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1537,7 +1537,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1622,7 +1570,7 @@ static void close_files (void) +@@ -1667,7 +1615,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1546,7 +1546,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1636,7 +1584,7 @@ static void close_files (void) +@@ -1681,7 +1629,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1555,7 +1555,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1828,7 +1776,7 @@ static void grp_add (void) +@@ -1942,7 +1890,7 @@ static void grp_add (void) Prog, gr_dbname (), grp.gr_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1564,7 +1564,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1844,7 +1792,7 @@ static void grp_add (void) +@@ -1958,7 +1906,7 @@ static void grp_add (void) Prog, sgr_dbname (), sgrp.sg_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1573,7 +1573,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1854,7 +1802,7 @@ static void grp_add (void) +@@ -1968,7 +1916,7 @@ static void grp_add (void) SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1582,7 +1582,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2025,12 +1973,6 @@ static void usr_update (void) +@@ -2161,12 +2109,6 @@ static void usr_update (unsigned long su fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spent.sp_namp); @@ -1595,7 +1595,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_PW_UPDATE); } #ifdef ENABLE_SUBIDS -@@ -2051,9 +1993,14 @@ static void usr_update (void) +@@ -2187,9 +2129,14 @@ static void usr_update (unsigned long su #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -1612,7 +1612,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif /* -@@ -2140,12 +2087,6 @@ static void create_home (void) +@@ -2279,12 +2226,6 @@ static void create_home (void) fprintf (stderr, _("%s: cannot create directory %s\n"), Prog, path); @@ -1625,7 +1625,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_HOMEDIR); } if (chown (path, 0, 0) < 0) { -@@ -2168,8 +2109,8 @@ static void create_home (void) +@@ -2311,8 +2252,8 @@ static void create_home (void) } home_added = true; #ifdef WITH_AUDIT @@ -1636,7 +1636,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -2354,12 +2295,6 @@ int main (int argc, char **argv) +@@ -2552,12 +2493,6 @@ int main (int argc, char **argv) */ if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); @@ -1649,7 +1649,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_NAME_IN_USE); } -@@ -2375,12 +2310,6 @@ int main (int argc, char **argv) +@@ -2573,12 +2508,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), Prog, user_name); @@ -1662,7 +1662,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_NAME_IN_USE); } } -@@ -2410,12 +2339,6 @@ int main (int argc, char **argv) +@@ -2608,12 +2537,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: UID %lu is not unique\n"), Prog, (unsigned long) user_id); @@ -1675,7 +1675,7 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c fail_exit (E_UID_IN_USE); } } -@@ -2489,9 +2412,10 @@ int main (int argc, char **argv) +@@ -2688,9 +2611,10 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -1689,10 +1689,10 @@ diff -up shadow-4.8.1/src/useradd.c.audit-update shadow-4.8.1/src/useradd.c #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); } -diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c ---- shadow-4.8.1/src/userdel.c.audit-update 2020-03-17 16:53:44.368943259 +0100 -+++ shadow-4.8.1/src/userdel.c 2020-03-17 16:53:44.373943325 +0100 -@@ -222,9 +222,9 @@ static void update_groups (void) +diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c +--- shadow-4.11.1/src/userdel.c.audit-update 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/userdel.c 2022-01-03 14:57:01.787006838 +0100 +@@ -202,9 +202,9 @@ static void update_groups (void) * Update the DBM group file with the new entry as well. */ #ifdef WITH_AUDIT @@ -1705,7 +1705,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", -@@ -284,9 +284,9 @@ static void update_groups (void) +@@ -264,9 +264,9 @@ static void update_groups (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -1718,7 +1718,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", -@@ -363,9 +363,9 @@ static void remove_usergroup (void) +@@ -343,9 +343,9 @@ static void remove_usergroup (void) } #ifdef WITH_AUDIT @@ -1731,7 +1731,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, -@@ -381,9 +381,9 @@ static void remove_usergroup (void) +@@ -361,9 +361,9 @@ static void remove_usergroup (void) fail_exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -1744,7 +1744,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, -@@ -545,7 +545,7 @@ static void fail_exit (int code) +@@ -525,7 +525,7 @@ static void fail_exit (int code) #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1753,7 +1753,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -565,24 +565,12 @@ static void open_files (void) +@@ -545,24 +545,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); @@ -1778,7 +1778,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_PW_UPDATE); } if (is_shadow_pwd) { -@@ -590,12 +578,6 @@ static void open_files (void) +@@ -570,12 +558,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); @@ -1791,7 +1791,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_PW_UPDATE); } spw_locked = true; -@@ -603,12 +585,6 @@ static void open_files (void) +@@ -583,12 +565,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); @@ -1804,7 +1804,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_PW_UPDATE); } } -@@ -616,23 +592,11 @@ static void open_files (void) +@@ -596,23 +572,11 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -1828,7 +1828,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_GRP_UPDATE); } #ifdef SHADOWGRP -@@ -641,24 +605,12 @@ static void open_files (void) +@@ -621,24 +585,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -1853,7 +1853,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_GRP_UPDATE); } } -@@ -669,24 +621,12 @@ static void open_files (void) +@@ -649,24 +601,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_uid_dbname ()); @@ -1878,7 +1878,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_SUB_UID_UPDATE); } } -@@ -695,24 +635,12 @@ static void open_files (void) +@@ -675,24 +615,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_gid_dbname ()); @@ -1903,7 +1903,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c fail_exit (E_SUB_GID_UPDATE); } } -@@ -757,7 +685,7 @@ static void update_user (void) +@@ -737,7 +665,7 @@ static void update_user (void) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1912,7 +1912,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ -@@ -865,7 +793,7 @@ static int remove_mailbox (void) +@@ -845,7 +773,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1921,7 +1921,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -882,7 +810,7 @@ static int remove_mailbox (void) +@@ -862,7 +790,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1930,7 +1930,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -892,8 +820,8 @@ static int remove_mailbox (void) +@@ -872,8 +800,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1941,7 +1941,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); } -@@ -911,7 +839,7 @@ static int remove_mailbox (void) +@@ -891,7 +819,7 @@ static int remove_mailbox (void) mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1950,7 +1950,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -928,7 +856,7 @@ static int remove_mailbox (void) +@@ -908,7 +836,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1959,7 +1959,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -938,8 +866,8 @@ static int remove_mailbox (void) +@@ -918,8 +846,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1970,7 +1970,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); } -@@ -1152,7 +1080,7 @@ int main (int argc, char **argv) +@@ -1138,7 +1066,7 @@ int main (int argc, char **argv) Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1979,7 +1979,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1208,7 +1136,7 @@ int main (int argc, char **argv) +@@ -1194,7 +1122,7 @@ int main (int argc, char **argv) if (!fflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1988,7 +1988,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1302,8 +1230,8 @@ int main (int argc, char **argv) +@@ -1288,8 +1216,8 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT else { @@ -1999,7 +1999,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); } -@@ -1312,7 +1240,7 @@ int main (int argc, char **argv) +@@ -1298,7 +1226,7 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT if (0 != errors) { audit_logger (AUDIT_DEL_USER, Prog, @@ -2008,7 +2008,7 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); } -@@ -1325,8 +1253,8 @@ int main (int argc, char **argv) +@@ -1311,8 +1239,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2019,10 +2019,10 @@ diff -up shadow-4.8.1/src/userdel.c.audit-update shadow-4.8.1/src/userdel.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c ---- shadow-4.8.1/src/usermod.c.audit-update 2020-03-17 16:53:44.370943285 +0100 -+++ shadow-4.8.1/src/usermod.c 2020-03-17 16:53:44.373943325 +0100 -@@ -457,8 +457,8 @@ static char *new_pw_passwd (char *pw_pas +diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c +--- shadow-4.11.1/src/usermod.c.audit-update 2022-01-03 14:57:01.776006769 +0100 ++++ shadow-4.11.1/src/usermod.c 2022-01-03 15:28:16.959101706 +0100 +@@ -417,8 +417,8 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -2033,7 +2033,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); strcpy (buf, "!"); -@@ -477,8 +477,8 @@ static char *new_pw_passwd (char *pw_pas +@@ -437,8 +437,8 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -2044,7 +2044,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); s = pw_pass; -@@ -489,7 +489,7 @@ static char *new_pw_passwd (char *pw_pas +@@ -449,7 +449,7 @@ static char *new_pw_passwd (char *pw_pas } else if (pflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -2053,7 +2053,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); -@@ -518,8 +518,8 @@ static void new_pwent (struct passwd *pw +@@ -478,8 +478,8 @@ static void new_pwent (struct passwd *pw fail_exit (E_NAME_IN_USE); } #ifdef WITH_AUDIT @@ -2064,7 +2064,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -539,8 +539,8 @@ static void new_pwent (struct passwd *pw +@@ -499,8 +499,8 @@ static void new_pwent (struct passwd *pw if (uflg) { #ifdef WITH_AUDIT @@ -2075,7 +2075,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -550,8 +550,8 @@ static void new_pwent (struct passwd *pw +@@ -510,8 +510,8 @@ static void new_pwent (struct passwd *pw } if (gflg) { #ifdef WITH_AUDIT @@ -2086,7 +2086,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -561,8 +561,8 @@ static void new_pwent (struct passwd *pw +@@ -521,8 +521,8 @@ static void new_pwent (struct passwd *pw } if (cflg) { #ifdef WITH_AUDIT @@ -2097,7 +2097,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif pwent->pw_gecos = user_newcomment; -@@ -570,8 +570,8 @@ static void new_pwent (struct passwd *pw +@@ -530,8 +530,8 @@ static void new_pwent (struct passwd *pw if (dflg) { #ifdef WITH_AUDIT @@ -2108,7 +2108,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -581,8 +581,8 @@ static void new_pwent (struct passwd *pw +@@ -547,8 +547,8 @@ static void new_pwent (struct passwd *pw } if (sflg) { #ifdef WITH_AUDIT @@ -2119,7 +2119,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -612,8 +612,8 @@ static void new_spent (struct spwd *spen +@@ -578,8 +578,8 @@ static void new_spent (struct spwd *spen if (fflg) { #ifdef WITH_AUDIT @@ -2130,9 +2130,9 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -629,8 +629,8 @@ static void new_spent (struct spwd *spen - date_to_str (old_exp, sizeof(old_exp), - user_expire * DAY); +@@ -593,8 +593,8 @@ static void new_spent (struct spwd *spen + date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); + date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "changing expiration date", @@ -2141,7 +2141,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -713,9 +713,9 @@ static /*@noreturn@*/void fail_exit (int +@@ -677,9 +677,9 @@ static /*@noreturn@*/void fail_exit (int #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -2154,7 +2154,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif exit (code); } -@@ -769,9 +769,12 @@ static void update_group (void) +@@ -741,9 +741,12 @@ static void update_group (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -2170,7 +2170,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in group '%s'", -@@ -785,9 +788,11 @@ static void update_group (void) +@@ -757,9 +760,11 @@ static void update_group (void) ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -2185,7 +2185,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from group '%s'", -@@ -800,9 +805,11 @@ static void update_group (void) +@@ -772,9 +777,11 @@ static void update_group (void) ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -2200,7 +2200,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to group '%s'", user_newname, ngrp->gr_name)); -@@ -877,9 +884,10 @@ static void update_gshadow (void) +@@ -859,9 +866,10 @@ static void update_gshadow (void) nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); changed = true; #ifdef WITH_AUDIT @@ -2214,7 +2214,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "change admin '%s' to '%s' in shadow group '%s'", -@@ -899,9 +907,10 @@ static void update_gshadow (void) +@@ -881,9 +889,10 @@ static void update_gshadow (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -2228,7 +2228,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in shadow group '%s'", -@@ -915,9 +924,10 @@ static void update_gshadow (void) +@@ -897,9 +906,10 @@ static void update_gshadow (void) nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -2242,7 +2242,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'", -@@ -930,9 +940,10 @@ static void update_gshadow (void) +@@ -912,9 +922,10 @@ static void update_gshadow (void) nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -2256,7 +2256,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", user_newname, nsgrp->sg_name)); -@@ -1799,8 +1810,8 @@ static void move_home (void) +@@ -1817,8 +1828,8 @@ static void move_home (void) #ifdef WITH_AUDIT if (uflg || gflg) { @@ -2267,7 +2267,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); } #endif -@@ -1818,8 +1829,8 @@ static void move_home (void) +@@ -1836,8 +1847,8 @@ static void move_home (void) fail_exit (E_HOMEDIR); } #ifdef WITH_AUDIT @@ -2278,7 +2278,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); #endif -@@ -1847,9 +1858,9 @@ static void move_home (void) +@@ -1865,9 +1876,9 @@ static void move_home (void) Prog, prefix_user_home); } #ifdef WITH_AUDIT @@ -2290,7 +2290,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); -@@ -2071,8 +2082,8 @@ static void move_mailbox (void) +@@ -2085,8 +2096,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2301,7 +2301,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); } #endif -@@ -2098,8 +2109,8 @@ static void move_mailbox (void) +@@ -2112,8 +2123,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2312,7 +2312,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_newname, (unsigned int) user_newid, 1); } #endif -@@ -2294,8 +2305,8 @@ int main (int argc, char **argv) +@@ -2310,8 +2321,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -2323,7 +2323,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2307,8 +2318,8 @@ int main (int argc, char **argv) +@@ -2323,8 +2334,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2334,7 +2334,7 @@ diff -up shadow-4.8.1/src/usermod.c.audit-update shadow-4.8.1/src/usermod.c user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2349,8 +2360,8 @@ int main (int argc, char **argv) +@@ -2365,8 +2376,8 @@ int main (int argc, char **argv) */ #ifdef WITH_AUDIT if (uflg || gflg) { diff --git a/shadow-4.11.1-null-tm.patch b/shadow-4.11.1-null-tm.patch new file mode 100644 index 0000000..b8d5fc8 --- /dev/null +++ b/shadow-4.11.1-null-tm.patch @@ -0,0 +1,22 @@ +diff -up shadow-4.11.1/src/chage.c.null-tm shadow-4.11.1/src/chage.c +diff -up shadow-4.11.1/src/lastlog.c.null-tm shadow-4.11.1/src/lastlog.c +--- shadow-4.11.1/src/lastlog.c.null-tm 2022-01-03 15:31:56.348555620 +0100 ++++ shadow-4.11.1/src/lastlog.c 2022-01-03 15:38:41.262229024 +0100 +@@ -151,9 +151,12 @@ static void print_one (/*@null@*/const s + + ll_time = ll.ll_time; + tm = localtime (&ll_time); +- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); +- cp = ptime; +- ++ if (tm == NULL) { ++ cp = "(unknown)"; ++ } else { ++ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); ++ cp = ptime; ++ } + if (ll.ll_time == (time_t) 0) { + cp = _("**Never logged in**\0"); + } +diff -up shadow-4.11.1/src/passwd.c.null-tm shadow-4.11.1/src/passwd.c +diff -up shadow-4.11.1/src/usermod.c.null-tm shadow-4.11.1/src/usermod.c diff --git a/shadow-4.9-redhat.patch b/shadow-4.11.1-redhat.patch similarity index 70% rename from shadow-4.9-redhat.patch rename to shadow-4.11.1-redhat.patch index 9dfb3e8..e5e6c60 100644 --- a/shadow-4.9-redhat.patch +++ b/shadow-4.11.1-redhat.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.9/src/useradd.c.redhat shadow-4.9/src/useradd.c ---- shadow-4.9/src/useradd.c.redhat 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/useradd.c 2021-08-02 11:45:11.942867250 +0200 -@@ -104,7 +104,7 @@ FILE *shadow_logfd = NULL; +diff -up shadow-4.11.1/src/useradd.c.redhat shadow-4.11.1/src/useradd.c +--- shadow-4.11.1/src/useradd.c.redhat 2022-01-03 01:46:53.000000000 +0100 ++++ shadow-4.11.1/src/useradd.c 2022-01-03 14:53:12.988484829 +0100 +@@ -82,7 +82,7 @@ const char *Prog; static gid_t def_group = 1000; static const char *def_gname = "other"; static const char *def_home = "/home"; @@ -9,8 +9,8 @@ diff -up shadow-4.9/src/useradd.c.redhat shadow-4.9/src/useradd.c +static const char *def_shell = "/sbin/nologin"; static const char *def_template = SKEL_DIR; static const char *def_create_mail_spool = "yes"; - -@@ -114,7 +114,7 @@ static const char *def_expire = ""; + static const char *def_log_init = "yes"; +@@ -93,7 +93,7 @@ static const char *def_expire = ""; #define VALID(s) (strcspn (s, ":\n") == strlen (s)) static const char *user_name = ""; @@ -19,7 +19,7 @@ diff -up shadow-4.9/src/useradd.c.redhat shadow-4.9/src/useradd.c static uid_t user_id; static gid_t user_gid; static const char *user_comment = ""; -@@ -1204,9 +1204,9 @@ static void process_flags (int argc, cha +@@ -1219,9 +1219,9 @@ static void process_flags (int argc, cha }; while ((c = getopt_long (argc, argv, #ifdef WITH_SELINUX @@ -31,7 +31,7 @@ diff -up shadow-4.9/src/useradd.c.redhat shadow-4.9/src/useradd.c #endif /* !WITH_SELINUX */ long_options, NULL)) != -1) { switch (c) { -@@ -1363,6 +1363,7 @@ static void process_flags (int argc, cha +@@ -1378,6 +1378,7 @@ static void process_flags (int argc, cha case 'M': Mflg = true; break; diff --git a/shadow-4.9-getsubids.patch b/shadow-4.9-getsubids.patch deleted file mode 100644 index b9f2449..0000000 --- a/shadow-4.9-getsubids.patch +++ /dev/null @@ -1,245 +0,0 @@ -diff -up shadow-4.9/man/getsubids.1.xml.getsubids shadow-4.9/man/getsubids.1.xml ---- shadow-4.9/man/getsubids.1.xml.getsubids 2021-11-18 16:27:33.951053120 +0100 -+++ shadow-4.9/man/getsubids.1.xml 2021-11-18 16:27:33.951053120 +0100 -@@ -0,0 +1,141 @@ -+ -+ -+ -+]> -+ -+ -+ -+ -+ Iker -+ Pedrosa -+ Creation, 2021 -+ -+ -+ -+ getsubids -+ 1 -+ User Commands -+ shadow-utils -+ &SHADOW_UTILS_VERSION; -+ -+ -+ getsubids -+ get the subordinate id ranges for a user -+ -+ -+ -+ -+ getsubids -+ -+ options -+ -+ -+ USER -+ -+ -+ -+ -+ -+ DESCRIPTION -+ -+ The getsubids command lists the subordinate user ID -+ ranges for a given user. The subordinate group IDs can be listed using -+ the option. -+ -+ -+ -+ -+ OPTIONS -+ -+ The options which apply to the getsubids command are: -+ -+ -+ -+ -+ -+ -+ -+ -+ List the subordinate group ID ranges. -+ -+ -+ -+ -+ -+ -+ -+ EXAMPLE -+ -+ For example, to obtain the subordinate UIDs of the testuser: -+ -+ -+ -+$ getsubids testuser -+0: testuser 100000 65536 -+ -+ -+ -+ This command output provides (in order from left to right) the list -+ index, username, UID range start, and number of UIDs in range. -+ -+ -+ -+ -+ SEE ALSO -+ -+ -+ login.defs5 -+ , -+ -+ newgidmap1 -+ , -+ -+ newuidmap1 -+ , -+ -+ subgid5 -+ , -+ -+ subuid5 -+ , -+ -+ useradd8 -+ , -+ -+ userdel8 -+ . -+ -+ usermod8 -+ , -+ -+ -+ -diff -up shadow-4.9/man/Makefile.am.getsubids shadow-4.9/man/Makefile.am ---- shadow-4.9/man/Makefile.am.getsubids 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/man/Makefile.am 2021-11-18 16:27:33.951053120 +0100 -@@ -62,6 +62,7 @@ man_MANS += $(man_nopam) - endif - - man_subids = \ -+ man1/getsubids.1 \ - man1/newgidmap.1 \ - man1/newuidmap.1 \ - man5/subgid.5 \ -@@ -80,6 +81,7 @@ man_XMANS = \ - expiry.1.xml \ - faillog.5.xml \ - faillog.8.xml \ -+ getsubids.1.xml \ - gpasswd.1.xml \ - groupadd.8.xml \ - groupdel.8.xml \ -diff -up shadow-4.9/src/getsubids.c.getsubids shadow-4.9/src/getsubids.c ---- shadow-4.9/src/getsubids.c.getsubids 2021-11-18 16:27:33.951053120 +0100 -+++ shadow-4.9/src/getsubids.c 2021-11-18 16:27:33.951053120 +0100 -@@ -0,0 +1,46 @@ -+#include -+#include -+#include -+#include "subid.h" -+#include "prototypes.h" -+ -+const char *Prog; -+FILE *shadow_logfd = NULL; -+ -+void usage(void) -+{ -+ fprintf(stderr, "Usage: %s [-g] user\n", Prog); -+ fprintf(stderr, " list subuid ranges for user\n"); -+ fprintf(stderr, " pass -g to list subgid ranges\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ int i, count=0; -+ struct subid_range *ranges; -+ const char *owner; -+ -+ Prog = Basename (argv[0]); -+ shadow_logfd = stderr; -+ if (argc < 2) -+ usage(); -+ owner = argv[1]; -+ if (argc == 3 && strcmp(argv[1], "-g") == 0) { -+ owner = argv[2]; -+ count = get_subgid_ranges(owner, &ranges); -+ } else if (argc == 2 && strcmp(argv[1], "-h") == 0) { -+ usage(); -+ } else { -+ count = get_subuid_ranges(owner, &ranges); -+ } -+ if (!ranges) { -+ fprintf(stderr, "Error fetching ranges\n"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) { -+ printf("%d: %s %lu %lu\n", i, owner, -+ ranges[i].start, ranges[i].count); -+ } -+ return 0; -+} -diff -up shadow-4.9/src/list_subid_ranges.c.getsubids shadow-4.9/src/list_subid_ranges.c -diff -up shadow-4.9/src/Makefile.am.getsubids shadow-4.9/src/Makefile.am ---- shadow-4.9/src/Makefile.am.getsubids 2021-11-18 16:27:33.943053061 +0100 -+++ shadow-4.9/src/Makefile.am 2021-11-18 16:28:03.647272392 +0100 -@@ -157,8 +157,8 @@ if FCAPS - setcap cap_setgid+ep $(DESTDIR)$(ubindir)/newgidmap - endif - --noinst_PROGRAMS += list_subid_ranges \ -- get_subid_owners \ -+bin_PROGRAMS += getsubids -+noinst_PROGRAMS += get_subid_owners \ - new_subid_range \ - free_subid_range \ - check_subid_range -@@ -174,13 +174,13 @@ MISCLIBS = \ - $(LIBCRYPT) \ - $(LIBTCB) - --list_subid_ranges_LDADD = \ -+getsubids_LDADD = \ - $(top_builddir)/lib/libshadow.la \ - $(top_builddir)/libmisc/libmisc.la \ - $(top_builddir)/libsubid/libsubid.la \ - $(MISCLIBS) -ldl - --list_subid_ranges_CPPFLAGS = \ -+getsubids_CPPFLAGS = \ - -I$(top_srcdir)/lib \ - -I$(top_srcdir)/libmisc \ - -I$(top_srcdir)/libsubid diff --git a/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch b/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch deleted file mode 100644 index 658156a..0000000 --- a/shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up shadow-4.9/libmisc/prefix_flag.c.groupdel-fix-sigsegv-when-passwd-does-not-exist shadow-4.9/libmisc/prefix_flag.c ---- shadow-4.9/libmisc/prefix_flag.c.groupdel-fix-sigsegv-when-passwd-does-not-exist 2021-11-19 09:21:36.997091941 +0100 -+++ shadow-4.9/libmisc/prefix_flag.c 2021-11-19 09:22:19.001341010 +0100 -@@ -288,6 +288,9 @@ extern struct passwd* prefix_getpwent() - if(!passwd_db_file) { - return getpwent(); - } -+ if (!fp_pwent) { -+ return NULL; -+ } - return fgetpwent(fp_pwent); - } - extern void prefix_endpwent() diff --git a/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch b/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch deleted file mode 100644 index 5eaaec9..0000000 --- a/shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 234e8fa7b134d1ebabfdad980a3ae5b63c046c62 Mon Sep 17 00:00:00 2001 -From: Mike Gilbert -Date: Sat, 14 Aug 2021 13:24:34 -0400 -Subject: [PATCH] libmisc: fix default value in SHA_get_salt_rounds() - -If SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS are both unspecified, -use SHA_ROUNDS_DEFAULT. - -Previously, the code fell through, calling shadow_random(-1, -1). This -ultimately set rounds = (unsigned long) -1, which ends up being a very -large number! This then got capped to SHA_ROUNDS_MAX later in the -function. - -The new behavior matches BCRYPT_get_salt_rounds(). - -Bug: https://bugs.gentoo.org/808195 -Fixes: https://github.com/shadow-maint/shadow/issues/393 ---- - libmisc/salt.c | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - -diff --git a/libmisc/salt.c b/libmisc/salt.c -index 91d528fd..30eefb9c 100644 ---- a/libmisc/salt.c -+++ b/libmisc/salt.c -@@ -223,20 +223,21 @@ static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *pre - if ((-1 == min_rounds) && (-1 == max_rounds)) { - rounds = SHA_ROUNDS_DEFAULT; - } -+ else { -+ if (-1 == min_rounds) { -+ min_rounds = max_rounds; -+ } - -- if (-1 == min_rounds) { -- min_rounds = max_rounds; -- } -+ if (-1 == max_rounds) { -+ max_rounds = min_rounds; -+ } - -- if (-1 == max_rounds) { -- max_rounds = min_rounds; -- } -+ if (min_rounds > max_rounds) { -+ max_rounds = min_rounds; -+ } - -- if (min_rounds > max_rounds) { -- max_rounds = min_rounds; -+ rounds = (unsigned long) shadow_random (min_rounds, max_rounds); - } -- -- rounds = (unsigned long) shadow_random (min_rounds, max_rounds); - } else if (0 == *prefered_rounds) { - rounds = SHA_ROUNDS_DEFAULT; - } else { --- -2.31.1 - diff --git a/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch b/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch deleted file mode 100644 index d0b7059..0000000 --- a/shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch +++ /dev/null @@ -1,2497 +0,0 @@ -diff -up shadow-4.9/lib/commonio.c.debug1 shadow-4.9/lib/commonio.c ---- shadow-4.9/lib/commonio.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/commonio.c 2022-01-10 10:45:52.202132937 +0100 -@@ -51,6 +51,7 @@ - #endif /* WITH_TCB */ - #include "prototypes.h" - #include "commonio.h" -+#include "shadowlog_internal.h" - - /* local function prototypes */ - static int lrename (const char *, const char *); -diff -up shadow-4.9/lib/encrypt.c.debug1 shadow-4.9/lib/encrypt.c ---- shadow-4.9/lib/encrypt.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/encrypt.c 2022-01-10 10:45:52.202132937 +0100 -@@ -39,6 +39,7 @@ - - #include "prototypes.h" - #include "defines.h" -+#include "shadowlog_internal.h" - - /*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt) - { -diff -up shadow-4.9/lib/getdef.c.debug1 shadow-4.9/lib/getdef.c ---- shadow-4.9/lib/getdef.c.debug1 2022-01-10 10:45:52.191132858 +0100 -+++ shadow-4.9/lib/getdef.c 2022-01-10 10:45:52.202132937 +0100 -@@ -44,6 +44,7 @@ - #include - #endif - #include "getdef.h" -+#include "shadowlog_internal.h" - /* - * A configuration item definition. - */ -diff -up shadow-4.9/lib/Makefile.am.debug1 shadow-4.9/lib/Makefile.am ---- shadow-4.9/lib/Makefile.am.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/Makefile.am 2022-01-10 10:45:52.202132937 +0100 -@@ -34,6 +34,8 @@ libshadow_la_SOURCES = \ - nss.c \ - nscd.c \ - nscd.h \ -+ shadowlog.c \ -+ shadowlog.h \ - sssd.c \ - sssd.h \ - pam_defs.h \ -diff -up shadow-4.9/libmisc/addgrps.c.debug1 shadow-4.9/libmisc/addgrps.c ---- shadow-4.9/libmisc/addgrps.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/addgrps.c 2022-01-10 10:45:52.203132944 +0100 -@@ -40,6 +40,7 @@ - #include - #include - #include -+#include "shadowlog.h" - - #ident "$Id$" - -@@ -58,6 +59,7 @@ int add_groups (const char *list) - char *token; - char buf[1024]; - int ret; -+ FILE *shadow_logfd = log_get_logfd(); - - if (strlen (list) >= sizeof (buf)) { - errno = EINVAL; -diff -up shadow-4.9/libmisc/audit_help.c.debug1 shadow-4.9/libmisc/audit_help.c ---- shadow-4.9/libmisc/audit_help.c.debug1 2022-01-10 10:45:52.184132808 +0100 -+++ shadow-4.9/libmisc/audit_help.c 2022-01-10 10:45:52.203132944 +0100 -@@ -45,6 +45,7 @@ - #include - #include - #include "prototypes.h" -+#include "shadowlog.h" - int audit_fd; - - void audit_help_open (void) -@@ -59,7 +60,7 @@ void audit_help_open (void) - return; - } - (void) fputs (_("Cannot open audit interface - aborting.\n"), -- shadow_logfd); -+ log_get_logfd()); - exit (EXIT_FAILURE); - } - } -diff -up shadow-4.9/libmisc/chowntty.c.debug1 shadow-4.9/libmisc/chowntty.c ---- shadow-4.9/libmisc/chowntty.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/chowntty.c 2022-01-10 10:45:52.203132944 +0100 -@@ -43,6 +43,7 @@ - #include "defines.h" - #include - #include "getdef.h" -+#include "shadowlog.h" - - /* - * chown_tty() sets the login tty to be owned by the new user ID -@@ -75,6 +76,7 @@ void chown_tty (const struct passwd *inf - if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0) - || (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) { - int err = errno; -+ FILE *shadow_logfd = log_get_logfd(); - - fprintf (shadow_logfd, - _("Unable to change owner or mode of tty stdin: %s"), -diff -up shadow-4.9/libmisc/cleanup_group.c.debug1 shadow-4.9/libmisc/cleanup_group.c ---- shadow-4.9/libmisc/cleanup_group.c.debug1 2022-01-10 10:45:52.184132808 +0100 -+++ shadow-4.9/libmisc/cleanup_group.c 2022-01-10 10:47:02.241632844 +0100 -@@ -36,6 +36,7 @@ - #include "groupio.h" - #include "sgroupio.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /* - * cleanup_report_add_group - Report failure to add a group to the system -@@ -48,7 +49,7 @@ void cleanup_report_add_group (void *gro - - SYSLOG ((LOG_ERR, "failed to add group %s", name)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -+ audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -66,7 +67,7 @@ void cleanup_report_del_group (void *gro - - SYSLOG ((LOG_ERR, "failed to remove group %s", name)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -+ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), - "", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -83,7 +84,7 @@ void cleanup_report_mod_group (void *cle - gr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_GRP_MGMT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -101,7 +102,7 @@ void cleanup_report_mod_gshadow (void *c - sgr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_GRP_MGMT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -121,7 +122,7 @@ void cleanup_report_add_group_group (voi - - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -+ audit_logger (AUDIT_ADD_GROUP, log_get_progname(), - "adding-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -141,7 +142,7 @@ void cleanup_report_add_group_gshadow (v - - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_GRP_MGMT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - "adding-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -164,7 +165,7 @@ void cleanup_report_del_group_group (voi - "failed to remove group %s from %s", - name, gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -+ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), - "removing-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -187,7 +188,7 @@ void cleanup_report_del_group_gshadow (v - "failed to remove group %s from %s", - name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_GRP_MGMT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - "removing-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -203,9 +204,9 @@ void cleanup_report_del_group_gshadow (v - void cleanup_unlock_group (unused void *arg) - { - if (gr_unlock () == 0) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), -- Prog, gr_dbname ()); -+ log_get_progname(), gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT - audit_logger_message ("unlocking-group", -@@ -223,9 +224,9 @@ void cleanup_unlock_group (unused void * - void cleanup_unlock_gshadow (unused void *arg) - { - if (sgr_unlock () == 0) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), -- Prog, sgr_dbname ()); -+ log_get_progname(), sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT - audit_logger_message ("unlocking-gshadow", -diff -up shadow-4.9/libmisc/cleanup_user.c.debug1 shadow-4.9/libmisc/cleanup_user.c ---- shadow-4.9/libmisc/cleanup_user.c.debug1 2022-01-10 10:45:52.184132808 +0100 -+++ shadow-4.9/libmisc/cleanup_user.c 2022-01-10 10:47:49.539970421 +0100 -@@ -36,6 +36,7 @@ - #include "pwio.h" - #include "shadowio.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /* - * cleanup_report_add_user - Report failure to add an user to the system -@@ -48,7 +49,7 @@ void cleanup_report_add_user (void *user - - SYSLOG ((LOG_ERR, "failed to add user %s", name)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -+ audit_logger (AUDIT_ADD_USER, log_get_progname(), - "", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -65,7 +66,7 @@ void cleanup_report_mod_passwd (void *cl - pw_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_MGMT, Prog, -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -85,7 +86,7 @@ void cleanup_report_add_user_passwd (voi - - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -+ audit_logger (AUDIT_ADD_USER, log_get_progname(), - "adding-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -105,7 +106,7 @@ void cleanup_report_add_user_shadow (voi - - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_MGMT, Prog, -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), - "adding-shadow-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -120,9 +121,9 @@ void cleanup_report_add_user_shadow (voi - void cleanup_unlock_passwd (unused void *arg) - { - if (pw_unlock () == 0) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), -- Prog, pw_dbname ()); -+ log_get_progname(), pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT - audit_logger_message ("unlocking-passwd", -@@ -139,9 +140,9 @@ void cleanup_unlock_passwd (unused void - void cleanup_unlock_shadow (unused void *arg) - { - if (spw_unlock () == 0) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), -- Prog, spw_dbname ()); -+ log_get_progname(), spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT - audit_logger_message ("unlocking-shadow", -diff -up shadow-4.9/libmisc/copydir.c.debug1 shadow-4.9/libmisc/copydir.c ---- shadow-4.9/libmisc/copydir.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/copydir.c 2022-01-10 10:48:02.158060482 +0100 -@@ -55,6 +55,7 @@ - #ifdef WITH_ATTR - #include - #endif /* WITH_ATTR */ -+#include "shadowlog.h" - - - static /*@null@*/const char *src_orig; -@@ -116,6 +117,7 @@ static int fchown_if_needed (int fdst, c - static void error_acl (struct error_context *ctx, const char *fmt, ...) - { - va_list ap; -+ FILE *shadow_logfd = log_get_logfd(); - - /* ignore the case when destination does not support ACLs - * or extended attributes */ -@@ -125,7 +127,7 @@ static void error_acl (struct error_cont - } - - va_start (ap, fmt); -- (void) fprintf (shadow_logfd, _("%s: "), Prog); -+ (void) fprintf (shadow_logfd, _("%s: "), log_get_progname()); - if (vfprintf (shadow_logfd, fmt, ap) != 0) { - (void) fputs (_(": "), shadow_logfd); - } -@@ -248,9 +250,9 @@ int copy_tree (const char *src_root, con - } - - if (!S_ISDIR (sb.st_mode)) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - "%s: %s is not a directory", -- Prog, src_root); -+ log_get_progname(), src_root); - return -1; - } - -diff -up shadow-4.9/libmisc/env.c.debug1 shadow-4.9/libmisc/env.c ---- shadow-4.9/libmisc/env.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/env.c 2022-01-10 10:45:52.203132944 +0100 -@@ -40,6 +40,7 @@ - #include - #include "prototypes.h" - #include "defines.h" -+#include "shadowlog.h" - /* - * NEWENVP_STEP must be a power of two. This is the number - * of (char *) pointers to allocate at a time, to avoid using -@@ -171,7 +172,7 @@ void addenv (const char *string, /*@null - } - newenvp = __newenvp; - } else { -- (void) fputs (_("Environment overflow\n"), shadow_logfd); -+ (void) fputs (_("Environment overflow\n"), log_get_logfd()); - newenvc--; - free (newenvp[newenvc]); - } -diff -up shadow-4.9/libmisc/find_new_gid.c.debug1 shadow-4.9/libmisc/find_new_gid.c ---- shadow-4.9/libmisc/find_new_gid.c.debug1 2022-01-10 10:45:52.191132858 +0100 -+++ shadow-4.9/libmisc/find_new_gid.c 2022-01-10 10:45:52.203132944 +0100 -@@ -38,6 +38,7 @@ - #include "prototypes.h" - #include "groupio.h" - #include "getdef.h" -+#include "shadowlog.h" - - /* - * get_ranges - Get the minimum and maximum ID ranges for the search -@@ -74,10 +75,10 @@ static int get_ranges (bool sys_group, g - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: SYS_GID_MIN (%lu), " - "GID_MIN (%lu), SYS_GID_MAX (%lu)\n"), -- Prog, (unsigned long) *min_id, -+ log_get_progname(), (unsigned long) *min_id, - getdef_ulong ("GID_MIN", 1000UL), - (unsigned long) *max_id); - return EINVAL; -@@ -104,10 +105,10 @@ static int get_ranges (bool sys_group, g - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: GID_MIN (%lu), " - "GID_MAX (%lu)\n"), -- Prog, (unsigned long) *min_id, -+ log_get_progname(), (unsigned long) *min_id, - (unsigned long) *max_id); - return EINVAL; - } -@@ -220,10 +221,10 @@ int find_new_gid (bool sys_group, - * more likely to want to stop and address the - * issue. - */ -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Encountered error attempting to use " - "preferred GID: %s\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - return -1; - } - } -@@ -250,9 +251,9 @@ int find_new_gid (bool sys_group, - /* Create an array to hold all of the discovered GIDs */ - used_gids = malloc (sizeof (bool) * (gid_max +1)); - if (NULL == used_gids) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to allocate memory: %s\n"), -- Prog, strerror (errno)); -+ log_get_progname(), strerror (errno)); - return -1; - } - memset (used_gids, false, sizeof (bool) * (gid_max + 1)); -@@ -330,10 +331,10 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique system GID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available GIDs: %s", - strerror (result))); -@@ -373,10 +374,10 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique system GID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available GIDs: %s", - strerror (result))); -@@ -433,10 +434,10 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique GID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available GIDs: %s", - strerror (result))); -@@ -476,10 +477,10 @@ int find_new_gid (bool sys_group, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique GID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available GIDs: %s", - strerror (result))); -@@ -495,9 +496,9 @@ int find_new_gid (bool sys_group, - } - - /* The code reached here and found no available IDs in the range */ -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique GID (no more available GIDs)\n"), -- Prog); -+ log_get_progname()); - SYSLOG ((LOG_WARN, "no more available GIDs on the system")); - free (used_gids); - return -1; -diff -up shadow-4.9/libmisc/find_new_sub_gids.c.debug1 shadow-4.9/libmisc/find_new_sub_gids.c ---- shadow-4.9/libmisc/find_new_sub_gids.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/find_new_sub_gids.c 2022-01-10 10:45:52.203132944 +0100 -@@ -37,6 +37,7 @@ - #include "prototypes.h" - #include "subordinateio.h" - #include "getdef.h" -+#include "shadowlog.h" - - /* - * find_new_sub_gids - Find a new unused range of GIDs. -@@ -60,18 +61,18 @@ int find_new_sub_gids (gid_t *range_star - count = getdef_ulong ("SUB_GID_COUNT", 65536); - - if (min > max || count >= max || (min + count - 1) > max) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: SUB_GID_MIN (%lu)," - " SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"), -- Prog, min, max, count); -+ log_get_progname(), min, max, count); - return -1; - } - - start = sub_gid_find_free_range(min, max, count); - if (start == (gid_t)-1) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique subordinate GID range\n"), -- Prog); -+ log_get_progname()); - SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system")); - return -1; - } -diff -up shadow-4.9/libmisc/find_new_sub_uids.c.debug1 shadow-4.9/libmisc/find_new_sub_uids.c ---- shadow-4.9/libmisc/find_new_sub_uids.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/find_new_sub_uids.c 2022-01-10 10:45:52.203132944 +0100 -@@ -37,6 +37,7 @@ - #include "prototypes.h" - #include "subordinateio.h" - #include "getdef.h" -+#include "shadowlog.h" - - /* - * find_new_sub_uids - Find a new unused range of UIDs. -@@ -60,18 +61,18 @@ int find_new_sub_uids (uid_t *range_star - count = getdef_ulong ("SUB_UID_COUNT", 65536); - - if (min > max || count >= max || (min + count - 1) > max) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: SUB_UID_MIN (%lu)," - " SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"), -- Prog, min, max, count); -+ log_get_progname(), min, max, count); - return -1; - } - - start = sub_uid_find_free_range(min, max, count); - if (start == (uid_t)-1) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique subordinate UID range\n"), -- Prog); -+ log_get_progname()); - SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system")); - return -1; - } -diff -up shadow-4.9/libmisc/find_new_uid.c.debug1 shadow-4.9/libmisc/find_new_uid.c ---- shadow-4.9/libmisc/find_new_uid.c.debug1 2022-01-10 10:45:52.191132858 +0100 -+++ shadow-4.9/libmisc/find_new_uid.c 2022-01-10 10:45:52.204132951 +0100 -@@ -38,6 +38,7 @@ - #include "prototypes.h" - #include "pwio.h" - #include "getdef.h" -+#include "shadowlog.h" - - /* - * get_ranges - Get the minimum and maximum ID ranges for the search -@@ -74,10 +75,10 @@ static int get_ranges (bool sys_user, ui - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: SYS_UID_MIN (%lu), " - "UID_MIN (%lu), SYS_UID_MAX (%lu)\n"), -- Prog, (unsigned long) *min_id, -+ log_get_progname(), (unsigned long) *min_id, - getdef_ulong ("UID_MIN", 1000UL), - (unsigned long) *max_id); - return EINVAL; -@@ -104,10 +105,10 @@ static int get_ranges (bool sys_user, ui - - /* Check that the ranges make sense */ - if (*max_id < *min_id) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: Invalid configuration: UID_MIN (%lu), " - "UID_MAX (%lu)\n"), -- Prog, (unsigned long) *min_id, -+ log_get_progname(), (unsigned long) *min_id, - (unsigned long) *max_id); - return EINVAL; - } -@@ -220,10 +221,10 @@ int find_new_uid(bool sys_user, - * more likely to want to stop and address the - * issue. - */ -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Encountered error attempting to use " - "preferred UID: %s\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - return -1; - } - } -@@ -250,9 +251,9 @@ int find_new_uid(bool sys_user, - /* Create an array to hold all of the discovered UIDs */ - used_uids = malloc (sizeof (bool) * (uid_max +1)); - if (NULL == used_uids) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: failed to allocate memory: %s\n"), -- Prog, strerror (errno)); -+ log_get_progname(), strerror (errno)); - return -1; - } - memset (used_uids, false, sizeof (bool) * (uid_max + 1)); -@@ -330,10 +331,10 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique system UID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available UIDs: %s", - strerror (result))); -@@ -373,10 +374,10 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique system UID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG((LOG_ERR, - "Error checking available UIDs: %s", - strerror (result))); -@@ -433,10 +434,10 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique UID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available UIDs: %s", - strerror (result))); -@@ -476,10 +477,10 @@ int find_new_uid(bool sys_user, - * - */ - if (!nospam) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique UID (%s). " - "Suppressing additional messages.\n"), -- Prog, strerror (result)); -+ log_get_progname(), strerror (result)); - SYSLOG ((LOG_ERR, - "Error checking available UIDs: %s", - strerror (result))); -@@ -495,9 +496,9 @@ int find_new_uid(bool sys_user, - } - - /* The code reached here and found no available IDs in the range */ -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: Can't get unique UID (no more available UIDs)\n"), -- Prog); -+ log_get_progname()); - SYSLOG ((LOG_WARN, "no more available UIDs on the system")); - free (used_uids); - return -1; -diff -up shadow-4.9/libmisc/gettime.c.debug1 shadow-4.9/libmisc/gettime.c ---- shadow-4.9/libmisc/gettime.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/gettime.c 2022-01-10 10:45:52.204132951 +0100 -@@ -36,6 +36,7 @@ - #include - #include "defines.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /* - * gettime() returns the time as the number of seconds since the Epoch -@@ -50,6 +51,7 @@ - char *source_date_epoch; - time_t fallback; - unsigned long long epoch; -+ FILE *shadow_logfd = log_get_logfd(); - - fallback = time (NULL); - source_date_epoch = shadow_getenv ("SOURCE_DATE_EPOCH"); -diff -up shadow-4.9/libmisc/idmapping.c.debug1 shadow-4.9/libmisc/idmapping.c ---- shadow-4.9/libmisc/idmapping.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/idmapping.c 2022-01-10 10:45:52.204132951 +0100 -@@ -40,6 +40,7 @@ - #include - #include - #endif -+#include "shadowlog.h" - - struct map_range *get_map_ranges(int ranges, int argc, char **argv) - { -@@ -47,28 +48,28 @@ struct map_range *get_map_ranges(int ran - int idx, argidx; - - if (ranges < 0 || argc < 0) { -- fprintf(shadow_logfd, "%s: error calculating number of arguments\n", Prog); -+ fprintf(log_get_logfd(), "%s: error calculating number of arguments\n", log_get_progname()); - return NULL; - } - - if (ranges != ((argc + 2) / 3)) { -- fprintf(shadow_logfd, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc); -+ fprintf(log_get_logfd(), "%s: ranges: %u is wrong for argc: %d\n", log_get_progname(), ranges, argc); - return NULL; - } - - if ((ranges * 3) > argc) { -- fprintf(shadow_logfd, "ranges: %u argc: %d\n", -+ fprintf(log_get_logfd(), "ranges: %u argc: %d\n", - ranges, argc); -- fprintf(shadow_logfd, -+ fprintf(log_get_logfd(), - _( "%s: Not enough arguments to form %u mappings\n"), -- Prog, ranges); -+ log_get_progname(), ranges); - return NULL; - } - - mappings = calloc(ranges, sizeof(*mappings)); - if (!mappings) { -- fprintf(shadow_logfd, _( "%s: Memory allocation failure\n"), -- Prog); -+ fprintf(log_get_logfd(), _( "%s: Memory allocation failure\n"), -+ log_get_progname()); - exit(EXIT_FAILURE); - } - -@@ -88,24 +89,24 @@ struct map_range *get_map_ranges(int ran - return NULL; - } - if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) { -- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - if (mapping->upper > UINT_MAX || - mapping->lower > UINT_MAX || - mapping->count > UINT_MAX) { -- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - if (mapping->lower + mapping->count > UINT_MAX || - mapping->upper + mapping->count > UINT_MAX) { -- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - if (mapping->lower + mapping->count < mapping->lower || - mapping->upper + mapping->count < mapping->upper) { - /* this one really shouldn't be possible given previous checks */ -- fprintf(shadow_logfd, _( "%s: subuid overflow detected.\n"), Prog); -+ fprintf(log_get_logfd(), _( "%s: subuid overflow detected.\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - } -@@ -176,19 +177,19 @@ void write_mapping(int proc_dir_fd, int - } else if (strcmp(map_file, "gid_map") == 0) { - cap = CAP_SETGID; - } else { -- fprintf(shadow_logfd, _("%s: Invalid map file %s specified\n"), Prog, map_file); -+ fprintf(log_get_logfd(), _("%s: Invalid map file %s specified\n"), log_get_progname(), map_file); - exit(EXIT_FAILURE); - } - - /* Align setuid- and fscaps-based new{g,u}idmap behavior. */ - if (geteuid() == 0 && geteuid() != ruid) { - if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { -- fprintf(shadow_logfd, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog); -+ fprintf(log_get_logfd(), _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - - if (seteuid(ruid) < 0) { -- fprintf(shadow_logfd, _("%s: Could not seteuid to %d\n"), Prog, ruid); -+ fprintf(log_get_logfd(), _("%s: Could not seteuid to %d\n"), log_get_progname(), ruid); - exit(EXIT_FAILURE); - } - } -@@ -204,7 +205,7 @@ void write_mapping(int proc_dir_fd, int - data[0].effective |= CAP_TO_MASK(CAP_SETFCAP); - data[0].permitted = data[0].effective; - if (capset(&hdr, data) < 0) { -- fprintf(shadow_logfd, _("%s: Could not set caps\n"), Prog); -+ fprintf(log_get_logfd(), _("%s: Could not set caps\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - #endif -@@ -222,7 +223,7 @@ void write_mapping(int proc_dir_fd, int - mapping->lower, - mapping->count); - if ((written <= 0) || (written >= (bufsize - (pos - buf)))) { -- fprintf(shadow_logfd, _("%s: snprintf failed!\n"), Prog); -+ fprintf(log_get_logfd(), _("%s: snprintf failed!\n"), log_get_progname()); - exit(EXIT_FAILURE); - } - pos += written; -@@ -231,13 +232,13 @@ void write_mapping(int proc_dir_fd, int - /* Write the mapping to the mapping file */ - fd = openat(proc_dir_fd, map_file, O_WRONLY); - if (fd < 0) { -- fprintf(shadow_logfd, _("%s: open of %s failed: %s\n"), -- Prog, map_file, strerror(errno)); -+ fprintf(log_get_logfd(), _("%s: open of %s failed: %s\n"), -+ log_get_progname(), map_file, strerror(errno)); - exit(EXIT_FAILURE); - } - if (write(fd, buf, pos - buf) != (pos - buf)) { -- fprintf(shadow_logfd, _("%s: write to %s failed: %s\n"), -- Prog, map_file, strerror(errno)); -+ fprintf(log_get_logfd(), _("%s: write to %s failed: %s\n"), -+ log_get_progname(), map_file, strerror(errno)); - exit(EXIT_FAILURE); - } - close(fd); -diff -up shadow-4.9/libmisc/limits.c.debug1 shadow-4.9/libmisc/limits.c ---- shadow-4.9/libmisc/limits.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/limits.c 2022-01-10 10:45:52.204132951 +0100 -@@ -50,6 +50,7 @@ - #include "defines.h" - #include - #include "getdef.h" -+#include "shadowlog.h" - #ifdef HAVE_SYS_RESOURCE_H - #include - #define LIMITS -@@ -548,7 +549,7 @@ void setup_limits (const struct passwd * - #ifdef LIMITS - if (info->pw_uid != 0) { - if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) { -- (void) fputs (_("Too many logins.\n"), shadow_logfd); -+ (void) fputs (_("Too many logins.\n"), log_get_logfd()); - (void) sleep (2); /* XXX: Should be FAIL_DELAY */ - exit (EXIT_FAILURE); - } -diff -up shadow-4.9/libmisc/pam_pass.c.debug1 shadow-4.9/libmisc/pam_pass.c ---- shadow-4.9/libmisc/pam_pass.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/pam_pass.c 2022-01-10 10:45:52.204132951 +0100 -@@ -46,11 +46,13 @@ - #include "defines.h" - #include "pam_defs.h" - #include "prototypes.h" -+#include "shadowlog.h" - - void do_pam_passwd (const char *user, bool silent, bool change_expired) - { - pam_handle_t *pamh = NULL; - int flags = 0, ret; -+ FILE *shadow_logfd = log_get_logfd(); - - if (silent) - flags |= PAM_SILENT; -diff -up shadow-4.9/libmisc/pam_pass_non_interactive.c.debug1 shadow-4.9/libmisc/pam_pass_non_interactive.c ---- shadow-4.9/libmisc/pam_pass_non_interactive.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/pam_pass_non_interactive.c 2022-01-10 10:45:52.204132951 +0100 -@@ -38,6 +38,7 @@ - #include - #include - #include "prototypes.h" -+#include "shadowlog.h" - - /*@null@*/ /*@only@*/static const char *non_interactive_password = NULL; - static int ni_conv (int num_msg, -@@ -76,9 +77,9 @@ static int ni_conv (int num_msg, - - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: PAM modules requesting echoing are not supported.\n"), -- Prog); -+ log_get_progname()); - goto failed_conversation; - case PAM_PROMPT_ECHO_OFF: - responses[count].resp = strdup (non_interactive_password); -@@ -88,7 +89,7 @@ static int ni_conv (int num_msg, - break; - case PAM_ERROR_MSG: - if ( (NULL == msg[count]->msg) -- || (fprintf (shadow_logfd, "%s\n", msg[count]->msg) <0)) { -+ || (fprintf (log_get_logfd(), "%s\n", msg[count]->msg) <0)) { - goto failed_conversation; - } - responses[count].resp = NULL; -@@ -101,9 +102,9 @@ static int ni_conv (int num_msg, - responses[count].resp = NULL; - break; - default: -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: conversation type %d not supported.\n"), -- Prog, msg[count]->msg_style); -+ log_get_progname(), msg[count]->msg_style); - goto failed_conversation; - } - } -@@ -143,19 +144,19 @@ int do_pam_passwd_non_interactive (const - - ret = pam_start (pam_service, username, &non_interactive_pam_conv, &pamh); - if (ret != PAM_SUCCESS) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: (user %s) pam_start failure %d\n"), -- Prog, username, ret); -+ log_get_progname(), username, ret); - return 1; - } - - non_interactive_password = password; - ret = pam_chauthtok (pamh, 0); - if (ret != PAM_SUCCESS) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: (user %s) pam_chauthtok() failed, error:\n" - "%s\n"), -- Prog, username, pam_strerror (pamh, ret)); -+ log_get_progname(), username, pam_strerror (pamh, ret)); - } - - (void) pam_end (pamh, PAM_SUCCESS); -diff -up shadow-4.9/libmisc/prefix_flag.c.debug1 shadow-4.9/libmisc/prefix_flag.c ---- shadow-4.9/libmisc/prefix_flag.c.debug1 2022-01-10 10:45:52.201132929 +0100 -+++ shadow-4.9/libmisc/prefix_flag.c 2022-01-10 10:45:52.204132951 +0100 -@@ -48,6 +48,7 @@ - #include "subordinateio.h" - #endif /* ENABLE_SUBIDS */ - #include "getdef.h" -+#include "shadowlog.h" - - static char *passwd_db_file = NULL; - static char *spw_db_file = NULL; -@@ -83,18 +84,18 @@ extern const char* process_prefix_flag ( - && (val = argv[i] + 9)) - || (strcmp (argv[i], short_opt) == 0)) { - if (NULL != prefix) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: multiple --prefix options\n"), -- Prog); -+ log_get_progname()); - exit (E_BAD_ARG); - } - - if (val) { - prefix = val; - } else if (i + 1 == argc) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: option '%s' requires an argument\n"), -- Prog, argv[i]); -+ log_get_progname(), argv[i]); - exit (E_BAD_ARG); - } else { - prefix = argv[++ i]; -@@ -110,9 +111,9 @@ extern const char* process_prefix_flag ( - /* should we prevent symbolic link from being used as a prefix? */ - - if ( prefix[0] != '/') { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: prefix must be an absolute path\n"), -- Prog); -+ log_get_progname()); - exit (E_BAD_ARG); - } - size_t len; -diff -up shadow-4.9/libmisc/pwdcheck.c.debug1 shadow-4.9/libmisc/pwdcheck.c ---- shadow-4.9/libmisc/pwdcheck.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/pwdcheck.c 2022-01-10 10:45:52.204132951 +0100 -@@ -39,6 +39,7 @@ - #include "prototypes.h" - #include "defines.h" - #include "pwauth.h" -+#include "shadowlog.h" - - void passwd_check (const char *user, const char *passwd, unused const char *progname) - { -@@ -51,7 +52,7 @@ void passwd_check (const char *user, con - if (pw_auth (passwd, user, PW_LOGIN, (char *) 0) != 0) { - SYSLOG ((LOG_WARN, "incorrect password for `%s'", user)); - (void) sleep (1); -- fprintf (shadow_logfd, _("Incorrect password for %s.\n"), user); -+ fprintf (log_get_logfd(), _("Incorrect password for %s.\n"), user); - exit (EXIT_FAILURE); - } - } -diff -up shadow-4.9/libmisc/root_flag.c.debug1 shadow-4.9/libmisc/root_flag.c ---- shadow-4.9/libmisc/root_flag.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/root_flag.c 2022-01-10 10:45:52.204132951 +0100 -@@ -38,6 +38,7 @@ - #include "prototypes.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - static void change_root (const char* newroot); - -@@ -65,18 +66,18 @@ extern void process_root_flag (const cha - && (val = argv[i] + 7)) - || (strcmp (argv[i], short_opt) == 0)) { - if (NULL != newroot) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: multiple --root options\n"), -- Prog); -+ log_get_progname()); - exit (E_BAD_ARG); - } - - if (val) { - newroot = val; - } else if (i + 1 == argc) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: option '%s' requires an argument\n"), -- Prog, argv[i]); -+ log_get_progname(), argv[i]); - exit (E_BAD_ARG); - } else { - newroot = argv[++ i]; -@@ -94,36 +95,36 @@ static void change_root (const char* new - /* Drop privileges */ - if ( (setregid (getgid (), getgid ()) != 0) - || (setreuid (getuid (), getuid ()) != 0)) { -- fprintf (shadow_logfd, _("%s: failed to drop privileges (%s)\n"), -- Prog, strerror (errno)); -+ fprintf (log_get_logfd(), _("%s: failed to drop privileges (%s)\n"), -+ log_get_progname(), strerror (errno)); - exit (EXIT_FAILURE); - } - - if ('/' != newroot[0]) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: invalid chroot path '%s'\n"), -- Prog, newroot); -+ log_get_progname(), newroot); - exit (E_BAD_ARG); - } - - if (access (newroot, F_OK) != 0) { -- fprintf(shadow_logfd, -+ fprintf(log_get_logfd(), - _("%s: cannot access chroot directory %s: %s\n"), -- Prog, newroot, strerror (errno)); -+ log_get_progname(), newroot, strerror (errno)); - exit (E_BAD_ARG); - } - - if (chdir (newroot) != 0) { -- fprintf(shadow_logfd, -+ fprintf(log_get_logfd(), - _("%s: cannot chdir to chroot directory %s: %s\n"), -- Prog, newroot, strerror (errno)); -+ log_get_progname(), newroot, strerror (errno)); - exit (E_BAD_ARG); - } - - if (chroot (newroot) != 0) { -- fprintf(shadow_logfd, -+ fprintf(log_get_logfd(), - _("%s: unable to chroot to directory %s: %s\n"), -- Prog, newroot, strerror (errno)); -+ log_get_progname(), newroot, strerror (errno)); - exit (E_BAD_ARG); - } - } -diff -up shadow-4.9/libmisc/salt.c.debug1 shadow-4.9/libmisc/salt.c ---- shadow-4.9/libmisc/salt.c.debug1 2022-01-10 10:45:52.195132887 +0100 -+++ shadow-4.9/libmisc/salt.c 2022-01-10 10:45:52.204132951 +0100 -@@ -21,6 +21,7 @@ - #include "prototypes.h" - #include "defines.h" - #include "getdef.h" -+#include "shadowlog.h" - - #if (defined CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY && \ - CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) -@@ -178,7 +179,7 @@ static long read_random_bytes (void) - #endif - - fail: -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("Unable to obtain random bytes.\n")); - exit (1); - -@@ -506,7 +507,7 @@ static /*@observer@*/const char *gensalt - SHA_salt_rounds_to_buf (result, rounds); - #endif /* USE_SHA_CRYPT */ - } else if (0 != strcmp (method, "DES")) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("Invalid ENCRYPT_METHOD value: '%s'.\n" - "Defaulting to DES.\n"), - method); -@@ -532,7 +533,7 @@ static /*@observer@*/const char *gensalt - - /* Should not happen, but... */ - if (NULL == retval) { -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("Unable to generate a salt from setting " - "\"%s\", check your settings in " - "ENCRYPT_METHOD and the corresponding " -diff -up shadow-4.9/libmisc/setupenv.c.debug1 shadow-4.9/libmisc/setupenv.c ---- shadow-4.9/libmisc/setupenv.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/setupenv.c 2022-01-10 10:45:52.204132951 +0100 -@@ -47,6 +47,7 @@ - #include "defines.h" - #include - #include "getdef.h" -+#include "shadowlog.h" - - #ifndef USE_PAM - static void -@@ -219,7 +220,7 @@ void setup_env (struct passwd *info) - static char temp_pw_dir[] = "/"; - - if (!getdef_bool ("DEFAULT_HOME") || chdir ("/") == -1) { -- fprintf (shadow_logfd, _("Unable to cd to '%s'\n"), -+ fprintf (log_get_logfd(), _("Unable to cd to '%s'\n"), - info->pw_dir); - SYSLOG ((LOG_WARN, - "unable to cd to `%s' for user `%s'\n", -diff -up shadow-4.9/libmisc/user_busy.c.debug1 shadow-4.9/libmisc/user_busy.c ---- shadow-4.9/libmisc/user_busy.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/user_busy.c 2022-01-10 10:45:52.204132951 +0100 -@@ -45,6 +45,7 @@ - #ifdef ENABLE_SUBIDS - #include "subordinateio.h" - #endif /* ENABLE_SUBIDS */ -+#include "shadowlog.h" - - #ifdef __linux__ - static int check_status (const char *name, const char *sname, uid_t uid); -@@ -96,9 +97,9 @@ static int user_busy_utmp (const char *n - continue; - } - -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: user %s is currently logged in\n"), -- Prog, name); -+ log_get_progname(), name); - return 1; - } - -@@ -249,9 +250,9 @@ static int user_busy_processes (const ch - #ifdef ENABLE_SUBIDS - sub_uid_close(); - #endif -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: user %s is currently used by process %d\n"), -- Prog, name, pid); -+ log_get_progname(), name, pid); - return 1; - } - -@@ -273,9 +274,9 @@ static int user_busy_processes (const ch - #ifdef ENABLE_SUBIDS - sub_uid_close(); - #endif -- fprintf (shadow_logfd, -+ fprintf (log_get_logfd(), - _("%s: user %s is currently used by process %d\n"), -- Prog, name, pid); -+ log_get_progname(), name, pid); - return 1; - } - } -diff -up shadow-4.9/libmisc/xgetXXbyYY.c.debug1 shadow-4.9/libmisc/xgetXXbyYY.c ---- shadow-4.9/libmisc/xgetXXbyYY.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/xgetXXbyYY.c 2022-01-10 10:45:52.204132951 +0100 -@@ -54,6 +54,7 @@ - #include - #include - #include "prototypes.h" -+#include "shadowlog.h" - - #define XFUNCTION_NAME XPREFIX (FUNCTION_NAME) - #define XPREFIX(name) XPREFIX1 (name) -@@ -74,7 +75,7 @@ - - result = malloc(sizeof(LOOKUP_TYPE)); - if (NULL == result) { -- fprintf (shadow_logfd, _("%s: out of memory\n"), -+ fprintf (log_get_logfd(), _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -@@ -84,7 +85,7 @@ - LOOKUP_TYPE *resbuf = NULL; - buffer = (char *)realloc (buffer, length); - if (NULL == buffer) { -- fprintf (shadow_logfd, _("%s: out of memory\n"), -+ fprintf (log_get_logfd(), _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -@@ -132,7 +133,7 @@ - if (result) { - result = DUP_FUNCTION(result); - if (NULL == result) { -- fprintf (shadow_logfd, _("%s: out of memory\n"), -+ fprintf (log_get_logfd(), _("%s: out of memory\n"), - "x" STRINGIZE(FUNCTION_NAME)); - exit (13); - } -diff -up shadow-4.9/libmisc/xmalloc.c.debug1 shadow-4.9/libmisc/xmalloc.c ---- shadow-4.9/libmisc/xmalloc.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libmisc/xmalloc.c 2022-01-10 10:45:52.204132951 +0100 -@@ -47,6 +47,7 @@ - #include - #include "defines.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size) - { -@@ -54,9 +55,9 @@ - - ptr = (char *) malloc (size); - if (NULL == ptr) { -- (void) fprintf (shadow_logfd, -+ (void) fprintf (log_get_logfd(), - _("%s: failed to allocate memory: %s\n"), -- Prog, strerror (errno)); -+ log_get_progname(), strerror (errno)); - exit (13); - } - return ptr; -diff -up shadow-4.9/lib/nscd.c.debug1 shadow-4.9/lib/nscd.c ---- shadow-4.9/lib/nscd.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/nscd.c 2022-01-10 10:45:52.202132937 +0100 -@@ -10,6 +10,7 @@ - #include "defines.h" - #include "prototypes.h" - #include "nscd.h" -+#include "shadowlog_internal.h" - - #define MSG_NSCD_FLUSH_CACHE_FAILED "%s: Failed to flush the nscd cache.\n" - -diff -up shadow-4.9/lib/nss.c.debug1 shadow-4.9/lib/nss.c ---- shadow-4.9/lib/nss.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/nss.c 2022-01-10 10:45:52.202132937 +0100 -@@ -8,6 +8,7 @@ - #include - #include "prototypes.h" - #include "../libsubid/subid.h" -+#include "shadowlog_internal.h" - - #define NSSWITCH "/etc/nsswitch.conf" - -diff -up shadow-4.9/lib/prototypes.h.debug1 shadow-4.9/lib/prototypes.h ---- shadow-4.9/lib/prototypes.h.debug1 2022-01-10 10:45:52.195132887 +0100 -+++ shadow-4.9/lib/prototypes.h 2022-01-10 10:45:52.202132937 +0100 -@@ -59,9 +59,6 @@ - #include "defines.h" - #include "commonio.h" - --extern /*@observer@*/ const char *Prog; /* Program name showed in error messages */ --extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ -- - /* addgrps.c */ - #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) - extern int add_groups (const char *); -diff -up shadow-4.9/lib/run_part.c.debug1 shadow-4.9/lib/run_part.c ---- shadow-4.9/lib/run_part.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/run_part.c 2022-01-10 10:45:52.202132937 +0100 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include "shadowlog_internal.h" - - int run_part (char *script_path, char *name, char *action) - { -diff -up shadow-4.9/lib/selinux.c.debug1 shadow-4.9/lib/selinux.c ---- shadow-4.9/lib/selinux.c.debug1 2022-01-10 10:45:52.196132894 +0100 -+++ shadow-4.9/lib/selinux.c 2022-01-10 10:45:52.202132937 +0100 -@@ -38,6 +38,8 @@ - #include - #include "prototypes.h" - -+#include "shadowlog_internal.h" -+ - static bool selinux_checked = false; - static bool selinux_enabled; - static /*@null@*/struct selabel_handle *selabel_hnd = NULL; -diff -up shadow-4.9/lib/semanage.c.debug1 shadow-4.9/lib/semanage.c ---- shadow-4.9/lib/semanage.c.debug1 2022-01-10 10:45:52.196132894 +0100 -+++ shadow-4.9/lib/semanage.c 2022-01-10 10:45:52.202132937 +0100 -@@ -43,6 +43,7 @@ - #include - #include "prototypes.h" - -+#include "shadowlog_internal.h" - - #ifndef DEFAULT_SERANGE - #define DEFAULT_SERANGE "s0" -diff -up shadow-4.9/lib/shadowlog.c.debug1 shadow-4.9/lib/shadowlog.c ---- shadow-4.9/lib/shadowlog.c.debug1 2022-01-10 10:45:52.202132937 +0100 -+++ shadow-4.9/lib/shadowlog.c 2022-01-10 10:45:52.202132937 +0100 -@@ -0,0 +1,28 @@ -+#include "shadowlog.h" -+ -+#include "lib/shadowlog_internal.h" -+ -+void log_set_progname(const char *progname) -+{ -+ Prog = progname; -+} -+ -+const char *log_get_progname(void) -+{ -+ return Prog; -+} -+ -+void log_set_logfd(FILE *fd) -+{ -+ if (NULL != fd) -+ shadow_logfd = fd; -+ else -+ shadow_logfd = stderr; -+} -+ -+FILE *log_get_logfd(void) -+{ -+ if (shadow_logfd != NULL) -+ return shadow_logfd; -+ return stderr; -+} -diff -up shadow-4.9/lib/shadowlog.h.debug1 shadow-4.9/lib/shadowlog.h ---- shadow-4.9/lib/shadowlog.h.debug1 2022-01-10 10:45:52.202132937 +0100 -+++ shadow-4.9/lib/shadowlog.h 2022-01-10 10:45:52.202132937 +0100 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (c) 2021 , Serge Hallyn -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the copyright holders or contributors may not be used to -+ * endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/* $Id$ */ -+#ifndef _LOG_H -+#define _LOG_H -+#include -+ -+extern void log_set_progname(const char *); -+extern const char *log_get_progname(void); -+extern void log_set_logfd(FILE *fd); -+extern FILE *log_get_logfd(void); -+extern void log_dolog(char *, ...); -+ -+#endif -diff -up shadow-4.9/lib/shadowlog_internal.h.debug1 shadow-4.9/lib/shadowlog_internal.h ---- shadow-4.9/lib/shadowlog_internal.h.debug1 2022-01-10 10:45:52.202132937 +0100 -+++ shadow-4.9/lib/shadowlog_internal.h 2022-01-10 10:45:52.202132937 +0100 -@@ -0,0 +1,2 @@ -+const char *Prog; /* Program name showed in error messages */ -+FILE *shadow_logfd; /* file descripter to which error messages are printed */ -diff -up shadow-4.9/lib/spawn.c.debug1 shadow-4.9/lib/spawn.c ---- shadow-4.9/lib/spawn.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/spawn.c 2022-01-10 10:45:52.202132937 +0100 -@@ -38,6 +38,8 @@ - #include "exitcodes.h" - #include "prototypes.h" - -+#include "shadowlog_internal.h" -+ - int run_command (const char *cmd, const char *argv[], - /*@null@*/const char *envp[], /*@out@*/int *status) - { -diff -up shadow-4.9/lib/sssd.c.debug1 shadow-4.9/lib/sssd.c ---- shadow-4.9/lib/sssd.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/sssd.c 2022-01-10 10:45:52.203132944 +0100 -@@ -11,6 +11,8 @@ - #include "prototypes.h" - #include "sssd.h" - -+#include "shadowlog_internal.h" -+ - #define MSG_SSSD_FLUSH_CACHE_FAILED "%s: Failed to flush the sssd cache." - - int sssd_flush_cache (int dbflags) -diff -up shadow-4.9/libsubid/api.c.debug1 shadow-4.9/libsubid/api.c ---- shadow-4.9/libsubid/api.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/libsubid/api.c 2022-01-10 10:48:14.913151522 +0100 -@@ -38,12 +38,13 @@ - #include "subordinateio.h" - #include "idmapping.h" - #include "subid.h" -+#include "shadowlog.h" - - const char *Prog = "(libsubid)"; --FILE *shadow_logfd; - - bool libsubid_init(const char *progname, FILE * logfd) - { -+ FILE *shadow_logfd; - if (progname) { - progname = strdup(progname); - if (progname) -@@ -53,14 +54,15 @@ bool libsubid_init(const char *progname, - } - - if (logfd) { -- shadow_logfd = logfd; -+ log_set_logfd(logfd); - return true; - } - shadow_logfd = fopen("/dev/null", "w"); - if (!shadow_logfd) { -- shadow_logfd = stderr; -+ log_set_logfd(stderr); - return false; - } -+ log_set_logfd(shadow_logfd); - return true; - } - -diff -up shadow-4.9/lib/tcbfuncs.c.debug1 shadow-4.9/lib/tcbfuncs.c ---- shadow-4.9/lib/tcbfuncs.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/tcbfuncs.c 2022-01-10 10:45:52.203132944 +0100 -@@ -38,6 +38,8 @@ - #include "shadowio.h" - #include "tcbfuncs.h" - -+#include "shadowlog_internal.h" -+ - #define SHADOWTCB_HASH_BY 1000 - #define SHADOWTCB_LOCK_SUFFIX ".lock" - -diff -up shadow-4.9/src/chage.c.debug1 shadow-4.9/src/chage.c ---- shadow-4.9/src/chage.c.debug1 2022-01-10 10:45:52.188132837 +0100 -+++ shadow-4.9/src/chage.c 2022-01-10 10:45:52.205132958 +0100 -@@ -52,6 +52,7 @@ - #include "defines.h" - #include "pwio.h" - #include "shadowio.h" -+#include "shadowlog.h" - #ifdef WITH_TCB - #include "tcbfuncs.h" - #endif -@@ -62,7 +63,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool - dflg = false, /* set last password change date */ -@@ -820,7 +820,8 @@ int main (int argc, char **argv) - * Get the program name so that error messages can use it. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - sanitize_env (); - (void) setlocale (LC_ALL, ""); -diff -up shadow-4.9/src/check_subid_range.c.debug1 shadow-4.9/src/check_subid_range.c ---- shadow-4.9/src/check_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/check_subid_range.c 2022-01-10 10:45:52.205132958 +0100 -@@ -16,9 +16,9 @@ - #include "prototypes.h" - #include "subordinateio.h" - #include "idmapping.h" -+#include "shadowlog.h" - - const char *Prog; --FILE *shadow_logfd = NULL; - - int main(int argc, char **argv) - { -@@ -26,7 +26,8 @@ int main(int argc, char **argv) - unsigned long start, count; - bool check_uids; - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - if (argc != 5) - exit(1); -diff -up shadow-4.9/src/chfn.c.debug1 shadow-4.9/src/chfn.c ---- shadow-4.9/src/chfn.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/chfn.c 2022-01-10 10:45:52.205132958 +0100 -@@ -52,12 +52,12 @@ - #include "pwio.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables. - */ - const char *Prog; --FILE *shadow_logfd = NULL; - static char fullnm[BUFSIZ]; - static char roomno[BUFSIZ]; - static char workph[BUFSIZ]; -@@ -640,7 +640,8 @@ int main (int argc, char **argv) - * prefix to most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - sanitize_env (); - (void) setlocale (LC_ALL, ""); -diff -up shadow-4.9/src/chgpasswd.c.debug1 shadow-4.9/src/chgpasswd.c ---- shadow-4.9/src/chgpasswd.c.debug1 2022-01-10 10:45:52.188132837 +0100 -+++ shadow-4.9/src/chgpasswd.c 2022-01-10 10:45:52.205132958 +0100 -@@ -61,12 +61,12 @@ - #endif - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -@@ -506,7 +506,8 @@ int main (int argc, char **argv) - int line = 0; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/chpasswd.c.debug1 shadow-4.9/src/chpasswd.c ---- shadow-4.9/src/chpasswd.c.debug1 2022-01-10 10:45:52.188132837 +0100 -+++ shadow-4.9/src/chpasswd.c 2022-01-10 10:45:52.205132958 +0100 -@@ -58,12 +58,12 @@ - #include "shadowio.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - static bool eflg = false; - static bool md5flg = false; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -@@ -494,7 +494,8 @@ int main (int argc, char **argv) - int line = 0; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/chsh.c.debug1 shadow-4.9/src/chsh.c ---- shadow-4.9/src/chsh.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/chsh.c 2022-01-10 10:45:52.205132958 +0100 -@@ -51,6 +51,7 @@ - #endif - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - #ifndef SHELLS_FILE - #define SHELLS_FILE "/etc/shells" -@@ -59,7 +60,6 @@ - * Global variables - */ - const char *Prog; /* Program name */ --FILE *shadow_logfd = NULL; - static bool amroot; /* Real UID is root */ - static char loginsh[BUFSIZ]; /* Name of new login shell */ - /* command line options */ -@@ -442,7 +442,8 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/expiry.c.debug1 shadow-4.9/src/expiry.c ---- shadow-4.9/src/expiry.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/expiry.c 2022-01-10 10:45:52.205132958 +0100 -@@ -43,10 +43,10 @@ - #include "prototypes.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* Global variables */ - const char *Prog; --FILE *shadow_logfd = NULL; - static bool cflg = false; - - /* local function prototypes */ -@@ -145,7 +145,8 @@ int main (int argc, char **argv) - struct spwd *spwd; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - sanitize_env (); - -diff -up shadow-4.9/src/faillog.c.debug1 shadow-4.9/src/faillog.c ---- shadow-4.9/src/faillog.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/faillog.c 2022-01-10 10:45:52.205132958 +0100 -@@ -46,6 +46,7 @@ - #include "prototypes.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* local function prototypes */ - static /*@noreturn@*/void usage (int status); -@@ -62,7 +63,6 @@ static void reset (void); - * Global variables - */ - const char *Prog; /* Program name */ --FILE *shadow_logfd = NULL; - static FILE *fail; /* failure file stream */ - static time_t seconds; /* that number of days in seconds */ - static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ -@@ -574,7 +574,8 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/free_subid_range.c.debug1 shadow-4.9/src/free_subid_range.c ---- shadow-4.9/src/free_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/free_subid_range.c 2022-01-10 10:45:52.205132958 +0100 -@@ -3,11 +3,11 @@ - #include "subid.h" - #include "stdlib.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /* Test program for the subid freeing routine */ - - const char *Prog; --FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -24,7 +24,8 @@ int main(int argc, char *argv[]) - bool group = false; // get subuids by default - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - while ((c = getopt(argc, argv, "g")) != EOF) { - switch(c) { - case 'g': group = true; break; -diff -up shadow-4.9/src/get_subid_owners.c.debug1 shadow-4.9/src/get_subid_owners.c ---- shadow-4.9/src/get_subid_owners.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/get_subid_owners.c 2022-01-10 10:45:52.205132958 +0100 -@@ -2,9 +2,9 @@ - #include "subid.h" - #include "stdlib.h" - #include "prototypes.h" -+#include "shadowlog.h" - - const char *Prog; --FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -20,7 +20,8 @@ int main(int argc, char *argv[]) - uid_t *uids; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - if (argc < 2) { - usage(); - } -diff -up shadow-4.9/src/getsubids.c.debug1 shadow-4.9/src/getsubids.c ---- shadow-4.9/src/getsubids.c.debug1 2022-01-10 10:45:52.200132922 +0100 -+++ shadow-4.9/src/getsubids.c 2022-01-10 10:45:52.205132958 +0100 -@@ -3,9 +3,9 @@ - #include - #include "subid.h" - #include "prototypes.h" -+#include "shadowlog.h" - - const char *Prog; --FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -22,7 +22,8 @@ int main(int argc, char *argv[]) - const char *owner; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - if (argc < 2) - usage(); - owner = argv[1]; -diff -up shadow-4.9/src/gpasswd.c.debug1 shadow-4.9/src/gpasswd.c ---- shadow-4.9/src/gpasswd.c.debug1 2022-01-10 10:45:52.184132808 +0100 -+++ shadow-4.9/src/gpasswd.c 2022-01-10 10:45:52.205132958 +0100 -@@ -53,12 +53,12 @@ - /*@-exitarg@*/ - #include "exitcodes.h" - -+#include "shadowlog.h" - /* - * Global variables - */ - /* The name of this command, as it is invoked */ - const char *Prog; --FILE *shadow_logfd = NULL; - - #ifdef SHADOWGRP - /* Indicate if shadow groups are enabled on the system -@@ -927,7 +927,8 @@ int main (int argc, char **argv) - */ - bywho = getuid (); - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - OPENLOG ("gpasswd"); - setbuf (stdout, NULL); -diff -up shadow-4.9/src/groupadd.c.debug1 shadow-4.9/src/groupadd.c ---- shadow-4.9/src/groupadd.c.debug1 2022-01-10 10:45:52.184132808 +0100 -+++ shadow-4.9/src/groupadd.c 2022-01-10 10:45:52.205132958 +0100 -@@ -56,6 +56,7 @@ - #ifdef SHADOWGRP - #include "sgroupio.h" - #endif -+#include "shadowlog.h" - - /* - * exit status values -@@ -72,7 +73,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static /*@null@*/char *group_name; - static gid_t group_id; -@@ -602,7 +602,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/groupdel.c.debug1 shadow-4.9/src/groupdel.c ---- shadow-4.9/src/groupdel.c.debug1 2022-01-10 10:45:52.185132815 +0100 -+++ shadow-4.9/src/groupdel.c 2022-01-10 10:45:52.205132958 +0100 -@@ -54,11 +54,11 @@ - #ifdef SHADOWGRP - #include "sgroupio.h" - #endif -+#include "shadowlog.h" - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static char *group_name; - static gid_t group_id = -1; -@@ -379,7 +379,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/groupmems.c.debug1 shadow-4.9/src/groupmems.c ---- shadow-4.9/src/groupmems.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/groupmems.c 2022-01-10 10:45:52.206132965 +0100 -@@ -47,6 +47,7 @@ - #ifdef SHADOWGRP - #include "sgroupio.h" - #endif -+#include "shadowlog.h" - - /* Exit Status Values */ - /*@-exitarg@*/ -@@ -65,7 +66,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static char *adduser = NULL; - static char *deluser = NULL; -@@ -596,7 +596,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/groupmod.c.debug1 shadow-4.9/src/groupmod.c ---- shadow-4.9/src/groupmod.c.debug1 2022-01-10 10:45:52.185132815 +0100 -+++ shadow-4.9/src/groupmod.c 2022-01-10 10:45:52.206132965 +0100 -@@ -56,6 +56,7 @@ - #ifdef SHADOWGRP - #include "sgroupio.h" - #endif -+#include "shadowlog.h" - /* - * exit status values - */ -@@ -76,7 +77,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - #ifdef SHADOWGRP - static bool is_shadow_grp; -@@ -840,7 +840,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/groups.c.debug1 shadow-4.9/src/groups.c ---- shadow-4.9/src/groups.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/groups.c 2022-01-10 10:45:52.206132965 +0100 -@@ -39,11 +39,11 @@ - #include - #include "defines.h" - #include "prototypes.h" -+#include "shadowlog.h" - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - /* local function prototypes */ - static void print_groups (const char *member); -@@ -127,7 +127,8 @@ int main (int argc, char **argv) - * Get the program name so that error messages can use it. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - if (argc == 1) { - -diff -up shadow-4.9/src/grpck.c.debug1 shadow-4.9/src/grpck.c ---- shadow-4.9/src/grpck.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/grpck.c 2022-01-10 10:45:52.206132965 +0100 -@@ -45,6 +45,7 @@ - #include "nscd.h" - #include "sssd.h" - #include "prototypes.h" -+#include "shadowlog.h" - - #ifdef SHADOWGRP - #include "sgroupio.h" -@@ -66,7 +67,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static const char *grp_file = GROUP_FILE; - static bool use_system_grp_file = true; -@@ -841,7 +841,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/grpconv.c.debug1 shadow-4.9/src/grpconv.c ---- shadow-4.9/src/grpconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/grpconv.c 2022-01-10 10:45:52.206132965 +0100 -@@ -55,11 +55,11 @@ - #ifdef SHADOWGRP - #include "groupio.h" - #include "sgroupio.h" -+#include "shadowlog.h" - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool gr_locked = false; - static bool sgr_locked = false; -@@ -147,7 +147,8 @@ int main (int argc, char **argv) - struct sgrp sgent; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/grpunconv.c.debug1 shadow-4.9/src/grpunconv.c ---- shadow-4.9/src/grpunconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/grpunconv.c 2022-01-10 10:45:52.206132965 +0100 -@@ -55,11 +55,11 @@ - #ifdef SHADOWGRP - #include "groupio.h" - #include "sgroupio.h" -+#include "shadowlog.h" - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool gr_locked = false; - static bool sgr_locked = false; -@@ -146,7 +146,8 @@ int main (int argc, char **argv) - const struct sgrp *sg; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/lastlog.c.debug1 shadow-4.9/src/lastlog.c ---- shadow-4.9/src/lastlog.c.debug1 2022-01-10 10:45:52.189132844 +0100 -+++ shadow-4.9/src/lastlog.c 2022-01-10 10:45:52.206132965 +0100 -@@ -50,6 +50,7 @@ - #include "getdef.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Needed for MkLinux DR1/2/2.1 - J. -@@ -62,7 +63,6 @@ - * Global variables - */ - const char *Prog; /* Program name */ --FILE *shadow_logfd = NULL; - static FILE *lastlogfile; /* lastlog file stream */ - static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */ - static bool has_umin = false; -@@ -322,7 +322,8 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/login.c.debug1 shadow-4.9/src/login.c ---- shadow-4.9/src/login.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/login.c 2022-01-10 10:45:52.206132965 +0100 -@@ -53,6 +53,7 @@ - #include "pwauth.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - #ifdef USE_PAM - #include "pam_defs.h" -@@ -83,7 +84,6 @@ static pam_handle_t *pamh = NULL; - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static const char *hostname = ""; - static /*@null@*/ /*@only@*/char *username = NULL; -@@ -578,7 +578,8 @@ int main (int argc, char **argv) - - amroot = (getuid () == 0); - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - if (geteuid() != 0) { - fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog); -diff -up shadow-4.9/src/logoutd.c.debug1 shadow-4.9/src/logoutd.c ---- shadow-4.9/src/logoutd.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/logoutd.c 2022-01-10 10:45:52.206132965 +0100 -@@ -40,11 +40,11 @@ - #include - #include "defines.h" - #include "prototypes.h" -+#include "shadowlog.h" - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - #ifndef DEFAULT_HUP_MESG - #define DEFAULT_HUP_MESG _("login time exceeded\n\n") -@@ -188,7 +188,8 @@ int main (int argc, char **argv) - * Start syslogging everything - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - OPENLOG ("logoutd"); - -diff -up shadow-4.9/src/newgidmap.c.debug1 shadow-4.9/src/newgidmap.c ---- shadow-4.9/src/newgidmap.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/newgidmap.c 2022-01-10 10:45:52.206132965 +0100 -@@ -41,12 +41,12 @@ - #include "subordinateio.h" - #include "getdef.h" - #include "idmapping.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - - static bool verify_range(struct passwd *pw, struct map_range *range, bool *allow_setgroups) -@@ -177,7 +177,8 @@ int main(int argc, char **argv) - bool allow_setgroups = false; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - /* - * The valid syntax are -diff -up shadow-4.9/src/newgrp.c.debug1 shadow-4.9/src/newgrp.c ---- shadow-4.9/src/newgrp.c.debug1 2022-01-10 10:45:52.199132915 +0100 -+++ shadow-4.9/src/newgrp.c 2022-01-10 10:45:52.206132965 +0100 -@@ -44,12 +44,12 @@ - #include "prototypes.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - extern char **newenvp; - extern char **environ; -@@ -446,7 +446,8 @@ int main (int argc, char **argv) - * don't need to re-exec anything. -- JWP - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - is_newgrp = (strcmp (Prog, "newgrp") == 0); - OPENLOG (is_newgrp ? "newgrp" : "sg"); - argc--; -diff -up shadow-4.9/src/new_subid_range.c.debug1 shadow-4.9/src/new_subid_range.c ---- shadow-4.9/src/new_subid_range.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/new_subid_range.c 2022-01-10 10:45:52.206132965 +0100 -@@ -3,11 +3,11 @@ - #include "subid.h" - #include "stdlib.h" - #include "prototypes.h" -+#include "shadowlog.h" - - /* Test program for the subid creation routine */ - - const char *Prog; --FILE *shadow_logfd = NULL; - - void usage(void) - { -@@ -27,7 +27,8 @@ int main(int argc, char *argv[]) - bool ok; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - while ((c = getopt(argc, argv, "gn")) != EOF) { - switch(c) { - case 'n': makenew = true; break; -diff -up shadow-4.9/src/newuidmap.c.debug1 shadow-4.9/src/newuidmap.c ---- shadow-4.9/src/newuidmap.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/newuidmap.c 2022-01-10 10:45:52.206132965 +0100 -@@ -41,12 +41,12 @@ - #include "subordinateio.h" - #include "getdef.h" - #include "idmapping.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool verify_range(struct passwd *pw, struct map_range *range) - { -@@ -107,7 +107,8 @@ int main(int argc, char **argv) - int written; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - /* - * The valid syntax are -diff -up shadow-4.9/src/newusers.c.debug1 shadow-4.9/src/newusers.c ---- shadow-4.9/src/newusers.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/newusers.c 2022-01-10 10:45:52.207132972 +0100 -@@ -70,12 +70,12 @@ - #include "subordinateio.h" - #endif /* ENABLE_SUBIDS */ - #include "chkname.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool rflg = false; /* create a system account */ - #ifndef USE_PAM -@@ -1071,7 +1071,8 @@ int main (int argc, char **argv) - #endif /* USE_PAM */ - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/passwd.c.debug1 shadow-4.9/src/passwd.c ---- shadow-4.9/src/passwd.c.debug1 2022-01-10 10:45:52.189132844 +0100 -+++ shadow-4.9/src/passwd.c 2022-01-10 10:45:52.207132972 +0100 -@@ -50,6 +50,7 @@ - #include "pwauth.h" - #include "pwio.h" - #include "shadowio.h" -+#include "shadowlog.h" - - /* - * exit status values -@@ -66,7 +67,6 @@ - * Global variables - */ - const char *Prog; /* Program name */ --FILE *shadow_logfd = NULL; - - static char *name; /* The name of user whose password is being changed */ - static char *myname; /* The current user's name */ -@@ -761,7 +761,8 @@ int main (int argc, char **argv) - * most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/pwck.c.debug1 shadow-4.9/src/pwck.c ---- shadow-4.9/src/pwck.c.debug1 2022-01-10 10:45:52.198132908 +0100 -+++ shadow-4.9/src/pwck.c 2022-01-10 10:45:52.207132972 +0100 -@@ -52,6 +52,7 @@ - #ifdef WITH_TCB - #include "tcbfuncs.h" - #endif /* WITH_TCB */ -+#include "shadowlog.h" - - /* - * Exit codes -@@ -70,7 +71,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool use_system_pw_file = true; - static bool use_system_spw_file = true; -@@ -857,7 +857,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/pwconv.c.debug1 shadow-4.9/src/pwconv.c ---- shadow-4.9/src/pwconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/pwconv.c 2022-01-10 10:45:52.207132972 +0100 -@@ -73,6 +73,7 @@ - #include "shadowio.h" - #include "nscd.h" - #include "sssd.h" -+#include "shadowlog.h" - - /* - * exit status values -@@ -89,7 +90,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool spw_locked = false; - static bool pw_locked = false; -@@ -177,7 +177,8 @@ int main (int argc, char **argv) - struct spwd spent; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/pwunconv.c.debug1 shadow-4.9/src/pwunconv.c ---- shadow-4.9/src/pwunconv.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/pwunconv.c 2022-01-10 10:45:52.207132972 +0100 -@@ -48,12 +48,12 @@ - #include "shadowio.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static bool spw_locked = false; - static bool pw_locked = false; -@@ -138,7 +138,8 @@ int main (int argc, char **argv) - const struct spwd *spwd; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/su.c.debug1 shadow-4.9/src/su.c ---- shadow-4.9/src/su.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/su.c 2022-01-10 10:45:52.207132972 +0100 -@@ -77,12 +77,12 @@ - #endif /* USE_PAM */ - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - static /*@observer@*/const char *caller_tty = NULL; /* Name of tty SU is run from */ - static bool caller_is_root = false; - static uid_t caller_uid; -@@ -717,7 +717,8 @@ static void save_caller_context (char ** - * most error messages. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - caller_uid = getuid (); - caller_is_root = (caller_uid == 0); -diff -up shadow-4.9/src/sulogin.c.debug1 shadow-4.9/src/sulogin.c ---- shadow-4.9/src/sulogin.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/sulogin.c 2022-01-10 10:45:52.207132972 +0100 -@@ -45,12 +45,12 @@ - #include "pwauth.h" - /*@-exitarg@*/ - #include "exitcodes.h" -+#include "shadowlog.h" - - /* - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static char name[BUFSIZ]; - static char pass[BUFSIZ]; -@@ -107,7 +107,8 @@ static RETSIGTYPE catch_signals (unused - #endif - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); -diff -up shadow-4.9/src/useradd.c.debug1 shadow-4.9/src/useradd.c ---- shadow-4.9/src/useradd.c.debug1 2022-01-10 10:45:52.197132901 +0100 -+++ shadow-4.9/src/useradd.c 2022-01-10 10:45:52.207132972 +0100 -@@ -78,6 +78,7 @@ - #ifdef WITH_TCB - #include "tcbfuncs.h" - #endif -+#include "shadowlog.h" - - #ifndef SKEL_DIR - #define SKEL_DIR "/etc/skel" -@@ -96,7 +97,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - /* - * These defaults are used if there is no defaults file. -@@ -2359,7 +2359,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/userdel.c.debug1 shadow-4.9/src/userdel.c ---- shadow-4.9/src/userdel.c.debug1 2022-01-10 10:45:52.186132823 +0100 -+++ shadow-4.9/src/userdel.c 2022-01-10 10:45:52.208132979 +0100 -@@ -72,6 +72,7 @@ - #ifdef ENABLE_SUBIDS - #include "subordinateio.h" - #endif /* ENABLE_SUBIDS */ -+#include "shadowlog.h" - - /* - * exit status values -@@ -91,7 +92,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static char *user_name; - static uid_t user_id; -@@ -944,7 +944,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); -diff -up shadow-4.9/src/usermod.c.debug1 shadow-4.9/src/usermod.c ---- shadow-4.9/src/usermod.c.debug1 2022-01-10 10:45:52.193132872 +0100 -+++ shadow-4.9/src/usermod.c 2022-01-10 10:45:52.208132979 +0100 -@@ -74,6 +74,7 @@ - #ifdef WITH_TCB - #include "tcbfuncs.h" - #endif -+#include "shadowlog.h" - - /* - * exit status values -@@ -105,7 +106,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static char *user_name; - static char *user_newname; -@@ -2172,7 +2172,8 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); -diff -up shadow-4.9/src/vipw.c.debug1 shadow-4.9/src/vipw.c ---- shadow-4.9/src/vipw.c.debug1 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/src/vipw.c 2022-01-10 10:45:52.208132979 +0100 -@@ -53,6 +53,7 @@ - #include - #include "tcbfuncs.h" - #endif /* WITH_TCB */ -+#include "shadowlog.h" - - #define MSG_WARN_EDIT_OTHER_FILE _( \ - "You have modified %s.\n"\ -@@ -63,7 +64,6 @@ - * Global variables - */ - const char *Prog; --FILE *shadow_logfd = NULL; - - static const char *filename, *fileeditname; - static bool filelocked = false; -@@ -482,7 +482,8 @@ int main (int argc, char **argv) - bool do_vipw; - - Prog = Basename (argv[0]); -- shadow_logfd = stderr; -+ log_set_progname(Prog); -+ log_set_logfd(stderr); - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); diff --git a/shadow-4.9-move-create-home.patch b/shadow-4.9-move-create-home.patch deleted file mode 100644 index 0ed6ea7..0000000 --- a/shadow-4.9-move-create-home.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 09c752f00f9dfc610f66d68be38c9e5be8ca7f15 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 8 Oct 2021 13:09:59 +0200 -Subject: [PATCH] useradd: create directories after the SELinux user - -Create the home and mail folders after the SELinux user has been set for -the added user. This will allow the folders to be created with the -SELinux user label. - -Signed-off-by: Iker Pedrosa ---- - src/useradd.c | 46 +++++++++++++++++++++++----------------------- - 1 file changed, 23 insertions(+), 23 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 6269c01c..b463a170 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2670,27 +2670,12 @@ int main (int argc, char **argv) - - usr_update (); - -- if (mflg) { -- create_home (); -- if (home_added) { -- copy_tree (def_template, prefix_user_home, false, false, -- (uid_t)-1, user_id, (gid_t)-1, user_gid); -- } else { -- fprintf (stderr, -- _("%s: warning: the home directory %s already exists.\n" -- "%s: Not copying any file from skel directory into it.\n"), -- Prog, user_home, Prog); -- } -- -- } -- -- /* Do not create mail directory for system accounts */ -- if (!rflg) { -- create_mail (); -- } -- - close_files (); - -+ nscd_flush_cache ("passwd"); -+ nscd_flush_cache ("group"); -+ sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); -+ - /* - * tallylog_reset needs to be able to lookup - * a valid existing user name, -@@ -2716,15 +2701,30 @@ int main (int argc, char **argv) - } - #endif /* WITH_SELINUX */ - -+ if (mflg) { -+ create_home (); -+ if (home_added) { -+ copy_tree (def_template, prefix_user_home, false, false, -+ (uid_t)-1, user_id, (gid_t)-1, user_gid); -+ } else { -+ fprintf (stderr, -+ _("%s: warning: the home directory %s already exists.\n" -+ "%s: Not copying any file from skel directory into it.\n"), -+ Prog, user_home, Prog); -+ } -+ -+ } -+ -+ /* Do not create mail directory for system accounts */ -+ if (!rflg) { -+ create_mail (); -+ } -+ - if (run_parts ("/etc/shadow-maint/useradd-post.d", (char*)user_name, - "useradd")) { - exit(1); - } - -- nscd_flush_cache ("passwd"); -- nscd_flush_cache ("group"); -- sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); -- - return E_SUCCESS; - } - --- -2.31.1 - diff --git a/shadow-4.9-newgrp-fix-segmentation-fault.patch b/shadow-4.9-newgrp-fix-segmentation-fault.patch deleted file mode 100644 index 49332a1..0000000 --- a/shadow-4.9-newgrp-fix-segmentation-fault.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 497e90751bc0d95cc998b0f06305040563903948 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Wed, 10 Nov 2021 12:02:04 +0100 -Subject: [PATCH] newgrp: fix segmentation fault - -Fix segmentation fault in newgrp when xgetspnam() returns a NULL value -that is immediately freed. - -The error was committed in -https://github.com/shadow-maint/shadow/commit/e65cc6aebcb4132fa413f00a905216a5b35b3d57 - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2019553 - -Signed-off-by: Iker Pedrosa ---- - src/newgrp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/newgrp.c b/src/newgrp.c -index 730f47e8..566f1c89 100644 ---- a/src/newgrp.c -+++ b/src/newgrp.c -@@ -163,8 +163,8 @@ static void check_perms (const struct group *grp, - spwd = xgetspnam (pwd->pw_name); - if (NULL != spwd) { - pwd->pw_passwd = xstrdup (spwd->sp_pwdp); -+ spw_free (spwd); - } -- spw_free (spwd); - - if ((pwd->pw_passwd[0] == '\0') && (grp->gr_passwd[0] != '\0')) { - needspasswd = true; --- -2.31.1 - diff --git a/shadow-4.9-newuidmap-libeconf-dependency.patch b/shadow-4.9-newuidmap-libeconf-dependency.patch deleted file mode 100644 index a1907a6..0000000 --- a/shadow-4.9-newuidmap-libeconf-dependency.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/src/Makefile.am b/src/Makefile.am -index 7c1a3491..6cc873be 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -96,8 +96,8 @@ LIBCRYPT_NOPAM = $(LIBCRYPT) - endif - - chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) --newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl --newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) -ldl -+newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl -+newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) $(LIBECONF) -ldl - chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) - chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) - chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) diff --git a/shadow-4.9-null-tm.patch b/shadow-4.9-null-tm.patch deleted file mode 100644 index 249b27b..0000000 --- a/shadow-4.9-null-tm.patch +++ /dev/null @@ -1,70 +0,0 @@ -Index: shadow-4.5/src/chage.c -=================================================================== ---- shadow-4.5.orig/src/chage.c -+++ shadow-4.5/src/chage.c -@@ -168,6 +168,10 @@ static void date_to_str (char *buf, size - struct tm *tp; - - tp = gmtime (&date); -+ if (tp == NULL) { -+ (void) snprintf (buf, maxsize, "(unknown)"); -+ return; -+ } - #ifdef HAVE_STRFTIME - (void) strftime (buf, maxsize, "%Y-%m-%d", tp); - #else -Index: shadow-4.5/src/lastlog.c -=================================================================== ---- shadow-4.5.orig/src/lastlog.c -+++ shadow-4.5/src/lastlog.c -@@ -158,13 +158,17 @@ static void print_one (/*@null@*/const s - - ll_time = ll.ll_time; - tm = localtime (&ll_time); -+ if (tm == NULL) { -+ cp = "(unknown)"; -+ } else { - #ifdef HAVE_STRFTIME -- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -- cp = ptime; -+ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -+ cp = ptime; - #else -- cp = asctime (tm); -- cp[24] = '\0'; -+ cp = asctime (tm); -+ cp[24] = '\0'; - #endif -+ } - - if (ll.ll_time == (time_t) 0) { - cp = _("**Never logged in**\0"); -Index: shadow-4.5/src/passwd.c -=================================================================== ---- shadow-4.5.orig/src/passwd.c -+++ shadow-4.5/src/passwd.c -@@ -455,6 +455,9 @@ static /*@observer@*/const char *date_to - struct tm *tm; - - tm = gmtime (&t); -+ if (tm == NULL) { -+ return "(unknown)"; -+ } - #ifdef HAVE_STRFTIME - (void) strftime (buf, sizeof buf, "%m/%d/%Y", tm); - #else /* !HAVE_STRFTIME */ -Index: shadow-4.5/src/usermod.c -=================================================================== ---- shadow-4.5.orig/src/usermod.c -+++ shadow-4.5/src/usermod.c -@@ -210,6 +210,10 @@ static void date_to_str (/*@unique@*//*@ - } else { - time_t t = (time_t) date; - tp = gmtime (&t); -+ if (tp == NULL) { -+ strncpy (buf, "unknown", maxsize); -+ return; -+ } - #ifdef HAVE_STRFTIME - strftime (buf, maxsize, "%Y-%m-%d", tp); - #else diff --git a/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch b/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch deleted file mode 100644 index e7761b7..0000000 --- a/shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d8e54618feea201987c1f3cb402ed50d1d8b604f Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 15 Nov 2021 12:40:15 +0100 -Subject: [PATCH] pwck: fix segfault when calling fprintf() - -As shadow_logfd variable is not set at the beginning of the program if -something fails and fprintf() is called a segmentation fault happens. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2021339 - -Signed-off-by: Iker Pedrosa ---- - src/pwck.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/pwck.c b/src/pwck.c -index 4248944a..4ce86af2 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -857,6 +857,7 @@ int main (int argc, char **argv) - * Get my name so that I can use it to report errors. - */ - Prog = Basename (argv[0]); -+ shadow_logfd = stderr; - - (void) setlocale (LC_ALL, ""); - (void) bindtextdomain (PACKAGE, LOCALEDIR); --- -2.31.1 - diff --git a/shadow-4.9-rename-prog-to-shadow-progname.patch b/shadow-4.9-rename-prog-to-shadow-progname.patch deleted file mode 100644 index d3a73a3..0000000 --- a/shadow-4.9-rename-prog-to-shadow-progname.patch +++ /dev/null @@ -1,507 +0,0 @@ -diff -up shadow-4.9/lib/commonio.c.debug2 shadow-4.9/lib/commonio.c ---- shadow-4.9/lib/commonio.c.debug2 2022-01-10 10:57:47.535238522 +0100 -+++ shadow-4.9/lib/commonio.c 2022-01-10 10:57:47.544238586 +0100 -@@ -147,7 +147,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: %s: %s\n", -- Prog, file, strerror (errno)); -+ shadow_progname, file, strerror (errno)); - } - return 0; - } -@@ -159,7 +159,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: %s file write error: %s\n", -- Prog, file, strerror (errno)); -+ shadow_progname, file, strerror (errno)); - } - (void) close (fd); - unlink (file); -@@ -169,7 +169,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: %s file sync error: %s\n", -- Prog, file, strerror (errno)); -+ shadow_progname, file, strerror (errno)); - } - (void) close (fd); - unlink (file); -@@ -182,7 +182,7 @@ static int do_lock_file (const char *fil - if ((0==retval) && log) { - (void) fprintf (shadow_logfd, - "%s: %s: lock file already used\n", -- Prog, file); -+ shadow_progname, file); - } - unlink (file); - return retval; -@@ -193,7 +193,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: %s: %s\n", -- Prog, lock, strerror (errno)); -+ shadow_progname, lock, strerror (errno)); - } - unlink (file); - errno = EINVAL; -@@ -205,7 +205,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: existing lock file %s without a PID\n", -- Prog, lock); -+ shadow_progname, lock); - } - unlink (file); - errno = EINVAL; -@@ -216,7 +216,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: existing lock file %s with an invalid PID '%s'\n", -- Prog, lock, buf); -+ shadow_progname, lock, buf); - } - unlink (file); - errno = EINVAL; -@@ -226,7 +226,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: lock %s already used by PID %lu\n", -- Prog, lock, (unsigned long) pid); -+ shadow_progname, lock, (unsigned long) pid); - } - unlink (file); - errno = EEXIST; -@@ -236,7 +236,7 @@ static int do_lock_file (const char *fil - if (log) { - (void) fprintf (shadow_logfd, - "%s: cannot get lock %s: %s\n", -- Prog, lock, strerror (errno)); -+ shadow_progname, lock, strerror (errno)); - } - unlink (file); - return 0; -@@ -248,13 +248,13 @@ static int do_lock_file (const char *fil - if ((0==retval) && log) { - (void) fprintf (shadow_logfd, - "%s: %s: lock file already used\n", -- Prog, file); -+ shadow_progname, file); - } - } else { - if (log) { - (void) fprintf (shadow_logfd, - "%s: cannot get lock %s: %s\n", -- Prog, lock, strerror (errno)); -+ shadow_progname, lock, strerror (errno)); - } - } - -@@ -449,7 +449,7 @@ int commonio_lock (struct commonio_db *d - if (geteuid () != 0) { - (void) fprintf (shadow_logfd, - "%s: Permission denied.\n", -- Prog); -+ shadow_progname); - } - return 0; /* failure */ - } -@@ -484,7 +484,7 @@ int commonio_lock (struct commonio_db *d - /* no unnecessary retries on "permission denied" errors */ - if (geteuid () != 0) { - (void) fprintf (shadow_logfd, "%s: Permission denied.\n", -- Prog); -+ shadow_progname); - return 0; - } - } -diff -up shadow-4.9/lib/nscd.c.debug2 shadow-4.9/lib/nscd.c ---- shadow-4.9/lib/nscd.c.debug2 2022-01-10 10:57:47.537238536 +0100 -+++ shadow-4.9/lib/nscd.c 2022-01-10 10:57:47.544238586 +0100 -@@ -26,7 +26,7 @@ int nscd_flush_cache (const char *servic - - if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) { - /* run_command writes its own more detailed message. */ -- (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); -+ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), shadow_progname); - return -1; - } - -@@ -34,7 +34,7 @@ int nscd_flush_cache (const char *servic - if (!WIFEXITED (status)) { - (void) fprintf (shadow_logfd, - _("%s: nscd did not terminate normally (signal %d)\n"), -- Prog, WTERMSIG (status)); -+ shadow_progname, WTERMSIG (status)); - return -1; - } else if (code == E_CMD_NOTFOUND) { - /* nscd is not installed, or it is installed but uses an -@@ -45,8 +45,8 @@ int nscd_flush_cache (const char *servic - return 0; - } else if (code != 0) { - (void) fprintf (shadow_logfd, _("%s: nscd exited with status %d\n"), -- Prog, code); -- (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog); -+ shadow_progname, code); -+ (void) fprintf (shadow_logfd, _(MSG_NSCD_FLUSH_CACHE_FAILED), shadow_progname); - return -1; - } - -diff -up shadow-4.9/lib/selinux.c.debug2 shadow-4.9/lib/selinux.c ---- shadow-4.9/lib/selinux.c.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/selinux.c 2022-01-10 10:57:47.544238586 +0100 -@@ -216,7 +216,7 @@ int check_selinux_permit (const char *pe - if (getprevcon_raw (&user_context_raw) != 0) { - fprintf (shadow_logfd, - _("%s: can not get previous SELinux process context: %s\n"), -- Prog, strerror (errno)); -+ shadow_progname, strerror (errno)); - SYSLOG ((LOG_WARN, - "can not get previous SELinux process context: %s", - strerror (errno))); -diff -up shadow-4.9/lib/shadowlog.c.debug2 shadow-4.9/lib/shadowlog.c ---- shadow-4.9/lib/shadowlog.c.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/shadowlog.c 2022-01-10 10:57:47.544238586 +0100 -@@ -2,14 +2,17 @@ - - #include "lib/shadowlog_internal.h" - -+const char *shadow_progname; -+FILE *shadow_logfd; -+ - void log_set_progname(const char *progname) - { -- Prog = progname; -+ shadow_progname = progname; - } - - const char *log_get_progname(void) - { -- return Prog; -+ return shadow_progname; - } - - void log_set_logfd(FILE *fd) -diff -up shadow-4.9/lib/shadowlog_internal.h.debug2 shadow-4.9/lib/shadowlog_internal.h ---- shadow-4.9/lib/shadowlog_internal.h.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/shadowlog_internal.h 2022-01-10 10:57:47.544238586 +0100 -@@ -1,2 +1,2 @@ --const char *Prog; /* Program name showed in error messages */ --FILE *shadow_logfd; /* file descripter to which error messages are printed */ -+extern const char *shadow_progname; /* Program name showed in error messages */ -+extern FILE *shadow_logfd; /* file descripter to which error messages are printed */ -diff -up shadow-4.9/lib/spawn.c.debug2 shadow-4.9/lib/spawn.c ---- shadow-4.9/lib/spawn.c.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/spawn.c 2022-01-10 10:57:47.544238586 +0100 -@@ -60,11 +60,11 @@ int run_command (const char *cmd, const - exit (E_CMD_NOTFOUND); - } - fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", -- Prog, cmd, strerror (errno)); -+ shadow_progname, cmd, strerror (errno)); - exit (E_CMD_NOEXEC); - } else if ((pid_t)-1 == pid) { - fprintf (shadow_logfd, "%s: cannot execute %s: %s\n", -- Prog, cmd, strerror (errno)); -+ shadow_progname, cmd, strerror (errno)); - return -1; - } - -@@ -77,7 +77,7 @@ int run_command (const char *cmd, const - - if ((pid_t)-1 == wpid) { - fprintf (shadow_logfd, "%s: waitpid (status: %d): %s\n", -- Prog, *status, strerror (errno)); -+ shadow_progname, *status, strerror (errno)); - return -1; - } - -diff -up shadow-4.9/lib/sssd.c.debug2 shadow-4.9/lib/sssd.c ---- shadow-4.9/lib/sssd.c.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/sssd.c 2022-01-10 10:57:47.544238586 +0100 -@@ -48,22 +48,22 @@ int sssd_flush_cache (int dbflags) - free(sss_cache_args); - if (rv != 0) { - /* run_command writes its own more detailed message. */ -- SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog)); -+ SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, shadow_progname)); - return -1; - } - - code = WEXITSTATUS (status); - if (!WIFEXITED (status)) { - SYSLOG ((LOG_WARN, "%s: sss_cache did not terminate normally (signal %d)", -- Prog, WTERMSIG (status))); -+ shadow_progname, WTERMSIG (status))); - return -1; - } else if (code == E_CMD_NOTFOUND) { - /* sss_cache is not installed, or it is installed but uses an - interpreter that is missing. Probably the former. */ - return 0; - } else if (code != 0) { -- SYSLOG ((LOG_WARN, "%s: sss_cache exited with status %d", Prog, code)); -- SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, Prog)); -+ SYSLOG ((LOG_WARN, "%s: sss_cache exited with status %d", shadow_progname, code)); -+ SYSLOG ((LOG_WARN, MSG_SSSD_FLUSH_CACHE_FAILED, shadow_progname)); - return -1; - } - -diff -up shadow-4.9/lib/tcbfuncs.c.debug2 shadow-4.9/lib/tcbfuncs.c ---- shadow-4.9/lib/tcbfuncs.c.debug2 2022-01-10 10:57:47.538238543 +0100 -+++ shadow-4.9/lib/tcbfuncs.c 2022-01-10 10:59:01.228764507 +0100 -@@ -74,7 +74,7 @@ shadowtcb_status shadowtcb_gain_priv (vo - * to exit soon. - */ - #define OUT_OF_MEMORY do { \ -- fprintf (shadow_logfd, _("%s: out of memory\n"), Prog); \ -+ fprintf (shadow_logfd, _("%s: out of memory\n"), shadow_progname); \ - (void) fflush (shadow_logfd); \ - } while (false) - -@@ -120,7 +120,7 @@ static /*@null@*/ char *shadowtcb_path_r - if (lstat (path, &st) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), -- Prog, path, strerror (errno)); -+ shadow_progname, path, strerror (errno)); - free (path); - return NULL; - } -@@ -136,7 +136,7 @@ static /*@null@*/ char *shadowtcb_path_r - if (!S_ISLNK (st.st_mode)) { - fprintf (shadow_logfd, - _("%s: %s is neither a directory, nor a symlink.\n"), -- Prog, path); -+ shadow_progname, path); - free (path); - return NULL; - } -@@ -144,7 +144,7 @@ static /*@null@*/ char *shadowtcb_path_r - if (-1 == ret) { - fprintf (shadow_logfd, - _("%s: Cannot read symbolic link %s: %s\n"), -- Prog, path, strerror (errno)); -+ shadow_progname, path, strerror (errno)); - free (path); - return NULL; - } -@@ -153,7 +153,7 @@ static /*@null@*/ char *shadowtcb_path_r - link[sizeof(link) - 1] = '\0'; - fprintf (shadow_logfd, - _("%s: Suspiciously long symlink: %s\n"), -- Prog, link); -+ shadow_progname, link); - return NULL; - } - link[(size_t)ret] = '\0'; -@@ -211,7 +211,7 @@ static shadowtcb_status mkdir_leading (c - if (stat (TCB_DIR, &st) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), -- Prog, TCB_DIR, strerror (errno)); -+ shadow_progname, TCB_DIR, strerror (errno)); - goto out_free_path; - } - while ((ind = strchr (ptr, '/'))) { -@@ -223,19 +223,19 @@ static shadowtcb_status mkdir_leading (c - if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) { - fprintf (shadow_logfd, - _("%s: Cannot create directory %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free_dir; - } - if (chown (dir, 0, st.st_gid) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free_dir; - } - if (chmod (dir, 0711) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free_dir; - } - free (dir); -@@ -265,7 +265,7 @@ static shadowtcb_status unlink_suffs (co - if ((unlink (tmp) != 0) && (errno != ENOENT)) { - fprintf (shadow_logfd, - _("%s: unlink: %s: %s\n"), -- Prog, tmp, strerror (errno)); -+ shadow_progname, tmp, strerror (errno)); - free (tmp); - return SHADOWTCB_FAILURE; - } -@@ -290,7 +290,7 @@ static shadowtcb_status rmdir_leading (c - if (errno != ENOTEMPTY) { - fprintf (shadow_logfd, - _("%s: Cannot remove directory %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - ret = SHADOWTCB_FAILURE; - } - free (dir); -@@ -319,7 +319,7 @@ static shadowtcb_status move_dir (const - if (stat (olddir, &oldmode) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), -- Prog, olddir, strerror (errno)); -+ shadow_progname, olddir, strerror (errno)); - goto out_free; - } - old_uid = oldmode.st_uid; -@@ -346,7 +346,7 @@ static shadowtcb_status move_dir (const - if (rename (real_old_dir, real_new_dir) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot rename %s to %s: %s\n"), -- Prog, real_old_dir, real_new_dir, strerror (errno)); -+ shadow_progname, real_old_dir, real_new_dir, strerror (errno)); - goto out_free; - } - if (rmdir_leading (real_old_dir_rel) == SHADOWTCB_FAILURE) { -@@ -355,7 +355,7 @@ static shadowtcb_status move_dir (const - if ((unlink (olddir) != 0) && (errno != ENOENT)) { - fprintf (shadow_logfd, - _("%s: Cannot remove %s: %s\n"), -- Prog, olddir, strerror (errno)); -+ shadow_progname, olddir, strerror (errno)); - goto out_free; - } - if (asprintf (&newdir, TCB_DIR "/%s", user_newname) == -1) { -@@ -369,7 +369,7 @@ static shadowtcb_status move_dir (const - && (symlink (real_new_dir_rel, newdir) != 0)) { - fprintf (shadow_logfd, - _("%s: Cannot create symbolic link %s: %s\n"), -- Prog, real_new_dir_rel, strerror (errno)); -+ shadow_progname, real_new_dir_rel, strerror (errno)); - goto out_free; - } - ret = SHADOWTCB_SUCCESS; -@@ -468,31 +468,31 @@ shadowtcb_status shadowtcb_move (/*@NULL - if (stat (tcbdir, &dirmode) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), -- Prog, tcbdir, strerror (errno)); -+ shadow_progname, tcbdir, strerror (errno)); - goto out_free; - } - if (chown (tcbdir, 0, 0) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owners of %s: %s\n"), -- Prog, tcbdir, strerror (errno)); -+ shadow_progname, tcbdir, strerror (errno)); - goto out_free; - } - if (chmod (tcbdir, 0700) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), -- Prog, tcbdir, strerror (errno)); -+ shadow_progname, tcbdir, strerror (errno)); - goto out_free; - } - if (lstat (shadow, &filemode) != 0) { - if (errno != ENOENT) { - fprintf (shadow_logfd, - _("%s: Cannot lstat %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - fprintf (shadow_logfd, - _("%s: Warning, user %s has no tcb shadow file.\n"), -- Prog, user_newname); -+ shadow_progname, user_newname); - } else { - if (!S_ISREG (filemode.st_mode) || - filemode.st_nlink != 1) { -@@ -500,19 +500,19 @@ shadowtcb_status shadowtcb_move (/*@NULL - _("%s: Emergency: %s's tcb shadow is not a " - "regular file with st_nlink=1.\n" - "The account is left locked.\n"), -- Prog, user_newname); -+ shadow_progname, user_newname); - goto out_free; - } - if (chown (shadow, user_newid, filemode.st_gid) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - if (chmod (shadow, filemode.st_mode & 07777) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - } -@@ -522,7 +522,7 @@ shadowtcb_status shadowtcb_move (/*@NULL - if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), -- Prog, tcbdir, strerror (errno)); -+ shadow_progname, tcbdir, strerror (errno)); - goto out_free; - } - ret = SHADOWTCB_SUCCESS; -@@ -547,7 +547,7 @@ shadowtcb_status shadowtcb_create (const - if (stat (TCB_DIR, &tcbdir_stat) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot stat %s: %s\n"), -- Prog, TCB_DIR, strerror (errno)); -+ shadow_progname, TCB_DIR, strerror (errno)); - return SHADOWTCB_FAILURE; - } - shadowgid = tcbdir_stat.st_gid; -@@ -567,39 +567,39 @@ shadowtcb_status shadowtcb_create (const - if (mkdir (dir, 0700) != 0) { - fprintf (shadow_logfd, - _("%s: mkdir: %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free; - } - fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { - fprintf (shadow_logfd, - _("%s: Cannot open %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - close (fd); - if (chown (shadow, 0, authgid) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), -- Prog, shadow, strerror (errno)); -+ shadow_progname, shadow, strerror (errno)); - goto out_free; - } - if (chown (dir, 0, authgid) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change owner of %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free; - } - if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) { - fprintf (shadow_logfd, - _("%s: Cannot change mode of %s: %s\n"), -- Prog, dir, strerror (errno)); -+ shadow_progname, dir, strerror (errno)); - goto out_free; - } - if ( (shadowtcb_set_user (name) == SHADOWTCB_FAILURE) diff --git a/shadow-4.9-revert-useradd-fix-memleak.patch b/shadow-4.9-revert-useradd-fix-memleak.patch deleted file mode 100644 index e8251f2..0000000 --- a/shadow-4.9-revert-useradd-fix-memleak.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4624e9fca1b02b64e25e8b2280a0186182ab73ba Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Sat, 14 Aug 2021 19:37:24 -0500 -Subject: [PATCH] Revert "useradd.c:fix memleaks of grp" - -In some cases, the value which was being freed is not actually -safe to free. - -Closes #394 - -This reverts commit c44b71cec25d60efc51aec9de3abce1f6efbfcf5. ---- - src/useradd.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index f90127cd..0d3f390d 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -413,7 +413,6 @@ static void get_defaults (void) - } else { - def_group = grp->gr_gid; - def_gname = xstrdup (grp->gr_name); -- gr_free(grp); - } - } - --- -2.31.1 - diff --git a/shadow-4.9-semanage-close-the-selabel-handle.patch b/shadow-4.9-semanage-close-the-selabel-handle.patch deleted file mode 100644 index 11a23e4..0000000 --- a/shadow-4.9-semanage-close-the-selabel-handle.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 234af5cf67fc1a3ba99fc246ba65869a3c416545 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 8 Oct 2021 13:13:13 +0200 -Subject: [PATCH] semanage: close the selabel handle - -Close the selabel handle to update the file_context. This means that the -file_context will be remmaped and used by selabel_lookup() to return -the appropriate context to label the home folder. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1993081 - -Signed-off-by: Iker Pedrosa ---- - lib/prototypes.h | 1 + - lib/selinux.c | 5 +++++ - lib/semanage.c | 1 + - 3 files changed, 7 insertions(+) - -diff --git a/lib/prototypes.h b/lib/prototypes.h -index 1d1586d4..b697e0ec 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -392,6 +392,7 @@ extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const - /* selinux.c */ - #ifdef WITH_SELINUX - extern int set_selinux_file_context (const char *dst_name, mode_t mode); -+extern void reset_selinux_handle (void); - extern int reset_selinux_file_context (void); - extern int check_selinux_permit (const char *perm_name); - #endif -diff --git a/lib/selinux.c b/lib/selinux.c -index c83545f9..b075d4c0 100644 ---- a/lib/selinux.c -+++ b/lib/selinux.c -@@ -50,6 +50,11 @@ static void cleanup(void) - } - } - -+void reset_selinux_handle (void) -+{ -+ cleanup(); -+} -+ - /* - * set_selinux_file_context - Set the security context before any file or - * directory creation. -diff --git a/lib/semanage.c b/lib/semanage.c -index 0d30456a..a5bf9218 100644 ---- a/lib/semanage.c -+++ b/lib/semanage.c -@@ -293,6 +293,7 @@ int set_seuser (const char *login_name, const char *seuser_name) - } - - ret = 0; -+ reset_selinux_handle(); - - done: - semanage_seuser_key_free (key); --- -2.31.1 - diff --git a/shadow-4.9-shadow-progname-default-init.patch b/shadow-4.9-shadow-progname-default-init.patch deleted file mode 100644 index 0c6d616..0000000 --- a/shadow-4.9-shadow-progname-default-init.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff -up shadow-4.9/lib/shadowlog.c.debug3 shadow-4.9/lib/shadowlog.c ---- shadow-4.9/lib/shadowlog.c.debug3 2022-01-10 11:16:31.636261531 +0100 -+++ shadow-4.9/lib/shadowlog.c 2022-01-10 11:16:31.637261538 +0100 -@@ -2,8 +2,8 @@ - - #include "lib/shadowlog_internal.h" - --const char *shadow_progname; --FILE *shadow_logfd; -+const char *shadow_progname = "libshadow"; -+FILE *shadow_logfd = NULL; - - void log_set_progname(const char *progname) - { -diff -up shadow-4.9/libsubid/api.c.debug3 shadow-4.9/libsubid/api.c ---- shadow-4.9/libsubid/api.c.debug3 2022-01-10 11:16:31.637261538 +0100 -+++ shadow-4.9/libsubid/api.c 2022-01-10 11:17:15.431574120 +0100 -@@ -40,17 +40,16 @@ - #include "subid.h" - #include "shadowlog.h" - --const char *Prog = "(libsubid)"; -- - bool libsubid_init(const char *progname, FILE * logfd) - { - FILE *shadow_logfd; - if (progname) { - progname = strdup(progname); -- if (progname) -- Prog = progname; -- else -+ if (!progname) - return false; -+ log_set_progname(progname); -+ } else { -+ log_set_progname("(libsubid)"); - } - - if (logfd) { diff --git a/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch b/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch deleted file mode 100644 index b94fd60..0000000 --- a/shadow-4.9-useradd-avoid-generating-empty-subid-range.patch +++ /dev/null @@ -1,79 +0,0 @@ -diff --git a/src/useradd.c b/src/useradd.c -index baeffb35..9abeea6e 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -142,9 +142,7 @@ static bool is_sub_gid = false; - static bool sub_uid_locked = false; - static bool sub_gid_locked = false; - static uid_t sub_uid_start; /* New subordinate uid range */ --static unsigned long sub_uid_count; - static gid_t sub_gid_start; /* New subordinate gid range */ --static unsigned long sub_gid_count; - #endif /* ENABLE_SUBIDS */ - static bool pw_locked = false; - static bool gr_locked = false; -@@ -234,7 +232,7 @@ static void open_shadow (void); - static void faillog_reset (uid_t); - static void lastlog_reset (uid_t); - static void tallylog_reset (const char *); --static void usr_update (void); -+static void usr_update (unsigned long subuid_count, unsigned long subgid_count); - static void create_home (void); - static void create_mail (void); - static void check_uid_range(int rflg, uid_t user_id); -@@ -2092,7 +2090,7 @@ static void tallylog_reset (const char *user_name) - * usr_update() creates the password file entries for this user - * and will update the group entries if required. - */ --static void usr_update (void) -+static void usr_update (unsigned long subuid_count, unsigned long subgid_count) - { - struct passwd pwent; - struct spwd spent; -@@ -2155,14 +2153,14 @@ static void usr_update (void) - } - #ifdef ENABLE_SUBIDS - if (is_sub_uid && -- (sub_uid_add(user_name, sub_uid_start, sub_uid_count) == 0)) { -+ (sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry\n"), - Prog, sub_uid_dbname ()); - fail_exit (E_SUB_UID_UPDATE); - } - if (is_sub_gid && -- (sub_gid_add(user_name, sub_gid_start, sub_gid_count) == 0)) { -+ (sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry\n"), - Prog, sub_uid_dbname ()); -@@ -2624,16 +2622,16 @@ int main (int argc, char **argv) - } - - #ifdef ENABLE_SUBIDS -- if (is_sub_uid && sub_uid_count != 0) { -- if (find_new_sub_uids(&sub_uid_start, &sub_uid_count) < 0) { -+ if (is_sub_uid && subuid_count != 0) { -+ if (find_new_sub_uids(&sub_uid_start, &subuid_count) < 0) { - fprintf (stderr, - _("%s: can't create subordinate user IDs\n"), - Prog); - fail_exit(E_SUB_UID_UPDATE); - } - } -- if (is_sub_gid && sub_gid_count != 0) { -- if (find_new_sub_gids(&sub_gid_start, &sub_gid_count) < 0) { -+ if (is_sub_gid && subgid_count != 0) { -+ if (find_new_sub_gids(&sub_gid_start, &subgid_count) < 0) { - fprintf (stderr, - _("%s: can't create subordinate group IDs\n"), - Prog); -@@ -2642,7 +2640,7 @@ int main (int argc, char **argv) - } - #endif /* ENABLE_SUBIDS */ - -- usr_update (); -+ usr_update (subuid_count, subgid_count); - - close_files (); - diff --git a/shadow-4.9-useradd-copy-tree-argument.patch b/shadow-4.9-useradd-copy-tree-argument.patch deleted file mode 100644 index f6b9827..0000000 --- a/shadow-4.9-useradd-copy-tree-argument.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/useradd.c b/src/useradd.c -index b463a170..f7c97958 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2704,7 +2704,7 @@ int main (int argc, char **argv) - if (mflg) { - create_home (); - if (home_added) { -- copy_tree (def_template, prefix_user_home, false, false, -+ copy_tree (def_template, prefix_user_home, false, true, - (uid_t)-1, user_id, (gid_t)-1, user_gid); - } else { - fprintf (stderr, diff --git a/shadow-4.9-usermod-allow-all-group-types.patch b/shadow-4.9-usermod-allow-all-group-types.patch deleted file mode 100644 index fada15e..0000000 --- a/shadow-4.9-usermod-allow-all-group-types.patch +++ /dev/null @@ -1,322 +0,0 @@ -From e481437ab9ebe9a8bf8fbaabe986d42b2f765991 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Tue, 3 Aug 2021 08:57:20 +0200 -Subject: [PATCH] usermod: allow all group types with -G option - -The only way of removing a group from the supplementary list is to use --G option, and list all groups that the user is a member of except for -the one that wants to be removed. The problem lies when there's a user -that contains both local and remote groups, and the group to be removed -is a local one. As we need to include the remote group with -G option -the command will fail. - -This reverts commit 140510de9de4771feb3af1d859c09604043a4c9b. This way, -it would be possible to remove the remote groups from the supplementary -list. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1967641 -Resolves: https://github.com/shadow-maint/shadow/issues/338 - -Signed-off-by: Iker Pedrosa ---- - src/usermod.c | 220 ++++++++++++++++++-------------------------------- - 1 file changed, 77 insertions(+), 143 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 03bb9b9d..a0c03afa 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -187,7 +187,6 @@ static bool sub_gid_locked = false; - static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, - long int date); - static int get_groups (char *); --static struct group * get_local_group (char * grp_name); - static /*@noreturn@*/void usage (int status); - static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); -@@ -201,9 +200,7 @@ static void grp_update (void); - - static void process_flags (int, char **); - static void close_files (void); --static void close_group_files (void); - static void open_files (void); --static void open_group_files (void); - static void usr_update (void); - static void move_home (void); - static void update_lastlog (void); -@@ -260,11 +257,6 @@ static int get_groups (char *list) - return 0; - } - -- /* -- * Open the group files -- */ -- open_group_files (); -- - /* - * So long as there is some data to be converted, strip off each - * name and look it up. A mix of numerical and string values for -@@ -284,7 +276,7 @@ static int get_groups (char *list) - * Names starting with digits are treated as numerical GID - * values, otherwise the string is looked up as is. - */ -- grp = get_local_group (list); -+ grp = prefix_getgr_nam_gid (list); - - /* - * There must be a match, either by GID value or by -@@ -334,8 +326,6 @@ static int get_groups (char *list) - gr_free ((struct group *)grp); - } while (NULL != list); - -- close_group_files (); -- - user_groups[ngroups] = (char *) 0; - - /* -@@ -348,44 +338,6 @@ static int get_groups (char *list) - return 0; - } - --/* -- * get_local_group - checks if a given group name exists locally -- * -- * get_local_group() checks if a given group name exists locally. -- * If the name exists the group information is returned, otherwise NULL is -- * returned. -- */ --static struct group * get_local_group(char * grp_name) --{ -- const struct group *grp; -- struct group *result_grp = NULL; -- long long int gid; -- char *endptr; -- -- gid = strtoll (grp_name, &endptr, 10); -- if ( ('\0' != *grp_name) -- && ('\0' == *endptr) -- && (ERANGE != errno) -- && (gid == (gid_t)gid)) { -- grp = gr_locate_gid ((gid_t) gid); -- } -- else { -- grp = gr_locate(grp_name); -- } -- -- if (grp != NULL) { -- result_grp = __gr_dup (grp); -- if (NULL == result_grp) { -- fprintf (stderr, -- _("%s: Out of memory. Cannot find group '%s'.\n"), -- Prog, grp_name); -- fail_exit (E_GRP_UPDATE); -- } -- } -- -- return result_grp; --} -- - #ifdef ENABLE_SUBIDS - struct ulong_range - { -@@ -1523,7 +1475,50 @@ static void close_files (void) - } - - if (Gflg || lflg) { -- close_group_files (); -+ if (gr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ gr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_close () == 0) { -+ fprintf (stderr, -+ _("%s: failure while writing changes to %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failure while writing changes to %s", -+ sgr_dbname ())); -+ fail_exit (E_GRP_UPDATE); -+ } -+ } -+#endif -+#ifdef SHADOWGRP -+ if (is_shadow_grp) { -+ if (sgr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, sgr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ sgr_dbname ())); -+ /* continue */ -+ } -+ } -+#endif -+ if (gr_unlock () == 0) { -+ fprintf (stderr, -+ _("%s: failed to unlock %s\n"), -+ Prog, gr_dbname ()); -+ SYSLOG ((LOG_ERR, -+ "failed to unlock %s", -+ gr_dbname ())); -+ /* continue */ -+ } - } - - if (is_shadow_pwd) { -@@ -1592,60 +1587,6 @@ static void close_files (void) - #endif - } - --/* -- * close_group_files - close all of the files that were opened -- * -- * close_group_files() closes all of the files that were opened related -- * with groups. This causes any modified entries to be written out. -- */ --static void close_group_files (void) --{ -- if (gr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_close () == 0) { -- fprintf (stderr, -- _("%s: failure while writing changes to %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failure while writing changes to %s", -- sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -- } -- } --#endif --#ifdef SHADOWGRP -- if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, sgr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- sgr_dbname ())); -- /* continue */ -- } -- } --#endif -- if (gr_unlock () == 0) { -- fprintf (stderr, -- _("%s: failed to unlock %s\n"), -- Prog, gr_dbname ()); -- SYSLOG ((LOG_ERR, -- "failed to unlock %s", -- gr_dbname ())); -- /* continue */ -- } --} -- - /* - * open_files - lock and open the password files - * -@@ -1681,7 +1622,38 @@ static void open_files (void) - } - - if (Gflg || lflg) { -- open_group_files (); -+ /* -+ * Lock and open the group file. This will load all of the -+ * group entries. -+ */ -+ if (gr_lock () == 0) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ gr_locked = true; -+ if (gr_open (O_CREAT | O_RDWR) == 0) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+#ifdef SHADOWGRP -+ if (is_shadow_grp && (sgr_lock () == 0)) { -+ fprintf (stderr, -+ _("%s: cannot lock %s; try again later.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ sgr_locked = true; -+ if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -+ fprintf (stderr, -+ _("%s: cannot open %s\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+#endif - } - #ifdef ENABLE_SUBIDS - if (vflg || Vflg) { -@@ -1717,44 +1689,6 @@ static void open_files (void) - #endif /* ENABLE_SUBIDS */ - } - --/* -- * open_group_files - lock and open the group files -- * -- * open_group_files() loads all of the group entries. -- */ --static void open_group_files (void) --{ -- if (gr_lock () == 0) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- gr_locked = true; -- if (gr_open (O_CREAT | O_RDWR) == 0) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- --#ifdef SHADOWGRP -- if (is_shadow_grp && (sgr_lock () == 0)) { -- fprintf (stderr, -- _("%s: cannot lock %s; try again later.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -- sgr_locked = true; -- if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { -- fprintf (stderr, -- _("%s: cannot open %s\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } --#endif --} -- - /* - * usr_update - create the user entries - * --- -2.31.1 - diff --git a/shadow-utils.spec b/shadow-utils.spec index bcbadf8..16ec56c 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.9 -Release: 10%{?dist} +Version: 4.11.1 +Release: 1%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -18,11 +18,9 @@ Source6: shadow-utils.HOME_MODE.xml ### Patches ### # Misc small changes - most probably non-upstreamable -Patch0: shadow-4.9-redhat.patch +Patch0: shadow-4.11.1-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable Patch1: shadow-4.8-goodname.patch -# https://github.com/shadow-maint/shadow/commit/09c752f00f9dfc610f66d68be38c9e5be8ca7f15 -Patch2: shadow-4.9-move-create-home.patch # SElinux related - upstreamability unknown Patch3: shadow-4.9-default-range.patch # Misc manual page changes - non-upstreamable @@ -32,50 +30,21 @@ Patch5: shadow-4.2.1-date-parsing.patch # Additional error message - could be upstreamed Patch6: shadow-4.6-move-home.patch # Audit message changes - upstreamability unknown -Patch7: shadow-4.9-audit-update.patch +Patch7: shadow-4.11.1-audit-update.patch # Changes related to password unlocking - could be upstreamed Patch8: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown Patch9: shadow-4.8-selinux-perms.patch -# Handle NULL return from *time funcs - could be upstreamed -Patch10: shadow-4.9-null-tm.patch +# Handle NULL return from *time funcs - upstreamable +Patch10: shadow-4.11.1-null-tm.patch # Handle /etc/passwd corruption - could be upstreamed Patch11: shadow-4.8-long-entry.patch # Limit uid/gid allocation to non-zero - could be upstreamed Patch12: shadow-4.6-sysugid-min-limit.patch # Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown Patch13: shadow-4.8-ignore-login-prompt.patch -# https://github.com/shadow-maint/shadow/commit/c6847011e8b656adacd9a0d2a78418cad0de34cb -Patch14: shadow-4.9-newuidmap-libeconf-dependency.patch -# https://github.com/shadow-maint/shadow/commit/e481437ab9ebe9a8bf8fbaabe986d42b2f765991 -Patch15: shadow-4.9-usermod-allow-all-group-types.patch -# https://github.com/shadow-maint/shadow/commit/9dd720a28578eef5be8171697aae0906e4c53249 -Patch16: shadow-4.9-useradd-avoid-generating-empty-subid-range.patch -# https://github.com/shadow-maint/shadow/commit/234e8fa7b134d1ebabfdad980a3ae5b63c046c62 -Patch17: shadow-4.9-libmisc-fix-default-value-in-SHA_get_salt_rounds.patch -# https://github.com/shadow-maint/shadow/commit/234af5cf67fc1a3ba99fc246ba65869a3c416545 -Patch18: shadow-4.9-semanage-close-the-selabel-handle.patch -# https://github.com/shadow-maint/shadow/commit/4624e9fca1b02b64e25e8b2280a0186182ab73ba -Patch19: shadow-4.9-revert-useradd-fix-memleak.patch -# https://github.com/shadow-maint/shadow/commit/06eb4e4d76ac7f1ac86e68a89b2dc9be7c7323a2 -Patch20: shadow-4.9-useradd-copy-tree-argument.patch -# https://github.com/shadow-maint/shadow/commit/d8e54618feea201987c1f3cb402ed50d1d8b604f -Patch21: shadow-4.9-pwck-fix-segfault-when-calling-fprintf.patch -# https://github.com/shadow-maint/shadow/commit/497e90751bc0d95cc998b0f06305040563903948 -Patch22: shadow-4.9-newgrp-fix-segmentation-fault.patch -# https://github.com/shadow-maint/shadow/commit/3b6ccf642c6bb2b7db087f09ee563ae9318af734 -Patch23: shadow-4.9-getsubids.patch -# https://github.com/shadow-maint/shadow/commit/a757b458ffb4fb9a40bcbb4f7869449431c67f83 -Patch24: shadow-4.9-groupdel-fix-sigsegv-when-passwd-does-not-exist.patch -# https://github.com/shadow-maint/shadow/commit/79157cbad87f42cdc2068d72e798488572c68bb2 -Patch25: shadow-4.9-make-shadow-logfd-and-prog-not-extern.patch -# https://github.com/shadow-maint/shadow/commit/0e6fe5e728a45baff3977d73e81a27adb6ae30c6 -Patch26: shadow-4.9-rename-prog-to-shadow-progname.patch -# https://github.com/shadow-maint/shadow/commit/2b0bdef6f9a18382e92b0fb6d893c4339123ffac -# https://github.com/shadow-maint/shadow/commit/9750fd681919ed558a9b044248a284d567cddf1a -Patch27: shadow-4.9-shadow-progname-default-init.patch # https://github.com/shadow-maint/shadow/commit/e101219ad71de11da3fdd1b3ec2620fd1a97b92c -Patch28: shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch +Patch14: shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -129,6 +98,7 @@ Utility library that provides a way to manage subid ranges. %package subid-devel Summary: Development package for shadow-utils-subid License: BSD and GPLv2+ +Requires: shadow-utils-subid = %{version}-%{release} %description subid-devel Development files for shadow-utils-subid. @@ -137,7 +107,6 @@ Development files for shadow-utils-subid. %setup -q -n shadow-%{version} %patch0 -p1 -b .redhat %patch1 -p1 -b .goodname -%patch2 -p1 -b .move-create-home %patch3 -p1 -b .default-range %patch4 -p1 -b .manfix %patch5 -p1 -b .date-parsing @@ -149,21 +118,7 @@ Development files for shadow-utils-subid. %patch11 -p1 -b .long-entry %patch12 -p1 -b .sysugid-min-limit %patch13 -p1 -b .login-prompt -%patch14 -p1 -b .newuidmap-libeconf-dependency -%patch15 -p1 -b .usermod-allow-all-group-types -%patch16 -p1 -b .useradd-avoid-generating-empty-subid-range -%patch17 -p1 -b .libmisc-fix-default-value-in-SHA_get_salt_rounds -%patch18 -p1 -b .semanage-close-the-selabel-handle -%patch19 -p1 -b .revert-useradd-fix-memleak -%patch20 -p1 -b .useradd-copy-tree-argument -%patch21 -p1 -b .pwck-fix-segfault-when-calling-fprintf -%patch22 -p1 -b .newgrp-fix-segmentation-fault -%patch23 -p1 -b .getsubids -%patch24 -p1 -b .groupdel-fix-sigsegv-when-passwd-does-not-exist -%patch25 -p1 -b .make-shadow-logfd-and-prog-not-extern -%patch26 -p1 -b .rename-prog-to-shadow-progname -%patch27 -p1 -b .shadow-progname-default-init -%patch28 -p1 -b .nss-get-shadow-logfd-with-log-get-logfd +%patch14 -p1 -b .nss-get-shadow-logfd-with-log-get-logfd iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -275,8 +230,9 @@ echo $(ls) mkdir -p $RPM_BUILD_ROOT/%{includesubiddir} install -m 644 libsubid/subid.h $RPM_BUILD_ROOT/%{includesubiddir}/ -# Remove .la files created by libsubid +# Remove .la and .a files created by libsubid rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la +rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %files -f shadow.lang %doc NEWS doc/HOWTO README @@ -336,6 +292,11 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la %{_libdir}/libsubid.so %changelog +* Tue Jan 25 2022 Iker Pedrosa - 2:4.11.1-1 +- Rebase to version 4.11.1 (#2034038) +- Fix release sources +- Add explicit subid requirement for subid-devel + * Sat Jan 22 2022 Fedora Release Engineering - 2:4.9-10 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild From a986f4a036f3f055e0b5fcd5bc48ea6415317bcf Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 26 Jan 2022 09:39:55 +0100 Subject: [PATCH 042/118] Add forgotten sources Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ sources | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index cc68ade..e368bdf 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.8.1.tar.xz.asc /shadow-4.9.tar.xz /shadow-4.9.tar.xz.asc +/shadow-4.11.1.tar.xz +/shadow-4.11.1.tar.xz.asc diff --git a/sources b/sources index 803fac0..53a4fb0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.9.tar.xz) = 254cda49bb14505a7604821e7fa898bf4bf317d648e9ddc881ab80a6860d52053dfffacad6feab87c7d16608c35ed6b6cee99e7757eac930da3a7b31cdcd4b95 -SHA512 (shadow-4.9.tar.xz.asc) = 16c0ff7be263c9d471b05656c9a1d14da8ec9b17544910323ca6ab854126d1a03ece221e0caf610e65a9b1d080b4cd1b8b46973f20e3ae45ea0e5581ce6c90d9 +SHA512 (shadow-4.11.1.tar.xz) = 12fbe4d6ac929ad3c21525ed0f1026b5b678ccec9762f2ec7e611d9c180934def506325f2835fb750dd30af035b592f827ff151cd6e4c805aaaf8e01425c279f +SHA512 (shadow-4.11.1.tar.xz.asc) = 4594189678cc9bcc8831f62a5d42c605b085be4a3b540429d7c800f4304e2e8fe04358547917eb90c1513646fade7c714611bfdc98af7dec5321a3dc3e65c4fd From 5ba2bc90cc868264bfea084504bee28e45ccbb79 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 10 Feb 2022 17:46:56 +0100 Subject: [PATCH 043/118] Fix explicit subid requirement for subid-devel Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 16ec56c..c90978b 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.11.1 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -98,7 +98,7 @@ Utility library that provides a way to manage subid ranges. %package subid-devel Summary: Development package for shadow-utils-subid License: BSD and GPLv2+ -Requires: shadow-utils-subid = %{version}-%{release} +Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} %description subid-devel Development files for shadow-utils-subid. @@ -292,6 +292,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Feb 10 2022 Iker Pedrosa - 2:4.11.1-2 +- Fix explicit subid requirement for subid-devel + * Tue Jan 25 2022 Iker Pedrosa - 2:4.11.1-1 - Rebase to version 4.11.1 (#2034038) - Fix release sources From 71c99ba5b1ae994e34e41111733227798b791f40 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 23 Jul 2022 08:29:04 +0000 Subject: [PATCH 044/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index c90978b..98efee1 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.11.1 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -292,6 +292,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jul 23 2022 Fedora Release Engineering - 2:4.11.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + * Thu Feb 10 2022 Iker Pedrosa - 2:4.11.1-2 - Fix explicit subid requirement for subid-devel From 97547bc00ae47970bfc9a99209083fff0f3d7931 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 1 Aug 2022 11:13:56 +0200 Subject: [PATCH 045/118] useradd: modify check ID range for system users Resolves: #2093692 Signed-off-by: Iker Pedrosa --- ...dify-check-ID-range-for-system-users.patch | 40 +++++++++++++++++++ shadow-utils.spec | 8 +++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch diff --git a/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch b/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch new file mode 100644 index 0000000..dead628 --- /dev/null +++ b/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch @@ -0,0 +1,40 @@ +From f1f1678e13aa3ae49bdb139efaa2c5bc53dcfe92 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Tue, 4 Jan 2022 13:06:00 +0100 +Subject: [PATCH] useradd: modify check ID range for system users + +useradd warns that a system user ID less than SYS_UID_MIN is outside the +expected range, even though that ID has been specifically selected with +the "-u" option. + +In my opinion all the user ID's below SYS_UID_MAX are for the system, +thus I change the condition to take that into account. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004911 + +Signed-off-by: Iker Pedrosa +--- + src/useradd.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 34376fa5..4c71c38a 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2409,11 +2409,9 @@ static void check_uid_range(int rflg, uid_t user_id) + uid_t uid_min ; + uid_t uid_max ; + if (rflg) { +- uid_min = (uid_t)getdef_ulong("SYS_UID_MIN",101UL); + uid_max = (uid_t)getdef_ulong("SYS_UID_MAX",getdef_ulong("UID_MIN",1000UL)-1); +- if (uid_min <= uid_max) { +- if (user_id < uid_min || user_id >uid_max) +- fprintf(stderr, _("%s warning: %s's uid %d outside of the SYS_UID_MIN %d and SYS_UID_MAX %d range.\n"), Prog, user_name, user_id, uid_min, uid_max); ++ if (user_id > uid_max) { ++ fprintf(stderr, _("%s warning: %s's uid %d is greater than SYS_UID_MAX %d\n"), Prog, user_name, user_id, uid_max); + } + }else{ + uid_min = (uid_t)getdef_ulong("UID_MIN", 1000UL); +-- +2.37.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 98efee1..660f777 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.11.1 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -45,6 +45,8 @@ Patch12: shadow-4.6-sysugid-min-limit.patch Patch13: shadow-4.8-ignore-login-prompt.patch # https://github.com/shadow-maint/shadow/commit/e101219ad71de11da3fdd1b3ec2620fd1a97b92c Patch14: shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch +# https://github.com/shadow-maint/shadow/commit/f1f1678e13aa3ae49bdb139efaa2c5bc53dcfe92 +Patch15: shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -119,6 +121,7 @@ Development files for shadow-utils-subid. %patch12 -p1 -b .sysugid-min-limit %patch13 -p1 -b .login-prompt %patch14 -p1 -b .nss-get-shadow-logfd-with-log-get-logfd +%patch15 -p1 -b .useradd-modify-check-ID-range-for-system-users iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -292,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Aug 1 2022 Iker Pedrosa - 2:4.11.1-4 +- useradd: modify check ID range for system users. Resolves: #2093692 + * Sat Jul 23 2022 Fedora Release Engineering - 2:4.11.1-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild From cd421e05aeb4f13565d980dc0a45f664dfd0ec09 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 23 Aug 2022 09:25:47 +0200 Subject: [PATCH 046/118] Rebase to version 4.12.3 Resolves: #2117809 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + ...dify-check-ID-range-for-system-users.patch | 40 ---------------- ...name.patch => shadow-4.12.3-goodname.patch | 28 +++++------ ...ry.patch => shadow-4.12.3-long-entry.patch | 48 +++++++++---------- ...redhat.patch => shadow-4.12.3-redhat.patch | 23 ++++----- ...patch => shadow-4.12.3-selinux-perms.patch | 34 ++++++------- ...-get-shadow-logfd-with-log-get-logfd.patch | 48 ------------------- shadow-utils.spec | 21 ++++---- sources | 4 +- 9 files changed, 78 insertions(+), 170 deletions(-) delete mode 100644 shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch rename shadow-4.8-goodname.patch => shadow-4.12.3-goodname.patch (77%) rename shadow-4.8-long-entry.patch => shadow-4.12.3-long-entry.patch (54%) rename shadow-4.11.1-redhat.patch => shadow-4.12.3-redhat.patch (53%) rename shadow-4.8-selinux-perms.patch => shadow-4.12.3-selinux-perms.patch (84%) delete mode 100644 shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch diff --git a/.gitignore b/.gitignore index e368bdf..7113c48 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.9.tar.xz.asc /shadow-4.11.1.tar.xz /shadow-4.11.1.tar.xz.asc +/shadow-4.12.3.tar.xz +/shadow-4.12.3.tar.xz.asc diff --git a/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch b/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch deleted file mode 100644 index dead628..0000000 --- a/shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch +++ /dev/null @@ -1,40 +0,0 @@ -From f1f1678e13aa3ae49bdb139efaa2c5bc53dcfe92 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Tue, 4 Jan 2022 13:06:00 +0100 -Subject: [PATCH] useradd: modify check ID range for system users - -useradd warns that a system user ID less than SYS_UID_MIN is outside the -expected range, even though that ID has been specifically selected with -the "-u" option. - -In my opinion all the user ID's below SYS_UID_MAX are for the system, -thus I change the condition to take that into account. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004911 - -Signed-off-by: Iker Pedrosa ---- - src/useradd.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 34376fa5..4c71c38a 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2409,11 +2409,9 @@ static void check_uid_range(int rflg, uid_t user_id) - uid_t uid_min ; - uid_t uid_max ; - if (rflg) { -- uid_min = (uid_t)getdef_ulong("SYS_UID_MIN",101UL); - uid_max = (uid_t)getdef_ulong("SYS_UID_MAX",getdef_ulong("UID_MIN",1000UL)-1); -- if (uid_min <= uid_max) { -- if (user_id < uid_min || user_id >uid_max) -- fprintf(stderr, _("%s warning: %s's uid %d outside of the SYS_UID_MIN %d and SYS_UID_MAX %d range.\n"), Prog, user_name, user_id, uid_min, uid_max); -+ if (user_id > uid_max) { -+ fprintf(stderr, _("%s warning: %s's uid %d is greater than SYS_UID_MAX %d\n"), Prog, user_name, user_id, uid_max); - } - }else{ - uid_min = (uid_t)getdef_ulong("UID_MIN", 1000UL); --- -2.37.1 - diff --git a/shadow-4.8-goodname.patch b/shadow-4.12.3-goodname.patch similarity index 77% rename from shadow-4.8-goodname.patch rename to shadow-4.12.3-goodname.patch index f3c18d5..2376674 100644 --- a/shadow-4.8-goodname.patch +++ b/shadow-4.12.3-goodname.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.8/libmisc/chkname.c.goodname shadow-4.8/libmisc/chkname.c ---- shadow-4.8/libmisc/chkname.c.goodname 2020-01-13 09:44:41.968507996 +0100 -+++ shadow-4.8/libmisc/chkname.c 2020-01-13 09:46:27.863727732 +0100 -@@ -55,26 +55,44 @@ static bool is_valid_name (const char *n +diff -up shadow-4.12.3/libmisc/chkname.c.goodname shadow-4.12.3/libmisc/chkname.c +--- shadow-4.12.3/libmisc/chkname.c.goodname 2022-06-19 16:16:48.000000000 +0200 ++++ shadow-4.12.3/libmisc/chkname.c 2022-08-22 16:00:27.646087971 +0200 +@@ -32,26 +32,44 @@ static bool is_valid_name (const char *n } /* @@ -56,12 +56,12 @@ diff -up shadow-4.8/libmisc/chkname.c.goodname shadow-4.8/libmisc/chkname.c } bool is_valid_user_name (const char *name) -diff -up shadow-4.8/man/groupadd.8.xml.goodname shadow-4.8/man/groupadd.8.xml ---- shadow-4.8/man/groupadd.8.xml.goodname 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/man/groupadd.8.xml 2020-01-13 09:44:41.968507996 +0100 -@@ -273,10 +273,12 @@ - - CAVEATS +diff -up shadow-4.12.3/man/groupadd.8.xml.goodname shadow-4.12.3/man/groupadd.8.xml +--- shadow-4.12.3/man/groupadd.8.xml.goodname 2022-08-22 16:00:27.646087971 +0200 ++++ shadow-4.12.3/man/groupadd.8.xml 2022-08-22 16:01:59.301779733 +0200 +@@ -64,10 +64,12 @@ + files as needed. + - Groupnames must start with a lower case letter or an underscore, - followed by lower case letters, digits, underscores, or dashes. @@ -76,10 +76,10 @@ diff -up shadow-4.8/man/groupadd.8.xml.goodname shadow-4.8/man/groupadd.8.xml Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long. -diff -up shadow-4.8/man/useradd.8.xml.goodname shadow-4.8/man/useradd.8.xml ---- shadow-4.8/man/useradd.8.xml.goodname 2019-10-05 03:23:58.000000000 +0200 -+++ shadow-4.8/man/useradd.8.xml 2020-01-13 09:44:41.968507996 +0100 -@@ -661,10 +661,14 @@ +diff -up shadow-4.12.3/man/useradd.8.xml.goodname shadow-4.12.3/man/useradd.8.xml +--- shadow-4.12.3/man/useradd.8.xml.goodname 2022-08-22 14:46:57.000000000 +0200 ++++ shadow-4.12.3/man/useradd.8.xml 2022-08-22 16:00:27.646087971 +0200 +@@ -692,10 +692,14 @@ diff --git a/shadow-4.8-long-entry.patch b/shadow-4.12.3-long-entry.patch similarity index 54% rename from shadow-4.8-long-entry.patch rename to shadow-4.12.3-long-entry.patch index 64d9636..9dc5ef2 100644 --- a/shadow-4.8-long-entry.patch +++ b/shadow-4.12.3-long-entry.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.8/lib/defines.h.long-entry shadow-4.8/lib/defines.h ---- shadow-4.8/lib/defines.h.long-entry 2020-01-13 10:29:45.288957339 +0100 -+++ shadow-4.8/lib/defines.h 2020-01-13 10:30:47.482902954 +0100 -@@ -388,6 +388,9 @@ extern char *strerror (); +diff -up shadow-4.12.3/lib/defines.h.long-entry shadow-4.12.3/lib/defines.h +--- shadow-4.12.3/lib/defines.h.long-entry 2022-08-18 23:51:37.000000000 +0200 ++++ shadow-4.12.3/lib/defines.h 2022-08-22 16:12:27.412522768 +0200 +@@ -335,6 +335,9 @@ extern char *strerror (); # endif #endif @@ -11,10 +11,10 @@ diff -up shadow-4.8/lib/defines.h.long-entry shadow-4.8/lib/defines.h #ifdef HAVE_SECURE_GETENV # define shadow_getenv(name) secure_getenv(name) # else -diff -up shadow-4.8/lib/pwio.c.long-entry shadow-4.8/lib/pwio.c ---- shadow-4.8/lib/pwio.c.long-entry 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/pwio.c 2020-01-13 10:29:45.288957339 +0100 -@@ -79,7 +79,10 @@ static int passwd_put (const void *ent, +diff -up shadow-4.12.3/lib/pwio.c.long-entry shadow-4.12.3/lib/pwio.c +--- shadow-4.12.3/lib/pwio.c.long-entry 2022-06-19 16:16:48.000000000 +0200 ++++ shadow-4.12.3/lib/pwio.c 2022-08-22 16:12:27.412522768 +0200 +@@ -56,7 +56,10 @@ static int passwd_put (const void *ent, || (pw->pw_gid == (gid_t)-1) || (valid_field (pw->pw_gecos, ":\n") == -1) || (valid_field (pw->pw_dir, ":\n") == -1) @@ -26,19 +26,19 @@ diff -up shadow-4.8/lib/pwio.c.long-entry shadow-4.8/lib/pwio.c return -1; } -diff -up shadow-4.8/lib/sgetpwent.c.long-entry shadow-4.8/lib/sgetpwent.c ---- shadow-4.8/lib/sgetpwent.c.long-entry 2019-10-05 03:23:58.000000000 +0200 -+++ shadow-4.8/lib/sgetpwent.c 2020-01-13 10:29:45.288957339 +0100 -@@ -57,7 +57,7 @@ +diff -up shadow-4.12.3/lib/sgetpwent.c.long-entry shadow-4.12.3/lib/sgetpwent.c +--- shadow-4.12.3/lib/sgetpwent.c.long-entry 2022-08-09 00:30:40.000000000 +0200 ++++ shadow-4.12.3/lib/sgetpwent.c 2022-08-22 16:14:10.955309200 +0200 +@@ -34,7 +34,7 @@ struct passwd *sgetpwent (const char *buf) { static struct passwd pwent; - static char pwdbuf[1024]; + static char pwdbuf[PASSWD_ENTRY_MAX_LENGTH]; - register int i; - register char *cp; + int i; + char *cp; char *fields[NFIELDS]; -@@ -67,8 +67,10 @@ struct passwd *sgetpwent (const char *bu +@@ -44,8 +44,10 @@ struct passwd *sgetpwent (const char *bu * the password structure remain valid. */ @@ -50,10 +50,10 @@ diff -up shadow-4.8/lib/sgetpwent.c.long-entry shadow-4.8/lib/sgetpwent.c strcpy (pwdbuf, buf); /* -diff -up shadow-4.8/lib/sgetspent.c.long-entry shadow-4.8/lib/sgetspent.c ---- shadow-4.8/lib/sgetspent.c.long-entry 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/sgetspent.c 2020-01-13 10:29:45.289957322 +0100 -@@ -48,7 +48,7 @@ +diff -up shadow-4.12.3/lib/sgetspent.c.long-entry shadow-4.12.3/lib/sgetspent.c +--- shadow-4.12.3/lib/sgetspent.c.long-entry 2022-06-19 16:16:54.000000000 +0200 ++++ shadow-4.12.3/lib/sgetspent.c 2022-08-22 16:12:27.413522776 +0200 +@@ -25,7 +25,7 @@ */ struct spwd *sgetspent (const char *string) { @@ -62,7 +62,7 @@ diff -up shadow-4.8/lib/sgetspent.c.long-entry shadow-4.8/lib/sgetspent.c static struct spwd spwd; char *fields[FIELDS]; char *cp; -@@ -61,6 +61,7 @@ struct spwd *sgetspent (const char *stri +@@ -37,6 +37,7 @@ struct spwd *sgetspent (const char *stri */ if (strlen (string) >= sizeof spwbuf) { @@ -70,10 +70,10 @@ diff -up shadow-4.8/lib/sgetspent.c.long-entry shadow-4.8/lib/sgetspent.c return 0; /* fail if too long */ } strcpy (spwbuf, string); -diff -up shadow-4.8/lib/shadowio.c.long-entry shadow-4.8/lib/shadowio.c ---- shadow-4.8/lib/shadowio.c.long-entry 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8/lib/shadowio.c 2020-01-13 10:29:45.289957322 +0100 -@@ -79,7 +79,9 @@ static int shadow_put (const void *ent, +diff -up shadow-4.12.3/lib/shadowio.c.long-entry shadow-4.12.3/lib/shadowio.c +--- shadow-4.12.3/lib/shadowio.c.long-entry 2022-06-19 16:16:48.000000000 +0200 ++++ shadow-4.12.3/lib/shadowio.c 2022-08-22 16:12:27.413522776 +0200 +@@ -56,7 +56,9 @@ static int shadow_put (const void *ent, if ( (NULL == sp) || (valid_field (sp->sp_namp, ":\n") == -1) diff --git a/shadow-4.11.1-redhat.patch b/shadow-4.12.3-redhat.patch similarity index 53% rename from shadow-4.11.1-redhat.patch rename to shadow-4.12.3-redhat.patch index e5e6c60..48c591d 100644 --- a/shadow-4.11.1-redhat.patch +++ b/shadow-4.12.3-redhat.patch @@ -1,6 +1,6 @@ -diff -up shadow-4.11.1/src/useradd.c.redhat shadow-4.11.1/src/useradd.c ---- shadow-4.11.1/src/useradd.c.redhat 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/useradd.c 2022-01-03 14:53:12.988484829 +0100 +diff -up shadow-4.12.3/src/useradd.c.redhat shadow-4.12.3/src/useradd.c +--- shadow-4.12.3/src/useradd.c.redhat 2022-08-06 18:22:45.000000000 +0200 ++++ shadow-4.12.3/src/useradd.c 2022-08-22 15:57:19.034664441 +0200 @@ -82,7 +82,7 @@ const char *Prog; static gid_t def_group = 1000; static const char *def_gname = "other"; @@ -19,19 +19,16 @@ diff -up shadow-4.11.1/src/useradd.c.redhat shadow-4.11.1/src/useradd.c static uid_t user_id; static gid_t user_gid; static const char *user_comment = ""; -@@ -1219,9 +1219,9 @@ static void process_flags (int argc, cha +@@ -1227,7 +1227,7 @@ static void process_flags (int argc, cha + {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, +- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U" ++ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:U" #ifdef WITH_SELINUX -- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:UZ:", -+ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:UZ:", - #else /* !WITH_SELINUX */ -- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U", -+ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:U", - #endif /* !WITH_SELINUX */ - long_options, NULL)) != -1) { - switch (c) { -@@ -1378,6 +1378,7 @@ static void process_flags (int argc, cha + "Z:" + #endif /* WITH_SELINUX */ +@@ -1395,6 +1395,7 @@ static void process_flags (int argc, cha case 'M': Mflg = true; break; diff --git a/shadow-4.8-selinux-perms.patch b/shadow-4.12.3-selinux-perms.patch similarity index 84% rename from shadow-4.8-selinux-perms.patch rename to shadow-4.12.3-selinux-perms.patch index dfb32ec..f396455 100644 --- a/shadow-4.8-selinux-perms.patch +++ b/shadow-4.12.3-selinux-perms.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c ---- shadow-4.8/src/chgpasswd.c.selinux-perms 2019-12-01 18:02:43.000000000 +0100 -+++ shadow-4.8/src/chgpasswd.c 2020-01-13 10:21:44.558107260 +0100 -@@ -39,6 +39,13 @@ +diff -up shadow-4.12.3/src/chgpasswd.c.selinux-perms shadow-4.12.3/src/chgpasswd.c +--- shadow-4.12.3/src/chgpasswd.c.selinux-perms 2022-06-19 16:16:48.000000000 +0200 ++++ shadow-4.12.3/src/chgpasswd.c 2022-08-22 16:09:02.006970030 +0200 +@@ -16,6 +16,13 @@ #include #include #include @@ -15,7 +15,7 @@ diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM #include "pam_defs.h" -@@ -80,6 +87,9 @@ static bool sgr_locked = false; +@@ -61,6 +68,9 @@ static bool sgr_locked = false; #endif static bool gr_locked = false; @@ -25,7 +25,7 @@ diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c /* local function prototypes */ static void fail_exit (int code); static /*@noreturn@*/void usage (int status); -@@ -334,6 +344,63 @@ static void check_perms (void) +@@ -318,6 +328,63 @@ static void check_perms (void) #endif /* ACCT_TOOLS_SETUID */ } @@ -89,7 +89,7 @@ diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c /* * open_files - lock and open the group databases */ -@@ -427,6 +494,7 @@ int main (int argc, char **argv) +@@ -411,6 +478,7 @@ int main (int argc, char **argv) const struct group *gr; struct group newgr; @@ -97,7 +97,7 @@ diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c int errors = 0; int line = 0; -@@ -436,12 +504,37 @@ int main (int argc, char **argv) +@@ -422,12 +490,37 @@ int main (int argc, char **argv) (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); @@ -135,10 +135,10 @@ diff -up shadow-4.8/src/chgpasswd.c.selinux-perms shadow-4.8/src/chgpasswd.c check_perms (); #ifdef SHADOWGRP -diff -up shadow-4.8/src/chpasswd.c.selinux-perms shadow-4.8/src/chpasswd.c ---- shadow-4.8/src/chpasswd.c.selinux-perms 2019-12-01 18:02:43.000000000 +0100 -+++ shadow-4.8/src/chpasswd.c 2020-01-13 10:21:44.558107260 +0100 -@@ -39,6 +39,13 @@ +diff -up shadow-4.12.3/src/chpasswd.c.selinux-perms shadow-4.12.3/src/chpasswd.c +--- shadow-4.12.3/src/chpasswd.c.selinux-perms 2022-06-19 16:16:48.000000000 +0200 ++++ shadow-4.12.3/src/chpasswd.c 2022-08-22 16:10:56.702835681 +0200 +@@ -16,6 +16,13 @@ #include #include #include @@ -152,7 +152,7 @@ diff -up shadow-4.8/src/chpasswd.c.selinux-perms shadow-4.8/src/chpasswd.c #ifdef USE_PAM #include "pam_defs.h" #endif /* USE_PAM */ -@@ -332,6 +339,63 @@ static void check_perms (void) +@@ -318,6 +325,63 @@ static void check_perms (void) #endif /* USE_PAM */ } @@ -216,7 +216,7 @@ diff -up shadow-4.8/src/chpasswd.c.selinux-perms shadow-4.8/src/chpasswd.c /* * open_files - lock and open the password databases */ -@@ -428,6 +492,10 @@ int main (int argc, char **argv) +@@ -450,6 +514,10 @@ int main (int argc, char **argv) (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); @@ -224,10 +224,10 @@ diff -up shadow-4.8/src/chpasswd.c.selinux-perms shadow-4.8/src/chpasswd.c + selinux_check_root (); +#endif + - process_root_flag ("-R", argc, argv); - process_flags (argc, argv); -@@ -440,6 +508,10 @@ int main (int argc, char **argv) + + salt = get_salt(); +@@ -463,6 +531,10 @@ int main (int argc, char **argv) OPENLOG ("chpasswd"); diff --git a/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch b/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch deleted file mode 100644 index 4d8e792..0000000 --- a/shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch +++ /dev/null @@ -1,48 +0,0 @@ -From e101219ad71de11da3fdd1b3ec2620fd1a97b92c Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 10 Jan 2022 15:30:28 +0100 -Subject: [PATCH] nss: get shadow_logfd with log_get_logfd() - -If /etc/nsswitch.conf doesn't exist podman crashes because shadow_logfd -is NULL. In order to avoid that load the log file descriptor with the -log_get_logfd() helper function. - -Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2038811 - -Signed-off-by: Iker Pedrosa ---- - lib/nss.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/lib/nss.c b/lib/nss.c -index 02742902..06fa48e5 100644 ---- a/lib/nss.c -+++ b/lib/nss.c -@@ -9,6 +9,7 @@ - #include "prototypes.h" - #include "../libsubid/subid.h" - #include "shadowlog_internal.h" -+#include "shadowlog.h" - - #define NSSWITCH "/etc/nsswitch.conf" - -@@ -42,6 +43,7 @@ void nss_init(const char *nsswitch_path) { - FILE *nssfp = NULL; - char *line = NULL, *p, *token, *saveptr; - size_t len = 0; -+ FILE *shadow_logfd = log_get_logfd(); - - if (atomic_flag_test_and_set(&nss_init_started)) { - // Another thread has started nss_init, wait for it to complete -@@ -57,7 +59,7 @@ void nss_init(const char *nsswitch_path) { - // subid: files - nssfp = fopen(nsswitch_path, "r"); - if (!nssfp) { -- fprintf(shadow_logfd, "Failed opening %s: %m", nsswitch_path); -+ fprintf(shadow_logfd, "Failed opening %s: %m\n", nsswitch_path); - atomic_store(&nss_init_completed, true); - return; - } --- -2.34.1 - diff --git a/shadow-utils.spec b/shadow-utils.spec index 660f777..69a2aa8 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.11.1 -Release: 4%{?dist} +Version: 4.12.3 +Release: 1%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -18,9 +18,9 @@ Source6: shadow-utils.HOME_MODE.xml ### Patches ### # Misc small changes - most probably non-upstreamable -Patch0: shadow-4.11.1-redhat.patch +Patch0: shadow-4.12.3-redhat.patch # Be more lenient with acceptable user/group names - non upstreamable -Patch1: shadow-4.8-goodname.patch +Patch1: shadow-4.12.3-goodname.patch # SElinux related - upstreamability unknown Patch3: shadow-4.9-default-range.patch # Misc manual page changes - non-upstreamable @@ -34,19 +34,15 @@ Patch7: shadow-4.11.1-audit-update.patch # Changes related to password unlocking - could be upstreamed Patch8: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown -Patch9: shadow-4.8-selinux-perms.patch +Patch9: shadow-4.12.3-selinux-perms.patch # Handle NULL return from *time funcs - upstreamable Patch10: shadow-4.11.1-null-tm.patch # Handle /etc/passwd corruption - could be upstreamed -Patch11: shadow-4.8-long-entry.patch +Patch11: shadow-4.12.3-long-entry.patch # Limit uid/gid allocation to non-zero - could be upstreamed Patch12: shadow-4.6-sysugid-min-limit.patch # Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown Patch13: shadow-4.8-ignore-login-prompt.patch -# https://github.com/shadow-maint/shadow/commit/e101219ad71de11da3fdd1b3ec2620fd1a97b92c -Patch14: shadow-4.9-nss-get-shadow-logfd-with-log-get-logfd.patch -# https://github.com/shadow-maint/shadow/commit/f1f1678e13aa3ae49bdb139efaa2c5bc53dcfe92 -Patch15: shadow-4.11.1-useradd-modify-check-ID-range-for-system-users.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -120,8 +116,6 @@ Development files for shadow-utils-subid. %patch11 -p1 -b .long-entry %patch12 -p1 -b .sysugid-min-limit %patch13 -p1 -b .login-prompt -%patch14 -p1 -b .nss-get-shadow-logfd-with-log-get-logfd -%patch15 -p1 -b .useradd-modify-check-ID-range-for-system-users iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -295,6 +289,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Aug 22 2022 Iker Pedrosa - 2:4.12.3-1 +- Rebase to version 4.12.3. Resolves: #2117809 + * Mon Aug 1 2022 Iker Pedrosa - 2:4.11.1-4 - useradd: modify check ID range for system users. Resolves: #2093692 diff --git a/sources b/sources index 53a4fb0..d1e0ebd 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.11.1.tar.xz) = 12fbe4d6ac929ad3c21525ed0f1026b5b678ccec9762f2ec7e611d9c180934def506325f2835fb750dd30af035b592f827ff151cd6e4c805aaaf8e01425c279f -SHA512 (shadow-4.11.1.tar.xz.asc) = 4594189678cc9bcc8831f62a5d42c605b085be4a3b540429d7c800f4304e2e8fe04358547917eb90c1513646fade7c714611bfdc98af7dec5321a3dc3e65c4fd +SHA512 (shadow-4.12.3.tar.xz) = 0529889258f54e7634762dc154aa680d55f8c5f1654afadd1b7431cfbb890a3b1ba27c7ff4b7c45986e4ee2289946db2e420b23ed13e4e5b15800a1fb3a013bc +SHA512 (shadow-4.12.3.tar.xz.asc) = d3f294d86c0e2174c88809810a801737c01cd01f9cadbe7b1ae382b2745d86e2e30c0718fa6489c2abb65500ed94c8ac1961d05243b5a1800c966384c69281c9 From d491f14619d851b66e1da1dbc2cd492f87b0d28e Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 9 Sep 2022 15:04:49 +0200 Subject: [PATCH 047/118] useradd: Do not reset non-existent data in {last,fail}log Signed-off-by: Iker Pedrosa --- ...2.3-useradd-stop-last-fail-log-reset.patch | 42 +++++++++++++++++++ shadow-utils.spec | 10 ++++- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 shadow-4.12.3-useradd-stop-last-fail-log-reset.patch diff --git a/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch b/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch new file mode 100644 index 0000000..8662672 --- /dev/null +++ b/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch @@ -0,0 +1,42 @@ +From ebf9b232b012725d2be5e750876c7336cf1c37fd Mon Sep 17 00:00:00 2001 +From: David Kalnischkies +Date: Wed, 24 Aug 2022 13:21:01 +0200 +Subject: [PATCH] useradd: Do not reset non-existent data in {last,fail}log + +useradd does not create the files if they don't exist, but if they exist +it will reset user data even if the data did not exist before creating +a hole and an explicitly zero'd data point resulting (especially for +high UIDs) in a lot of zeros ending up in containers and tarballs. +--- + src/useradd.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 6eaeb533..39a744ee 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1996,8 +1996,9 @@ static void faillog_reset (uid_t uid) + struct faillog fl; + int fd; + off_t offset_uid = (off_t) (sizeof fl) * uid; ++ struct stat st; + +- if (access (FAILLOG_FILE, F_OK) != 0) { ++ if (stat (FAILLOG_FILE, &st) != 0 || st.st_size <= offset_uid) { + return; + } + +@@ -2033,8 +2034,9 @@ static void lastlog_reset (uid_t uid) + int fd; + off_t offset_uid = (off_t) (sizeof ll) * uid; + uid_t max_uid; ++ struct stat st; + +- if (access (LASTLOG_FILE, F_OK) != 0) { ++ if (stat (LASTLOG_FILE, &st) != 0 || st.st_size <= offset_uid) { + return; + } + +-- +2.37.3 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 69a2aa8..bdc0515 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.12.3 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -19,7 +19,7 @@ Source6: shadow-utils.HOME_MODE.xml ### Patches ### # Misc small changes - most probably non-upstreamable Patch0: shadow-4.12.3-redhat.patch -# Be more lenient with acceptable user/group names - non upstreamable +# https://github.com/shadow-maint/shadow/commit/cfc981df2afc615e3792b918e9ee49e631b0a3a9 Patch1: shadow-4.12.3-goodname.patch # SElinux related - upstreamability unknown Patch3: shadow-4.9-default-range.patch @@ -43,6 +43,8 @@ Patch11: shadow-4.12.3-long-entry.patch Patch12: shadow-4.6-sysugid-min-limit.patch # Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown Patch13: shadow-4.8-ignore-login-prompt.patch +# https://github.com/shadow-maint/shadow/commit/ebf9b232b012725d2be5e750876c7336cf1c37fd +Patch14: shadow-4.12.3-useradd-stop-last-fail-log-reset.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -116,6 +118,7 @@ Development files for shadow-utils-subid. %patch11 -p1 -b .long-entry %patch12 -p1 -b .sysugid-min-limit %patch13 -p1 -b .login-prompt +%patch14 -p1 -b .useradd-stop-last-fail-log-reset iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -289,6 +292,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Sep 9 2022 Iker Pedrosa - 2:4.12.3-2 +- useradd: Do not reset non-existent data in {last,fail}log + * Mon Aug 22 2022 Iker Pedrosa - 2:4.12.3-1 - Rebase to version 4.12.3. Resolves: #2117809 From 47d965b5dcba59291e90261ccd9f3e6436b0691d Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 5 Oct 2022 13:04:29 +0200 Subject: [PATCH 048/118] chage: Fix regression in print_date Resolves: #2129336 Signed-off-by: Iker Pedrosa --- ...w-4.12.3-chage-print-date-regression.patch | 32 +++++++++++++++++++ shadow-utils.spec | 8 ++++- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 shadow-4.12.3-chage-print-date-regression.patch diff --git a/shadow-4.12.3-chage-print-date-regression.patch b/shadow-4.12.3-chage-print-date-regression.patch new file mode 100644 index 0000000..7f9f225 --- /dev/null +++ b/shadow-4.12.3-chage-print-date-regression.patch @@ -0,0 +1,32 @@ +From e503fd574b7dbf6b21b1168e20938f0922807916 Mon Sep 17 00:00:00 2001 +From: Xiami <1927254+Xiami2012@users.noreply.github.com> +Date: Wed, 5 Oct 2022 18:11:28 +0800 +Subject: [PATCH] chage: Fix regression in print_date + +Introduced by c6c8130db4319613a91dd07bbb845f6c33c5f79f + +After removing snprintf, the format string should get unescaped once. + +Fixes #564 + +Reporter and patch author: DerMouse (github.com/DerMouse) +--- + src/chage.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/chage.c b/src/chage.c +index 8cf67794..01570d72 100644 +--- a/src/chage.c ++++ b/src/chage.c +@@ -228,7 +228,7 @@ static void print_date (time_t date) + if (NULL == tp) { + (void) printf ("time_t: %lu\n", (unsigned long)date); + } else { +- (void) strftime (buf, sizeof buf, iflg ? "%%Y-%%m-%%d" : "%%b %%d, %%Y", tp); ++ (void) strftime (buf, sizeof buf, iflg ? "%Y-%m-%d" : "%b %d, %Y", tp); + (void) puts (buf); + } + } +-- +2.37.3 + diff --git a/shadow-utils.spec b/shadow-utils.spec index bdc0515..c9c1c89 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.12.3 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD and GPLv2+ URL: https://github.com/shadow-maint/shadow @@ -45,6 +45,8 @@ Patch12: shadow-4.6-sysugid-min-limit.patch Patch13: shadow-4.8-ignore-login-prompt.patch # https://github.com/shadow-maint/shadow/commit/ebf9b232b012725d2be5e750876c7336cf1c37fd Patch14: shadow-4.12.3-useradd-stop-last-fail-log-reset.patch +# https://github.com/shadow-maint/shadow/commit/e503fd574b7dbf6b21b1168e20938f0922807916 +Patch15: shadow-4.12.3-chage-print-date-regression.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -119,6 +121,7 @@ Development files for shadow-utils-subid. %patch12 -p1 -b .sysugid-min-limit %patch13 -p1 -b .login-prompt %patch14 -p1 -b .useradd-stop-last-fail-log-reset +%patch15 -p1 -b .chage-print-date-regression iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -292,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Oct 5 2022 Iker Pedrosa - 2:4.12.3-3 +- chage: Fix regression in print_date. Resolves: #2129336 + * Fri Sep 9 2022 Iker Pedrosa - 2:4.12.3-2 - useradd: Do not reset non-existent data in {last,fail}log From d3e12503afcd822a8dcd98a174813d1a70a585e6 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 9 Nov 2022 10:12:41 +0100 Subject: [PATCH 049/118] - Rebase to version 4.13 - SPDX license migration Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.11.1-null-tm.patch | 22 ---- ...w-4.12.3-chage-print-date-regression.patch | 32 ------ shadow-4.12.3-goodname.patch | 100 ------------------ shadow-4.12.3-long-entry.patch | 86 --------------- ...2.3-useradd-stop-last-fail-log-reset.patch | 42 -------- shadow-4.13-default-range.patch | 35 ++++++ shadow-4.6-move-home.patch | 15 --- shadow-4.6-sysugid-min-limit.patch | 34 ------ shadow-4.8-ignore-login-prompt.patch | 11 -- shadow-4.9-default-range.patch | 35 ------ shadow-utils.spec | 58 ++++------ sources | 4 +- 13 files changed, 58 insertions(+), 418 deletions(-) delete mode 100644 shadow-4.11.1-null-tm.patch delete mode 100644 shadow-4.12.3-chage-print-date-regression.patch delete mode 100644 shadow-4.12.3-goodname.patch delete mode 100644 shadow-4.12.3-long-entry.patch delete mode 100644 shadow-4.12.3-useradd-stop-last-fail-log-reset.patch create mode 100644 shadow-4.13-default-range.patch delete mode 100644 shadow-4.6-move-home.patch delete mode 100644 shadow-4.6-sysugid-min-limit.patch delete mode 100644 shadow-4.8-ignore-login-prompt.patch delete mode 100644 shadow-4.9-default-range.patch diff --git a/.gitignore b/.gitignore index 7113c48..44cb6ed 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.11.1.tar.xz.asc /shadow-4.12.3.tar.xz /shadow-4.12.3.tar.xz.asc +/shadow-4.13.tar.xz +/shadow-4.13.tar.xz.asc diff --git a/shadow-4.11.1-null-tm.patch b/shadow-4.11.1-null-tm.patch deleted file mode 100644 index b8d5fc8..0000000 --- a/shadow-4.11.1-null-tm.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -up shadow-4.11.1/src/chage.c.null-tm shadow-4.11.1/src/chage.c -diff -up shadow-4.11.1/src/lastlog.c.null-tm shadow-4.11.1/src/lastlog.c ---- shadow-4.11.1/src/lastlog.c.null-tm 2022-01-03 15:31:56.348555620 +0100 -+++ shadow-4.11.1/src/lastlog.c 2022-01-03 15:38:41.262229024 +0100 -@@ -151,9 +151,12 @@ static void print_one (/*@null@*/const s - - ll_time = ll.ll_time; - tm = localtime (&ll_time); -- strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -- cp = ptime; -- -+ if (tm == NULL) { -+ cp = "(unknown)"; -+ } else { -+ strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm); -+ cp = ptime; -+ } - if (ll.ll_time == (time_t) 0) { - cp = _("**Never logged in**\0"); - } -diff -up shadow-4.11.1/src/passwd.c.null-tm shadow-4.11.1/src/passwd.c -diff -up shadow-4.11.1/src/usermod.c.null-tm shadow-4.11.1/src/usermod.c diff --git a/shadow-4.12.3-chage-print-date-regression.patch b/shadow-4.12.3-chage-print-date-regression.patch deleted file mode 100644 index 7f9f225..0000000 --- a/shadow-4.12.3-chage-print-date-regression.patch +++ /dev/null @@ -1,32 +0,0 @@ -From e503fd574b7dbf6b21b1168e20938f0922807916 Mon Sep 17 00:00:00 2001 -From: Xiami <1927254+Xiami2012@users.noreply.github.com> -Date: Wed, 5 Oct 2022 18:11:28 +0800 -Subject: [PATCH] chage: Fix regression in print_date - -Introduced by c6c8130db4319613a91dd07bbb845f6c33c5f79f - -After removing snprintf, the format string should get unescaped once. - -Fixes #564 - -Reporter and patch author: DerMouse (github.com/DerMouse) ---- - src/chage.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/chage.c b/src/chage.c -index 8cf67794..01570d72 100644 ---- a/src/chage.c -+++ b/src/chage.c -@@ -228,7 +228,7 @@ static void print_date (time_t date) - if (NULL == tp) { - (void) printf ("time_t: %lu\n", (unsigned long)date); - } else { -- (void) strftime (buf, sizeof buf, iflg ? "%%Y-%%m-%%d" : "%%b %%d, %%Y", tp); -+ (void) strftime (buf, sizeof buf, iflg ? "%Y-%m-%d" : "%b %d, %Y", tp); - (void) puts (buf); - } - } --- -2.37.3 - diff --git a/shadow-4.12.3-goodname.patch b/shadow-4.12.3-goodname.patch deleted file mode 100644 index 2376674..0000000 --- a/shadow-4.12.3-goodname.patch +++ /dev/null @@ -1,100 +0,0 @@ -diff -up shadow-4.12.3/libmisc/chkname.c.goodname shadow-4.12.3/libmisc/chkname.c ---- shadow-4.12.3/libmisc/chkname.c.goodname 2022-06-19 16:16:48.000000000 +0200 -+++ shadow-4.12.3/libmisc/chkname.c 2022-08-22 16:00:27.646087971 +0200 -@@ -32,26 +32,44 @@ static bool is_valid_name (const char *n - } - - /* -- * User/group names must match [a-z_][a-z0-9_-]*[$] -- */ -+ * User/group names must match gnu e-regex: -+ * [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]? -+ * -+ * as a non-POSIX, extension, allow "$" as the last char for -+ * sake of Samba 3.x "add machine script" -+ * -+ * Also do not allow fully numeric names or just "." or "..". -+ */ -+ int numeric; - -- if (('\0' == *name) || -- !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) { -+ if ('\0' == *name || -+ ('.' == *name && (('.' == name[1] && '\0' == name[2]) || -+ '\0' == name[1])) || -+ !((*name >= 'a' && *name <= 'z') || -+ (*name >= 'A' && *name <= 'Z') || -+ (*name >= '0' && *name <= '9') || -+ *name == '_' || -+ *name == '.')) { - return false; - } - -+ numeric = isdigit(*name); -+ - while ('\0' != *++name) { -- if (!(( ('a' <= *name) && ('z' >= *name) ) || -- ( ('0' <= *name) && ('9' >= *name) ) || -- ('_' == *name) || -- ('-' == *name) || -- ( ('$' == *name) && ('\0' == *(name + 1)) ) -+ if (!((*name >= 'a' && *name <= 'z') || -+ (*name >= 'A' && *name <= 'Z') || -+ (*name >= '0' && *name <= '9') || -+ *name == '_' || -+ *name == '.' || -+ *name == '-' || -+ (*name == '$' && name[1] == '\0') - )) { - return false; - } -+ numeric &= isdigit(*name); - } - -- return true; -+ return !numeric; - } - - bool is_valid_user_name (const char *name) -diff -up shadow-4.12.3/man/groupadd.8.xml.goodname shadow-4.12.3/man/groupadd.8.xml ---- shadow-4.12.3/man/groupadd.8.xml.goodname 2022-08-22 16:00:27.646087971 +0200 -+++ shadow-4.12.3/man/groupadd.8.xml 2022-08-22 16:01:59.301779733 +0200 -@@ -64,10 +64,12 @@ - files as needed. - - -- Groupnames must start with a lower case letter or an underscore, -- followed by lower case letters, digits, underscores, or dashes. -- They can end with a dollar sign. -- In regular expression terms: [a-z_][a-z0-9_-]*[$]? -+ Groupnames may contain only lower and upper case letters, digits, -+ underscores, or dashes. They can end with a dollar sign. -+ -+ Dashes are not allowed at the beginning of the groupname. -+ Fully numeric groupnames and groupnames . or .. are -+ also disallowed. - - - Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long. -diff -up shadow-4.12.3/man/useradd.8.xml.goodname shadow-4.12.3/man/useradd.8.xml ---- shadow-4.12.3/man/useradd.8.xml.goodname 2022-08-22 14:46:57.000000000 +0200 -+++ shadow-4.12.3/man/useradd.8.xml 2022-08-22 16:00:27.646087971 +0200 -@@ -692,10 +692,14 @@ - - - -- Usernames must start with a lower case letter or an underscore, -- followed by lower case letters, digits, underscores, or dashes. -- They can end with a dollar sign. -- In regular expression terms: [a-z_][a-z0-9_-]*[$]? -+ Usernames may contain only lower and upper case letters, digits, -+ underscores, or dashes. They can end with a dollar sign. -+ -+ Dashes are not allowed at the beginning of the username. -+ Fully numeric usernames and usernames . or .. are -+ also disallowed. It is not recommended to use usernames beginning -+ with . character as their home directories will be hidden in -+ the ls output. - - - Usernames may only be up to 32 characters long. diff --git a/shadow-4.12.3-long-entry.patch b/shadow-4.12.3-long-entry.patch deleted file mode 100644 index 9dc5ef2..0000000 --- a/shadow-4.12.3-long-entry.patch +++ /dev/null @@ -1,86 +0,0 @@ -diff -up shadow-4.12.3/lib/defines.h.long-entry shadow-4.12.3/lib/defines.h ---- shadow-4.12.3/lib/defines.h.long-entry 2022-08-18 23:51:37.000000000 +0200 -+++ shadow-4.12.3/lib/defines.h 2022-08-22 16:12:27.412522768 +0200 -@@ -335,6 +335,9 @@ extern char *strerror (); - # endif - #endif - -+/* Maximum length of passwd entry */ -+#define PASSWD_ENTRY_MAX_LENGTH 32768 -+ - #ifdef HAVE_SECURE_GETENV - # define shadow_getenv(name) secure_getenv(name) - # else -diff -up shadow-4.12.3/lib/pwio.c.long-entry shadow-4.12.3/lib/pwio.c ---- shadow-4.12.3/lib/pwio.c.long-entry 2022-06-19 16:16:48.000000000 +0200 -+++ shadow-4.12.3/lib/pwio.c 2022-08-22 16:12:27.412522768 +0200 -@@ -56,7 +56,10 @@ static int passwd_put (const void *ent, - || (pw->pw_gid == (gid_t)-1) - || (valid_field (pw->pw_gecos, ":\n") == -1) - || (valid_field (pw->pw_dir, ":\n") == -1) -- || (valid_field (pw->pw_shell, ":\n") == -1)) { -+ || (valid_field (pw->pw_shell, ":\n") == -1) -+ || (strlen (pw->pw_name) + strlen (pw->pw_passwd) + -+ strlen (pw->pw_gecos) + strlen (pw->pw_dir) + -+ strlen (pw->pw_shell) + 100 > PASSWD_ENTRY_MAX_LENGTH)) { - return -1; - } - -diff -up shadow-4.12.3/lib/sgetpwent.c.long-entry shadow-4.12.3/lib/sgetpwent.c ---- shadow-4.12.3/lib/sgetpwent.c.long-entry 2022-08-09 00:30:40.000000000 +0200 -+++ shadow-4.12.3/lib/sgetpwent.c 2022-08-22 16:14:10.955309200 +0200 -@@ -34,7 +34,7 @@ - struct passwd *sgetpwent (const char *buf) - { - static struct passwd pwent; -- static char pwdbuf[1024]; -+ static char pwdbuf[PASSWD_ENTRY_MAX_LENGTH]; - int i; - char *cp; - char *fields[NFIELDS]; -@@ -44,8 +44,10 @@ struct passwd *sgetpwent (const char *bu - * the password structure remain valid. - */ - -- if (strlen (buf) >= sizeof pwdbuf) -+ if (strlen (buf) >= sizeof pwdbuf) { -+ fprintf (stderr, "Too long passwd entry encountered, file corruption?\n"); - return 0; /* fail if too long */ -+ } - strcpy (pwdbuf, buf); - - /* -diff -up shadow-4.12.3/lib/sgetspent.c.long-entry shadow-4.12.3/lib/sgetspent.c ---- shadow-4.12.3/lib/sgetspent.c.long-entry 2022-06-19 16:16:54.000000000 +0200 -+++ shadow-4.12.3/lib/sgetspent.c 2022-08-22 16:12:27.413522776 +0200 -@@ -25,7 +25,7 @@ - */ - struct spwd *sgetspent (const char *string) - { -- static char spwbuf[1024]; -+ static char spwbuf[PASSWD_ENTRY_MAX_LENGTH]; - static struct spwd spwd; - char *fields[FIELDS]; - char *cp; -@@ -37,6 +37,7 @@ struct spwd *sgetspent (const char *stri - */ - - if (strlen (string) >= sizeof spwbuf) { -+ fprintf (stderr, "Too long shadow entry encountered, file corruption?\n"); - return 0; /* fail if too long */ - } - strcpy (spwbuf, string); -diff -up shadow-4.12.3/lib/shadowio.c.long-entry shadow-4.12.3/lib/shadowio.c ---- shadow-4.12.3/lib/shadowio.c.long-entry 2022-06-19 16:16:48.000000000 +0200 -+++ shadow-4.12.3/lib/shadowio.c 2022-08-22 16:12:27.413522776 +0200 -@@ -56,7 +56,9 @@ static int shadow_put (const void *ent, - - if ( (NULL == sp) - || (valid_field (sp->sp_namp, ":\n") == -1) -- || (valid_field (sp->sp_pwdp, ":\n") == -1)) { -+ || (valid_field (sp->sp_pwdp, ":\n") == -1) -+ || (strlen (sp->sp_namp) + strlen (sp->sp_pwdp) + -+ 1000 > PASSWD_ENTRY_MAX_LENGTH)) { - return -1; - } - diff --git a/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch b/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch deleted file mode 100644 index 8662672..0000000 --- a/shadow-4.12.3-useradd-stop-last-fail-log-reset.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ebf9b232b012725d2be5e750876c7336cf1c37fd Mon Sep 17 00:00:00 2001 -From: David Kalnischkies -Date: Wed, 24 Aug 2022 13:21:01 +0200 -Subject: [PATCH] useradd: Do not reset non-existent data in {last,fail}log - -useradd does not create the files if they don't exist, but if they exist -it will reset user data even if the data did not exist before creating -a hole and an explicitly zero'd data point resulting (especially for -high UIDs) in a lot of zeros ending up in containers and tarballs. ---- - src/useradd.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 6eaeb533..39a744ee 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1996,8 +1996,9 @@ static void faillog_reset (uid_t uid) - struct faillog fl; - int fd; - off_t offset_uid = (off_t) (sizeof fl) * uid; -+ struct stat st; - -- if (access (FAILLOG_FILE, F_OK) != 0) { -+ if (stat (FAILLOG_FILE, &st) != 0 || st.st_size <= offset_uid) { - return; - } - -@@ -2033,8 +2034,9 @@ static void lastlog_reset (uid_t uid) - int fd; - off_t offset_uid = (off_t) (sizeof ll) * uid; - uid_t max_uid; -+ struct stat st; - -- if (access (LASTLOG_FILE, F_OK) != 0) { -+ if (stat (LASTLOG_FILE, &st) != 0 || st.st_size <= offset_uid) { - return; - } - --- -2.37.3 - diff --git a/shadow-4.13-default-range.patch b/shadow-4.13-default-range.patch new file mode 100644 index 0000000..f199b39 --- /dev/null +++ b/shadow-4.13-default-range.patch @@ -0,0 +1,35 @@ +diff -up shadow-4.13/lib/semanage.c.default-range shadow-4.13/lib/semanage.c +--- shadow-4.13/lib/semanage.c.default-range 2022-11-09 09:37:11.955314964 +0100 ++++ shadow-4.13/lib/semanage.c 2022-11-09 09:47:59.130645564 +0100 +@@ -122,6 +122,7 @@ static int semanage_user_mod (semanage_h + goto done; + } + ++#if 0 + if (semanage_mls_enabled(handle)) { + ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); + if (ret != 0) { +@@ -131,6 +132,7 @@ static int semanage_user_mod (semanage_h + goto done; + } + } ++#endif + + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); + if (ret != 0) { +@@ -181,6 +183,7 @@ static int semanage_user_add (semanage_h + goto done; + } + ++#if 0 + if (semanage_mls_enabled(handle)) { + ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); + if (ret != 0) { +@@ -190,6 +193,7 @@ static int semanage_user_add (semanage_h + goto done; + } + } ++#endif + + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); + if (ret != 0) { diff --git a/shadow-4.6-move-home.patch b/shadow-4.6-move-home.patch deleted file mode 100644 index cff9561..0000000 --- a/shadow-4.6-move-home.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -up shadow-4.6/src/usermod.c.move-home shadow-4.6/src/usermod.c ---- shadow-4.6/src/usermod.c.move-home 2018-05-28 14:59:05.594076665 +0200 -+++ shadow-4.6/src/usermod.c 2018-05-28 15:00:28.479837392 +0200 -@@ -1845,6 +1845,11 @@ static void move_home (void) - Prog, prefix_user_home, prefix_user_newhome); - fail_exit (E_HOMEDIR); - } -+ } else { -+ fprintf (stderr, -+ _("%s: The previous home directory (%s) does " -+ "not exist or is inaccessible. Move cannot be completed.\n"), -+ Prog, prefix_user_home); - } - } - diff --git a/shadow-4.6-sysugid-min-limit.patch b/shadow-4.6-sysugid-min-limit.patch deleted file mode 100644 index 4cea6ef..0000000 --- a/shadow-4.6-sysugid-min-limit.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff -up shadow-4.6/libmisc/find_new_gid.c.min-limit shadow-4.6/libmisc/find_new_gid.c ---- shadow-4.6/libmisc/find_new_gid.c.min-limit 2018-04-29 18:42:37.000000001 +0200 -+++ shadow-4.6/libmisc/find_new_gid.c 2018-11-06 10:51:20.554963292 +0100 -@@ -82,6 +82,13 @@ static int get_ranges (bool sys_group, g - (unsigned long) *max_id); - return EINVAL; - } -+ /* -+ * Zero is reserved for root and the allocation algorithm does not -+ * work right with it. -+ */ -+ if (*min_id == 0) { -+ *min_id = (gid_t) 1; -+ } - } else { - /* Non-system groups */ - -diff -up shadow-4.6/libmisc/find_new_uid.c.min-limit shadow-4.6/libmisc/find_new_uid.c ---- shadow-4.6/libmisc/find_new_uid.c.min-limit 2018-04-29 18:42:37.000000001 +0200 -+++ shadow-4.6/libmisc/find_new_uid.c 2018-11-06 10:51:39.341399569 +0100 -@@ -82,6 +82,13 @@ static int get_ranges (bool sys_user, ui - (unsigned long) *max_id); - return EINVAL; - } -+ /* -+ * Zero is reserved for root and the allocation algorithm does not -+ * work right with it. -+ */ -+ if (*min_id == 0) { -+ *min_id = (uid_t) 1; -+ } - } else { - /* Non-system users */ - diff --git a/shadow-4.8-ignore-login-prompt.patch b/shadow-4.8-ignore-login-prompt.patch deleted file mode 100644 index c93aae7..0000000 --- a/shadow-4.8-ignore-login-prompt.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -up shadow-4.8/lib/getdef.c.login-prompt shadow-4.8/lib/getdef.c ---- shadow-4.8/lib/getdef.c.login-prompt 2020-01-13 10:38:44.852796681 +0100 -+++ shadow-4.8/lib/getdef.c 2020-01-13 10:39:54.472612511 +0100 -@@ -98,6 +98,7 @@ static struct itemdef def_table[] = { - {"LASTLOG_UID_MAX", NULL}, - {"LOGIN_RETRIES", NULL}, - {"LOGIN_TIMEOUT", NULL}, -+ {"LOGIN_PLAIN_PROMPT", NULL}, - {"LOG_OK_LOGINS", NULL}, - {"LOG_UNKFAIL_ENAB", NULL}, - {"MAIL_DIR", NULL}, diff --git a/shadow-4.9-default-range.patch b/shadow-4.9-default-range.patch deleted file mode 100644 index f6e0427..0000000 --- a/shadow-4.9-default-range.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff -up shadow-4.9/lib/semanage.c.default-range shadow-4.9/lib/semanage.c ---- shadow-4.9/lib/semanage.c.default-range 2021-07-22 23:55:35.000000000 +0200 -+++ shadow-4.9/lib/semanage.c 2021-08-02 12:43:16.822817392 +0200 -@@ -143,6 +143,7 @@ static int semanage_user_mod (semanage_h - goto done; - } - -+#if 0 - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { - fprintf (shadow_logfd, -@@ -150,6 +151,7 @@ static int semanage_user_mod (semanage_h - ret = 1; - goto done; - } -+#endif - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { -@@ -200,6 +202,7 @@ static int semanage_user_add (semanage_h - goto done; - } - -+#if 0 - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { - fprintf (shadow_logfd, -@@ -208,6 +211,7 @@ static int semanage_user_add (semanage_h - ret = 1; - goto done; - } -+#endif - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { diff --git a/shadow-utils.spec b/shadow-utils.spec index c9c1c89..da2d3bd 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,9 +1,9 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.12.3 -Release: 3%{?dist} +Version: 4.13 +Release: 1%{?dist} Epoch: 2 -License: BSD and GPLv2+ +License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow Source0: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz Source1: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz.asc @@ -19,34 +19,18 @@ Source6: shadow-utils.HOME_MODE.xml ### Patches ### # Misc small changes - most probably non-upstreamable Patch0: shadow-4.12.3-redhat.patch -# https://github.com/shadow-maint/shadow/commit/cfc981df2afc615e3792b918e9ee49e631b0a3a9 -Patch1: shadow-4.12.3-goodname.patch # SElinux related - upstreamability unknown -Patch3: shadow-4.9-default-range.patch +Patch1: shadow-4.13-default-range.patch # Misc manual page changes - non-upstreamable -Patch4: shadow-4.9-manfix.patch +Patch2: shadow-4.9-manfix.patch # Date parsing improvement - could be upstreamed -Patch5: shadow-4.2.1-date-parsing.patch -# Additional error message - could be upstreamed -Patch6: shadow-4.6-move-home.patch +Patch3: shadow-4.2.1-date-parsing.patch # Audit message changes - upstreamability unknown -Patch7: shadow-4.11.1-audit-update.patch +Patch4: shadow-4.11.1-audit-update.patch # Changes related to password unlocking - could be upstreamed -Patch8: shadow-4.5-usermod-unlock.patch +Patch5: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown -Patch9: shadow-4.12.3-selinux-perms.patch -# Handle NULL return from *time funcs - upstreamable -Patch10: shadow-4.11.1-null-tm.patch -# Handle /etc/passwd corruption - could be upstreamed -Patch11: shadow-4.12.3-long-entry.patch -# Limit uid/gid allocation to non-zero - could be upstreamed -Patch12: shadow-4.6-sysugid-min-limit.patch -# Ignore LOGIN_PLAIN_PROMPT in login.defs - upstreamability unknown -Patch13: shadow-4.8-ignore-login-prompt.patch -# https://github.com/shadow-maint/shadow/commit/ebf9b232b012725d2be5e750876c7336cf1c37fd -Patch14: shadow-4.12.3-useradd-stop-last-fail-log-reset.patch -# https://github.com/shadow-maint/shadow/commit/e503fd574b7dbf6b21b1168e20938f0922807916 -Patch15: shadow-4.12.3-chage-print-date-regression.patch +Patch6: shadow-4.12.3-selinux-perms.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -108,20 +92,12 @@ Development files for shadow-utils-subid. %prep %setup -q -n shadow-%{version} %patch0 -p1 -b .redhat -%patch1 -p1 -b .goodname -%patch3 -p1 -b .default-range -%patch4 -p1 -b .manfix -%patch5 -p1 -b .date-parsing -%patch6 -p1 -b .move-home -%patch7 -p1 -b .audit-update -%patch8 -p1 -b .unlock -%patch9 -p1 -b .selinux-perms -%patch10 -p1 -b .null-tm -%patch11 -p1 -b .long-entry -%patch12 -p1 -b .sysugid-min-limit -%patch13 -p1 -b .login-prompt -%patch14 -p1 -b .useradd-stop-last-fail-log-reset -%patch15 -p1 -b .chage-print-date-regression +%patch1 -p1 -b .default-range +%patch2 -p1 -b .manfix +%patch3 -p1 -b .date-parsing +%patch4 -p1 -b .audit-update +%patch5 -p1 -b .unlock +%patch6 -p1 -b .selinux-perms iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -295,6 +271,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Nov 9 2022 Iker Pedrosa - 2:4.13-1 +- Rebase to version 4.13 +- SPDX license migration + * Wed Oct 5 2022 Iker Pedrosa - 2:4.12.3-3 - chage: Fix regression in print_date. Resolves: #2129336 diff --git a/sources b/sources index d1e0ebd..40bac31 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.12.3.tar.xz) = 0529889258f54e7634762dc154aa680d55f8c5f1654afadd1b7431cfbb890a3b1ba27c7ff4b7c45986e4ee2289946db2e420b23ed13e4e5b15800a1fb3a013bc -SHA512 (shadow-4.12.3.tar.xz.asc) = d3f294d86c0e2174c88809810a801737c01cd01f9cadbe7b1ae382b2745d86e2e30c0718fa6489c2abb65500ed94c8ac1961d05243b5a1800c966384c69281c9 +SHA512 (shadow-4.13.tar.xz) = 2949a728c3312bef13d23138d6b79caf402781b1cb179e33b5be546c1790971ec20778d0e9cd3dbe09691d928ffcbe88e60da42fab58c69a90d5ebe5e3e2ab8e +SHA512 (shadow-4.13.tar.xz.asc) = f8549c4e699c65721d53946d61b6127712572f7ad9ee13018ef3a25307002992aa727471c948d1bb22dcddf112715bed387d28f436123f30e153ae6bc0cd3648 From bb5dc8ec04d089507c26f58974b056ae1aa334ca Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 21 Nov 2022 11:55:57 +0100 Subject: [PATCH 050/118] Fix gshadow configure check (switching to glibc implementation) Related to: --- shadow-utils-configure-gshadow.patch | 20 ++++++++++++++++++++ shadow-utils.spec | 7 ++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 shadow-utils-configure-gshadow.patch diff --git a/shadow-utils-configure-gshadow.patch b/shadow-utils-configure-gshadow.patch new file mode 100644 index 0000000..a983ce0 --- /dev/null +++ b/shadow-utils-configure-gshadow.patch @@ -0,0 +1,20 @@ +The missing #include causes the configure check to fail +spuriously, resulting in HAVE_SHADOWGRP not being defined. + +Submitted upstream: + +diff --git a/configure.ac b/configure.ac +index 924254a0c8171802..6c7d9839979e037d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -116,6 +116,10 @@ if test "$ac_cv_header_shadow_h" = "yes"; then + ac_cv_libc_shadowgrp, + AC_RUN_IFELSE([AC_LANG_SOURCE([ + #include ++ #ifdef HAVE_GSHADOW_H ++ #include ++ #endif ++ int + main() + { + struct sgrp *sg = sgetsgent("test:x::"); diff --git a/shadow-utils.spec b/shadow-utils.spec index da2d3bd..0953cbc 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.13 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -31,6 +31,7 @@ Patch4: shadow-4.11.1-audit-update.patch Patch5: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown Patch6: shadow-4.12.3-selinux-perms.patch +Patch7: shadow-utils-configure-gshadow.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -98,6 +99,7 @@ Development files for shadow-utils-subid. %patch4 -p1 -b .audit-update %patch5 -p1 -b .unlock %patch6 -p1 -b .selinux-perms +%patch7 -p1 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -271,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Nov 21 2022 Florian Weimer - 2:4.13-2 +- Fix gshadow configure check (switching to glibc implementation) + * Wed Nov 9 2022 Iker Pedrosa - 2:4.13-1 - Rebase to version 4.13 - SPDX license migration From 8779239933ce3516955e1d54368399509f66e0cc Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 23 Nov 2022 15:57:56 +0100 Subject: [PATCH 051/118] Change SUB_UID_MIN and SUB_GID_MIN to 524288 Resolves: #2144558 Signed-off-by: Iker Pedrosa --- shadow-utils.login.defs | 4 ++-- shadow-utils.spec | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index a6c34a1..c0295b1 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -147,7 +147,7 @@ UID_MAX 60000 SYS_UID_MIN 201 SYS_UID_MAX 999 # Extra per user uids -SUB_UID_MIN 100000 +SUB_UID_MIN 524288 SUB_UID_MAX 600100000 SUB_UID_COUNT 65536 @@ -160,7 +160,7 @@ GID_MAX 60000 SYS_GID_MIN 201 SYS_GID_MAX 999 # Extra per user group ids -SUB_GID_MIN 100000 +SUB_GID_MIN 524288 SUB_GID_MAX 600100000 SUB_GID_COUNT 65536 diff --git a/shadow-utils.spec b/shadow-utils.spec index 0953cbc..85bf8a2 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.13 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -273,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Nov 23 2022 Iker Pedrosa - 2:4.13-3 +- Change SUB_UID_MIN and SUB_GID_MIN to 524288. Resolves: #2144558 + * Mon Nov 21 2022 Florian Weimer - 2:4.13-2 - Fix gshadow configure check (switching to glibc implementation) From f7089c062fe967a79f962385229781d1fa0d1fc5 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 21 Jan 2023 03:07:17 +0000 Subject: [PATCH 052/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 85bf8a2..74e1c42 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.13 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -273,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jan 21 2023 Fedora Release Engineering - 2:4.13-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + * Wed Nov 23 2022 Iker Pedrosa - 2:4.13-3 - Change SUB_UID_MIN and SUB_GID_MIN to 524288. Resolves: #2144558 From c0c2ea7769d5e6faf56f62dfa08df7d799c6c341 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 2 Mar 2023 14:36:39 +0100 Subject: [PATCH 053/118] newuidmap and newgidmap: support passing pid as fd Resolves: #2174752 Signed-off-by: Iker Pedrosa --- ...3-newidmap-support-passing-pid-as-fd.patch | 441 ++++++++++++++++++ shadow-utils.spec | 14 +- 2 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 shadow-4.13-newidmap-support-passing-pid-as-fd.patch diff --git a/shadow-4.13-newidmap-support-passing-pid-as-fd.patch b/shadow-4.13-newidmap-support-passing-pid-as-fd.patch new file mode 100644 index 0000000..37e0d41 --- /dev/null +++ b/shadow-4.13-newidmap-support-passing-pid-as-fd.patch @@ -0,0 +1,441 @@ +From 6974df39a708abf8bafbdfa2b7827e0f70f874cb Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Mon, 6 Feb 2023 22:49:42 -0600 +Subject: [PATCH] newuidmap and newgidmap: support passing pid as fd + +Closes #635 + +newuidmap and newgidmap currently take an integner pid as +the first argument, determining the process id on which to +act. Accept also "fd:N", where N must be an open file +descriptor to the /proc/pid directory for the process to +act upon. This way, if you + +exec 10 +--- + lib/get_pid.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ + lib/prototypes.h | 2 ++ + man/newgidmap.1.xml | 11 ++++++++++ + man/newuidmap.1.xml | 11 ++++++++++ + src/newgidmap.c | 41 ++++++++++++++---------------------- + src/newuidmap.c | 40 +++++++++++++---------------------- + 6 files changed, 106 insertions(+), 50 deletions(-) + +diff --git a/lib/get_pid.c b/lib/get_pid.c +index 10184bf0..ab91d158 100644 +--- a/lib/get_pid.c ++++ b/lib/get_pid.c +@@ -10,6 +10,9 @@ + + #include "prototypes.h" + #include "defines.h" ++#include ++#include ++#include + + int get_pid (const char *pidstr, pid_t *pid) + { +@@ -29,3 +32,51 @@ int get_pid (const char *pidstr, pid_t *pid) + return 1; + } + ++/* ++ * If use passed in fd:4 as an argument, then return the ++ * value '4', the fd to use. ++ */ ++int get_pidfd_from_fd(const char *pidfdstr) ++{ ++ long long int val; ++ char *endptr; ++ ++ errno = 0; ++ val = strtoll (pidfdstr, &endptr, 10); ++ if ( ('\0' == *pidfdstr) ++ || ('\0' != *endptr) ++ || (ERANGE == errno) ++ || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { ++ return 0; ++ } ++ ++ return (int)val; ++} ++ ++int open_pidfd(const char *pidstr) ++{ ++ int proc_dir_fd; ++ int written; ++ char proc_dir_name[32]; ++ pid_t target; ++ ++ if (get_pid(pidstr, &target) == 0) ++ return -ENOENT; ++ ++ /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ ++ written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", ++ target); ++ if ((written <= 0) || ((size_t)written >= sizeof(proc_dir_name))) { ++ fprintf(stderr, "snprintf of proc path failed for %u: %s\n", ++ target, strerror(errno)); ++ return -EINVAL; ++ } ++ ++ proc_dir_fd = open(proc_dir_name, O_DIRECTORY); ++ if (proc_dir_fd < 0) { ++ fprintf(stderr, _("Could not open proc directory for target %u: %s\n"), ++ target, strerror(errno)); ++ return -EINVAL; ++ } ++ return proc_dir_fd; ++} +diff --git a/lib/prototypes.h b/lib/prototypes.h +index 400d5b97..21df6f61 100644 +--- a/lib/prototypes.h ++++ b/lib/prototypes.h +@@ -160,6 +160,8 @@ extern int getlong (const char *numstr, /*@out@*/long int *result); + + /* get_pid.c */ + extern int get_pid (const char *pidstr, pid_t *pid); ++extern int get_pidfd_from_fd(const char *pidfdstr); ++extern int open_pidfd(const char *pidstr); + + /* getrange */ + extern int getrange (const char *range, +diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml +index e4ebc69e..9b7683eb 100644 +--- a/man/newgidmap.1.xml ++++ b/man/newgidmap.1.xml +@@ -116,6 +116,17 @@ + + Note that newgidmap may be used only once for a given process. + ++ ++ Instead of an integer process id, the first argument may be ++ specified as fd:N, where the integer N ++ is the file descriptor number for the calling process's opened ++ file for /proc/[pid[. In this case, ++ newgidmap will use ++ openat2 ++ to open the gid_map file under that ++ directory, avoiding a TOCTTOU in case the process exits and ++ the pid is immediately reused. ++ + + + +diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml +index f5cb5b48..ca917a77 100644 +--- a/man/newuidmap.1.xml ++++ b/man/newuidmap.1.xml +@@ -116,6 +116,17 @@ + + Note that newuidmap may be used only once for a given process. + ++ ++ Instead of an integer process id, the first argument may be ++ specified as fd:N, where the integer N ++ is the file descriptor number for the calling process's opened ++ file for /proc/[pid[. In this case, ++ newuidmap will use ++ openat2 ++ to open the uid_map file under that ++ directory, avoiding a TOCTTOU in case the process exits and ++ the pid is immediately reused. ++ + + + +diff --git a/src/newgidmap.c b/src/newgidmap.c +index 01d0fe90..d6d29725 100644 +--- a/src/newgidmap.c ++++ b/src/newgidmap.c +@@ -69,7 +69,7 @@ static void verify_ranges(struct passwd *pw, int ranges, + + static void usage(void) + { +- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); ++ fprintf(stderr, _("usage: %s [] [ ] ... \n"), Prog); + exit(EXIT_FAILURE); + } + +@@ -143,15 +143,12 @@ out: + */ + int main(int argc, char **argv) + { +- char proc_dir_name[32]; + char *target_str; +- pid_t target; + int proc_dir_fd; + int ranges; + struct map_range *mappings; + struct stat st; + struct passwd *pw; +- int written; + bool allow_setgroups = false; + + Prog = Basename (argv[0]); +@@ -168,25 +165,19 @@ int main(int argc, char **argv) + /* Find the process that needs its user namespace + * gid mapping set. + */ +- target_str = argv[1]; +- if (!get_pid(target_str, &target)) +- usage(); + +- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ +- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", +- target); +- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { +- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", +- Prog, strerror(errno)); +- } +- +- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); +- if (proc_dir_fd < 0) { +- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), +- Prog, target); +- return EXIT_FAILURE; ++ target_str = argv[1]; ++ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { ++ /* the user passed in a /proc/pid fd for the process */ ++ target_str = &target_str[3]; ++ proc_dir_fd = get_pidfd_from_fd(target_str); ++ if (proc_dir_fd < 0) ++ usage(); ++ } else { ++ proc_dir_fd = open_pidfd(target_str); ++ if (proc_dir_fd < 0) ++ usage(); + } +- + /* Who am i? */ + pw = get_my_pwent (); + if (NULL == pw) { +@@ -200,8 +191,8 @@ int main(int argc, char **argv) + + /* Get the effective uid and effective gid of the target process */ + if (fstat(proc_dir_fd, &st) < 0) { +- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), +- Prog, target); ++ fprintf(stderr, _("%s: Could not stat directory for process\n"), ++ Prog); + return EXIT_FAILURE; + } + +@@ -213,8 +204,8 @@ int main(int argc, char **argv) + (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || + (pw->pw_uid != st.st_uid) || + (getgid() != st.st_gid)) { +- fprintf(stderr, _( "%s: Target %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), +- Prog, target, ++ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), ++ Prog, + (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, + (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); + return EXIT_FAILURE; +diff --git a/src/newuidmap.c b/src/newuidmap.c +index e8798409..e99655c9 100644 +--- a/src/newuidmap.c ++++ b/src/newuidmap.c +@@ -64,7 +64,7 @@ static void verify_ranges(struct passwd *pw, int ranges, + + static void usage(void) + { +- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); ++ fprintf(stderr, _("usage: %s [|fd:] [ ] ... \n"), Prog); + exit(EXIT_FAILURE); + } + +@@ -73,15 +73,12 @@ static void usage(void) + */ + int main(int argc, char **argv) + { +- char proc_dir_name[32]; + char *target_str; +- pid_t target; + int proc_dir_fd; + int ranges; + struct map_range *mappings; + struct stat st; + struct passwd *pw; +- int written; + + Prog = Basename (argv[0]); + log_set_progname(Prog); +@@ -94,26 +91,20 @@ int main(int argc, char **argv) + if (argc < 2) + usage(); + ++ target_str = argv[1]; + /* Find the process that needs its user namespace + * uid mapping set. + */ +- target_str = argv[1]; +- if (!get_pid(target_str, &target)) +- usage(); +- +- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ +- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", +- target); +- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { +- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", +- Prog, strerror(errno)); +- } +- +- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); +- if (proc_dir_fd < 0) { +- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), +- Prog, target); +- return EXIT_FAILURE; ++ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { ++ /* the user passed in a /proc/pid fd for the process */ ++ target_str = &target_str[3]; ++ proc_dir_fd = get_pidfd_from_fd(target_str); ++ if (proc_dir_fd < 0) ++ usage(); ++ } else { ++ proc_dir_fd = open_pidfd(target_str); ++ if (proc_dir_fd < 0) ++ usage(); + } + + /* Who am i? */ +@@ -129,8 +120,7 @@ int main(int argc, char **argv) + + /* Get the effective uid and effective gid of the target process */ + if (fstat(proc_dir_fd, &st) < 0) { +- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), +- Prog, target); ++ fprintf(stderr, _("%s: Could not stat directory for target process\n"), Prog); + return EXIT_FAILURE; + } + +@@ -142,8 +132,8 @@ int main(int argc, char **argv) + (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || + (pw->pw_uid != st.st_uid) || + (getgid() != st.st_gid)) { +- fprintf(stderr, _( "%s: Target process %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), +- Prog, target, ++ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), ++ Prog, + (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, + (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); + return EXIT_FAILURE; +-- +2.39.2 + +From 7ff33fae6f9cd79c0e012671c37a172e9a681d0b Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Fri, 24 Feb 2023 13:52:32 -0600 +Subject: [PATCH] get_pidfd_from_fd: return -1 on error, not 0 + +Fixes: 6974df39a: newuidmap and newgidmap: support passing pid as fd +Signed-off-by: Serge Hallyn +--- + lib/get_pid.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/get_pid.c b/lib/get_pid.c +index ab91d158..5b6d9da4 100644 +--- a/lib/get_pid.c ++++ b/lib/get_pid.c +@@ -35,6 +35,7 @@ int get_pid (const char *pidstr, pid_t *pid) + /* + * If use passed in fd:4 as an argument, then return the + * value '4', the fd to use. ++ * On error, return -1. + */ + int get_pidfd_from_fd(const char *pidfdstr) + { +@@ -47,7 +48,7 @@ int get_pidfd_from_fd(const char *pidfdstr) + || ('\0' != *endptr) + || (ERANGE == errno) + || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { +- return 0; ++ return -1; + } + + return (int)val; +-- +2.39.2 + +From 05e2adf509ba0e3779dae66a276b86927a8e1e0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Vin=C3=ADcius=20dos=20Santos=20Oliveira?= + +Date: Fri, 24 Feb 2023 18:06:02 -0300 +Subject: [PATCH] Validate fds created by the user + +write_mapping() will do the following: + +openat(proc_dir_fd, map_file, O_WRONLY); + +An attacker could create a directory containing a symlink named +"uid_map" pointing to any file owned by root, and thus allow him to +overwrite any root-owned file. +--- + lib/get_pid.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/lib/get_pid.c b/lib/get_pid.c +index 5b6d9da4..8e5e6014 100644 +--- a/lib/get_pid.c ++++ b/lib/get_pid.c +@@ -41,6 +41,8 @@ int get_pidfd_from_fd(const char *pidfdstr) + { + long long int val; + char *endptr; ++ struct stat st; ++ dev_t proc_st_dev, proc_st_rdev; + + errno = 0; + val = strtoll (pidfdstr, &endptr, 10); +@@ -51,6 +53,21 @@ int get_pidfd_from_fd(const char *pidfdstr) + return -1; + } + ++ if (stat("/proc/self/uid_map", &st) < 0) { ++ return -1; ++ } ++ ++ proc_st_dev = st.st_dev; ++ proc_st_rdev = st.st_rdev; ++ ++ if (fstat(val, &st) < 0) { ++ return -1; ++ } ++ ++ if (st.st_dev != proc_st_dev || st.st_rdev != proc_st_rdev) { ++ return -1; ++ } ++ + return (int)val; + } + +-- +2.39.2 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 74e1c42..0ec578b 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.13 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -25,13 +25,19 @@ Patch1: shadow-4.13-default-range.patch Patch2: shadow-4.9-manfix.patch # Date parsing improvement - could be upstreamed Patch3: shadow-4.2.1-date-parsing.patch -# Audit message changes - upstreamability unknown +# Audit message changes - partially upstreamed +# https://github.com/shadow-maint/shadow/commit/37412f505ed0bc5c9e3f04b2266b40f8f6fc310f Patch4: shadow-4.11.1-audit-update.patch # Changes related to password unlocking - could be upstreamed Patch5: shadow-4.5-usermod-unlock.patch # Additional SElinux related changes - upstreamability unknown Patch6: shadow-4.12.3-selinux-perms.patch +# https://github.com/shadow-maint/shadow/commit/a281f241b592aec636d1b93a99e764499d68c7ef Patch7: shadow-utils-configure-gshadow.patch +# https://github.com/shadow-maint/shadow/commit/6974df39a708abf8bafbdfa2b7827e0f70f874cb +# https://github.com/shadow-maint/shadow/commit/7ff33fae6f9cd79c0e012671c37a172e9a681d0b +# https://github.com/shadow-maint/shadow/commit/05e2adf509ba0e3779dae66a276b86927a8e1e0e +Patch8: shadow-4.13-newidmap-support-passing-pid-as-fd.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -100,6 +106,7 @@ Development files for shadow-utils-subid. %patch5 -p1 -b .unlock %patch6 -p1 -b .selinux-perms %patch7 -p1 +%patch8 -p1 -b .newidmap-pid-fd iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -273,6 +280,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Mar 2 2023 Iker Pedrosa - 2:4.13-5 +- newuidmap and newgidmap: support passing pid as fd. Resolves: #2174752 + * Sat Jan 21 2023 Fedora Release Engineering - 2:4.13-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild From fd05b1cb1a183db7af622b34c9cf7c3994808475 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 6 Mar 2023 12:05:17 +0100 Subject: [PATCH 054/118] Add build dependencies Add libbsd-devel and libeconf-devel as build dependencies Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 0ec578b..438e9ca 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.13 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -57,6 +57,8 @@ BuildRequires: gettext-devel BuildRequires: itstool BuildRequires: libacl-devel BuildRequires: libattr-devel +BuildRequires: libbsd-devel +BuildRequires: libeconf-devel BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: libsemanage-devel BuildRequires: libtool @@ -280,6 +282,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Mar 6 2023 Iker Pedrosa - 2:4.13-6 +- Add libbsd-devel and libeconf-devel as build dependencies + * Thu Mar 2 2023 Iker Pedrosa - 2:4.13-5 - newuidmap and newgidmap: support passing pid as fd. Resolves: #2174752 From 14b1f3518c8e3837f868b719c1f7d3ebb6db62e6 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Tue, 6 Jun 2023 19:30:55 -0400 Subject: [PATCH 055/118] Remove unused libbsd-devel dependency libbsd is unwanted in RHEL, but the resulting binaries show no dependency on libbsd anyway. --- shadow-utils.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 438e9ca..d164957 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.13 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -57,7 +57,6 @@ BuildRequires: gettext-devel BuildRequires: itstool BuildRequires: libacl-devel BuildRequires: libattr-devel -BuildRequires: libbsd-devel BuildRequires: libeconf-devel BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: libsemanage-devel @@ -282,6 +281,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jun 06 2023 Yaakov Selkowitz - 2:4.13-7 +- Remove unused libbsd-devel dependency + * Mon Mar 6 2023 Iker Pedrosa - 2:4.13-6 - Add libbsd-devel and libeconf-devel as build dependencies From 874ece902889ef407a933f712ef550f31b822135 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 22 Jul 2023 01:31:45 +0000 Subject: [PATCH 056/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index d164957..419b8d0 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.13 -Release: 7%{?dist} +Release: 8%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -281,6 +281,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jul 22 2023 Fedora Release Engineering - 2:4.13-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + * Tue Jun 06 2023 Yaakov Selkowitz - 2:4.13-7 - Remove unused libbsd-devel dependency From 5cab3439c8ffe4e07ec09aa9acf5112348e80a0c Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Wed, 2 Aug 2023 16:33:21 +0200 Subject: [PATCH 057/118] Use %autosetup instead of obsoleted %patchX macros Also use -S git instead of suffixes, see https://rpm-software-management.github.io/rpm/manual/autosetup.html Fixes: RPM build warnings: %patchN is deprecated (9 usages found), use %patch N (or %patch -P N) Signed-off-by: Petr Lautrbach --- shadow-utils.spec | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 419b8d0..8ee19af 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -54,6 +54,7 @@ BuildRequires: docbook-style-xsl BuildRequires: flex BuildRequires: gcc BuildRequires: gettext-devel +BuildRequires: git BuildRequires: itstool BuildRequires: libacl-devel BuildRequires: libattr-devel @@ -98,16 +99,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%setup -q -n shadow-%{version} -%patch0 -p1 -b .redhat -%patch1 -p1 -b .default-range -%patch2 -p1 -b .manfix -%patch3 -p1 -b .date-parsing -%patch4 -p1 -b .audit-update -%patch5 -p1 -b .unlock -%patch6 -p1 -b .selinux-perms -%patch7 -p1 -%patch8 -p1 -b .newidmap-pid-fd +%autosetup -p 1 -S git -n shadow-%{version} iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO From 799aaaa5088cde64c65f2897d9c335c52e4de0bc Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 16 Aug 2023 10:55:53 +0200 Subject: [PATCH 058/118] Rebase to version 4.14.0 Resolves: #2229000 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.12.3-redhat.patch | 38 - shadow-4.12.3-selinux-perms.patch | 240 ----- shadow-4.13-default-range.patch | 35 - ....patch => shadow-4.14.0-audit-update.patch | 970 +++++++----------- ...manfix.patch => shadow-4.14.0-manfix.patch | 2 +- shadow-4.5-usermod-unlock.patch | 64 -- shadow-utils.spec | 33 +- sources | 4 +- 9 files changed, 381 insertions(+), 1007 deletions(-) delete mode 100644 shadow-4.12.3-redhat.patch delete mode 100644 shadow-4.12.3-selinux-perms.patch delete mode 100644 shadow-4.13-default-range.patch rename shadow-4.11.1-audit-update.patch => shadow-4.14.0-audit-update.patch (66%) rename shadow-4.9-manfix.patch => shadow-4.14.0-manfix.patch (99%) delete mode 100644 shadow-4.5-usermod-unlock.patch diff --git a/.gitignore b/.gitignore index 44cb6ed..422ed12 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.12.3.tar.xz.asc /shadow-4.13.tar.xz /shadow-4.13.tar.xz.asc +/shadow-4.14.0.tar.xz +/shadow-4.14.0.tar.xz.asc diff --git a/shadow-4.12.3-redhat.patch b/shadow-4.12.3-redhat.patch deleted file mode 100644 index 48c591d..0000000 --- a/shadow-4.12.3-redhat.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff -up shadow-4.12.3/src/useradd.c.redhat shadow-4.12.3/src/useradd.c ---- shadow-4.12.3/src/useradd.c.redhat 2022-08-06 18:22:45.000000000 +0200 -+++ shadow-4.12.3/src/useradd.c 2022-08-22 15:57:19.034664441 +0200 -@@ -82,7 +82,7 @@ const char *Prog; - static gid_t def_group = 1000; - static const char *def_gname = "other"; - static const char *def_home = "/home"; --static const char *def_shell = "/bin/bash"; -+static const char *def_shell = "/sbin/nologin"; - static const char *def_template = SKEL_DIR; - static const char *def_create_mail_spool = "yes"; - static const char *def_log_init = "yes"; -@@ -93,7 +93,7 @@ static const char *def_expire = ""; - #define VALID(s) (strcspn (s, ":\n") == strlen (s)) - - static const char *user_name = ""; --static const char *user_pass = "!"; -+static const char *user_pass = "!!"; - static uid_t user_id; - static gid_t user_gid; - static const char *user_comment = ""; -@@ -1227,7 +1227,7 @@ static void process_flags (int argc, cha - {NULL, 0, NULL, '\0'} - }; - while ((c = getopt_long (argc, argv, -- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U" -+ "b:c:d:De:f:g:G:hk:K:lmMnNop:rR:P:s:u:U" - #ifdef WITH_SELINUX - "Z:" - #endif /* WITH_SELINUX */ -@@ -1395,6 +1395,7 @@ static void process_flags (int argc, cha - case 'M': - Mflg = true; - break; -+ case 'n': - case 'N': - Nflg = true; - break; diff --git a/shadow-4.12.3-selinux-perms.patch b/shadow-4.12.3-selinux-perms.patch deleted file mode 100644 index f396455..0000000 --- a/shadow-4.12.3-selinux-perms.patch +++ /dev/null @@ -1,240 +0,0 @@ -diff -up shadow-4.12.3/src/chgpasswd.c.selinux-perms shadow-4.12.3/src/chgpasswd.c ---- shadow-4.12.3/src/chgpasswd.c.selinux-perms 2022-06-19 16:16:48.000000000 +0200 -+++ shadow-4.12.3/src/chgpasswd.c 2022-08-22 16:09:02.006970030 +0200 -@@ -16,6 +16,13 @@ - #include - #include - #include -+#ifdef WITH_SELINUX -+#include -+#include -+#endif -+#ifdef WITH_LIBAUDIT -+#include -+#endif - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - #include "pam_defs.h" -@@ -61,6 +68,9 @@ static bool sgr_locked = false; - #endif - static bool gr_locked = false; - -+/* The name of the caller */ -+static char *myname = NULL; -+ - /* local function prototypes */ - static void fail_exit (int code); - static /*@noreturn@*/void usage (int status); -@@ -318,6 +328,63 @@ static void check_perms (void) - #endif /* ACCT_TOOLS_SETUID */ - } - -+#ifdef WITH_SELINUX -+static int -+log_callback (int type, const char *fmt, ...) -+{ -+ int audit_fd; -+ va_list ap; -+ -+ va_start(ap, fmt); -+#ifdef WITH_AUDIT -+ audit_fd = audit_open(); -+ -+ if (audit_fd >= 0) { -+ char *buf; -+ -+ if (vasprintf (&buf, fmt, ap) < 0) -+ goto ret; -+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, -+ NULL, 0); -+ audit_close(audit_fd); -+ free(buf); -+ goto ret; -+ } -+ -+#endif -+ vsyslog (LOG_USER | LOG_INFO, fmt, ap); -+ret: -+ va_end(ap); -+ return 0; -+} -+ -+static void -+selinux_check_root (void) -+{ -+ int status = -1; -+ security_context_t user_context; -+ union selinux_callback old_callback; -+ -+ if (is_selinux_enabled() < 1) -+ return; -+ -+ old_callback = selinux_get_callback(SELINUX_CB_LOG); -+ /* setup callbacks */ -+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); -+ if ((status = getprevcon(&user_context)) < 0) { -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ exit(1); -+ } -+ -+ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); -+ -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ freecon(user_context); -+ if (status != 0 && security_getenforce() != 0) -+ exit(1); -+} -+#endif -+ - /* - * open_files - lock and open the group databases - */ -@@ -411,6 +478,7 @@ int main (int argc, char **argv) - - const struct group *gr; - struct group newgr; -+ struct passwd *pw = NULL; - int errors = 0; - int line = 0; - -@@ -422,12 +490,37 @@ int main (int argc, char **argv) - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); - -+#ifdef WITH_SELINUX -+ selinux_check_root (); -+#endif -+ - process_root_flag ("-R", argc, argv); - - process_flags (argc, argv); - - OPENLOG ("chgpasswd"); - -+#ifdef WITH_AUDIT -+ audit_help_open (); -+#endif -+ -+ /* -+ * Determine the name of the user that invoked this command. This -+ * is really hit or miss because there are so many ways that command -+ * can be executed and so many ways to trip up the routines that -+ * report the user name. -+ */ -+ pw = get_my_pwent (); -+ if (NULL == pw) { -+ fprintf (stderr, _("%s: Cannot determine your user name.\n"), -+ Prog); -+ SYSLOG ((LOG_WARN, -+ "Cannot determine the user name of the caller (UID %lu)", -+ (unsigned long) getuid ())); -+ exit (E_NOPERM); -+ } -+ myname = xstrdup (pw->pw_name); -+ - check_perms (); - - #ifdef SHADOWGRP -diff -up shadow-4.12.3/src/chpasswd.c.selinux-perms shadow-4.12.3/src/chpasswd.c ---- shadow-4.12.3/src/chpasswd.c.selinux-perms 2022-06-19 16:16:48.000000000 +0200 -+++ shadow-4.12.3/src/chpasswd.c 2022-08-22 16:10:56.702835681 +0200 -@@ -16,6 +16,13 @@ - #include - #include - #include -+#ifdef WITH_SELINUX -+#include -+#include -+#endif -+#ifdef WITH_LIBAUDIT -+#include -+#endif - #ifdef USE_PAM - #include "pam_defs.h" - #endif /* USE_PAM */ -@@ -318,6 +325,63 @@ static void check_perms (void) - #endif /* USE_PAM */ - } - -+#ifdef WITH_SELINUX -+static int -+log_callback (int type, const char *fmt, ...) -+{ -+ int audit_fd; -+ va_list ap; -+ -+ va_start(ap, fmt); -+#ifdef WITH_AUDIT -+ audit_fd = audit_open(); -+ -+ if (audit_fd >= 0) { -+ char *buf; -+ -+ if (vasprintf (&buf, fmt, ap) < 0) -+ goto ret; -+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, -+ NULL, 0); -+ audit_close(audit_fd); -+ free(buf); -+ goto ret; -+ } -+ -+#endif -+ vsyslog (LOG_USER | LOG_INFO, fmt, ap); -+ret: -+ va_end(ap); -+ return 0; -+} -+ -+static void -+selinux_check_root (void) -+{ -+ int status = -1; -+ security_context_t user_context; -+ union selinux_callback old_callback; -+ -+ if (is_selinux_enabled() < 1) -+ return; -+ -+ old_callback = selinux_get_callback(SELINUX_CB_LOG); -+ /* setup callbacks */ -+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback); -+ if ((status = getprevcon(&user_context)) < 0) { -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ exit(1); -+ } -+ -+ status = selinux_check_access(user_context, user_context, "passwd", "passwd", NULL); -+ -+ selinux_set_callback(SELINUX_CB_LOG, old_callback); -+ freecon(user_context); -+ if (status != 0 && security_getenforce() != 0) -+ exit(1); -+} -+#endif -+ - /* - * open_files - lock and open the password databases - */ -@@ -450,6 +514,10 @@ int main (int argc, char **argv) - (void) bindtextdomain (PACKAGE, LOCALEDIR); - (void) textdomain (PACKAGE); - -+#ifdef WITH_SELINUX -+ selinux_check_root (); -+#endif -+ - process_flags (argc, argv); - - salt = get_salt(); -@@ -463,6 +531,10 @@ int main (int argc, char **argv) - - OPENLOG ("chpasswd"); - -+#ifdef WITH_AUDIT -+ audit_help_open (); -+#endif -+ - check_perms (); - - #ifdef USE_PAM diff --git a/shadow-4.13-default-range.patch b/shadow-4.13-default-range.patch deleted file mode 100644 index f199b39..0000000 --- a/shadow-4.13-default-range.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff -up shadow-4.13/lib/semanage.c.default-range shadow-4.13/lib/semanage.c ---- shadow-4.13/lib/semanage.c.default-range 2022-11-09 09:37:11.955314964 +0100 -+++ shadow-4.13/lib/semanage.c 2022-11-09 09:47:59.130645564 +0100 -@@ -122,6 +122,7 @@ static int semanage_user_mod (semanage_h - goto done; - } - -+#if 0 - if (semanage_mls_enabled(handle)) { - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { -@@ -131,6 +132,7 @@ static int semanage_user_mod (semanage_h - goto done; - } - } -+#endif - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { -@@ -181,6 +183,7 @@ static int semanage_user_add (semanage_h - goto done; - } - -+#if 0 - if (semanage_mls_enabled(handle)) { - ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE); - if (ret != 0) { -@@ -190,6 +193,7 @@ static int semanage_user_add (semanage_h - goto done; - } - } -+#endif - - ret = semanage_seuser_set_sename (handle, seuser, seuser_name); - if (ret != 0) { diff --git a/shadow-4.11.1-audit-update.patch b/shadow-4.14.0-audit-update.patch similarity index 66% rename from shadow-4.11.1-audit-update.patch rename to shadow-4.14.0-audit-update.patch index 65acae0..0ff7dae 100644 --- a/shadow-4.11.1-audit-update.patch +++ b/shadow-4.14.0-audit-update.patch @@ -1,6 +1,6 @@ -diff -up shadow-4.11.1/libmisc/audit_help.c.audit-update shadow-4.11.1/libmisc/audit_help.c ---- shadow-4.11.1/libmisc/audit_help.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/libmisc/audit_help.c 2022-01-03 15:15:38.946046192 +0100 +diff -up shadow-4.14.0/libmisc/audit_help.c.audit-update shadow-4.14.0/libmisc/audit_help.c +--- shadow-4.14.0/libmisc/audit_help.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.14.0/libmisc/audit_help.c 2023-08-04 09:30:25.206963536 +0200 @@ -46,7 +46,7 @@ void audit_help_open (void) * This function will log a message to the audit system using a predefined * message format. Parameter usage is as follows: @@ -50,9 +50,9 @@ diff -up shadow-4.11.1/libmisc/audit_help.c.audit-update shadow-4.11.1/libmisc/a void audit_logger_message (const char *message, shadow_audit_result result) { if (audit_fd < 0) { -diff -up shadow-4.11.1/libmisc/cleanup_group.c.audit-update shadow-4.11.1/libmisc/cleanup_group.c ---- shadow-4.11.1/libmisc/cleanup_group.c.audit-update 2022-01-03 14:57:01.777006776 +0100 -+++ shadow-4.11.1/libmisc/cleanup_group.c 2022-01-03 15:22:27.438770608 +0100 +diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmisc/cleanup_group.c +--- shadow-4.14.0/libmisc/cleanup_group.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.14.0/libmisc/cleanup_group.c 2023-08-04 09:30:25.207963539 +0200 @@ -61,7 +61,7 @@ void cleanup_report_mod_group (void *cle gr_dbname (), info->action)); @@ -131,9 +131,9 @@ diff -up shadow-4.11.1/libmisc/cleanup_group.c.audit-update shadow-4.11.1/libmis SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.11.1/libmisc/cleanup_user.c.audit-update shadow-4.11.1/libmisc/cleanup_user.c ---- shadow-4.11.1/libmisc/cleanup_user.c.audit-update 2022-01-03 14:57:01.777006776 +0100 -+++ shadow-4.11.1/libmisc/cleanup_user.c 2022-01-03 15:21:22.593338130 +0100 +diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc/cleanup_user.c +--- shadow-4.14.0/libmisc/cleanup_user.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.14.0/libmisc/cleanup_user.c 2023-08-04 09:30:25.207963539 +0200 @@ -43,7 +43,7 @@ void cleanup_report_mod_passwd (void *cl pw_dbname (), info->action)); @@ -181,10 +181,10 @@ diff -up shadow-4.11.1/libmisc/cleanup_user.c.audit-update shadow-4.11.1/libmisc SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.11.1/lib/prototypes.h.audit-update shadow-4.11.1/lib/prototypes.h ---- shadow-4.11.1/lib/prototypes.h.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/lib/prototypes.h 2022-01-03 14:57:01.777006776 +0100 -@@ -197,12 +197,21 @@ extern int audit_fd; +diff -up shadow-4.14.0/lib/prototypes.h.audit-update shadow-4.14.0/lib/prototypes.h +--- shadow-4.14.0/lib/prototypes.h.audit-update 2023-08-03 18:28:35.000000000 +0200 ++++ shadow-4.14.0/lib/prototypes.h 2023-08-04 09:30:25.207963539 +0200 +@@ -202,12 +202,21 @@ extern int audit_fd; extern void audit_help_open (void); /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ #define AUDIT_NO_ID ((unsigned int) -1) @@ -206,100 +206,91 @@ diff -up shadow-4.11.1/lib/prototypes.h.audit-update shadow-4.11.1/lib/prototype void audit_logger_message (const char *message, shadow_audit_result result); #endif -diff -up shadow-4.11.1/src/chage.c.audit-update shadow-4.11.1/src/chage.c ---- shadow-4.11.1/src/chage.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/chage.c 2022-01-03 14:57:01.777006776 +0100 -@@ -100,9 +100,10 @@ static /*@noreturn@*/void fail_exit (int +diff -up shadow-4.14.0/src/chage.c.audit-update shadow-4.14.0/src/chage.c +--- shadow-4.14.0/src/chage.c.audit-update 2023-08-04 09:30:25.207963539 +0200 ++++ shadow-4.14.0/src/chage.c 2023-08-04 09:31:12.237080212 +0200 +@@ -106,8 +106,8 @@ fail_exit (int code) #ifdef WITH_AUDIT if (E_SUCCESS != code) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change age", -- user_name, (unsigned int) user_uid, 0); +- "change age", user_name, user_uid, 0); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-age", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_FAILURE); ++ "change-age", user_name, user_uid, SHADOW_AUDIT_FAILURE); } #endif -@@ -837,11 +838,7 @@ int main (int argc, char **argv) +@@ -841,10 +841,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } -#ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "display aging info", -- user_name, (unsigned int) user_uid, 1); +- "display aging info", user_name, user_uid, 1); -#endif + /* Displaying fields is not of interest to audit */ list_fields (); fail_exit (E_SUCCESS); } -@@ -860,41 +857,43 @@ int main (int argc, char **argv) +@@ -863,39 +860,39 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT else { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "change all aging information", -- user_name, (unsigned int) user_uid, 1); +- user_name, user_uid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, + "change-all-aging-information", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_SUCCESS); ++ user_name, user_uid, SHADOW_AUDIT_SUCCESS); } #endif } else { #ifdef WITH_AUDIT if (Mflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change max age", -- user_name, (unsigned int) user_uid, 1); +- "change max age", user_name, user_uid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-max-age", -+ user_name, (unsigned int) user_uid, -+ SHADOW_AUDIT_SUCCESS); ++ "change-max-age", user_name, user_uid, SHADOW_AUDIT_SUCCESS); } if (mflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change min age", +- "change min age", user_name, user_uid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-min-age", - user_name, (unsigned int) user_uid, 1); ++ "change-min-age", user_name, user_uid, 1); } if (dflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "change last change date", + audit_logger (AUDIT_USER_MGMT, Prog, + "change-last-change-date", - user_name, (unsigned int) user_uid, 1); + user_name, user_uid, 1); } if (Wflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "change passwd warning", + audit_logger (AUDIT_USER_MGMT, Prog, + "change-passwd-warning", - user_name, (unsigned int) user_uid, 1); + user_name, user_uid, 1); } if (Iflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "change inactive days", + audit_logger (AUDIT_USER_MGMT, Prog, + "change-inactive-days", - user_name, (unsigned int) user_uid, 1); + user_name, user_uid, 1); } if (Eflg) { - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "change passwd expiration", + audit_logger (AUDIT_USER_MGMT, Prog, + "change-passwd-expiration", - user_name, (unsigned int) user_uid, 1); + user_name, user_uid, 1); } #endif -diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c ---- shadow-4.11.1/src/gpasswd.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/gpasswd.c 2022-01-03 14:57:01.778006782 +0100 -@@ -116,7 +116,7 @@ static void usage (int status) +diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c +--- shadow-4.14.0/src/gpasswd.c.audit-update 2023-06-11 03:35:50.000000000 +0200 ++++ shadow-4.14.0/src/gpasswd.c 2023-08-04 09:30:25.207963539 +0200 +@@ -118,7 +118,7 @@ static void usage (int status) (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); @@ -308,7 +299,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); #ifdef SHADOWGRP -@@ -375,21 +375,14 @@ static void open_files (void) +@@ -377,21 +377,14 @@ static void open_files (void) static void log_gpasswd_failure (const char *suffix) { @@ -333,7 +324,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (dflg) { -@@ -397,13 +390,9 @@ static void log_gpasswd_failure (const c +@@ -399,13 +392,9 @@ static void log_gpasswd_failure (const c "%s failed to remove user %s from group %s%s", myname, user, group, suffix)); #ifdef WITH_AUDIT @@ -350,7 +341,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (rflg) { -@@ -411,13 +400,9 @@ static void log_gpasswd_failure (const c +@@ -413,13 +402,9 @@ static void log_gpasswd_failure (const c "%s failed to remove password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -367,7 +358,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Rflg) { -@@ -425,13 +410,9 @@ static void log_gpasswd_failure (const c +@@ -427,13 +412,9 @@ static void log_gpasswd_failure (const c "%s failed to restrict access to group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -384,7 +375,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Aflg || Mflg) { -@@ -441,13 +422,9 @@ static void log_gpasswd_failure (const c +@@ -443,13 +424,9 @@ static void log_gpasswd_failure (const c "%s failed to set the administrators of group %s to %s%s", myname, group, admins, suffix)); #ifdef WITH_AUDIT @@ -401,7 +392,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -457,13 +434,9 @@ static void log_gpasswd_failure (const c +@@ -459,13 +436,9 @@ static void log_gpasswd_failure (const c "%s failed to set the members of group %s to %s%s", myname, group, members, suffix)); #ifdef WITH_AUDIT @@ -418,7 +409,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -472,13 +445,9 @@ static void log_gpasswd_failure (const c +@@ -474,13 +447,9 @@ static void log_gpasswd_failure (const c "%s failed to change password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -435,7 +426,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -509,21 +478,14 @@ static void log_gpasswd_failure_gshadow +@@ -511,21 +480,14 @@ static void log_gpasswd_failure_gshadow static void log_gpasswd_success (const char *suffix) { @@ -460,7 +451,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (dflg) { -@@ -531,13 +493,9 @@ static void log_gpasswd_success (const c +@@ -533,13 +495,9 @@ static void log_gpasswd_success (const c "user %s removed by %s from group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT @@ -477,7 +468,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (rflg) { -@@ -545,13 +503,9 @@ static void log_gpasswd_success (const c +@@ -547,13 +505,9 @@ static void log_gpasswd_success (const c "password of group %s removed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -494,7 +485,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Rflg) { -@@ -559,13 +513,9 @@ static void log_gpasswd_success (const c +@@ -561,13 +515,9 @@ static void log_gpasswd_success (const c "access to group %s restricted by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -511,7 +502,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Aflg || Mflg) { -@@ -575,13 +525,9 @@ static void log_gpasswd_success (const c +@@ -577,13 +527,9 @@ static void log_gpasswd_success (const c "administrators of group %s set by %s to %s%s", group, myname, admins, suffix)); #ifdef WITH_AUDIT @@ -528,7 +519,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -591,13 +537,9 @@ static void log_gpasswd_success (const c +@@ -593,13 +539,9 @@ static void log_gpasswd_success (const c "members of group %s set by %s to %s%s", group, myname, members, suffix)); #ifdef WITH_AUDIT @@ -545,7 +536,7 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -606,13 +548,9 @@ static void log_gpasswd_success (const c +@@ -608,13 +550,9 @@ static void log_gpasswd_success (const c "password of group %s changed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -562,10 +553,10 @@ diff -up shadow-4.11.1/src/gpasswd.c.audit-update shadow-4.11.1/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c ---- shadow-4.11.1/src/groupadd.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/groupadd.c 2022-01-03 14:57:01.778006782 +0100 -@@ -111,6 +111,15 @@ static /*@noreturn@*/void usage (int sta +diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c +--- shadow-4.14.0/src/groupadd.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.14.0/src/groupadd.c 2023-08-04 09:34:34.125581046 +0200 +@@ -114,6 +114,15 @@ usage (int status) exit (status); } @@ -581,7 +572,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c /* * new_grent - initialize the values in a group file entry * -@@ -207,7 +216,7 @@ static void grp_update (void) +@@ -210,7 +219,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), grp.gr_name); @@ -590,7 +581,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } #ifdef SHADOWGRP /* -@@ -217,7 +226,7 @@ static void grp_update (void) +@@ -220,7 +229,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), sgrp.sg_name); @@ -599,7 +590,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } #endif /* SHADOWGRP */ } -@@ -241,7 +250,7 @@ static void check_new_name (void) +@@ -244,7 +253,7 @@ static void check_new_name (void) fprintf (stderr, _("%s: '%s' is not a valid group name\n"), Prog, group_name); @@ -608,7 +599,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } /* -@@ -257,11 +266,11 @@ static void close_files (void) +@@ -260,11 +269,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); @@ -619,10 +610,10 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c audit_logger (AUDIT_ADD_GROUP, Prog, - "adding group to /etc/group", + "add-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); + group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -279,11 +288,11 @@ static void close_files (void) + SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u", +@@ -281,11 +290,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); @@ -634,23 +625,21 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c - "adding group to /etc/gshadow", + audit_logger (AUDIT_GRP_MGMT, Prog, + "add-shadow-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); + group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -297,12 +306,6 @@ static void close_files (void) + SYSLOG ((LOG_INFO, "group added to %s: name=%s", +@@ -298,10 +307,6 @@ static void close_files (void) #endif /* SHADOWGRP */ /* Report success at the system level */ -#ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "", -- group_name, (unsigned int) group_id, -- SHADOW_AUDIT_SUCCESS); +- "", group_name, group_id, SHADOW_AUDIT_SUCCESS); -#endif SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", group_name, (unsigned int) group_id)); del_cleanup (cleanup_report_add_group); -@@ -320,7 +323,7 @@ static void open_files (void) +@@ -319,7 +324,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -659,7 +648,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } add_cleanup (cleanup_unlock_group, NULL); -@@ -330,7 +333,7 @@ static void open_files (void) +@@ -329,7 +334,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -668,7 +657,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } add_cleanup (cleanup_unlock_gshadow, NULL); } -@@ -346,7 +349,7 @@ static void open_files (void) +@@ -345,7 +350,7 @@ static void open_files (void) if (gr_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); @@ -677,7 +666,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } #ifdef SHADOWGRP -@@ -356,7 +359,7 @@ static void open_files (void) +@@ -355,7 +360,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); @@ -686,7 +675,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } } #endif /* SHADOWGRP */ -@@ -493,7 +496,7 @@ static void check_flags (void) +@@ -492,7 +497,7 @@ static void check_flags (void) fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_name); @@ -695,7 +684,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } if (gflg && (prefix_getgrgid (group_id) != NULL)) { -@@ -512,7 +515,7 @@ static void check_flags (void) +@@ -511,7 +516,7 @@ static void check_flags (void) fprintf (stderr, _("%s: GID '%lu' already exists\n"), Prog, (unsigned long int) group_id); @@ -704,7 +693,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } } } -@@ -540,7 +543,7 @@ static void check_perms (void) +@@ -539,7 +544,7 @@ static void check_perms (void) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -713,7 +702,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); -@@ -560,7 +563,7 @@ static void check_perms (void) +@@ -559,7 +564,7 @@ static void check_perms (void) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -722,7 +711,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -595,7 +598,7 @@ int main (int argc, char **argv) +@@ -594,7 +599,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -731,7 +720,7 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } /* -@@ -617,7 +620,7 @@ int main (int argc, char **argv) +@@ -621,7 +626,7 @@ int main (int argc, char **argv) if (!gflg) { if (find_new_gid (rflg, &group_id, NULL) < 0) { @@ -740,10 +729,10 @@ diff -up shadow-4.11.1/src/groupadd.c.audit-update shadow-4.11.1/src/groupadd.c } } -diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c ---- shadow-4.11.1/src/groupdel.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/groupdel.c 2022-01-03 14:57:01.778006782 +0100 -@@ -84,6 +84,15 @@ static /*@noreturn@*/void usage (int sta +diff -up shadow-4.14.0/src/groupdel.c.audit-update shadow-4.14.0/src/groupdel.c +--- shadow-4.14.0/src/groupdel.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.14.0/src/groupdel.c 2023-08-04 09:36:42.778900250 +0200 +@@ -87,6 +87,15 @@ usage (int status) exit (status); } @@ -759,7 +748,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c /* * grp_update - update group file entries * -@@ -110,7 +119,7 @@ static void grp_update (void) +@@ -113,7 +122,7 @@ static void grp_update (void) fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, group_name, gr_dbname ()); @@ -768,7 +757,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } #ifdef SHADOWGRP -@@ -122,7 +131,7 @@ static void grp_update (void) +@@ -125,7 +134,7 @@ static void grp_update (void) fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, group_name, sgr_dbname ()); @@ -777,7 +766,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } } #endif /* SHADOWGRP */ -@@ -141,12 +150,12 @@ static void close_files (void) +@@ -144,12 +153,12 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); @@ -789,10 +778,10 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c audit_logger (AUDIT_DEL_GROUP, Prog, - "removing group from /etc/group", + "delete-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); + group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -166,12 +175,12 @@ static void close_files (void) + SYSLOG ((LOG_INFO, +@@ -168,12 +177,12 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); @@ -805,24 +794,22 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c - "removing group from /etc/gshadow", + audit_logger (AUDIT_GRP_MGMT, Prog, + "delete-shadow-group", - group_name, (unsigned int) group_id, - SHADOW_AUDIT_SUCCESS); + group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -185,13 +194,6 @@ static void close_files (void) + SYSLOG ((LOG_INFO, +@@ -186,11 +195,6 @@ static void close_files (void) } #endif /* SHADOWGRP */ - /* Report success at the system level */ -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_GROUP, Prog, -- "", -- group_name, (unsigned int) group_id, -- SHADOW_AUDIT_SUCCESS); +- "", group_name, group_id, SHADOW_AUDIT_SUCCESS); -#endif SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); del_cleanup (cleanup_report_del_group); } -@@ -208,7 +210,7 @@ static void open_files (void) +@@ -207,7 +211,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -831,7 +818,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } add_cleanup (cleanup_unlock_group, NULL); #ifdef SHADOWGRP -@@ -217,7 +219,7 @@ static void open_files (void) +@@ -216,7 +220,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -840,7 +827,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } add_cleanup (cleanup_unlock_gshadow, NULL); } -@@ -235,7 +237,7 @@ static void open_files (void) +@@ -234,7 +238,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); @@ -849,7 +836,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } #ifdef SHADOWGRP if (is_shadow_grp) { -@@ -244,7 +246,7 @@ static void open_files (void) +@@ -243,7 +247,7 @@ static void open_files (void) _("%s: cannot open %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); @@ -858,7 +845,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } } #endif /* SHADOWGRP */ -@@ -285,7 +287,7 @@ static void group_busy (gid_t gid) +@@ -284,7 +288,7 @@ static void group_busy (gid_t gid) fprintf (stderr, _("%s: cannot remove the primary group of user '%s'\n"), Prog, pwd->pw_name); @@ -867,7 +854,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } /* -@@ -373,7 +375,7 @@ int main (int argc, char **argv) +@@ -372,7 +376,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -876,7 +863,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } process_flags (argc, argv); -@@ -387,7 +389,7 @@ int main (int argc, char **argv) +@@ -386,7 +390,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -885,7 +872,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); -@@ -408,7 +410,7 @@ int main (int argc, char **argv) +@@ -407,7 +411,7 @@ int main (int argc, char **argv) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -894,7 +881,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -428,7 +430,7 @@ int main (int argc, char **argv) +@@ -427,7 +431,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group '%s' does not exist\n"), Prog, group_name); @@ -903,7 +890,7 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } group_id = grp->gr_gid; -@@ -452,7 +454,7 @@ int main (int argc, char **argv) +@@ -451,7 +455,7 @@ int main (int argc, char **argv) _("%s: %s is the NIS master\n"), Prog, nis_master); } @@ -912,10 +899,10 @@ diff -up shadow-4.11.1/src/groupdel.c.audit-update shadow-4.11.1/src/groupdel.c } #endif -diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c ---- shadow-4.11.1/src/groupmod.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/groupmod.c 2022-01-03 14:57:01.778006782 +0100 -@@ -468,7 +468,7 @@ static void close_files (void) +diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c +--- shadow-4.14.0/src/groupmod.c.audit-update 2023-06-10 02:02:29.000000000 +0200 ++++ shadow-4.14.0/src/groupmod.c 2023-08-04 09:30:25.208963541 +0200 +@@ -473,7 +473,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -924,7 +911,7 @@ diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c info_group.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -491,7 +491,14 @@ static void close_files (void) +@@ -496,7 +496,14 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -940,7 +927,7 @@ diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c info_gshadow.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -514,7 +521,7 @@ static void close_files (void) +@@ -519,7 +526,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -949,7 +936,7 @@ diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c info_passwd.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -529,8 +536,8 @@ static void close_files (void) +@@ -534,8 +541,8 @@ static void close_files (void) } #ifdef WITH_AUDIT @@ -960,168 +947,10 @@ diff -up shadow-4.11.1/src/groupmod.c.audit-update shadow-4.11.1/src/groupmod.c group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -542,6 +549,8 @@ static void close_files (void) - */ - static void prepare_failure_reports (void) - { -+ char *nv_pair, nv[64]; -+ - info_group.name = group_name; - #ifdef SHADOWGRP - info_gshadow.name = group_name; -@@ -554,76 +563,109 @@ static void prepare_failure_reports (voi - #endif - info_passwd.audit_msg = xmalloc (512); - -- (void) snprintf (info_group.audit_msg, 511, -- "changing %s; ", gr_dbname ()); -+ info_group.action = xmalloc (512); - #ifdef SHADOWGRP -- (void) snprintf (info_gshadow.audit_msg, 511, -- "changing %s; ", sgr_dbname ()); -+ info_gshadow.action = xmalloc (512); - #endif -- (void) snprintf (info_passwd.audit_msg, 511, -- "changing %s; ", pw_dbname ()); -+ info_passwd.action = xmalloc (512); - -- info_group.action = info_group.audit_msg -- + strlen (info_group.audit_msg); -+ (void) snprintf (info_group.audit_msg, 511, -+ "changing-group"); - #ifdef SHADOWGRP -- info_gshadow.action = info_gshadow.audit_msg -- + strlen (info_gshadow.audit_msg); -+ (void) snprintf (info_gshadow.audit_msg, 511, -+ "changing-shadow-group"); - #endif -- info_passwd.action = info_passwd.audit_msg -- + strlen (info_passwd.audit_msg); -+ (void) snprintf (info_passwd.audit_msg, 511, -+ "changing-group-passwd"); - -+ nv_pair = audit_encode_nv_string(" grp", group_name, -+ strlen(group_name)); -+ if(nv_pair) { -+ strncat(info_group.audit_msg, nv_pair, -+ 511 - strlen(info_group.audit_msg)); -+#ifdef SHADOWGRP -+ strncat(info_gshadow.audit_msg, nv_pair, -+ 511 - strlen(info_gshadow.audit_msg)); -+#endif -+ strncat(info_passwd.audit_msg, nv_pair, -+ 511 - strlen(info_passwd.audit_msg)); -+ free(nv_pair); -+ } -+ snprintf(nv, sizeof(nv), " gid=%lu", (unsigned long)group_id); -+ strncat(info_group.audit_msg, nv, 511 - strlen(info_group.audit_msg)); -+ strncat(info_passwd.audit_msg, nv, 511 - strlen(info_passwd.audit_msg)); -+ - (void) snprintf (info_group.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s/%lu", - group_name, (unsigned long int) group_id); - #ifdef SHADOWGRP - (void) snprintf (info_gshadow.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s", group_name); - #endif - (void) snprintf (info_passwd.action, -- 511 - strlen (info_group.audit_msg), -+ 511, - "group %s/%lu", - group_name, (unsigned long int) group_id); - - if (nflg) { -+ nv_pair = audit_encode_nv_string(" new_group", group_newname, -+ strlen(group_newname)); -+ strncat(info_group.audit_msg, nv_pair, -+ 511 - strlen(info_group.audit_msg)); - strncat (info_group.action, ", new name: ", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - strncat (info_group.action, group_newname, -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - - #ifdef SHADOWGRP -+ strncat(info_gshadow.audit_msg, nv_pair, -+ 511 - strlen(info_gshadow.audit_msg)); - strncat (info_gshadow.action, ", new name: ", -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - strncat (info_gshadow.action, group_newname, -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - #endif - -+ strncat(info_passwd.audit_msg, nv_pair, -+ 511 - strlen(info_passwd.audit_msg)); - strncat (info_passwd.action, ", new name: ", -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); - strncat (info_passwd.action, group_newname, -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); -+ free(nv_pair); - } - if (pflg) { -+ strncat(info_passwd.audit_msg, "op=change-password", -+ 511 - strlen (info_passwd.action)); -+ -+ /* Note: audit doesn't want this value recorded */ - strncat (info_group.action, ", new password", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - - #ifdef SHADOWGRP - strncat (info_gshadow.action, ", new password", -- 511 - strlen (info_gshadow.audit_msg)); -+ 511 - strlen (info_gshadow.action)); - #endif - } - if (gflg) { -+ snprintf(nv, sizeof(nv), " new_gid=%lu", (unsigned long)group_newid); -+ strncat(info_group.audit_msg, nv, -+ 511 - strlen(info_group.audit_msg)); -+ strncat(info_passwd.audit_msg, nv, -+ 511 - strlen(info_passwd.audit_msg)); -+ - strncat (info_group.action, ", new gid: ", -- 511 - strlen (info_group.audit_msg)); -+ 511 - strlen (info_group.action)); - (void) snprintf (info_group.action+strlen (info_group.action), -- 511 - strlen (info_group.audit_msg), -+ 511 - strlen (info_group.action), - "%lu", (unsigned long int) group_newid); - - strncat (info_passwd.action, ", new gid: ", -- 511 - strlen (info_passwd.audit_msg)); -+ 511 - strlen (info_passwd.action)); - (void) snprintf (info_passwd.action+strlen (info_passwd.action), -- 511 - strlen (info_passwd.audit_msg), -+ 511 - strlen (info_passwd.action), - "%lu", (unsigned long int) group_newid); - } - info_group.audit_msg[511] = '\0'; -@@ -631,6 +673,11 @@ static void prepare_failure_reports (voi - info_gshadow.audit_msg[511] = '\0'; - #endif - info_passwd.audit_msg[511] = '\0'; -+ info_group.action[511] = '\0'; -+#ifdef SHADOWGRP -+ info_gshadow.action[511] = '\0'; -+#endif -+ info_passwd.action[511] = '\0'; - - // FIXME: add a system cleanup - add_cleanup (cleanup_report_mod_group, &info_group); -diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c ---- shadow-4.11.1/src/newgrp.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/newgrp.c 2022-01-03 15:25:39.407050922 +0100 -@@ -185,11 +185,12 @@ static void check_perms (const struct gr +diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c +--- shadow-4.14.0/src/newgrp.c.audit-update 2023-08-04 09:30:25.208963541 +0200 ++++ shadow-4.14.0/src/newgrp.c 2023-08-04 09:51:28.354208322 +0200 +@@ -186,10 +186,10 @@ static void check_perms (const struct gr strcmp (cpasswd, grp->gr_passwd) != 0) { #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1129,14 +958,12 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + "authentication new_gid=%lu", (unsigned long) grp->gr_gid); audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif SYSLOG ((LOG_INFO, "Invalid password for group '%s' from '%s'", -@@ -200,11 +201,12 @@ static void check_perms (const struct gr +@@ -200,10 +200,10 @@ static void check_perms (const struct gr } #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), @@ -1144,14 +971,12 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + "authentication new_gid=%lu", (unsigned long) grp->gr_gid); audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 1); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_SUCCESS); +- audit_buf, NULL, getuid (), 1); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); #endif } -@@ -215,19 +217,6 @@ failure: +@@ -214,17 +214,6 @@ failure: * harm. -- JWP */ closelog (); @@ -1160,18 +985,16 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c - snprintf (audit_buf, sizeof(audit_buf), - "changing new-group=%s", groupname); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, -- (unsigned int) getuid (), 0); +- audit_buf, NULL, getuid (), 0); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, -- (unsigned int) getuid (), 0); +- "changing", NULL, getuid (), 0); - } -#endif exit (EXIT_FAILURE); } -@@ -299,15 +288,27 @@ static void syslog_sg (const char *name, +@@ -298,13 +287,23 @@ static void syslog_sg (const char *name, is_newgrp ? "newgrp" : "sg", strerror (errno)); #ifdef WITH_AUDIT if (group) { @@ -1190,29 +1013,25 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + group); + } audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); } else { audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); +- "changing", NULL, getuid (), 0); ++ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); } #endif exit (EXIT_FAILURE); -@@ -438,7 +439,7 @@ int main (int argc, char **argv) +@@ -440,7 +439,7 @@ int main (int argc, char **argv) + Prog); #ifdef WITH_AUDIT audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- "changing", NULL, getuid (), 0); ++ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); -@@ -554,15 +555,26 @@ int main (int argc, char **argv) +@@ -556,13 +555,22 @@ int main (int argc, char **argv) perror ("getgroups"); #ifdef WITH_AUDIT if (group) { @@ -1230,59 +1049,52 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + "changing new_group=\"%s\"", group); + } audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); } else { audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), -+ SHADOW_AUDIT_FAILURE); +- "changing", NULL, getuid (), 0); ++ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); } #endif exit (EXIT_FAILURE); -@@ -719,10 +731,10 @@ int main (int argc, char **argv) +@@ -717,9 +725,9 @@ int main (int argc, char **argv) perror ("setgid"); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), - "changing new-gid=%lu", (unsigned long) gid); + "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif exit (EXIT_FAILURE); } -@@ -731,10 +743,10 @@ int main (int argc, char **argv) +@@ -728,9 +736,9 @@ int main (int argc, char **argv) perror ("setuid"); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), - "changing new-gid=%lu", (unsigned long) gid); + "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif exit (EXIT_FAILURE); } -@@ -748,10 +760,10 @@ int main (int argc, char **argv) - execl (SHELL, "sh", "-c", command, (char *) 0); +@@ -744,9 +752,9 @@ int main (int argc, char **argv) + execl (SHELL, "sh", "-c", command, (char *) NULL); #ifdef WITH_AUDIT snprintf (audit_buf, sizeof(audit_buf), - "changing new-gid=%lu", (unsigned long) gid); + "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif perror (SHELL); exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -815,11 +827,11 @@ int main (int argc, char **argv) +@@ -810,10 +818,10 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT @@ -1290,13 +1102,12 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + snprintf (audit_buf, sizeof(audit_buf), "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 1); -+ (unsigned int) getuid (), SHADOW_AUDIT_SUCCESS); +- audit_buf, NULL, getuid (), 1); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); #endif /* * Exec the login shell and go away. We are trying to get back to -@@ -843,15 +855,24 @@ int main (int argc, char **argv) +@@ -837,13 +845,22 @@ int main (int argc, char **argv) closelog (); #ifdef WITH_AUDIT if (NULL != group) { @@ -1314,112 +1125,91 @@ diff -up shadow-4.11.1/src/newgrp.c.audit-update shadow-4.11.1/src/newgrp.c + "changing new_group=\"%s\"", group); + } audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- audit_buf, NULL, getuid (), 0); ++ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); } else { audit_logger (AUDIT_CHGRP_ID, Prog, - "changing", NULL, -- (unsigned int) getuid (), 0); -+ (unsigned int) getuid (), SHADOW_AUDIT_FAILURE); +- "changing", NULL, getuid (), 0); ++ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); } #endif exit (EXIT_FAILURE); -diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c ---- shadow-4.11.1/src/useradd.c.audit-update 2022-01-03 14:57:01.772006744 +0100 -+++ shadow-4.11.1/src/useradd.c 2022-01-03 14:57:01.787006838 +0100 -@@ -222,6 +222,8 @@ static void check_uid_range(int rflg, ui +diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c +--- shadow-4.14.0/src/useradd.c.audit-update 2023-07-30 12:38:39.000000000 +0200 ++++ shadow-4.14.0/src/useradd.c 2023-08-04 10:02:18.851935396 +0200 +@@ -240,6 +240,8 @@ static void check_uid_range(int rflg, ui */ static void fail_exit (int code) { + int type; + - if (home_added) { - if (rmdir (prefix_user_home) != 0) { - fprintf (stderr, -@@ -235,12 +237,6 @@ static void fail_exit (int code) - if (spw_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + if (home_added && rmdir(prefix_user_home) != 0) { + fprintf(stderr, + _("%s: %s was created, but could not be removed\n"), +@@ -250,38 +252,22 @@ static void fail_exit (int code) + if (spw_locked && spw_unlock() == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); -#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking shadow file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); +- audit_logger(AUDIT_ADD_USER, Prog, "unlocking shadow file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -#endif - /* continue */ - } + /* continue */ } -@@ -248,12 +244,6 @@ static void fail_exit (int code) - if (pw_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + if (pw_locked && pw_unlock() == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); -#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking passwd file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); +- audit_logger(AUDIT_ADD_USER, Prog, "unlocking passwd file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -#endif - /* continue */ - } + /* continue */ } -@@ -261,12 +251,6 @@ static void fail_exit (int code) - if (gr_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + if (gr_locked && gr_unlock() == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); -#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking group file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); +- audit_logger(AUDIT_ADD_USER, Prog, "unlocking group file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -#endif - /* continue */ - } + /* continue */ } -@@ -275,12 +259,6 @@ static void fail_exit (int code) - if (sgr_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking gshadow file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } + #ifdef SHADOWGRP + if (sgr_locked && sgr_unlock() == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); +-# ifdef WITH_AUDIT +- audit_logger(AUDIT_ADD_USER, Prog, "unlocking gshadow file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); +-# endif + /* continue */ } -@@ -290,12 +268,6 @@ static void fail_exit (int code) - if (sub_uid_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking subordinate user file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } + #endif +@@ -289,27 +275,23 @@ static void fail_exit (int code) + if (sub_uid_locked && sub_uid_unlock() == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); +-# ifdef WITH_AUDIT +- audit_logger(AUDIT_ADD_USER, Prog, +- "unlocking subordinate user file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); +-# endif + /* continue */ } -@@ -303,20 +275,19 @@ static void fail_exit (int code) - if (sub_gid_unlock () == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking subordinate group file", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } + if (sub_gid_locked && sub_gid_unlock() == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); +-# ifdef WITH_AUDIT +- audit_logger(AUDIT_ADD_USER, Prog, +- "unlocking subordinate group file", +- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); +-# endif + /* continue */ } - #endif /* ENABLE_SUBIDS */ + #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", +- audit_logger(AUDIT_ADD_USER, Prog, "adding user", + if (code == E_PW_UPDATE || code >= E_GRP_UPDATE) + type = AUDIT_USER_MGMT; + else @@ -1427,10 +1217,10 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c + + audit_logger (type, Prog, + "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); + user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -719,7 +690,7 @@ static int set_defaults (void) + SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); +@@ -759,7 +741,7 @@ static int set_defaults (void) } #ifdef WITH_AUDIT audit_logger (AUDIT_USYS_CONFIG, Prog, @@ -1439,7 +1229,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c NULL, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -1050,12 +1021,6 @@ static void grp_update (void) +@@ -1096,12 +1078,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1452,7 +1242,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1069,18 +1034,12 @@ static void grp_update (void) +@@ -1115,18 +1091,12 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1474,7 +1264,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1125,12 +1084,6 @@ static void grp_update (void) +@@ -1171,12 +1141,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1487,7 +1277,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1144,18 +1097,13 @@ static void grp_update (void) +@@ -1190,18 +1154,13 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1510,7 +1300,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1528,7 +1476,7 @@ static void process_flags (int argc, cha +@@ -1596,7 +1555,7 @@ static void process_flags (int argc, cha Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1519,7 +1309,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1637,7 +1585,7 @@ static void close_files (void) +@@ -1705,7 +1664,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1528,7 +1318,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1650,7 +1598,7 @@ static void close_files (void) +@@ -1718,7 +1677,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1537,7 +1327,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1667,7 +1615,7 @@ static void close_files (void) +@@ -1735,7 +1694,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1546,7 +1336,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1681,7 +1629,7 @@ static void close_files (void) +@@ -1749,7 +1708,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1555,7 +1345,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1942,7 +1890,7 @@ static void grp_add (void) +@@ -2012,7 +1971,7 @@ static void grp_add (void) Prog, gr_dbname (), grp.gr_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1564,7 +1354,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1958,7 +1906,7 @@ static void grp_add (void) +@@ -2028,7 +1987,7 @@ static void grp_add (void) Prog, sgr_dbname (), sgrp.sg_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1573,7 +1363,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1968,7 +1916,7 @@ static void grp_add (void) +@@ -2038,7 +1997,7 @@ static void grp_add (void) SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1582,61 +1372,48 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2161,12 +2109,6 @@ static void usr_update (unsigned long su +@@ -2240,11 +2199,6 @@ static void usr_update (unsigned long su fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spent.sp_namp); -#ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, - "adding shadow password", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif fail_exit (E_PW_UPDATE); } #ifdef ENABLE_SUBIDS -@@ -2187,9 +2129,14 @@ static void usr_update (unsigned long su - #endif /* ENABLE_SUBIDS */ - - #ifdef WITH_AUDIT -+ /* -+ * Even though we have the ID of the user, we won't send it now -+ * because its not written to disk yet. After close_files it is -+ * and we can use the real ID thereafter. -+ */ +@@ -2271,7 +2225,7 @@ static void usr_update (unsigned long su + * and we can use the real ID thereafter. + */ audit_logger (AUDIT_ADD_USER, Prog, - "adding user", -- user_name, (unsigned int) user_id, + "add-user", -+ user_name, AUDIT_NO_ID, + user_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif - /* -@@ -2279,12 +2226,6 @@ static void create_home (void) - fprintf (stderr, - _("%s: cannot create directory %s\n"), - Prog, path); +@@ -2365,10 +2319,6 @@ static void create_home (void) + if (mkdir(path, 0) != 0) { + fprintf(stderr, _("%s: cannot create directory %s\n"), + Prog, path); -#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding home directory", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- audit_logger(AUDIT_ADD_USER, Prog, "adding home directory", +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif - fail_exit (E_HOMEDIR); + fail_exit(E_HOMEDIR); } - if (chown (path, 0, 0) < 0) { -@@ -2311,8 +2252,8 @@ static void create_home (void) - } - home_added = true; + if (chown(path, 0, 0) < 0) { +@@ -2393,7 +2343,7 @@ static void create_home (void) + } + home_added = true; #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "add-home-dir", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); +- audit_logger(AUDIT_ADD_USER, Prog, "adding home directory", ++ audit_logger(AUDIT_USER_MGMT, Prog, "add-home-dir", + user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif -@@ -2552,12 +2493,6 @@ int main (int argc, char **argv) + #ifdef WITH_SELINUX +@@ -2637,12 +2587,6 @@ int main (int argc, char **argv) */ if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); @@ -1649,7 +1426,7 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c fail_exit (E_NAME_IN_USE); } -@@ -2573,12 +2508,6 @@ int main (int argc, char **argv) +@@ -2658,12 +2602,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), Prog, user_name); @@ -1662,62 +1439,61 @@ diff -up shadow-4.11.1/src/useradd.c.audit-update shadow-4.11.1/src/useradd.c fail_exit (E_NAME_IN_USE); } } -@@ -2608,12 +2537,6 @@ int main (int argc, char **argv) +@@ -2693,12 +2631,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: UID %lu is not unique\n"), Prog, (unsigned long) user_id); -#ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, - "adding user", -- user_name, (unsigned int) user_id, +- user_name, user_id, - SHADOW_AUDIT_FAILURE); -#endif fail_exit (E_UID_IN_USE); } } -@@ -2688,9 +2611,10 @@ int main (int argc, char **argv) +@@ -2773,9 +2705,9 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, - "adding SELinux user mapping", -- user_name, (unsigned int) user_id, 0); +- user_name, user_id, 0); + audit_logger (AUDIT_ROLE_ASSIGN, Prog, + "add-selinux-user-mapping", -+ user_name, (unsigned int) user_id, -+ SHADOW_AUDIT_FAILURE); ++ user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); } -diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c ---- shadow-4.11.1/src/userdel.c.audit-update 2022-01-03 01:46:53.000000000 +0100 -+++ shadow-4.11.1/src/userdel.c 2022-01-03 14:57:01.787006838 +0100 -@@ -202,9 +202,9 @@ static void update_groups (void) +diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c +--- shadow-4.14.0/src/userdel.c.audit-update 2023-06-10 02:02:29.000000000 +0200 ++++ shadow-4.14.0/src/userdel.c 2023-08-04 10:26:18.225695416 +0200 +@@ -204,9 +204,9 @@ static void update_groups (void) * Update the DBM group file with the new entry as well. */ #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "deleting user from group", -- user_name, (unsigned int) user_id, +- user_name, user_id, SHADOW_AUDIT_SUCCESS); + audit_logger_with_group (AUDIT_USER_MGMT, Prog, + "deleting-user-from-group", -+ user_name, (unsigned int) user_id, ngrp->gr_name, - SHADOW_AUDIT_SUCCESS); ++ user_name, user_id, ngrp->gr_name, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", -@@ -264,9 +264,9 @@ static void update_groups (void) + user_name, ngrp->gr_name)); +@@ -265,9 +265,9 @@ static void update_groups (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "deleting user from shadow group", -- user_name, (unsigned int) user_id, +- user_name, user_id, SHADOW_AUDIT_SUCCESS); + audit_logger_with_group (AUDIT_USER_MGMT, Prog, + "deleting-user-from-shadow-group", -+ user_name, (unsigned int) user_id, nsgrp->sg_name, - SHADOW_AUDIT_SUCCESS); ++ user_name, user_id, nsgrp->sg_name, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", + user_name, nsgrp->sg_name)); @@ -343,9 +343,9 @@ static void remove_usergroup (void) } @@ -1750,18 +1526,17 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c audit_logger (AUDIT_DEL_USER, Prog, - "deleting user", + "delete-user", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -545,24 +545,12 @@ static void open_files (void) + +@@ -544,22 +544,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } @@ -1772,47 +1547,43 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } if (is_shadow_pwd) { -@@ -570,12 +558,6 @@ static void open_files (void) +@@ -567,11 +557,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking shadow password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } spw_locked = true; -@@ -583,12 +565,6 @@ static void open_files (void) +@@ -579,11 +564,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening shadow password file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } } -@@ -596,23 +572,11 @@ static void open_files (void) +@@ -591,21 +571,11 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } @@ -1822,21 +1593,19 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } #ifdef SHADOWGRP -@@ -621,24 +585,12 @@ static void open_files (void) +@@ -614,22 +584,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking shadow group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } @@ -1847,21 +1616,19 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening shadow group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } } -@@ -649,24 +601,12 @@ static void open_files (void) +@@ -640,22 +600,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_uid_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking subordinate user file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_SUB_UID_UPDATE); } @@ -1872,21 +1639,19 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening subordinate user file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_SUB_UID_UPDATE); } } -@@ -675,24 +615,12 @@ static void open_files (void) +@@ -664,22 +614,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_gid_dbname ()); -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "locking subordinate group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_SUB_GID_UPDATE); } @@ -1897,40 +1662,39 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c -#ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, - "opening subordinate group file", -- user_name, (unsigned int) user_id, -- SHADOW_AUDIT_FAILURE); +- user_name, user_id, SHADOW_AUDIT_FAILURE); -#endif /* WITH_AUDIT */ fail_exit (E_SUB_GID_UPDATE); } } -@@ -737,7 +665,7 @@ static void update_user (void) +@@ -724,7 +664,7 @@ static void update_user (void) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, - "deleting user entries", + "delete-user", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); + user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ -@@ -845,7 +773,7 @@ static int remove_mailbox (void) + SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); +@@ -831,7 +771,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, - "deleting mail file", + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -862,7 +790,7 @@ static int remove_mailbox (void) + free(mailfile); +@@ -847,7 +787,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, - "deleting mail file", + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -872,8 +800,8 @@ static int remove_mailbox (void) + errors = 1; +@@ -856,8 +796,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1938,28 +1702,28 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c - "deleting mail file", + audit_logger (AUDIT_USER_MGMT, Prog, + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); + user_name, user_id, SHADOW_AUDIT_SUCCESS); } -@@ -891,7 +819,7 @@ static int remove_mailbox (void) + #endif /* WITH_AUDIT */ +@@ -874,7 +814,7 @@ static int remove_mailbox (void) mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, - "deleting mail file", + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -908,7 +836,7 @@ static int remove_mailbox (void) + free(mailfile); +@@ -890,7 +830,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, - "deleting mail file", + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -918,8 +846,8 @@ static int remove_mailbox (void) + errors = 1; +@@ -899,8 +839,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1967,10 +1731,10 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c - "deleting mail file", + audit_logger (AUDIT_USER_MGMT, Prog, + "delete-mail-file", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); + user_name, user_id, SHADOW_AUDIT_SUCCESS); } -@@ -1138,7 +1066,7 @@ int main (int argc, char **argv) + #endif /* WITH_AUDIT */ +@@ -1118,7 +1058,7 @@ int main (int argc, char **argv) Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1979,7 +1743,7 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1194,7 +1122,7 @@ int main (int argc, char **argv) +@@ -1174,7 +1114,7 @@ int main (int argc, char **argv) if (!fflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1988,7 +1752,7 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1288,8 +1216,8 @@ int main (int argc, char **argv) +@@ -1268,8 +1208,8 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT else { @@ -1996,10 +1760,10 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c - "deleting home directory", + audit_logger (AUDIT_USER_MGMT, Prog, + "deleting-home-directory", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_SUCCESS); + user_name, user_id, SHADOW_AUDIT_SUCCESS); } -@@ -1298,7 +1226,7 @@ int main (int argc, char **argv) + #endif /* WITH_AUDIT */ +@@ -1277,7 +1217,7 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT if (0 != errors) { audit_logger (AUDIT_DEL_USER, Prog, @@ -2008,7 +1772,7 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); } -@@ -1311,8 +1239,8 @@ int main (int argc, char **argv) +@@ -1290,8 +1230,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2016,66 +1780,61 @@ diff -up shadow-4.11.1/src/userdel.c.audit-update shadow-4.11.1/src/userdel.c - "removing SELinux user mapping", + audit_logger (AUDIT_ROLE_REMOVE, Prog, + "delete-selinux-user-mapping", - user_name, (unsigned int) user_id, - SHADOW_AUDIT_FAILURE); + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c ---- shadow-4.11.1/src/usermod.c.audit-update 2022-01-03 14:57:01.776006769 +0100 -+++ shadow-4.11.1/src/usermod.c 2022-01-03 15:28:16.959101706 +0100 -@@ -417,8 +417,8 @@ static char *new_pw_passwd (char *pw_pas + fail_exit (E_SE_UPDATE); +diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c +--- shadow-4.14.0/src/usermod.c.audit-update 2023-07-30 12:38:39.000000000 +0200 ++++ shadow-4.14.0/src/usermod.c 2023-08-04 10:33:04.601749324 +0200 +@@ -427,7 +427,7 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating passwd", -- user_newname, (unsigned int) user_newid, 0); -+ "updating-password", -+ user_newname, (unsigned int) user_newid, 1); +- "updating passwd", user_newname, user_newid, 0); ++ "updating-passwd", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); strcpy (buf, "!"); -@@ -437,8 +437,8 @@ static char *new_pw_passwd (char *pw_pas +@@ -444,14 +444,14 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating password", -- user_newname, (unsigned int) user_newid, 0); -+ "updating-password", -+ user_newname, (unsigned int) user_newid, 1); +- "updating password", user_newname, user_newid, 0); ++ "updating-password", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); - s = pw_pass; -@@ -449,7 +449,7 @@ static char *new_pw_passwd (char *pw_pas + memmove(pw_pass, pw_pass + 1, strlen(pw_pass)); } else if (pflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing password", -+ "updating-password", - user_newname, (unsigned int) user_newid, 1); +- "changing password", user_newname, user_newid, 1); ++ "updating-password", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); -@@ -478,8 +478,8 @@ static void new_pwent (struct passwd *pw + pw_pass = xstrdup (user_pass); +@@ -479,8 +479,8 @@ static void new_pwent (struct passwd *pw fail_exit (E_NAME_IN_USE); } #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing name", +- "changing name", user_newname, user_newid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-name", - user_newname, (unsigned int) user_newid, 1); ++ "changing-name", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, + "change user name '%s' to '%s'", @@ -499,8 +499,8 @@ static void new_pwent (struct passwd *pw if (uflg) { #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing uid", +- "changing uid", user_newname, user_newid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-uid", - user_newname, (unsigned int) user_newid, 1); ++ "changing-uid", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -510,8 +510,8 @@ static void new_pwent (struct passwd *pw + "change user '%s' UID from '%d' to '%d'", +@@ -509,8 +509,8 @@ static void new_pwent (struct passwd *pw } if (gflg) { #ifdef WITH_AUDIT @@ -2083,21 +1842,20 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing primary group", + audit_logger (AUDIT_USER_MGMT, Prog, + "changing-primary-group", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -521,8 +521,8 @@ static void new_pwent (struct passwd *pw +@@ -520,16 +520,16 @@ static void new_pwent (struct passwd *pw } if (cflg) { #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing comment", +- "changing comment", user_newname, user_newid, 1); + audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-comment", - user_newname, (unsigned int) user_newid, 1); ++ "changing-comment", user_newname, user_newid, 1); #endif pwent->pw_gecos = user_newcomment; -@@ -530,8 +530,8 @@ static void new_pwent (struct passwd *pw + } if (dflg) { #ifdef WITH_AUDIT @@ -2105,10 +1863,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing home directory", + audit_logger (AUDIT_USER_MGMT, Prog, + "changing-home-dir", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -547,8 +547,8 @@ static void new_pwent (struct passwd *pw +@@ -545,8 +545,8 @@ static void new_pwent (struct passwd *pw } if (sflg) { #ifdef WITH_AUDIT @@ -2116,10 +1874,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing user shell", + audit_logger (AUDIT_USER_MGMT, Prog, + "changing-shell", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -578,8 +578,8 @@ static void new_spent (struct spwd *spen +@@ -576,8 +576,8 @@ static void new_spent (struct spwd *spen if (fflg) { #ifdef WITH_AUDIT @@ -2127,10 +1885,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing inactive days", + audit_logger (AUDIT_USER_MGMT, Prog, + "changing-inactive-days", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -593,8 +593,8 @@ static void new_spent (struct spwd *spen +@@ -591,8 +591,8 @@ static void new_spent (struct spwd *spen date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT @@ -2138,10 +1896,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing expiration date", + audit_logger (AUDIT_USER_MGMT, Prog, + "changing-expiration-date", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -677,9 +677,9 @@ static /*@noreturn@*/void fail_exit (int +@@ -677,9 +677,9 @@ fail_exit (int code) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -2256,7 +2014,7 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", user_newname, nsgrp->sg_name)); -@@ -1817,8 +1828,8 @@ static void move_home (void) +@@ -1830,8 +1841,8 @@ static void move_home (void) #ifdef WITH_AUDIT if (uflg || gflg) { @@ -2264,10 +2022,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing home directory owner", + audit_logger (AUDIT_USER_MGMT, Prog, + "updating-home-dir-owner", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); } #endif -@@ -1836,8 +1847,8 @@ static void move_home (void) +@@ -1849,8 +1860,8 @@ static void move_home (void) fail_exit (E_HOMEDIR); } #ifdef WITH_AUDIT @@ -2275,10 +2033,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "moving home directory", + audit_logger (AUDIT_USER_MGMT, Prog, + "moving-home-dir", - user_newname, (unsigned int) user_newid, - 1); + user_newname, user_newid, 1); #endif -@@ -1865,9 +1876,9 @@ static void move_home (void) + return; +@@ -1877,9 +1888,9 @@ static void move_home (void) Prog, prefix_user_home); } #ifdef WITH_AUDIT @@ -2288,9 +2046,9 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "moving home directory", + "moving-home-dir", user_newname, - (unsigned int) user_newid, + user_newid, 1); -@@ -2085,8 +2096,8 @@ static void move_mailbox (void) +@@ -2100,8 +2111,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2298,10 +2056,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing mail file owner", + audit_logger (AUDIT_USER_MGMT, Prog, + "updating-mail-file-owner", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); } #endif -@@ -2112,8 +2123,8 @@ static void move_mailbox (void) +@@ -2129,8 +2140,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2309,10 +2067,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing mail file name", + audit_logger (AUDIT_USER_MGMT, Prog, + "updating-mail-file-name", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); } - #endif -@@ -2310,8 +2321,8 @@ int main (int argc, char **argv) + +@@ -2331,8 +2342,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -2320,10 +2078,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "modifying User mapping ", + audit_logger (AUDIT_ROLE_ASSIGN, Prog, + "changing-selinux-user-mapping ", - user_name, (unsigned int) user_id, + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2323,8 +2334,8 @@ int main (int argc, char **argv) +@@ -2344,8 +2355,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2331,10 +2089,10 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "removing SELinux user mapping", + audit_logger (AUDIT_ROLE_REMOVE, Prog, + "delete-selinux-user-mapping", - user_name, (unsigned int) user_id, + user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2365,8 +2376,8 @@ int main (int argc, char **argv) +@@ -2388,8 +2399,8 @@ int main (int argc, char **argv) */ #ifdef WITH_AUDIT if (uflg || gflg) { @@ -2342,6 +2100,6 @@ diff -up shadow-4.11.1/src/usermod.c.audit-update shadow-4.11.1/src/usermod.c - "changing home directory owner", + audit_logger (AUDIT_USER_MGMT, Prog, + "updating-home-dir-owner", - user_newname, (unsigned int) user_newid, 1); + user_newname, user_newid, 1); } #endif diff --git a/shadow-4.9-manfix.patch b/shadow-4.14.0-manfix.patch similarity index 99% rename from shadow-4.9-manfix.patch rename to shadow-4.14.0-manfix.patch index 46cba1a..70f030e 100644 --- a/shadow-4.9-manfix.patch +++ b/shadow-4.14.0-manfix.patch @@ -19,7 +19,7 @@ diff -up shadow-4.8.1/man/groupmems.8.xml.manfix shadow-4.8.1/man/groupmems.8.xm - - $ groupadd -r groups - $ chmod 2710 groupmems -- $ chown root.groups groupmems +- $ chown root:groups groupmems - $ groupmems -g groups -a gk4 - diff --git a/shadow-4.5-usermod-unlock.patch b/shadow-4.5-usermod-unlock.patch deleted file mode 100644 index e2d70b5..0000000 --- a/shadow-4.5-usermod-unlock.patch +++ /dev/null @@ -1,64 +0,0 @@ -Index: shadow-4.5/src/usermod.c -=================================================================== ---- shadow-4.5.orig/src/usermod.c -+++ shadow-4.5/src/usermod.c -@@ -455,14 +455,17 @@ static char *new_pw_passwd (char *pw_pas - strcat (buf, pw_pass); - pw_pass = buf; - } else if (Uflg && pw_pass[0] == '!') { -- char *s; -+ char *s = pw_pass; - -- if (pw_pass[1] == '\0') { -+ while ('!' == *s) -+ ++s; -+ -+ if (*s == '\0') { - fprintf (stderr, - _("%s: unlocking the user's password would result in a passwordless account.\n" - "You should set a password with usermod -p to unlock this user's password.\n"), - Prog); -- return pw_pass; -+ return NULL; - } - - #ifdef WITH_AUDIT -@@ -471,12 +474,15 @@ static char *new_pw_passwd (char *pw_pas - user_newname, (unsigned int) user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); -- s = pw_pass; -- while ('\0' != *s) { -- *s = *(s + 1); -- s++; -- } -+ memmove (pw_pass, s, strlen (s) + 1); - } else if (pflg) { -+ if (strchr (user_pass, ':') != NULL) { -+ fprintf (stderr, -+ _("%s: The password field cannot contain a colon character.\n"), -+ Prog); -+ return NULL; -+ -+ } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "updating-password", -@@ -525,6 +531,8 @@ static void new_pwent (struct passwd *pw - if ( (!is_shadow_pwd) - || (strcmp (pwent->pw_passwd, SHADOW_PASSWD_STRING) != 0)) { - pwent->pw_passwd = new_pw_passwd (pwent->pw_passwd); -+ if (pwent->pw_passwd == NULL) -+ fail_exit (E_PW_UPDATE); - } - - if (uflg) { -@@ -639,6 +647,8 @@ static void new_spent (struct spwd *spen - * + aging has been requested - */ - spent->sp_pwdp = new_pw_passwd (spent->sp_pwdp); -+ if (spent->sp_pwdp == NULL) -+ fail_exit(E_PW_UPDATE); - - if (pflg) { - spent->sp_lstchg = (long) gettime () / SCALE; diff --git a/shadow-utils.spec b/shadow-utils.spec index 8ee19af..74f4ec6 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.13 -Release: 8%{?dist} +Version: 4.14.0 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -17,27 +17,12 @@ Source6: shadow-utils.HOME_MODE.xml %global includesubiddir %{_includedir}/shadow ### Patches ### -# Misc small changes - most probably non-upstreamable -Patch0: shadow-4.12.3-redhat.patch -# SElinux related - upstreamability unknown -Patch1: shadow-4.13-default-range.patch # Misc manual page changes - non-upstreamable -Patch2: shadow-4.9-manfix.patch +Patch0: shadow-4.14.0-manfix.patch # Date parsing improvement - could be upstreamed -Patch3: shadow-4.2.1-date-parsing.patch +Patch1: shadow-4.2.1-date-parsing.patch # Audit message changes - partially upstreamed -# https://github.com/shadow-maint/shadow/commit/37412f505ed0bc5c9e3f04b2266b40f8f6fc310f -Patch4: shadow-4.11.1-audit-update.patch -# Changes related to password unlocking - could be upstreamed -Patch5: shadow-4.5-usermod-unlock.patch -# Additional SElinux related changes - upstreamability unknown -Patch6: shadow-4.12.3-selinux-perms.patch -# https://github.com/shadow-maint/shadow/commit/a281f241b592aec636d1b93a99e764499d68c7ef -Patch7: shadow-utils-configure-gshadow.patch -# https://github.com/shadow-maint/shadow/commit/6974df39a708abf8bafbdfa2b7827e0f70f874cb -# https://github.com/shadow-maint/shadow/commit/7ff33fae6f9cd79c0e012671c37a172e9a681d0b -# https://github.com/shadow-maint/shadow/commit/05e2adf509ba0e3779dae66a276b86927a8e1e0e -Patch8: shadow-4.13-newidmap-support-passing-pid-as-fd.patch +Patch2: shadow-4.14.0-audit-update.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -129,10 +114,13 @@ autoreconf --with-bcrypt \ --with-yescrypt \ --with-selinux \ + --without-libbsd \ --without-libcrack \ --without-libpam \ --enable-shared \ - --with-group-name-max-length=32 + --with-group-name-max-length=32 \ + --enable-lastlog \ + --enable-logind=no %make_build %install @@ -273,6 +261,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Aug 16 2023 Iker Pedrosa - 2:4.14.0-1 +- Rebase to version 4.14.0. Resolves: #2229000 + * Sat Jul 22 2023 Fedora Release Engineering - 2:4.13-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild diff --git a/sources b/sources index 40bac31..1ec1caa 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.13.tar.xz) = 2949a728c3312bef13d23138d6b79caf402781b1cb179e33b5be546c1790971ec20778d0e9cd3dbe09691d928ffcbe88e60da42fab58c69a90d5ebe5e3e2ab8e -SHA512 (shadow-4.13.tar.xz.asc) = f8549c4e699c65721d53946d61b6127712572f7ad9ee13018ef3a25307002992aa727471c948d1bb22dcddf112715bed387d28f436123f30e153ae6bc0cd3648 +SHA512 (shadow-4.14.0.tar.xz) = ff960481d576f9db5a9f10becc4e1a74c03de484ecfdcd7f1ea735fded683d7ba0f9cd895dc6a431b77e5a633752273178b1bcda4cefaa5adbf0f143c9a0c86f +SHA512 (shadow-4.14.0.tar.xz.asc) = d011a732d73b4b066ca8d204c0420303f925c87efc7655feb5c5f60b619d67da450e220ee44f6c86929ae79cbd4343136fe9c20d25b39fa0a228a48e57636309 From b2b4416387c3424380e5efcaa20e1a100406b8e1 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 3 Oct 2023 09:59:47 +0200 Subject: [PATCH 059/118] useradd: Set proper SELinux labels for def_usrtemplate Signed-off-by: Iker Pedrosa --- ...seradd-def-usrtemplate-selinux-label.patch | 28 +++++++++++++++++++ shadow-utils.spec | 7 ++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch diff --git a/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch b/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch new file mode 100644 index 0000000..97b709a --- /dev/null +++ b/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch @@ -0,0 +1,28 @@ +From 48aa12af31c0b72872b411857d03a518a4200a3d Mon Sep 17 00:00:00 2001 +From: Johannes Segitz +Date: Tue, 26 Sep 2023 15:14:14 +0200 +Subject: [PATCH] useradd: Set proper SELinux labels for def_usrtemplate + +Fixes: 74c17c716 ("Add support for skeleton files from /usr/etc/skel") + +Signed-off-by: Johannes Segitz +--- + src/useradd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 76a4d649..fe62a051 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2788,7 +2788,7 @@ int main (int argc, char **argv) + if (home_added) { + copy_tree (def_template, prefix_user_home, false, true, + (uid_t)-1, user_id, (gid_t)-1, user_gid); +- copy_tree (def_usrtemplate, prefix_user_home, false, false, ++ copy_tree (def_usrtemplate, prefix_user_home, false, true, + (uid_t)-1, user_id, (gid_t)-1, user_gid); + } else { + fprintf (stderr, +-- +2.41.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 74f4ec6..49a7819 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.14.0 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -23,6 +23,8 @@ Patch0: shadow-4.14.0-manfix.patch Patch1: shadow-4.2.1-date-parsing.patch # Audit message changes - partially upstreamed Patch2: shadow-4.14.0-audit-update.patch +# https://github.com/shadow-maint/shadow/pull/812 +Patch3: shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -261,6 +263,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Oct 3 2023 Iker Pedrosa - 2:4.14.0-2 +- useradd: Set proper SELinux labels for def_usrtemplate + * Wed Aug 16 2023 Iker Pedrosa - 2:4.14.0-1 - Rebase to version 4.14.0. Resolves: #2229000 From d5da1a5785e9955df3119cffb836dbc191ad0d49 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 27 Jan 2024 02:49:28 +0000 Subject: [PATCH 060/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 49a7819..22ecf32 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.14.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -263,6 +263,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jan 27 2024 Fedora Release Engineering - 2:4.14.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Tue Oct 3 2023 Iker Pedrosa - 2:4.14.0-2 - useradd: Set proper SELinux labels for def_usrtemplate From 1820858d26f633482d3679d1c97324e25e3c1df8 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 26 Jan 2024 10:32:23 +0100 Subject: [PATCH 061/118] Disable SSSD support Resolves: #2253182 Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 22ecf32..633f1fe 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.14.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -119,6 +119,7 @@ autoreconf --without-libbsd \ --without-libcrack \ --without-libpam \ + --without-sssd \ --enable-shared \ --with-group-name-max-length=32 \ --enable-lastlog \ @@ -263,6 +264,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Jan 29 2024 Iker Pedrosa - 2:4.14.0-4 +- Disable SSSD support. Resolves: #2253182 + * Sat Jan 27 2024 Fedora Release Engineering - 2:4.14.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 91360f25a8c8b810d59bec2803a2477a2647c775 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 27 Nov 2023 11:51:16 +0100 Subject: [PATCH 062/118] passwd: Provide binary from this package Provide binary from this package. Enable libpam and disable account-tools-setuid. Provide passwd PAM service file. Finally, provide --stdin option in passwd. Resolves: #2233275 Signed-off-by: Iker Pedrosa --- passwd.pamd | 5 + shadow-4.14.0-account-tools-setuid.patch | 383 +++++++++++++++++++++++ shadow-4.14.0-passwd-stdin.patch | 288 +++++++++++++++++ shadow-4.14.0-remove-libcrack.patch | 306 ++++++++++++++++++ shadow-utils.login.defs | 20 +- shadow-utils.spec | 34 +- 6 files changed, 1026 insertions(+), 10 deletions(-) create mode 100644 passwd.pamd create mode 100644 shadow-4.14.0-account-tools-setuid.patch create mode 100644 shadow-4.14.0-passwd-stdin.patch create mode 100644 shadow-4.14.0-remove-libcrack.patch diff --git a/passwd.pamd b/passwd.pamd new file mode 100644 index 0000000..fd03d03 --- /dev/null +++ b/passwd.pamd @@ -0,0 +1,5 @@ +#%PAM-1.0 +# This tool only uses the password stack. +password substack system-auth +-password optional pam_gnome_keyring.so use_authtok +password substack postlogin diff --git a/shadow-4.14.0-account-tools-setuid.patch b/shadow-4.14.0-account-tools-setuid.patch new file mode 100644 index 0000000..17d8918 --- /dev/null +++ b/shadow-4.14.0-account-tools-setuid.patch @@ -0,0 +1,383 @@ +diff --git a/src/chpasswd.c b/src/chpasswd.c +index 3a4bd4fe..246e4176 100644 +--- a/src/chpasswd.c ++++ b/src/chpasswd.c +@@ -443,9 +443,11 @@ int main (int argc, char **argv) + char *cp; + const char *salt; + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + bool use_pam = true; + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + int errors = 0; + int line = 0; +@@ -470,19 +472,23 @@ int main (int argc, char **argv) + process_root_flag ("-R", argc, argv); + prefix = process_prefix_flag ("-P", argc, argv); + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (md5flg || eflg || cflg || prefix[0]) { + use_pam = false; + } + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + OPENLOG ("chpasswd"); + + check_perms (); + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + is_shadow_pwd = spw_file_present (); + +@@ -544,6 +550,7 @@ int main (int argc, char **argv) + } + newpwd = cp; + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (use_pam) { + if (do_pam_passwd_non_interactive ("chpasswd", name, newpwd) != 0) { +@@ -554,6 +561,7 @@ int main (int argc, char **argv) + } + } else + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + const struct spwd *sp; + struct spwd newsp; +@@ -673,9 +681,11 @@ int main (int argc, char **argv) + * password database. + */ + if (0 != errors) { ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + fprintf (stderr, + _("%s: error detected, changes ignored\n"), +@@ -684,9 +694,11 @@ int main (int argc, char **argv) + fail_exit (1); + } + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + /* Save the changes */ + close_files (); +diff --git a/src/groupmems.c b/src/groupmems.c +index 63a1601c..73f7310e 100644 +--- a/src/groupmems.c ++++ b/src/groupmems.c +@@ -14,9 +14,11 @@ + #include + #include + #include ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + #include "pam_defs.h" + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + #include + + #include "alloc.h" +@@ -430,6 +432,7 @@ static void process_flags (int argc, char **argv) + static void check_perms (void) + { + if (!list) { ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + pam_handle_t *pamh = NULL; + int retval; +@@ -463,7 +466,8 @@ static void check_perms (void) + fail_exit (1); + } + (void) pam_end (pamh, retval); +-#endif ++#endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + } + } + +diff --git a/src/newusers.c b/src/newusers.c +index 09e14a48..96b60de2 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -59,6 +59,7 @@ + const char *Prog; + + static bool rflg = false; /* create a system account */ ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + static /*@null@*//*@observer@*/char *crypt_method = NULL; + #define cflg (NULL != crypt_method) +@@ -75,6 +76,7 @@ static long bcrypt_rounds = 13; + static long yescrypt_cost = 5; + #endif /* USE_YESCRYPT */ + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + + static bool is_shadow; + #ifdef SHADOWGRP +@@ -97,9 +99,11 @@ NORETURN static void fail_exit (int); + static int add_group (const char *, const char *, gid_t *, gid_t); + static int get_user_id (const char *, uid_t *); + static int add_user (const char *, uid_t, gid_t); ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + static int update_passwd (struct passwd *, const char *); + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + static int add_passwd (struct passwd *, const char *); + static void process_flags (int argc, char **argv); + static void check_flags (void); +@@ -121,6 +125,7 @@ static void usage (int status) + "Options:\n"), + Prog); + (void) fputs (_(" -b, --badname allow bad names\n"), usageout); ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + (void) fprintf (usageout, + _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), +@@ -136,9 +141,11 @@ static void usage (int status) + #endif + ); + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); + (void) fputs (_(" -r, --system create system accounts\n"), usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" +@@ -146,6 +153,7 @@ static void usage (int status) + usageout); + #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + (void) fputs ("\n", usageout); + + exit (status); +@@ -405,6 +413,7 @@ static int add_user (const char *name, uid_t uid, gid_t gid) + return (pw_update (&pwent) == 0) ? -1 : 0; + } + ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + /* + * update_passwd - update the password in the passwd entry +@@ -457,6 +466,7 @@ static int update_passwd (struct passwd *pwd, const char *password) + return 0; + } + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + + /* + * add_passwd - add or update the encrypted password +@@ -465,10 +475,13 @@ static int add_passwd (struct passwd *pwd, const char *password) + { + const struct spwd *sp; + struct spwd spent; ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + char *cp; + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + void *crypt_arg = NULL; + if (NULL != crypt_method) { +@@ -505,13 +518,14 @@ static int add_passwd (struct passwd *pwd, const char *password) + return update_passwd (pwd, password); + } + #endif /* USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + + /* + * Do the first and easiest shadow file case. The user already + * exists in the shadow password file. + */ + sp = spw_locate (pwd->pw_name); +-#ifndef USE_PAM ++#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) + if (NULL != sp) { + spent = *sp; + if ( (NULL != crypt_method) +@@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pwd, const char *password) + if (strcmp (pwd->pw_passwd, "x") != 0) { + return update_passwd (pwd, password); + } +-#else /* USE_PAM */ ++#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ + /* + * If there is already a shadow entry, do not touch it. + * If there is already a passwd entry with a password, do not +@@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pwd, const char *password) + || (strcmp (pwd->pw_passwd, "x") != 0)) { + return 0; + } +-#endif /* USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID && !USE_PAM */ + + /* + * Now the really hard case - I need to create an entirely new + * shadow password file entry. + */ + spent.sp_namp = pwd->pw_name; +-#ifndef USE_PAM ++#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) + if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { + spent.sp_pwdp = (char *)password; + } else { +@@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pwd, const char *password) + static void process_flags (int argc, char **argv) + { + int c; ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + int bad_s; + #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + static struct option long_options[] = { + {"badname", no_argument, NULL, 'b'}, ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + {"crypt-method", required_argument, NULL, 'c'}, + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + {"help", no_argument, NULL, 'h'}, + {"system", no_argument, NULL, 'r'}, + {"root", required_argument, NULL, 'R'}, ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + {"sha-rounds", required_argument, NULL, 's'}, + #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + {NULL, 0, NULL, '\0'} + }; + + while ((c = getopt_long (argc, argv, +-#ifndef USE_PAM ++#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + "c:bhrs:", + #else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ + "c:bhr", + #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ +-#else /* USE_PAM */ ++#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ + "bhr", + #endif + long_options, NULL)) != -1) { +@@ -646,11 +666,13 @@ static void process_flags (int argc, char **argv) + case 'b': + allow_bad_names = true; + break; ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + case 'c': + crypt_method = optarg; + break; + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + case 'h': + usage (EXIT_SUCCESS); + break; +@@ -659,6 +681,7 @@ static void process_flags (int argc, char **argv) + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': +@@ -698,6 +721,7 @@ static void process_flags (int argc, char **argv) + break; + #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + default: + usage (EXIT_FAILURE); + break; +@@ -730,6 +754,7 @@ static void process_flags (int argc, char **argv) + */ + static void check_flags (void) + { ++#ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + if (sflg && !cflg) { +@@ -762,6 +787,7 @@ static void check_flags (void) + } + } + #endif /* !USE_PAM */ ++#endif /* !ACCT_TOOLS_SETUID */ + } + + /* +@@ -1052,12 +1078,14 @@ int main (int argc, char **argv) + int line = 0; + uid_t uid; + gid_t gid; ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + int *lines = NULL; + char **usernames = NULL; + char **passwords = NULL; + unsigned int nusers = 0; + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + Prog = Basename (argv[0]); + log_set_progname(Prog); +@@ -1196,6 +1224,7 @@ int main (int argc, char **argv) + } + newpw = *pw; + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + /* keep the list of user/password for later update by PAM */ + nusers++; +@@ -1212,6 +1241,7 @@ int main (int argc, char **argv) + usernames[nusers-1] = strdup (fields[0]); + passwords[nusers-1] = strdup (fields[1]); + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + if (add_passwd (&newpw, fields[1]) != 0) { + fprintf (stderr, + _("%s: line %d: can't update password\n"), +@@ -1328,6 +1358,7 @@ int main (int argc, char **argv) + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + unsigned int i; + /* Now update the passwords using PAM */ +@@ -1340,6 +1371,7 @@ int main (int argc, char **argv) + } + } + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + exit (EXIT_SUCCESS); + } diff --git a/shadow-4.14.0-passwd-stdin.patch b/shadow-4.14.0-passwd-stdin.patch new file mode 100644 index 0000000..2603350 --- /dev/null +++ b/shadow-4.14.0-passwd-stdin.patch @@ -0,0 +1,288 @@ +diff -up shadow-4.14.0/libmisc/agetpass.c.orig shadow-4.14.0/libmisc/agetpass.c +--- shadow-4.14.0/libmisc/agetpass.c.orig 2024-01-24 20:06:20.557577853 +0100 ++++ shadow-4.14.0/libmisc/agetpass.c 2024-01-24 21:21:06.379445080 +0100 +@@ -32,6 +32,7 @@ + * SYNOPSIS + * [[gnu::malloc(erase_pass)]] + * char *agetpass(const char *prompt); ++ * char *agetpass_stdin(); + * + * void erase_pass(char *pass); + * +@@ -64,6 +65,10 @@ + * erased by calling erase_pass(), to avoid possibly leaking the + * password. + * ++ * agetpass_stdin() ++ * This function is the same as previous one (agetpass). Just the ++ * password is read from stdin and terminal is not required. ++ * + * erase_pass() + * This function first clears the password, by calling + * explicit_bzero(3) (or an equivalent call), and then frees the +@@ -92,8 +97,8 @@ + */ + + +-char * +-agetpass(const char *prompt) ++static char * ++agetpass_internal(const char *prompt, int flags) + { + char *pass; + size_t len; +@@ -110,7 +115,7 @@ agetpass(const char *prompt) + if (pass == NULL) + return NULL; + +- if (readpassphrase(prompt, pass, PASS_MAX + 2, RPP_REQUIRE_TTY) == NULL) ++ if (readpassphrase(prompt, pass, PASS_MAX + 2, flags) == NULL) + goto fail; + + len = strlen(pass); +@@ -126,6 +131,17 @@ fail: + return NULL; + } + ++char * ++agetpass(const char *prompt) ++{ ++ return agetpass_internal(prompt, RPP_REQUIRE_TTY); ++} ++ ++char * ++agetpass_stdin() ++{ ++ return agetpass_internal(NULL, RPP_STDIN); ++} + + void + erase_pass(char *pass) +diff -up shadow-4.14.0/lib/prototypes.h.orig shadow-4.14.0/lib/prototypes.h +--- shadow-4.14.0/lib/prototypes.h.orig 2024-01-24 22:06:18.786184942 +0100 ++++ shadow-4.14.0/lib/prototypes.h 2024-01-24 20:19:45.299231059 +0100 +@@ -47,6 +47,7 @@ extern int expire (const struct passwd * + extern void erase_pass(char *pass); + ATTR_MALLOC(erase_pass) + extern char *agetpass(const char *prompt); ++extern char *agetpass_stdin(); + + /* isexpired.c */ + extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); +diff -up shadow-4.14.0/man/passwd.1.xml.orig shadow-4.14.0/man/passwd.1.xml +--- shadow-4.14.0/man/passwd.1.xml.orig 2024-01-24 20:33:31.438972506 +0100 ++++ shadow-4.14.0/man/passwd.1.xml 2024-01-29 17:36:31.082495245 +0100 +@@ -341,6 +341,17 @@ + + + ++ ++ ++ , ++ ++ ++ ++ This option is used to indicate that passwd should read the new password from standard ++ input, which can be a pipe. ++ ++ ++ + + + +diff -up shadow-4.14.0/src/passwd.c.orig shadow-4.14.0/src/passwd.c +--- shadow-4.14.0/src/passwd.c.orig 2024-01-24 13:57:15.714549266 +0100 ++++ shadow-4.14.0/src/passwd.c 2024-01-29 17:33:59.421508534 +0100 +@@ -65,7 +65,8 @@ static bool + Sflg = false, /* -S - show password status */ + uflg = false, /* -u - unlock the user's password */ + wflg = false, /* -w - set warning days */ +- xflg = false; /* -x - set maximum days */ ++ xflg = false, /* -x - set maximum days */ ++ sflg = false; /* -s - read passwd from stdin */ + + /* + * set to 1 if there are any flags which require root privileges, +@@ -156,6 +157,7 @@ usage (int status) + (void) fputs (_(" -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout); + (void) fputs (_(" -x, --maxdays MAX_DAYS set maximum number of days before password\n" + " change to MAX_DAYS\n"), usageout); ++ (void) fputs (_(" -s, --stdin read new token from stdin\n"), usageout); + (void) fputs ("\n", usageout); + exit (status); + } +@@ -275,7 +277,7 @@ static int new_password (const struct pa + pass_max_len = getdef_num ("PASS_MAX_LEN", 8); + } + } +- if (!qflg) { ++ if (!qflg && !sflg) { + if (pass_max_len == -1) { + (void) printf (_( + "Enter the new password (minimum of %d characters)\n" +@@ -289,55 +291,67 @@ static int new_password (const struct pa + } + } + +- warned = false; +- for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) { +- cp = agetpass (_("New password: ")); ++ if (sflg) { ++ /* ++ * root is setting the passphrase from stdin ++ */ ++ cp = agetpass_stdin (); + if (NULL == cp) { +- memzero (orig, sizeof orig); +- memzero (pass, sizeof pass); + return -1; + } +- if (warned && (strcmp (pass, cp) != 0)) { +- warned = false; +- } + STRFCPY (pass, cp); + erase_pass (cp); ++ } else { ++ warned = false; ++ for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) { ++ cp = agetpass (_("New password: ")); ++ if (NULL == cp) { ++ memzero (orig, sizeof orig); ++ memzero (pass, sizeof pass); ++ return -1; ++ } ++ if (warned && (strcmp (pass, cp) != 0)) { ++ warned = false; ++ } ++ STRFCPY (pass, cp); ++ erase_pass (cp); + +- if (!amroot && !obscure(orig, pass, pw)) { +- (void) puts (_("Try again.")); +- continue; +- } ++ if (!amroot && !obscure(orig, pass, pw)) { ++ (void) puts (_("Try again.")); ++ continue; ++ } + +- /* +- * If enabled, warn about weak passwords even if you are +- * root (enter this password again to use it anyway). +- * --marekm +- */ +- if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") +- && !obscure(orig, pass, pw)) { +- (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); +- warned = true; +- continue; ++ /* ++ * If enabled, warn about weak passwords even if you are ++ * root (enter this password again to use it anyway). ++ * --marekm ++ */ ++ if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") ++ && !obscure(orig, pass, pw)) { ++ (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); ++ warned = true; ++ continue; ++ } ++ cp = agetpass (_("Re-enter new password: ")); ++ if (NULL == cp) { ++ memzero (orig, sizeof orig); ++ memzero (pass, sizeof pass); ++ return -1; ++ } ++ if (strcmp (cp, pass) != 0) { ++ erase_pass (cp); ++ (void) fputs (_("They don't match; try again.\n"), stderr); ++ } else { ++ erase_pass (cp); ++ break; ++ } + } +- cp = agetpass (_("Re-enter new password: ")); +- if (NULL == cp) { +- memzero (orig, sizeof orig); ++ memzero (orig, sizeof orig); ++ ++ if (i == 0) { + memzero (pass, sizeof pass); + return -1; + } +- if (strcmp (cp, pass) != 0) { +- erase_pass (cp); +- (void) fputs (_("They don't match; try again.\n"), stderr); +- } else { +- erase_pass (cp); +- break; +- } +- } +- memzero (orig, sizeof orig); +- +- if (i == 0) { +- memzero (pass, sizeof pass); +- return -1; + } + + /* +@@ -714,6 +728,7 @@ static void update_shadow (void) + * -u unlock the password of the named account (*) + * -w # set sp_warn to # days (*) + * -x # set sp_max to # days (*) ++ * -s read password from stdin + * + * (*) requires root permission to execute. + * +@@ -781,10 +796,11 @@ int main (int argc, char **argv) + {"unlock", no_argument, NULL, 'u'}, + {"warndays", required_argument, NULL, 'w'}, + {"maxdays", required_argument, NULL, 'x'}, ++ {"stdin", no_argument, NULL, 's'}, + {NULL, 0, NULL, '\0'} + }; + +- while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:", ++ while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:s", + long_options, NULL)) != -1) { + switch (c) { + case 'a': +@@ -877,6 +893,15 @@ int main (int argc, char **argv) + xflg = true; + anyflag = true; + break; ++ case 's': ++ if (!amroot) { ++ (void) fprintf (stderr, ++ _("%s: only root can use --stdin/-s option\n"), ++ Prog); ++ usage (E_BAD_ARG); ++ } ++ sflg = true; ++ break; + default: + usage (E_BAD_ARG); + } +@@ -1068,7 +1093,16 @@ int main (int argc, char **argv) + * Don't set the real UID for PAM... + */ + if (!anyflag && use_pam) { +- do_pam_passwd (name, qflg, kflg); ++ if (sflg) { ++ cp = agetpass_stdin (); ++ if (cp == NULL) { ++ exit (E_FAILURE); ++ } ++ do_pam_passwd_non_interactive ("passwd", name, cp); ++ erase_pass (cp); ++ } else { ++ do_pam_passwd (name, qflg, kflg); ++ } + exit (E_SUCCESS); + } + #endif /* USE_PAM */ +@@ -1102,4 +1136,3 @@ int main (int argc, char **argv) + + return E_SUCCESS; + } +- diff --git a/shadow-4.14.0-remove-libcrack.patch b/shadow-4.14.0-remove-libcrack.patch new file mode 100644 index 0000000..4dc1328 --- /dev/null +++ b/shadow-4.14.0-remove-libcrack.patch @@ -0,0 +1,306 @@ +From 43b4e5a6c41f5c43cad18810f9229e40e8c4a57e Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Mon, 30 Oct 2023 12:53:37 +0100 +Subject: [PATCH 1/2] Remove FascistHistory() and FascistHistoryPw() calls + +These functions don't seem to exist anymore. I can't find them in +Debian, nor in a web search. They probably were functions from an +ancient implementation of cracklib that doesn't exist anymore. + +$ git remote -v +origin git@github.com:cracklib/cracklib.git (fetch) +origin git@github.com:cracklib/cracklib.git (push) +$ grep -rni fascisthistory +$ git log --grep FascistHistory +$ git log -S FascistHistory + +Closes: +Cc: Mike Frysinger +Acked-by: Michael Vetter +Signed-off-by: Alejandro Colomar +--- + configure.ac | 4 ---- + libmisc/obscure.c | 8 -------- + src/passwd.c | 33 ++------------------------------- + 3 files changed, 2 insertions(+), 43 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2c8cca3f..5c8c7764 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -526,10 +526,6 @@ if test "$with_libcrack" = "yes"; then + echo "checking cracklib flavour, don't be surprised by the results" + AC_CHECK_LIB(crack, FascistCheck, + [LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])]) +- AC_CHECK_LIB(crack, FascistHistory, +- AC_DEFINE(HAVE_LIBCRACK_HIST, 1, [Defined if you have the ts&szs cracklib.])) +- AC_CHECK_LIB(crack, FascistHistoryPw, +- AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.])) + fi + + if test "$with_btrfs" != "no"; then +diff --git a/libmisc/obscure.c b/libmisc/obscure.c +index ccffb71d..4070d4e4 100644 +--- a/libmisc/obscure.c ++++ b/libmisc/obscure.c +@@ -100,11 +100,7 @@ static /*@observer@*//*@null@*/const char *password_check ( + #ifdef HAVE_LIBCRACK + char *dictpath; + +-#ifdef HAVE_LIBCRACK_PW +- char *FascistCheckPw (); +-#else + char *FascistCheck (); +-#endif + #endif + + if (strcmp (new, old) == 0) { +@@ -133,11 +129,7 @@ static /*@observer@*//*@null@*/const char *password_check ( + + dictpath = getdef_str ("CRACKLIB_DICTPATH"); + if (NULL != dictpath) { +-#ifdef HAVE_LIBCRACK_PW +- msg = FascistCheckPw (new, dictpath, pwdp); +-#else + msg = FascistCheck (new, dictpath); +-#endif + } + #endif + } +diff --git a/src/passwd.c b/src/passwd.c +index 67608619..a4f49320 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -114,7 +114,6 @@ static bool do_update_pwd = false; + /* local function prototypes */ + NORETURN static void usage (int); + +-static bool reuse (const char *, const struct passwd *); + static int new_password (const struct passwd *); + + static void check_password (const struct passwd *, const struct spwd *); +@@ -163,27 +162,6 @@ usage (int status) + exit (status); + } + +-static bool reuse (const char *pass, const struct passwd *pw) +-{ +-#ifdef HAVE_LIBCRACK_HIST +- const char *reason; +- +-#ifdef HAVE_LIBCRACK_PW +- const char *FascistHistoryPw (const char *, const struct passwd *); +- +- reason = FascistHistory (pass, pw); +-#else /* !HAVE_LIBCRACK_PW */ +- const char *FascistHistory (const char *, int); +- +- reason = FascistHistory (pass, pw->pw_uid); +-#endif /* !HAVE_LIBCRACK_PW */ +- if (NULL != reason) { +- (void) printf (_("Bad password: %s. "), reason); +- return true; +- } +-#endif /* HAVE_LIBCRACK_HIST */ +- return false; +-} + + /* + * new_password - validate old password and replace with new (both old and +@@ -202,10 +180,6 @@ static int new_password (const struct passwd *pw) + int pass_max_len = -1; + const char *method; + +-#ifdef HAVE_LIBCRACK_HIST +- int HistUpdate (const char *, const char *); +-#endif /* HAVE_LIBCRACK_HIST */ +- + /* + * Authenticate the user. The user will be prompted for their own + * password. +@@ -306,7 +280,7 @@ static int new_password (const struct passwd *pw) + STRFCPY (pass, cp); + erase_pass (cp); + +- if (!amroot && (!obscure (orig, pass, pw) || reuse (pass, pw))) { ++ if (!amroot && !obscure(orig, pass, pw)) { + (void) puts (_("Try again.")); + continue; + } +@@ -317,7 +291,7 @@ static int new_password (const struct passwd *pw) + * --marekm + */ + if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") +- && (!obscure (orig, pass, pw) || reuse (pass, pw))) { ++ && !obscure(orig, pass, pw)) { + (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); + warned = true; + continue; +@@ -357,9 +331,6 @@ static int new_password (const struct passwd *pw) + return -1; + } + +-#ifdef HAVE_LIBCRACK_HIST +- HistUpdate (pw->pw_name, crypt_passwd); +-#endif /* HAVE_LIBCRACK_HIST */ + STRFCPY (crypt_passwd, cp); + return 0; + } +-- +2.43.0 + + +From 45f34ee8c196a98397504cb7ed8576b6f1825cf9 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Mon, 30 Oct 2023 13:31:42 +0100 +Subject: [PATCH 2/2] Remove libcrack support + +Signed-off-by: Alejandro Colomar +--- + configure.ac | 11 ----------- + etc/login.defs | 5 ----- + lib/getdef.c | 1 - + libmisc/obscure.c | 22 ---------------------- + libsubid/Makefile.am | 1 - + src/Makefile.am | 2 +- + 7 files changed, 2 insertions(+), 42 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 5c8c7764..c2b0a1a5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -243,9 +243,6 @@ AC_ARG_WITH(skey, + AC_ARG_WITH(tcb, + [AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])], + [with_tcb=$withval], [with_tcb=maybe]) +-AC_ARG_WITH(libcrack, +- [AS_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])], +- [with_libcrack=$withval], [with_libcrack=no]) + AC_ARG_WITH(sha-crypt, + [AS_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])], + [with_sha_crypt=$withval], [with_sha_crypt=yes]) +@@ -521,13 +518,6 @@ if test "$with_audit" != "no"; then + fi + fi + +-AC_SUBST(LIBCRACK) +-if test "$with_libcrack" = "yes"; then +- echo "checking cracklib flavour, don't be surprised by the results" +- AC_CHECK_LIB(crack, FascistCheck, +- [LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])]) +-fi +- + if test "$with_btrfs" != "no"; then + AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \ + [btrfs_headers="yes"], [btrfs_headers="no"]) +@@ -768,7 +758,6 @@ echo + echo "shadow will be compiled with the following features:" + echo + echo " auditing support: $with_audit" +-echo " CrackLib support: $with_libcrack" + echo " PAM support: $with_libpam" + if test "$with_libpam" = "yes"; then + echo " suid account management tools: $enable_acct_tools_setuid" +diff --git a/etc/login.defs b/etc/login.defs +index 114dbcd9..33622c29 100644 +--- a/etc/login.defs ++++ b/etc/login.defs +@@ -227,11 +227,6 @@ PASS_WARN_AGE 7 + # + SU_WHEEL_ONLY no + +-# +-# If compiled with cracklib support, sets the path to the dictionaries +-# +-CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict +- + # + # Min/max values for automatic uid selection in useradd(8) + # +diff --git a/lib/getdef.c b/lib/getdef.c +index 977660c2..d64e6343 100644 +--- a/lib/getdef.c ++++ b/lib/getdef.c +@@ -39,7 +39,6 @@ struct itemdef { + #define PAMDEFS \ + {"CHFN_AUTH", NULL}, \ + {"CHSH_AUTH", NULL}, \ +- {"CRACKLIB_DICTPATH", NULL}, \ + {"ENV_HZ", NULL}, \ + {"ENVIRON_FILE", NULL}, \ + {"ENV_TZ", NULL}, \ +diff --git a/libmisc/obscure.c b/libmisc/obscure.c +index 4070d4e4..2aece68b 100644 +--- a/libmisc/obscure.c ++++ b/libmisc/obscure.c +@@ -12,11 +12,6 @@ + #ident "$Id$" + + +-/* +- * This version of obscure.c contains modifications to support "cracklib" +- * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib +- * library source code for this function to operate. +- */ + #include + #include + +@@ -97,12 +92,6 @@ static /*@observer@*//*@null@*/const char *password_check ( + const char *msg = NULL; + char *oldmono, *newmono, *wrapped; + +-#ifdef HAVE_LIBCRACK +- char *dictpath; +- +- char *FascistCheck (); +-#endif +- + if (strcmp (new, old) == 0) { + return _("no change"); + } +@@ -121,17 +110,6 @@ static /*@observer@*//*@null@*/const char *password_check ( + msg = _("too similar"); + } else if (strstr (wrapped, newmono) != NULL) { + msg = _("rotated"); +- } else { +-#ifdef HAVE_LIBCRACK +- /* +- * Invoke Alec Muffett's cracklib routines. +- */ +- +- dictpath = getdef_str ("CRACKLIB_DICTPATH"); +- if (NULL != dictpath) { +- msg = FascistCheck (new, dictpath); +- } +-#endif + } + strzero (newmono); + strzero (oldmono); +diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am +index 5ba0ab35..b6488e77 100644 +--- a/libsubid/Makefile.am ++++ b/libsubid/Makefile.am +@@ -8,7 +8,6 @@ MISCLIBS = \ + $(LIBAUDIT) \ + $(LIBSELINUX) \ + $(LIBSEMANAGE) \ +- $(LIBCRACK) \ + $(LIBCRYPT_NOPAM) \ + $(LIBSKEY) \ + $(LIBMD) \ +diff --git a/src/Makefile.am b/src/Makefile.am +index fcfee9d2..b6cb09ef 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -123,7 +123,7 @@ login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(L + newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF) + newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl + nologin_LDADD = +-passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl ++passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl + pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +-- +2.43.0 + diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index c0295b1..e84c7ab 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -130,10 +130,9 @@ HOME_MODE 0700 # PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 +PASS_MIN_LEN 8 PASS_WARN_AGE 7 -# Currently PASS_MIN_LEN is not supported - # Currently SU_WHEEL_ONLY is not supported # Currently CRACKLIB_DICTPATH is not supported @@ -174,11 +173,22 @@ SUB_GID_COUNT 65536 # #LOGIN_TIMEOUT 60 -# Currently PASS_CHANGE_TRIES is not supported +# +# Maximum number of attempts to change password if rejected (too easy) +# +PASS_CHANGE_TRIES 5 -# Currently PASS_ALWAYS_WARN is not supported +# +# Warn about weak passwords (but still allow them) if you are root. +# +PASS_ALWAYS_WARN yes -# Currently PASS_MAX_LEN is not supported +# +# Number of significant characters in the password for crypt(). +# Default is 8, don't change unless your crypt() is better. +# Ignored if MD5_CRYPT_ENAB set to "yes". +# +#PASS_MAX_LEN 8 # Currently CHFN_AUTH is not supported diff --git a/shadow-utils.spec b/shadow-utils.spec index 633f1fe..416cfa1 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.14.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -12,6 +12,7 @@ Source3: shadow-utils.login.defs Source4: shadow-bsd.txt Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt Source6: shadow-utils.HOME_MODE.xml +Source7: passwd.pamd ### Globals ### %global includesubiddir %{_includedir}/shadow @@ -25,10 +26,18 @@ Patch1: shadow-4.2.1-date-parsing.patch Patch2: shadow-4.14.0-audit-update.patch # https://github.com/shadow-maint/shadow/pull/812 Patch3: shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch +# Probably non-upstreamable +Patch4: shadow-4.14.0-account-tools-setuid.patch +# https://github.com/shadow-maint/shadow/commit/43b4e5a6c41f5c43cad18810f9229e40e8c4a57e +# https://github.com/shadow-maint/shadow/commit/45f34ee8c196a98397504cb7ed8576b6f1825cf9 +Patch5: shadow-4.14.0-remove-libcrack.patch +# https://github.com/shadow-maint/shadow/pull/927 +Patch6: shadow-4.14.0-passwd-stdin.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 Requires: libselinux >= 1.25.2-1 +Requires: pam-libs Requires: setup ### Build Dependencies ### @@ -51,9 +60,12 @@ BuildRequires: libsemanage-devel BuildRequires: libtool BuildRequires: libxslt BuildRequires: make +BuildRequires: pam-devel ### Provides ### Provides: shadow = %{epoch}:%{version}-%{release} +Provides: passwd = 0.80-18 +Obsoletes: passwd <= 0.80-19 %description The shadow-utils package includes the necessary programs for @@ -112,6 +124,7 @@ autoreconf --enable-shadowgrp \ --enable-man \ --with-audit \ + --with-libpam \ --with-sha-crypt \ --with-bcrypt \ --with-yescrypt \ @@ -123,7 +136,8 @@ autoreconf --enable-shared \ --with-group-name-max-length=32 \ --enable-lastlog \ - --enable-logind=no + --enable-logind=no \ + --disable-account-tools-setuid %make_build %install @@ -131,6 +145,8 @@ autoreconf install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/default install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/login.defs install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/default/useradd +install -d -m 755 $RPM_BUILD_ROOT%{_pam_confdir} +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/passwd ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser @@ -145,7 +161,6 @@ rm $RPM_BUILD_ROOT%{_bindir}/chsh rm $RPM_BUILD_ROOT%{_bindir}/expiry rm $RPM_BUILD_ROOT%{_bindir}/groups rm $RPM_BUILD_ROOT%{_bindir}/login -rm $RPM_BUILD_ROOT%{_bindir}/passwd rm $RPM_BUILD_ROOT%{_bindir}/su rm $RPM_BUILD_ROOT%{_bindir}/faillog rm $RPM_BUILD_ROOT%{_sysconfdir}/login.access @@ -162,8 +177,6 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/groups.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/groups.* rm $RPM_BUILD_ROOT%{_mandir}/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.* -rm $RPM_BUILD_ROOT%{_mandir}/man1/passwd.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man1/passwd.* rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/man5/limits.* @@ -187,6 +200,8 @@ rm $RPM_BUILD_ROOT%{_mandir}/*/man5/faillog.* rm $RPM_BUILD_ROOT%{_mandir}/man8/faillog.* rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* +# Remove PAM service files we don't use. + find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete %find_lang shadow for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do @@ -211,6 +226,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %license gpl-2.0.txt shadow-bsd.txt %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/login.defs %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/default/useradd +%config(noreplace) %{_pam_confdir}/passwd %{_bindir}/sg %attr(4755,root,root) %{_bindir}/chage %attr(4755,root,root) %{_bindir}/gpasswd @@ -218,6 +234,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %attr(4755,root,root) %{_bindir}/newgrp %attr(0755,root,root) %caps(cap_setgid=ep) %{_bindir}/newgidmap %attr(0755,root,root) %caps(cap_setuid=ep) %{_bindir}/newuidmap +%attr(4755,root,root) %{_bindir}/passwd %{_sbindir}/adduser %attr(0755,root,root) %{_sbindir}/user* %attr(0755,root,root) %{_sbindir}/group* @@ -235,6 +252,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_mandir}/man1/newgrp.1* %{_mandir}/man1/newgidmap.1* %{_mandir}/man1/newuidmap.1* +%{_mandir}/man1/passwd.* %{_mandir}/man3/shadow.3* %{_mandir}/man5/shadow.5* %{_mandir}/man5/login.defs.5* @@ -264,6 +282,12 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Feb 1 2024 Iker Pedrosa - 2:4.14.0-5 +- passwd: Provide binary from this package. Enable libpam and + disable account-tools-setuid. Provide passwd PAM service file. + Resolves: #2233275 +- passwd: provide --stdin option + * Mon Jan 29 2024 Iker Pedrosa - 2:4.14.0-4 - Disable SSSD support. Resolves: #2253182 From 07607754dfff84049249e3d0a474b5ec203d6e01 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 12 Feb 2024 15:57:19 +0100 Subject: [PATCH 063/118] Build linking `libpam` Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 416cfa1..6b705cd 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.14.0 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -131,7 +131,6 @@ autoreconf --with-selinux \ --without-libbsd \ --without-libcrack \ - --without-libpam \ --without-sssd \ --enable-shared \ --with-group-name-max-length=32 \ @@ -163,8 +162,6 @@ rm $RPM_BUILD_ROOT%{_bindir}/groups rm $RPM_BUILD_ROOT%{_bindir}/login rm $RPM_BUILD_ROOT%{_bindir}/su rm $RPM_BUILD_ROOT%{_bindir}/faillog -rm $RPM_BUILD_ROOT%{_sysconfdir}/login.access -rm $RPM_BUILD_ROOT%{_sysconfdir}/limits rm $RPM_BUILD_ROOT%{_sbindir}/logoutd rm $RPM_BUILD_ROOT%{_sbindir}/nologin rm $RPM_BUILD_ROOT%{_mandir}/man1/chfn.* @@ -179,14 +176,8 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.* -rm $RPM_BUILD_ROOT%{_mandir}/man5/limits.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man5/limits.* -rm $RPM_BUILD_ROOT%{_mandir}/man5/login.access.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man5/login.access.* rm $RPM_BUILD_ROOT%{_mandir}/man5/passwd.* rm $RPM_BUILD_ROOT%{_mandir}/*/man5/passwd.* -rm $RPM_BUILD_ROOT%{_mandir}/man5/porttime.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man5/porttime.* rm $RPM_BUILD_ROOT%{_mandir}/man5/suauth.* rm $RPM_BUILD_ROOT%{_mandir}/*/man5/suauth.* rm $RPM_BUILD_ROOT%{_mandir}/man8/logoutd.* @@ -201,6 +192,11 @@ rm $RPM_BUILD_ROOT%{_mandir}/man8/faillog.* rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* # Remove PAM service files we don't use. +rm $RPM_BUILD_ROOT%{_pam_confdir}/chfn +rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh +rm $RPM_BUILD_ROOT%{_pam_confdir}/groupmems +rm $RPM_BUILD_ROOT%{_pam_confdir}/login +rm $RPM_BUILD_ROOT%{_pam_confdir}/su find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete %find_lang shadow @@ -282,6 +278,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Feb 12 2024 Iker Pedrosa - 2:4.14.0-6 +- Build linking `libpam` + * Thu Feb 1 2024 Iker Pedrosa - 2:4.14.0-5 - passwd: Provide binary from this package. Enable libpam and disable account-tools-setuid. Provide passwd PAM service file. From fb4d9302930511096134f042c54aaa360a7af8e2 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 19 Feb 2024 10:56:01 +0100 Subject: [PATCH 064/118] Rebase to version 4.15.0rc2 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.14.0-passwd-stdin.patch | 288 ---------- shadow-4.14.0-remove-libcrack.patch | 306 ---------- ...seradd-def-usrtemplate-selinux-label.patch | 28 - ....patch => shadow-4.15.0-audit-update.patch | 523 ++++++++---------- ....patch => shadow-4.15.0-date-parsing.patch | 6 +- ...manfix.patch => shadow-4.15.0-manfix.patch | 54 +- shadow-utils.spec | 26 +- sources | 4 +- 9 files changed, 277 insertions(+), 960 deletions(-) delete mode 100644 shadow-4.14.0-passwd-stdin.patch delete mode 100644 shadow-4.14.0-remove-libcrack.patch delete mode 100644 shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch rename shadow-4.14.0-audit-update.patch => shadow-4.15.0-audit-update.patch (80%) rename shadow-4.2.1-date-parsing.patch => shadow-4.15.0-date-parsing.patch (93%) rename shadow-4.14.0-manfix.patch => shadow-4.15.0-manfix.patch (76%) diff --git a/.gitignore b/.gitignore index 422ed12..8b8ecf6 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.13.tar.xz.asc /shadow-4.14.0.tar.xz /shadow-4.14.0.tar.xz.asc +/shadow-4.15.0rc2.tar.xz +/shadow-4.15.0rc2.tar.xz.asc diff --git a/shadow-4.14.0-passwd-stdin.patch b/shadow-4.14.0-passwd-stdin.patch deleted file mode 100644 index 2603350..0000000 --- a/shadow-4.14.0-passwd-stdin.patch +++ /dev/null @@ -1,288 +0,0 @@ -diff -up shadow-4.14.0/libmisc/agetpass.c.orig shadow-4.14.0/libmisc/agetpass.c ---- shadow-4.14.0/libmisc/agetpass.c.orig 2024-01-24 20:06:20.557577853 +0100 -+++ shadow-4.14.0/libmisc/agetpass.c 2024-01-24 21:21:06.379445080 +0100 -@@ -32,6 +32,7 @@ - * SYNOPSIS - * [[gnu::malloc(erase_pass)]] - * char *agetpass(const char *prompt); -+ * char *agetpass_stdin(); - * - * void erase_pass(char *pass); - * -@@ -64,6 +65,10 @@ - * erased by calling erase_pass(), to avoid possibly leaking the - * password. - * -+ * agetpass_stdin() -+ * This function is the same as previous one (agetpass). Just the -+ * password is read from stdin and terminal is not required. -+ * - * erase_pass() - * This function first clears the password, by calling - * explicit_bzero(3) (or an equivalent call), and then frees the -@@ -92,8 +97,8 @@ - */ - - --char * --agetpass(const char *prompt) -+static char * -+agetpass_internal(const char *prompt, int flags) - { - char *pass; - size_t len; -@@ -110,7 +115,7 @@ agetpass(const char *prompt) - if (pass == NULL) - return NULL; - -- if (readpassphrase(prompt, pass, PASS_MAX + 2, RPP_REQUIRE_TTY) == NULL) -+ if (readpassphrase(prompt, pass, PASS_MAX + 2, flags) == NULL) - goto fail; - - len = strlen(pass); -@@ -126,6 +131,17 @@ fail: - return NULL; - } - -+char * -+agetpass(const char *prompt) -+{ -+ return agetpass_internal(prompt, RPP_REQUIRE_TTY); -+} -+ -+char * -+agetpass_stdin() -+{ -+ return agetpass_internal(NULL, RPP_STDIN); -+} - - void - erase_pass(char *pass) -diff -up shadow-4.14.0/lib/prototypes.h.orig shadow-4.14.0/lib/prototypes.h ---- shadow-4.14.0/lib/prototypes.h.orig 2024-01-24 22:06:18.786184942 +0100 -+++ shadow-4.14.0/lib/prototypes.h 2024-01-24 20:19:45.299231059 +0100 -@@ -47,6 +47,7 @@ extern int expire (const struct passwd * - extern void erase_pass(char *pass); - ATTR_MALLOC(erase_pass) - extern char *agetpass(const char *prompt); -+extern char *agetpass_stdin(); - - /* isexpired.c */ - extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); -diff -up shadow-4.14.0/man/passwd.1.xml.orig shadow-4.14.0/man/passwd.1.xml ---- shadow-4.14.0/man/passwd.1.xml.orig 2024-01-24 20:33:31.438972506 +0100 -+++ shadow-4.14.0/man/passwd.1.xml 2024-01-29 17:36:31.082495245 +0100 -@@ -341,6 +341,17 @@ - - - -+ -+ -+ , -+ -+ -+ -+ This option is used to indicate that passwd should read the new password from standard -+ input, which can be a pipe. -+ -+ -+ - - - -diff -up shadow-4.14.0/src/passwd.c.orig shadow-4.14.0/src/passwd.c ---- shadow-4.14.0/src/passwd.c.orig 2024-01-24 13:57:15.714549266 +0100 -+++ shadow-4.14.0/src/passwd.c 2024-01-29 17:33:59.421508534 +0100 -@@ -65,7 +65,8 @@ static bool - Sflg = false, /* -S - show password status */ - uflg = false, /* -u - unlock the user's password */ - wflg = false, /* -w - set warning days */ -- xflg = false; /* -x - set maximum days */ -+ xflg = false, /* -x - set maximum days */ -+ sflg = false; /* -s - read passwd from stdin */ - - /* - * set to 1 if there are any flags which require root privileges, -@@ -156,6 +157,7 @@ usage (int status) - (void) fputs (_(" -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout); - (void) fputs (_(" -x, --maxdays MAX_DAYS set maximum number of days before password\n" - " change to MAX_DAYS\n"), usageout); -+ (void) fputs (_(" -s, --stdin read new token from stdin\n"), usageout); - (void) fputs ("\n", usageout); - exit (status); - } -@@ -275,7 +277,7 @@ static int new_password (const struct pa - pass_max_len = getdef_num ("PASS_MAX_LEN", 8); - } - } -- if (!qflg) { -+ if (!qflg && !sflg) { - if (pass_max_len == -1) { - (void) printf (_( - "Enter the new password (minimum of %d characters)\n" -@@ -289,55 +291,67 @@ static int new_password (const struct pa - } - } - -- warned = false; -- for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) { -- cp = agetpass (_("New password: ")); -+ if (sflg) { -+ /* -+ * root is setting the passphrase from stdin -+ */ -+ cp = agetpass_stdin (); - if (NULL == cp) { -- memzero (orig, sizeof orig); -- memzero (pass, sizeof pass); - return -1; - } -- if (warned && (strcmp (pass, cp) != 0)) { -- warned = false; -- } - STRFCPY (pass, cp); - erase_pass (cp); -+ } else { -+ warned = false; -+ for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) { -+ cp = agetpass (_("New password: ")); -+ if (NULL == cp) { -+ memzero (orig, sizeof orig); -+ memzero (pass, sizeof pass); -+ return -1; -+ } -+ if (warned && (strcmp (pass, cp) != 0)) { -+ warned = false; -+ } -+ STRFCPY (pass, cp); -+ erase_pass (cp); - -- if (!amroot && !obscure(orig, pass, pw)) { -- (void) puts (_("Try again.")); -- continue; -- } -+ if (!amroot && !obscure(orig, pass, pw)) { -+ (void) puts (_("Try again.")); -+ continue; -+ } - -- /* -- * If enabled, warn about weak passwords even if you are -- * root (enter this password again to use it anyway). -- * --marekm -- */ -- if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") -- && !obscure(orig, pass, pw)) { -- (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); -- warned = true; -- continue; -+ /* -+ * If enabled, warn about weak passwords even if you are -+ * root (enter this password again to use it anyway). -+ * --marekm -+ */ -+ if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") -+ && !obscure(orig, pass, pw)) { -+ (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); -+ warned = true; -+ continue; -+ } -+ cp = agetpass (_("Re-enter new password: ")); -+ if (NULL == cp) { -+ memzero (orig, sizeof orig); -+ memzero (pass, sizeof pass); -+ return -1; -+ } -+ if (strcmp (cp, pass) != 0) { -+ erase_pass (cp); -+ (void) fputs (_("They don't match; try again.\n"), stderr); -+ } else { -+ erase_pass (cp); -+ break; -+ } - } -- cp = agetpass (_("Re-enter new password: ")); -- if (NULL == cp) { -- memzero (orig, sizeof orig); -+ memzero (orig, sizeof orig); -+ -+ if (i == 0) { - memzero (pass, sizeof pass); - return -1; - } -- if (strcmp (cp, pass) != 0) { -- erase_pass (cp); -- (void) fputs (_("They don't match; try again.\n"), stderr); -- } else { -- erase_pass (cp); -- break; -- } -- } -- memzero (orig, sizeof orig); -- -- if (i == 0) { -- memzero (pass, sizeof pass); -- return -1; - } - - /* -@@ -714,6 +728,7 @@ static void update_shadow (void) - * -u unlock the password of the named account (*) - * -w # set sp_warn to # days (*) - * -x # set sp_max to # days (*) -+ * -s read password from stdin - * - * (*) requires root permission to execute. - * -@@ -781,10 +796,11 @@ int main (int argc, char **argv) - {"unlock", no_argument, NULL, 'u'}, - {"warndays", required_argument, NULL, 'w'}, - {"maxdays", required_argument, NULL, 'x'}, -+ {"stdin", no_argument, NULL, 's'}, - {NULL, 0, NULL, '\0'} - }; - -- while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:", -+ while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:s", - long_options, NULL)) != -1) { - switch (c) { - case 'a': -@@ -877,6 +893,15 @@ int main (int argc, char **argv) - xflg = true; - anyflag = true; - break; -+ case 's': -+ if (!amroot) { -+ (void) fprintf (stderr, -+ _("%s: only root can use --stdin/-s option\n"), -+ Prog); -+ usage (E_BAD_ARG); -+ } -+ sflg = true; -+ break; - default: - usage (E_BAD_ARG); - } -@@ -1068,7 +1093,16 @@ int main (int argc, char **argv) - * Don't set the real UID for PAM... - */ - if (!anyflag && use_pam) { -- do_pam_passwd (name, qflg, kflg); -+ if (sflg) { -+ cp = agetpass_stdin (); -+ if (cp == NULL) { -+ exit (E_FAILURE); -+ } -+ do_pam_passwd_non_interactive ("passwd", name, cp); -+ erase_pass (cp); -+ } else { -+ do_pam_passwd (name, qflg, kflg); -+ } - exit (E_SUCCESS); - } - #endif /* USE_PAM */ -@@ -1102,4 +1136,3 @@ int main (int argc, char **argv) - - return E_SUCCESS; - } -- diff --git a/shadow-4.14.0-remove-libcrack.patch b/shadow-4.14.0-remove-libcrack.patch deleted file mode 100644 index 4dc1328..0000000 --- a/shadow-4.14.0-remove-libcrack.patch +++ /dev/null @@ -1,306 +0,0 @@ -From 43b4e5a6c41f5c43cad18810f9229e40e8c4a57e Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Mon, 30 Oct 2023 12:53:37 +0100 -Subject: [PATCH 1/2] Remove FascistHistory() and FascistHistoryPw() calls - -These functions don't seem to exist anymore. I can't find them in -Debian, nor in a web search. They probably were functions from an -ancient implementation of cracklib that doesn't exist anymore. - -$ git remote -v -origin git@github.com:cracklib/cracklib.git (fetch) -origin git@github.com:cracklib/cracklib.git (push) -$ grep -rni fascisthistory -$ git log --grep FascistHistory -$ git log -S FascistHistory - -Closes: -Cc: Mike Frysinger -Acked-by: Michael Vetter -Signed-off-by: Alejandro Colomar ---- - configure.ac | 4 ---- - libmisc/obscure.c | 8 -------- - src/passwd.c | 33 ++------------------------------- - 3 files changed, 2 insertions(+), 43 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 2c8cca3f..5c8c7764 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -526,10 +526,6 @@ if test "$with_libcrack" = "yes"; then - echo "checking cracklib flavour, don't be surprised by the results" - AC_CHECK_LIB(crack, FascistCheck, - [LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])]) -- AC_CHECK_LIB(crack, FascistHistory, -- AC_DEFINE(HAVE_LIBCRACK_HIST, 1, [Defined if you have the ts&szs cracklib.])) -- AC_CHECK_LIB(crack, FascistHistoryPw, -- AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.])) - fi - - if test "$with_btrfs" != "no"; then -diff --git a/libmisc/obscure.c b/libmisc/obscure.c -index ccffb71d..4070d4e4 100644 ---- a/libmisc/obscure.c -+++ b/libmisc/obscure.c -@@ -100,11 +100,7 @@ static /*@observer@*//*@null@*/const char *password_check ( - #ifdef HAVE_LIBCRACK - char *dictpath; - --#ifdef HAVE_LIBCRACK_PW -- char *FascistCheckPw (); --#else - char *FascistCheck (); --#endif - #endif - - if (strcmp (new, old) == 0) { -@@ -133,11 +129,7 @@ static /*@observer@*//*@null@*/const char *password_check ( - - dictpath = getdef_str ("CRACKLIB_DICTPATH"); - if (NULL != dictpath) { --#ifdef HAVE_LIBCRACK_PW -- msg = FascistCheckPw (new, dictpath, pwdp); --#else - msg = FascistCheck (new, dictpath); --#endif - } - #endif - } -diff --git a/src/passwd.c b/src/passwd.c -index 67608619..a4f49320 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -114,7 +114,6 @@ static bool do_update_pwd = false; - /* local function prototypes */ - NORETURN static void usage (int); - --static bool reuse (const char *, const struct passwd *); - static int new_password (const struct passwd *); - - static void check_password (const struct passwd *, const struct spwd *); -@@ -163,27 +162,6 @@ usage (int status) - exit (status); - } - --static bool reuse (const char *pass, const struct passwd *pw) --{ --#ifdef HAVE_LIBCRACK_HIST -- const char *reason; -- --#ifdef HAVE_LIBCRACK_PW -- const char *FascistHistoryPw (const char *, const struct passwd *); -- -- reason = FascistHistory (pass, pw); --#else /* !HAVE_LIBCRACK_PW */ -- const char *FascistHistory (const char *, int); -- -- reason = FascistHistory (pass, pw->pw_uid); --#endif /* !HAVE_LIBCRACK_PW */ -- if (NULL != reason) { -- (void) printf (_("Bad password: %s. "), reason); -- return true; -- } --#endif /* HAVE_LIBCRACK_HIST */ -- return false; --} - - /* - * new_password - validate old password and replace with new (both old and -@@ -202,10 +180,6 @@ static int new_password (const struct passwd *pw) - int pass_max_len = -1; - const char *method; - --#ifdef HAVE_LIBCRACK_HIST -- int HistUpdate (const char *, const char *); --#endif /* HAVE_LIBCRACK_HIST */ -- - /* - * Authenticate the user. The user will be prompted for their own - * password. -@@ -306,7 +280,7 @@ static int new_password (const struct passwd *pw) - STRFCPY (pass, cp); - erase_pass (cp); - -- if (!amroot && (!obscure (orig, pass, pw) || reuse (pass, pw))) { -+ if (!amroot && !obscure(orig, pass, pw)) { - (void) puts (_("Try again.")); - continue; - } -@@ -317,7 +291,7 @@ static int new_password (const struct passwd *pw) - * --marekm - */ - if (amroot && !warned && getdef_bool ("PASS_ALWAYS_WARN") -- && (!obscure (orig, pass, pw) || reuse (pass, pw))) { -+ && !obscure(orig, pass, pw)) { - (void) puts (_("\nWarning: weak password (enter it again to use it anyway).")); - warned = true; - continue; -@@ -357,9 +331,6 @@ static int new_password (const struct passwd *pw) - return -1; - } - --#ifdef HAVE_LIBCRACK_HIST -- HistUpdate (pw->pw_name, crypt_passwd); --#endif /* HAVE_LIBCRACK_HIST */ - STRFCPY (crypt_passwd, cp); - return 0; - } --- -2.43.0 - - -From 45f34ee8c196a98397504cb7ed8576b6f1825cf9 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Mon, 30 Oct 2023 13:31:42 +0100 -Subject: [PATCH 2/2] Remove libcrack support - -Signed-off-by: Alejandro Colomar ---- - configure.ac | 11 ----------- - etc/login.defs | 5 ----- - lib/getdef.c | 1 - - libmisc/obscure.c | 22 ---------------------- - libsubid/Makefile.am | 1 - - src/Makefile.am | 2 +- - 7 files changed, 2 insertions(+), 42 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 5c8c7764..c2b0a1a5 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -243,9 +243,6 @@ AC_ARG_WITH(skey, - AC_ARG_WITH(tcb, - [AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])], - [with_tcb=$withval], [with_tcb=maybe]) --AC_ARG_WITH(libcrack, -- [AS_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])], -- [with_libcrack=$withval], [with_libcrack=no]) - AC_ARG_WITH(sha-crypt, - [AS_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])], - [with_sha_crypt=$withval], [with_sha_crypt=yes]) -@@ -521,13 +518,6 @@ if test "$with_audit" != "no"; then - fi - fi - --AC_SUBST(LIBCRACK) --if test "$with_libcrack" = "yes"; then -- echo "checking cracklib flavour, don't be surprised by the results" -- AC_CHECK_LIB(crack, FascistCheck, -- [LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])]) --fi -- - if test "$with_btrfs" != "no"; then - AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \ - [btrfs_headers="yes"], [btrfs_headers="no"]) -@@ -768,7 +758,6 @@ echo - echo "shadow will be compiled with the following features:" - echo - echo " auditing support: $with_audit" --echo " CrackLib support: $with_libcrack" - echo " PAM support: $with_libpam" - if test "$with_libpam" = "yes"; then - echo " suid account management tools: $enable_acct_tools_setuid" -diff --git a/etc/login.defs b/etc/login.defs -index 114dbcd9..33622c29 100644 ---- a/etc/login.defs -+++ b/etc/login.defs -@@ -227,11 +227,6 @@ PASS_WARN_AGE 7 - # - SU_WHEEL_ONLY no - --# --# If compiled with cracklib support, sets the path to the dictionaries --# --CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict -- - # - # Min/max values for automatic uid selection in useradd(8) - # -diff --git a/lib/getdef.c b/lib/getdef.c -index 977660c2..d64e6343 100644 ---- a/lib/getdef.c -+++ b/lib/getdef.c -@@ -39,7 +39,6 @@ struct itemdef { - #define PAMDEFS \ - {"CHFN_AUTH", NULL}, \ - {"CHSH_AUTH", NULL}, \ -- {"CRACKLIB_DICTPATH", NULL}, \ - {"ENV_HZ", NULL}, \ - {"ENVIRON_FILE", NULL}, \ - {"ENV_TZ", NULL}, \ -diff --git a/libmisc/obscure.c b/libmisc/obscure.c -index 4070d4e4..2aece68b 100644 ---- a/libmisc/obscure.c -+++ b/libmisc/obscure.c -@@ -12,11 +12,6 @@ - #ident "$Id$" - - --/* -- * This version of obscure.c contains modifications to support "cracklib" -- * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib -- * library source code for this function to operate. -- */ - #include - #include - -@@ -97,12 +92,6 @@ static /*@observer@*//*@null@*/const char *password_check ( - const char *msg = NULL; - char *oldmono, *newmono, *wrapped; - --#ifdef HAVE_LIBCRACK -- char *dictpath; -- -- char *FascistCheck (); --#endif -- - if (strcmp (new, old) == 0) { - return _("no change"); - } -@@ -121,17 +110,6 @@ static /*@observer@*//*@null@*/const char *password_check ( - msg = _("too similar"); - } else if (strstr (wrapped, newmono) != NULL) { - msg = _("rotated"); -- } else { --#ifdef HAVE_LIBCRACK -- /* -- * Invoke Alec Muffett's cracklib routines. -- */ -- -- dictpath = getdef_str ("CRACKLIB_DICTPATH"); -- if (NULL != dictpath) { -- msg = FascistCheck (new, dictpath); -- } --#endif - } - strzero (newmono); - strzero (oldmono); -diff --git a/libsubid/Makefile.am b/libsubid/Makefile.am -index 5ba0ab35..b6488e77 100644 ---- a/libsubid/Makefile.am -+++ b/libsubid/Makefile.am -@@ -8,7 +8,6 @@ MISCLIBS = \ - $(LIBAUDIT) \ - $(LIBSELINUX) \ - $(LIBSEMANAGE) \ -- $(LIBCRACK) \ - $(LIBCRYPT_NOPAM) \ - $(LIBSKEY) \ - $(LIBMD) \ -diff --git a/src/Makefile.am b/src/Makefile.am -index fcfee9d2..b6cb09ef 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -123,7 +123,7 @@ login_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(L - newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF) - newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl - nologin_LDADD = --passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl -+passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl - pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) - pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) --- -2.43.0 - diff --git a/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch b/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch deleted file mode 100644 index 97b709a..0000000 --- a/shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 48aa12af31c0b72872b411857d03a518a4200a3d Mon Sep 17 00:00:00 2001 -From: Johannes Segitz -Date: Tue, 26 Sep 2023 15:14:14 +0200 -Subject: [PATCH] useradd: Set proper SELinux labels for def_usrtemplate - -Fixes: 74c17c716 ("Add support for skeleton files from /usr/etc/skel") - -Signed-off-by: Johannes Segitz ---- - src/useradd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 76a4d649..fe62a051 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2788,7 +2788,7 @@ int main (int argc, char **argv) - if (home_added) { - copy_tree (def_template, prefix_user_home, false, true, - (uid_t)-1, user_id, (gid_t)-1, user_gid); -- copy_tree (def_usrtemplate, prefix_user_home, false, false, -+ copy_tree (def_usrtemplate, prefix_user_home, false, true, - (uid_t)-1, user_id, (gid_t)-1, user_gid); - } else { - fprintf (stderr, --- -2.41.0 - diff --git a/shadow-4.14.0-audit-update.patch b/shadow-4.15.0-audit-update.patch similarity index 80% rename from shadow-4.14.0-audit-update.patch rename to shadow-4.15.0-audit-update.patch index 0ff7dae..60c1ad7 100644 --- a/shadow-4.14.0-audit-update.patch +++ b/shadow-4.15.0-audit-update.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.14.0/libmisc/audit_help.c.audit-update shadow-4.14.0/libmisc/audit_help.c ---- shadow-4.14.0/libmisc/audit_help.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.14.0/libmisc/audit_help.c 2023-08-04 09:30:25.206963536 +0200 -@@ -46,7 +46,7 @@ void audit_help_open (void) +diff -up shadow-4.15.0/lib/audit_help.c.audit-update shadow-4.15.0/lib/audit_help.c +--- shadow-4.15.0/lib/audit_help.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/lib/audit_help.c 2024-02-09 10:49:57.106840590 +0100 +@@ -48,7 +48,7 @@ void audit_help_open (void) * This function will log a message to the audit system using a predefined * message format. Parameter usage is as follows: * @@ -10,7 +10,7 @@ diff -up shadow-4.14.0/libmisc/audit_help.c.audit-update shadow-4.14.0/libmisc/a * attributes. * pgname - program's name * op - operation. "adding user", "changing finger info", "deleting group" -@@ -66,6 +66,39 @@ void audit_logger (int type, unused cons +@@ -68,6 +68,39 @@ void audit_logger (int type, MAYBE_UNUSE } } @@ -27,7 +27,7 @@ diff -up shadow-4.14.0/libmisc/audit_help.c.audit-update shadow-4.14.0/libmisc/a + * only when user is NULL. + * grp - group name associated with event + */ -+void audit_logger_with_group (int type, unused const char *pgname, ++void audit_logger_with_group (int type, MAYBE_UNUSED const char *pgname, + const char *op, const char *name, unsigned int id, + const char *grp, shadow_audit_result result) +{ @@ -50,10 +50,10 @@ diff -up shadow-4.14.0/libmisc/audit_help.c.audit-update shadow-4.14.0/libmisc/a void audit_logger_message (const char *message, shadow_audit_result result) { if (audit_fd < 0) { -diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmisc/cleanup_group.c ---- shadow-4.14.0/libmisc/cleanup_group.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.14.0/libmisc/cleanup_group.c 2023-08-04 09:30:25.207963539 +0200 -@@ -61,7 +61,7 @@ void cleanup_report_mod_group (void *cle +diff -up shadow-4.15.0/lib/cleanup_group.c.audit-update shadow-4.15.0/lib/cleanup_group.c +--- shadow-4.15.0/lib/cleanup_group.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/lib/cleanup_group.c 2024-02-09 10:49:57.106840590 +0100 +@@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cle gr_dbname (), info->action)); #ifdef WITH_AUDIT @@ -62,7 +62,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -79,7 +79,7 @@ void cleanup_report_mod_gshadow (void *c +@@ -80,7 +80,7 @@ void cleanup_report_mod_gshadow (void *c sgr_dbname (), info->action)); #ifdef WITH_AUDIT @@ -71,7 +71,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -100,7 +100,7 @@ void cleanup_report_add_group_group (voi +@@ -101,7 +101,7 @@ void cleanup_report_add_group_group (voi SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, log_get_progname(), @@ -80,7 +80,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -119,8 +119,8 @@ void cleanup_report_add_group_gshadow (v +@@ -120,8 +120,8 @@ void cleanup_report_add_group_gshadow (v SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); #ifdef WITH_AUDIT @@ -91,7 +91,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -142,8 +142,8 @@ void cleanup_report_del_group_group (voi +@@ -143,8 +143,8 @@ void cleanup_report_del_group_group (voi "failed to remove group %s from %s", name, gr_dbname ())); #ifdef WITH_AUDIT @@ -102,7 +102,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -165,8 +165,8 @@ void cleanup_report_del_group_gshadow (v +@@ -166,8 +166,8 @@ void cleanup_report_del_group_gshadow (v "failed to remove group %s from %s", name, sgr_dbname ())); #ifdef WITH_AUDIT @@ -113,7 +113,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -186,7 +186,7 @@ void cleanup_unlock_group (unused void * +@@ -187,7 +187,7 @@ void cleanup_unlock_group (MAYBE_UNUSED log_get_progname(), gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); #ifdef WITH_AUDIT @@ -122,7 +122,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis SHADOW_AUDIT_FAILURE); #endif } -@@ -206,7 +206,7 @@ void cleanup_unlock_gshadow (unused void +@@ -207,7 +207,7 @@ void cleanup_unlock_gshadow (MAYBE_UNUSE log_get_progname(), sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); #ifdef WITH_AUDIT @@ -131,10 +131,10 @@ diff -up shadow-4.14.0/libmisc/cleanup_group.c.audit-update shadow-4.14.0/libmis SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc/cleanup_user.c ---- shadow-4.14.0/libmisc/cleanup_user.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.14.0/libmisc/cleanup_user.c 2023-08-04 09:30:25.207963539 +0200 -@@ -43,7 +43,7 @@ void cleanup_report_mod_passwd (void *cl +diff -up shadow-4.15.0/lib/cleanup_user.c.audit-update shadow-4.15.0/lib/cleanup_user.c +--- shadow-4.15.0/lib/cleanup_user.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/lib/cleanup_user.c 2024-02-09 10:49:57.106840590 +0100 +@@ -44,7 +44,7 @@ void cleanup_report_mod_passwd (void *cl pw_dbname (), info->action)); #ifdef WITH_AUDIT @@ -143,7 +143,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc info->audit_msg, info->name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -@@ -64,7 +64,7 @@ void cleanup_report_add_user_passwd (voi +@@ -65,7 +65,7 @@ void cleanup_report_add_user_passwd (voi SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, log_get_progname(), @@ -152,7 +152,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -83,8 +83,8 @@ void cleanup_report_add_user_shadow (voi +@@ -84,8 +84,8 @@ void cleanup_report_add_user_shadow (voi SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); #ifdef WITH_AUDIT @@ -163,7 +163,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -103,7 +103,7 @@ void cleanup_unlock_passwd (unused void +@@ -104,7 +104,7 @@ void cleanup_unlock_passwd (MAYBE_UNUSED log_get_progname(), pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT @@ -172,7 +172,7 @@ diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc SHADOW_AUDIT_FAILURE); #endif } -@@ -122,7 +122,7 @@ void cleanup_unlock_shadow (unused void +@@ -123,7 +123,7 @@ void cleanup_unlock_shadow (MAYBE_UNUSED log_get_progname(), spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT @@ -181,10 +181,10 @@ diff -up shadow-4.14.0/libmisc/cleanup_user.c.audit-update shadow-4.14.0/libmisc SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.14.0/lib/prototypes.h.audit-update shadow-4.14.0/lib/prototypes.h ---- shadow-4.14.0/lib/prototypes.h.audit-update 2023-08-03 18:28:35.000000000 +0200 -+++ shadow-4.14.0/lib/prototypes.h 2023-08-04 09:30:25.207963539 +0200 -@@ -202,12 +202,21 @@ extern int audit_fd; +diff -up shadow-4.15.0/lib/prototypes.h.audit-update shadow-4.15.0/lib/prototypes.h +--- shadow-4.15.0/lib/prototypes.h.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/lib/prototypes.h 2024-02-09 10:49:57.106840590 +0100 +@@ -198,12 +198,21 @@ extern int audit_fd; extern void audit_help_open (void); /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ #define AUDIT_NO_ID ((unsigned int) -1) @@ -200,16 +200,16 @@ diff -up shadow-4.14.0/lib/prototypes.h.audit-update shadow-4.14.0/lib/prototype extern void audit_logger (int type, const char *pgname, const char *op, const char *name, unsigned int id, shadow_audit_result result); -+void audit_logger_with_group (int type, unused const char *pgname, ++void audit_logger_with_group (int type, MAYBE_UNUSED const char *pgname, + const char *op, const char *name, unsigned int id, + const char *grp, shadow_audit_result result); void audit_logger_message (const char *message, shadow_audit_result result); #endif -diff -up shadow-4.14.0/src/chage.c.audit-update shadow-4.14.0/src/chage.c ---- shadow-4.14.0/src/chage.c.audit-update 2023-08-04 09:30:25.207963539 +0200 -+++ shadow-4.14.0/src/chage.c 2023-08-04 09:31:12.237080212 +0200 -@@ -106,8 +106,8 @@ fail_exit (int code) +diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c +--- shadow-4.15.0/src/chage.c.audit-update 2024-01-22 22:36:43.000000000 +0100 ++++ shadow-4.15.0/src/chage.c 2024-02-09 10:49:57.106840590 +0100 +@@ -110,8 +110,8 @@ fail_exit (int code) #ifdef WITH_AUDIT if (E_SUCCESS != code) { @@ -220,7 +220,7 @@ diff -up shadow-4.14.0/src/chage.c.audit-update shadow-4.14.0/src/chage.c } #endif -@@ -841,10 +841,7 @@ int main (int argc, char **argv) +@@ -845,10 +845,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } @@ -232,7 +232,7 @@ diff -up shadow-4.14.0/src/chage.c.audit-update shadow-4.14.0/src/chage.c list_fields (); fail_exit (E_SUCCESS); } -@@ -863,39 +860,39 @@ int main (int argc, char **argv) +@@ -867,39 +864,39 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT else { @@ -287,10 +287,10 @@ diff -up shadow-4.14.0/src/chage.c.audit-update shadow-4.14.0/src/chage.c user_name, user_uid, 1); } #endif -diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c ---- shadow-4.14.0/src/gpasswd.c.audit-update 2023-06-11 03:35:50.000000000 +0200 -+++ shadow-4.14.0/src/gpasswd.c 2023-08-04 09:30:25.207963539 +0200 -@@ -118,7 +118,7 @@ static void usage (int status) +diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c +--- shadow-4.15.0/src/gpasswd.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/src/gpasswd.c 2024-02-09 10:55:42.642444103 +0100 +@@ -125,7 +125,7 @@ static void usage (int status) (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); @@ -299,22 +299,21 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); #ifdef SHADOWGRP -@@ -377,21 +377,14 @@ static void open_files (void) +@@ -384,20 +384,14 @@ static void open_files (void) static void log_gpasswd_failure (const char *suffix) { -#ifdef WITH_AUDIT -- char buf[1024]; +- char buf[1024]; -#endif +- if (aflg) { SYSLOG ((LOG_ERR, "%s failed to add user %s to group %s%s", myname, user, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to add user %s to group %s%s", -- myname, user, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to add user %s to group %s%s", +- myname, user, group, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -324,14 +323,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (dflg) { -@@ -399,13 +392,9 @@ static void log_gpasswd_failure (const c +@@ -405,11 +399,9 @@ static void log_gpasswd_failure (const c "%s failed to remove user %s from group %s%s", myname, user, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to remove user %s from group %s%s", -- myname, user, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to remove user %s from group %s%s", +- myname, user, group, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -341,14 +338,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (rflg) { -@@ -413,13 +402,9 @@ static void log_gpasswd_failure (const c +@@ -417,11 +409,9 @@ static void log_gpasswd_failure (const c "%s failed to remove password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to remove password of group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to remove password of group %s%s", +- myname, group, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -358,14 +353,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Rflg) { -@@ -427,13 +412,9 @@ static void log_gpasswd_failure (const c +@@ -429,11 +429,9 @@ static void log_gpasswd_failure (const c "%s failed to restrict access to group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to restrict access to group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to restrict access to group %s%s", +- myname, group, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -375,14 +368,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Aflg || Mflg) { -@@ -443,13 +424,9 @@ static void log_gpasswd_failure (const c +@@ -443,11 +433,9 @@ static void log_gpasswd_failure (const c "%s failed to set the administrators of group %s to %s%s", myname, group, admins, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to set the administrators of group %s to %s%s", -- myname, group, admins, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to set the administrators of group %s to %s%s", +- myname, group, admins, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -392,14 +383,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -459,13 +436,9 @@ static void log_gpasswd_failure (const c +@@ -457,11 +457,9 @@ static void log_gpasswd_failure (const c "%s failed to set the members of group %s to %s%s", myname, group, members, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to set the members of group %s to %s%s", -- myname, group, members, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to set the members of group %s to %s%s", +- myname, group, members, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -409,14 +398,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -474,13 +447,9 @@ static void log_gpasswd_failure (const c +@@ -470,11 +468,9 @@ static void log_gpasswd_failure (const c "%s failed to change password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "%s failed to change password of group %s%s", -- myname, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "%s failed to change password of group %s%s", +- myname, group, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -426,22 +413,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -511,21 +480,14 @@ static void log_gpasswd_failure_gshadow - - static void log_gpasswd_success (const char *suffix) - { --#ifdef WITH_AUDIT -- char buf[1024]; --#endif - if (aflg) { - SYSLOG ((LOG_INFO, +@@ -514,11 +502,9 @@ static void log_gpasswd_success (const c "user %s added by %s to group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "user %s added by %s to group %s%s", -- user, myname, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "user %s added by %s to group %s%s", +- user, myname, group, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -451,14 +428,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (dflg) { -@@ -533,13 +495,9 @@ static void log_gpasswd_success (const c +@@ -526,11 +512,9 @@ static void log_gpasswd_success (const c "user %s removed by %s from group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "user %s removed by %s from group %s%s", -- user, myname, group, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "user %s removed by %s from group %s%s", +- user, myname, group, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -468,14 +443,10 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (rflg) { -@@ -547,13 +505,9 @@ static void log_gpasswd_success (const c - "password of group %s removed by %s%s", - group, myname, suffix)); +@@ -540,9 +524,9 @@ static void log_gpasswd_success (const c #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "password of group %s removed by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; + SNPRINTF(buf, "password of group %s removed by %s%s", + group, myname, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -485,14 +456,10 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Rflg) { -@@ -561,13 +515,9 @@ static void log_gpasswd_success (const c - "access to group %s restricted by %s%s", - group, myname, suffix)); +@@ -552,9 +536,9 @@ static void log_gpasswd_success (const c #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "access to group %s restricted by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; + SNPRINTF(buf, "access to group %s restricted by %s%s", + group, myname, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -502,14 +469,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Aflg || Mflg) { -@@ -577,13 +527,9 @@ static void log_gpasswd_success (const c +@@ -564,11 +548,9 @@ static void log_gpasswd_success (const c "administrators of group %s set by %s to %s%s", group, myname, admins, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "administrators of group %s set by %s to %s%s", -- group, myname, admins, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "administrators of group %s set by %s to %s%s", +- group, myname, admins, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -519,14 +484,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -593,13 +539,9 @@ static void log_gpasswd_success (const c +@@ -578,11 +560,9 @@ static void log_gpasswd_success (const c "members of group %s set by %s to %s%s", group, myname, members, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "members of group %s set by %s to %s%s", -- group, myname, members, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "members of group %s set by %s to %s%s", +- group, myname, members, suffix); - audit_logger (AUDIT_USER_ACCT, Prog, - buf, - group, AUDIT_NO_ID, @@ -536,14 +499,12 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -608,13 +550,9 @@ static void log_gpasswd_success (const c +@@ -591,11 +571,9 @@ static void log_gpasswd_success (const c "password of group %s changed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT -- snprintf (buf, 1023, -- "password of group %s changed by %s%s", -- group, myname, suffix); -- buf[1023] = '\0'; +- SNPRINTF(buf, "password of group %s changed by %s%s", +- group, myname, suffix); - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - buf, - group, AUDIT_NO_ID, @@ -553,10 +514,10 @@ diff -up shadow-4.14.0/src/gpasswd.c.audit-update shadow-4.14.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c ---- shadow-4.14.0/src/groupadd.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.14.0/src/groupadd.c 2023-08-04 09:34:34.125581046 +0200 -@@ -114,6 +114,15 @@ usage (int status) +diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c +--- shadow-4.15.0/src/groupadd.c.audit-update 2024-01-22 22:36:43.000000000 +0100 ++++ shadow-4.15.0/src/groupadd.c 2024-02-09 10:58:18.325715738 +0100 +@@ -115,6 +115,15 @@ usage (int status) exit (status); } @@ -572,7 +533,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c /* * new_grent - initialize the values in a group file entry * -@@ -210,7 +219,7 @@ static void grp_update (void) +@@ -211,7 +220,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), grp.gr_name); @@ -581,7 +542,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } #ifdef SHADOWGRP /* -@@ -220,7 +229,7 @@ static void grp_update (void) +@@ -221,7 +230,7 @@ static void grp_update (void) fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), sgrp.sg_name); @@ -590,7 +551,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } #endif /* SHADOWGRP */ } -@@ -244,7 +253,7 @@ static void check_new_name (void) +@@ -245,7 +254,7 @@ static void check_new_name (void) fprintf (stderr, _("%s: '%s' is not a valid group name\n"), Prog, group_name); @@ -599,7 +560,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } /* -@@ -260,11 +269,11 @@ static void close_files (void) +@@ -261,11 +270,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); @@ -613,7 +574,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u", -@@ -281,11 +290,11 @@ static void close_files (void) +@@ -282,11 +291,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); @@ -628,7 +589,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c group_name, group_id, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "group added to %s: name=%s", -@@ -298,10 +307,6 @@ static void close_files (void) +@@ -299,10 +308,6 @@ static void close_files (void) #endif /* SHADOWGRP */ /* Report success at the system level */ @@ -639,7 +600,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", group_name, (unsigned int) group_id)); del_cleanup (cleanup_report_add_group); -@@ -319,7 +324,7 @@ static void open_files (void) +@@ -320,7 +325,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -648,7 +609,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } add_cleanup (cleanup_unlock_group, NULL); -@@ -329,7 +334,7 @@ static void open_files (void) +@@ -330,7 +335,7 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -657,25 +618,25 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } add_cleanup (cleanup_unlock_gshadow, NULL); } -@@ -345,7 +350,7 @@ static void open_files (void) +@@ -346,7 +351,7 @@ static void open_files (void) if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); + fprintf (stderr, _("%s: cannot open %s: %s\n"), Prog, gr_dbname (), strerror(errno)); + SYSLOG ((LOG_WARN, "cannot open %s: %s", gr_dbname (), strerror(errno))); - exit (E_GRP_UPDATE); + fail_exit (E_GRP_UPDATE); } #ifdef SHADOWGRP -@@ -355,7 +360,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); +@@ -356,7 +361,7 @@ static void open_files (void) + _("%s: cannot open %s: %s\n"), + Prog, sgr_dbname (), strerror(errno)); + SYSLOG ((LOG_WARN, "cannot open %s: %s", sgr_dbname (), strerror(errno))); - exit (E_GRP_UPDATE); + fail_exit (E_GRP_UPDATE); } } #endif /* SHADOWGRP */ -@@ -492,7 +497,7 @@ static void check_flags (void) +@@ -493,7 +498,7 @@ static void check_flags (void) fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_name); @@ -684,16 +645,16 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } if (gflg && (prefix_getgrgid (group_id) != NULL)) { -@@ -511,7 +516,7 @@ static void check_flags (void) +@@ -512,7 +517,7 @@ static void check_flags (void) fprintf (stderr, _("%s: GID '%lu' already exists\n"), - Prog, (unsigned long int) group_id); + Prog, (unsigned long) group_id); - exit (E_GID_IN_USE); + fail_exit (E_GID_IN_USE); } } } -@@ -539,7 +544,7 @@ static void check_perms (void) +@@ -540,7 +545,7 @@ static void check_perms (void) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -702,7 +663,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); -@@ -559,7 +564,7 @@ static void check_perms (void) +@@ -560,7 +565,7 @@ static void check_perms (void) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -711,7 +672,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -594,7 +599,7 @@ int main (int argc, char **argv) +@@ -595,7 +600,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -720,7 +681,7 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } /* -@@ -621,7 +626,7 @@ int main (int argc, char **argv) +@@ -622,7 +627,7 @@ int main (int argc, char **argv) if (!gflg) { if (find_new_gid (rflg, &group_id, NULL) < 0) { @@ -729,9 +690,9 @@ diff -up shadow-4.14.0/src/groupadd.c.audit-update shadow-4.14.0/src/groupadd.c } } -diff -up shadow-4.14.0/src/groupdel.c.audit-update shadow-4.14.0/src/groupdel.c ---- shadow-4.14.0/src/groupdel.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.14.0/src/groupdel.c 2023-08-04 09:36:42.778900250 +0200 +diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c +--- shadow-4.15.0/src/groupdel.c.audit-update 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.15.0/src/groupdel.c 2024-02-09 10:49:57.107840592 +0100 @@ -87,6 +87,15 @@ usage (int status) exit (status); } @@ -899,10 +860,10 @@ diff -up shadow-4.14.0/src/groupdel.c.audit-update shadow-4.14.0/src/groupdel.c } #endif -diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c ---- shadow-4.14.0/src/groupmod.c.audit-update 2023-06-10 02:02:29.000000000 +0200 -+++ shadow-4.14.0/src/groupmod.c 2023-08-04 09:30:25.208963541 +0200 -@@ -473,7 +473,7 @@ static void close_files (void) +diff -up shadow-4.15.0/src/groupmod.c.audit-update shadow-4.15.0/src/groupmod.c +--- shadow-4.15.0/src/groupmod.c.audit-update 2024-01-22 22:36:43.000000000 +0100 ++++ shadow-4.15.0/src/groupmod.c 2024-02-09 10:49:57.107840592 +0100 +@@ -474,7 +474,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -911,7 +872,7 @@ diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c info_group.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -496,7 +496,14 @@ static void close_files (void) +@@ -497,7 +497,14 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -927,7 +888,7 @@ diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c info_gshadow.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -519,7 +526,7 @@ static void close_files (void) +@@ -520,7 +527,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -936,7 +897,7 @@ diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c info_passwd.audit_msg, group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); -@@ -534,8 +541,8 @@ static void close_files (void) +@@ -535,8 +542,8 @@ static void close_files (void) } #ifdef WITH_AUDIT @@ -947,43 +908,42 @@ diff -up shadow-4.14.0/src/groupmod.c.audit-update shadow-4.14.0/src/groupmod.c group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c ---- shadow-4.14.0/src/newgrp.c.audit-update 2023-08-04 09:30:25.208963541 +0200 -+++ shadow-4.14.0/src/newgrp.c 2023-08-04 09:51:28.354208322 +0200 -@@ -186,10 +186,10 @@ static void check_perms (const struct gr +diff -up shadow-4.15.0/src/newgrp.c.audit-update shadow-4.15.0/src/newgrp.c +--- shadow-4.15.0/src/newgrp.c.audit-update 2023-12-27 16:58:48.000000000 +0100 ++++ shadow-4.15.0/src/newgrp.c 2024-02-09 11:02:30.575155871 +0100 +@@ -188,10 +188,10 @@ static void check_perms (const struct gr + if (grp->gr_passwd[0] == '\0' || strcmp (cpasswd, grp->gr_passwd) != 0) { #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "authentication new-gid=%lu", -+ "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); +- SNPRINTF(audit_buf, "authentication new-gid=%lu", ++ SNPRINTF(audit_buf, "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, getuid (), 0); + audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif SYSLOG ((LOG_INFO, "Invalid password for group '%s' from '%s'", -@@ -200,10 +200,10 @@ static void check_perms (const struct gr +@@ -201,10 +201,10 @@ static void check_perms (const struct gr + goto failure; } #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "authentication new-gid=%lu", -+ "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); +- SNPRINTF(audit_buf, "authentication new-gid=%lu", ++ SNPRINTF(audit_buf, "authentication new_gid=%lu", + (unsigned long) grp->gr_gid); audit_logger (AUDIT_GRP_AUTH, Prog, - audit_buf, NULL, getuid (), 1); + audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); #endif } -@@ -214,17 +214,6 @@ failure: +@@ -215,16 +215,6 @@ failure: * harm. -- JWP */ closelog (); -#ifdef WITH_AUDIT - if (groupname) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", groupname); +- SNPRINTF(audit_buf, "changing new-group=%s", groupname); - audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, getuid (), 0); - } else { @@ -994,12 +954,12 @@ diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c exit (EXIT_FAILURE); } -@@ -298,13 +287,23 @@ static void syslog_sg (const char *name, +@@ -298,13 +288,23 @@ static void syslog_sg (const char *name, is_newgrp ? "newgrp" : "sg", strerror (errno)); #ifdef WITH_AUDIT if (group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); +- SNPRINTF(audit_buf, +- "changing new-group=%s", group); + char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; + int len = strnlen(group, sizeof(enc_group)/2); + if (audit_value_needs_encoding(group, len)) { @@ -1022,7 +982,7 @@ diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c } #endif exit (EXIT_FAILURE); -@@ -440,7 +439,7 @@ int main (int argc, char **argv) +@@ -440,7 +440,7 @@ int main (int argc, char **argv) Prog); #ifdef WITH_AUDIT audit_logger (AUDIT_CHGRP_ID, Prog, @@ -1031,12 +991,11 @@ diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c #endif SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); -@@ -556,13 +555,22 @@ int main (int argc, char **argv) +@@ -556,12 +556,22 @@ int main (int argc, char **argv) perror ("getgroups"); #ifdef WITH_AUDIT if (group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); +- SNPRINTF(audit_buf, "changing new-group=%s", group); + char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; + int len = strnlen(group, sizeof(enc_group)/2); + if (audit_value_needs_encoding(group, len)) { @@ -1058,61 +1017,59 @@ diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c } #endif exit (EXIT_FAILURE); -@@ -717,9 +725,9 @@ int main (int argc, char **argv) +@@ -715,9 +725,9 @@ int main (int argc, char **argv) + if (setgid (gid) != 0) { perror ("setgid"); #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); +- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); ++ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, getuid (), 0); + audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif exit (EXIT_FAILURE); } -@@ -728,9 +736,9 @@ int main (int argc, char **argv) +@@ -725,9 +735,9 @@ int main (int argc, char **argv) + if (setuid (getuid ()) != 0) { perror ("setuid"); #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); +- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); ++ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, getuid (), 0); + audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif exit (EXIT_FAILURE); } -@@ -744,9 +752,9 @@ int main (int argc, char **argv) +@@ -740,9 +750,9 @@ int main (int argc, char **argv) + closelog (); execl (SHELL, "sh", "-c", command, (char *) NULL); #ifdef WITH_AUDIT - snprintf (audit_buf, sizeof(audit_buf), -- "changing new-gid=%lu", (unsigned long) gid); -+ "changing new_gid=%lu", (unsigned long) gid); +- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); ++ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, getuid (), 0); + audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); #endif perror (SHELL); exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -810,10 +818,10 @@ int main (int argc, char **argv) +@@ -806,9 +816,9 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT -- snprintf (audit_buf, sizeof(audit_buf), "changing new-gid=%lu", -+ snprintf (audit_buf, sizeof(audit_buf), "changing new_gid=%lu", - (unsigned long) gid); +- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); ++ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); audit_logger (AUDIT_CHGRP_ID, Prog, - audit_buf, NULL, getuid (), 1); + audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); #endif /* * Exec the login shell and go away. We are trying to get back to -@@ -837,13 +845,22 @@ int main (int argc, char **argv) +@@ -832,12 +842,22 @@ int main (int argc, char **argv) closelog (); #ifdef WITH_AUDIT if (NULL != group) { -- snprintf (audit_buf, sizeof(audit_buf), -- "changing new-group=%s", group); +- SNPRINTF(audit_buf, "changing new-group=%s", group); + char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; + int len = strnlen(group, sizeof(enc_group)/2); + if (audit_value_needs_encoding(group, len)) { @@ -1134,10 +1091,10 @@ diff -up shadow-4.14.0/src/newgrp.c.audit-update shadow-4.14.0/src/newgrp.c } #endif exit (EXIT_FAILURE); -diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c ---- shadow-4.14.0/src/useradd.c.audit-update 2023-07-30 12:38:39.000000000 +0200 -+++ shadow-4.14.0/src/useradd.c 2023-08-04 10:02:18.851935396 +0200 -@@ -240,6 +240,8 @@ static void check_uid_range(int rflg, ui +diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c +--- shadow-4.15.0/src/useradd.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/src/useradd.c 2024-02-09 10:49:57.108840594 +0100 +@@ -242,6 +242,8 @@ static void check_uid_range(int rflg, ui */ static void fail_exit (int code) { @@ -1146,7 +1103,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c if (home_added && rmdir(prefix_user_home) != 0) { fprintf(stderr, _("%s: %s was created, but could not be removed\n"), -@@ -250,38 +252,22 @@ static void fail_exit (int code) +@@ -252,38 +254,22 @@ static void fail_exit (int code) if (spw_locked && spw_unlock() == 0) { fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); @@ -1185,7 +1142,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c /* continue */ } #endif -@@ -289,27 +275,23 @@ static void fail_exit (int code) +@@ -291,27 +277,23 @@ static void fail_exit (int code) if (sub_uid_locked && sub_uid_unlock() == 0) { fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); @@ -1220,7 +1177,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); -@@ -759,7 +741,7 @@ static int set_defaults (void) +@@ -732,7 +714,7 @@ static int set_defaults (void) } #ifdef WITH_AUDIT audit_logger (AUDIT_USYS_CONFIG, Prog, @@ -1229,7 +1186,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c NULL, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -1096,12 +1078,6 @@ static void grp_update (void) +@@ -1060,12 +1042,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1242,7 +1199,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1115,18 +1091,12 @@ static void grp_update (void) +@@ -1079,18 +1055,12 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1264,7 +1221,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1171,12 +1141,6 @@ static void grp_update (void) +@@ -1135,12 +1105,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1277,7 +1234,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1190,18 +1154,13 @@ static void grp_update (void) +@@ -1154,18 +1118,13 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1300,7 +1257,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1596,7 +1555,7 @@ static void process_flags (int argc, cha +@@ -1560,7 +1519,7 @@ static void process_flags (int argc, cha Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1309,7 +1266,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1705,7 +1664,7 @@ static void close_files (void) +@@ -1660,7 +1619,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1318,7 +1275,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1718,7 +1677,7 @@ static void close_files (void) +@@ -1673,7 +1632,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1327,7 +1284,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1735,7 +1694,7 @@ static void close_files (void) +@@ -1690,7 +1649,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1336,7 +1293,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1749,7 +1708,7 @@ static void close_files (void) +@@ -1704,7 +1663,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1345,7 +1302,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -2012,7 +1971,7 @@ static void grp_add (void) +@@ -1967,7 +1926,7 @@ static void grp_add (void) Prog, gr_dbname (), grp.gr_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1354,7 +1311,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -2028,7 +1987,7 @@ static void grp_add (void) +@@ -1983,7 +1942,7 @@ static void grp_add (void) Prog, sgr_dbname (), sgrp.sg_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1363,7 +1320,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -2038,7 +1997,7 @@ static void grp_add (void) +@@ -1993,7 +1952,7 @@ static void grp_add (void) SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1372,7 +1329,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2240,11 +2199,6 @@ static void usr_update (unsigned long su +@@ -2195,11 +2154,6 @@ static void usr_update (unsigned long su fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spent.sp_namp); @@ -1384,7 +1341,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_PW_UPDATE); } #ifdef ENABLE_SUBIDS -@@ -2271,7 +2225,7 @@ static void usr_update (unsigned long su +@@ -2226,7 +2180,7 @@ static void usr_update (unsigned long su * and we can use the real ID thereafter. */ audit_logger (AUDIT_ADD_USER, Prog, @@ -1393,7 +1350,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2365,10 +2319,6 @@ static void create_home (void) +@@ -2321,10 +2275,6 @@ static void create_home (void) if (mkdir(path, 0) != 0) { fprintf(stderr, _("%s: cannot create directory %s\n"), Prog, path); @@ -1404,7 +1361,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit(E_HOMEDIR); } if (chown(path, 0, 0) < 0) { -@@ -2393,7 +2343,7 @@ static void create_home (void) +@@ -2349,7 +2299,7 @@ static void create_home (void) } home_added = true; #ifdef WITH_AUDIT @@ -1413,7 +1370,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif #ifdef WITH_SELINUX -@@ -2637,12 +2587,6 @@ int main (int argc, char **argv) +@@ -2594,12 +2544,6 @@ int main (int argc, char **argv) */ if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); @@ -1426,7 +1383,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_NAME_IN_USE); } -@@ -2658,12 +2602,6 @@ int main (int argc, char **argv) +@@ -2615,12 +2559,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), Prog, user_name); @@ -1439,7 +1396,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_NAME_IN_USE); } } -@@ -2693,12 +2631,6 @@ int main (int argc, char **argv) +@@ -2650,12 +2588,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: UID %lu is not unique\n"), Prog, (unsigned long) user_id); @@ -1452,7 +1409,7 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c fail_exit (E_UID_IN_USE); } } -@@ -2773,9 +2705,9 @@ int main (int argc, char **argv) +@@ -2730,9 +2662,9 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -1465,10 +1422,10 @@ diff -up shadow-4.14.0/src/useradd.c.audit-update shadow-4.14.0/src/useradd.c #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); } -diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c ---- shadow-4.14.0/src/userdel.c.audit-update 2023-06-10 02:02:29.000000000 +0200 -+++ shadow-4.14.0/src/userdel.c 2023-08-04 10:26:18.225695416 +0200 -@@ -204,9 +204,9 @@ static void update_groups (void) +diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c +--- shadow-4.15.0/src/userdel.c.audit-update 2023-12-27 16:58:48.000000000 +0100 ++++ shadow-4.15.0/src/userdel.c 2024-02-09 10:49:57.108840594 +0100 +@@ -206,9 +206,9 @@ static void update_groups (void) * Update the DBM group file with the new entry as well. */ #ifdef WITH_AUDIT @@ -1481,7 +1438,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", user_name, ngrp->gr_name)); -@@ -265,9 +265,9 @@ static void update_groups (void) +@@ -267,9 +267,9 @@ static void update_groups (void) exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -1494,7 +1451,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", user_name, nsgrp->sg_name)); -@@ -343,9 +343,9 @@ static void remove_usergroup (void) +@@ -345,9 +345,9 @@ static void remove_usergroup (void) } #ifdef WITH_AUDIT @@ -1507,7 +1464,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, -@@ -361,9 +361,9 @@ static void remove_usergroup (void) +@@ -363,9 +363,9 @@ static void remove_usergroup (void) fail_exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT @@ -1520,7 +1477,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, -@@ -525,7 +525,7 @@ static void fail_exit (int code) +@@ -527,7 +527,7 @@ static void fail_exit (int code) #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1529,7 +1486,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -544,22 +544,12 @@ static void open_files (void) +@@ -546,22 +546,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); @@ -1552,7 +1509,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_PW_UPDATE); } if (is_shadow_pwd) { -@@ -567,11 +557,6 @@ static void open_files (void) +@@ -569,11 +559,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); @@ -1564,7 +1521,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_PW_UPDATE); } spw_locked = true; -@@ -579,11 +564,6 @@ static void open_files (void) +@@ -581,11 +566,6 @@ static void open_files (void) fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); @@ -1576,7 +1533,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_PW_UPDATE); } } -@@ -591,21 +571,11 @@ static void open_files (void) +@@ -593,21 +573,11 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); @@ -1598,7 +1555,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_GRP_UPDATE); } #ifdef SHADOWGRP -@@ -614,22 +584,12 @@ static void open_files (void) +@@ -616,22 +586,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); @@ -1621,7 +1578,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_GRP_UPDATE); } } -@@ -640,22 +600,12 @@ static void open_files (void) +@@ -642,22 +602,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_uid_dbname ()); @@ -1644,7 +1601,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_SUB_UID_UPDATE); } } -@@ -664,22 +614,12 @@ static void open_files (void) +@@ -666,22 +616,12 @@ static void open_files (void) fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_gid_dbname ()); @@ -1667,7 +1624,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c fail_exit (E_SUB_GID_UPDATE); } } -@@ -724,7 +664,7 @@ static void update_user (void) +@@ -726,7 +666,7 @@ static void update_user (void) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1676,7 +1633,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); -@@ -831,7 +771,7 @@ static int remove_mailbox (void) +@@ -824,7 +764,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1685,7 +1642,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ free(mailfile); -@@ -847,7 +787,7 @@ static int remove_mailbox (void) +@@ -840,7 +780,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1694,7 +1651,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ errors = 1; -@@ -856,8 +796,8 @@ static int remove_mailbox (void) +@@ -849,8 +789,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1705,7 +1662,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); } #endif /* WITH_AUDIT */ -@@ -874,7 +814,7 @@ static int remove_mailbox (void) +@@ -867,7 +807,7 @@ static int remove_mailbox (void) mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1714,7 +1671,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ free(mailfile); -@@ -890,7 +830,7 @@ static int remove_mailbox (void) +@@ -883,7 +823,7 @@ static int remove_mailbox (void) SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1723,7 +1680,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ errors = 1; -@@ -899,8 +839,8 @@ static int remove_mailbox (void) +@@ -892,8 +832,8 @@ static int remove_mailbox (void) #ifdef WITH_AUDIT else { @@ -1734,7 +1691,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); } #endif /* WITH_AUDIT */ -@@ -1118,7 +1058,7 @@ int main (int argc, char **argv) +@@ -1108,7 +1048,7 @@ int main (int argc, char **argv) Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1743,7 +1700,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1174,7 +1114,7 @@ int main (int argc, char **argv) +@@ -1158,7 +1098,7 @@ int main (int argc, char **argv) if (!fflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1752,7 +1709,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1268,8 +1208,8 @@ int main (int argc, char **argv) +@@ -1252,8 +1192,8 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT else { @@ -1763,7 +1720,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); } #endif /* WITH_AUDIT */ -@@ -1277,7 +1217,7 @@ int main (int argc, char **argv) +@@ -1261,7 +1201,7 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT if (0 != errors) { audit_logger (AUDIT_DEL_USER, Prog, @@ -1772,7 +1729,7 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); } -@@ -1290,8 +1230,8 @@ int main (int argc, char **argv) +@@ -1274,8 +1214,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -1783,10 +1740,10 @@ diff -up shadow-4.14.0/src/userdel.c.audit-update shadow-4.14.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); -diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c ---- shadow-4.14.0/src/usermod.c.audit-update 2023-07-30 12:38:39.000000000 +0200 -+++ shadow-4.14.0/src/usermod.c 2023-08-04 10:33:04.601749324 +0200 -@@ -427,7 +427,7 @@ static char *new_pw_passwd (char *pw_pas +diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c +--- shadow-4.15.0/src/usermod.c.audit-update 2024-02-01 23:59:36.000000000 +0100 ++++ shadow-4.15.0/src/usermod.c 2024-02-09 10:49:57.108840594 +0100 +@@ -431,7 +431,7 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1795,7 +1752,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); strcpy (buf, "!"); -@@ -444,14 +444,14 @@ static char *new_pw_passwd (char *pw_pas +@@ -448,14 +448,14 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1812,7 +1769,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); pw_pass = xstrdup (user_pass); -@@ -479,8 +479,8 @@ static void new_pwent (struct passwd *pw +@@ -483,8 +483,8 @@ static void new_pwent (struct passwd *pw fail_exit (E_NAME_IN_USE); } #ifdef WITH_AUDIT @@ -1823,7 +1780,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user name '%s' to '%s'", -@@ -499,8 +499,8 @@ static void new_pwent (struct passwd *pw +@@ -503,8 +503,8 @@ static void new_pwent (struct passwd *pw if (uflg) { #ifdef WITH_AUDIT @@ -1834,7 +1791,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' UID from '%d' to '%d'", -@@ -509,8 +509,8 @@ static void new_pwent (struct passwd *pw +@@ -513,8 +513,8 @@ static void new_pwent (struct passwd *pw } if (gflg) { #ifdef WITH_AUDIT @@ -1845,7 +1802,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -520,16 +520,16 @@ static void new_pwent (struct passwd *pw +@@ -524,16 +524,16 @@ static void new_pwent (struct passwd *pw } if (cflg) { #ifdef WITH_AUDIT @@ -1866,7 +1823,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -545,8 +545,8 @@ static void new_pwent (struct passwd *pw +@@ -549,8 +549,8 @@ static void new_pwent (struct passwd *pw } if (sflg) { #ifdef WITH_AUDIT @@ -1877,7 +1834,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -576,8 +576,8 @@ static void new_spent (struct spwd *spen +@@ -580,8 +580,8 @@ static void new_spent (struct spwd *spen if (fflg) { #ifdef WITH_AUDIT @@ -1888,7 +1845,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -591,8 +591,8 @@ static void new_spent (struct spwd *spen +@@ -595,8 +595,8 @@ static void new_spent (struct spwd *spen date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT @@ -1899,7 +1856,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -677,9 +677,9 @@ fail_exit (int code) +@@ -681,9 +681,9 @@ fail_exit (int code) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -1912,7 +1869,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif exit (code); } -@@ -741,9 +741,12 @@ static void update_group (void) +@@ -745,9 +745,12 @@ static void update_group (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -1928,7 +1885,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in group '%s'", -@@ -757,9 +760,11 @@ static void update_group (void) +@@ -761,9 +764,11 @@ static void update_group (void) ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -1943,7 +1900,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from group '%s'", -@@ -772,9 +777,11 @@ static void update_group (void) +@@ -776,9 +781,11 @@ static void update_group (void) ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -1958,7 +1915,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to group '%s'", user_newname, ngrp->gr_name)); -@@ -859,9 +866,10 @@ static void update_gshadow (void) +@@ -863,9 +870,10 @@ static void update_gshadow (void) nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); changed = true; #ifdef WITH_AUDIT @@ -1972,7 +1929,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change admin '%s' to '%s' in shadow group '%s'", -@@ -881,9 +889,10 @@ static void update_gshadow (void) +@@ -885,9 +893,10 @@ static void update_gshadow (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -1986,7 +1943,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in shadow group '%s'", -@@ -897,9 +906,10 @@ static void update_gshadow (void) +@@ -901,9 +910,10 @@ static void update_gshadow (void) nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -2000,7 +1957,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'", -@@ -912,9 +922,10 @@ static void update_gshadow (void) +@@ -916,9 +926,10 @@ static void update_gshadow (void) nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -2014,7 +1971,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", user_newname, nsgrp->sg_name)); -@@ -1830,8 +1841,8 @@ static void move_home (void) +@@ -1829,8 +1840,8 @@ static void move_home (void) #ifdef WITH_AUDIT if (uflg || gflg) { @@ -2025,7 +1982,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -1849,8 +1860,8 @@ static void move_home (void) +@@ -1848,8 +1859,8 @@ static void move_home (void) fail_exit (E_HOMEDIR); } #ifdef WITH_AUDIT @@ -2036,7 +1993,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); #endif return; -@@ -1877,9 +1888,9 @@ static void move_home (void) +@@ -1876,9 +1887,9 @@ static void move_home (void) Prog, prefix_user_home); } #ifdef WITH_AUDIT @@ -2048,7 +2005,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); -@@ -2100,8 +2111,8 @@ static void move_mailbox (void) +@@ -2102,8 +2113,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2059,7 +2016,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -2129,8 +2140,8 @@ static void move_mailbox (void) +@@ -2126,8 +2137,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2070,7 +2027,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_newname, user_newid, 1); } -@@ -2331,8 +2342,8 @@ int main (int argc, char **argv) +@@ -2328,8 +2339,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -2081,7 +2038,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2344,8 +2355,8 @@ int main (int argc, char **argv) +@@ -2341,8 +2352,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2092,7 +2049,7 @@ diff -up shadow-4.14.0/src/usermod.c.audit-update shadow-4.14.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2388,8 +2399,8 @@ int main (int argc, char **argv) +@@ -2385,8 +2396,8 @@ int main (int argc, char **argv) */ #ifdef WITH_AUDIT if (uflg || gflg) { diff --git a/shadow-4.2.1-date-parsing.patch b/shadow-4.15.0-date-parsing.patch similarity index 93% rename from shadow-4.2.1-date-parsing.patch rename to shadow-4.15.0-date-parsing.patch index 2a798d0..272d2df 100644 --- a/shadow-4.2.1-date-parsing.patch +++ b/shadow-4.15.0-date-parsing.patch @@ -1,7 +1,7 @@ -Index: shadow-4.5/libmisc/getdate.y +Index: shadow-4.5/lib/getdate.y =================================================================== ---- shadow-4.5.orig/libmisc/getdate.y -+++ shadow-4.5/libmisc/getdate.y +--- shadow-4.5.orig/lib/getdate.y ++++ shadow-4.5/lib/getdate.y @@ -152,6 +152,7 @@ static int yyHaveDay; static int yyHaveRel; static int yyHaveTime; diff --git a/shadow-4.14.0-manfix.patch b/shadow-4.15.0-manfix.patch similarity index 76% rename from shadow-4.14.0-manfix.patch rename to shadow-4.15.0-manfix.patch index 70f030e..34e62f9 100644 --- a/shadow-4.14.0-manfix.patch +++ b/shadow-4.15.0-manfix.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.8.1/man/groupmems.8.xml.manfix shadow-4.8.1/man/groupmems.8.xml ---- shadow-4.8.1/man/groupmems.8.xml.manfix 2020-03-17 15:34:48.750414984 +0100 -+++ shadow-4.8.1/man/groupmems.8.xml 2020-03-17 15:41:13.383588722 +0100 -@@ -179,20 +179,10 @@ +diff -up shadow-4.15.0/man/groupmems.8.xml.manfix shadow-4.15.0/man/groupmems.8.xml +--- shadow-4.15.0/man/groupmems.8.xml.manfix 2023-05-26 04:56:11.000000000 +0200 ++++ shadow-4.15.0/man/groupmems.8.xml 2024-02-09 10:42:20.337036378 +0100 +@@ -156,20 +156,10 @@ SETUP @@ -25,10 +25,10 @@ diff -up shadow-4.8.1/man/groupmems.8.xml.manfix shadow-4.8.1/man/groupmems.8.xm -diff -up shadow-4.8.1/man/ja/man5/login.defs.5.manfix shadow-4.8.1/man/ja/man5/login.defs.5 ---- shadow-4.8.1/man/ja/man5/login.defs.5.manfix 2019-07-23 17:26:08.000000000 +0200 -+++ shadow-4.8.1/man/ja/man5/login.defs.5 2020-03-17 15:34:48.750414984 +0100 -@@ -147,10 +147,6 @@ 以下の参照表は、 +diff -up shadow-4.15.0/man/ja/man5/login.defs.5.manfix shadow-4.15.0/man/ja/man5/login.defs.5 +--- shadow-4.15.0/man/ja/man5/login.defs.5.manfix 2023-03-13 21:58:56.000000000 +0100 ++++ shadow-4.15.0/man/ja/man5/login.defs.5 2024-02-09 10:42:20.337036378 +0100 +@@ -123,10 +123,6 @@ 以下の参照表は、 shadow パスワード機能のどのプログラムが どのパラメータを使用するかを示したものである。 .na @@ -39,10 +39,10 @@ diff -up shadow-4.8.1/man/ja/man5/login.defs.5.manfix shadow-4.8.1/man/ja/man5/l .IP groupadd 12 GID_MAX GID_MIN .IP newusers 12 -diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5.xml ---- shadow-4.8.1/man/login.defs.5.xml.manfix 2020-01-17 16:47:56.000000000 +0100 -+++ shadow-4.8.1/man/login.defs.5.xml 2020-03-17 15:34:48.750414984 +0100 -@@ -164,6 +164,17 @@ +diff -up shadow-4.15.0/man/login.defs.5.xml.manfix shadow-4.15.0/man/login.defs.5.xml +--- shadow-4.15.0/man/login.defs.5.xml.manfix 2024-01-22 22:36:43.000000000 +0100 ++++ shadow-4.15.0/man/login.defs.5.xml 2024-02-09 10:45:49.014407259 +0100 +@@ -144,6 +144,17 @@ long numeric parameters is machine-dependent. @@ -60,7 +60,7 @@ diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5. The following configuration items are provided: -@@ -256,16 +267,6 @@ +@@ -240,16 +251,6 @@ @@ -77,7 +77,7 @@ diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5. chgpasswd -@@ -286,14 +287,6 @@ +@@ -276,14 +277,6 @@ @@ -92,7 +92,7 @@ diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5. -@@ -359,34 +352,6 @@ +@@ -352,34 +345,6 @@ LASTLOG_UID_MAX @@ -127,25 +127,7 @@ diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5. newgrp / sg -@@ -415,17 +380,6 @@ - - - -- -- passwd -- -- -- ENCRYPT_METHOD MD5_CRYPT_ENAB OBSCURE_CHECKS_ENAB -- PASS_ALWAYS_WARN PASS_CHANGE_TRIES PASS_MAX_LEN PASS_MIN_LEN -- SHA_CRYPT_MAX_ROUNDS -- SHA_CRYPT_MIN_ROUNDS -- -- -- - - pwck - -@@ -452,32 +406,6 @@ +@@ -451,32 +416,6 @@ @@ -166,12 +148,12 @@ diff -up shadow-4.8.1/man/login.defs.5.xml.manfix shadow-4.8.1/man/login.defs.5. - - - -- +- - sulogin - - - ENV_HZ -- ENV_TZ +- ENV_TZ - - - diff --git a/shadow-utils.spec b/shadow-utils.spec index 6b705cd..2892562 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.14.0 -Release: 6%{?dist} +Version: 4.15.0rc2 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -19,20 +19,13 @@ Source7: passwd.pamd ### Patches ### # Misc manual page changes - non-upstreamable -Patch0: shadow-4.14.0-manfix.patch +Patch0: shadow-4.15.0-manfix.patch # Date parsing improvement - could be upstreamed -Patch1: shadow-4.2.1-date-parsing.patch +Patch1: shadow-4.15.0-date-parsing.patch # Audit message changes - partially upstreamed -Patch2: shadow-4.14.0-audit-update.patch -# https://github.com/shadow-maint/shadow/pull/812 -Patch3: shadow-4.14.0-useradd-def-usrtemplate-selinux-label.patch +Patch2: shadow-4.15.0-audit-update.patch # Probably non-upstreamable -Patch4: shadow-4.14.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/43b4e5a6c41f5c43cad18810f9229e40e8c4a57e -# https://github.com/shadow-maint/shadow/commit/45f34ee8c196a98397504cb7ed8576b6f1825cf9 -Patch5: shadow-4.14.0-remove-libcrack.patch -# https://github.com/shadow-maint/shadow/pull/927 -Patch6: shadow-4.14.0-passwd-stdin.patch +Patch3: shadow-4.14.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -107,7 +100,7 @@ cp -a %{SOURCE4} %{SOURCE5} . cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml # Force regeneration of getdate.c -rm libmisc/getdate.c +rm lib/getdate.c %build %ifarch sparc64 @@ -193,9 +186,11 @@ rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* # Remove PAM service files we don't use. rm $RPM_BUILD_ROOT%{_pam_confdir}/chfn +rm $RPM_BUILD_ROOT%{_pam_confdir}/chpasswd rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh rm $RPM_BUILD_ROOT%{_pam_confdir}/groupmems rm $RPM_BUILD_ROOT%{_pam_confdir}/login +rm $RPM_BUILD_ROOT%{_pam_confdir}/newusers rm $RPM_BUILD_ROOT%{_pam_confdir}/su find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete @@ -278,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Feb 16 2024 Iker Pedrosa - 2:4.15.0rc2-1 +- Rebase to version 4.15.0rc2 + * Mon Feb 12 2024 Iker Pedrosa - 2:4.14.0-6 - Build linking `libpam` diff --git a/sources b/sources index 1ec1caa..a023638 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.14.0.tar.xz) = ff960481d576f9db5a9f10becc4e1a74c03de484ecfdcd7f1ea735fded683d7ba0f9cd895dc6a431b77e5a633752273178b1bcda4cefaa5adbf0f143c9a0c86f -SHA512 (shadow-4.14.0.tar.xz.asc) = d011a732d73b4b066ca8d204c0420303f925c87efc7655feb5c5f60b619d67da450e220ee44f6c86929ae79cbd4343136fe9c20d25b39fa0a228a48e57636309 +SHA512 (shadow-4.15.0rc2.tar.xz) = d54808226fb40998801d64c5835cdbd07d4fa78536611c5d4cdfc0ade04798c10cf279af6667e0f50cf1995a122a36fa525c5372fa9fbdbe72aef656ecc88dc8 +SHA512 (shadow-4.15.0rc2.tar.xz.asc) = b258c261cf6a7f16b078635a0c900144fc1868fd0686336255823e22b589e9b19459a5e43bb52cff7104b794e62c81de84d52d24d380c8e262d56b7e8cb5eb8b From 54fe2d4ca44c281bb7424a2aa7e69f79dda88f9b Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 1 Mar 2024 09:33:00 +0100 Subject: [PATCH 065/118] Rebase to version 4.15.0rc3 Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ shadow-utils.spec | 5 ++++- sources | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 8b8ecf6..26ea3ae 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.14.0.tar.xz.asc /shadow-4.15.0rc2.tar.xz /shadow-4.15.0rc2.tar.xz.asc +/shadow-4.15.0rc3.tar.xz +/shadow-4.15.0rc3.tar.xz.asc diff --git a/shadow-utils.spec b/shadow-utils.spec index 2892562..b864952 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,6 +1,6 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.15.0rc2 +Version: 4.15.0rc3 Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later @@ -273,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Mar 1 2024 Iker Pedrosa - 2:4.15.0rc3-1 +- Rebase to version 4.15.0rc3 + * Fri Feb 16 2024 Iker Pedrosa - 2:4.15.0rc2-1 - Rebase to version 4.15.0rc2 diff --git a/sources b/sources index a023638..a6a9165 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.15.0rc2.tar.xz) = d54808226fb40998801d64c5835cdbd07d4fa78536611c5d4cdfc0ade04798c10cf279af6667e0f50cf1995a122a36fa525c5372fa9fbdbe72aef656ecc88dc8 -SHA512 (shadow-4.15.0rc2.tar.xz.asc) = b258c261cf6a7f16b078635a0c900144fc1868fd0686336255823e22b589e9b19459a5e43bb52cff7104b794e62c81de84d52d24d380c8e262d56b7e8cb5eb8b +SHA512 (shadow-4.15.0rc3.tar.xz) = 4b5329c73e495c2ff4ab69070ce30c1fd8219a8f87a394effa2a301949849e0db53ace5356a373e75707847e2248710fe9943db8c2d3238e76ee2a73e4274d9c +SHA512 (shadow-4.15.0rc3.tar.xz.asc) = 5261e179ca264a7ad8c5d8ae62c5bed606bb6db2b17e16ef863fade88938bcc6e27e19deed7c58099ec51bb39e0d3b4332a7d8b58dcde8280b49993da7774e23 From 7c3405fb6a0afdae840b6f0d775243135240807c Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 11 Mar 2024 11:36:23 +0100 Subject: [PATCH 066/118] Rebase to version 4.15.0 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + ...> shadow-4.15.0-account-tools-setuid.patch | 71 ++++---- shadow-4.15.0-audit-update.patch | 164 +++++++++--------- shadow-utils.spec | 11 +- sources | 4 +- 5 files changed, 124 insertions(+), 128 deletions(-) rename shadow-4.14.0-account-tools-setuid.patch => shadow-4.15.0-account-tools-setuid.patch (81%) diff --git a/.gitignore b/.gitignore index 26ea3ae..db3a21c 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.15.0rc2.tar.xz.asc /shadow-4.15.0rc3.tar.xz /shadow-4.15.0rc3.tar.xz.asc +/shadow-4.15.0.tar.xz +/shadow-4.15.0.tar.xz.asc diff --git a/shadow-4.14.0-account-tools-setuid.patch b/shadow-4.15.0-account-tools-setuid.patch similarity index 81% rename from shadow-4.14.0-account-tools-setuid.patch rename to shadow-4.15.0-account-tools-setuid.patch index 17d8918..d162487 100644 --- a/shadow-4.14.0-account-tools-setuid.patch +++ b/shadow-4.15.0-account-tools-setuid.patch @@ -1,7 +1,6 @@ -diff --git a/src/chpasswd.c b/src/chpasswd.c -index 3a4bd4fe..246e4176 100644 ---- a/src/chpasswd.c -+++ b/src/chpasswd.c +diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chpasswd.c +--- shadow-4.15.0/src/chpasswd.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/chpasswd.c 2024-03-11 11:21:57.561150382 +0100 @@ -443,9 +443,11 @@ int main (int argc, char **argv) char *cp; const char *salt; @@ -14,7 +13,7 @@ index 3a4bd4fe..246e4176 100644 int errors = 0; int line = 0; -@@ -470,19 +472,23 @@ int main (int argc, char **argv) +@@ -469,19 +471,23 @@ int main (int argc, char **argv) process_root_flag ("-R", argc, argv); prefix = process_prefix_flag ("-P", argc, argv); @@ -26,7 +25,7 @@ index 3a4bd4fe..246e4176 100644 #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ - OPENLOG ("chpasswd"); + OPENLOG (Prog); check_perms (); @@ -38,15 +37,15 @@ index 3a4bd4fe..246e4176 100644 { is_shadow_pwd = spw_file_present (); -@@ -544,6 +550,7 @@ int main (int argc, char **argv) +@@ -543,6 +549,7 @@ int main (int argc, char **argv) } newpwd = cp; +#ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM if (use_pam) { - if (do_pam_passwd_non_interactive ("chpasswd", name, newpwd) != 0) { -@@ -554,6 +561,7 @@ int main (int argc, char **argv) + if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { +@@ -553,6 +560,7 @@ int main (int argc, char **argv) } } else #endif /* USE_PAM */ @@ -54,7 +53,7 @@ index 3a4bd4fe..246e4176 100644 { const struct spwd *sp; struct spwd newsp; -@@ -673,9 +681,11 @@ int main (int argc, char **argv) +@@ -672,9 +680,11 @@ int main (int argc, char **argv) * password database. */ if (0 != errors) { @@ -66,7 +65,7 @@ index 3a4bd4fe..246e4176 100644 { fprintf (stderr, _("%s: error detected, changes ignored\n"), -@@ -684,9 +694,11 @@ int main (int argc, char **argv) +@@ -683,9 +693,11 @@ int main (int argc, char **argv) fail_exit (1); } @@ -78,10 +77,9 @@ index 3a4bd4fe..246e4176 100644 { /* Save the changes */ close_files (); -diff --git a/src/groupmems.c b/src/groupmems.c -index 63a1601c..73f7310e 100644 ---- a/src/groupmems.c -+++ b/src/groupmems.c +diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/groupmems.c +--- shadow-4.15.0/src/groupmems.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/groupmems.c 2024-03-11 11:16:18.365408572 +0100 @@ -14,9 +14,11 @@ #include #include @@ -94,7 +92,7 @@ index 63a1601c..73f7310e 100644 #include #include "alloc.h" -@@ -430,6 +432,7 @@ static void process_flags (int argc, char **argv) +@@ -430,6 +432,7 @@ static void process_flags (int argc, cha static void check_perms (void) { if (!list) { @@ -112,12 +110,11 @@ index 63a1601c..73f7310e 100644 } } -diff --git a/src/newusers.c b/src/newusers.c -index 09e14a48..96b60de2 100644 ---- a/src/newusers.c -+++ b/src/newusers.c +diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/newusers.c +--- shadow-4.15.0/src/newusers.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/newusers.c 2024-03-11 11:20:07.198909046 +0100 @@ -59,6 +59,7 @@ - const char *Prog; + static const char Prog[] = "newusers"; static bool rflg = false; /* create a system account */ +#ifndef ACCT_TOOLS_SETUID @@ -172,7 +169,7 @@ index 09e14a48..96b60de2 100644 (void) fputs ("\n", usageout); exit (status); -@@ -405,6 +413,7 @@ static int add_user (const char *name, uid_t uid, gid_t gid) +@@ -405,6 +413,7 @@ static int add_user (const char *name, u return (pw_update (&pwent) == 0) ? -1 : 0; } @@ -180,7 +177,7 @@ index 09e14a48..96b60de2 100644 #ifndef USE_PAM /* * update_passwd - update the password in the passwd entry -@@ -457,6 +466,7 @@ static int update_passwd (struct passwd *pwd, const char *password) +@@ -457,6 +466,7 @@ static int update_passwd (struct passwd return 0; } #endif /* !USE_PAM */ @@ -188,7 +185,7 @@ index 09e14a48..96b60de2 100644 /* * add_passwd - add or update the encrypted password -@@ -465,10 +475,13 @@ static int add_passwd (struct passwd *pwd, const char *password) +@@ -465,10 +475,13 @@ static int add_passwd (struct passwd *pw { const struct spwd *sp; struct spwd spent; @@ -202,7 +199,7 @@ index 09e14a48..96b60de2 100644 #ifndef USE_PAM void *crypt_arg = NULL; if (NULL != crypt_method) { -@@ -505,13 +518,14 @@ static int add_passwd (struct passwd *pwd, const char *password) +@@ -505,13 +518,14 @@ static int add_passwd (struct passwd *pw return update_passwd (pwd, password); } #endif /* USE_PAM */ @@ -218,7 +215,7 @@ index 09e14a48..96b60de2 100644 if (NULL != sp) { spent = *sp; if ( (NULL != crypt_method) -@@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pwd, const char *password) +@@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pw if (strcmp (pwd->pw_passwd, "x") != 0) { return update_passwd (pwd, password); } @@ -227,7 +224,7 @@ index 09e14a48..96b60de2 100644 /* * If there is already a shadow entry, do not touch it. * If there is already a passwd entry with a password, do not -@@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pwd, const char *password) +@@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pw || (strcmp (pwd->pw_passwd, "x") != 0)) { return 0; } @@ -244,7 +241,7 @@ index 09e14a48..96b60de2 100644 if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { spent.sp_pwdp = (char *)password; } else { -@@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pwd, const char *password) +@@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pw static void process_flags (int argc, char **argv) { int c; @@ -288,7 +285,7 @@ index 09e14a48..96b60de2 100644 "bhr", #endif long_options, NULL)) != -1) { -@@ -646,11 +666,13 @@ static void process_flags (int argc, char **argv) +@@ -646,11 +666,13 @@ static void process_flags (int argc, cha case 'b': allow_bad_names = true; break; @@ -302,7 +299,7 @@ index 09e14a48..96b60de2 100644 case 'h': usage (EXIT_SUCCESS); break; -@@ -659,6 +681,7 @@ static void process_flags (int argc, char **argv) +@@ -659,6 +681,7 @@ static void process_flags (int argc, cha break; case 'R': /* no-op, handled in process_root_flag () */ break; @@ -310,7 +307,7 @@ index 09e14a48..96b60de2 100644 #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': -@@ -698,6 +721,7 @@ static void process_flags (int argc, char **argv) +@@ -698,6 +721,7 @@ static void process_flags (int argc, cha break; #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -318,7 +315,7 @@ index 09e14a48..96b60de2 100644 default: usage (EXIT_FAILURE); break; -@@ -730,6 +754,7 @@ static void process_flags (int argc, char **argv) +@@ -730,6 +754,7 @@ static void process_flags (int argc, cha */ static void check_flags (void) { @@ -347,9 +344,9 @@ index 09e14a48..96b60de2 100644 #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ - Prog = Basename (argv[0]); log_set_progname(Prog); -@@ -1196,6 +1224,7 @@ int main (int argc, char **argv) + log_set_logfd(stderr); +@@ -1195,6 +1223,7 @@ int main (int argc, char **argv) } newpw = *pw; @@ -357,7 +354,7 @@ index 09e14a48..96b60de2 100644 #ifdef USE_PAM /* keep the list of user/password for later update by PAM */ nusers++; -@@ -1212,6 +1241,7 @@ int main (int argc, char **argv) +@@ -1211,6 +1240,7 @@ int main (int argc, char **argv) usernames[nusers-1] = strdup (fields[0]); passwords[nusers-1] = strdup (fields[1]); #endif /* USE_PAM */ @@ -365,7 +362,7 @@ index 09e14a48..96b60de2 100644 if (add_passwd (&newpw, fields[1]) != 0) { fprintf (stderr, _("%s: line %d: can't update password\n"), -@@ -1328,6 +1358,7 @@ int main (int argc, char **argv) +@@ -1327,6 +1357,7 @@ int main (int argc, char **argv) nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); @@ -373,7 +370,7 @@ index 09e14a48..96b60de2 100644 #ifdef USE_PAM unsigned int i; /* Now update the passwords using PAM */ -@@ -1340,6 +1371,7 @@ int main (int argc, char **argv) +@@ -1339,6 +1370,7 @@ int main (int argc, char **argv) } } #endif /* USE_PAM */ diff --git a/shadow-4.15.0-audit-update.patch b/shadow-4.15.0-audit-update.patch index 60c1ad7..a625c5c 100644 --- a/shadow-4.15.0-audit-update.patch +++ b/shadow-4.15.0-audit-update.patch @@ -1,6 +1,6 @@ diff -up shadow-4.15.0/lib/audit_help.c.audit-update shadow-4.15.0/lib/audit_help.c ---- shadow-4.15.0/lib/audit_help.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/lib/audit_help.c 2024-02-09 10:49:57.106840590 +0100 +--- shadow-4.15.0/lib/audit_help.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.0/lib/audit_help.c 2024-03-11 10:56:20.233991612 +0100 @@ -48,7 +48,7 @@ void audit_help_open (void) * This function will log a message to the audit system using a predefined * message format. Parameter usage is as follows: @@ -51,8 +51,8 @@ diff -up shadow-4.15.0/lib/audit_help.c.audit-update shadow-4.15.0/lib/audit_hel { if (audit_fd < 0) { diff -up shadow-4.15.0/lib/cleanup_group.c.audit-update shadow-4.15.0/lib/cleanup_group.c ---- shadow-4.15.0/lib/cleanup_group.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/lib/cleanup_group.c 2024-02-09 10:49:57.106840590 +0100 +--- shadow-4.15.0/lib/cleanup_group.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.0/lib/cleanup_group.c 2024-03-11 10:56:20.233991612 +0100 @@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cle gr_dbname (), info->action)); @@ -132,8 +132,8 @@ diff -up shadow-4.15.0/lib/cleanup_group.c.audit-update shadow-4.15.0/lib/cleanu #endif } diff -up shadow-4.15.0/lib/cleanup_user.c.audit-update shadow-4.15.0/lib/cleanup_user.c ---- shadow-4.15.0/lib/cleanup_user.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/lib/cleanup_user.c 2024-02-09 10:49:57.106840590 +0100 +--- shadow-4.15.0/lib/cleanup_user.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.0/lib/cleanup_user.c 2024-03-11 10:56:20.233991612 +0100 @@ -44,7 +44,7 @@ void cleanup_report_mod_passwd (void *cl pw_dbname (), info->action)); @@ -182,8 +182,8 @@ diff -up shadow-4.15.0/lib/cleanup_user.c.audit-update shadow-4.15.0/lib/cleanup #endif } diff -up shadow-4.15.0/lib/prototypes.h.audit-update shadow-4.15.0/lib/prototypes.h ---- shadow-4.15.0/lib/prototypes.h.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/lib/prototypes.h 2024-02-09 10:49:57.106840590 +0100 +--- shadow-4.15.0/lib/prototypes.h.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.0/lib/prototypes.h 2024-03-11 10:56:20.233991612 +0100 @@ -198,12 +198,21 @@ extern int audit_fd; extern void audit_help_open (void); /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ @@ -207,8 +207,8 @@ diff -up shadow-4.15.0/lib/prototypes.h.audit-update shadow-4.15.0/lib/prototype #endif diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c ---- shadow-4.15.0/src/chage.c.audit-update 2024-01-22 22:36:43.000000000 +0100 -+++ shadow-4.15.0/src/chage.c 2024-02-09 10:49:57.106840590 +0100 +--- shadow-4.15.0/src/chage.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/chage.c 2024-03-11 10:56:20.234991618 +0100 @@ -110,8 +110,8 @@ fail_exit (int code) #ifdef WITH_AUDIT @@ -220,7 +220,7 @@ diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c } #endif -@@ -845,10 +845,7 @@ int main (int argc, char **argv) +@@ -846,10 +846,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Permission denied.\n"), Prog); fail_exit (E_NOPERM); } @@ -232,7 +232,7 @@ diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c list_fields (); fail_exit (E_SUCCESS); } -@@ -867,39 +864,39 @@ int main (int argc, char **argv) +@@ -868,39 +865,39 @@ int main (int argc, char **argv) } #ifdef WITH_AUDIT else { @@ -288,8 +288,8 @@ diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c } #endif diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c ---- shadow-4.15.0/src/gpasswd.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/src/gpasswd.c 2024-02-09 10:55:42.642444103 +0100 +--- shadow-4.15.0/src/gpasswd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/gpasswd.c 2024-03-11 10:56:20.234991618 +0100 @@ -125,7 +125,7 @@ static void usage (int status) (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); @@ -353,7 +353,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Rflg) { -@@ -429,11 +429,9 @@ static void log_gpasswd_failure (const c +@@ -429,11 +419,9 @@ static void log_gpasswd_failure (const c "%s failed to restrict access to group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -368,7 +368,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } else if (Aflg || Mflg) { -@@ -443,11 +433,9 @@ static void log_gpasswd_failure (const c +@@ -443,11 +431,9 @@ static void log_gpasswd_failure (const c "%s failed to set the administrators of group %s to %s%s", myname, group, admins, suffix)); #ifdef WITH_AUDIT @@ -383,7 +383,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -457,11 +457,9 @@ static void log_gpasswd_failure (const c +@@ -457,11 +443,9 @@ static void log_gpasswd_failure (const c "%s failed to set the members of group %s to %s%s", myname, group, members, suffix)); #ifdef WITH_AUDIT @@ -398,7 +398,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -470,11 +468,9 @@ static void log_gpasswd_failure (const c +@@ -470,11 +454,9 @@ static void log_gpasswd_failure (const c "%s failed to change password of group %s%s", myname, group, suffix)); #ifdef WITH_AUDIT @@ -413,7 +413,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_FAILURE); #endif } -@@ -514,11 +502,9 @@ static void log_gpasswd_success (const c +@@ -514,11 +496,9 @@ static void log_gpasswd_success (const c "user %s added by %s to group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT @@ -428,7 +428,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (dflg) { -@@ -526,11 +512,9 @@ static void log_gpasswd_success (const c +@@ -526,11 +506,9 @@ static void log_gpasswd_success (const c "user %s removed by %s from group %s%s", user, myname, group, suffix)); #ifdef WITH_AUDIT @@ -443,7 +443,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (rflg) { -@@ -540,9 +524,9 @@ static void log_gpasswd_success (const c +@@ -540,9 +518,9 @@ static void log_gpasswd_success (const c #ifdef WITH_AUDIT SNPRINTF(buf, "password of group %s removed by %s%s", group, myname, suffix); @@ -456,7 +456,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Rflg) { -@@ -552,9 +536,9 @@ static void log_gpasswd_success (const c +@@ -552,9 +530,9 @@ static void log_gpasswd_success (const c #ifdef WITH_AUDIT SNPRINTF(buf, "access to group %s restricted by %s%s", group, myname, suffix); @@ -469,7 +469,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } else if (Aflg || Mflg) { -@@ -564,11 +548,9 @@ static void log_gpasswd_success (const c +@@ -564,11 +542,9 @@ static void log_gpasswd_success (const c "administrators of group %s set by %s to %s%s", group, myname, admins, suffix)); #ifdef WITH_AUDIT @@ -484,7 +484,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -578,11 +560,9 @@ static void log_gpasswd_success (const c +@@ -578,11 +554,9 @@ static void log_gpasswd_success (const c "members of group %s set by %s to %s%s", group, myname, members, suffix)); #ifdef WITH_AUDIT @@ -499,7 +499,7 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -@@ -591,11 +571,9 @@ static void log_gpasswd_success (const c +@@ -591,11 +565,9 @@ static void log_gpasswd_success (const c "password of group %s changed by %s%s", group, myname, suffix)); #ifdef WITH_AUDIT @@ -515,8 +515,8 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c #endif } diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c ---- shadow-4.15.0/src/groupadd.c.audit-update 2024-01-22 22:36:43.000000000 +0100 -+++ shadow-4.15.0/src/groupadd.c 2024-02-09 10:58:18.325715738 +0100 +--- shadow-4.15.0/src/groupadd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/groupadd.c 2024-03-11 10:59:11.522108956 +0100 @@ -115,6 +115,15 @@ usage (int status) exit (status); } @@ -662,7 +662,7 @@ diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c + fail_exit (1); } - retval = pam_start ("groupadd", pampw->pw_name, &conv, &pamh); + retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); @@ -560,7 +565,7 @@ static void check_perms (void) if (NULL != pamh) { (void) pam_end (pamh, retval); @@ -672,7 +672,7 @@ diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -595,7 +600,7 @@ int main (int argc, char **argv) +@@ -591,7 +596,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -681,7 +681,7 @@ diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c } /* -@@ -622,7 +627,7 @@ int main (int argc, char **argv) +@@ -618,7 +623,7 @@ int main (int argc, char **argv) if (!gflg) { if (find_new_gid (rflg, &group_id, NULL) < 0) { @@ -691,8 +691,8 @@ diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c } diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c ---- shadow-4.15.0/src/groupdel.c.audit-update 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.15.0/src/groupdel.c 2024-02-09 10:49:57.107840592 +0100 +--- shadow-4.15.0/src/groupdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/groupdel.c 2024-03-11 11:14:20.572151046 +0100 @@ -87,6 +87,15 @@ usage (int status) exit (status); } @@ -815,7 +815,7 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c } /* -@@ -372,7 +376,7 @@ int main (int argc, char **argv) +@@ -368,7 +372,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot setup cleanup service.\n"), Prog); @@ -824,7 +824,7 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c } process_flags (argc, argv); -@@ -386,7 +390,7 @@ int main (int argc, char **argv) +@@ -382,7 +386,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); @@ -832,8 +832,8 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c + fail_exit (1); } - retval = pam_start ("groupdel", pampw->pw_name, &conv, &pamh); -@@ -407,7 +411,7 @@ int main (int argc, char **argv) + retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); +@@ -403,7 +407,7 @@ int main (int argc, char **argv) if (NULL != pamh) { (void) pam_end (pamh, retval); } @@ -842,7 +842,7 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c } (void) pam_end (pamh, retval); #endif /* USE_PAM */ -@@ -427,7 +431,7 @@ int main (int argc, char **argv) +@@ -423,7 +427,7 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group '%s' does not exist\n"), Prog, group_name); @@ -851,7 +851,7 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c } group_id = grp->gr_gid; -@@ -451,7 +455,7 @@ int main (int argc, char **argv) +@@ -447,7 +451,7 @@ int main (int argc, char **argv) _("%s: %s is the NIS master\n"), Prog, nis_master); } @@ -861,8 +861,8 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c #endif diff -up shadow-4.15.0/src/groupmod.c.audit-update shadow-4.15.0/src/groupmod.c ---- shadow-4.15.0/src/groupmod.c.audit-update 2024-01-22 22:36:43.000000000 +0100 -+++ shadow-4.15.0/src/groupmod.c 2024-02-09 10:49:57.107840592 +0100 +--- shadow-4.15.0/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/groupmod.c 2024-03-11 10:56:20.234991618 +0100 @@ -474,7 +474,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } @@ -909,8 +909,8 @@ diff -up shadow-4.15.0/src/groupmod.c.audit-update shadow-4.15.0/src/groupmod.c SHADOW_AUDIT_SUCCESS); #endif diff -up shadow-4.15.0/src/newgrp.c.audit-update shadow-4.15.0/src/newgrp.c ---- shadow-4.15.0/src/newgrp.c.audit-update 2023-12-27 16:58:48.000000000 +0100 -+++ shadow-4.15.0/src/newgrp.c 2024-02-09 11:02:30.575155871 +0100 +--- shadow-4.15.0/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/newgrp.c 2024-03-11 10:56:20.234991618 +0100 @@ -188,10 +188,10 @@ static void check_perms (const struct gr if (grp->gr_passwd[0] == '\0' || strcmp (cpasswd, grp->gr_passwd) != 0) { @@ -1092,8 +1092,8 @@ diff -up shadow-4.15.0/src/newgrp.c.audit-update shadow-4.15.0/src/newgrp.c #endif exit (EXIT_FAILURE); diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c ---- shadow-4.15.0/src/useradd.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/src/useradd.c 2024-02-09 10:49:57.108840594 +0100 +--- shadow-4.15.0/src/useradd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/useradd.c 2024-03-11 10:56:20.235991625 +0100 @@ -242,6 +242,8 @@ static void check_uid_range(int rflg, ui */ static void fail_exit (int code) @@ -1370,7 +1370,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif #ifdef WITH_SELINUX -@@ -2594,12 +2544,6 @@ int main (int argc, char **argv) +@@ -2590,12 +2540,6 @@ int main (int argc, char **argv) */ if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); @@ -1383,7 +1383,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_NAME_IN_USE); } -@@ -2615,12 +2559,6 @@ int main (int argc, char **argv) +@@ -2611,12 +2555,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), Prog, user_name); @@ -1396,7 +1396,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_NAME_IN_USE); } } -@@ -2650,12 +2588,6 @@ int main (int argc, char **argv) +@@ -2646,12 +2584,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: UID %lu is not unique\n"), Prog, (unsigned long) user_id); @@ -1409,7 +1409,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_UID_IN_USE); } } -@@ -2730,9 +2662,9 @@ int main (int argc, char **argv) +@@ -2726,9 +2658,9 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -1423,8 +1423,8 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_SE_UPDATE); } diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c ---- shadow-4.15.0/src/userdel.c.audit-update 2023-12-27 16:58:48.000000000 +0100 -+++ shadow-4.15.0/src/userdel.c 2024-02-09 10:49:57.108840594 +0100 +--- shadow-4.15.0/src/userdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/userdel.c 2024-03-11 10:56:20.235991625 +0100 @@ -206,9 +206,9 @@ static void update_groups (void) * Update the DBM group file with the new entry as well. */ @@ -1691,7 +1691,7 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); } #endif /* WITH_AUDIT */ -@@ -1108,7 +1048,7 @@ int main (int argc, char **argv) +@@ -1104,7 +1044,7 @@ int main (int argc, char **argv) Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1700,7 +1700,7 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1158,7 +1098,7 @@ int main (int argc, char **argv) +@@ -1154,7 +1094,7 @@ int main (int argc, char **argv) if (!fflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, @@ -1709,7 +1709,7 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -1252,8 +1192,8 @@ int main (int argc, char **argv) +@@ -1248,8 +1188,8 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT else { @@ -1720,7 +1720,7 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_SUCCESS); } #endif /* WITH_AUDIT */ -@@ -1261,7 +1201,7 @@ int main (int argc, char **argv) +@@ -1257,7 +1197,7 @@ int main (int argc, char **argv) #ifdef WITH_AUDIT if (0 != errors) { audit_logger (AUDIT_DEL_USER, Prog, @@ -1729,7 +1729,7 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); } -@@ -1274,8 +1214,8 @@ int main (int argc, char **argv) +@@ -1270,8 +1210,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -1741,9 +1741,9 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c ---- shadow-4.15.0/src/usermod.c.audit-update 2024-02-01 23:59:36.000000000 +0100 -+++ shadow-4.15.0/src/usermod.c 2024-02-09 10:49:57.108840594 +0100 -@@ -431,7 +431,7 @@ static char *new_pw_passwd (char *pw_pas +--- shadow-4.15.0/src/usermod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/usermod.c 2024-03-11 10:56:20.235991625 +0100 +@@ -438,7 +438,7 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1752,7 +1752,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); strcpy (buf, "!"); -@@ -448,14 +448,14 @@ static char *new_pw_passwd (char *pw_pas +@@ -455,14 +455,14 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1769,7 +1769,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); pw_pass = xstrdup (user_pass); -@@ -483,8 +483,8 @@ static void new_pwent (struct passwd *pw +@@ -490,8 +490,8 @@ static void new_pwent (struct passwd *pw fail_exit (E_NAME_IN_USE); } #ifdef WITH_AUDIT @@ -1780,7 +1780,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user name '%s' to '%s'", -@@ -503,8 +503,8 @@ static void new_pwent (struct passwd *pw +@@ -510,8 +510,8 @@ static void new_pwent (struct passwd *pw if (uflg) { #ifdef WITH_AUDIT @@ -1791,7 +1791,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' UID from '%d' to '%d'", -@@ -513,8 +513,8 @@ static void new_pwent (struct passwd *pw +@@ -520,8 +520,8 @@ static void new_pwent (struct passwd *pw } if (gflg) { #ifdef WITH_AUDIT @@ -1802,7 +1802,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -524,16 +524,16 @@ static void new_pwent (struct passwd *pw +@@ -531,16 +531,16 @@ static void new_pwent (struct passwd *pw } if (cflg) { #ifdef WITH_AUDIT @@ -1823,7 +1823,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -549,8 +549,8 @@ static void new_pwent (struct passwd *pw +@@ -556,8 +556,8 @@ static void new_pwent (struct passwd *pw } if (sflg) { #ifdef WITH_AUDIT @@ -1834,7 +1834,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -580,8 +580,8 @@ static void new_spent (struct spwd *spen +@@ -587,8 +587,8 @@ static void new_spent (struct spwd *spen if (fflg) { #ifdef WITH_AUDIT @@ -1845,7 +1845,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -595,8 +595,8 @@ static void new_spent (struct spwd *spen +@@ -602,8 +602,8 @@ static void new_spent (struct spwd *spen date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT @@ -1856,7 +1856,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -681,9 +681,9 @@ fail_exit (int code) +@@ -688,9 +688,9 @@ fail_exit (int code) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -1869,7 +1869,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif exit (code); } -@@ -745,9 +745,12 @@ static void update_group (void) +@@ -752,9 +752,12 @@ static void update_group (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -1885,7 +1885,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in group '%s'", -@@ -761,9 +764,11 @@ static void update_group (void) +@@ -768,9 +771,11 @@ static void update_group (void) ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -1900,7 +1900,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from group '%s'", -@@ -776,9 +781,11 @@ static void update_group (void) +@@ -783,9 +788,11 @@ static void update_group (void) ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -1915,7 +1915,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to group '%s'", user_newname, ngrp->gr_name)); -@@ -863,9 +870,10 @@ static void update_gshadow (void) +@@ -870,9 +877,10 @@ static void update_gshadow (void) nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); changed = true; #ifdef WITH_AUDIT @@ -1929,7 +1929,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change admin '%s' to '%s' in shadow group '%s'", -@@ -885,9 +893,10 @@ static void update_gshadow (void) +@@ -892,9 +900,10 @@ static void update_gshadow (void) user_newname); changed = true; #ifdef WITH_AUDIT @@ -1943,7 +1943,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change '%s' to '%s' in shadow group '%s'", -@@ -901,9 +910,10 @@ static void update_gshadow (void) +@@ -908,9 +917,10 @@ static void update_gshadow (void) nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); changed = true; #ifdef WITH_AUDIT @@ -1957,7 +1957,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'", -@@ -916,9 +926,10 @@ static void update_gshadow (void) +@@ -923,9 +933,10 @@ static void update_gshadow (void) nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); changed = true; #ifdef WITH_AUDIT @@ -1971,7 +1971,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", user_newname, nsgrp->sg_name)); -@@ -1829,8 +1840,8 @@ static void move_home (void) +@@ -1836,8 +1847,8 @@ static void move_home (void) #ifdef WITH_AUDIT if (uflg || gflg) { @@ -1982,7 +1982,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -1848,8 +1859,8 @@ static void move_home (void) +@@ -1855,8 +1866,8 @@ static void move_home (void) fail_exit (E_HOMEDIR); } #ifdef WITH_AUDIT @@ -1993,7 +1993,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif return; -@@ -1876,9 +1887,9 @@ static void move_home (void) +@@ -1883,9 +1894,9 @@ static void move_home (void) Prog, prefix_user_home); } #ifdef WITH_AUDIT @@ -2005,7 +2005,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); -@@ -2102,8 +2113,8 @@ static void move_mailbox (void) +@@ -2109,8 +2120,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2016,7 +2016,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -2126,8 +2137,8 @@ static void move_mailbox (void) +@@ -2133,8 +2144,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2027,7 +2027,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } -@@ -2328,8 +2339,8 @@ int main (int argc, char **argv) +@@ -2331,8 +2342,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -2038,7 +2038,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2341,8 +2352,8 @@ int main (int argc, char **argv) +@@ -2344,8 +2355,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2049,7 +2049,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2385,8 +2396,8 @@ int main (int argc, char **argv) +@@ -2388,8 +2399,8 @@ int main (int argc, char **argv) */ #ifdef WITH_AUDIT if (uflg || gflg) { diff --git a/shadow-utils.spec b/shadow-utils.spec index b864952..bbd0a0d 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,6 +1,6 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.15.0rc3 +Version: 4.15.0 Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later @@ -25,7 +25,7 @@ Patch1: shadow-4.15.0-date-parsing.patch # Audit message changes - partially upstreamed Patch2: shadow-4.15.0-audit-update.patch # Probably non-upstreamable -Patch3: shadow-4.14.0-account-tools-setuid.patch +Patch3: shadow-4.15.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -273,11 +273,8 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog -* Fri Mar 1 2024 Iker Pedrosa - 2:4.15.0rc3-1 -- Rebase to version 4.15.0rc3 - -* Fri Feb 16 2024 Iker Pedrosa - 2:4.15.0rc2-1 -- Rebase to version 4.15.0rc2 +* Mon Mar 11 2024 Iker Pedrosa - 2:4.15.0-1 +- Rebase to version 4.15.0 * Mon Feb 12 2024 Iker Pedrosa - 2:4.14.0-6 - Build linking `libpam` diff --git a/sources b/sources index a6a9165..c3c37d6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.15.0rc3.tar.xz) = 4b5329c73e495c2ff4ab69070ce30c1fd8219a8f87a394effa2a301949849e0db53ace5356a373e75707847e2248710fe9943db8c2d3238e76ee2a73e4274d9c -SHA512 (shadow-4.15.0rc3.tar.xz.asc) = 5261e179ca264a7ad8c5d8ae62c5bed606bb6db2b17e16ef863fade88938bcc6e27e19deed7c58099ec51bb39e0d3b4332a7d8b58dcde8280b49993da7774e23 +SHA512 (shadow-4.15.0.tar.xz) = 88d72fb706f6792b460c14a9b1b42fe0b5962834ec3793f296cbc138807736b5ad73d3f802cda74db740a71545eb1c8ec47447c2250299eb730ed2b2674e2249 +SHA512 (shadow-4.15.0.tar.xz.asc) = 0a39d6a45b7d8df12aade89ed9fc9d481c91297dbd34e85fe831426c1d0051cbcf8478759306b8871cd6b1835604c5836decf398d0165c50ac52fee365561446 From f38dfa13570663ea7ad8f776619a3d7b0b5c3eff Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 12 Mar 2024 09:21:15 +0100 Subject: [PATCH 067/118] Bump the minor release to 4.15.1 Wrong versioning for 4.15.0 RC releases makes the oficial release look lower than them. Fix it by bumping the minor release to 4.15.1 Resolves: #2268690 Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ shadow-utils.spec | 6 +++++- sources | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index db3a21c..5db8705 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.15.0rc3.tar.xz.asc /shadow-4.15.0.tar.xz /shadow-4.15.0.tar.xz.asc +/shadow-4.15.1.tar.xz +/shadow-4.15.1.tar.xz.asc diff --git a/shadow-utils.spec b/shadow-utils.spec index bbd0a0d..a0e9990 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,6 +1,6 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.15.0 +Version: 4.15.1 Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later @@ -273,6 +273,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Mar 12 2024 Iker Pedrosa - 2:4.15.1-1 +- Wrong versioning for 4.15.0 RC releases makes the oficial release look lower than them. + Fix it by bumping the minor release to 4.15.1. Resolves: #2268690 + * Mon Mar 11 2024 Iker Pedrosa - 2:4.15.0-1 - Rebase to version 4.15.0 diff --git a/sources b/sources index c3c37d6..ca5a1c9 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.15.0.tar.xz) = 88d72fb706f6792b460c14a9b1b42fe0b5962834ec3793f296cbc138807736b5ad73d3f802cda74db740a71545eb1c8ec47447c2250299eb730ed2b2674e2249 -SHA512 (shadow-4.15.0.tar.xz.asc) = 0a39d6a45b7d8df12aade89ed9fc9d481c91297dbd34e85fe831426c1d0051cbcf8478759306b8871cd6b1835604c5836decf398d0165c50ac52fee365561446 +SHA512 (shadow-4.15.1.tar.xz) = 2667a1d781066adce42e684463329c3f32d28c07b7b79b628525bffcd61c078f6ff430be3d42976d0509d9f9a55cd80f5a50d479b85155476cee7f00f06708d8 +SHA512 (shadow-4.15.1.tar.xz.asc) = 0a39d6a45b7d8df12aade89ed9fc9d481c91297dbd34e85fe831426c1d0051cbcf8478759306b8871cd6b1835604c5836decf398d0165c50ac52fee365561446 From 1f1cc49defa6b4bed84aacc74ceaa388d0420abf Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 21 Mar 2024 11:29:11 +0530 Subject: [PATCH 068/118] getdef: avoid spurious error messages Avoid spurious error messages about unknown configuration options Resolves: #2265291 Signed-off-by: Iker Pedrosa --- shadow-4.15.0-getdef-spurious-error.patch | 137 ++++++++++++++++++++++ shadow-utils.spec | 8 +- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 shadow-4.15.0-getdef-spurious-error.patch diff --git a/shadow-4.15.0-getdef-spurious-error.patch b/shadow-4.15.0-getdef-spurious-error.patch new file mode 100644 index 0000000..9cec295 --- /dev/null +++ b/shadow-4.15.0-getdef-spurious-error.patch @@ -0,0 +1,137 @@ +From ead55e9ba8958504e23e29545f90c4dd925c7462 Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Wed, 20 Mar 2024 17:39:46 -0500 +Subject: [PATCH] getdef: avoid spurious error messages about unknown + configuration options + +def_find can return NULL for unset, not just unknown, config options. So +move the decision of whether to log an error message about an unknown config +option back into def_find, which knows the difference. Only putdef_str() +will pass a char* srcfile to def_find, so only calls from putdef_str will +cause the message, which was the original intent of fa68441bc4be8. + +closes #967 + +fixes: fa68441bc4be8 ("Improve the login.defs unknown item error message") +Signed-off-by: Serge Hallyn +--- + lib/getdef.c | 30 ++++++++++++++++-------------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/lib/getdef.c b/lib/getdef.c +index 4d4d4e19..ef2ae1f0 100644 +--- a/lib/getdef.c ++++ b/lib/getdef.c +@@ -176,7 +176,7 @@ static const char* def_fname = LOGINDEFS; /* login config defs file */ + static bool def_loaded = false; /* are defs already loaded? */ + + /* local function prototypes */ +-static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *); ++static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *, const char *); + static void def_load (void); + + +@@ -195,7 +195,7 @@ static void def_load (void); + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + return (NULL == d) ? NULL : d->value; + } + +@@ -214,7 +214,7 @@ bool getdef_bool (const char *item) + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + if ((NULL == d) || (NULL == d->value)) { + return false; + } +@@ -240,7 +240,7 @@ int getdef_num (const char *item, int dflt) + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + if ((NULL == d) || (NULL == d->value)) { + return dflt; + } +@@ -275,7 +275,7 @@ unsigned int getdef_unum (const char *item, unsigned int dflt) + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + if ((NULL == d) || (NULL == d->value)) { + return dflt; + } +@@ -310,7 +310,7 @@ long getdef_long (const char *item, long dflt) + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + if ((NULL == d) || (NULL == d->value)) { + return dflt; + } +@@ -342,7 +342,7 @@ unsigned long getdef_ulong (const char *item, unsigned long dflt) + def_load (); + } + +- d = def_find (item); ++ d = def_find (item, NULL); + if ((NULL == d) || (NULL == d->value)) { + return dflt; + } +@@ -375,12 +375,9 @@ int putdef_str (const char *name, const char *value, const char *srcfile) + * Locate the slot to save the value. If this parameter + * is unknown then "def_find" will print an err message. + */ +- d = def_find (name); +- if (NULL == d) { +- if (NULL != srcfile) +- SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); ++ d = def_find (name, srcfile); ++ if (NULL == d) + return -1; +- } + + /* + * Save off the value. +@@ -404,9 +401,12 @@ int putdef_str (const char *name, const char *value, const char *srcfile) + * + * Search through a table of configurable items to locate the + * specified configuration option. ++ * ++ * If srcfile is not NULL, and the item is not found, then report an error saying ++ * the unknown item was used in this file. + */ + +-static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) ++static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name, const char *srcfile) + { + struct itemdef *ptr; + +@@ -432,6 +432,8 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) + fprintf (shadow_logfd, + _("configuration error - unknown item '%s' (notify administrator)\n"), + name); ++ if (srcfile != NULL) ++ SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); + + out: + return NULL; +@@ -610,7 +612,7 @@ int main (int argc, char **argv) + def_load (); + + for (i = 0; i < NUMDEFS; ++i) { +- d = def_find (def_table[i].name); ++ d = def_find (def_table[i].name, NULL); + if (NULL == d) { + printf ("error - lookup '%s' failed\n", + def_table[i].name); +-- +2.44.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index a0e9990..655174e 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.1 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,6 +26,8 @@ Patch1: shadow-4.15.0-date-parsing.patch Patch2: shadow-4.15.0-audit-update.patch # Probably non-upstreamable Patch3: shadow-4.15.0-account-tools-setuid.patch +# https://github.com/shadow-maint/shadow/commit/ead55e9ba8958504e23e29545f90c4dd925c7462 +Patch4: shadow-4.15.0-getdef-spurious-error.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -273,6 +275,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Mar 21 2024 Iker Pedrosa - 2:4.15.1-2 +- getdef: avoid spurious error messages about unknown configuration options. + Resolves: #2265291 + * Tue Mar 12 2024 Iker Pedrosa - 2:4.15.1-1 - Wrong versioning for 4.15.0 RC releases makes the oficial release look lower than them. Fix it by bumping the minor release to 4.15.1. Resolves: #2268690 From 39c1e07961334ffb76861182c2ac01967110cac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 10 Apr 2024 13:43:36 +0200 Subject: [PATCH 069/118] Prepare for bin-sbin merge https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin First, fix build if %_sbindir == %_bindir. Second, add Provides for the old locations. We rely on the filesystem(unmerged-sbin-symlinks) feature to actually create the symlinks for us. This commit makes things compatible with the state before and after the merge. --- shadow-utils.spec | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 655174e..ad712a1 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.1 -Release: 2%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -62,6 +62,19 @@ Provides: shadow = %{epoch}:%{version}-%{release} Provides: passwd = 0.80-18 Obsoletes: passwd <= 0.80-19 +%if "%{_sbindir}" == "%{_bindir}" +# Compat symlinks for Requires in other packages. +# We rely on filesystem to create the symlinks for us. +Requires: filesystem(unmerged-sbin-symlinks) +Provides: /usr/sbin/adduser +Provides: /usr/sbin/useradd +Provides: /usr/sbin/userdel +Provides: /usr/sbin/usermod +Provides: /usr/sbin/groupadd +Provides: /usr/sbin/groupdel +Provides: /usr/sbin/groupmod +%endif + %description The shadow-utils package includes the necessary programs for converting UNIX password files to the shadow password format, plus @@ -149,6 +162,11 @@ for subdir in $RPM_BUILD_ROOT%{_mandir}/{??,??_??,??_??.*}/man* ; do test -d $subdir && test -e $subdir/useradd.8 && echo ".so man8/useradd.8" > $subdir/adduser.8 done +%if "%{_sbindir}" == "%{_bindir}" +# The installation script doesn't actually use the configured paths :( +mv -v $RPM_BUILD_ROOT/usr/sbin/* $RPM_BUILD_ROOT%{_bindir}/ +%endif + # Remove binaries we don't use. rm $RPM_BUILD_ROOT%{_bindir}/chfn rm $RPM_BUILD_ROOT%{_bindir}/chsh @@ -275,6 +293,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Apr 11 2024 Zbigniew Jedrzejewski-Szmek - 2:4.15.1-4 +- Fix build with %%_bindir==%%_sbindir +- Add virtual Provides for old file paths used by other packages + * Thu Mar 21 2024 Iker Pedrosa - 2:4.15.1-2 - getdef: avoid spurious error messages about unknown configuration options. Resolves: #2265291 From 6ad0830639f87cc09dd52228b4a2820dcaab05dc Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 20 May 2024 12:14:47 +0200 Subject: [PATCH 070/118] Several fixes for issues detected by static analyzer tools Signed-off-by: Iker Pedrosa --- ....patch => shadow-4.15.1-audit-update.patch | 302 ++-- shadow-4.15.1-sast-fixes.patch | 1413 +++++++++++++++++ shadow-utils.spec | 13 +- 3 files changed, 1573 insertions(+), 155 deletions(-) rename shadow-4.15.0-audit-update.patch => shadow-4.15.1-audit-update.patch (89%) create mode 100644 shadow-4.15.1-sast-fixes.patch diff --git a/shadow-4.15.0-audit-update.patch b/shadow-4.15.1-audit-update.patch similarity index 89% rename from shadow-4.15.0-audit-update.patch rename to shadow-4.15.1-audit-update.patch index a625c5c..a738d60 100644 --- a/shadow-4.15.0-audit-update.patch +++ b/shadow-4.15.1-audit-update.patch @@ -1,6 +1,6 @@ -diff -up shadow-4.15.0/lib/audit_help.c.audit-update shadow-4.15.0/lib/audit_help.c ---- shadow-4.15.0/lib/audit_help.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.0/lib/audit_help.c 2024-03-11 10:56:20.233991612 +0100 +diff -up shadow-4.15.1/lib/audit_help.c.audit-update shadow-4.15.1/lib/audit_help.c +--- shadow-4.15.1/lib/audit_help.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.1/lib/audit_help.c 2024-05-20 11:52:05.639758532 +0200 @@ -48,7 +48,7 @@ void audit_help_open (void) * This function will log a message to the audit system using a predefined * message format. Parameter usage is as follows: @@ -50,9 +50,9 @@ diff -up shadow-4.15.0/lib/audit_help.c.audit-update shadow-4.15.0/lib/audit_hel void audit_logger_message (const char *message, shadow_audit_result result) { if (audit_fd < 0) { -diff -up shadow-4.15.0/lib/cleanup_group.c.audit-update shadow-4.15.0/lib/cleanup_group.c ---- shadow-4.15.0/lib/cleanup_group.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.0/lib/cleanup_group.c 2024-03-11 10:56:20.233991612 +0100 +diff -up shadow-4.15.1/lib/cleanup_group.c.audit-update shadow-4.15.1/lib/cleanup_group.c +--- shadow-4.15.1/lib/cleanup_group.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.1/lib/cleanup_group.c 2024-05-20 11:52:05.639758532 +0200 @@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cle gr_dbname (), info->action)); @@ -131,9 +131,9 @@ diff -up shadow-4.15.0/lib/cleanup_group.c.audit-update shadow-4.15.0/lib/cleanu SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.15.0/lib/cleanup_user.c.audit-update shadow-4.15.0/lib/cleanup_user.c ---- shadow-4.15.0/lib/cleanup_user.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.0/lib/cleanup_user.c 2024-03-11 10:56:20.233991612 +0100 +diff -up shadow-4.15.1/lib/cleanup_user.c.audit-update shadow-4.15.1/lib/cleanup_user.c +--- shadow-4.15.1/lib/cleanup_user.c.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.1/lib/cleanup_user.c 2024-05-20 11:52:05.639758532 +0200 @@ -44,7 +44,7 @@ void cleanup_report_mod_passwd (void *cl pw_dbname (), info->action)); @@ -181,9 +181,9 @@ diff -up shadow-4.15.0/lib/cleanup_user.c.audit-update shadow-4.15.0/lib/cleanup SHADOW_AUDIT_FAILURE); #endif } -diff -up shadow-4.15.0/lib/prototypes.h.audit-update shadow-4.15.0/lib/prototypes.h ---- shadow-4.15.0/lib/prototypes.h.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.0/lib/prototypes.h 2024-03-11 10:56:20.233991612 +0100 +diff -up shadow-4.15.1/lib/prototypes.h.audit-update shadow-4.15.1/lib/prototypes.h +--- shadow-4.15.1/lib/prototypes.h.audit-update 2024-03-01 02:50:52.000000000 +0100 ++++ shadow-4.15.1/lib/prototypes.h 2024-05-20 11:52:05.639758532 +0200 @@ -198,12 +198,21 @@ extern int audit_fd; extern void audit_help_open (void); /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ @@ -206,9 +206,9 @@ diff -up shadow-4.15.0/lib/prototypes.h.audit-update shadow-4.15.0/lib/prototype void audit_logger_message (const char *message, shadow_audit_result result); #endif -diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c ---- shadow-4.15.0/src/chage.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/chage.c 2024-03-11 10:56:20.234991618 +0100 +diff -up shadow-4.15.1/src/chage.c.audit-update shadow-4.15.1/src/chage.c +--- shadow-4.15.1/src/chage.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/chage.c 2024-05-20 11:52:05.639758532 +0200 @@ -110,8 +110,8 @@ fail_exit (int code) #ifdef WITH_AUDIT @@ -287,9 +287,9 @@ diff -up shadow-4.15.0/src/chage.c.audit-update shadow-4.15.0/src/chage.c user_name, user_uid, 1); } #endif -diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c ---- shadow-4.15.0/src/gpasswd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/gpasswd.c 2024-03-11 10:56:20.234991618 +0100 +diff -up shadow-4.15.1/src/gpasswd.c.audit-update shadow-4.15.1/src/gpasswd.c +--- shadow-4.15.1/src/gpasswd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/gpasswd.c 2024-05-20 11:52:05.640758536 +0200 @@ -125,7 +125,7 @@ static void usage (int status) (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); @@ -514,9 +514,9 @@ diff -up shadow-4.15.0/src/gpasswd.c.audit-update shadow-4.15.0/src/gpasswd.c SHADOW_AUDIT_SUCCESS); #endif } -diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c ---- shadow-4.15.0/src/groupadd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/groupadd.c 2024-03-11 10:59:11.522108956 +0100 +diff -up shadow-4.15.1/src/groupadd.c.audit-update shadow-4.15.1/src/groupadd.c +--- shadow-4.15.1/src/groupadd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/groupadd.c 2024-05-20 11:52:05.640758536 +0200 @@ -115,6 +115,15 @@ usage (int status) exit (status); } @@ -690,9 +690,9 @@ diff -up shadow-4.15.0/src/groupadd.c.audit-update shadow-4.15.0/src/groupadd.c } } -diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c ---- shadow-4.15.0/src/groupdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/groupdel.c 2024-03-11 11:14:20.572151046 +0100 +diff -up shadow-4.15.1/src/groupdel.c.audit-update shadow-4.15.1/src/groupdel.c +--- shadow-4.15.1/src/groupdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/groupdel.c 2024-05-20 11:52:05.640758536 +0200 @@ -87,6 +87,15 @@ usage (int status) exit (status); } @@ -860,9 +860,9 @@ diff -up shadow-4.15.0/src/groupdel.c.audit-update shadow-4.15.0/src/groupdel.c } #endif -diff -up shadow-4.15.0/src/groupmod.c.audit-update shadow-4.15.0/src/groupmod.c ---- shadow-4.15.0/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/groupmod.c 2024-03-11 10:56:20.234991618 +0100 +diff -up shadow-4.15.1/src/groupmod.c.audit-update shadow-4.15.1/src/groupmod.c +--- shadow-4.15.1/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/groupmod.c 2024-05-20 11:52:05.640758536 +0200 @@ -474,7 +474,7 @@ static void close_files (void) exit (E_GRP_UPDATE); } @@ -908,9 +908,9 @@ diff -up shadow-4.15.0/src/groupmod.c.audit-update shadow-4.15.0/src/groupmod.c group_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -diff -up shadow-4.15.0/src/newgrp.c.audit-update shadow-4.15.0/src/newgrp.c ---- shadow-4.15.0/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/newgrp.c 2024-03-11 10:56:20.234991618 +0100 +diff -up shadow-4.15.1/src/newgrp.c.audit-update shadow-4.15.1/src/newgrp.c +--- shadow-4.15.1/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/newgrp.c 2024-05-20 11:52:05.640758536 +0200 @@ -188,10 +188,10 @@ static void check_perms (const struct gr if (grp->gr_passwd[0] == '\0' || strcmp (cpasswd, grp->gr_passwd) != 0) { @@ -1091,10 +1091,10 @@ diff -up shadow-4.15.0/src/newgrp.c.audit-update shadow-4.15.0/src/newgrp.c } #endif exit (EXIT_FAILURE); -diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c ---- shadow-4.15.0/src/useradd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/useradd.c 2024-03-11 10:56:20.235991625 +0100 -@@ -242,6 +242,8 @@ static void check_uid_range(int rflg, ui +diff -up shadow-4.15.1/src/useradd.c.audit-update shadow-4.15.1/src/useradd.c +--- shadow-4.15.1/src/useradd.c.audit-update 2024-05-20 11:52:05.635758519 +0200 ++++ shadow-4.15.1/src/useradd.c 2024-05-20 11:52:05.640758536 +0200 +@@ -245,6 +245,8 @@ static FILE *fmkstemp(char *template); */ static void fail_exit (int code) { @@ -1103,7 +1103,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c if (home_added && rmdir(prefix_user_home) != 0) { fprintf(stderr, _("%s: %s was created, but could not be removed\n"), -@@ -252,38 +254,22 @@ static void fail_exit (int code) +@@ -255,38 +257,22 @@ static void fail_exit (int code) if (spw_locked && spw_unlock() == 0) { fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); @@ -1142,7 +1142,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c /* continue */ } #endif -@@ -291,27 +277,23 @@ static void fail_exit (int code) +@@ -294,27 +280,23 @@ static void fail_exit (int code) if (sub_uid_locked && sub_uid_unlock() == 0) { fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); @@ -1177,7 +1177,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); -@@ -732,7 +714,7 @@ static int set_defaults (void) +@@ -727,7 +709,7 @@ static int set_defaults (void) } #ifdef WITH_AUDIT audit_logger (AUDIT_USYS_CONFIG, Prog, @@ -1186,7 +1186,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c NULL, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -1060,12 +1042,6 @@ static void grp_update (void) +@@ -1056,12 +1038,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1199,7 +1199,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1079,18 +1055,12 @@ static void grp_update (void) +@@ -1075,18 +1051,12 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); @@ -1221,7 +1221,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1135,12 +1105,6 @@ static void grp_update (void) +@@ -1131,12 +1101,6 @@ static void grp_update (void) _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1234,7 +1234,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_GRP_UPDATE); /* XXX */ } -@@ -1154,18 +1118,13 @@ static void grp_update (void) +@@ -1150,18 +1114,13 @@ static void grp_update (void) _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); @@ -1257,7 +1257,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, -@@ -1560,7 +1519,7 @@ static void process_flags (int argc, cha +@@ -1556,7 +1515,7 @@ static void process_flags (int argc, cha Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1266,7 +1266,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1660,7 +1619,7 @@ static void close_files (void) +@@ -1656,7 +1615,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1275,7 +1275,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1673,7 +1632,7 @@ static void close_files (void) +@@ -1669,7 +1628,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1284,7 +1284,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1690,7 +1649,7 @@ static void close_files (void) +@@ -1686,7 +1645,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1293,7 +1293,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1704,7 +1663,7 @@ static void close_files (void) +@@ -1700,7 +1659,7 @@ static void close_files (void) SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, @@ -1302,7 +1302,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1967,7 +1926,7 @@ static void grp_add (void) +@@ -1963,7 +1922,7 @@ static void grp_add (void) Prog, gr_dbname (), grp.gr_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1311,7 +1311,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1983,7 +1942,7 @@ static void grp_add (void) +@@ -1979,7 +1938,7 @@ static void grp_add (void) Prog, sgr_dbname (), sgrp.sg_name); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1320,7 +1320,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif -@@ -1993,7 +1952,7 @@ static void grp_add (void) +@@ -1989,7 +1948,7 @@ static void grp_add (void) SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_GROUP, Prog, @@ -1329,7 +1329,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c grp.gr_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2195,11 +2154,6 @@ static void usr_update (unsigned long su +@@ -2191,11 +2150,6 @@ static void usr_update (unsigned long su fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spent.sp_namp); @@ -1341,7 +1341,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_PW_UPDATE); } #ifdef ENABLE_SUBIDS -@@ -2226,7 +2180,7 @@ static void usr_update (unsigned long su +@@ -2222,7 +2176,7 @@ static void usr_update (unsigned long su * and we can use the real ID thereafter. */ audit_logger (AUDIT_ADD_USER, Prog, @@ -1350,7 +1350,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif -@@ -2321,10 +2275,6 @@ static void create_home (void) +@@ -2317,10 +2271,6 @@ static void create_home (void) if (mkdir(path, 0) != 0) { fprintf(stderr, _("%s: cannot create directory %s\n"), Prog, path); @@ -1361,7 +1361,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit(E_HOMEDIR); } if (chown(path, 0, 0) < 0) { -@@ -2349,7 +2299,7 @@ static void create_home (void) +@@ -2345,7 +2295,7 @@ static void create_home (void) } home_added = true; #ifdef WITH_AUDIT @@ -1370,7 +1370,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c user_name, user_id, SHADOW_AUDIT_SUCCESS); #endif #ifdef WITH_SELINUX -@@ -2590,12 +2540,6 @@ int main (int argc, char **argv) +@@ -2586,12 +2536,6 @@ int main (int argc, char **argv) */ if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); @@ -1383,7 +1383,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_NAME_IN_USE); } -@@ -2611,12 +2555,6 @@ int main (int argc, char **argv) +@@ -2607,12 +2551,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), Prog, user_name); @@ -1396,7 +1396,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_NAME_IN_USE); } } -@@ -2646,12 +2584,6 @@ int main (int argc, char **argv) +@@ -2642,12 +2580,6 @@ int main (int argc, char **argv) fprintf (stderr, _("%s: UID %lu is not unique\n"), Prog, (unsigned long) user_id); @@ -1409,7 +1409,7 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c fail_exit (E_UID_IN_USE); } } -@@ -2726,9 +2658,9 @@ int main (int argc, char **argv) +@@ -2722,9 +2654,9 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -1422,9 +1422,9 @@ diff -up shadow-4.15.0/src/useradd.c.audit-update shadow-4.15.0/src/useradd.c #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); } -diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c ---- shadow-4.15.0/src/userdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/userdel.c 2024-03-11 10:56:20.235991625 +0100 +diff -up shadow-4.15.1/src/userdel.c.audit-update shadow-4.15.1/src/userdel.c +--- shadow-4.15.1/src/userdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.1/src/userdel.c 2024-05-20 11:52:05.641758539 +0200 @@ -206,9 +206,9 @@ static void update_groups (void) * Update the DBM group file with the new entry as well. */ @@ -1740,10 +1740,10 @@ diff -up shadow-4.15.0/src/userdel.c.audit-update shadow-4.15.0/src/userdel.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SE_UPDATE); -diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c ---- shadow-4.15.0/src/usermod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/usermod.c 2024-03-11 10:56:20.235991625 +0100 -@@ -438,7 +438,7 @@ static char *new_pw_passwd (char *pw_pas +diff -up shadow-4.15.1/src/usermod.c.audit-update shadow-4.15.1/src/usermod.c +--- shadow-4.15.1/src/usermod.c.audit-update 2024-05-20 11:52:05.638758529 +0200 ++++ shadow-4.15.1/src/usermod.c 2024-05-20 11:56:51.962509443 +0200 +@@ -440,7 +440,7 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1752,7 +1752,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); strcpy (buf, "!"); -@@ -455,14 +455,14 @@ static char *new_pw_passwd (char *pw_pas +@@ -457,14 +457,14 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, @@ -1769,7 +1769,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); pw_pass = xstrdup (user_pass); -@@ -490,8 +490,8 @@ static void new_pwent (struct passwd *pw +@@ -492,8 +492,8 @@ static void new_pwent (struct passwd *pw fail_exit (E_NAME_IN_USE); } #ifdef WITH_AUDIT @@ -1780,7 +1780,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user name '%s' to '%s'", -@@ -510,8 +510,8 @@ static void new_pwent (struct passwd *pw +@@ -512,8 +512,8 @@ static void new_pwent (struct passwd *pw if (uflg) { #ifdef WITH_AUDIT @@ -1791,7 +1791,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif SYSLOG ((LOG_INFO, "change user '%s' UID from '%d' to '%d'", -@@ -520,8 +520,8 @@ static void new_pwent (struct passwd *pw +@@ -522,8 +522,8 @@ static void new_pwent (struct passwd *pw } if (gflg) { #ifdef WITH_AUDIT @@ -1802,7 +1802,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -531,16 +531,16 @@ static void new_pwent (struct passwd *pw +@@ -533,16 +533,16 @@ static void new_pwent (struct passwd *pw } if (cflg) { #ifdef WITH_AUDIT @@ -1823,7 +1823,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -556,8 +556,8 @@ static void new_pwent (struct passwd *pw +@@ -558,8 +558,8 @@ static void new_pwent (struct passwd *pw } if (sflg) { #ifdef WITH_AUDIT @@ -1834,7 +1834,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -587,8 +587,8 @@ static void new_spent (struct spwd *spen +@@ -589,8 +589,8 @@ static void new_spent (struct spwd *spen if (fflg) { #ifdef WITH_AUDIT @@ -1845,7 +1845,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -602,8 +602,8 @@ static void new_spent (struct spwd *spen +@@ -604,8 +604,8 @@ static void new_spent (struct spwd *spen date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT @@ -1856,7 +1856,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, -@@ -688,9 +688,9 @@ fail_exit (int code) +@@ -690,9 +690,9 @@ fail_exit (int code) #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT @@ -1869,109 +1869,109 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c #endif exit (code); } -@@ -752,9 +752,12 @@ static void update_group (void) - user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing group member", -- user_newname, AUDIT_NO_ID, 1); -+ audit_logger_with_group ( -+ AUDIT_USER_MGMT, Prog, -+ "update-member-in-group", -+ user_newname, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in group '%s'", -@@ -768,9 +771,11 @@ static void update_group (void) - ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); +@@ -762,9 +762,12 @@ update_group(const struct group *grp) + user_newname); changed = true; #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing group member", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user_name, AUDIT_NO_ID, +- "changing group member", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group ( ++ AUDIT_USER_MGMT, Prog, ++ "update-member-in-group", ++ user_newname, AUDIT_NO_ID, + ngrp->gr_name, + SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, - "delete '%s' from group '%s'", -@@ -783,9 +788,11 @@ static void update_group (void) - ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); + "change '%s' to '%s' in group '%s'", +@@ -778,9 +781,11 @@ update_group(const struct group *grp) + ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); changed = true; #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, 1); +- "removing group member", +- user_name, AUDIT_NO_ID, 1); + audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", ++ "delete-user-from-group", + user_name, AUDIT_NO_ID, + ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "add '%s' to group '%s'", - user_newname, ngrp->gr_name)); -@@ -870,9 +877,10 @@ static void update_gshadow (void) - nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing admin name in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "update-admin-name-in-shadow-group", -+ user_name, AUDIT_NO_ID, nsgrp->sg_name, + SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, - "change admin '%s' to '%s' in shadow group '%s'", -@@ -892,9 +900,10 @@ static void update_gshadow (void) - user_newname); - changed = true; + "delete '%s' from group '%s'", +@@ -793,9 +798,11 @@ update_group(const struct group *grp) + ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); + changed = true; #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing member in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "update-member-in-shadow-group", -+ user_name, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-group", ++ user_name, AUDIT_NO_ID, ++ ngrp->gr_name, ++ SHADOW_AUDIT_SUCCESS); #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in shadow group '%s'", -@@ -908,9 +917,10 @@ static void update_gshadow (void) - nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + SYSLOG ((LOG_INFO, "add '%s' to group '%s'", + user_newname, ngrp->gr_name)); +@@ -888,9 +895,10 @@ update_gshadow(const struct sgrp *sgrp) + nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing admin name in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, ++ "update-admin-name-in-shadow-group", ++ user_name, AUDIT_NO_ID, nsgrp->sg_name, ++ SHADOW_AUDIT_SUCCESS); + #endif + SYSLOG ((LOG_INFO, + "change admin '%s' to '%s' in shadow group '%s'", +@@ -910,9 +918,10 @@ update_gshadow(const struct sgrp *sgrp) + user_newname); changed = true; #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing user from shadow group", -- user_name, AUDIT_NO_ID, 1); +- "changing member in shadow group", +- user_name, AUDIT_NO_ID, 1); + audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-shadow-group", ++ "update-member-in-shadow-group", + user_name, AUDIT_NO_ID, + nsgrp->sg_name, 1); #endif SYSLOG ((LOG_INFO, - "delete '%s' from shadow group '%s'", -@@ -923,9 +933,10 @@ static void update_gshadow (void) - nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); + "change '%s' to '%s' in shadow group '%s'", +@@ -926,9 +935,10 @@ update_gshadow(const struct sgrp *sgrp) + nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); changed = true; #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to shadow group", -- user_newname, AUDIT_NO_ID, 1); +- "removing user from shadow group", +- user_name, AUDIT_NO_ID, 1); + audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-shadow-group", -+ user_newname, AUDIT_NO_ID, ++ "delete-user-from-shadow-group", ++ user_name, AUDIT_NO_ID, + nsgrp->sg_name, 1); #endif - SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", - user_newname, nsgrp->sg_name)); -@@ -1836,8 +1847,8 @@ static void move_home (void) + SYSLOG ((LOG_INFO, + "delete '%s' from shadow group '%s'", +@@ -941,9 +951,10 @@ update_gshadow(const struct sgrp *sgrp) + nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); + changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to shadow group", +- user_newname, AUDIT_NO_ID, 1); ++ audit_logger_with_group (AUDIT_USER_MGMT, Prog, ++ "add-user-to-shadow-group", ++ user_newname, AUDIT_NO_ID, ++ nsgrp->sg_name, 1); + #endif + SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", + user_newname, nsgrp->sg_name)); +@@ -1852,8 +1863,8 @@ static void move_home (void) #ifdef WITH_AUDIT if (uflg || gflg) { @@ -1982,7 +1982,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -1855,8 +1866,8 @@ static void move_home (void) +@@ -1871,8 +1882,8 @@ static void move_home (void) fail_exit (E_HOMEDIR); } #ifdef WITH_AUDIT @@ -1993,7 +1993,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); #endif return; -@@ -1883,9 +1894,9 @@ static void move_home (void) +@@ -1899,9 +1910,9 @@ static void move_home (void) Prog, prefix_user_home); } #ifdef WITH_AUDIT @@ -2005,7 +2005,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); -@@ -2109,8 +2120,8 @@ static void move_mailbox (void) +@@ -2125,8 +2136,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2016,7 +2016,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } #endif -@@ -2133,8 +2144,8 @@ static void move_mailbox (void) +@@ -2149,8 +2160,8 @@ static void move_mailbox (void) } #ifdef WITH_AUDIT else { @@ -2027,7 +2027,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_newname, user_newid, 1); } -@@ -2331,8 +2342,8 @@ int main (int argc, char **argv) +@@ -2347,8 +2358,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); #ifdef WITH_AUDIT @@ -2038,7 +2038,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2344,8 +2355,8 @@ int main (int argc, char **argv) +@@ -2360,8 +2371,8 @@ int main (int argc, char **argv) _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), Prog, user_name); #ifdef WITH_AUDIT @@ -2049,7 +2049,7 @@ diff -up shadow-4.15.0/src/usermod.c.audit-update shadow-4.15.0/src/usermod.c user_name, user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ -@@ -2388,8 +2399,8 @@ int main (int argc, char **argv) +@@ -2404,8 +2415,8 @@ int main (int argc, char **argv) */ #ifdef WITH_AUDIT if (uflg || gflg) { diff --git a/shadow-4.15.1-sast-fixes.patch b/shadow-4.15.1-sast-fixes.patch new file mode 100644 index 0000000..e674ebf --- /dev/null +++ b/shadow-4.15.1-sast-fixes.patch @@ -0,0 +1,1413 @@ +From 4c16416ebc5f0958d58a1ea1e7890eafd9f8bb75 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Wed, 15 May 2024 12:25:51 +0200 +Subject: [PATCH 01/16] port: fix OVERRUN (CWE-119) + +``` +shadow-4.15.0/lib/port.c:154:2: alias: Assigning: "port.pt_names" = "ttys". "port.pt_names" now points to element 0 of "ttys" (which consists of 65 8-byte elements). +shadow-4.15.0/lib/port.c:155:2: cond_const: Checking "j < 64" implies that "j" is 64 on the false branch. +shadow-4.15.0/lib/port.c:175:2: overrun-local: Overrunning array of 65 8-byte elements at element index 65 (byte offset 527) by dereferencing pointer "port.pt_names + (j + 1)". +173| *cp = '\0'; +174| cp++; +175|-> port.pt_names[j + 1] = NULL; +176| +177| /* +``` + +Resolves: https://issues.redhat.com/browse/RHEL-35383 + +Signed-off-by: Iker Pedrosa +Reviewed-by: Alejandro Colomar +--- + lib/port.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/port.c b/lib/port.c +index 05b95651..60ff8989 100644 +--- a/lib/port.c ++++ b/lib/port.c +@@ -168,7 +168,7 @@ again: + } + *cp = '\0'; + cp++; +- port.pt_names[j + 1] = NULL; ++ port.pt_names[j] = NULL; + + /* + * Get the list of user names. It is the second colon +-- +2.45.1 + + +From f8fc6371f69930bbd5801284256e182ba35ced2a Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 14:05:31 +0200 +Subject: [PATCH 02/16] src/useradd.c: set_defaults(): Fix order of clean-ups + +Resources should be freed in the inverse order of the allocation. +This refactor prepares for the following commits, which fix some leaks. + +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 88d8ab7f..56a74559 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -745,10 +745,9 @@ static int set_defaults (void) + def_create_mail_spool, def_log_init)); + ret = 0; + setdef_err: +- free(new_file); +- if (prefix[0]) { ++ if (prefix[0]) + free(default_file); +- } ++ free(new_file); + + return ret; + } +-- +2.45.1 + + +From 37ae8827a0869ee4a723954c3c9e7c48165d9b50 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 14:28:50 +0200 +Subject: [PATCH 03/16] src/useradd.c: set_defaults(): Rename goto label + +This will help add other labels in the following commits. + +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 56a74559..bc72e6bc 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -558,7 +558,7 @@ static int set_defaults (void) + fprintf(stderr, + _("%s: cannot create new defaults file: %s\n"), + Prog, strerror(errno)); +- goto setdef_err; ++ goto err_free_def; + } + } + +@@ -567,7 +567,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: cannot create directory for defaults file\n"), + Prog); +- goto setdef_err; ++ goto err_free_def; + } + + ret = mkdir(dirname(new_file_dup), 0755); +@@ -576,7 +576,7 @@ static int set_defaults (void) + _("%s: cannot create directory for defaults file\n"), + Prog); + free(new_file_dup); +- goto setdef_err; ++ goto err_free_def; + } + free(new_file_dup); + +@@ -588,7 +588,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: cannot create new defaults file\n"), + Prog); +- goto setdef_err; ++ goto err_free_def; + } + + ofp = fdopen (ofd, "w"); +@@ -596,7 +596,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: cannot open new defaults file\n"), + Prog); +- goto setdef_err; ++ goto err_free_def; + } + + /* +@@ -623,7 +623,7 @@ static int set_defaults (void) + _("%s: line too long in %s: %s..."), + Prog, default_file, buf); + (void) fclose (ifp); +- goto setdef_err; ++ goto err_free_def; + } + } + +@@ -702,9 +702,10 @@ static int set_defaults (void) + (void) fflush (ofp); + if ( (ferror (ofp) != 0) + || (fsync (fileno (ofp)) != 0) +- || (fclose (ofp) != 0)) { ++ || (fclose (ofp) != 0)) ++ { + unlink (new_file); +- goto setdef_err; ++ goto err_free_def; + } + + /* +@@ -718,7 +719,7 @@ static int set_defaults (void) + _("%s: Cannot create backup file (%s): %s\n"), + Prog, buf, strerror (err)); + unlink (new_file); +- goto setdef_err; ++ goto err_free_def; + } + + /* +@@ -729,7 +730,7 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: rename: %s: %s\n"), + Prog, new_file, strerror (err)); +- goto setdef_err; ++ goto err_free_def; + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USYS_CONFIG, Prog, +@@ -744,7 +745,8 @@ static int set_defaults (void) + def_inactive, def_expire, def_template, + def_create_mail_spool, def_log_init)); + ret = 0; +- setdef_err: ++ ++err_free_def: + if (prefix[0]) + free(default_file); + free(new_file); +-- +2.45.1 + + +From 701fe4cf1aeac9e66fa949369c91d135dbf375d2 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 13:10:46 +0200 +Subject: [PATCH 04/16] src/useradd.c: set_defaults(): Do not free(3) the + result of asprintf(3) if it failed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +See asprintf(3): + +RETURN VALUE + When successful, these functions return the number of bytes + printed, just like sprintf(3). If memory allocation wasn’t possi‐ + ble, or some other error occurs, these functions will return -1, + and the contents of strp are undefined. + +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index bc72e6bc..6a3edfe3 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -558,7 +558,7 @@ static int set_defaults (void) + fprintf(stderr, + _("%s: cannot create new defaults file: %s\n"), + Prog, strerror(errno)); +- goto err_free_def; ++ goto err_free_new; + } + } + +@@ -749,6 +749,7 @@ static int set_defaults (void) + err_free_def: + if (prefix[0]) + free(default_file); ++err_free_new: + free(new_file); + + return ret; +-- +2.45.1 + + +From a74c4b6ae124a55cd272e574e0d056102f331e17 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 13:14:31 +0200 +Subject: [PATCH 05/16] src/useradd.c: De-duplicate code + +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 6a3edfe3..ad2676c1 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -571,14 +571,13 @@ static int set_defaults (void) + } + + ret = mkdir(dirname(new_file_dup), 0755); ++ free(new_file_dup); + if (-1 == ret && EEXIST != errno) { + fprintf (stderr, + _("%s: cannot create directory for defaults file\n"), + Prog); +- free(new_file_dup); + goto err_free_def; + } +- free(new_file_dup); + + /* + * Create a temporary file to copy the new output to. +-- +2.45.1 + + +From e7d1508e076bbf4053faacc0370c6fe43d9c8f04 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 13:40:58 +0200 +Subject: [PATCH 06/16] src/useradd.c: Add fmkstemp() to fix file-descriptor + leak + +This function creates a temporary file, and returns a FILE pointer to +it. This avoids dealing with both a file descriptor and a FILE pointer, +and correctly deallocating the resources on error. + +The code before this patch was leaking the file descriptor if fdopen(3) +failed. + +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 34 ++++++++++++++++++++++++---------- + 1 file changed, 24 insertions(+), 10 deletions(-) + +diff --git a/src/useradd.c b/src/useradd.c +index ad2676c1..e0238457 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -238,6 +238,9 @@ static void create_home (void); + static void create_mail (void); + static void check_uid_range(int rflg, uid_t user_id); + ++static FILE *fmkstemp(char *template); ++ ++ + /* + * fail_exit - undo as much as possible + */ +@@ -524,7 +527,6 @@ static void show_defaults (void) + */ + static int set_defaults (void) + { +- int ofd; + int ret = -1; + bool out_group = false; + bool out_groups = false; +@@ -582,15 +584,7 @@ static int set_defaults (void) + /* + * Create a temporary file to copy the new output to. + */ +- ofd = mkstemp (new_file); +- if (-1 == ofd) { +- fprintf (stderr, +- _("%s: cannot create new defaults file\n"), +- Prog); +- goto err_free_def; +- } +- +- ofp = fdopen (ofd, "w"); ++ ofp = fmkstemp(new_file); + if (NULL == ofp) { + fprintf (stderr, + _("%s: cannot open new defaults file\n"), +@@ -2752,3 +2746,23 @@ int main (int argc, char **argv) + return E_SUCCESS; + } + ++ ++static FILE * ++fmkstemp(char *template) ++{ ++ int fd; ++ FILE *fp; ++ ++ fd = mkstemp(template); ++ if (fd == -1) ++ return NULL; ++ ++ fp = fdopen(fd, "w"); ++ if (fp == NULL) { ++ close(fd); ++ unlink(template); ++ return NULL; ++ } ++ ++ return fp; ++} +-- +2.45.1 + + +From 1ee066ae1e5b39ac42120ad0f6f8af0f102db952 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 13:52:07 +0200 +Subject: [PATCH 07/16] src/useradd.c: set_defaults(): Fix FILE* leak + +Report: +> shadow-4.15.0/src/useradd.c:575:2: alloc_fn: Storage is returned from allocation function "fdopen". +> shadow-4.15.0/src/useradd.c:575:2: var_assign: Assigning: "ofp" = storage returned from "fdopen(ofd, "w")". +> shadow-4.15.0/src/useradd.c:734:2: leaked_storage: Variable "ofp" going out of scope leaks the storage it points to. +> 732| } +> 733| +> 734|-> return ret; +> 735| } +> 736| + +Link: +Reported-by: Iker Pedrosa +Reviewed-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/useradd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index e0238457..347334a6 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -615,7 +615,8 @@ static int set_defaults (void) + fprintf (stderr, + _("%s: line too long in %s: %s..."), + Prog, default_file, buf); +- (void) fclose (ifp); ++ fclose(ifp); ++ fclose(ofp); + goto err_free_def; + } + } +-- +2.45.1 + + +From 151f14ad69de8100d25c1974947d53ae40d1448a Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 16 May 2024 13:52:15 +0200 +Subject: [PATCH 08/16] src/usermod.c: Reduce scope of local variables + +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 0fcf0325..57b58f5b 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -687,11 +687,8 @@ fail_exit (int code) + + static void update_group (void) + { +- bool is_member; +- bool was_member; +- bool changed; +- const struct group *grp; +- struct group *ngrp; ++ bool changed; ++ const struct group *grp; + + changed = false; + +@@ -700,6 +697,9 @@ static void update_group (void) + * the user is a member of. + */ + while ((grp = gr_next ()) != NULL) { ++ bool is_member; ++ bool was_member; ++ struct group *ngrp; + /* + * See if the user specified this group as one of their + * concurrent groups. +@@ -799,12 +799,8 @@ static void update_group (void) + #ifdef SHADOWGRP + static void update_gshadow (void) + { +- bool is_member; +- bool was_member; +- bool was_admin; +- bool changed; +- const struct sgrp *sgrp; +- struct sgrp *nsgrp; ++ bool changed; ++ const struct sgrp *sgrp; + + changed = false; + +@@ -813,6 +809,10 @@ static void update_gshadow (void) + * that the user is a member of. + */ + while ((sgrp = sgr_next ()) != NULL) { ++ bool is_member; ++ bool was_member; ++ bool was_admin; ++ struct sgrp *nsgrp; + + /* + * See if the user was a member of this group +-- +2.45.1 + + +From b089a63ab38f69c32d099320fe8181802f7f4092 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 16 May 2024 13:49:34 +0200 +Subject: [PATCH 09/16] src/usermod.c: Rename update_group() => + update_group_file() + +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 57b58f5b..aaa83d7d 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -178,7 +178,7 @@ NORETURN static void usage (int status); + static void new_pwent (struct passwd *); + static void new_spent (struct spwd *); + NORETURN static void fail_exit (int); +-static void update_group (void); ++static void update_group_file(void); + + #ifdef SHADOWGRP + static void update_gshadow (void); +@@ -685,7 +685,8 @@ fail_exit (int code) + } + + +-static void update_group (void) ++static void ++update_group_file(void) + { + bool changed; + const struct group *grp; +@@ -950,7 +951,7 @@ static void update_gshadow (void) + */ + static void grp_update (void) + { +- update_group (); ++ update_group_file(); + #ifdef SHADOWGRP + if (is_shadow_grp) { + update_gshadow (); +-- +2.45.1 + + +From 81bc78ec5cdd59790bc7c591c9d1f66bd4d7b78e Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 02:11:22 +0200 +Subject: [PATCH 10/16] src/usermod.c: Rename update_gshadow() => + update_gshadow_file() + +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index aaa83d7d..3048f801 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -181,7 +181,7 @@ NORETURN static void fail_exit (int); + static void update_group_file(void); + + #ifdef SHADOWGRP +-static void update_gshadow (void); ++static void update_gshadow_file(void); + #endif + static void grp_update (void); + +@@ -798,7 +798,8 @@ update_group_file(void) + } + + #ifdef SHADOWGRP +-static void update_gshadow (void) ++static void ++update_gshadow_file(void) + { + bool changed; + const struct sgrp *sgrp; +@@ -954,7 +955,7 @@ static void grp_update (void) + update_group_file(); + #ifdef SHADOWGRP + if (is_shadow_grp) { +- update_gshadow (); ++ update_gshadow_file(); + } + #endif + } +-- +2.45.1 + + +From 61964aa06b9e6e0643a6519f64290f18ac04867f Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 16 May 2024 13:54:06 +0200 +Subject: [PATCH 11/16] src/usermod.c: update_group_file(): Fix RESOURCE_LEAK + (CWE-772) + +Report: +> shadow-4.15.0/src/usermod.c:734:3: alloc_fn: Storage is returned from allocation function "__gr_dup". +> shadow-4.15.0/src/usermod.c:734:3: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)". +> shadow-4.15.0/src/usermod.c:815:1: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to. +> 813| gr_free(ngrp); +> 814| } +> 815|-> } +> 816| +> 817| #ifdef SHADOWGRP + +Link: https://issues.redhat.com/browse/RHEL-35383 +Reported-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 3048f801..e0cfdd83 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -780,9 +780,8 @@ update_group_file(void) + SYSLOG ((LOG_INFO, "add '%s' to group '%s'", + user_newname, ngrp->gr_name)); + } +- if (!changed) { +- continue; +- } ++ if (!changed) ++ goto free_ngrp; + + changed = false; + if (gr_update (ngrp) == 0) { +@@ -793,6 +792,7 @@ update_group_file(void) + fail_exit (E_GRP_UPDATE); + } + ++free_ngrp: + gr_free(ngrp); + } + } +-- +2.45.1 + + +From 71a3238b7996285fc3c8dec841244ba95d663fa5 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 02:15:15 +0200 +Subject: [PATCH 12/16] src/usermod.c: update_gshadow_file(): Fix RESOURCE_LEAK + (CWE-772) + +Report: +> shadow-4.15.0/src/usermod.c:864:3: alloc_fn: Storage is returned from allocation function "__sgr_dup". +> shadow-4.15.0/src/usermod.c:864:3: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)". +> shadow-4.15.0/src/usermod.c:964:1: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to. +> 962| free (nsgrp); +> 963| } +> 964|-> } +> 965| #endif /* SHADOWGRP */ +> 966| + +Link: https://issues.redhat.com/browse/RHEL-35383 +Reported-by: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index e0cfdd83..bb5d3535 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -921,9 +921,8 @@ update_gshadow_file(void) + SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", + user_newname, nsgrp->sg_name)); + } +- if (!changed) { +- continue; +- } ++ if (!changed) ++ goto free_nsgrp; + + changed = false; + +@@ -939,6 +938,7 @@ update_gshadow_file(void) + fail_exit (E_GRP_UPDATE); + } + ++free_nsgrp: + free (nsgrp); + } + } +-- +2.45.1 + + +From 68d42a8fbe42b89cf13d3f672ad8502dbaf05835 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 16 May 2024 14:02:54 +0200 +Subject: [PATCH 13/16] src/usermod.c: update_group_file(): Reduce scope of + local variable + +After _every_ iteration, 'changed' is always 'false'. We don't need to +have it outside of the loop. + +See: + +$ grepc update_group_file . \ +| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ +| pcre2grep -v -M '{\n\t*}'; +{ + bool changed; + changed = false; + while ((grp = gr_next ()) != NULL) { + if (!was_member && !is_member) { + continue; + } + if (was_member) { + if ((!Gflg) || is_member) { + if (lflg) { + changed = true; + } + } else { + changed = true; + } + } else if (is_member) { + changed = true; + } + if (!changed) + goto free_ngrp; + changed = false; +free_ngrp: + } +} + +This was already true in the commit that introduced the code: + +$ git show 45c6603cc:src/usermod.c \ +| grepc update_group \ +| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ +| pcre2grep -v -M '{\n\t*}'; +{ + int changed; + changed = 0; + while ((grp = gr_next())) { + * See if the user specified this group as one of their + if (!was_member && !is_member) + continue; + if (was_member && (!Gflg || is_member)) { + if (lflg) { + changed = 1; + } + } else if (was_member && Gflg && !is_member) { + changed = 1; + } else if (!was_member && Gflg && is_member) { + changed = 1; + } + if (!changed) + continue; + changed = 0; + } +} + +Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index bb5d3535..30f47b8a 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -688,19 +688,20 @@ fail_exit (int code) + static void + update_group_file(void) + { +- bool changed; + const struct group *grp; + +- changed = false; +- + /* + * Scan through the entire group file looking for the groups that + * the user is a member of. + */ + while ((grp = gr_next ()) != NULL) { ++ bool changed; + bool is_member; + bool was_member; + struct group *ngrp; ++ ++ changed = false; ++ + /* + * See if the user specified this group as one of their + * concurrent groups. +@@ -783,7 +784,6 @@ update_group_file(void) + if (!changed) + goto free_ngrp; + +- changed = false; + if (gr_update (ngrp) == 0) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), +-- +2.45.1 + + +From da77a82ecbc90e89808f143e7fa2abb7650f50d7 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 02:19:46 +0200 +Subject: [PATCH 14/16] src/usermod.c: update_gshadow_file(): Reduce scope of + local variable + +After _every_ iteration, 'changed' is always 'false'. We don't need to +have it outside of the loop. + +See: + +$ grepc update_gshadow_file . \ +| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ +| pcre2grep -v -M '{\n\t*}'; +{ + bool changed; + changed = false; + while ((sgrp = sgr_next ()) != NULL) { + if (!was_member && !was_admin && !is_member) { + continue; + } + if (was_admin && lflg) { + changed = true; + } + if (was_member) { + if ((!Gflg) || is_member) { + if (lflg) { + changed = true; + } + } else { + changed = true; + } + } else if (is_member) { + changed = true; + } + if (!changed) + goto free_nsgrp; + changed = false; + } +} + +This was already true in the commit that introduced the code: + +$ git show 45c6603cc:src/usermod.c \ +| grepc update_gshadow \ +| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ +| pcre2grep -v -M '{\n\t*}'; +{ + int changed; + changed = 0; + while ((sgrp = sgr_next())) { + * See if the user was a member of this group + * See if the user was an administrator of this group + * See if the user specified this group as one of their + if (!was_member && !was_admin && !is_member) + continue; + if (was_admin && lflg) { + changed = 1; + } + if (was_member && (!Gflg || is_member)) { + if (lflg) { + changed = 1; + } + } else if (was_member && Gflg && !is_member) { + changed = 1; + } else if (!was_member && Gflg && is_member) { + changed = 1; + } + if (!changed) + continue; + changed = 0; + } +} + +Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 30f47b8a..7b1e0581 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -801,21 +801,21 @@ free_ngrp: + static void + update_gshadow_file(void) + { +- bool changed; + const struct sgrp *sgrp; + +- changed = false; +- + /* + * Scan through the entire shadow group file looking for the groups + * that the user is a member of. + */ + while ((sgrp = sgr_next ()) != NULL) { ++ bool changed; + bool is_member; + bool was_member; + bool was_admin; + struct sgrp *nsgrp; + ++ changed = false; ++ + /* + * See if the user was a member of this group + */ +@@ -924,8 +924,6 @@ update_gshadow_file(void) + if (!changed) + goto free_nsgrp; + +- changed = false; +- + /* + * Update the group entry to reflect the changes. + */ +-- +2.45.1 + + +From adf37cccd0fa4ce7d05644514b0af57fe71905c3 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 16 May 2024 14:12:09 +0200 +Subject: [PATCH 15/16] src/usermod.c: update_group(): Add helper function + +Keep the while loop in the outer function, and move the iteration code +to this new helper. This makes it a bit more readable. + +Cc: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 167 ++++++++++++++++++++++++++------------------------ + 1 file changed, 87 insertions(+), 80 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 7b1e0581..4ea11376 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -179,6 +179,7 @@ static void new_pwent (struct passwd *); + static void new_spent (struct spwd *); + NORETURN static void fail_exit (int); + static void update_group_file(void); ++static void update_group(const struct group *grp); + + #ifdef SHADOWGRP + static void update_gshadow_file(void); +@@ -694,109 +695,115 @@ update_group_file(void) + * Scan through the entire group file looking for the groups that + * the user is a member of. + */ +- while ((grp = gr_next ()) != NULL) { +- bool changed; +- bool is_member; +- bool was_member; +- struct group *ngrp; ++ while ((grp = gr_next()) != NULL) ++ update_group(grp); ++} + +- changed = false; + +- /* +- * See if the user specified this group as one of their +- * concurrent groups. +- */ +- was_member = is_on_list (grp->gr_mem, user_name); +- is_member = Gflg && ( (was_member && aflg) +- || is_on_list (user_groups, grp->gr_name)); ++static void ++update_group(const struct group *grp) ++{ ++ bool changed; ++ bool is_member; ++ bool was_member; ++ struct group *ngrp; + +- if (!was_member && !is_member) { +- continue; +- } ++ changed = false; + +- /* +- * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes +- * mentioned groups while leaving the others. +- */ +- if (Gflg && rflg) { +- is_member = !is_member; +- } ++ /* ++ * See if the user specified this group as one of their ++ * concurrent groups. ++ */ ++ was_member = is_on_list (grp->gr_mem, user_name); ++ is_member = Gflg && ( (was_member && aflg) ++ || is_on_list (user_groups, grp->gr_name)); + +- ngrp = __gr_dup (grp); +- if (NULL == ngrp) { +- fprintf (stderr, +- _("%s: Out of memory. Cannot update %s.\n"), +- Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } ++ if (!was_member && !is_member) ++ return; + +- if (was_member) { +- if ((!Gflg) || is_member) { +- /* User was a member and is still a member +- * of this group. +- * But the user might have been renamed. +- */ +- if (lflg) { +- ngrp->gr_mem = del_list (ngrp->gr_mem, +- user_name); +- ngrp->gr_mem = add_list (ngrp->gr_mem, +- user_newname); +- changed = true; +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing group member", +- user_newname, AUDIT_NO_ID, 1); +-#endif +- SYSLOG ((LOG_INFO, +- "change '%s' to '%s' in group '%s'", +- user_name, user_newname, +- ngrp->gr_name)); +- } +- } else { +- /* User was a member but is no more a +- * member of this group. +- */ +- ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); ++ /* ++ * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes ++ * mentioned groups while leaving the others. ++ */ ++ if (Gflg && rflg) { ++ is_member = !is_member; ++ } ++ ++ ngrp = __gr_dup (grp); ++ if (NULL == ngrp) { ++ fprintf (stderr, ++ _("%s: Out of memory. Cannot update %s.\n"), ++ Prog, gr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++ ++ if (was_member) { ++ if ((!Gflg) || is_member) { ++ /* User was a member and is still a member ++ * of this group. ++ * But the user might have been renamed. ++ */ ++ if (lflg) { ++ ngrp->gr_mem = del_list (ngrp->gr_mem, ++ user_name); ++ ngrp->gr_mem = add_list (ngrp->gr_mem, ++ user_newname); + changed = true; + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing group member", +- user_name, AUDIT_NO_ID, 1); ++ "changing group member", ++ user_newname, AUDIT_NO_ID, 1); + #endif + SYSLOG ((LOG_INFO, +- "delete '%s' from group '%s'", +- user_name, ngrp->gr_name)); ++ "change '%s' to '%s' in group '%s'", ++ user_name, user_newname, ++ ngrp->gr_name)); + } +- } else if (is_member) { +- /* User was not a member but is now a member this +- * group. ++ } else { ++ /* User was a member but is no more a ++ * member of this group. + */ +- ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); ++ ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); + changed = true; + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to group", +- user_name, AUDIT_NO_ID, 1); ++ "removing group member", ++ user_name, AUDIT_NO_ID, 1); + #endif +- SYSLOG ((LOG_INFO, "add '%s' to group '%s'", +- user_newname, ngrp->gr_name)); ++ SYSLOG ((LOG_INFO, ++ "delete '%s' from group '%s'", ++ user_name, ngrp->gr_name)); + } +- if (!changed) +- goto free_ngrp; ++ } else if (is_member) { ++ /* User was not a member but is now a member this ++ * group. ++ */ ++ ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); ++ changed = true; ++#ifdef WITH_AUDIT ++ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, ++ "adding user to group", ++ user_name, AUDIT_NO_ID, 1); ++#endif ++ SYSLOG ((LOG_INFO, "add '%s' to group '%s'", ++ user_newname, ngrp->gr_name)); ++ } ++ if (!changed) ++ goto free_ngrp; + +- if (gr_update (ngrp) == 0) { +- fprintf (stderr, +- _("%s: failed to prepare the new %s entry '%s'\n"), +- Prog, gr_dbname (), ngrp->gr_name); +- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); +- fail_exit (E_GRP_UPDATE); +- } ++ if (gr_update (ngrp) == 0) { ++ fprintf (stderr, ++ _("%s: failed to prepare the new %s entry '%s'\n"), ++ Prog, gr_dbname (), ngrp->gr_name); ++ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); ++ fail_exit (E_GRP_UPDATE); ++ } + + free_ngrp: +- gr_free(ngrp); +- } ++ gr_free(ngrp); + } + ++ + #ifdef SHADOWGRP + static void + update_gshadow_file(void) +-- +2.45.1 + + +From d8e6a8b99b4d844328d875287babf6e13860d464 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 17 May 2024 02:29:46 +0200 +Subject: [PATCH 16/16] src/usermod.c: update_gshadow(): Add helper function + +Keep the while loop in the outer function, and move the iteration code +to this new helper. This makes it a bit more readable. + +Cc: Iker Pedrosa +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 223 ++++++++++++++++++++++++++------------------------ + 1 file changed, 116 insertions(+), 107 deletions(-) + +diff --git a/src/usermod.c b/src/usermod.c +index 4ea11376..f8896984 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -183,6 +183,7 @@ static void update_group(const struct group *grp); + + #ifdef SHADOWGRP + static void update_gshadow_file(void); ++static void update_gshadow(const struct sgrp *sgrp); + #endif + static void grp_update (void); + +@@ -814,141 +815,149 @@ update_gshadow_file(void) + * Scan through the entire shadow group file looking for the groups + * that the user is a member of. + */ +- while ((sgrp = sgr_next ()) != NULL) { +- bool changed; +- bool is_member; +- bool was_member; +- bool was_admin; +- struct sgrp *nsgrp; ++ while ((sgrp = sgr_next()) != NULL) ++ update_gshadow(sgrp); ++} ++#endif /* SHADOWGRP */ + +- changed = false; + +- /* +- * See if the user was a member of this group +- */ +- was_member = is_on_list (sgrp->sg_mem, user_name); ++#ifdef SHADOWGRP ++static void ++update_gshadow(const struct sgrp *sgrp) ++{ ++ bool changed; ++ bool is_member; ++ bool was_member; ++ bool was_admin; ++ struct sgrp *nsgrp; + +- /* +- * See if the user was an administrator of this group +- */ +- was_admin = is_on_list (sgrp->sg_adm, user_name); ++ changed = false; + +- /* +- * See if the user specified this group as one of their +- * concurrent groups. +- */ +- is_member = Gflg && ( (was_member && aflg) +- || is_on_list (user_groups, sgrp->sg_name)); ++ /* ++ * See if the user was a member of this group ++ */ ++ was_member = is_on_list (sgrp->sg_mem, user_name); + +- if (!was_member && !was_admin && !is_member) { +- continue; +- } ++ /* ++ * See if the user was an administrator of this group ++ */ ++ was_admin = is_on_list (sgrp->sg_adm, user_name); + +- /* +- * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted +- * groups while leaving the user apart of groups not mentioned +- */ +- if (Gflg && rflg) { +- is_member = !is_member; +- } ++ /* ++ * See if the user specified this group as one of their ++ * concurrent groups. ++ */ ++ is_member = Gflg && ( (was_member && aflg) ++ || is_on_list (user_groups, sgrp->sg_name)); + +- nsgrp = __sgr_dup (sgrp); +- if (NULL == nsgrp) { +- fprintf (stderr, +- _("%s: Out of memory. Cannot update %s.\n"), +- Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); +- } ++ if (!was_member && !was_admin && !is_member) ++ return; + +- if (was_admin && lflg) { +- /* User was an admin of this group but the user +- * has been renamed. +- */ +- nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); +- nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); +- changed = true; +-#ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing admin name in shadow group", +- user_name, AUDIT_NO_ID, 1); +-#endif +- SYSLOG ((LOG_INFO, +- "change admin '%s' to '%s' in shadow group '%s'", +- user_name, user_newname, nsgrp->sg_name)); +- } +- +- if (was_member) { +- if ((!Gflg) || is_member) { +- /* User was a member and is still a member +- * of this group. +- * But the user might have been renamed. +- */ +- if (lflg) { +- nsgrp->sg_mem = del_list (nsgrp->sg_mem, +- user_name); +- nsgrp->sg_mem = add_list (nsgrp->sg_mem, +- user_newname); +- changed = true; ++ /* ++ * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted ++ * groups while leaving the user apart of groups not mentioned ++ */ ++ if (Gflg && rflg) { ++ is_member = !is_member; ++ } ++ ++ nsgrp = __sgr_dup (sgrp); ++ if (NULL == nsgrp) { ++ fprintf (stderr, ++ _("%s: Out of memory. Cannot update %s.\n"), ++ Prog, sgr_dbname ()); ++ fail_exit (E_GRP_UPDATE); ++ } ++ ++ if (was_admin && lflg) { ++ /* User was an admin of this group but the user ++ * has been renamed. ++ */ ++ nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); ++ nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); ++ changed = true; + #ifdef WITH_AUDIT +- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "changing member in shadow group", +- user_name, AUDIT_NO_ID, 1); ++ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, ++ "changing admin name in shadow group", ++ user_name, AUDIT_NO_ID, 1); + #endif +- SYSLOG ((LOG_INFO, +- "change '%s' to '%s' in shadow group '%s'", +- user_name, user_newname, +- nsgrp->sg_name)); +- } +- } else { +- /* User was a member but is no more a +- * member of this group. +- */ +- nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); ++ SYSLOG ((LOG_INFO, ++ "change admin '%s' to '%s' in shadow group '%s'", ++ user_name, user_newname, nsgrp->sg_name)); ++ } ++ ++ if (was_member) { ++ if ((!Gflg) || is_member) { ++ /* User was a member and is still a member ++ * of this group. ++ * But the user might have been renamed. ++ */ ++ if (lflg) { ++ nsgrp->sg_mem = del_list (nsgrp->sg_mem, ++ user_name); ++ nsgrp->sg_mem = add_list (nsgrp->sg_mem, ++ user_newname); + changed = true; + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "removing user from shadow group", +- user_name, AUDIT_NO_ID, 1); ++ "changing member in shadow group", ++ user_name, AUDIT_NO_ID, 1); + #endif + SYSLOG ((LOG_INFO, +- "delete '%s' from shadow group '%s'", +- user_name, nsgrp->sg_name)); ++ "change '%s' to '%s' in shadow group '%s'", ++ user_name, user_newname, ++ nsgrp->sg_name)); + } +- } else if (is_member) { +- /* User was not a member but is now a member this +- * group. ++ } else { ++ /* User was a member but is no more a ++ * member of this group. + */ +- nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); ++ nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + changed = true; + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_CHAUTHTOK, Prog, +- "adding user to shadow group", +- user_newname, AUDIT_NO_ID, 1); ++ "removing user from shadow group", ++ user_name, AUDIT_NO_ID, 1); + #endif +- SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", +- user_newname, nsgrp->sg_name)); ++ SYSLOG ((LOG_INFO, ++ "delete '%s' from shadow group '%s'", ++ user_name, nsgrp->sg_name)); + } +- if (!changed) +- goto free_nsgrp; +- +- /* +- * Update the group entry to reflect the changes. ++ } else if (is_member) { ++ /* User was not a member but is now a member this ++ * group. + */ +- if (sgr_update (nsgrp) == 0) { +- fprintf (stderr, +- _("%s: failed to prepare the new %s entry '%s'\n"), +- Prog, sgr_dbname (), nsgrp->sg_name); +- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", +- sgr_dbname (), nsgrp->sg_name)); +- fail_exit (E_GRP_UPDATE); +- } ++ nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); ++ changed = true; ++#ifdef WITH_AUDIT ++ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, ++ "adding user to shadow group", ++ user_newname, AUDIT_NO_ID, 1); ++#endif ++ SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", ++ user_newname, nsgrp->sg_name)); ++ } ++ if (!changed) ++ goto free_nsgrp; + +-free_nsgrp: +- free (nsgrp); ++ /* ++ * Update the group entry to reflect the changes. ++ */ ++ if (sgr_update (nsgrp) == 0) { ++ fprintf (stderr, ++ _("%s: failed to prepare the new %s entry '%s'\n"), ++ Prog, sgr_dbname (), nsgrp->sg_name); ++ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", ++ sgr_dbname (), nsgrp->sg_name)); ++ fail_exit (E_GRP_UPDATE); + } ++ ++free_nsgrp: ++ free (nsgrp); + } + #endif /* SHADOWGRP */ + ++ + /* + * grp_update - add user to secondary group set + * +-- +2.45.1 + diff --git a/shadow-utils.spec b/shadow-utils.spec index ad712a1..c361429 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.1 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -22,12 +22,14 @@ Source7: passwd.pamd Patch0: shadow-4.15.0-manfix.patch # Date parsing improvement - could be upstreamed Patch1: shadow-4.15.0-date-parsing.patch +# Several patches already available upstream. PRs:#994, #996, #997 +Patch2: shadow-4.15.1-sast-fixes.patch # Audit message changes - partially upstreamed -Patch2: shadow-4.15.0-audit-update.patch +Patch3: shadow-4.15.1-audit-update.patch # Probably non-upstreamable -Patch3: shadow-4.15.0-account-tools-setuid.patch +Patch4: shadow-4.15.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/ead55e9ba8958504e23e29545f90c4dd925c7462 -Patch4: shadow-4.15.0-getdef-spurious-error.patch +Patch5: shadow-4.15.0-getdef-spurious-error.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -293,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon May 20 2024 Iker Pedrosa - 2:4.15.1-5 +- Several fixes for issues detected by static analyzer tools + * Thu Apr 11 2024 Zbigniew Jedrzejewski-Szmek - 2:4.15.1-4 - Fix build with %%_bindir==%%_sbindir - Add virtual Provides for old file paths used by other packages From e3591abba01fcc215e0622d58f4dec51d5f815e0 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 30 May 2024 16:01:39 +0200 Subject: [PATCH 071/118] chpasswd: use PAM again Resolves: #2283963 Signed-off-by: Iker Pedrosa --- shadow-4.15.0-account-tools-setuid.patch | 79 ------------------------ shadow-utils.spec | 5 +- 2 files changed, 4 insertions(+), 80 deletions(-) diff --git a/shadow-4.15.0-account-tools-setuid.patch b/shadow-4.15.0-account-tools-setuid.patch index d162487..5ab6406 100644 --- a/shadow-4.15.0-account-tools-setuid.patch +++ b/shadow-4.15.0-account-tools-setuid.patch @@ -1,82 +1,3 @@ -diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chpasswd.c ---- shadow-4.15.0/src/chpasswd.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/chpasswd.c 2024-03-11 11:21:57.561150382 +0100 -@@ -443,9 +443,11 @@ int main (int argc, char **argv) - char *cp; - const char *salt; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - bool use_pam = true; - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - int errors = 0; - int line = 0; -@@ -469,19 +471,23 @@ int main (int argc, char **argv) - process_root_flag ("-R", argc, argv); - prefix = process_prefix_flag ("-P", argc, argv); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (md5flg || eflg || cflg || prefix[0]) { - use_pam = false; - } - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - OPENLOG (Prog); - - check_perms (); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - is_shadow_pwd = spw_file_present (); - -@@ -543,6 +549,7 @@ int main (int argc, char **argv) - } - newpwd = cp; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (use_pam) { - if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { -@@ -553,6 +560,7 @@ int main (int argc, char **argv) - } - } else - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - const struct spwd *sp; - struct spwd newsp; -@@ -672,9 +680,11 @@ int main (int argc, char **argv) - * password database. - */ - if (0 != errors) { -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - fprintf (stderr, - _("%s: error detected, changes ignored\n"), -@@ -683,9 +693,11 @@ int main (int argc, char **argv) - fail_exit (1); - } - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - /* Save the changes */ - close_files (); diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/groupmems.c --- shadow-4.15.0/src/groupmems.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 +++ shadow-4.15.0/src/groupmems.c 2024-03-11 11:16:18.365408572 +0100 diff --git a/shadow-utils.spec b/shadow-utils.spec index c361429..53fe61b 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.1 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -295,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu May 30 2024 Iker Pedrosa - 2:4.15.1-6 +- chpasswd: use PAM again (#2283963) + * Mon May 20 2024 Iker Pedrosa - 2:4.15.1-5 - Several fixes for issues detected by static analyzer tools From 99c074978fd6ebe2cfe8ae8922cfb541fb0979b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 9 Jul 2024 13:56:48 +0200 Subject: [PATCH 072/118] Rebuilt for the bin-sbin merge https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 53fe61b..3b9232d 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.1 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -295,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek - 2:4.15.1-7 +- Rebuilt for the bin-sbin merge + * Thu May 30 2024 Iker Pedrosa - 2:4.15.1-6 - chpasswd: use PAM again (#2283963) From 3f78d723fa1ad792c4e3d6fa949d89d80603aebe Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 20 Jul 2024 05:23:05 +0000 Subject: [PATCH 073/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 3b9232d..f1bdda5 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.1 -Release: 7%{?dist} +Release: 8%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -295,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jul 20 2024 Fedora Release Engineering - 2:4.15.1-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek - 2:4.15.1-7 - Rebuilt for the bin-sbin merge From 029086935e7eb96ea4e9f1e86984caaa113c593d Mon Sep 17 00:00:00 2001 From: Kevin Fenzi Date: Tue, 23 Jul 2024 14:03:06 -0700 Subject: [PATCH 074/118] Revert chpasswd: use PAM again for now. Revert chpasswd: use PAM again for now. Revert chpasswd: use PAM again for now. --- shadow-4.15.0-account-tools-setuid.patch | 79 ++++++++++++++++++++++++ shadow-utils.spec | 5 +- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/shadow-4.15.0-account-tools-setuid.patch b/shadow-4.15.0-account-tools-setuid.patch index 5ab6406..d162487 100644 --- a/shadow-4.15.0-account-tools-setuid.patch +++ b/shadow-4.15.0-account-tools-setuid.patch @@ -1,3 +1,82 @@ +diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chpasswd.c +--- shadow-4.15.0/src/chpasswd.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 ++++ shadow-4.15.0/src/chpasswd.c 2024-03-11 11:21:57.561150382 +0100 +@@ -443,9 +443,11 @@ int main (int argc, char **argv) + char *cp; + const char *salt; + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + bool use_pam = true; + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + int errors = 0; + int line = 0; +@@ -469,19 +471,23 @@ int main (int argc, char **argv) + process_root_flag ("-R", argc, argv); + prefix = process_prefix_flag ("-P", argc, argv); + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (md5flg || eflg || cflg || prefix[0]) { + use_pam = false; + } + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + + OPENLOG (Prog); + + check_perms (); + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + is_shadow_pwd = spw_file_present (); + +@@ -543,6 +549,7 @@ int main (int argc, char **argv) + } + newpwd = cp; + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (use_pam) { + if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { +@@ -553,6 +560,7 @@ int main (int argc, char **argv) + } + } else + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + const struct spwd *sp; + struct spwd newsp; +@@ -672,9 +680,11 @@ int main (int argc, char **argv) + * password database. + */ + if (0 != errors) { ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + fprintf (stderr, + _("%s: error detected, changes ignored\n"), +@@ -683,9 +693,11 @@ int main (int argc, char **argv) + fail_exit (1); + } + ++#ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + if (!use_pam) + #endif /* USE_PAM */ ++#endif /* ACCT_TOOLS_SETUID */ + { + /* Save the changes */ + close_files (); diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/groupmems.c --- shadow-4.15.0/src/groupmems.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 +++ shadow-4.15.0/src/groupmems.c 2024-03-11 11:16:18.365408572 +0100 diff --git a/shadow-utils.spec b/shadow-utils.spec index f1bdda5..e3cd026 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.1 -Release: 8%{?dist} +Release: 9%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -295,6 +295,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jul 23 2024 Kevin Fenzi - 2:4.15.1-9 +- Revert chpasswd: use PAM again for now. + * Sat Jul 20 2024 Fedora Release Engineering - 2:4.15.1-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild From c3bc52a4f1222196953759c8bd3ef64ff81095fe Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 13 Aug 2024 09:57:02 +0200 Subject: [PATCH 075/118] Rebase to version 4.16.0 Resolves: #2293678 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.15.0-getdef-spurious-error.patch | 137 -- shadow-4.15.1-audit-update.patch | 13 +- shadow-4.15.1-sast-fixes.patch | 1413 --------------------- shadow-utils.spec | 15 +- sources | 4 +- 6 files changed, 13 insertions(+), 1571 deletions(-) delete mode 100644 shadow-4.15.0-getdef-spurious-error.patch delete mode 100644 shadow-4.15.1-sast-fixes.patch diff --git a/.gitignore b/.gitignore index 5db8705..08e3c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.15.0.tar.xz.asc /shadow-4.15.1.tar.xz /shadow-4.15.1.tar.xz.asc +/shadow-4.16.0.tar.xz +/shadow-4.16.0.tar.xz.asc diff --git a/shadow-4.15.0-getdef-spurious-error.patch b/shadow-4.15.0-getdef-spurious-error.patch deleted file mode 100644 index 9cec295..0000000 --- a/shadow-4.15.0-getdef-spurious-error.patch +++ /dev/null @@ -1,137 +0,0 @@ -From ead55e9ba8958504e23e29545f90c4dd925c7462 Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Wed, 20 Mar 2024 17:39:46 -0500 -Subject: [PATCH] getdef: avoid spurious error messages about unknown - configuration options - -def_find can return NULL for unset, not just unknown, config options. So -move the decision of whether to log an error message about an unknown config -option back into def_find, which knows the difference. Only putdef_str() -will pass a char* srcfile to def_find, so only calls from putdef_str will -cause the message, which was the original intent of fa68441bc4be8. - -closes #967 - -fixes: fa68441bc4be8 ("Improve the login.defs unknown item error message") -Signed-off-by: Serge Hallyn ---- - lib/getdef.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) - -diff --git a/lib/getdef.c b/lib/getdef.c -index 4d4d4e19..ef2ae1f0 100644 ---- a/lib/getdef.c -+++ b/lib/getdef.c -@@ -176,7 +176,7 @@ static const char* def_fname = LOGINDEFS; /* login config defs file */ - static bool def_loaded = false; /* are defs already loaded? */ - - /* local function prototypes */ --static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *); -+static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *, const char *); - static void def_load (void); - - -@@ -195,7 +195,7 @@ static void def_load (void); - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - return (NULL == d) ? NULL : d->value; - } - -@@ -214,7 +214,7 @@ bool getdef_bool (const char *item) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return false; - } -@@ -240,7 +240,7 @@ int getdef_num (const char *item, int dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -275,7 +275,7 @@ unsigned int getdef_unum (const char *item, unsigned int dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -310,7 +310,7 @@ long getdef_long (const char *item, long dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -342,7 +342,7 @@ unsigned long getdef_ulong (const char *item, unsigned long dflt) - def_load (); - } - -- d = def_find (item); -+ d = def_find (item, NULL); - if ((NULL == d) || (NULL == d->value)) { - return dflt; - } -@@ -375,12 +375,9 @@ int putdef_str (const char *name, const char *value, const char *srcfile) - * Locate the slot to save the value. If this parameter - * is unknown then "def_find" will print an err message. - */ -- d = def_find (name); -- if (NULL == d) { -- if (NULL != srcfile) -- SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); -+ d = def_find (name, srcfile); -+ if (NULL == d) - return -1; -- } - - /* - * Save off the value. -@@ -404,9 +401,12 @@ int putdef_str (const char *name, const char *value, const char *srcfile) - * - * Search through a table of configurable items to locate the - * specified configuration option. -+ * -+ * If srcfile is not NULL, and the item is not found, then report an error saying -+ * the unknown item was used in this file. - */ - --static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) -+static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name, const char *srcfile) - { - struct itemdef *ptr; - -@@ -432,6 +432,8 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name) - fprintf (shadow_logfd, - _("configuration error - unknown item '%s' (notify administrator)\n"), - name); -+ if (srcfile != NULL) -+ SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile)); - - out: - return NULL; -@@ -610,7 +612,7 @@ int main (int argc, char **argv) - def_load (); - - for (i = 0; i < NUMDEFS; ++i) { -- d = def_find (def_table[i].name); -+ d = def_find (def_table[i].name, NULL); - if (NULL == d) { - printf ("error - lookup '%s' failed\n", - def_table[i].name); --- -2.44.0 - diff --git a/shadow-4.15.1-audit-update.patch b/shadow-4.15.1-audit-update.patch index a738d60..0295ecc 100644 --- a/shadow-4.15.1-audit-update.patch +++ b/shadow-4.15.1-audit-update.patch @@ -851,15 +851,6 @@ diff -up shadow-4.15.1/src/groupdel.c.audit-update shadow-4.15.1/src/groupdel.c } group_id = grp->gr_gid; -@@ -447,7 +451,7 @@ int main (int argc, char **argv) - _("%s: %s is the NIS master\n"), - Prog, nis_master); - } -- exit (E_NOTFOUND); -+ fail_exit (E_NOTFOUND); - } - #endif - diff -up shadow-4.15.1/src/groupmod.c.audit-update shadow-4.15.1/src/groupmod.c --- shadow-4.15.1/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 +++ shadow-4.15.1/src/groupmod.c 2024-05-20 11:52:05.640758536 +0200 @@ -1846,8 +1837,8 @@ diff -up shadow-4.15.1/src/usermod.c.audit-update shadow-4.15.1/src/usermod.c #endif SYSLOG ((LOG_INFO, @@ -604,8 +604,8 @@ static void new_spent (struct spwd *spen - date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); - date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); + DAY_TO_STR(new_exp, user_newexpire); + DAY_TO_STR(old_exp, user_expire); #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, - "changing expiration date", diff --git a/shadow-4.15.1-sast-fixes.patch b/shadow-4.15.1-sast-fixes.patch deleted file mode 100644 index e674ebf..0000000 --- a/shadow-4.15.1-sast-fixes.patch +++ /dev/null @@ -1,1413 +0,0 @@ -From 4c16416ebc5f0958d58a1ea1e7890eafd9f8bb75 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Wed, 15 May 2024 12:25:51 +0200 -Subject: [PATCH 01/16] port: fix OVERRUN (CWE-119) - -``` -shadow-4.15.0/lib/port.c:154:2: alias: Assigning: "port.pt_names" = "ttys". "port.pt_names" now points to element 0 of "ttys" (which consists of 65 8-byte elements). -shadow-4.15.0/lib/port.c:155:2: cond_const: Checking "j < 64" implies that "j" is 64 on the false branch. -shadow-4.15.0/lib/port.c:175:2: overrun-local: Overrunning array of 65 8-byte elements at element index 65 (byte offset 527) by dereferencing pointer "port.pt_names + (j + 1)". -173| *cp = '\0'; -174| cp++; -175|-> port.pt_names[j + 1] = NULL; -176| -177| /* -``` - -Resolves: https://issues.redhat.com/browse/RHEL-35383 - -Signed-off-by: Iker Pedrosa -Reviewed-by: Alejandro Colomar ---- - lib/port.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/port.c b/lib/port.c -index 05b95651..60ff8989 100644 ---- a/lib/port.c -+++ b/lib/port.c -@@ -168,7 +168,7 @@ again: - } - *cp = '\0'; - cp++; -- port.pt_names[j + 1] = NULL; -+ port.pt_names[j] = NULL; - - /* - * Get the list of user names. It is the second colon --- -2.45.1 - - -From f8fc6371f69930bbd5801284256e182ba35ced2a Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 14:05:31 +0200 -Subject: [PATCH 02/16] src/useradd.c: set_defaults(): Fix order of clean-ups - -Resources should be freed in the inverse order of the allocation. -This refactor prepares for the following commits, which fix some leaks. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 88d8ab7f..56a74559 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -745,10 +745,9 @@ static int set_defaults (void) - def_create_mail_spool, def_log_init)); - ret = 0; - setdef_err: -- free(new_file); -- if (prefix[0]) { -+ if (prefix[0]) - free(default_file); -- } -+ free(new_file); - - return ret; - } --- -2.45.1 - - -From 37ae8827a0869ee4a723954c3c9e7c48165d9b50 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 14:28:50 +0200 -Subject: [PATCH 03/16] src/useradd.c: set_defaults(): Rename goto label - -This will help add other labels in the following commits. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 24 +++++++++++++----------- - 1 file changed, 13 insertions(+), 11 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 56a74559..bc72e6bc 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -558,7 +558,7 @@ static int set_defaults (void) - fprintf(stderr, - _("%s: cannot create new defaults file: %s\n"), - Prog, strerror(errno)); -- goto setdef_err; -+ goto err_free_def; - } - } - -@@ -567,7 +567,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot create directory for defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - ret = mkdir(dirname(new_file_dup), 0755); -@@ -576,7 +576,7 @@ static int set_defaults (void) - _("%s: cannot create directory for defaults file\n"), - Prog); - free(new_file_dup); -- goto setdef_err; -+ goto err_free_def; - } - free(new_file_dup); - -@@ -588,7 +588,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot create new defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - ofp = fdopen (ofd, "w"); -@@ -596,7 +596,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: cannot open new defaults file\n"), - Prog); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -623,7 +623,7 @@ static int set_defaults (void) - _("%s: line too long in %s: %s..."), - Prog, default_file, buf); - (void) fclose (ifp); -- goto setdef_err; -+ goto err_free_def; - } - } - -@@ -702,9 +702,10 @@ static int set_defaults (void) - (void) fflush (ofp); - if ( (ferror (ofp) != 0) - || (fsync (fileno (ofp)) != 0) -- || (fclose (ofp) != 0)) { -+ || (fclose (ofp) != 0)) -+ { - unlink (new_file); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -718,7 +719,7 @@ static int set_defaults (void) - _("%s: Cannot create backup file (%s): %s\n"), - Prog, buf, strerror (err)); - unlink (new_file); -- goto setdef_err; -+ goto err_free_def; - } - - /* -@@ -729,7 +730,7 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: rename: %s: %s\n"), - Prog, new_file, strerror (err)); -- goto setdef_err; -+ goto err_free_def; - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USYS_CONFIG, Prog, -@@ -744,7 +745,8 @@ static int set_defaults (void) - def_inactive, def_expire, def_template, - def_create_mail_spool, def_log_init)); - ret = 0; -- setdef_err: -+ -+err_free_def: - if (prefix[0]) - free(default_file); - free(new_file); --- -2.45.1 - - -From 701fe4cf1aeac9e66fa949369c91d135dbf375d2 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:10:46 +0200 -Subject: [PATCH 04/16] src/useradd.c: set_defaults(): Do not free(3) the - result of asprintf(3) if it failed -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -See asprintf(3): - -RETURN VALUE - When successful, these functions return the number of bytes - printed, just like sprintf(3). If memory allocation wasn’t possi‐ - ble, or some other error occurs, these functions will return -1, - and the contents of strp are undefined. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index bc72e6bc..6a3edfe3 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -558,7 +558,7 @@ static int set_defaults (void) - fprintf(stderr, - _("%s: cannot create new defaults file: %s\n"), - Prog, strerror(errno)); -- goto err_free_def; -+ goto err_free_new; - } - } - -@@ -749,6 +749,7 @@ static int set_defaults (void) - err_free_def: - if (prefix[0]) - free(default_file); -+err_free_new: - free(new_file); - - return ret; --- -2.45.1 - - -From a74c4b6ae124a55cd272e574e0d056102f331e17 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:14:31 +0200 -Subject: [PATCH 05/16] src/useradd.c: De-duplicate code - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 6a3edfe3..ad2676c1 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -571,14 +571,13 @@ static int set_defaults (void) - } - - ret = mkdir(dirname(new_file_dup), 0755); -+ free(new_file_dup); - if (-1 == ret && EEXIST != errno) { - fprintf (stderr, - _("%s: cannot create directory for defaults file\n"), - Prog); -- free(new_file_dup); - goto err_free_def; - } -- free(new_file_dup); - - /* - * Create a temporary file to copy the new output to. --- -2.45.1 - - -From e7d1508e076bbf4053faacc0370c6fe43d9c8f04 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:40:58 +0200 -Subject: [PATCH 06/16] src/useradd.c: Add fmkstemp() to fix file-descriptor - leak - -This function creates a temporary file, and returns a FILE pointer to -it. This avoids dealing with both a file descriptor and a FILE pointer, -and correctly deallocating the resources on error. - -The code before this patch was leaking the file descriptor if fdopen(3) -failed. - -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 34 ++++++++++++++++++++++++---------- - 1 file changed, 24 insertions(+), 10 deletions(-) - -diff --git a/src/useradd.c b/src/useradd.c -index ad2676c1..e0238457 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -238,6 +238,9 @@ static void create_home (void); - static void create_mail (void); - static void check_uid_range(int rflg, uid_t user_id); - -+static FILE *fmkstemp(char *template); -+ -+ - /* - * fail_exit - undo as much as possible - */ -@@ -524,7 +527,6 @@ static void show_defaults (void) - */ - static int set_defaults (void) - { -- int ofd; - int ret = -1; - bool out_group = false; - bool out_groups = false; -@@ -582,15 +584,7 @@ static int set_defaults (void) - /* - * Create a temporary file to copy the new output to. - */ -- ofd = mkstemp (new_file); -- if (-1 == ofd) { -- fprintf (stderr, -- _("%s: cannot create new defaults file\n"), -- Prog); -- goto err_free_def; -- } -- -- ofp = fdopen (ofd, "w"); -+ ofp = fmkstemp(new_file); - if (NULL == ofp) { - fprintf (stderr, - _("%s: cannot open new defaults file\n"), -@@ -2752,3 +2746,23 @@ int main (int argc, char **argv) - return E_SUCCESS; - } - -+ -+static FILE * -+fmkstemp(char *template) -+{ -+ int fd; -+ FILE *fp; -+ -+ fd = mkstemp(template); -+ if (fd == -1) -+ return NULL; -+ -+ fp = fdopen(fd, "w"); -+ if (fp == NULL) { -+ close(fd); -+ unlink(template); -+ return NULL; -+ } -+ -+ return fp; -+} --- -2.45.1 - - -From 1ee066ae1e5b39ac42120ad0f6f8af0f102db952 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 13:52:07 +0200 -Subject: [PATCH 07/16] src/useradd.c: set_defaults(): Fix FILE* leak - -Report: -> shadow-4.15.0/src/useradd.c:575:2: alloc_fn: Storage is returned from allocation function "fdopen". -> shadow-4.15.0/src/useradd.c:575:2: var_assign: Assigning: "ofp" = storage returned from "fdopen(ofd, "w")". -> shadow-4.15.0/src/useradd.c:734:2: leaked_storage: Variable "ofp" going out of scope leaks the storage it points to. -> 732| } -> 733| -> 734|-> return ret; -> 735| } -> 736| - -Link: -Reported-by: Iker Pedrosa -Reviewed-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/useradd.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index e0238457..347334a6 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -615,7 +615,8 @@ static int set_defaults (void) - fprintf (stderr, - _("%s: line too long in %s: %s..."), - Prog, default_file, buf); -- (void) fclose (ifp); -+ fclose(ifp); -+ fclose(ofp); - goto err_free_def; - } - } --- -2.45.1 - - -From 151f14ad69de8100d25c1974947d53ae40d1448a Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:52:15 +0200 -Subject: [PATCH 08/16] src/usermod.c: Reduce scope of local variables - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 0fcf0325..57b58f5b 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -687,11 +687,8 @@ fail_exit (int code) - - static void update_group (void) - { -- bool is_member; -- bool was_member; -- bool changed; -- const struct group *grp; -- struct group *ngrp; -+ bool changed; -+ const struct group *grp; - - changed = false; - -@@ -700,6 +697,9 @@ static void update_group (void) - * the user is a member of. - */ - while ((grp = gr_next ()) != NULL) { -+ bool is_member; -+ bool was_member; -+ struct group *ngrp; - /* - * See if the user specified this group as one of their - * concurrent groups. -@@ -799,12 +799,8 @@ static void update_group (void) - #ifdef SHADOWGRP - static void update_gshadow (void) - { -- bool is_member; -- bool was_member; -- bool was_admin; -- bool changed; -- const struct sgrp *sgrp; -- struct sgrp *nsgrp; -+ bool changed; -+ const struct sgrp *sgrp; - - changed = false; - -@@ -813,6 +809,10 @@ static void update_gshadow (void) - * that the user is a member of. - */ - while ((sgrp = sgr_next ()) != NULL) { -+ bool is_member; -+ bool was_member; -+ bool was_admin; -+ struct sgrp *nsgrp; - - /* - * See if the user was a member of this group --- -2.45.1 - - -From b089a63ab38f69c32d099320fe8181802f7f4092 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:49:34 +0200 -Subject: [PATCH 09/16] src/usermod.c: Rename update_group() => - update_group_file() - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 57b58f5b..aaa83d7d 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -178,7 +178,7 @@ NORETURN static void usage (int status); - static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); - NORETURN static void fail_exit (int); --static void update_group (void); -+static void update_group_file(void); - - #ifdef SHADOWGRP - static void update_gshadow (void); -@@ -685,7 +685,8 @@ fail_exit (int code) - } - - --static void update_group (void) -+static void -+update_group_file(void) - { - bool changed; - const struct group *grp; -@@ -950,7 +951,7 @@ static void update_gshadow (void) - */ - static void grp_update (void) - { -- update_group (); -+ update_group_file(); - #ifdef SHADOWGRP - if (is_shadow_grp) { - update_gshadow (); --- -2.45.1 - - -From 81bc78ec5cdd59790bc7c591c9d1f66bd4d7b78e Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:11:22 +0200 -Subject: [PATCH 10/16] src/usermod.c: Rename update_gshadow() => - update_gshadow_file() - -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index aaa83d7d..3048f801 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -181,7 +181,7 @@ NORETURN static void fail_exit (int); - static void update_group_file(void); - - #ifdef SHADOWGRP --static void update_gshadow (void); -+static void update_gshadow_file(void); - #endif - static void grp_update (void); - -@@ -798,7 +798,8 @@ update_group_file(void) - } - - #ifdef SHADOWGRP --static void update_gshadow (void) -+static void -+update_gshadow_file(void) - { - bool changed; - const struct sgrp *sgrp; -@@ -954,7 +955,7 @@ static void grp_update (void) - update_group_file(); - #ifdef SHADOWGRP - if (is_shadow_grp) { -- update_gshadow (); -+ update_gshadow_file(); - } - #endif - } --- -2.45.1 - - -From 61964aa06b9e6e0643a6519f64290f18ac04867f Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 13:54:06 +0200 -Subject: [PATCH 11/16] src/usermod.c: update_group_file(): Fix RESOURCE_LEAK - (CWE-772) - -Report: -> shadow-4.15.0/src/usermod.c:734:3: alloc_fn: Storage is returned from allocation function "__gr_dup". -> shadow-4.15.0/src/usermod.c:734:3: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)". -> shadow-4.15.0/src/usermod.c:815:1: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to. -> 813| gr_free(ngrp); -> 814| } -> 815|-> } -> 816| -> 817| #ifdef SHADOWGRP - -Link: https://issues.redhat.com/browse/RHEL-35383 -Reported-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 3048f801..e0cfdd83 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -780,9 +780,8 @@ update_group_file(void) - SYSLOG ((LOG_INFO, "add '%s' to group '%s'", - user_newname, ngrp->gr_name)); - } -- if (!changed) { -- continue; -- } -+ if (!changed) -+ goto free_ngrp; - - changed = false; - if (gr_update (ngrp) == 0) { -@@ -793,6 +792,7 @@ update_group_file(void) - fail_exit (E_GRP_UPDATE); - } - -+free_ngrp: - gr_free(ngrp); - } - } --- -2.45.1 - - -From 71a3238b7996285fc3c8dec841244ba95d663fa5 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:15:15 +0200 -Subject: [PATCH 12/16] src/usermod.c: update_gshadow_file(): Fix RESOURCE_LEAK - (CWE-772) - -Report: -> shadow-4.15.0/src/usermod.c:864:3: alloc_fn: Storage is returned from allocation function "__sgr_dup". -> shadow-4.15.0/src/usermod.c:864:3: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)". -> shadow-4.15.0/src/usermod.c:964:1: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to. -> 962| free (nsgrp); -> 963| } -> 964|-> } -> 965| #endif /* SHADOWGRP */ -> 966| - -Link: https://issues.redhat.com/browse/RHEL-35383 -Reported-by: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index e0cfdd83..bb5d3535 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -921,9 +921,8 @@ update_gshadow_file(void) - SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", - user_newname, nsgrp->sg_name)); - } -- if (!changed) { -- continue; -- } -+ if (!changed) -+ goto free_nsgrp; - - changed = false; - -@@ -939,6 +938,7 @@ update_gshadow_file(void) - fail_exit (E_GRP_UPDATE); - } - -+free_nsgrp: - free (nsgrp); - } - } --- -2.45.1 - - -From 68d42a8fbe42b89cf13d3f672ad8502dbaf05835 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 14:02:54 +0200 -Subject: [PATCH 13/16] src/usermod.c: update_group_file(): Reduce scope of - local variable - -After _every_ iteration, 'changed' is always 'false'. We don't need to -have it outside of the loop. - -See: - -$ grepc update_group_file . \ -| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - bool changed; - changed = false; - while ((grp = gr_next ()) != NULL) { - if (!was_member && !is_member) { - continue; - } - if (was_member) { - if ((!Gflg) || is_member) { - if (lflg) { - changed = true; - } - } else { - changed = true; - } - } else if (is_member) { - changed = true; - } - if (!changed) - goto free_ngrp; - changed = false; -free_ngrp: - } -} - -This was already true in the commit that introduced the code: - -$ git show 45c6603cc:src/usermod.c \ -| grepc update_group \ -| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - int changed; - changed = 0; - while ((grp = gr_next())) { - * See if the user specified this group as one of their - if (!was_member && !is_member) - continue; - if (was_member && (!Gflg || is_member)) { - if (lflg) { - changed = 1; - } - } else if (was_member && Gflg && !is_member) { - changed = 1; - } else if (!was_member && Gflg && is_member) { - changed = 1; - } - if (!changed) - continue; - changed = 0; - } -} - -Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index bb5d3535..30f47b8a 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -688,19 +688,20 @@ fail_exit (int code) - static void - update_group_file(void) - { -- bool changed; - const struct group *grp; - -- changed = false; -- - /* - * Scan through the entire group file looking for the groups that - * the user is a member of. - */ - while ((grp = gr_next ()) != NULL) { -+ bool changed; - bool is_member; - bool was_member; - struct group *ngrp; -+ -+ changed = false; -+ - /* - * See if the user specified this group as one of their - * concurrent groups. -@@ -783,7 +784,6 @@ update_group_file(void) - if (!changed) - goto free_ngrp; - -- changed = false; - if (gr_update (ngrp) == 0) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), --- -2.45.1 - - -From da77a82ecbc90e89808f143e7fa2abb7650f50d7 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:19:46 +0200 -Subject: [PATCH 14/16] src/usermod.c: update_gshadow_file(): Reduce scope of - local variable - -After _every_ iteration, 'changed' is always 'false'. We don't need to -have it outside of the loop. - -See: - -$ grepc update_gshadow_file . \ -| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - bool changed; - changed = false; - while ((sgrp = sgr_next ()) != NULL) { - if (!was_member && !was_admin && !is_member) { - continue; - } - if (was_admin && lflg) { - changed = true; - } - if (was_member) { - if ((!Gflg) || is_member) { - if (lflg) { - changed = true; - } - } else { - changed = true; - } - } else if (is_member) { - changed = true; - } - if (!changed) - goto free_nsgrp; - changed = false; - } -} - -This was already true in the commit that introduced the code: - -$ git show 45c6603cc:src/usermod.c \ -| grepc update_gshadow \ -| grep -e changed -e goto -e break -e continue -e '\' -e '{' -e '}' \ -| pcre2grep -v -M '{\n\t*}'; -{ - int changed; - changed = 0; - while ((sgrp = sgr_next())) { - * See if the user was a member of this group - * See if the user was an administrator of this group - * See if the user specified this group as one of their - if (!was_member && !was_admin && !is_member) - continue; - if (was_admin && lflg) { - changed = 1; - } - if (was_member && (!Gflg || is_member)) { - if (lflg) { - changed = 1; - } - } else if (was_member && Gflg && !is_member) { - changed = 1; - } else if (!was_member && Gflg && is_member) { - changed = 1; - } - if (!changed) - continue; - changed = 0; - } -} - -Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)") -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 30f47b8a..7b1e0581 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -801,21 +801,21 @@ free_ngrp: - static void - update_gshadow_file(void) - { -- bool changed; - const struct sgrp *sgrp; - -- changed = false; -- - /* - * Scan through the entire shadow group file looking for the groups - * that the user is a member of. - */ - while ((sgrp = sgr_next ()) != NULL) { -+ bool changed; - bool is_member; - bool was_member; - bool was_admin; - struct sgrp *nsgrp; - -+ changed = false; -+ - /* - * See if the user was a member of this group - */ -@@ -924,8 +924,6 @@ update_gshadow_file(void) - if (!changed) - goto free_nsgrp; - -- changed = false; -- - /* - * Update the group entry to reflect the changes. - */ --- -2.45.1 - - -From adf37cccd0fa4ce7d05644514b0af57fe71905c3 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 16 May 2024 14:12:09 +0200 -Subject: [PATCH 15/16] src/usermod.c: update_group(): Add helper function - -Keep the while loop in the outer function, and move the iteration code -to this new helper. This makes it a bit more readable. - -Cc: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 167 ++++++++++++++++++++++++++------------------------ - 1 file changed, 87 insertions(+), 80 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 7b1e0581..4ea11376 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -179,6 +179,7 @@ static void new_pwent (struct passwd *); - static void new_spent (struct spwd *); - NORETURN static void fail_exit (int); - static void update_group_file(void); -+static void update_group(const struct group *grp); - - #ifdef SHADOWGRP - static void update_gshadow_file(void); -@@ -694,109 +695,115 @@ update_group_file(void) - * Scan through the entire group file looking for the groups that - * the user is a member of. - */ -- while ((grp = gr_next ()) != NULL) { -- bool changed; -- bool is_member; -- bool was_member; -- struct group *ngrp; -+ while ((grp = gr_next()) != NULL) -+ update_group(grp); -+} - -- changed = false; - -- /* -- * See if the user specified this group as one of their -- * concurrent groups. -- */ -- was_member = is_on_list (grp->gr_mem, user_name); -- is_member = Gflg && ( (was_member && aflg) -- || is_on_list (user_groups, grp->gr_name)); -+static void -+update_group(const struct group *grp) -+{ -+ bool changed; -+ bool is_member; -+ bool was_member; -+ struct group *ngrp; - -- if (!was_member && !is_member) { -- continue; -- } -+ changed = false; - -- /* -- * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes -- * mentioned groups while leaving the others. -- */ -- if (Gflg && rflg) { -- is_member = !is_member; -- } -+ /* -+ * See if the user specified this group as one of their -+ * concurrent groups. -+ */ -+ was_member = is_on_list (grp->gr_mem, user_name); -+ is_member = Gflg && ( (was_member && aflg) -+ || is_on_list (user_groups, grp->gr_name)); - -- ngrp = __gr_dup (grp); -- if (NULL == ngrp) { -- fprintf (stderr, -- _("%s: Out of memory. Cannot update %s.\n"), -- Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -+ if (!was_member && !is_member) -+ return; - -- if (was_member) { -- if ((!Gflg) || is_member) { -- /* User was a member and is still a member -- * of this group. -- * But the user might have been renamed. -- */ -- if (lflg) { -- ngrp->gr_mem = del_list (ngrp->gr_mem, -- user_name); -- ngrp->gr_mem = add_list (ngrp->gr_mem, -- user_newname); -- changed = true; --#ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing group member", -- user_newname, AUDIT_NO_ID, 1); --#endif -- SYSLOG ((LOG_INFO, -- "change '%s' to '%s' in group '%s'", -- user_name, user_newname, -- ngrp->gr_name)); -- } -- } else { -- /* User was a member but is no more a -- * member of this group. -- */ -- ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); -+ /* -+ * If rflg+Gflg is passed in AKA -rG invert is_member flag, which removes -+ * mentioned groups while leaving the others. -+ */ -+ if (Gflg && rflg) { -+ is_member = !is_member; -+ } -+ -+ ngrp = __gr_dup (grp); -+ if (NULL == ngrp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot update %s.\n"), -+ Prog, gr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+ if (was_member) { -+ if ((!Gflg) || is_member) { -+ /* User was a member and is still a member -+ * of this group. -+ * But the user might have been renamed. -+ */ -+ if (lflg) { -+ ngrp->gr_mem = del_list (ngrp->gr_mem, -+ user_name); -+ ngrp->gr_mem = add_list (ngrp->gr_mem, -+ user_newname); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing group member", -- user_name, AUDIT_NO_ID, 1); -+ "changing group member", -+ user_newname, AUDIT_NO_ID, 1); - #endif - SYSLOG ((LOG_INFO, -- "delete '%s' from group '%s'", -- user_name, ngrp->gr_name)); -+ "change '%s' to '%s' in group '%s'", -+ user_name, user_newname, -+ ngrp->gr_name)); - } -- } else if (is_member) { -- /* User was not a member but is now a member this -- * group. -+ } else { -+ /* User was a member but is no more a -+ * member of this group. - */ -- ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); -+ ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, 1); -+ "removing group member", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, "add '%s' to group '%s'", -- user_newname, ngrp->gr_name)); -+ SYSLOG ((LOG_INFO, -+ "delete '%s' from group '%s'", -+ user_name, ngrp->gr_name)); - } -- if (!changed) -- goto free_ngrp; -+ } else if (is_member) { -+ /* User was not a member but is now a member this -+ * group. -+ */ -+ ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); -+ changed = true; -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "adding user to group", -+ user_name, AUDIT_NO_ID, 1); -+#endif -+ SYSLOG ((LOG_INFO, "add '%s' to group '%s'", -+ user_newname, ngrp->gr_name)); -+ } -+ if (!changed) -+ goto free_ngrp; - -- if (gr_update (ngrp) == 0) { -- fprintf (stderr, -- _("%s: failed to prepare the new %s entry '%s'\n"), -- Prog, gr_dbname (), ngrp->gr_name); -- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); -- fail_exit (E_GRP_UPDATE); -- } -+ if (gr_update (ngrp) == 0) { -+ fprintf (stderr, -+ _("%s: failed to prepare the new %s entry '%s'\n"), -+ Prog, gr_dbname (), ngrp->gr_name); -+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); -+ fail_exit (E_GRP_UPDATE); -+ } - - free_ngrp: -- gr_free(ngrp); -- } -+ gr_free(ngrp); - } - -+ - #ifdef SHADOWGRP - static void - update_gshadow_file(void) --- -2.45.1 - - -From d8e6a8b99b4d844328d875287babf6e13860d464 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 17 May 2024 02:29:46 +0200 -Subject: [PATCH 16/16] src/usermod.c: update_gshadow(): Add helper function - -Keep the while loop in the outer function, and move the iteration code -to this new helper. This makes it a bit more readable. - -Cc: Iker Pedrosa -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 223 ++++++++++++++++++++++++++------------------------ - 1 file changed, 116 insertions(+), 107 deletions(-) - -diff --git a/src/usermod.c b/src/usermod.c -index 4ea11376..f8896984 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -183,6 +183,7 @@ static void update_group(const struct group *grp); - - #ifdef SHADOWGRP - static void update_gshadow_file(void); -+static void update_gshadow(const struct sgrp *sgrp); - #endif - static void grp_update (void); - -@@ -814,141 +815,149 @@ update_gshadow_file(void) - * Scan through the entire shadow group file looking for the groups - * that the user is a member of. - */ -- while ((sgrp = sgr_next ()) != NULL) { -- bool changed; -- bool is_member; -- bool was_member; -- bool was_admin; -- struct sgrp *nsgrp; -+ while ((sgrp = sgr_next()) != NULL) -+ update_gshadow(sgrp); -+} -+#endif /* SHADOWGRP */ - -- changed = false; - -- /* -- * See if the user was a member of this group -- */ -- was_member = is_on_list (sgrp->sg_mem, user_name); -+#ifdef SHADOWGRP -+static void -+update_gshadow(const struct sgrp *sgrp) -+{ -+ bool changed; -+ bool is_member; -+ bool was_member; -+ bool was_admin; -+ struct sgrp *nsgrp; - -- /* -- * See if the user was an administrator of this group -- */ -- was_admin = is_on_list (sgrp->sg_adm, user_name); -+ changed = false; - -- /* -- * See if the user specified this group as one of their -- * concurrent groups. -- */ -- is_member = Gflg && ( (was_member && aflg) -- || is_on_list (user_groups, sgrp->sg_name)); -+ /* -+ * See if the user was a member of this group -+ */ -+ was_member = is_on_list (sgrp->sg_mem, user_name); - -- if (!was_member && !was_admin && !is_member) { -- continue; -- } -+ /* -+ * See if the user was an administrator of this group -+ */ -+ was_admin = is_on_list (sgrp->sg_adm, user_name); - -- /* -- * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted -- * groups while leaving the user apart of groups not mentioned -- */ -- if (Gflg && rflg) { -- is_member = !is_member; -- } -+ /* -+ * See if the user specified this group as one of their -+ * concurrent groups. -+ */ -+ is_member = Gflg && ( (was_member && aflg) -+ || is_on_list (user_groups, sgrp->sg_name)); - -- nsgrp = __sgr_dup (sgrp); -- if (NULL == nsgrp) { -- fprintf (stderr, -- _("%s: Out of memory. Cannot update %s.\n"), -- Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -- } -+ if (!was_member && !was_admin && !is_member) -+ return; - -- if (was_admin && lflg) { -- /* User was an admin of this group but the user -- * has been renamed. -- */ -- nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); -- nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); -- changed = true; --#ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing admin name in shadow group", -- user_name, AUDIT_NO_ID, 1); --#endif -- SYSLOG ((LOG_INFO, -- "change admin '%s' to '%s' in shadow group '%s'", -- user_name, user_newname, nsgrp->sg_name)); -- } -- -- if (was_member) { -- if ((!Gflg) || is_member) { -- /* User was a member and is still a member -- * of this group. -- * But the user might have been renamed. -- */ -- if (lflg) { -- nsgrp->sg_mem = del_list (nsgrp->sg_mem, -- user_name); -- nsgrp->sg_mem = add_list (nsgrp->sg_mem, -- user_newname); -- changed = true; -+ /* -+ * If rflg+Gflg is passed in AKA -rG invert is_member, to remove targeted -+ * groups while leaving the user apart of groups not mentioned -+ */ -+ if (Gflg && rflg) { -+ is_member = !is_member; -+ } -+ -+ nsgrp = __sgr_dup (sgrp); -+ if (NULL == nsgrp) { -+ fprintf (stderr, -+ _("%s: Out of memory. Cannot update %s.\n"), -+ Prog, sgr_dbname ()); -+ fail_exit (E_GRP_UPDATE); -+ } -+ -+ if (was_admin && lflg) { -+ /* User was an admin of this group but the user -+ * has been renamed. -+ */ -+ nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); -+ nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); -+ changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing member in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "changing admin name in shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, -- "change '%s' to '%s' in shadow group '%s'", -- user_name, user_newname, -- nsgrp->sg_name)); -- } -- } else { -- /* User was a member but is no more a -- * member of this group. -- */ -- nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); -+ SYSLOG ((LOG_INFO, -+ "change admin '%s' to '%s' in shadow group '%s'", -+ user_name, user_newname, nsgrp->sg_name)); -+ } -+ -+ if (was_member) { -+ if ((!Gflg) || is_member) { -+ /* User was a member and is still a member -+ * of this group. -+ * But the user might have been renamed. -+ */ -+ if (lflg) { -+ nsgrp->sg_mem = del_list (nsgrp->sg_mem, -+ user_name); -+ nsgrp->sg_mem = add_list (nsgrp->sg_mem, -+ user_newname); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing user from shadow group", -- user_name, AUDIT_NO_ID, 1); -+ "changing member in shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif - SYSLOG ((LOG_INFO, -- "delete '%s' from shadow group '%s'", -- user_name, nsgrp->sg_name)); -+ "change '%s' to '%s' in shadow group '%s'", -+ user_name, user_newname, -+ nsgrp->sg_name)); - } -- } else if (is_member) { -- /* User was not a member but is now a member this -- * group. -+ } else { -+ /* User was a member but is no more a -+ * member of this group. - */ -- nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); -+ nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); - changed = true; - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to shadow group", -- user_newname, AUDIT_NO_ID, 1); -+ "removing user from shadow group", -+ user_name, AUDIT_NO_ID, 1); - #endif -- SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", -- user_newname, nsgrp->sg_name)); -+ SYSLOG ((LOG_INFO, -+ "delete '%s' from shadow group '%s'", -+ user_name, nsgrp->sg_name)); - } -- if (!changed) -- goto free_nsgrp; -- -- /* -- * Update the group entry to reflect the changes. -+ } else if (is_member) { -+ /* User was not a member but is now a member this -+ * group. - */ -- if (sgr_update (nsgrp) == 0) { -- fprintf (stderr, -- _("%s: failed to prepare the new %s entry '%s'\n"), -- Prog, sgr_dbname (), nsgrp->sg_name); -- SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", -- sgr_dbname (), nsgrp->sg_name)); -- fail_exit (E_GRP_UPDATE); -- } -+ nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); -+ changed = true; -+#ifdef WITH_AUDIT -+ audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -+ "adding user to shadow group", -+ user_newname, AUDIT_NO_ID, 1); -+#endif -+ SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", -+ user_newname, nsgrp->sg_name)); -+ } -+ if (!changed) -+ goto free_nsgrp; - --free_nsgrp: -- free (nsgrp); -+ /* -+ * Update the group entry to reflect the changes. -+ */ -+ if (sgr_update (nsgrp) == 0) { -+ fprintf (stderr, -+ _("%s: failed to prepare the new %s entry '%s'\n"), -+ Prog, sgr_dbname (), nsgrp->sg_name); -+ SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", -+ sgr_dbname (), nsgrp->sg_name)); -+ fail_exit (E_GRP_UPDATE); - } -+ -+free_nsgrp: -+ free (nsgrp); - } - #endif /* SHADOWGRP */ - -+ - /* - * grp_update - add user to secondary group set - * --- -2.45.1 - diff --git a/shadow-utils.spec b/shadow-utils.spec index e3cd026..0786f83 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.1 -Release: 9%{?dist} +Version: 4.16.0 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -22,14 +22,10 @@ Source7: passwd.pamd Patch0: shadow-4.15.0-manfix.patch # Date parsing improvement - could be upstreamed Patch1: shadow-4.15.0-date-parsing.patch -# Several patches already available upstream. PRs:#994, #996, #997 -Patch2: shadow-4.15.1-sast-fixes.patch # Audit message changes - partially upstreamed -Patch3: shadow-4.15.1-audit-update.patch +Patch2: shadow-4.15.1-audit-update.patch # Probably non-upstreamable -Patch4: shadow-4.15.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/ead55e9ba8958504e23e29545f90c4dd925c7462 -Patch5: shadow-4.15.0-getdef-spurious-error.patch +Patch3: shadow-4.15.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -295,6 +291,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Aug 13 2024 Iker Pedrosa - 2:4.16.0-1 +- Rebase to version 4.16.0 (#2293678) + * Tue Jul 23 2024 Kevin Fenzi - 2:4.15.1-9 - Revert chpasswd: use PAM again for now. diff --git a/sources b/sources index ca5a1c9..a2d890c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.15.1.tar.xz) = 2667a1d781066adce42e684463329c3f32d28c07b7b79b628525bffcd61c078f6ff430be3d42976d0509d9f9a55cd80f5a50d479b85155476cee7f00f06708d8 -SHA512 (shadow-4.15.1.tar.xz.asc) = 0a39d6a45b7d8df12aade89ed9fc9d481c91297dbd34e85fe831426c1d0051cbcf8478759306b8871cd6b1835604c5836decf398d0165c50ac52fee365561446 +SHA512 (shadow-4.16.0.tar.xz) = 3986572c74cce013c733c592ef5a8113e69bba8fee74fb697fe8206bd616d29553e42822e663478db81b3e17b26b403bc69b3492dd981b87643b0e1c55035ecf +SHA512 (shadow-4.16.0.tar.xz.asc) = be98d5c157115869e23932e347b609ab342c0bc1a9d716d07ae61b497779c1a5a436534eb3ee0294687eca5831e193776a005d13b43b6979c8acd380b9372550 From 8971f52d1594b16f8166c2c8d312b2c0799ac1d9 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 28 Aug 2024 13:20:46 +0200 Subject: [PATCH 076/118] Rebase to version 4.16.0 Resolves: #2293678 Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 0786f83..3c6d110 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.16.0 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -291,7 +291,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog -* Tue Aug 13 2024 Iker Pedrosa - 2:4.16.0-1 +* Wed Aug 28 2024 Iker Pedrosa - 2:4.16.0-2 - Rebase to version 4.16.0 (#2293678) * Tue Jul 23 2024 Kevin Fenzi - 2:4.15.1-9 From 4642a65eb4963253b1abd952aa727fcbb238df53 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 13 Sep 2024 09:24:39 +0200 Subject: [PATCH 077/118] Sort alphabetically configuration options Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 3c6d110..85615d9 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -127,22 +127,22 @@ export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" autoreconf %configure \ + --disable-account-tools-setuid \ + --enable-lastlog \ + --enable-logind=no \ + --enable-man \ --enable-shadowgrp \ - --enable-man \ + --enable-shared \ --with-audit \ - --with-libpam \ - --with-sha-crypt \ --with-bcrypt \ - --with-yescrypt \ + --with-group-name-max-length=32 \ + --with-libpam \ --with-selinux \ + --with-sha-crypt \ + --with-yescrypt \ --without-libbsd \ --without-libcrack \ - --without-sssd \ - --enable-shared \ - --with-group-name-max-length=32 \ - --enable-lastlog \ - --enable-logind=no \ - --disable-account-tools-setuid + --without-sssd %make_build %install From fe4f9dc5c0ad3270c280392bb574748f7c49bf81 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 13 Sep 2024 09:43:20 +0200 Subject: [PATCH 078/118] Disable nscd Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 85615d9..7021037 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.16.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -142,6 +142,7 @@ autoreconf --with-yescrypt \ --without-libbsd \ --without-libcrack \ + --without-nscd \ --without-sssd %make_build @@ -291,6 +292,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Sep 13 2024 Iker Pedrosa - 2:4.16.0-3 +- Disable nscd + * Wed Aug 28 2024 Iker Pedrosa - 2:4.16.0-2 - Rebase to version 4.16.0 (#2293678) From cb321b1db18591f6a8acd44a1b8d5fc838ba3077 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 19 Sep 2024 16:52:21 +0200 Subject: [PATCH 079/118] useradd: fix write_full() return value Resolves: #2313559 Signed-off-by: Iker Pedrosa --- ...4.16.0-useradd-fix-write-full-return.patch | 34 +++++++++++++++++++ shadow-utils.spec | 7 +++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 shadow-4.16.0-useradd-fix-write-full-return.patch diff --git a/shadow-4.16.0-useradd-fix-write-full-return.patch b/shadow-4.16.0-useradd-fix-write-full-return.patch new file mode 100644 index 0000000..6f66333 --- /dev/null +++ b/shadow-4.16.0-useradd-fix-write-full-return.patch @@ -0,0 +1,34 @@ +From 8903b94c86c978e8abef623358fd3e4629c06967 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 9 Sep 2024 10:36:17 +0200 +Subject: [PATCH] useradd: fix write_full() return value + +write_full() returns -1 on error and useradd was checking another value. + +Closes: https://github.com/shadow-maint/shadow/issues/1072 +Fixes: f45498a6c286 ("libmisc/write_full.c: Improve write_full()") + +Reported-by: +Suggested-by: +Reviewed-by: Alejandro Colomar +Reviewed-by: Iker Pedrosa +--- + src/useradd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index 02c500d0..d64fd892 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2042,7 +2042,7 @@ static void lastlog_reset (uid_t uid) + return; + } + if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) +- || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) ++ || (write_full (fd, &ll, sizeof (ll)) != -1) + || (fsync (fd) != 0)) { + fprintf (stderr, + _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), +-- +2.46.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 7021037..0096c95 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.16.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,6 +26,8 @@ Patch1: shadow-4.15.0-date-parsing.patch Patch2: shadow-4.15.1-audit-update.patch # Probably non-upstreamable Patch3: shadow-4.15.0-account-tools-setuid.patch +# https://github.com/shadow-maint/shadow/commit/8903b94c86c978e8abef623358fd3e4629c06967 +Patch4: shadow-4.16.0-useradd-fix-write-full-return.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -292,6 +294,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Sep 19 2024 Iker Pedrosa - 2:4.16.0-4 +- useradd: fix write_full() return value. Resolves: #2313559 + * Fri Sep 13 2024 Iker Pedrosa - 2:4.16.0-3 - Disable nscd From cbfed0db1ea3fb6094d44d5a5642182d3fff2738 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 7 Oct 2024 10:00:36 +0200 Subject: [PATCH 080/118] useradd: fix write_full() return value Resolves: #2313559 Signed-off-by: Iker Pedrosa --- shadow-4.16.0-useradd-fix-write-full-return.patch | 2 +- shadow-utils.spec | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shadow-4.16.0-useradd-fix-write-full-return.patch b/shadow-4.16.0-useradd-fix-write-full-return.patch index 6f66333..64e2ef8 100644 --- a/shadow-4.16.0-useradd-fix-write-full-return.patch +++ b/shadow-4.16.0-useradd-fix-write-full-return.patch @@ -25,7 +25,7 @@ index 02c500d0..d64fd892 100644 } if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) - || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) -+ || (write_full (fd, &ll, sizeof (ll)) != -1) ++ || (write_full (fd, &ll, sizeof (ll)) == -1) || (fsync (fd) != 0)) { fprintf (stderr, _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), diff --git a/shadow-utils.spec b/shadow-utils.spec index 0096c95..fa3ef81 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.16.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,7 +26,7 @@ Patch1: shadow-4.15.0-date-parsing.patch Patch2: shadow-4.15.1-audit-update.patch # Probably non-upstreamable Patch3: shadow-4.15.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/8903b94c86c978e8abef623358fd3e4629c06967 +# https://github.com/shadow-maint/shadow/commit/903593249630054ab5df327481f7386f718088cc Patch4: shadow-4.16.0-useradd-fix-write-full-return.patch ### Dependencies ### @@ -294,7 +294,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog -* Thu Sep 19 2024 Iker Pedrosa - 2:4.16.0-4 +* Mon Oct 7 2024 Iker Pedrosa - 2:4.16.0-5 - useradd: fix write_full() return value. Resolves: #2313559 * Fri Sep 13 2024 Iker Pedrosa - 2:4.16.0-3 From 4eba5ba13e9508f39d30c439ee494a7fe13c6cb1 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 16 Oct 2024 12:04:44 +0200 Subject: [PATCH 081/118] Rebuilt for libeconf soname bump Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index fa3ef81..633a2c8 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.16.0 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -294,6 +294,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Oct 16 2024 Iker Pedrosa - 2:4.16.0-6 +- Rebuilt for libeconf soname bump + * Mon Oct 7 2024 Iker Pedrosa - 2:4.16.0-5 - useradd: fix write_full() return value. Resolves: #2313559 From e7d5253e951ad6169b017318ef143d6b992c07e2 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 12 Nov 2024 09:34:52 +0100 Subject: [PATCH 082/118] SPDX license migration for subpackages Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 633a2c8..31cd953 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.16.0 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -91,7 +91,6 @@ are used for managing group accounts. ### Subpackages ### %package subid Summary: A library to manage subordinate uid and gid ranges -License: BSD and GPLv2+ %description subid Utility library that provides a way to manage subid ranges. @@ -99,7 +98,6 @@ Utility library that provides a way to manage subid ranges. %package subid-devel Summary: Development package for shadow-utils-subid -License: BSD and GPLv2+ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} %description subid-devel @@ -294,6 +292,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Nov 12 2024 Iker Pedrosa - 2:4.16.0-7 +- SPDX license migration for subpackages + * Wed Oct 16 2024 Iker Pedrosa - 2:4.16.0-6 - Rebuilt for libeconf soname bump From 796cd4dc3b67f307697301441ed6c78f3bff5ed0 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 9 Dec 2024 14:36:59 +0100 Subject: [PATCH 083/118] Rebase to version 4.17.0-rc1 Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ ...4.16.0-useradd-fix-write-full-return.patch | 34 ------------------- ...> shadow-4.17.0-account-tools-setuid.patch | 12 +++---- ....patch => shadow-4.17.0-audit-update.patch | 18 +++++----- shadow-utils.spec | 22 ++++++------ sources | 4 +-- 6 files changed, 29 insertions(+), 63 deletions(-) delete mode 100644 shadow-4.16.0-useradd-fix-write-full-return.patch rename shadow-4.15.0-account-tools-setuid.patch => shadow-4.17.0-account-tools-setuid.patch (97%) rename shadow-4.15.1-audit-update.patch => shadow-4.17.0-audit-update.patch (99%) diff --git a/.gitignore b/.gitignore index 08e3c3f..62cae0c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.15.1.tar.xz.asc /shadow-4.16.0.tar.xz /shadow-4.16.0.tar.xz.asc +/shadow-4.17.0-rc1.tar.xz +/shadow-4.17.0-rc1.tar.xz.asc diff --git a/shadow-4.16.0-useradd-fix-write-full-return.patch b/shadow-4.16.0-useradd-fix-write-full-return.patch deleted file mode 100644 index 64e2ef8..0000000 --- a/shadow-4.16.0-useradd-fix-write-full-return.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 8903b94c86c978e8abef623358fd3e4629c06967 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Mon, 9 Sep 2024 10:36:17 +0200 -Subject: [PATCH] useradd: fix write_full() return value - -write_full() returns -1 on error and useradd was checking another value. - -Closes: https://github.com/shadow-maint/shadow/issues/1072 -Fixes: f45498a6c286 ("libmisc/write_full.c: Improve write_full()") - -Reported-by: -Suggested-by: -Reviewed-by: Alejandro Colomar -Reviewed-by: Iker Pedrosa ---- - src/useradd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index 02c500d0..d64fd892 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2042,7 +2042,7 @@ static void lastlog_reset (uid_t uid) - return; - } - if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid) -- || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll)) -+ || (write_full (fd, &ll, sizeof (ll)) == -1) - || (fsync (fd) != 0)) { - fprintf (stderr, - _("%s: failed to reset the lastlog entry of UID %lu: %s\n"), --- -2.46.0 - diff --git a/shadow-4.15.0-account-tools-setuid.patch b/shadow-4.17.0-account-tools-setuid.patch similarity index 97% rename from shadow-4.15.0-account-tools-setuid.patch rename to shadow-4.17.0-account-tools-setuid.patch index d162487..83453e0 100644 --- a/shadow-4.15.0-account-tools-setuid.patch +++ b/shadow-4.17.0-account-tools-setuid.patch @@ -91,7 +91,7 @@ diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/gr +#endif /* ACCT_TOOLS_SETUID */ #include - #include "alloc.h" + #include "alloc/x/xmalloc.h" @@ -430,6 +432,7 @@ static void process_flags (int argc, cha static void check_perms (void) { @@ -216,7 +216,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new spent = *sp; if ( (NULL != crypt_method) @@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pw - if (strcmp (pwd->pw_passwd, "x") != 0) { + if (!streq(pwd->pw_passwd, "x")) { return update_passwd (pwd, password); } -#else /* USE_PAM */ @@ -225,7 +225,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new * If there is already a shadow entry, do not touch it. * If there is already a passwd entry with a password, do not @@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pw - || (strcmp (pwd->pw_passwd, "x") != 0)) { + || !streq(pwd->pw_passwd, "x")) { return 0; } -#endif /* USE_PAM */ @@ -238,7 +238,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new spent.sp_namp = pwd->pw_name; -#ifndef USE_PAM +#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) { + if ((crypt_method != NULL) && streq(crypt_method, "NONE")) { spent.sp_pwdp = (char *)password; } else { @@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pw @@ -355,8 +355,8 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new /* keep the list of user/password for later update by PAM */ nusers++; @@ -1211,6 +1240,7 @@ int main (int argc, char **argv) - usernames[nusers-1] = strdup (fields[0]); - passwords[nusers-1] = strdup (fields[1]); + usernames[nusers-1] = xstrdup(fields[0]); + passwords[nusers-1] = xstrdup(fields[1]); #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ if (add_passwd (&newpw, fields[1]) != 0) { diff --git a/shadow-4.15.1-audit-update.patch b/shadow-4.17.0-audit-update.patch similarity index 99% rename from shadow-4.15.1-audit-update.patch rename to shadow-4.17.0-audit-update.patch index 0295ecc..fc05c51 100644 --- a/shadow-4.15.1-audit-update.patch +++ b/shadow-4.17.0-audit-update.patch @@ -552,14 +552,14 @@ diff -up shadow-4.15.1/src/groupadd.c.audit-update shadow-4.15.1/src/groupadd.c #endif /* SHADOWGRP */ } @@ -245,7 +254,7 @@ static void check_new_name (void) - fprintf (stderr, _("%s: '%s' is not a valid group name\n"), - Prog, group_name); + fprintf(stderr, _("%s: '%s' is not a valid group name\n"), + Prog, group_name); -- exit (E_BAD_ARG); -+ fail_exit (E_BAD_ARG); - } +- exit(E_BAD_ARG); ++ fail_exit (E_BAD_ARG); + } - /* + return; @@ -261,11 +270,11 @@ static void close_files (void) fprintf (stderr, _("%s: failure while writing changes to %s\n"), @@ -904,7 +904,7 @@ diff -up shadow-4.15.1/src/newgrp.c.audit-update shadow-4.15.1/src/newgrp.c +++ shadow-4.15.1/src/newgrp.c 2024-05-20 11:52:05.640758536 +0200 @@ -188,10 +188,10 @@ static void check_perms (const struct gr if (grp->gr_passwd[0] == '\0' || - strcmp (cpasswd, grp->gr_passwd) != 0) { + !streq(cpasswd, grp->gr_passwd)) { #ifdef WITH_AUDIT - SNPRINTF(audit_buf, "authentication new-gid=%lu", + SNPRINTF(audit_buf, "authentication new_gid=%lu", @@ -1249,7 +1249,7 @@ diff -up shadow-4.15.1/src/useradd.c.audit-update shadow-4.15.1/src/useradd.c #endif SYSLOG ((LOG_INFO, @@ -1556,7 +1515,7 @@ static void process_flags (int argc, cha - Prog, user_name); + } #ifdef WITH_AUDIT audit_logger (AUDIT_ADD_USER, Prog, - "adding user", @@ -1742,7 +1742,7 @@ diff -up shadow-4.15.1/src/usermod.c.audit-update shadow-4.15.1/src/usermod.c + "updating-passwd", user_newname, user_newid, 1); #endif SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); - strcpy (buf, "!"); + xasprintf(&buf, "!%s", pw_pass); @@ -457,14 +457,14 @@ static char *new_pw_passwd (char *pw_pas #ifdef WITH_AUDIT diff --git a/shadow-utils.spec b/shadow-utils.spec index 31cd953..acce5d0 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.16.0 -Release: 7%{?dist} +Version: 4.17.0~rc1 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/v%{version}/shadow-%{version}.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.0-rc1/shadow-4.17.0-rc1.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.0-rc1/shadow-4.17.0-rc1.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -23,11 +23,9 @@ Patch0: shadow-4.15.0-manfix.patch # Date parsing improvement - could be upstreamed Patch1: shadow-4.15.0-date-parsing.patch # Audit message changes - partially upstreamed -Patch2: shadow-4.15.1-audit-update.patch +Patch2: shadow-4.17.0-audit-update.patch # Probably non-upstreamable -Patch3: shadow-4.15.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/903593249630054ab5df327481f7386f718088cc -Patch4: shadow-4.16.0-useradd-fix-write-full-return.patch +Patch3: shadow-4.17.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -104,7 +102,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-%{version} +%autosetup -p 1 -S git -n shadow-4.17.0-rc1 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -170,7 +168,6 @@ mv -v $RPM_BUILD_ROOT/usr/sbin/* $RPM_BUILD_ROOT%{_bindir}/ rm $RPM_BUILD_ROOT%{_bindir}/chfn rm $RPM_BUILD_ROOT%{_bindir}/chsh rm $RPM_BUILD_ROOT%{_bindir}/expiry -rm $RPM_BUILD_ROOT%{_bindir}/groups rm $RPM_BUILD_ROOT%{_bindir}/login rm $RPM_BUILD_ROOT%{_bindir}/su rm $RPM_BUILD_ROOT%{_bindir}/faillog @@ -182,8 +179,6 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/chsh.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chsh.* rm $RPM_BUILD_ROOT%{_mandir}/man1/expiry.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/expiry.* -rm $RPM_BUILD_ROOT%{_mandir}/man1/groups.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man1/groups.* rm $RPM_BUILD_ROOT%{_mandir}/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* @@ -292,6 +287,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Dec 9 2024 Iker Pedrosa - 2:4.17.0~rc1-1 +- Rebase to version 4.17.0-rc1 + * Tue Nov 12 2024 Iker Pedrosa - 2:4.16.0-7 - SPDX license migration for subpackages diff --git a/sources b/sources index a2d890c..f611d3a 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.16.0.tar.xz) = 3986572c74cce013c733c592ef5a8113e69bba8fee74fb697fe8206bd616d29553e42822e663478db81b3e17b26b403bc69b3492dd981b87643b0e1c55035ecf -SHA512 (shadow-4.16.0.tar.xz.asc) = be98d5c157115869e23932e347b609ab342c0bc1a9d716d07ae61b497779c1a5a436534eb3ee0294687eca5831e193776a005d13b43b6979c8acd380b9372550 +SHA512 (shadow-4.17.0-rc1.tar.xz) = debf2d16fc50de8e118cde71ff85597829849548e3e608025c827ed0fa21dfd784e41b79dda87a06ae0a2f3869edf2c4a4ebd95e7b5b4cae04ea8790eae21f7a +SHA512 (shadow-4.17.0-rc1.tar.xz.asc) = 5ae16f8e17ee1d5453060233a3eefaae932e35f106661023af0aabdf370a1870d279a8f7944b7b87e8cecc836fe4fc9b68a5349b84e954fea692fab13d246f20 From be06553cde095f6cd65820caec503ffb7a43e2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sun, 22 Dec 2024 15:31:08 +0100 Subject: [PATCH 084/118] Remove potentially dangerous {C,LD}FLAGS shenanigans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fail linking if there are undefined symbols at link-time. Signed-off-by: Björn Esser --- shadow-utils.spec | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index acce5d0..a89e964 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.17.0~rc1 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -16,6 +16,8 @@ Source7: passwd.pamd ### Globals ### %global includesubiddir %{_includedir}/shadow +# Fail linking if there are undefined symbols. +%global _ld_strict_symbol_defs 1 ### Patches ### # Misc manual page changes - non-upstreamable @@ -114,15 +116,6 @@ cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml rm lib/getdate.c %build -%ifarch sparc64 -#sparc64 need big PIE -export CFLAGS="$RPM_OPT_FLAGS -fPIE" -export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" -%else -export CFLAGS="$RPM_OPT_FLAGS -fpie" -export LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" -%endif - autoreconf %configure \ --disable-account-tools-setuid \ @@ -287,6 +280,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sun Dec 22 2024 Björn Esser - 2:4.17.0~rc1-2 +- Remove potentially dangerous {C,LD}FLAGS shenanigans +- Fail linking if there are undefined symbols at link-time + * Mon Dec 9 2024 Iker Pedrosa - 2:4.17.0~rc1-1 - Rebase to version 4.17.0-rc1 From 35488fe25418e771073a691604dd0340874d59dd Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 26 Dec 2024 09:51:56 +0100 Subject: [PATCH 085/118] Rebase to version 4.17.0 Resolves: #2293678 Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ shadow-4.17.0-audit-update.patch | 4 ++-- shadow-utils.spec | 11 +++++++---- sources | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 62cae0c..1585108 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.16.0.tar.xz.asc /shadow-4.17.0-rc1.tar.xz /shadow-4.17.0-rc1.tar.xz.asc +/shadow-4.17.0.tar.xz +/shadow-4.17.0.tar.xz.asc diff --git a/shadow-4.17.0-audit-update.patch b/shadow-4.17.0-audit-update.patch index fc05c51..3ae6400 100644 --- a/shadow-4.17.0-audit-update.patch +++ b/shadow-4.17.0-audit-update.patch @@ -903,8 +903,8 @@ diff -up shadow-4.15.1/src/newgrp.c.audit-update shadow-4.15.1/src/newgrp.c --- shadow-4.15.1/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 +++ shadow-4.15.1/src/newgrp.c 2024-05-20 11:52:05.640758536 +0200 @@ -188,10 +188,10 @@ static void check_perms (const struct gr - if (grp->gr_passwd[0] == '\0' || - !streq(cpasswd, grp->gr_passwd)) { + if (streq(grp->gr_passwd, "") || + !streq(grp->gr_passwd, cpasswd)) { #ifdef WITH_AUDIT - SNPRINTF(audit_buf, "authentication new-gid=%lu", + SNPRINTF(audit_buf, "authentication new_gid=%lu", diff --git a/shadow-utils.spec b/shadow-utils.spec index a89e964..7d1bb53 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.17.0~rc1 +Version: 4.17.0 Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.0-rc1/shadow-4.17.0-rc1.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.0-rc1/shadow-4.17.0-rc1.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.0/shadow-4.17.0.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.0/shadow-4.17.0.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -104,7 +104,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.17.0-rc1 +%autosetup -p 1 -S git -n shadow-4.17.0 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -280,6 +280,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Dec 26 2024 Iker Pedrosa - 2:4.17.0 +- Rebase to version 4.17.0. Resolves: #2293678 + * Sun Dec 22 2024 Björn Esser - 2:4.17.0~rc1-2 - Remove potentially dangerous {C,LD}FLAGS shenanigans - Fail linking if there are undefined symbols at link-time diff --git a/sources b/sources index f611d3a..4d4e5ae 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.17.0-rc1.tar.xz) = debf2d16fc50de8e118cde71ff85597829849548e3e608025c827ed0fa21dfd784e41b79dda87a06ae0a2f3869edf2c4a4ebd95e7b5b4cae04ea8790eae21f7a -SHA512 (shadow-4.17.0-rc1.tar.xz.asc) = 5ae16f8e17ee1d5453060233a3eefaae932e35f106661023af0aabdf370a1870d279a8f7944b7b87e8cecc836fe4fc9b68a5349b84e954fea692fab13d246f20 +SHA512 (shadow-4.17.0.tar.xz) = 36fb4a17cce43f5c97f669124c9419376ccbaa04fee8865fe590f525f3b2d14ce6422da6c52544e7d563ac8bebb29532ac9935c3ecd298718814118a932a00c7 +SHA512 (shadow-4.17.0.tar.xz.asc) = 53143dcdb637aa3c579ac5302904c10ad0e39611c0384061d8d7f06a03ae4612a5e42c6c1fd6dc8da0220d27fc429870f749ab9be508f58966f362e80a6fb43b From edb8f1a314e7da724556c551687f6b190d92e6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 12 Jan 2025 14:41:48 +0100 Subject: [PATCH 086/118] Rebuilt for the bin-sbin merge (2nd attempt) https://fedoraproject.org/wiki/Changes/Unify_bin_and_sbin --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 7d1bb53..bf4d6af 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.17.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -280,6 +280,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek - 2:4.17.0-3 +- Rebuilt for the bin-sbin merge (2nd attempt) + * Thu Dec 26 2024 Iker Pedrosa - 2:4.17.0 - Rebase to version 4.17.0. Resolves: #2293678 From 7b5d11c4b7d0d91c4d879b18facaefd7975544a5 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sun, 19 Jan 2025 10:32:26 +0000 Subject: [PATCH 087/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index bf4d6af..cdd4784 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.17.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -280,6 +280,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sun Jan 19 2025 Fedora Release Engineering - 2:4.17.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek - 2:4.17.0-3 - Rebuilt for the bin-sbin merge (2nd attempt) From f872b43d352b5d97f9f7f5ee091b5cd7cb3ffa17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sat, 1 Feb 2025 19:57:31 +0100 Subject: [PATCH 088/118] Add explicit BR: libxcrypt-devel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- shadow-utils.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index cdd4784..42b8d1d 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.17.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -53,6 +53,7 @@ BuildRequires: libeconf-devel BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: libsemanage-devel BuildRequires: libtool +BuildRequires: libxcrypt-devel BuildRequires: libxslt BuildRequires: make BuildRequires: pam-devel @@ -280,6 +281,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Feb 01 2025 Björn Esser - 2:4.17.0-5 +- Add explicit BR: libxcrypt-devel + * Sun Jan 19 2025 Fedora Release Engineering - 2:4.17.0-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild From 889277e842663629aa7f9fd1795bcc82201b4b39 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 20 Mar 2025 11:55:30 +0100 Subject: [PATCH 089/118] Rebase to version 4.17.4 Resolves: #2353491 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + shadow-4.15.0-date-parsing.patch | 69 - shadow-4.17.0-audit-update.patch | 2053 ----------------- ...> shadow-4.17.4-account-tools-setuid.patch | 16 +- shadow-utils.spec | 26 +- sources | 4 +- 6 files changed, 26 insertions(+), 2144 deletions(-) delete mode 100644 shadow-4.15.0-date-parsing.patch delete mode 100644 shadow-4.17.0-audit-update.patch rename shadow-4.17.0-account-tools-setuid.patch => shadow-4.17.4-account-tools-setuid.patch (98%) diff --git a/.gitignore b/.gitignore index 1585108..ff11943 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.17.0-rc1.tar.xz.asc /shadow-4.17.0.tar.xz /shadow-4.17.0.tar.xz.asc +/shadow-4.17.4.tar.xz +/shadow-4.17.4.tar.xz.asc diff --git a/shadow-4.15.0-date-parsing.patch b/shadow-4.15.0-date-parsing.patch deleted file mode 100644 index 272d2df..0000000 --- a/shadow-4.15.0-date-parsing.patch +++ /dev/null @@ -1,69 +0,0 @@ -Index: shadow-4.5/lib/getdate.y -=================================================================== ---- shadow-4.5.orig/lib/getdate.y -+++ shadow-4.5/lib/getdate.y -@@ -152,6 +152,7 @@ static int yyHaveDay; - static int yyHaveRel; - static int yyHaveTime; - static int yyHaveZone; -+static int yyHaveYear; - static int yyTimezone; - static int yyDay; - static int yyHour; -@@ -293,18 +294,21 @@ date : tUNUMBER '/' tUNUMBER { - yyDay = $3; - yyYear = $5; - } -+ yyHaveYear++; - } - | tUNUMBER tSNUMBER tSNUMBER { - /* ISO 8601 format. yyyy-mm-dd. */ - yyYear = $1; - yyMonth = -$2; - yyDay = -$3; -+ yyHaveYear++; - } - | tUNUMBER tMONTH tSNUMBER { - /* e.g. 17-JUN-1992. */ - yyDay = $1; - yyMonth = $2; - yyYear = -$3; -+ yyHaveYear++; - } - | tMONTH tUNUMBER { - yyMonth = $1; -@@ -314,6 +318,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $1; - yyDay = $2; - yyYear = $4; -+ yyHaveYear++; - } - | tUNUMBER tMONTH { - yyMonth = $2; -@@ -323,6 +328,7 @@ date : tUNUMBER '/' tUNUMBER { - yyMonth = $2; - yyDay = $1; - yyYear = $3; -+ yyHaveYear++; - } - ; - -@@ -395,7 +401,8 @@ relunit : tUNUMBER tYEAR_UNIT { - - number : tUNUMBER - { -- if ((yyHaveTime != 0) && (yyHaveDate != 0) && (yyHaveRel == 0)) -+ if ((yyHaveTime != 0 || $1 >= 100) && !yyHaveYear -+ && (yyHaveDate != 0) && (yyHaveRel == 0)) - yyYear = $1; - else - { -@@ -802,7 +809,7 @@ yylex (void) - return LookupWord (buff); - } - if (c != '(') -- return *yyInput++; -+ return (unsigned char)*yyInput++; - Count = 0; - do - { diff --git a/shadow-4.17.0-audit-update.patch b/shadow-4.17.0-audit-update.patch deleted file mode 100644 index 3ae6400..0000000 --- a/shadow-4.17.0-audit-update.patch +++ /dev/null @@ -1,2053 +0,0 @@ -diff -up shadow-4.15.1/lib/audit_help.c.audit-update shadow-4.15.1/lib/audit_help.c ---- shadow-4.15.1/lib/audit_help.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/audit_help.c 2024-05-20 11:52:05.639758532 +0200 -@@ -48,7 +48,7 @@ void audit_help_open (void) - * This function will log a message to the audit system using a predefined - * message format. Parameter usage is as follows: - * -- * type - type of message: AUDIT_USER_CHAUTHTOK for changing any account -+ * type - type of message: AUDIT_USER_MGMT for changing any account - * attributes. - * pgname - program's name - * op - operation. "adding user", "changing finger info", "deleting group" -@@ -68,6 +68,39 @@ void audit_logger (int type, MAYBE_UNUSE - } - } - -+/* -+ * This function will log a message to the audit system using a predefined -+ * message format. Parameter usage is as follows: -+ * -+ * type - type of message: AUDIT_USER_MGMT for changing any account -+ * attributes. -+ * pgname - program's name -+ * op - operation. "adding user", "changing finger info", "deleting group" -+ * name - user's account or group name. If not available use NULL. -+ * id - uid or gid that the operation is being performed on. This is used -+ * only when user is NULL. -+ * grp - group name associated with event -+ */ -+void audit_logger_with_group (int type, MAYBE_UNUSED const char *pgname, -+ const char *op, const char *name, unsigned int id, -+ const char *grp, shadow_audit_result result) -+{ -+ int len; -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1], buf[1024]; -+ if (audit_fd < 0) { -+ return; -+ } -+ len = strnlen(grp, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(grp, len)) { -+ snprintf(buf, sizeof(buf), "%s grp=%s", op, -+ audit_encode_value(enc_group, grp, len)); -+ } else { -+ snprintf(buf, sizeof(buf), "%s grp=\"%s\"", op, grp); -+ } -+ audit_log_acct_message (audit_fd, type, NULL, buf, name, id, -+ NULL, NULL, NULL, (int) result); -+} -+ - void audit_logger_message (const char *message, shadow_audit_result result) - { - if (audit_fd < 0) { -diff -up shadow-4.15.1/lib/cleanup_group.c.audit-update shadow-4.15.1/lib/cleanup_group.c ---- shadow-4.15.1/lib/cleanup_group.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/cleanup_group.c 2024-05-20 11:52:05.639758532 +0200 -@@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cle - gr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -80,7 +80,7 @@ void cleanup_report_mod_gshadow (void *c - sgr_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -101,7 +101,7 @@ void cleanup_report_add_group_group (voi - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, log_get_progname(), -- "adding group to /etc/group", -+ "adding-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -120,8 +120,8 @@ void cleanup_report_add_group_gshadow (v - - SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), -- "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), -+ "adding-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -143,8 +143,8 @@ void cleanup_report_del_group_group (voi - "failed to remove group %s from %s", - name, gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), -- "removing group from /etc/group", -+ audit_logger (AUDIT_DEL_GROUP, log_get_progname(), -+ "removing-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -166,8 +166,8 @@ void cleanup_report_del_group_gshadow (v - "failed to remove group %s from %s", - name, sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, log_get_progname(), -- "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, log_get_progname(), -+ "removing-shadow-group", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -187,7 +187,7 @@ void cleanup_unlock_group (MAYBE_UNUSED - log_get_progname(), gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking group file", -+ audit_logger_message ("unlocking-group", - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -207,7 +207,7 @@ void cleanup_unlock_gshadow (MAYBE_UNUSE - log_get_progname(), sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking gshadow file", -+ audit_logger_message ("unlocking-gshadow", - SHADOW_AUDIT_FAILURE); - #endif - } -diff -up shadow-4.15.1/lib/cleanup_user.c.audit-update shadow-4.15.1/lib/cleanup_user.c ---- shadow-4.15.1/lib/cleanup_user.c.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/cleanup_user.c 2024-05-20 11:52:05.639758532 +0200 -@@ -44,7 +44,7 @@ void cleanup_report_mod_passwd (void *cl - pw_dbname (), - info->action)); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, log_get_progname(), -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), - info->audit_msg, - info->name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); -@@ -65,7 +65,7 @@ void cleanup_report_add_user_passwd (voi - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, log_get_progname(), -- "adding user to /etc/passwd", -+ "adding-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -84,8 +84,8 @@ void cleanup_report_add_user_shadow (voi - - SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, log_get_progname(), -- "adding user to /etc/shadow", -+ audit_logger (AUDIT_USER_MGMT, log_get_progname(), -+ "adding-shadow-user", - name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -104,7 +104,7 @@ void cleanup_unlock_passwd (MAYBE_UNUSED - log_get_progname(), pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking passwd file", -+ audit_logger_message ("unlocking-passwd", - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -123,7 +123,7 @@ void cleanup_unlock_shadow (MAYBE_UNUSED - log_get_progname(), spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT -- audit_logger_message ("unlocking shadow file", -+ audit_logger_message ("unlocking-shadow", - SHADOW_AUDIT_FAILURE); - #endif - } -diff -up shadow-4.15.1/lib/prototypes.h.audit-update shadow-4.15.1/lib/prototypes.h ---- shadow-4.15.1/lib/prototypes.h.audit-update 2024-03-01 02:50:52.000000000 +0100 -+++ shadow-4.15.1/lib/prototypes.h 2024-05-20 11:52:05.639758532 +0200 -@@ -198,12 +198,21 @@ extern int audit_fd; - extern void audit_help_open (void); - /* Use AUDIT_NO_ID when a name is provided to audit_logger instead of an ID */ - #define AUDIT_NO_ID ((unsigned int) -1) -+#ifndef AUDIT_GRP_MGMT -+#define AUDIT_GRP_MGMT 1132 /* Group account was modified */ -+#endif -+#ifndef AUDIT_GRP_CHAUTHTOK -+#define AUDIT_GRP_CHAUTHTOK 1133 /* Group account password was changed */ -+#endif - typedef enum { - SHADOW_AUDIT_FAILURE = 0, - SHADOW_AUDIT_SUCCESS = 1} shadow_audit_result; - extern void audit_logger (int type, const char *pgname, const char *op, - const char *name, unsigned int id, - shadow_audit_result result); -+void audit_logger_with_group (int type, MAYBE_UNUSED const char *pgname, -+ const char *op, const char *name, unsigned int id, -+ const char *grp, shadow_audit_result result); - void audit_logger_message (const char *message, shadow_audit_result result); - #endif - -diff -up shadow-4.15.1/src/chage.c.audit-update shadow-4.15.1/src/chage.c ---- shadow-4.15.1/src/chage.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/chage.c 2024-05-20 11:52:05.639758532 +0200 -@@ -110,8 +110,8 @@ fail_exit (int code) - - #ifdef WITH_AUDIT - if (E_SUCCESS != code) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change age", user_name, user_uid, 0); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-age", user_name, user_uid, SHADOW_AUDIT_FAILURE); - } - #endif - -@@ -846,10 +846,7 @@ int main (int argc, char **argv) - fprintf (stderr, _("%s: Permission denied.\n"), Prog); - fail_exit (E_NOPERM); - } --#ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "display aging info", user_name, user_uid, 1); --#endif -+ /* Displaying fields is not of interest to audit */ - list_fields (); - fail_exit (E_SUCCESS); - } -@@ -868,39 +865,39 @@ int main (int argc, char **argv) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change all aging information", -- user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-all-aging-information", -+ user_name, user_uid, SHADOW_AUDIT_SUCCESS); - } - #endif - } else { - #ifdef WITH_AUDIT - if (Mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change max age", user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-max-age", user_name, user_uid, SHADOW_AUDIT_SUCCESS); - } - if (mflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change min age", user_name, user_uid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-min-age", user_name, user_uid, 1); - } - if (dflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change last change date", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-last-change-date", - user_name, user_uid, 1); - } - if (Wflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change passwd warning", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-passwd-warning", - user_name, user_uid, 1); - } - if (Iflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change inactive days", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-inactive-days", - user_name, user_uid, 1); - } - if (Eflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "change passwd expiration", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "change-passwd-expiration", - user_name, user_uid, 1); - } - #endif -diff -up shadow-4.15.1/src/gpasswd.c.audit-update shadow-4.15.1/src/gpasswd.c ---- shadow-4.15.1/src/gpasswd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/gpasswd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -125,7 +125,7 @@ static void usage (int status) - (void) fputs (_(" -d, --delete USER remove USER from GROUP\n"), usageout); - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -Q, --root CHROOT_DIR directory to chroot into\n"), usageout); -- (void) fputs (_(" -r, --remove-password remove the GROUP's password\n"), usageout); -+ (void) fputs (_(" -r, --delete-password remove the GROUP's password\n"), usageout); - (void) fputs (_(" -R, --restrict restrict access to GROUP to its members\n"), usageout); - (void) fputs (_(" -M, --members USER,... set the list of members of GROUP\n"), usageout); - #ifdef SHADOWGRP -@@ -384,20 +384,14 @@ static void open_files (void) - - static void log_gpasswd_failure (const char *suffix) - { --#ifdef WITH_AUDIT -- char buf[1024]; --#endif -- - if (aflg) { - SYSLOG ((LOG_ERR, - "%s failed to add user %s to group %s%s", - myname, user, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to add user %s to group %s%s", -- myname, user, group, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (dflg) { -@@ -405,11 +399,9 @@ static void log_gpasswd_failure (const c - "%s failed to remove user %s from group %s%s", - myname, user, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to remove user %s from group %s%s", -- myname, user, group, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (rflg) { -@@ -417,11 +409,9 @@ static void log_gpasswd_failure (const c - "%s failed to remove password of group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to remove password of group %s%s", -- myname, group, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "delete-group-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (Rflg) { -@@ -429,11 +419,9 @@ static void log_gpasswd_failure (const c - "%s failed to restrict access to group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to restrict access to group %s%s", -- myname, group, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "restrict-group", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } else if (Aflg || Mflg) { -@@ -443,11 +431,9 @@ static void log_gpasswd_failure (const c - "%s failed to set the administrators of group %s to %s%s", - myname, group, admins, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to set the administrators of group %s to %s%s", -- myname, group, admins, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "set-admins-of-group", -+ admins, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -457,11 +443,9 @@ static void log_gpasswd_failure (const c - "%s failed to set the members of group %s to %s%s", - myname, group, members, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to set the members of group %s to %s%s", -- myname, group, members, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-users-to-group", -+ members, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -470,11 +454,9 @@ static void log_gpasswd_failure (const c - "%s failed to change password of group %s%s", - myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "%s failed to change password of group %s%s", -- myname, group, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "change-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_FAILURE); - #endif - } -@@ -514,11 +496,9 @@ static void log_gpasswd_success (const c - "user %s added by %s to group %s%s", - user, myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "user %s added by %s to group %s%s", -- user, myname, group, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (dflg) { -@@ -526,11 +506,9 @@ static void log_gpasswd_success (const c - "user %s removed by %s from group %s%s", - user, myname, group, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "user %s removed by %s from group %s%s", -- user, myname, group, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (rflg) { -@@ -540,9 +518,9 @@ static void log_gpasswd_success (const c - #ifdef WITH_AUDIT - SNPRINTF(buf, "password of group %s removed by %s%s", - group, myname, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "delete-group-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (Rflg) { -@@ -552,9 +530,9 @@ static void log_gpasswd_success (const c - #ifdef WITH_AUDIT - SNPRINTF(buf, "access to group %s restricted by %s%s", - group, myname, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "restrict-group", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } else if (Aflg || Mflg) { -@@ -564,11 +542,9 @@ static void log_gpasswd_success (const c - "administrators of group %s set by %s to %s%s", - group, myname, admins, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "administrators of group %s set by %s to %s%s", -- group, myname, admins, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "set-admins-of-group", -+ admins, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -@@ -578,11 +554,9 @@ static void log_gpasswd_success (const c - "members of group %s set by %s to %s%s", - group, myname, members, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "members of group %s set by %s to %s%s", -- group, myname, members, suffix); -- audit_logger (AUDIT_USER_ACCT, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-users-to-group", -+ members, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -@@ -591,11 +565,9 @@ static void log_gpasswd_success (const c - "password of group %s changed by %s%s", - group, myname, suffix)); - #ifdef WITH_AUDIT -- SNPRINTF(buf, "password of group %s changed by %s%s", -- group, myname, suffix); -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- buf, -- group, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_CHAUTHTOK, Prog, -+ "change-password", -+ myname, AUDIT_NO_ID, group, - SHADOW_AUDIT_SUCCESS); - #endif - } -diff -up shadow-4.15.1/src/groupadd.c.audit-update shadow-4.15.1/src/groupadd.c ---- shadow-4.15.1/src/groupadd.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupadd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -115,6 +115,15 @@ usage (int status) - exit (status); - } - -+static void fail_exit(int status) -+{ -+#ifdef WITH_AUDIT -+ audit_logger(AUDIT_ADD_GROUP, Prog, "add-group", group_name, -+ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -+#endif -+ exit (status); -+} -+ - /* - * new_grent - initialize the values in a group file entry - * -@@ -211,7 +220,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), grp.gr_name); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP - /* -@@ -221,7 +230,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), sgrp.sg_name); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #endif /* SHADOWGRP */ - } -@@ -245,7 +254,7 @@ static void check_new_name (void) - fprintf(stderr, _("%s: '%s' is not a valid group name\n"), - Prog, group_name); - -- exit(E_BAD_ARG); -+ fail_exit (E_BAD_ARG); - } - - return; -@@ -261,11 +270,11 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/group", -+ "add-group", - group_name, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "group added to %s: name=%s, GID=%u", -@@ -282,11 +291,11 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group to /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "add-shadow-group", - group_name, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "group added to %s: name=%s", -@@ -299,10 +308,6 @@ static void close_files (void) - #endif /* SHADOWGRP */ - - /* Report success at the system level */ --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_GROUP, Prog, -- "", group_name, group_id, SHADOW_AUDIT_SUCCESS); --#endif - SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", - group_name, (unsigned int) group_id)); - del_cleanup (cleanup_report_add_group); -@@ -320,7 +325,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_group, NULL); - -@@ -330,7 +335,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_gshadow, NULL); - } -@@ -346,7 +351,7 @@ static void open_files (void) - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s: %s\n"), Prog, gr_dbname (), strerror(errno)); - SYSLOG ((LOG_WARN, "cannot open %s: %s", gr_dbname (), strerror(errno))); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef SHADOWGRP -@@ -356,7 +361,7 @@ static void open_files (void) - _("%s: cannot open %s: %s\n"), - Prog, sgr_dbname (), strerror(errno)); - SYSLOG ((LOG_WARN, "cannot open %s: %s", sgr_dbname (), strerror(errno))); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -493,7 +498,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: group '%s' already exists\n"), - Prog, group_name); -- exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE); - } - - if (gflg && (prefix_getgrgid (group_id) != NULL)) { -@@ -512,7 +517,7 @@ static void check_flags (void) - fprintf (stderr, - _("%s: GID '%lu' already exists\n"), - Prog, (unsigned long) group_id); -- exit (E_GID_IN_USE); -+ fail_exit (E_GID_IN_USE); - } - } - } -@@ -540,7 +545,7 @@ static void check_perms (void) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); -@@ -560,7 +565,7 @@ static void check_perms (void) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- exit (1); -+ fail_exit (1); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -591,7 +596,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot setup cleanup service.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - /* -@@ -618,7 +623,7 @@ int main (int argc, char **argv) - - if (!gflg) { - if (find_new_gid (rflg, &group_id, NULL) < 0) { -- exit (E_GID_IN_USE); -+ fail_exit (E_GID_IN_USE); - } - } - -diff -up shadow-4.15.1/src/groupdel.c.audit-update shadow-4.15.1/src/groupdel.c ---- shadow-4.15.1/src/groupdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupdel.c 2024-05-20 11:52:05.640758536 +0200 -@@ -87,6 +87,15 @@ usage (int status) - exit (status); - } - -+static void fail_exit(int status) -+{ -+#ifdef WITH_AUDIT -+ audit_logger(AUDIT_GRP_MGMT, Prog, "delete-group", group_name, -+ AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); -+#endif -+ exit (status); -+} -+ - /* - * grp_update - update group file entries - * -@@ -113,7 +122,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, group_name, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef SHADOWGRP -@@ -125,7 +134,7 @@ static void grp_update (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, group_name, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -144,12 +153,12 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_GROUP, Prog, -- "removing group from /etc/group", -+ "delete-group", - group_name, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -168,12 +177,12 @@ static void close_files (void) - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "removing group from /etc/gshadow", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "delete-shadow-group", - group_name, group_id, SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -186,11 +195,6 @@ static void close_files (void) - } - #endif /* SHADOWGRP */ - -- /* Report success at the system level */ --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "", group_name, group_id, SHADOW_AUDIT_SUCCESS); --#endif - SYSLOG ((LOG_INFO, "group '%s' removed\n", group_name)); - del_cleanup (cleanup_report_del_group); - } -@@ -207,7 +211,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_group, NULL); - #ifdef SHADOWGRP -@@ -216,7 +220,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - add_cleanup (cleanup_unlock_gshadow, NULL); - } -@@ -234,7 +238,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP - if (is_shadow_grp) { -@@ -243,7 +247,7 @@ static void open_files (void) - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); -- exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE); - } - } - #endif /* SHADOWGRP */ -@@ -284,7 +288,7 @@ static void group_busy (gid_t gid) - fprintf (stderr, - _("%s: cannot remove the primary group of user '%s'\n"), - Prog, pwd->pw_name); -- exit (E_GROUP_BUSY); -+ fail_exit (E_GROUP_BUSY); - } - - /* -@@ -368,7 +372,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot setup cleanup service.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - process_flags (argc, argv); -@@ -382,7 +386,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- exit (1); -+ fail_exit (1); - } - - retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); -@@ -403,7 +407,7 @@ int main (int argc, char **argv) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- exit (1); -+ fail_exit (1); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -423,7 +427,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: group '%s' does not exist\n"), - Prog, group_name); -- exit (E_NOTFOUND); -+ fail_exit (E_NOTFOUND); - } - - group_id = grp->gr_gid; -diff -up shadow-4.15.1/src/groupmod.c.audit-update shadow-4.15.1/src/groupmod.c ---- shadow-4.15.1/src/groupmod.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/groupmod.c 2024-05-20 11:52:05.640758536 +0200 -@@ -474,7 +474,7 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_group.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -497,7 +497,14 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ /* If both happened, log password change as its more important */ -+ if (pflg) -+ audit_logger (AUDIT_GRP_CHAUTHTOK, Prog, -+ info_gshadow.audit_msg, -+ group_name, AUDIT_NO_ID, -+ SHADOW_AUDIT_SUCCESS); -+ else -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_gshadow.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -520,7 +527,7 @@ static void close_files (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -+ audit_logger (AUDIT_GRP_MGMT, Prog, - info_passwd.audit_msg, - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); -@@ -535,8 +542,8 @@ static void close_files (void) - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_ACCT, Prog, -- "modifying group", -+ audit_logger (AUDIT_GRP_MGMT, Prog, -+ "modify-group", - group_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -diff -up shadow-4.15.1/src/newgrp.c.audit-update shadow-4.15.1/src/newgrp.c ---- shadow-4.15.1/src/newgrp.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/newgrp.c 2024-05-20 11:52:05.640758536 +0200 -@@ -188,10 +188,10 @@ static void check_perms (const struct gr - if (streq(grp->gr_passwd, "") || - !streq(grp->gr_passwd, cpasswd)) { - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "authentication new-gid=%lu", -+ SNPRINTF(audit_buf, "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_INFO, - "Invalid password for group '%s' from '%s'", -@@ -201,10 +201,10 @@ static void check_perms (const struct gr - goto failure; - } - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "authentication new-gid=%lu", -+ SNPRINTF(audit_buf, "authentication new_gid=%lu", - (unsigned long) grp->gr_gid); - audit_logger (AUDIT_GRP_AUTH, Prog, -- audit_buf, NULL, getuid (), 1); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); - #endif - } - -@@ -215,16 +215,6 @@ failure: - * harm. -- JWP - */ - closelog (); --#ifdef WITH_AUDIT -- if (groupname) { -- SNPRINTF(audit_buf, "changing new-group=%s", groupname); -- audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -- } else { -- audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -- } --#endif - exit (EXIT_FAILURE); - } - -@@ -298,13 +288,23 @@ static void syslog_sg (const char *name, - is_newgrp ? "newgrp" : "sg", strerror (errno)); - #ifdef WITH_AUDIT - if (group) { -- SNPRINTF(audit_buf, -- "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", -+ group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -440,7 +440,7 @@ int main (int argc, char **argv) - Prog); - #ifdef WITH_AUDIT - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", - (unsigned long) getuid ())); -@@ -556,12 +556,22 @@ int main (int argc, char **argv) - perror ("getgroups"); - #ifdef WITH_AUDIT - if (group) { -- SNPRINTF(audit_buf, "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -@@ -715,9 +725,9 @@ int main (int argc, char **argv) - if (setgid (gid) != 0) { - perror ("setgid"); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -725,9 +735,9 @@ int main (int argc, char **argv) - if (setuid (getuid ()) != 0) { - perror ("setuid"); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - exit (EXIT_FAILURE); - } -@@ -740,9 +750,9 @@ int main (int argc, char **argv) - closelog (); - execl (SHELL, "sh", "-c", command, (char *) NULL); - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - #endif - perror (SHELL); - exit ((errno == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC); -@@ -806,9 +816,9 @@ int main (int argc, char **argv) - } - - #ifdef WITH_AUDIT -- SNPRINTF(audit_buf, "changing new-gid=%lu", (unsigned long) gid); -+ SNPRINTF(audit_buf, "changing new_gid=%lu", (unsigned long) gid); - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 1); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_SUCCESS); - #endif - /* - * Exec the login shell and go away. We are trying to get back to -@@ -832,12 +842,22 @@ int main (int argc, char **argv) - closelog (); - #ifdef WITH_AUDIT - if (NULL != group) { -- SNPRINTF(audit_buf, "changing new-group=%s", group); -+ char enc_group[(GROUP_NAME_MAX_LENGTH*2)+1]; -+ int len = strnlen(group, sizeof(enc_group)/2); -+ if (audit_value_needs_encoding(group, len)) { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=%s", -+ audit_encode_value(enc_group, -+ group, len)); -+ } else { -+ snprintf (audit_buf, sizeof(audit_buf), -+ "changing new_group=\"%s\"", group); -+ } - audit_logger (AUDIT_CHGRP_ID, Prog, -- audit_buf, NULL, getuid (), 0); -+ audit_buf, NULL, getuid (), SHADOW_AUDIT_FAILURE); - } else { - audit_logger (AUDIT_CHGRP_ID, Prog, -- "changing", NULL, getuid (), 0); -+ "changing", NULL, getuid (), SHADOW_AUDIT_FAILURE); - } - #endif - exit (EXIT_FAILURE); -diff -up shadow-4.15.1/src/useradd.c.audit-update shadow-4.15.1/src/useradd.c ---- shadow-4.15.1/src/useradd.c.audit-update 2024-05-20 11:52:05.635758519 +0200 -+++ shadow-4.15.1/src/useradd.c 2024-05-20 11:52:05.640758536 +0200 -@@ -245,6 +245,8 @@ static FILE *fmkstemp(char *template); - */ - static void fail_exit (int code) - { -+ int type; -+ - if (home_added && rmdir(prefix_user_home) != 0) { - fprintf(stderr, - _("%s: %s was created, but could not be removed\n"), -@@ -255,38 +257,22 @@ static void fail_exit (int code) - if (spw_locked && spw_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); --#ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "unlocking shadow file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - if (pw_locked && pw_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); --#ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "unlocking passwd file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - if (gr_locked && gr_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); --#ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "unlocking group file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --#endif - /* continue */ - } - #ifdef SHADOWGRP - if (sgr_locked && sgr_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); --# ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "unlocking gshadow file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --# endif - /* continue */ - } - #endif -@@ -294,27 +280,23 @@ static void fail_exit (int code) - if (sub_uid_locked && sub_uid_unlock() == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); --# ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, -- "unlocking subordinate user file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --# endif - /* continue */ - } - if (sub_gid_locked && sub_gid_unlock() == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); --# ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, -- "unlocking subordinate group file", -- user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); --# endif - /* continue */ - } - #endif /* ENABLE_SUBIDS */ - - #ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "adding user", -+ if (code == E_PW_UPDATE || code >= E_GRP_UPDATE) -+ type = AUDIT_USER_MGMT; -+ else -+ type = AUDIT_ADD_USER; -+ -+ audit_logger (type, Prog, -+ "add-user", - user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); - #endif - SYSLOG((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); -@@ -727,7 +709,7 @@ static int set_defaults (void) - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USYS_CONFIG, Prog, -- "changing useradd defaults", -+ "changing-useradd-defaults", - NULL, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -1056,12 +1038,6 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); /* XXX */ - } - -@@ -1075,18 +1051,12 @@ static void grp_update (void) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), ngrp->gr_name); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user_name, AUDIT_NO_ID, ngrp->gr_name, - SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -1131,12 +1101,6 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_GRP_UPDATE); /* XXX */ - } - -@@ -1150,18 +1114,13 @@ static void grp_update (void) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), nsgrp->sg_name); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif -+ - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user to shadow group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-to-shadow-group", -+ user_name, AUDIT_NO_ID, nsgrp->sg_name, - SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, -@@ -1556,7 +1515,7 @@ static void process_flags (int argc, cha - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1656,7 +1615,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking shadow file", -+ "unlocking-shadow-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1669,7 +1628,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking passwd file", -+ "unlocking-passwd-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1686,7 +1645,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking subordinate user file", -+ "unlocking-subordinate-user-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1700,7 +1659,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_USER, Prog, -- "unlocking subordinate group file", -+ "unlocking-subordinate-group-file", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1963,7 +1922,7 @@ static void grp_add (void) - Prog, gr_dbname (), grp.gr_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1979,7 +1938,7 @@ static void grp_add (void) - Prog, sgr_dbname (), sgrp.sg_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -@@ -1989,7 +1948,7 @@ static void grp_add (void) - SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); - #ifdef WITH_AUDIT - audit_logger (AUDIT_ADD_GROUP, Prog, -- "adding group", -+ "add-group", - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -2191,11 +2150,6 @@ static void usr_update (unsigned long su - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), spent.sp_namp); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding shadow password", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_PW_UPDATE); - } - #ifdef ENABLE_SUBIDS -@@ -2222,7 +2176,7 @@ static void usr_update (unsigned long su - * and we can use the real ID thereafter. - */ - audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -+ "add-user", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_SUCCESS); - #endif -@@ -2317,10 +2271,6 @@ static void create_home (void) - if (mkdir(path, 0) != 0) { - fprintf(stderr, _("%s: cannot create directory %s\n"), - Prog, path); --#ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "adding home directory", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif - fail_exit(E_HOMEDIR); - } - if (chown(path, 0, 0) < 0) { -@@ -2345,7 +2295,7 @@ static void create_home (void) - } - home_added = true; - #ifdef WITH_AUDIT -- audit_logger(AUDIT_ADD_USER, Prog, "adding home directory", -+ audit_logger(AUDIT_USER_MGMT, Prog, "add-home-dir", - user_name, user_id, SHADOW_AUDIT_SUCCESS); - #endif - #ifdef WITH_SELINUX -@@ -2586,12 +2536,6 @@ int main (int argc, char **argv) - */ - if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ - fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_NAME_IN_USE); - } - -@@ -2607,12 +2551,6 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), - Prog, user_name); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding group", -- user_name, AUDIT_NO_ID, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_NAME_IN_USE); - } - } -@@ -2642,12 +2580,6 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: UID %lu is not unique\n"), - Prog, (unsigned long) user_id); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding user", -- user_name, user_id, -- SHADOW_AUDIT_FAILURE); --#endif - fail_exit (E_UID_IN_USE); - } - } -@@ -2722,9 +2654,9 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), - Prog, user_name, user_selinux); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "adding SELinux user mapping", -- user_name, user_id, 0); -+ audit_logger (AUDIT_ROLE_ASSIGN, Prog, -+ "add-selinux-user-mapping", -+ user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - fail_exit (E_SE_UPDATE); - } -diff -up shadow-4.15.1/src/userdel.c.audit-update shadow-4.15.1/src/userdel.c ---- shadow-4.15.1/src/userdel.c.audit-update 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.1/src/userdel.c 2024-05-20 11:52:05.641758539 +0200 -@@ -206,9 +206,9 @@ static void update_groups (void) - * Update the DBM group file with the new entry as well. - */ - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user from group", -- user_name, user_id, SHADOW_AUDIT_SUCCESS); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-group", -+ user_name, user_id, ngrp->gr_name, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", - user_name, ngrp->gr_name)); -@@ -267,9 +267,9 @@ static void update_groups (void) - exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user from shadow group", -- user_name, user_id, SHADOW_AUDIT_SUCCESS); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "deleting-user-from-shadow-group", -+ user_name, user_id, nsgrp->sg_name, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", - user_name, nsgrp->sg_name)); -@@ -345,9 +345,9 @@ static void remove_usergroup (void) - } - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "deleting group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_DEL_GROUP, Prog, -+ "delete-group", -+ user_name, AUDIT_NO_ID, user_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, -@@ -363,9 +363,9 @@ static void remove_usergroup (void) - fail_exit (E_GRP_UPDATE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_GROUP, Prog, -- "deleting shadow group", -- user_name, AUDIT_NO_ID, -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "delete-shadow-group", -+ user_name, AUDIT_NO_ID, user_name, - SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, -@@ -527,7 +527,7 @@ static void fail_exit (int code) - - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user", -+ "delete-user", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - -@@ -546,22 +546,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking password file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening password file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - if (is_shadow_pwd) { -@@ -569,11 +559,6 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking shadow password file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - spw_locked = true; -@@ -581,11 +566,6 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening shadow password file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_PW_UPDATE); - } - } -@@ -593,21 +573,11 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - #ifdef SHADOWGRP -@@ -616,22 +586,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking shadow group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - sgr_locked= true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening shadow group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_GRP_UPDATE); - } - } -@@ -642,22 +602,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_uid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking subordinate user file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_UID_UPDATE); - } - sub_uid_locked = true; - if (sub_uid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening subordinate user file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_UID_UPDATE); - } - } -@@ -666,22 +616,12 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_gid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "locking subordinate group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_GID_UPDATE); - } - sub_gid_locked = true; - if (sub_gid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); --#ifdef WITH_AUDIT -- audit_logger (AUDIT_DEL_USER, Prog, -- "opening subordinate group file", -- user_name, user_id, SHADOW_AUDIT_FAILURE); --#endif /* WITH_AUDIT */ - fail_exit (E_SUB_GID_UPDATE); - } - } -@@ -726,7 +666,7 @@ static void update_user (void) - #endif /* ENABLE_SUBIDS */ - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user entries", -+ "delete-user", - user_name, user_id, SHADOW_AUDIT_SUCCESS); - #endif /* WITH_AUDIT */ - SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); -@@ -824,7 +764,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - free(mailfile); -@@ -840,7 +780,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - errors = 1; -@@ -849,8 +789,8 @@ static int remove_mailbox (void) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -867,7 +807,7 @@ static int remove_mailbox (void) - mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - free(mailfile); -@@ -883,7 +823,7 @@ static int remove_mailbox (void) - SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - errors = 1; -@@ -892,8 +832,8 @@ static int remove_mailbox (void) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting mail file", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "delete-mail-file", - user_name, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -1104,7 +1044,7 @@ int main (int argc, char **argv) - Prog, user_name); - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user not found", -+ "deleting-user-not-found", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1154,7 +1094,7 @@ int main (int argc, char **argv) - if (!fflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting user logged in", -+ "deleting-user-logged-in", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -1248,8 +1188,8 @@ int main (int argc, char **argv) - #ifdef WITH_AUDIT - else - { -- audit_logger (AUDIT_DEL_USER, Prog, -- "deleting home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "deleting-home-directory", - user_name, user_id, SHADOW_AUDIT_SUCCESS); - } - #endif /* WITH_AUDIT */ -@@ -1257,7 +1197,7 @@ int main (int argc, char **argv) - #ifdef WITH_AUDIT - if (0 != errors) { - audit_logger (AUDIT_DEL_USER, Prog, -- "deleting home directory", -+ "deleting-home-directory", - user_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - } -@@ -1270,8 +1210,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), - Prog, user_name); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "removing SELinux user mapping", -+ audit_logger (AUDIT_ROLE_REMOVE, Prog, -+ "delete-selinux-user-mapping", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ - fail_exit (E_SE_UPDATE); -diff -up shadow-4.15.1/src/usermod.c.audit-update shadow-4.15.1/src/usermod.c ---- shadow-4.15.1/src/usermod.c.audit-update 2024-05-20 11:52:05.638758529 +0200 -+++ shadow-4.15.1/src/usermod.c 2024-05-20 11:56:51.962509443 +0200 -@@ -440,7 +440,7 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating passwd", user_newname, user_newid, 0); -+ "updating-passwd", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname)); - xasprintf(&buf, "!%s", pw_pass); -@@ -457,14 +457,14 @@ static char *new_pw_passwd (char *pw_pas - - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "updating password", user_newname, user_newid, 0); -+ "updating-password", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "unlock user '%s' password", user_newname)); - memmove(pw_pass, pw_pass + 1, strlen(pw_pass)); - } else if (pflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing password", user_newname, user_newid, 1); -+ "updating-password", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, "change user '%s' password", user_newname)); - pw_pass = xstrdup (user_pass); -@@ -492,8 +492,8 @@ static void new_pwent (struct passwd *pw - fail_exit (E_NAME_IN_USE); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing name", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-name", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, - "change user name '%s' to '%s'", -@@ -512,8 +512,8 @@ static void new_pwent (struct passwd *pw - - if (uflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing uid", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-uid", user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, - "change user '%s' UID from '%d' to '%d'", -@@ -522,8 +522,8 @@ static void new_pwent (struct passwd *pw - } - if (gflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing primary group", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-primary-group", - user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -533,16 +533,16 @@ static void new_pwent (struct passwd *pw - } - if (cflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing comment", user_newname, user_newid, 1); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-comment", user_newname, user_newid, 1); - #endif - pwent->pw_gecos = user_newcomment; - } - - if (dflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-home-dir", - user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -558,8 +558,8 @@ static void new_pwent (struct passwd *pw - } - if (sflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing user shell", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-shell", - user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -589,8 +589,8 @@ static void new_spent (struct spwd *spen - - if (fflg) { - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing inactive days", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-inactive-days", - user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -604,8 +604,8 @@ static void new_spent (struct spwd *spen - DAY_TO_STR(new_exp, user_newexpire); - DAY_TO_STR(old_exp, user_expire); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing expiration date", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "changing-expiration-date", - user_newname, user_newid, 1); - #endif - SYSLOG ((LOG_INFO, -@@ -690,9 +690,9 @@ fail_exit (int code) - #endif /* ENABLE_SUBIDS */ - - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "modifying account", -- user_name, AUDIT_NO_ID, 0); -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "modify-account", -+ user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); - #endif - exit (code); - } -@@ -762,9 +762,12 @@ update_group(const struct group *grp) - user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing group member", -- user_newname, AUDIT_NO_ID, 1); -+ audit_logger_with_group ( -+ AUDIT_USER_MGMT, Prog, -+ "update-member-in-group", -+ user_newname, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in group '%s'", -@@ -778,9 +781,11 @@ update_group(const struct group *grp) - ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing group member", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-group", -+ user_name, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "delete '%s' from group '%s'", -@@ -793,9 +798,11 @@ update_group(const struct group *grp) - ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-group", -+ user_name, AUDIT_NO_ID, -+ ngrp->gr_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, "add '%s' to group '%s'", - user_newname, ngrp->gr_name)); -@@ -888,9 +895,10 @@ update_gshadow(const struct sgrp *sgrp) - nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing admin name in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_GRP_MGMT, Prog, -+ "update-admin-name-in-shadow-group", -+ user_name, AUDIT_NO_ID, nsgrp->sg_name, -+ SHADOW_AUDIT_SUCCESS); - #endif - SYSLOG ((LOG_INFO, - "change admin '%s' to '%s' in shadow group '%s'", -@@ -910,9 +918,10 @@ update_gshadow(const struct sgrp *sgrp) - user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing member in shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "update-member-in-shadow-group", -+ user_name, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, - "change '%s' to '%s' in shadow group '%s'", -@@ -926,9 +935,10 @@ update_gshadow(const struct sgrp *sgrp) - nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "removing user from shadow group", -- user_name, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "delete-user-from-shadow-group", -+ user_name, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, - "delete '%s' from shadow group '%s'", -@@ -941,9 +951,10 @@ update_gshadow(const struct sgrp *sgrp) - nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); - changed = true; - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "adding user to shadow group", -- user_newname, AUDIT_NO_ID, 1); -+ audit_logger_with_group (AUDIT_USER_MGMT, Prog, -+ "add-user-to-shadow-group", -+ user_newname, AUDIT_NO_ID, -+ nsgrp->sg_name, 1); - #endif - SYSLOG ((LOG_INFO, "add '%s' to shadow group '%s'", - user_newname, nsgrp->sg_name)); -@@ -1852,8 +1863,8 @@ static void move_home (void) - - #ifdef WITH_AUDIT - if (uflg || gflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-home-dir-owner", - user_newname, user_newid, 1); - } - #endif -@@ -1871,8 +1882,8 @@ static void move_home (void) - fail_exit (E_HOMEDIR); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "moving home directory", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "moving-home-dir", - user_newname, user_newid, 1); - #endif - return; -@@ -1899,9 +1910,9 @@ static void move_home (void) - Prog, prefix_user_home); - } - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, -+ audit_logger (AUDIT_USER_MGMT, - Prog, -- "moving home directory", -+ "moving-home-dir", - user_newname, - user_newid, - 1); -@@ -2125,8 +2136,8 @@ static void move_mailbox (void) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing mail file owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-mail-file-owner", - user_newname, user_newid, 1); - } - #endif -@@ -2149,8 +2160,8 @@ static void move_mailbox (void) - } - #ifdef WITH_AUDIT - else { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing mail file name", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-mail-file-name", - user_newname, user_newid, 1); - } - -@@ -2347,8 +2358,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), - Prog, user_name, user_selinux); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "modifying User mapping ", -+ audit_logger (AUDIT_ROLE_ASSIGN, Prog, -+ "changing-selinux-user-mapping ", - user_name, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -2360,8 +2371,8 @@ int main (int argc, char **argv) - _("%s: warning: the user name %s to SELinux user mapping removal failed.\n"), - Prog, user_name); - #ifdef WITH_AUDIT -- audit_logger (AUDIT_ADD_USER, Prog, -- "removing SELinux user mapping", -+ audit_logger (AUDIT_ROLE_REMOVE, Prog, -+ "delete-selinux-user-mapping", - user_name, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -@@ -2404,8 +2415,8 @@ int main (int argc, char **argv) - */ - #ifdef WITH_AUDIT - if (uflg || gflg) { -- audit_logger (AUDIT_USER_CHAUTHTOK, Prog, -- "changing home directory owner", -+ audit_logger (AUDIT_USER_MGMT, Prog, -+ "updating-home-dir-owner", - user_newname, user_newid, 1); - } - #endif diff --git a/shadow-4.17.0-account-tools-setuid.patch b/shadow-4.17.4-account-tools-setuid.patch similarity index 98% rename from shadow-4.17.0-account-tools-setuid.patch rename to shadow-4.17.4-account-tools-setuid.patch index 83453e0..4c1ff92 100644 --- a/shadow-4.17.0-account-tools-setuid.patch +++ b/shadow-4.17.4-account-tools-setuid.patch @@ -11,8 +11,8 @@ diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chp #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ - int errors = 0; - int line = 0; + bool errors = false; + intmax_t line = 0; @@ -469,19 +471,23 @@ int main (int argc, char **argv) process_root_flag ("-R", argc, argv); prefix = process_prefix_flag ("-P", argc, argv); @@ -56,7 +56,7 @@ diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chp @@ -672,9 +680,11 @@ int main (int argc, char **argv) * password database. */ - if (0 != errors) { + if (errors) { +#ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM if (!use_pam) @@ -332,15 +332,15 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new /* @@ -1052,12 +1078,14 @@ int main (int argc, char **argv) - int line = 0; + intmax_t line = 0; uid_t uid; gid_t gid; +#ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM - int *lines = NULL; + intmax_t *lines = NULL; char **usernames = NULL; char **passwords = NULL; - unsigned int nusers = 0; + size_t nusers = 0; #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ @@ -361,15 +361,15 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new +#endif /* ACCT_TOOLS_SETUID */ if (add_passwd (&newpw, fields[1]) != 0) { fprintf (stderr, - _("%s: line %d: can't update password\n"), + _("%s: line %jd: can't update password\n"), @@ -1327,6 +1357,7 @@ int main (int argc, char **argv) nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); +#ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM - unsigned int i; /* Now update the passwords using PAM */ + for (size_t i = 0; i < nusers; i++) { @@ -1339,6 +1370,7 @@ int main (int argc, char **argv) } } diff --git a/shadow-utils.spec b/shadow-utils.spec index 42b8d1d..eb9aebe 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.17.0 -Release: 5%{?dist} +Version: 4.17.4 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.0/shadow-4.17.0.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.0/shadow-4.17.0.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.4/shadow-4.17.4.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.4/shadow-4.17.4.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -18,16 +18,16 @@ Source7: passwd.pamd %global includesubiddir %{_includedir}/shadow # Fail linking if there are undefined symbols. %global _ld_strict_symbol_defs 1 +# workaround: _pam_confdir definition disappeared +%if ! %{defined _pam_confdir} +%define _pam_confdir /etc/pam.d +%endif ### Patches ### # Misc manual page changes - non-upstreamable Patch0: shadow-4.15.0-manfix.patch -# Date parsing improvement - could be upstreamed -Patch1: shadow-4.15.0-date-parsing.patch -# Audit message changes - partially upstreamed -Patch2: shadow-4.17.0-audit-update.patch # Probably non-upstreamable -Patch3: shadow-4.17.0-account-tools-setuid.patch +Patch1: shadow-4.17.4-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -105,7 +105,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.17.0 +%autosetup -p 1 -S git -n shadow-4.17.4 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -179,8 +179,6 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/man5/passwd.* rm $RPM_BUILD_ROOT%{_mandir}/*/man5/passwd.* -rm $RPM_BUILD_ROOT%{_mandir}/man5/suauth.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man5/suauth.* rm $RPM_BUILD_ROOT%{_mandir}/man8/logoutd.* rm $RPM_BUILD_ROOT%{_mandir}/*/man8/logoutd.* rm $RPM_BUILD_ROOT%{_mandir}/man8/nologin.* @@ -281,6 +279,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Mar 20 2025 Iker Pedrosa - 2:4.17.4-1 +- Rebase to version 4.17.4. Resolves: #2353491 +- Fixes problems with expiration dates + * Sat Feb 01 2025 Björn Esser - 2:4.17.0-5 - Add explicit BR: libxcrypt-devel diff --git a/sources b/sources index 4d4e5ae..6e720c5 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.17.0.tar.xz) = 36fb4a17cce43f5c97f669124c9419376ccbaa04fee8865fe590f525f3b2d14ce6422da6c52544e7d563ac8bebb29532ac9935c3ecd298718814118a932a00c7 -SHA512 (shadow-4.17.0.tar.xz.asc) = 53143dcdb637aa3c579ac5302904c10ad0e39611c0384061d8d7f06a03ae4612a5e42c6c1fd6dc8da0220d27fc429870f749ab9be508f58966f362e80a6fb43b +SHA512 (shadow-4.17.4.tar.xz) = 06830f654650312a79ccd6d729a51808b324d594abf1c05d56a2d0880936df292ec5c9fd6c7f4ad59a6d0f2bf5be0af42afe6386c24c2c087fd64fff301bade3 +SHA512 (shadow-4.17.4.tar.xz.asc) = 24f14397a975e4b09be087705a96544ff8ad76e0aa8c708ed4a53db3a295ad0a33fd0797fc570dcbb2446d4e103a3e43922a93168f65012eba5d3fe31549ebdd From a7f68f91584ffdd51a38b20c562e319e060ac53c Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 25 Mar 2025 16:54:24 +0100 Subject: [PATCH 090/118] Add pam dependency for _pam_confdir missing macro Resolves: #2354806 Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index eb9aebe..b835dd5 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.17.4 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -18,10 +18,6 @@ Source7: passwd.pamd %global includesubiddir %{_includedir}/shadow # Fail linking if there are undefined symbols. %global _ld_strict_symbol_defs 1 -# workaround: _pam_confdir definition disappeared -%if ! %{defined _pam_confdir} -%define _pam_confdir /etc/pam.d -%endif ### Patches ### # Misc manual page changes - non-upstreamable @@ -56,6 +52,7 @@ BuildRequires: libtool BuildRequires: libxcrypt-devel BuildRequires: libxslt BuildRequires: make +BuildRequires: pam BuildRequires: pam-devel ### Provides ### @@ -279,6 +276,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Mar 25 2025 Iker Pedrosa - 2:4.17.4-2 +- Add pam dependency for _pam_confdir missing macro. Resolves: #2354806 + * Thu Mar 20 2025 Iker Pedrosa - 2:4.17.4-1 - Rebase to version 4.17.4. Resolves: #2353491 - Fixes problems with expiration dates From 92eaac9b2c03814446ff08a2835f8168b3dc5a57 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 22 Apr 2025 11:31:29 +0200 Subject: [PATCH 091/118] FSWC: Migrate to lastlog2 Link: Resolves: #2361588 Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index b835dd5..def827b 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.17.4 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -80,10 +80,9 @@ programs for managing user and group accounts. The pwconv command converts passwords to the shadow password format. The pwunconv command unconverts shadow passwords and generates a passwd file (a standard UNIX password file). The pwck command checks the integrity of password -and shadow files. The lastlog command prints out the last login times -for all users. The useradd, userdel, and usermod commands are used for -managing user accounts. The groupadd, groupdel, and groupmod commands -are used for managing group accounts. +and shadow files. The useradd, userdel, and usermod commands are used +for managing user accounts. The groupadd, groupdel, and groupmod +commands are used for managing group accounts. ### Subpackages ### @@ -117,7 +116,6 @@ rm lib/getdate.c autoreconf %configure \ --disable-account-tools-setuid \ - --enable-lastlog \ --enable-logind=no \ --enable-man \ --enable-shadowgrp \ @@ -224,7 +222,6 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_bindir}/sg %attr(4755,root,root) %{_bindir}/chage %attr(4755,root,root) %{_bindir}/gpasswd -%{_bindir}/lastlog %attr(4755,root,root) %{_bindir}/newgrp %attr(0755,root,root) %caps(cap_setgid=ep) %{_bindir}/newgidmap %attr(0755,root,root) %caps(cap_setuid=ep) %{_bindir}/newuidmap @@ -262,7 +259,6 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_mandir}/man8/chgpasswd.8* %{_mandir}/man8/newusers.8* %{_mandir}/man8/*conv.8* -%{_mandir}/man8/lastlog.8* %{_mandir}/man8/vipw.8* %{_mandir}/man8/vigr.8* @@ -276,6 +272,11 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Apr 22 2025 Iker Pedrosa - 2:4.17.4-3 +* FSWC: Migrate to lastlog2 + Link: + Resolves: #2361588 + * Tue Mar 25 2025 Iker Pedrosa - 2:4.17.4-2 - Add pam dependency for _pam_confdir missing macro. Resolves: #2354806 From 39c75f8e5825d87385d2a1d76b03f7e2da47b4b6 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 15 Jul 2025 12:28:52 +0200 Subject: [PATCH 092/118] Rebuild for new side-tag for lastlog2 migration Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index def827b..a3cc639 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.17.4 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -272,7 +272,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog -* Tue Apr 22 2025 Iker Pedrosa - 2:4.17.4-3 +* Tue Jul 15 2025 Iker Pedrosa - 2:4.17.4-4 * FSWC: Migrate to lastlog2 Link: Resolves: #2361588 From e1cfa31731cd68aa2d76ebfb3142037d16d3bb1e Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 18 Jul 2025 17:33:47 +0200 Subject: [PATCH 093/118] Stop assigning subids by default Resolves: CVE-2024-56433 and #2334168 Signed-off-by: Iker Pedrosa --- shadow-utils.login.defs | 4 ++-- shadow-utils.spec | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index e84c7ab..1e9129a 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -148,7 +148,7 @@ SYS_UID_MAX 999 # Extra per user uids SUB_UID_MIN 524288 SUB_UID_MAX 600100000 -SUB_UID_COUNT 65536 +SUB_UID_COUNT 0 # # Min/max values for automatic gid selection in groupadd(8) @@ -161,7 +161,7 @@ SYS_GID_MAX 999 # Extra per user group ids SUB_GID_MIN 524288 SUB_GID_MAX 600100000 -SUB_GID_COUNT 65536 +SUB_GID_COUNT 0 # # Max number of login(1) retries if password is bad diff --git a/shadow-utils.spec b/shadow-utils.spec index a3cc639..834ff15 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.17.4 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -272,8 +272,12 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Jul 18 2025 Iker Pedrosa - 2:4.17.4-5 +- Stop assigning subids by default + Resolves: CVE-2024-56433 and #2334168 + * Tue Jul 15 2025 Iker Pedrosa - 2:4.17.4-4 -* FSWC: Migrate to lastlog2 +- FSWC: Migrate to lastlog2 Link: Resolves: #2361588 From 1f100b614dcbe4ea063620707f8aaaf0c83d7ef1 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 22 Jul 2025 11:33:02 +0200 Subject: [PATCH 094/118] Rebase to version 4.18.0 Resolves: #2374710 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + ...> shadow-4.18.0-account-tools-setuid.patch | 74 +++++++++---------- shadow-utils.spec | 18 ++--- sources | 4 +- 4 files changed, 50 insertions(+), 48 deletions(-) rename shadow-4.17.4-account-tools-setuid.patch => shadow-4.18.0-account-tools-setuid.patch (79%) diff --git a/.gitignore b/.gitignore index ff11943..f4e82f2 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.17.0.tar.xz.asc /shadow-4.17.4.tar.xz /shadow-4.17.4.tar.xz.asc +/shadow-4.18.0.tar.xz +/shadow-4.18.0.tar.xz.asc diff --git a/shadow-4.17.4-account-tools-setuid.patch b/shadow-4.18.0-account-tools-setuid.patch similarity index 79% rename from shadow-4.17.4-account-tools-setuid.patch rename to shadow-4.18.0-account-tools-setuid.patch index 4c1ff92..9c018f7 100644 --- a/shadow-4.17.4-account-tools-setuid.patch +++ b/shadow-4.18.0-account-tools-setuid.patch @@ -1,8 +1,8 @@ -diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chpasswd.c ---- shadow-4.15.0/src/chpasswd.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/chpasswd.c 2024-03-11 11:21:57.561150382 +0100 -@@ -443,9 +443,11 @@ int main (int argc, char **argv) - char *cp; +diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1/src/chpasswd.c +--- shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid 2025-06-08 15:58:36.650175673 +0200 ++++ shadow-4.18.0-rc1/src/chpasswd.c 2025-06-09 10:09:17.902939220 +0200 +@@ -448,9 +448,11 @@ int main (int argc, char **argv) + char *newpwd; const char *salt; +#ifdef ACCT_TOOLS_SETUID @@ -13,7 +13,7 @@ diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chp bool errors = false; intmax_t line = 0; -@@ -469,19 +471,23 @@ int main (int argc, char **argv) +@@ -474,19 +476,23 @@ int main (int argc, char **argv) process_root_flag ("-R", argc, argv); prefix = process_prefix_flag ("-P", argc, argv); @@ -77,9 +77,9 @@ diff -up shadow-4.15.0/src/chpasswd.c.account-tools-setuid shadow-4.15.0/src/chp { /* Save the changes */ close_files (); -diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/groupmems.c ---- shadow-4.15.0/src/groupmems.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/groupmems.c 2024-03-11 11:16:18.365408572 +0100 +diff -up shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.18.0-rc1/src/groupmems.c +--- shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid 2025-06-08 15:58:36.651250652 +0200 ++++ shadow-4.18.0-rc1/src/groupmems.c 2025-06-09 10:08:59.836763261 +0200 @@ -14,9 +14,11 @@ #include #include @@ -92,7 +92,7 @@ diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/gr #include #include "alloc/x/xmalloc.h" -@@ -430,6 +432,7 @@ static void process_flags (int argc, cha +@@ -417,6 +419,7 @@ static void process_flags (int argc, cha static void check_perms (void) { if (!list) { @@ -100,7 +100,7 @@ diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/gr #ifdef USE_PAM pam_handle_t *pamh = NULL; int retval; -@@ -463,7 +466,8 @@ static void check_perms (void) +@@ -450,7 +453,8 @@ static void check_perms (void) fail_exit (1); } (void) pam_end (pamh, retval); @@ -110,10 +110,10 @@ diff -up shadow-4.15.0/src/groupmems.c.account-tools-setuid shadow-4.15.0/src/gr } } -diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/newusers.c ---- shadow-4.15.0/src/newusers.c.account-tools-setuid 2024-03-08 22:27:04.000000000 +0100 -+++ shadow-4.15.0/src/newusers.c 2024-03-11 11:20:07.198909046 +0100 -@@ -59,6 +59,7 @@ +diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1/src/newusers.c +--- shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid 2025-06-08 15:58:36.652250643 +0200 ++++ shadow-4.18.0-rc1/src/newusers.c 2025-06-09 10:08:59.836928828 +0200 +@@ -67,6 +67,7 @@ static const char Prog[] = "newusers"; static bool rflg = false; /* create a system account */ @@ -121,7 +121,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM static /*@null@*//*@observer@*/char *crypt_method = NULL; #define cflg (NULL != crypt_method) -@@ -75,6 +76,7 @@ static long bcrypt_rounds = 13; +@@ -83,6 +84,7 @@ static long bcrypt_rounds = 13; static long yescrypt_cost = 5; #endif /* USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -129,7 +129,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new static bool is_shadow; #ifdef SHADOWGRP -@@ -97,9 +99,11 @@ NORETURN static void fail_exit (int); +@@ -105,9 +107,11 @@ NORETURN static void fail_exit (int); static int add_group (const char *, const char *, gid_t *, gid_t); static int get_user_id (const char *, uid_t *); static int add_user (const char *, uid_t, gid_t); @@ -141,7 +141,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new static int add_passwd (struct passwd *, const char *); static void process_flags (int argc, char **argv); static void check_flags (void); -@@ -121,6 +125,7 @@ static void usage (int status) +@@ -129,6 +133,7 @@ static void usage (int status) "Options:\n"), Prog); (void) fputs (_(" -b, --badname allow bad names\n"), usageout); @@ -149,7 +149,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM (void) fprintf (usageout, _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -@@ -136,9 +141,11 @@ static void usage (int status) +@@ -144,9 +149,11 @@ static void usage (int status) #endif ); #endif /* !USE_PAM */ @@ -161,7 +161,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -@@ -146,6 +153,7 @@ static void usage (int status) +@@ -154,6 +161,7 @@ static void usage (int status) usageout); #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -169,7 +169,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new (void) fputs ("\n", usageout); exit (status); -@@ -405,6 +413,7 @@ static int add_user (const char *name, u +@@ -419,6 +427,7 @@ static int add_user (const char *name, u return (pw_update (&pwent) == 0) ? -1 : 0; } @@ -177,7 +177,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM /* * update_passwd - update the password in the passwd entry -@@ -457,6 +466,7 @@ static int update_passwd (struct passwd +@@ -471,6 +480,7 @@ static int update_passwd (struct passwd return 0; } #endif /* !USE_PAM */ @@ -185,7 +185,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new /* * add_passwd - add or update the encrypted password -@@ -465,10 +475,13 @@ static int add_passwd (struct passwd *pw +@@ -479,10 +489,13 @@ static int add_passwd (struct passwd *pw { const struct spwd *sp; struct spwd spent; @@ -199,7 +199,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM void *crypt_arg = NULL; if (NULL != crypt_method) { -@@ -505,13 +518,14 @@ static int add_passwd (struct passwd *pw +@@ -520,13 +533,14 @@ static int add_passwd (struct passwd *pw return update_passwd (pwd, password); } #endif /* USE_PAM */ @@ -215,7 +215,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new if (NULL != sp) { spent = *sp; if ( (NULL != crypt_method) -@@ -547,7 +561,7 @@ static int add_passwd (struct passwd *pw +@@ -563,7 +577,7 @@ static int add_passwd (struct passwd *pw if (!streq(pwd->pw_passwd, "x")) { return update_passwd (pwd, password); } @@ -224,7 +224,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new /* * If there is already a shadow entry, do not touch it. * If there is already a passwd entry with a password, do not -@@ -558,14 +572,14 @@ static int add_passwd (struct passwd *pw +@@ -574,14 +588,14 @@ static int add_passwd (struct passwd *pw || !streq(pwd->pw_passwd, "x")) { return 0; } @@ -241,7 +241,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new if ((crypt_method != NULL) && streq(crypt_method, "NONE")) { spent.sp_pwdp = (char *)password; } else { -@@ -610,35 +624,41 @@ static int add_passwd (struct passwd *pw +@@ -626,35 +640,41 @@ static int add_passwd (struct passwd *pw static void process_flags (int argc, char **argv) { int c; @@ -285,7 +285,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new "bhr", #endif long_options, NULL)) != -1) { -@@ -646,11 +666,13 @@ static void process_flags (int argc, cha +@@ -662,11 +682,13 @@ static void process_flags (int argc, cha case 'b': allow_bad_names = true; break; @@ -299,7 +299,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new case 'h': usage (EXIT_SUCCESS); break; -@@ -659,6 +681,7 @@ static void process_flags (int argc, cha +@@ -675,6 +697,7 @@ static void process_flags (int argc, cha break; case 'R': /* no-op, handled in process_root_flag () */ break; @@ -307,7 +307,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': -@@ -698,6 +721,7 @@ static void process_flags (int argc, cha +@@ -714,6 +737,7 @@ static void process_flags (int argc, cha break; #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -315,7 +315,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new default: usage (EXIT_FAILURE); break; -@@ -730,6 +754,7 @@ static void process_flags (int argc, cha +@@ -746,6 +770,7 @@ static void process_flags (int argc, cha */ static void check_flags (void) { @@ -323,7 +323,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg && !cflg) { -@@ -762,6 +787,7 @@ static void check_flags (void) +@@ -778,6 +803,7 @@ static void check_flags (void) } } #endif /* !USE_PAM */ @@ -331,7 +331,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new } /* -@@ -1052,12 +1078,14 @@ int main (int argc, char **argv) +@@ -1066,12 +1092,14 @@ int main (int argc, char **argv) intmax_t line = 0; uid_t uid; gid_t gid; @@ -346,7 +346,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new log_set_progname(Prog); log_set_logfd(stderr); -@@ -1195,6 +1223,7 @@ int main (int argc, char **argv) +@@ -1191,6 +1219,7 @@ int main (int argc, char **argv) } newpw = *pw; @@ -354,7 +354,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifdef USE_PAM /* keep the list of user/password for later update by PAM */ nusers++; -@@ -1211,6 +1240,7 @@ int main (int argc, char **argv) +@@ -1207,6 +1236,7 @@ int main (int argc, char **argv) usernames[nusers-1] = xstrdup(fields[0]); passwords[nusers-1] = xstrdup(fields[1]); #endif /* USE_PAM */ @@ -362,7 +362,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new if (add_passwd (&newpw, fields[1]) != 0) { fprintf (stderr, _("%s: line %jd: can't update password\n"), -@@ -1327,6 +1357,7 @@ int main (int argc, char **argv) +@@ -1323,6 +1353,7 @@ int main (int argc, char **argv) nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); @@ -370,7 +370,7 @@ diff -up shadow-4.15.0/src/newusers.c.account-tools-setuid shadow-4.15.0/src/new #ifdef USE_PAM /* Now update the passwords using PAM */ for (size_t i = 0; i < nusers; i++) { -@@ -1339,6 +1370,7 @@ int main (int argc, char **argv) +@@ -1334,6 +1365,7 @@ int main (int argc, char **argv) } } #endif /* USE_PAM */ diff --git a/shadow-utils.spec b/shadow-utils.spec index 834ff15..5465e15 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.17.4 -Release: 5%{?dist} +Version: 4.18.0 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.17.4/shadow-4.17.4.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.17.4/shadow-4.17.4.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.18.0/shadow-4.18.0.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.18.0/shadow-4.18.0.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -23,7 +23,7 @@ Source7: passwd.pamd # Misc manual page changes - non-upstreamable Patch0: shadow-4.15.0-manfix.patch # Probably non-upstreamable -Patch1: shadow-4.17.4-account-tools-setuid.patch +Patch1: shadow-4.18.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -101,7 +101,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.17.4 +%autosetup -p 1 -S git -n shadow-4.18.0 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -109,9 +109,6 @@ cp -f doc/HOWTO.utf8 doc/HOWTO cp -a %{SOURCE4} %{SOURCE5} . cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml -# Force regeneration of getdate.c -rm lib/getdate.c - %build autoreconf %configure \ @@ -272,6 +269,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jul 22 2025 Iker Pedrosa - 2:4.18.0-1 +- Rebase to version 4.18.0. Resolves: #2374710 + * Fri Jul 18 2025 Iker Pedrosa - 2:4.17.4-5 - Stop assigning subids by default Resolves: CVE-2024-56433 and #2334168 diff --git a/sources b/sources index 6e720c5..8e3da98 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.17.4.tar.xz) = 06830f654650312a79ccd6d729a51808b324d594abf1c05d56a2d0880936df292ec5c9fd6c7f4ad59a6d0f2bf5be0af42afe6386c24c2c087fd64fff301bade3 -SHA512 (shadow-4.17.4.tar.xz.asc) = 24f14397a975e4b09be087705a96544ff8ad76e0aa8c708ed4a53db3a295ad0a33fd0797fc570dcbb2446d4e103a3e43922a93168f65012eba5d3fe31549ebdd +SHA512 (shadow-4.18.0.tar.xz) = e724670362949ccb570bb300322eb280c28ad609d631072b8db15a5e6eeba9fb9ac5d3df1df270f8b894235e4995b56c0e8f9aadb34d66bb5cea9b7a4f55e6ce +SHA512 (shadow-4.18.0.tar.xz.asc) = bb82b3d54eec0f11ace57609281974b315bba1240eafdae3b6513c7d7dfbcf10c3ae855c74c9eae33539709072046787e4b3e86dfb8bbfbf4bf23446daeb3422 From 654ff210dae918a9880cc1962b75b8a4c7ebab1f Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 25 Jul 2025 18:12:54 +0000 Subject: [PATCH 095/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 5465e15..f2238ca 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.18.0 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -269,6 +269,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Jul 25 2025 Fedora Release Engineering - 2:4.18.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Tue Jul 22 2025 Iker Pedrosa - 2:4.18.0-1 - Rebase to version 4.18.0. Resolves: #2374710 From b75f74d3f1b086fd5e699e55f131ae9e1beca525 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov Date: Tue, 29 Jul 2025 20:20:15 +0200 Subject: [PATCH 096/118] Revert "Stop assigning subids by default" This reverts commit e1cfa31731cd68aa2d76ebfb3142037d16d3bb1e while CVE-2024-56433 is being disputed. Resolves: #2382662 --- shadow-utils.login.defs | 4 ++-- shadow-utils.spec | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/shadow-utils.login.defs b/shadow-utils.login.defs index 1e9129a..e84c7ab 100644 --- a/shadow-utils.login.defs +++ b/shadow-utils.login.defs @@ -148,7 +148,7 @@ SYS_UID_MAX 999 # Extra per user uids SUB_UID_MIN 524288 SUB_UID_MAX 600100000 -SUB_UID_COUNT 0 +SUB_UID_COUNT 65536 # # Min/max values for automatic gid selection in groupadd(8) @@ -161,7 +161,7 @@ SYS_GID_MAX 999 # Extra per user group ids SUB_GID_MIN 524288 SUB_GID_MAX 600100000 -SUB_GID_COUNT 0 +SUB_GID_COUNT 65536 # # Max number of login(1) retries if password is bad diff --git a/shadow-utils.spec b/shadow-utils.spec index f2238ca..34baef4 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.18.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -269,6 +269,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jul 29 2025 Alexey Tikhonov - 2:4.18.0-3 +- Revert "Stop assigning subids by default" + Resolves: #2382662 + * Fri Jul 25 2025 Fedora Release Engineering - 2:4.18.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild From 9fbb086db0bf8f6b1436d76a5224e44ca5abf41b Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 18 Aug 2025 11:48:31 +0200 Subject: [PATCH 097/118] tests/: remove them These tests need to be migrated to TMT to continue running, but nobody is maintaining them so we've decided to remove them. Closes: 2383071 Signed-off-by: Iker Pedrosa --- tests/sanity/Makefile | 77 --- tests/sanity/PURPOSE | 10 - tests/sanity/runtest.sh | 24 - tests/sanity/sanity_test.py | 1013 ----------------------------------- tests/tests.yml | 13 - 5 files changed, 1137 deletions(-) delete mode 100644 tests/sanity/Makefile delete mode 100644 tests/sanity/PURPOSE delete mode 100755 tests/sanity/runtest.sh delete mode 100755 tests/sanity/sanity_test.py delete mode 100644 tests/tests.yml diff --git a/tests/sanity/Makefile b/tests/sanity/Makefile deleted file mode 100644 index 386221b..0000000 --- a/tests/sanity/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2006 Red Hat, Inc. All rights reserved. This copyrighted material -# is made available to anyone wishing to use, modify, copy, or -# redistribute it subject to the terms and conditions of the GNU General -# Public License v.2. -# -# This program 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# Author: Jakub Hrozek - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# -# Example Makefile for RHTS # -# This example is geared towards a test for a specific package # -# It does most of the work for you, but may require further coding # -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# - -# The toplevel namespace within which the test lives. -TOPLEVEL_NAMESPACE=CoreOS - -# The name of the package under test: -PACKAGE_NAME=shadow-utils - -# The path of the test below the package: -RELATIVE_PATH=sanity - -# Version of the Test. Used with make tag. -export TESTVERSION=1.1 - -# The combined namespace of the test. -export TEST=/$(TOPLEVEL_NAMESPACE)/$(PACKAGE_NAME)/$(RELATIVE_PATH) - -# A phony target is one that is not really the name of a file. -# It is just a name for some commands to be executed when you -# make an explicit request. There are two reasons to use a -# phony target: to avoid a conflict with a file of the same -# name, and to improve performance. -.PHONY: all install download clean - -# Executables to be built should be added here, they will be generated on the system under test. -BUILT_FILES= - -# Data files, .c files, scripts anything needed to either compile the test and/or run it. -FILES=$(METADATA) Makefile PURPOSE sanity_test.py runtest.sh - -run: $(FILES) build - ./runtest.sh - -build: $(BUILT_FILES) - chmod a+x ./sanity_test.py - chmod a+x ./runtest.sh - -clean: - rm -f *~ *.rpm $(BUILT_FILES) - -# Include Common Makefile -include /usr/share/rhts/lib/rhts-make.include - -# Generate the testinfo.desc here: -$(METADATA): Makefile - @touch $(METADATA) - @echo "Owner: Jakub Hrozek " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "License: GNU GPL" >> $(METADATA) - @echo "Description: Basic sanity test for shadow-utils" >> $(METADATA) - @echo "TestTime: 5m" >> $(METADATA) - @echo "RunFor: $(PACKAGE_NAME)" >> $(METADATA) - @echo "Requires: $(PACKAGE_NAME)" >> $(METADATA) - @echo "Requires: python" >> $(METADATA) - rhts-lint $(METADATA) - diff --git a/tests/sanity/PURPOSE b/tests/sanity/PURPOSE deleted file mode 100644 index 27062e1..0000000 --- a/tests/sanity/PURPOSE +++ /dev/null @@ -1,10 +0,0 @@ -This is a basic sanity test for the shadow-utils package. It is implemented -in python on top of the unittesting.py module. - -Its purpose is to ensure that the binaries in the shadow-utils package behave -as expected and its switches/options work correctly. - -For the most part, every binary in the shadow-utils package is represented by -a single class named Test, i.e. TestUsermod etc. There are some -exceptions, like TestUseraddWeirdNameTest though. - diff --git a/tests/sanity/runtest.sh b/tests/sanity/runtest.sh deleted file mode 100755 index cb2a2b5..0000000 --- a/tests/sanity/runtest.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -. /usr/bin/rhts-environment.sh -. /usr/share/beakerlib/beakerlib.sh || exit 1 - -rlJournalStart -rlFileBackup --clean /etc/default/useradd- /etc/default/useradd -setenforce 0 -python sanity_test.py -v -setenforce 1 -rlFileRestore - -EXIT=$? -if [[ $EXIT -eq 0 ]]; then - RESULT="PASS" -else - RESULT="FAIL" -fi - - -rlJournalEnd - -echo "Result: $RESULT" -echo "Exit: $EXIT" -report_result $TEST $RESULT $EXIT diff --git a/tests/sanity/sanity_test.py b/tests/sanity/sanity_test.py deleted file mode 100755 index e9c45c2..0000000 --- a/tests/sanity/sanity_test.py +++ /dev/null @@ -1,1013 +0,0 @@ -#!/usr/bin/env python -""" -A script that tests functionality of the shadow-utils package. - -Author: Jakub Hrozek, -License: GNU GPL v2 -Date: 2007 - -TODO: - * tests for password aging - * if something fails, print out the command issued for easier debugging - * test long options variants along with the short ones -""" - -import unittest -import pwd -import grp -import commands -import os -import os.path -import sys -import copy -import tempfile -import rpm -import shutil - -from UserDict import UserDict - -class RedHatVersion(object): - def __init__(self, type=None, version=None, release=None): - self.type = type - self.version = version - self.release = release - self.rhel = False - - def __eq__( self, other): - """ - Don't compare if either of the values is None - so we can do comparisons like 'is it fedora?' or 'is it rhel4?' - """ - ok = (self.type == other.type) - if ok == False: return False - - if self.version and other.version: - ok = (self.version == other.version) - if ok == False: return False - - if (self.release == other.release): - ok = (self.release == other.release) - - return ok - - def __ne__( self, other): - return not self.__eq__(other) - - def __get_fedora_info(self, mi): - return [ (h['version'],h['release']) for h in mi ][0] - - def __get_rhel_info(self, mi): - # The rules for RHEL versions are braindead..releases even more - ver_rpm, rel_rpm = [ (h['version'],h['release']) for h in mi ][0] - rhel_versions = { '3AS' : 3, '4AS' : 4, '5Server' : 5, '5Client' : 5, '6' : 6 } - if ver_rpm[:3] == '5.9' or ver_rpm[:1] == '6': # rhel6 prerelease and release hack - rhel_versions[ver_rpm] = 6 - if ver_rpm in rhel_versions.keys(): - return (rhel_versions[ver_rpm], rel_rpm) - - def is_rhel(self): - return self.rhel - - def get_info(self): - """ - Returns a tuple containing (type, version, release) of RHEL or Fedora. - Type is either RHEL or Fedora. - Returns None if it cannot parse the info - """ - - ts = rpm.TransactionSet() - mi = ts.dbMatch() - mi.pattern('name', rpm.RPMMIRE_GLOB, 'redhat-release*') - - if mi: - self.rhel = True - return ('RHEL',) + self.__get_rhel_info(mi) - else: - mi = ts.dbMatch('name','fedora-release') - self.rhel = False - if mi.count() != 0: - return ('Fedora',) + self.__get_fedora_info(mi) - - return None - - -class UserInfo(UserDict): - fields = { "pw_name" : 0, "pw_passwd" : 1, "pw_uid" : 2, "pw_gid" : 3, - "pw_gecos" : 4, "pw_dir" : 5, "pw_shell" : 6 } - - def __init__(self): - UserDict.__init__(self) - for f in UserInfo.fields: self[f] = None - - def __getitem__(self, key): - return UserDict.__getitem__(self, key) - - def __setitem__(self, key, value): - UserDict.__setitem__(self, key, value) - - def __cmp__(self, other): - return UserDict.__cmp__(self, other) - - def __repr__(self): - return " ; ".join( [ "%s => %s" % (k, v) for k, v in self.data.items() ] ) - - def __parse_info(self, struct): - for f in UserInfo.fields: - self[f] = struct[UserInfo.fields[f]] - - def get_info_uid(self, uid): - self.__parse_info(pwd.getpwuid(uid)) - - def get_info_name(self, name): - try: - self.__parse_info(pwd.getpwnam(name)) - except KeyError: - return None - - def lazy_compare(self, pattern): - """ Compare pattern against self. If any field in pattern is set - to None, it is automatically considered equal with the corresponding - field in self. """ - for field in UserInfo.fields: - if pattern[field] and pattern[field] != self[field]: - return False - - return True - -class GroupInfo(UserDict): - fields = { "gr_name" : 0, "gr_passwd" : 1, - "gr_gid" : 2, "gr_mem" : 3} - - def __init__(self): - UserDict.__init__(self) - for f in GroupInfo.fields: self[f] = None - - def __getitem__(self, key): - return UserDict.__getitem__(self, key) - - def __setitem__(self, key, value): - UserDict.__setitem__(self, key, value) - - def __cmp__(self, other): - return UserDict.__cmp__(self, other) - - def __repr__(self): - return " ; ".join( [ "%s => %s" % (k, v) for k, v in self.data.items() ] ) - - def __parse_info(self, struct): - for f in GroupInfo.fields: - self[f] = struct[GroupInfo.fields[f]] - - def get_info_gid(self, gid): - self.__parse_info(grp.getgrgid(gid)) - - def get_info_name(self, name): - self.__parse_info(grp.getgrnam(name)) - - def lazy_compare(self, pattern): - """ Compare pattern against self. If any field in pattern is set - to None, it is automatically considered equal with the corresponding - field in self. """ - for field in GroupInfo.fields: - if pattern[field] and pattern[field] != self[field]: - return False - - return True - -class LoginDefsParser(UserDict): - "A quick-n-dirty way how to fetch the defaults from /etc/login.defs into a dictionary" - - def __getitem__(self, key): - try: - return UserDict.__getitem__(self, key) - except KeyError: - # if a name-value is not defined in the config file, return defaults - if key == "CREATE_MAIL_SPOOL": - return "yes" - if key == "UMASK": - return "077" - - def __init__(self, path="/etc/login.defs",split=None): - self.path = path - UserDict.__init__(self) - try: - defs = open(path) - except IOError: - print "Could not open the config file %s" % (path) - - for line in defs: - if line.startswith('#'): continue - fields = line.split(split) - if len(fields) != 2: continue # yeah, we're dirty - self.data[fields[0]] = fields[1] - - def serialize(self): - output = open(self.path, "w+") - for k,v in self.data.items(): - output.write("%s=%s" % (k, v)) - - output.write("\n") - output.close() - -class TestUserInfo(unittest.TestCase): - def testLazyCompare(self): - """ (test sanity): Test comparing two UserInfo records """ - a = UserInfo() - a["pw_name"] = "foo" - a["pw_uid"] = 555 - b = copy.deepcopy(a) - c = UserInfo() - - self.assertEqual(a.lazy_compare(b), True) - self.assertEqual(a.lazy_compare(c), True) - - c["pw_name"] = "foo" - c["pw_uid"] = None - self.assertEqual(a.lazy_compare(c), True) - self.assertEqual(c.lazy_compare(a), False) - - c["pw_name"] = "bar" - self.assertNotEqual(a.lazy_compare(c), True) - - def testGetInfoUid(self): - """ (test sanity): Test getting user info based on his UID """ - a = UserInfo() - a.get_info_uid(0) - self.assertEqual(a["pw_name"], "root") - - def testGetInfoName(self): - """ (test sanity): Test getting user info based on his name """ - a = UserInfo() - a.get_info_name("root") - self.assertEqual(a["pw_uid"], 0) - -class ShadowUtilsTestBase: - """ Handy routines """ - def getDefaults(self): - # get the default values for so we can compare against that - (status, defaults_str) = commands.getstatusoutput('useradd -D') - if status != 0: - raise RuntimeError("Could not get the default values for useradd") - return dict([ rec.split("=") for rec in defaults_str.split("\n") ]) - - def getDefaultUserInfo(self, username): - expected = UserInfo() - defaults = self.getDefaults() - - expected["pw_name"] = username - expected["pw_dir"] = defaults["HOME"] + "/" + username - expected["pw_shell"] = defaults["SHELL"] - - return expected - -class TestUseradd(ShadowUtilsTestBase, unittest.TestCase): - def setUp(self): - self.username = "test-shadow-utils-useradd" - - def tearDown(self): - commands.getstatusoutput("userdel -r %s" % (self.username)) - - def testBasicAdd(self): - """ useradd: Tests basic adding of a user """ - expected = self.getDefaultUserInfo(self.username) - - runme = "useradd %s" % (self.username) - (status, output) = commands.getstatusoutput(runme) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user\nIssued command: %s" % (runme)) - - def testExistingUser(self): - """ useradd: Test that user with an existing name cannot be added """ - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - self.assertNotEqual(commands.getstatusoutput("useradd %s" % (self.username))[0], 0, "FAIL: User that already exists added") - - def testCustomUID(self): - """ useradd: Adding an user with a specific UID """ - UID = 23456 # FIXME - test for a free UID slot first - - expected = self.getDefaultUserInfo(self.username) - expected["pw_uid"] = UID - - runme = "useradd %s -u %d" % (self.username, UID) - (status, output) = commands.getstatusoutput(runme) - self.failUnlessEqual(status, 0, "Issued command: %s\n" % (runme) + "Got from useradd: %s\n" % (output)) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific UID\nIssued command: %s" % (runme)) - - def testNegativeUID(self): - """ useradd: Tests that user cannot have a negative UID assigned """ - self.assertNotEqual(commands.getstatusoutput("useradd %s --uid -5" % (self.username))[0], 0, "FAIL: User with UID < 0 added") - - def testCustomExistingUID(self): - """ useradd: Adding a user with a specific existing UID """ - UID = 32112 - - expected = self.getDefaultUserInfo(self.username) - expected["pw_uid"] = UID - - (status_u, output_u) = commands.getstatusoutput("useradd %s -u %d" % (self.username, UID)) - - # must fail without -o flag - (status_u_no_o, output_u_no_o) = commands.getstatusoutput("useradd foo -u %d" % (UID)) - - # must pass with -o flag - (status_o, output_o) = commands.getstatusoutput("useradd foo -u %d -o" % (UID)) - - # clean up - (status, output) = commands.getstatusoutput("userdel -r foo") - - self.failUnlessEqual(status_u, 0, "FAIL: cannot add an user with a specified UID\n"+output_u) - self.assertEqual(status_o, 0, "FAIL: cannot add an user with an existing UID using the -o flag\n"+output_o) - self.failUnlessEqual(status, 0, output) - self.assertNotEqual(status_u_no_o, 0, "FAIL: user with an existing UID added\n"+output_u_no_o) - - def testCustomGID(self): - """ useradd: Adding an user with a specific GID """ - GID = 100 # users group should be everywhere - should we test before? - expected = self.getDefaultUserInfo(self.username) - expected["pw_gid"] = GID - - (status, output) = commands.getstatusoutput("useradd %s -g %d" % (self.username, GID)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific GID") - - def testCustomShell(self): - """ useradd: Adding an user with a specific login shell """ - shell = "/bin/ksh" - expected = self.getDefaultUserInfo(self.username) - expected["pw_shell"] = shell - - (status, output) = commands.getstatusoutput("useradd %s -s %s" % (self.username, shell)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific shell") - - def testCustomHome(self): - """ useradd: Adding an user with a specific home directory """ - home = "/tmp/useradd-test" - os.mkdir(home) - expected = self.getDefaultUserInfo(self.username) - expected["pw_dir"] = home - - (status, output) = commands.getstatusoutput("useradd %s -d %s" % (self.username, home)) - shutil.rmtree(home) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a user with a specific home") - - def testSystemAccount(self): - """ useradd: Adding a system user (UID < UID_MIN from /etc/login.defs) """ - defaults = LoginDefsParser() - - # system account with no home dir - expected = self.getDefaultUserInfo(self.username) - - (status, output) = commands.getstatusoutput("useradd -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(os.path.exists(created["pw_dir"]), False, "FAIL: System user has a home dir created") - self.assertEqual(created["pw_uid"] < defaults['UID_MIN'], True, "FAIL: System user has UID > UID_MIN") - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a system user") - - def testAddToMoreGroups(self): - """ useradd: Creating an user that belongs to more than one group """ - (status, output) = commands.getstatusoutput("useradd -G bin %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - gr_bin = GroupInfo() - gr_bin.get_info_name("bin") - self.assertEqual(self.username in gr_bin["gr_mem"], True, "FAIL: User not in supplementary group after usermod -G -a") - - - def testAddWithCommonName(self): - """ useradd: Specifying a comment (user for account name) """ - comment = "zzzzzz" - (status, output) = commands.getstatusoutput("useradd -c %s %s" % (comment, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created["pw_gecos"], comment, "FAIL: failed to create a user with a GECOS comment") - - def testHomePermissions(self): - """ useradd: Check if permissions on newly created home dir match the umask """ - defaults = LoginDefsParser() - - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - - import stat - perm = os.stat(created["pw_dir"])[stat.ST_MODE] - mode = int(oct(perm & 0777)) - - self.assertEqual(defaults["UMASK"], "077", "FAIL: umask setting is not sane - is %s, should be 077" % (defaults["UMASK"])) - self.assertEqual(int(defaults["UMASK"]) + mode , 777, "FAIL: newly-created home dir does not match the umask") - - def testCreateMailSpool(self): - """ useradd: Check whether the mail spool gets created when told to""" - # set up creating of mail spool - defaults = LoginDefsParser("/etc/default/useradd", split="=") - - create_mail = defaults["CREATE_MAIL_SPOOL"] - defaults["CREATE_MAIL_SPOOL"] = "yes" - defaults.serialize() - - login_defs = LoginDefsParser() - - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - # clean up - defaults["CREATE_MAIL_SPOOL"] = create_mail - defaults.serialize() - self.assertEqual(os.path.exists(login_defs["MAIL_DIR"] + "/" + self.username), True, "FAIL: useradd did not create mail spool") - - def testDefaultMailSettings(self): - """ useradd: Check whether the mail spool is on by default""" - defaults = LoginDefsParser("/etc/default/useradd", split="=") - self.assertEqual(defaults["CREATE_MAIL_SPOOL"], "yes\n") - - def testNoLastlog(self): - """ useradd: Check if the -l option prevents from being added to the lastlog """ - pass # FIXME - add some code here - - -class TestUseraddWeirdNameTest(unittest.TestCase, ShadowUtilsTestBase): - """ Tests addition/removal of usernames that have proven to be problematic in the past. - The reason to separate these from the main useradd test suite is to not run the setUp - and tearDown methods """ - - def addAndRemove(self, username, success=True): - expected = self.getDefaultUserInfo(username) - expected["pw_name"] = username - - (status, output) = commands.getstatusoutput("useradd %s" % (username)) - if success: - self.failUnlessEqual(status, 0, output) - else: - self.failIfEqual(status, 0, output) - return True - - created = UserInfo() - created.get_info_name(username) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: TestUseraddWeirdName::addAndRemove - could not add a user") - - # the cleanup method won't help this time - (status, output) = commands.getstatusoutput("userdel -r %s" % (username)) - self.failUnlessEqual(status, 0, output) - - def testNumericName(self): - """ useradd: Test if an user with a purely numerical name can be added (123) """ - return self.addAndRemove("123") - - def testSambaName(self): - """ useradd: Test if an user with a name with a dollar at the end can be added (joepublic$ ) """ - return self.addAndRemove("joepublic$") - - def testDotInName(self): - """ useradd: Test if an user with a name with a dot in it can be added (joe.public ) """ - return self.addAndRemove("joe.public") - - def testAtInName(self): - """ useradd: Test if an user with an '@' in name can be added (joe@public.com) - should fail """ - return self.addAndRemove("joe@public.com", False) - - def testUppercase(self): - """ useradd: Test if an user with UPPERCASE or Uppercase name can be added """ - return self.addAndRemove("JOEPUBLIC") - return self.addAndRemove("Joepublic") - -class TestUseraddDefaultsChange(unittest.TestCase, ShadowUtilsTestBase): - def testDefaultsChange(self): - """ useradd: Test overriding default settings (shell, home dir, group) with a -D option """ - save = self.getDefaults() - - new_defs = dict() - new_defs["SHELL"] = "/bin/ksh" - new_defs["GROUP"] = "1" - new_defs["HOME"] = "/tmp" - - command = "useradd -D -s%s -g%s -b%s" % (new_defs["SHELL"], new_defs["GROUP"], new_defs["HOME"]) - (status, output) = commands.getstatusoutput(command) - self.failUnlessEqual(status, 0, output) - - overriden = self.getDefaults() - [ self.assertEqual(overriden[k], new_defs[k]) for k in new_defs.keys() ] - - command = "useradd -D -s%s -g%s -b%s" % (save["SHELL"], save["GROUP"], save["HOME"]) - (status, output) = commands.getstatusoutput(command) - self.failUnlessEqual(status, 0, output) - - -class TestUserdel(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.username = "test-shadow-utils-userdel" - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def testRemoveUserGroup(self): - """ userdel: test if userdel removes user's group when he's deleted - regression test for #201379 """ - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - # This would fail if we did not have the group removed - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - -class TestUsermod(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.username = "test-shadow-utils-usermod" - (status, output) = commands.getstatusoutput("useradd %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def tearDown(self): - (status, output) = commands.getstatusoutput("userdel -r %s" % (self.username)) - self.failUnlessEqual(status, 0, output) - - def testAppendToSupplementaryGroup(self): - """ usermod: Test if a user can be added to a supplementary group """ - add_group = "additional_group" - (status, output) = commands.getstatusoutput("groupadd %s" % (add_group)) - self.failUnlessEqual(status, 0, output) - - (status_mod, output_mod) = commands.getstatusoutput("usermod -a -G %s %s" % (add_group, self.username)) - add_group_info = GroupInfo() - add_group_info.get_info_name(add_group) - (status, output) = commands.getstatusoutput("groupdel %s" % (add_group)) - - self.failUnlessEqual(status, 0, output) - self.failUnlessEqual(status_mod, 0, output_mod) - self.assertEqual(self.username in add_group_info["gr_mem"], True, "User not in supplementary group after usermod -G --append") - - - def testAppendToSupplementaryGroupLongOption(self): - """ usermod: Test if a user can be added to a supplementary group via --append rather that -a (regression test for 222540) """ - # this is known to not work on older RHELs - test what we are running - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 5: - print "This test makes sense for RHEL5+" - return - else: - if runs[1] < 6: - print "This test makes sense for Fedora 6+" - return - - type, release, version = RedHatVersion().get_info() - if RedHatVersion().is_rhel(): - if release < 5 or (release == 5 and version < 2): - print "This test makes sense for RHEL 5.2+" - return - - add_group = "additional_group" - (status, output) = commands.getstatusoutput("groupadd %s" % (add_group)) - self.failUnlessEqual(status, 0, output) - - (status_mod, output_mod) = commands.getstatusoutput("usermod --append -G %s %s" % (add_group, self.username)) - add_group_info = GroupInfo() - add_group_info.get_info_name(add_group) - (status, output) = commands.getstatusoutput("groupdel %s" % (add_group)) - - self.failUnlessEqual(status, 0, output) - self.failUnlessEqual(status_mod, 0, output_mod) - self.assertEqual(self.username in add_group_info["gr_mem"], True, "User not in supplementary group after usermod -G --append") - - - def testNameChange(self): - """ usermod: Test if the comment field (used as the Common Name) can be changed """ - new_comment = "zzzzzz" - - (status, output) = commands.getstatusoutput("usermod -c %s %s" % (new_comment, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - - self.assertEqual(created["pw_gecos"], new_comment) - - def testHomeChange(self): - """ usermod: Test if user's home directory can be changed """ - new_home = "/tmp" - created = UserInfo() - created.get_info_name(self.username) - old_home = created["pw_dir"] - - (status, output) = commands.getstatusoutput("usermod -d %s %s" % (new_home, self.username)) - self.failUnlessEqual(status, 0, output) - - created.get_info_name(self.username) - self.assertEqual(created["pw_dir"], new_home) - - # revert to old home so we can userdel -r in tearDown - (status, output) = commands.getstatusoutput("usermod -d %s %s" % (old_home, self.username)) - self.failUnlessEqual(status, 0, output) - - # FIXME - test if contents of /home directories are transferred with the -m option - # FIXME - test if new home is created if does not exist before - - def testGIDChange(self): - """ usermod: Test if user's gid can be changed. """ - new_group = "root" - # test non-existing group - (status_fail, output_fail) = commands.getstatusoutput("usermod -g no-such-group %s" % (self.username)) - (status, output) = commands.getstatusoutput("usermod -g %s %s" % (new_group, self.username)) - - created = UserInfo() - created.get_info_name(self.username) - - left = GroupInfo() - if left.get_info_name(self.username) == None: - (status_del, output_del) = commands.getstatusoutput("groupdel %s" % (self.username)) - self.failUnlessEqual(status_del, 0, output_del) - - self.failIfEqual(status_fail, 0, output_fail) - self.failUnlessEqual(status, 0, output) - self.assertEqual(created["pw_gid"], 0) #0 is root group - - def testLoginChange(self): - """ usermod: Test if user's login can be changed """ - new_login = "usermod-login-change" - user = UserInfo() - user.get_info_name(self.username) - uid = user["pw_uid"] # UID won't change even when login does - - # test changing to an existing user name - (status, output) = commands.getstatusoutput("usermod -l root %s" % (self.username)) - self.failIfEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("usermod -l %s %s" % (new_login, self.username)) - self.failUnlessEqual(status, 0, output) - user.get_info_name(new_login) - self.assertEqual(user["pw_uid"], uid) - - # revert so we can userdel -r on tearDown - (status, output) = commands.getstatusoutput("usermod -l %s %s" % (self.username, new_login)) - self.failUnlessEqual(status, 0, output) - - def testShellChange(self): - """ usermod: Test if user's shell can be changed """ - new_shell = "/bin/sh" - - (status, output) = commands.getstatusoutput("usermod -s %s %s" % (new_shell, self.username)) - self.failUnlessEqual(status, 0, output) - - created = UserInfo() - created.get_info_name(self.username) - self.assertEqual(created["pw_shell"], new_shell) - -class TestGroupadd(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.groupname = "test-shadow-utils-groups" - - def tearDown(self): - commands.getstatusoutput("groupdel %s" % (self.groupname)) - - def testAddGroup(self): - """ groupadd: Basic adding of a group """ - - expected = GroupInfo() - expected["gr_name"] = self.groupname - - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a group") - - def testAddSystemGroup(self): - """ groupadd: Adding a system group with gid < MIN_GID """ - - expected = GroupInfo() - expected["gr_name"] = self.groupname - defaults = LoginDefsParser() - - (status, output) = commands.getstatusoutput("groupadd -r %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created["gr_gid"] < defaults["GID_MIN"], True, "FAIL: System group has gid >= GID_MIN") - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not add a system group") - - def testAddExistingGid(self): - """ groupadd: Test if we group with an existing GID can be added """ - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - gname = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - # no -o option -> this should fail - (status, output) = commands.getstatusoutput("groupadd -g%s %s" % (created["gr_gid"], gname)) - self.failIfEqual(status, 0, output) - - # override with -o option, should pass now - (status, output) = commands.getstatusoutput("groupadd -g%s -o %s" % (created["gr_gid"], gname)) - self.failUnlessEqual(status, 0, output) - - # test if the new GID is really the same - same_gid = GroupInfo() - same_gid.get_info_name(gname) - self.assertEqual(same_gid["gr_gid"], created["gr_gid"]) - - # clean up - (status, output) = commands.getstatusoutput("groupdel %s" % (gname)) - self.failUnlessEqual(status, 0, output) - - - def testOverrideDefaults(self): - """ groupadd: Test if the defaults can be overriden with the -K option """ - # this is known to not work on older RHELs - test what we are running - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 5: - print "This test makes sense for RHEL5+" - return - else: - if runs[1] < 6: - print "This test makes sense for Fedora 6+" - return - - - GID_MIN = 600 - GID_MAX = 625 - - (status, output) = commands.getstatusoutput("groupadd -K GID_MIN=%d -K GID_MAX=%d %s" % - (GID_MIN, GID_MAX, self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(GID_MIN <= created["gr_gid"] <= GID_MAX, True, "FAIL: created an user with UID of %d" % (created["gr_gid"])) - - - def testFOption(self): - """ groupadd: Tests the -f option of groupadd """ - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("groupadd -f %s" % (self.groupname)) - self.assertEqual(status, 0, output) - -class TestGroupaddInvalidName(unittest.TestCase, ShadowUtilsTestBase): - def testGroupaddInvalidName(self): - """ groupadd: Test adding of a group with an invalid name """ - (status, output) = commands.getstatusoutput("groupadd foo?") - self.assertNotEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffggg") #33 chars - self.assertNotEqual(status, 0, output) - -class TestGroupaddValidName(unittest.TestCase, ShadowUtilsTestBase): - def testGroupaddValidName(self): - """ groupadd: Test adding and removing of groups with maximal valid name and name ending with $ """ - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffgg") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupadd aaaaabbbbbcccccdddddeeeeefffffg\$") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel aaaaabbbbbcccccdddddeeeeefffffgg") #32 chars - self.assertEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel aaaaabbbbbcccccdddddeeeeefffffg\$") #32 chars - self.assertEqual(status, 0, output) - - -class TestGroupmod(unittest.TestCase, ShadowUtilsTestBase): - def setUp(self): - self.groupname = "test-shadow-utils-groups" - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - - def tearDown(self): - commands.getstatusoutput("groupdel %s" % (self.groupname)) - - def testChangeGID(self): - """ groupmod: Test changing a gid of a group """ - expected = GroupInfo() - expected["gr_name"] = self.groupname - expected["gr_gid"] = 54321 - - (status, output) = commands.getstatusoutput("groupmod -g%d %s" % (expected["gr_gid"], self.groupname)) - self.failUnlessEqual(status, 0, output) - - created = GroupInfo() - created.get_info_name(self.groupname) - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not change GID of an existing group") - - def testChangeGIDToExistingValue(self): - """ groupmod: Test changing GID to an existing value """ - second_name = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - expected = GroupInfo() - expected["gr_name"] = self.groupname - expected["gr_gid"] = created["gr_gid"] - - (status, output) = commands.getstatusoutput("groupadd %s" % (second_name)) - self.failUnlessEqual(status, 0, output) - - # try to assingn GID of the first group to the second - this should fail without the -o option - (status, output) = commands.getstatusoutput("groupmod -g%d %s" % (created["gr_gid"], second_name)) - self.failIfEqual(status, 0, output) - - # should pass with the -o option - (status, output) = commands.getstatusoutput("groupmod -g%d -o %s" % (created["gr_gid"], second_name)) - self.failUnlessEqual(status, 0, output) - - self.assertEqual(created.lazy_compare(expected), True, "FAIL: Could not change GID of an existing group to an existing one") - - # clean up - commands.getstatusoutput("groupdel %s" % (second_name)) - self.failUnlessEqual(status, 0, output) - - def testChangeGroupName(self): - """ groupmod: Test changing a group's name """ - second_name = "%s-2" % (self.groupname) - - created = GroupInfo() - created.get_info_name(self.groupname) - - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (second_name, self.groupname)) - self.failUnlessEqual(status, 0, output) - - changed = GroupInfo() - changed.get_info_gid(created["gr_gid"]) - self.assertEqual(changed["gr_name"], second_name) - self.assertEqual(changed["gr_gid"], created["gr_gid"]) - - # change back, so the group could be deleted by tearDown - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (self.groupname, second_name)) - self.failUnlessEqual(status, 0, output) - - def testChangeGroupNameExisting(self): - """ groupmod: Test changing a group's name to an existing one """ - existing = "bin" - (status, output) = commands.getstatusoutput("groupmod -n%s %s" % (existing, self.groupname)) - self.assertNotEqual(status, 0, output) # man groupmod -> 9: group name already in use - - def testChangeNonExistingGroup(self): - """ groupmod: Test properties of a non-existing group """ - nonexistent = "foobar" - (status, output) = commands.getstatusoutput("groupmod -nspameggs %s" % (nonexistent)) - self.assertNotEqual(status, 0, status) # man groupmod -> 6: specified group doesn't exist - -class TestGroupdel(unittest.TestCase, ShadowUtilsTestBase): - def testCorrectGroupdel(self): - """ groupdel: Basic usage of groupdel """ - self.groupname = "test-shadow-utils-groups" - (status, output) = commands.getstatusoutput("groupadd %s" % (self.groupname)) - self.failUnlessEqual(status, 0, output) - (status, output) = commands.getstatusoutput("groupdel %s" % (self.groupname)) - self.assertEqual(status, 0, output) - - def testGroupdelNoSuchGroup(self): - """ groupdel: Remove non-existing group """ - (status, output) = commands.getstatusoutput("groupdel foobar") - self.assertNotEqual(status, 0, output) - - def testRemovePrimaryGroup(self): - """ groupdel: Remove a primary group of an user """ - username = "test-groupdel-primary" - (status, output) = commands.getstatusoutput("useradd %s" % (username)) - self.failUnlessEqual(status, 0, output) - - (status, output) = commands.getstatusoutput("groupdel %s" % (username)) - self.assertNotEqual(status, 0, output) - - # clean up - (status, output) = commands.getstatusoutput("userdel -r %s" % (username)) - self.failUnlessEqual(status, 0, output) - -class TestPwckGrpck(unittest.TestCase): - def setUp(self): - self.passwd_path = tempfile.mktemp(suffix="test-pwck-passwd") - self.passwd_file = open(self.passwd_path, "w") - self.group_path = tempfile.mktemp(suffix="test-pwck-grp") - self.group_file = open(self.group_path, "w") - self.gshadow_path = tempfile.mktemp(suffix="test-pwck-gshadow") - self.gshadow_file = open(self.gshadow_path, "w") - - def tearDown(self): - self.passwd_file.close() - self.group_file.close() - self.gshadow_file.close() - - os.remove(self.passwd_path) - os.remove(self.group_path) - os.remove(self.gshadow_path) - - def runPwckCheck(self, passwd, group): - self.passwd_file.truncate() - self.group_file.truncate() - - self.passwd_file.write(passwd) - self.passwd_file.flush() - self.group_file.write(group) - self.group_file.flush() - - command = "pwck -r %s %s" % (self.passwd_path, self.group_path) - return commands.getstatusoutput(command) - - def runGrpCheck(self, group, gshadow): - self.group_file.truncate() - self.gshadow_file.truncate() - - self.gshadow_file.write(gshadow) - self.gshadow_file.flush() - - self.group_file.write(group) - self.group_file.flush() - - command = "grpck -r %s %s" % (self.group_path, self.gshadow_path) - return commands.getstatusoutput(command) - - - def testValidEntries(self): - """ pwck: a valid entry """ - status, output = self.runPwckCheck("foo:x:685:0::/dev/null:/bin/bash", "") - rhv = RedHatVersion() - runs = rhv.get_info() - if rhv.is_rhel(): - if runs[1] < 6: - self.assertEqual(status, 0, output) - else: - self.assertNotEqual(status, 0, output) - - def testNumberOfFields(self): - """ pwck: invalid number of fields in the record """ - not_enough = "foo:x:685:685::/dev/null" - too_many = "foo:x:685:685::/dev/null:/bin/bash:comment" - status, output = self.runPwckCheck(not_enough, "") - self.assertNotEqual(status, 0, output) - - status, output = self.runPwckCheck(too_many, "") - self.assertNotEqual(status, 0, output) - - def testUniqueUserName(self): - """ pwck: unique user name in the record """ - duplicate_username = "foo:x:685:685::/dev/null:/bin/bash\nfoo:x:686:686::/dev/null:/bin/bash" - status, output = self.runPwckCheck(duplicate_username, "") - self.assertNotEqual(status, 0, output) - - def testValidID(self): - """ pwck: invalid UID in the records """ - invalid_ids = [ "foo:x:-1:685::/dev/null:/bin/bash", "foo:x:blah:685::/dev/null:/bin/bash", "foo:x:1234567890:685::/dev/null:/bin/bash" ] - for record in invalid_ids: - status, output = self.runPwckCheck(record, "") - self.assertNotEqual(status, 0, record) - - - def testValidPrimaryGroup(self): - """ pwck: invalid primary group """ - invalid_groups = [ "foo:x:685:-1::/dev/null:/bin/bash", "foo:x:685:blah::/dev/null:/bin/bash", "foo:x:685:1234567890::/dev/null:/bin/bash" ] - for record in invalid_groups: - status, output = self.runPwckCheck("", record) - self.assertNotEqual(status, 0, output) - - def testValidHomeDir(self): - """ pwck: invalid home dir """ - for record in [ "foo:x:685:685::123:/bin/bash", "foo:x:685:685::/path/to/nowhere:/bin/bash", "foo:x:685:1234567890::!:/bin/bash" ]: - status, output = self.runPwckCheck(record, "") - self.assertNotEqual(status, 0, output) - - def testBZ164954(self): - """ grpck: regression test for BZ164954 """ - record = "root:x:0:root\nbin:x:1:root,bin,daemon\ndaemon:x:2:root,bin,daemon\nsys:x:3:root,bin,adm\nadm:x:4:root,adm,daemon" - status, output = self.runGrpCheck("", record) - self.assertNotEqual(status, 0, output) - -if __name__ == "__main__": - broken_on_rhel4 = { "TestUseradd" : [ "testCustomUID", "testCustomGID" ] } - - if os.getuid() != 0: - print "This test must be run as root" - sys.exit(1) - - unittest.main() - diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 09f4769..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -# This first play always runs on the local staging system -- hosts: localhost - roles: - - role: standard-test-beakerlib - tags: - - classic - - atomic - tests: - - sanity - required_packages: - - shadow-utils # sanity test needs shadow-utils - - python # sanity test needs python From 5d57398d35ece8d92141cbc07e712f3d4bc3fcbe Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 31 Oct 2025 12:52:35 +0100 Subject: [PATCH 098/118] Stop setting SELinux labels in chroot and prefix environments Resolves: #2249524 Signed-off-by: Iker Pedrosa --- shadow-4.18.0-selinux-chroot-prefix.patch | 10433 ++++++++++++++++++++ shadow-utils.spec | 8 +- 2 files changed, 10440 insertions(+), 1 deletion(-) create mode 100644 shadow-4.18.0-selinux-chroot-prefix.patch diff --git a/shadow-4.18.0-selinux-chroot-prefix.patch b/shadow-4.18.0-selinux-chroot-prefix.patch new file mode 100644 index 0000000..a5db17b --- /dev/null +++ b/shadow-4.18.0-selinux-chroot-prefix.patch @@ -0,0 +1,10433 @@ +From 218cc94da84459bfa5b8417d933e8898e24ecff6 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:13:12 +0200 +Subject: [PATCH 01/15] lib/: add SELinux control flag in commonio_close() + +Expand commonio_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/commonio.c | 16 ++++++++++------ + lib/commonio.h | 2 +- + lib/groupio.c | 2 +- + lib/pwio.c | 2 +- + lib/sgroupio.c | 2 +- + lib/shadowio.c | 2 +- + lib/subordinateio.c | 4 ++-- + 7 files changed, 17 insertions(+), 13 deletions(-) + +diff --git a/lib/commonio.c b/lib/commonio.c +index 7304ec00..7ee6df4d 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -473,7 +473,7 @@ int commonio_unlock (struct commonio_db *db) + + if (db->isopen) { + db->readonly = true; +- if (commonio_close (db) == 0) { ++ if (commonio_close (db, true) == 0) { + if (db->locked) { + dec_lock_count (); + } +@@ -885,7 +885,7 @@ static int write_all (const struct commonio_db *db) + } + + +-int commonio_close (struct commonio_db *db) ++int commonio_close (struct commonio_db *db, bool process_selinux) + { + bool errors = false; + char buf[1024]; +@@ -927,7 +927,8 @@ int commonio_close (struct commonio_db *db) + } + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (db->filename, S_IFREG) != 0) { ++ if (process_selinux ++ && set_selinux_file_context (db->filename, S_IFREG) != 0) { + errors = true; + } + #endif +@@ -942,7 +943,8 @@ int commonio_close (struct commonio_db *db) + db->fp = NULL; + + #ifdef WITH_SELINUX +- if (reset_selinux_file_context () != 0) { ++ if (process_selinux ++ && reset_selinux_file_context () != 0) { + errors = true; + } + #endif +@@ -961,7 +963,8 @@ int commonio_close (struct commonio_db *db) + goto fail; + + #ifdef WITH_SELINUX +- if (set_selinux_file_context (db->filename, S_IFREG) != 0) { ++ if (process_selinux ++ && set_selinux_file_context (db->filename, S_IFREG) != 0) { + errors = true; + } + #endif +@@ -999,7 +1002,8 @@ int commonio_close (struct commonio_db *db) + } + + #ifdef WITH_SELINUX +- if (reset_selinux_file_context () != 0) { ++ if (process_selinux ++ && reset_selinux_file_context () != 0) { + goto fail; + } + #endif +diff --git a/lib/commonio.h b/lib/commonio.h +index fedbefa3..dadc0500 100644 +--- a/lib/commonio.h ++++ b/lib/commonio.h +@@ -138,7 +138,7 @@ extern int commonio_append (struct commonio_db *, const void *); + extern int commonio_remove (struct commonio_db *, const char *); + extern int commonio_rewind (struct commonio_db *); + extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); +-extern int commonio_close (struct commonio_db *); ++extern int commonio_close (struct commonio_db *, bool); + extern int commonio_unlock (struct commonio_db *); + extern void commonio_del_entry (struct commonio_db *, + const struct commonio_entry *); +diff --git a/lib/groupio.c b/lib/groupio.c +index 72391433..5076fd3d 100644 +--- a/lib/groupio.c ++++ b/lib/groupio.c +@@ -186,7 +186,7 @@ int gr_rewind (void) + + int gr_close (void) + { +- return commonio_close (&group_db); ++ return commonio_close (&group_db, true); + } + + int gr_unlock (void) +diff --git a/lib/pwio.c b/lib/pwio.c +index 415447d6..6f666ec6 100644 +--- a/lib/pwio.c ++++ b/lib/pwio.c +@@ -158,7 +158,7 @@ int pw_rewind (void) + + int pw_close (void) + { +- return commonio_close (&passwd_db); ++ return commonio_close (&passwd_db, true); + } + + int pw_unlock (void) +diff --git a/lib/sgroupio.c b/lib/sgroupio.c +index ef82976d..659dcd06 100644 +--- a/lib/sgroupio.c ++++ b/lib/sgroupio.c +@@ -278,7 +278,7 @@ int sgr_rewind (void) + + int sgr_close (void) + { +- return commonio_close (&gshadow_db); ++ return commonio_close (&gshadow_db, true); + } + + int sgr_unlock (void) +diff --git a/lib/shadowio.c b/lib/shadowio.c +index 8b1c1d2c..55d33da2 100644 +--- a/lib/shadowio.c ++++ b/lib/shadowio.c +@@ -195,7 +195,7 @@ int spw_close (void) + return 0; + } + #endif /* WITH_TCB */ +- retval = commonio_close (&shadow_db); ++ retval = commonio_close (&shadow_db, true); + #ifdef WITH_TCB + if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { + return 0; +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 27f888b9..3638ec61 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -670,7 +670,7 @@ int sub_uid_remove (const char *owner, uid_t start, unsigned long count) + + int sub_uid_close (void) + { +- return commonio_close (&subordinate_uid_db); ++ return commonio_close (&subordinate_uid_db, true); + } + + int sub_uid_unlock (void) +@@ -777,7 +777,7 @@ int sub_gid_remove (const char *owner, gid_t start, unsigned long count) + + int sub_gid_close (void) + { +- return commonio_close (&subordinate_gid_db); ++ return commonio_close (&subordinate_gid_db, true); + } + + int sub_gid_unlock (void) +-- +2.50.0 + + +From 7e7dbe0e65d2795c15c42bb04c7c03b9ff86ea84 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:19:29 +0200 +Subject: [PATCH 02/15] lib/, src/: add SELinux control flag in pw_close() + +Expand pw_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/pwio.c | 4 ++-- + lib/pwio.h | 3 ++- + src/chage.c | 2 +- + src/chfn.c | 2 +- + src/chpasswd.c | 2 +- + src/chsh.c | 2 +- + src/groupmod.c | 2 +- + src/newusers.c | 2 +- + src/passwd.c | 2 +- + src/pwck.c | 2 +- + src/pwconv.c | 2 +- + src/pwunconv.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 6 +++--- + src/usermod.c | 2 +- + 15 files changed, 19 insertions(+), 18 deletions(-) + +diff --git a/lib/pwio.c b/lib/pwio.c +index 6f666ec6..c5c1cdb1 100644 +--- a/lib/pwio.c ++++ b/lib/pwio.c +@@ -156,9 +156,9 @@ int pw_rewind (void) + return commonio_next (&passwd_db); + } + +-int pw_close (void) ++int pw_close (bool process_selinux) + { +- return commonio_close (&passwd_db, true); ++ return commonio_close (&passwd_db, process_selinux); + } + + int pw_unlock (void) +diff --git a/lib/pwio.h b/lib/pwio.h +index 882a7c7a..b051a7e7 100644 +--- a/lib/pwio.h ++++ b/lib/pwio.h +@@ -14,8 +14,9 @@ + + #include + #include ++#include + +-extern int pw_close (void); ++extern int pw_close (bool process_selinux); + extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate (const char *name); + extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate_uid (uid_t uid); + extern int pw_lock (void); +diff --git a/src/chage.c b/src/chage.c +index 4b9c96d6..1ebe34c5 100644 +--- a/src/chage.c ++++ b/src/chage.c +@@ -557,7 +557,7 @@ static void close_files (void) + * Close the password file. If any entries were modified, the file + * will be re-written. + */ +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_NOPERM); +diff --git a/src/chfn.c b/src/chfn.c +index 58502929..abf88cc8 100644 +--- a/src/chfn.c ++++ b/src/chfn.c +@@ -493,7 +493,7 @@ static void update_gecos (const char *user, char *gecos) + /* + * Changes have all been made, so commit them and unlock the file. + */ +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_NOPERM); +diff --git a/src/chpasswd.c b/src/chpasswd.c +index 315e91ce..17f3d6d5 100644 +--- a/src/chpasswd.c ++++ b/src/chpasswd.c +@@ -393,7 +393,7 @@ static void close_files (void) + spw_locked = false; + } + +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/chsh.c b/src/chsh.c +index 236ff784..b5ae28da 100644 +--- a/src/chsh.c ++++ b/src/chsh.c +@@ -428,7 +428,7 @@ static void update_shell (const char *user, char *newshell) + /* + * Changes have all been made, so commit them and unlock the file. + */ +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (1); +diff --git a/src/groupmod.c b/src/groupmod.c +index cce6fd49..14b7e746 100644 +--- a/src/groupmod.c ++++ b/src/groupmod.c +@@ -534,7 +534,7 @@ static void close_files (void) + #endif /* SHADOWGRP */ + + if (gflg) { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/newusers.c b/src/newusers.c +index 38cbdddb..a738f944 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -939,7 +939,7 @@ static void open_files (void) + */ + static void close_files (void) + { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (EXIT_FAILURE); +diff --git a/src/passwd.c b/src/passwd.c +index cdd817a2..8bdff6dd 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -586,7 +586,7 @@ static void update_noshadow (void) + Prog, pw_dbname (), npw->pw_name); + fail_exit (E_FAILURE); + } +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/pwck.c b/src/pwck.c +index 6272839f..b1c6970f 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -309,7 +309,7 @@ static void close_files (bool changed) + * changes to the files. + */ + if (changed) { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/pwconv.c b/src/pwconv.c +index 1bb92752..da3a5820 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -281,7 +281,7 @@ int main (int argc, char **argv) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (E_FAILURE); + } +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/pwunconv.c b/src/pwunconv.c +index 2e4d3d75..8423cda4 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -207,7 +207,7 @@ int main (int argc, char **argv) + + (void) spw_close (); /* was only open O_RDONLY */ + +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +diff --git a/src/useradd.c b/src/useradd.c +index 36b9b8f8..8c9e9003 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1564,7 +1564,7 @@ static void process_flags (int argc, char **argv) + */ + static void close_files (void) + { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_PW_UPDATE); +diff --git a/src/userdel.c b/src/userdel.c +index 72ce11fa..b5a02b3c 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -390,7 +390,7 @@ static void remove_usergroup (void) + */ + static void close_files (void) + { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_PW_UPDATE); +@@ -1046,7 +1046,7 @@ int main (int argc, char **argv) + pw_open(O_RDONLY); + pwd = pw_locate (user_name); /* we care only about local users */ + if (NULL == pwd) { +- pw_close(); ++ pw_close(true); + fprintf (stderr, _("%s: user '%s' does not exist\n"), + Prog, user_name); + #ifdef WITH_AUDIT +@@ -1065,7 +1065,7 @@ int main (int argc, char **argv) + } else { + user_home = xstrdup(pwd->pw_dir); + } +- pw_close(); ++ pw_close(true); + } + #ifdef WITH_TCB + if (shadowtcb_set_user (user_name) == SHADOWTCB_FAILURE) { +diff --git a/src/usermod.c b/src/usermod.c +index a0f4d7dd..180b7da0 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1469,7 +1469,7 @@ process_flags(int argc, char **argv) + */ + static void close_files (void) + { +- if (pw_close () == 0) { ++ if (pw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +-- +2.50.0 + + +From abffb267659bb1f9d49af5cba69c7a9ba2489e3d Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:23:11 +0200 +Subject: [PATCH 03/15] lib/, src/: add SELinux control flag in spw_close() + +Expand spw_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/shadowio.c | 4 ++-- + lib/shadowio.h | 2 +- + src/chage.c | 2 +- + src/chpasswd.c | 2 +- + src/newusers.c | 2 +- + src/passwd.c | 4 ++-- + src/pwck.c | 4 ++-- + src/pwconv.c | 2 +- + src/pwunconv.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 2 +- + src/usermod.c | 2 +- + 12 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/lib/shadowio.c b/lib/shadowio.c +index 55d33da2..a109576d 100644 +--- a/lib/shadowio.c ++++ b/lib/shadowio.c +@@ -185,7 +185,7 @@ int spw_rewind (void) + return commonio_next (&shadow_db); + } + +-int spw_close (void) ++int spw_close (bool process_selinux) + { + int retval = 0; + #ifdef WITH_TCB +@@ -195,7 +195,7 @@ int spw_close (void) + return 0; + } + #endif /* WITH_TCB */ +- retval = commonio_close (&shadow_db, true); ++ retval = commonio_close (&shadow_db, process_selinux); + #ifdef WITH_TCB + if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { + return 0; +diff --git a/lib/shadowio.h b/lib/shadowio.h +index 4dbeb6d6..e64d8d60 100644 +--- a/lib/shadowio.h ++++ b/lib/shadowio.h +@@ -13,7 +13,7 @@ + + #include "defines.h" + +-extern int spw_close (void); ++extern int spw_close (bool process_selinux); + extern bool spw_file_present (void); + extern /*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name); + extern int spw_lock (void); +diff --git a/src/chage.c b/src/chage.c +index 1ebe34c5..a59428c5 100644 +--- a/src/chage.c ++++ b/src/chage.c +@@ -546,7 +546,7 @@ static void close_files (void) + * Now close the shadow password file, which will cause all of the + * entries to be re-written. + */ +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +diff --git a/src/chpasswd.c b/src/chpasswd.c +index 17f3d6d5..e3d8dcef 100644 +--- a/src/chpasswd.c ++++ b/src/chpasswd.c +@@ -378,7 +378,7 @@ static void open_files (void) + static void close_files (void) + { + if (is_shadow_pwd) { +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +diff --git a/src/newusers.c b/src/newusers.c +index a738f944..43672dd2 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -952,7 +952,7 @@ static void close_files (void) + pw_locked = false; + + if (is_shadow) { +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +diff --git a/src/passwd.c b/src/passwd.c +index 8bdff6dd..01efb285 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -625,7 +625,7 @@ static void update_shadow (void) + sp = spw_locate (name); + if (NULL == sp) { + /* Try to update the password in /etc/passwd instead. */ +- (void) spw_close (); ++ (void) spw_close (true); + update_noshadow (); + if (spw_unlock () == 0) { + (void) fprintf (stderr, +@@ -681,7 +681,7 @@ static void update_shadow (void) + Prog, spw_dbname (), nsp->sp_namp); + fail_exit (E_FAILURE); + } +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +diff --git a/src/pwck.c b/src/pwck.c +index b1c6970f..718b639f 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -320,7 +320,7 @@ static void close_files (bool changed) + } + fail_exit (E_CANTUPDATE); + } +- if (spw_opened && (spw_close () == 0)) { ++ if (spw_opened && (spw_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +@@ -657,7 +657,7 @@ static void check_pw_file (bool *errors, bool *changed) + } + #ifdef WITH_TCB + if (getdef_bool ("USE_TCB") && spw_locked) { +- if (spw_opened && (spw_close () == 0)) { ++ if (spw_opened && (spw_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +diff --git a/src/pwconv.c b/src/pwconv.c +index da3a5820..296b527a 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -274,7 +274,7 @@ int main (int argc, char **argv) + } + } + +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +diff --git a/src/pwunconv.c b/src/pwunconv.c +index 8423cda4..e15c8c06 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -205,7 +205,7 @@ int main (int argc, char **argv) + } + } + +- (void) spw_close (); /* was only open O_RDONLY */ ++ (void) spw_close (true); /* was only open O_RDONLY */ + + if (pw_close (true) == 0) { + fprintf (stderr, +diff --git a/src/useradd.c b/src/useradd.c +index 8c9e9003..8a7df6cf 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1569,7 +1569,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_PW_UPDATE); + } +- if (is_shadow_pwd && (spw_close () == 0)) { ++ if (is_shadow_pwd && (spw_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +diff --git a/src/userdel.c b/src/userdel.c +index b5a02b3c..b87f2459 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -403,7 +403,7 @@ static void close_files (void) + pw_locked = false; + + if (is_shadow_pwd) { +- if (spw_close () == 0) { ++ if (spw_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +diff --git a/src/usermod.c b/src/usermod.c +index 180b7da0..d741508a 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1476,7 +1476,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_PW_UPDATE); + } +- if (is_shadow_pwd && (spw_close () == 0)) { ++ if (is_shadow_pwd && (spw_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +-- +2.50.0 + + +From 16bd1d985900fe83a1f7c9001fa3b9f18e0f06f0 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:28:42 +0200 +Subject: [PATCH 04/15] lib/, src/: add SELinux control flag in gr_close() + +Expand gr_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/groupio.c | 4 ++-- + lib/groupio.h | 3 ++- + src/chgpasswd.c | 2 +- + src/gpasswd.c | 4 ++-- + src/groupadd.c | 2 +- + src/groupdel.c | 2 +- + src/groupmems.c | 2 +- + src/groupmod.c | 2 +- + src/grpck.c | 2 +- + src/grpconv.c | 2 +- + src/grpunconv.c | 2 +- + src/newusers.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 2 +- + src/usermod.c | 2 +- + 15 files changed, 18 insertions(+), 17 deletions(-) + +diff --git a/lib/groupio.c b/lib/groupio.c +index 5076fd3d..837e4c47 100644 +--- a/lib/groupio.c ++++ b/lib/groupio.c +@@ -184,9 +184,9 @@ int gr_rewind (void) + return commonio_next (&group_db); + } + +-int gr_close (void) ++int gr_close (bool process_selinux) + { +- return commonio_close (&group_db, true); ++ return commonio_close (&group_db, process_selinux); + } + + int gr_unlock (void) +diff --git a/lib/groupio.h b/lib/groupio.h +index 2014de0c..ef9242d0 100644 +--- a/lib/groupio.h ++++ b/lib/groupio.h +@@ -14,8 +14,9 @@ + + #include + #include ++#include + +-extern int gr_close (void); ++extern int gr_close (bool process_selinux); + extern /*@observer@*/ /*@null@*/const struct group *gr_locate (const char *name); + extern /*@observer@*/ /*@null@*/const struct group *gr_locate_gid (gid_t gid); + extern int gr_lock (void); +diff --git a/src/chgpasswd.c b/src/chgpasswd.c +index e7759657..9b686ef0 100644 +--- a/src/chgpasswd.c ++++ b/src/chgpasswd.c +@@ -397,7 +397,7 @@ static void close_files (void) + } + #endif + +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/gpasswd.c b/src/gpasswd.c +index 460bd14c..1013f004 100644 +--- a/src/gpasswd.c ++++ b/src/gpasswd.c +@@ -593,7 +593,7 @@ static void log_gpasswd_success_group (MAYBE_UNUSED void *arg) + */ + static void close_files (void) + { +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +@@ -724,7 +724,7 @@ static void get_group (struct group *gr) + gr->gr_passwd = xstrdup (tmpgr->gr_passwd); + gr->gr_mem = dup_list (tmpgr->gr_mem); + +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while closing read-only %s\n"), + Prog, gr_dbname ()); +diff --git a/src/groupadd.c b/src/groupadd.c +index a0d5adeb..d9a9d36c 100644 +--- a/src/groupadd.c ++++ b/src/groupadd.c +@@ -274,7 +274,7 @@ check_new_name(void) + static void close_files (void) + { + /* First, write the changes in the regular group database */ +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/groupdel.c b/src/groupdel.c +index 3d289fef..c52a2ae7 100644 +--- a/src/groupdel.c ++++ b/src/groupdel.c +@@ -149,7 +149,7 @@ static void grp_update (void) + static void close_files (void) + { + /* First, write the changes in the regular group database */ +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/groupmems.c b/src/groupmems.c +index d37b237f..fff9ae10 100644 +--- a/src/groupmems.c ++++ b/src/groupmems.c +@@ -522,7 +522,7 @@ static void open_files (void) + + static void close_files (void) + { +- if ((gr_close () == 0) && !list) { ++ if ((gr_close (true) == 0) && !list) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); + fail_exit (EXIT_GROUP_FILE); +diff --git a/src/groupmod.c b/src/groupmod.c +index 14b7e746..49b68c55 100644 +--- a/src/groupmod.c ++++ b/src/groupmod.c +@@ -481,7 +481,7 @@ static void process_flags (int argc, char **argv) + */ + static void close_files (void) + { +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/grpck.c b/src/grpck.c +index 5fcf6fad..db8f1e68 100644 +--- a/src/grpck.c ++++ b/src/grpck.c +@@ -321,7 +321,7 @@ static void close_files (bool changed) + * changes to the files. + */ + if (changed) { +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), + Prog, grp_file); + fail_exit (E_CANT_UPDATE); +diff --git a/src/grpconv.c b/src/grpconv.c +index 1b31cb85..e7928a4a 100644 +--- a/src/grpconv.c ++++ b/src/grpconv.c +@@ -241,7 +241,7 @@ int main (int argc, char **argv) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); + fail_exit (3); + } +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/grpunconv.c b/src/grpunconv.c +index ea65a329..63597da1 100644 +--- a/src/grpunconv.c ++++ b/src/grpunconv.c +@@ -193,7 +193,7 @@ int main (int argc, char **argv) + + (void) sgr_close (); /* was only open O_RDONLY */ + +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/newusers.c b/src/newusers.c +index 43672dd2..29d3a536 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -969,7 +969,7 @@ static void close_files (void) + spw_locked = false; + } + +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +diff --git a/src/useradd.c b/src/useradd.c +index 8a7df6cf..f52e5483 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1664,7 +1664,7 @@ static void close_group_files (void) + if (!do_grp_update) + return; + +- if (gr_close() == 0) { ++ if (gr_close(true) == 0) { + fprintf(stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname()); +diff --git a/src/userdel.c b/src/userdel.c +index b87f2459..b0e0d541 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -417,7 +417,7 @@ static void close_files (void) + spw_locked = false; + } + +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); + fail_exit (E_GRP_UPDATE); +diff --git a/src/usermod.c b/src/usermod.c +index d741508a..d1d26eaa 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1487,7 +1487,7 @@ static void close_files (void) + } + + if (Gflg || lflg) { +- if (gr_close () == 0) { ++ if (gr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +-- +2.50.0 + + +From f4a67dd6281a513b56c15aa1a3f292ca05674f13 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:32:05 +0200 +Subject: [PATCH 05/15] lib/, src/: add SELinux control flag in sgr_close() + +Expand sgr_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/sgroupio.c | 4 ++-- + lib/sgroupio.h | 2 +- + src/chgpasswd.c | 2 +- + src/gpasswd.c | 4 ++-- + src/groupadd.c | 2 +- + src/groupdel.c | 2 +- + src/groupmems.c | 2 +- + src/groupmod.c | 2 +- + src/grpck.c | 2 +- + src/grpconv.c | 2 +- + src/grpunconv.c | 2 +- + src/newusers.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 2 +- + src/usermod.c | 2 +- + 15 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/lib/sgroupio.c b/lib/sgroupio.c +index 659dcd06..025584ad 100644 +--- a/lib/sgroupio.c ++++ b/lib/sgroupio.c +@@ -276,9 +276,9 @@ int sgr_rewind (void) + return commonio_next (&gshadow_db); + } + +-int sgr_close (void) ++int sgr_close (bool process_selinux) + { +- return commonio_close (&gshadow_db, true); ++ return commonio_close (&gshadow_db, process_selinux); + } + + int sgr_unlock (void) +diff --git a/lib/sgroupio.h b/lib/sgroupio.h +index 3474a985..0e25fc0b 100644 +--- a/lib/sgroupio.h ++++ b/lib/sgroupio.h +@@ -12,7 +12,7 @@ + #ifndef _SGROUPIO_H + #define _SGROUPIO_H + +-extern int sgr_close (void); ++extern int sgr_close (bool process_selinux); + extern bool sgr_file_present (void); + extern /*@observer@*/ /*@null@*/const struct sgrp *sgr_locate (const char *name); + extern int sgr_lock (void); +diff --git a/src/chgpasswd.c b/src/chgpasswd.c +index 9b686ef0..47402ecc 100644 +--- a/src/chgpasswd.c ++++ b/src/chgpasswd.c +@@ -381,7 +381,7 @@ static void close_files (void) + { + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/gpasswd.c b/src/gpasswd.c +index 1013f004..a49b9140 100644 +--- a/src/gpasswd.c ++++ b/src/gpasswd.c +@@ -607,7 +607,7 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadowgrp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +@@ -762,7 +762,7 @@ static void get_group (struct group *gr) + sg->sg_adm[0] = NULL; + + } +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while closing read-only %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/groupadd.c b/src/groupadd.c +index d9a9d36c..7cfb0eb5 100644 +--- a/src/groupadd.c ++++ b/src/groupadd.c +@@ -295,7 +295,7 @@ static void close_files (void) + /* Now, write the changes in the shadow database */ + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/groupdel.c b/src/groupdel.c +index c52a2ae7..56123a7b 100644 +--- a/src/groupdel.c ++++ b/src/groupdel.c +@@ -173,7 +173,7 @@ static void close_files (void) + /* Then, write the changes in the shadow database */ + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/groupmems.c b/src/groupmems.c +index fff9ae10..5976b074 100644 +--- a/src/groupmems.c ++++ b/src/groupmems.c +@@ -538,7 +538,7 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadowgrp) { +- if ((sgr_close () == 0) && !list) { ++ if ((sgr_close (true) == 0) && !list) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); + fail_exit (EXIT_GROUP_FILE); +diff --git a/src/groupmod.c b/src/groupmod.c +index 49b68c55..3c258feb 100644 +--- a/src/groupmod.c ++++ b/src/groupmod.c +@@ -504,7 +504,7 @@ static void close_files (void) + #ifdef SHADOWGRP + if ( is_shadow_grp + && (pflg || nflg || user_list)) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/grpck.c b/src/grpck.c +index db8f1e68..872f882f 100644 +--- a/src/grpck.c ++++ b/src/grpck.c +@@ -327,7 +327,7 @@ static void close_files (bool changed) + fail_exit (E_CANT_UPDATE); + } + #ifdef SHADOWGRP +- if (is_shadow && (sgr_close () == 0)) { ++ if (is_shadow && (sgr_close (true) == 0)) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), + Prog, sgr_file); + fail_exit (E_CANT_UPDATE); +diff --git a/src/grpconv.c b/src/grpconv.c +index e7928a4a..d9c59fc9 100644 +--- a/src/grpconv.c ++++ b/src/grpconv.c +@@ -234,7 +234,7 @@ int main (int argc, char **argv) + } + } + +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/grpunconv.c b/src/grpunconv.c +index 63597da1..03fc824e 100644 +--- a/src/grpunconv.c ++++ b/src/grpunconv.c +@@ -191,7 +191,7 @@ int main (int argc, char **argv) + } + } + +- (void) sgr_close (); /* was only open O_RDONLY */ ++ (void) sgr_close (true); /* was only open O_RDONLY */ + + if (gr_close (true) == 0) { + fprintf (stderr, +diff --git a/src/newusers.c b/src/newusers.c +index 29d3a536..19a32863 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -1002,7 +1002,7 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/useradd.c b/src/useradd.c +index f52e5483..7f596673 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1672,7 +1672,7 @@ static void close_group_files (void) + fail_exit(E_GRP_UPDATE); + } + #ifdef SHADOWGRP +- if (is_shadow_grp && sgr_close() == 0) { ++ if (is_shadow_grp && sgr_close(true) == 0) { + fprintf(stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname()); +diff --git a/src/userdel.c b/src/userdel.c +index b0e0d541..1829ba4d 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -431,7 +431,7 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +diff --git a/src/usermod.c b/src/usermod.c +index d1d26eaa..dbcb32b2 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1498,7 +1498,7 @@ static void close_files (void) + } + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close () == 0) { ++ if (sgr_close (true) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +-- +2.50.0 + + +From f3dce7ede9c3f267e810fec3500498e76a305d8a Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:35:48 +0200 +Subject: [PATCH 06/15] lib/, src/: add SELinux control flag in sub_uid_close() + +Expand sub_uid_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/subordinateio.c | 14 +++++++------- + lib/subordinateio.h | 2 +- + lib/user_busy.c | 10 +++++----- + src/newuidmap.c | 2 +- + src/newusers.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 2 +- + src/usermod.c | 2 +- + 8 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 3638ec61..206a1348 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -590,7 +590,7 @@ static bool have_range(struct commonio_db *db, + + if (doclose) { + if (db == &subordinate_uid_db) +- sub_uid_close(); ++ sub_uid_close(true); + else + sub_gid_close(); + } +@@ -668,9 +668,9 @@ int sub_uid_remove (const char *owner, uid_t start, unsigned long count) + return remove_range (&subordinate_uid_db, owner, start, count); + } + +-int sub_uid_close (void) ++int sub_uid_close (bool process_selinux) + { +- return commonio_close (&subordinate_uid_db, true); ++ return commonio_close (&subordinate_uid_db, process_selinux); + } + + int sub_uid_unlock (void) +@@ -907,7 +907,7 @@ int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_r + + out: + if (id_type == ID_TYPE_UID) +- sub_uid_close(); ++ sub_uid_close(true); + else + sub_gid_close(); + +@@ -998,7 +998,7 @@ int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) + } + + if (id_type == ID_TYPE_UID) +- sub_uid_close(); ++ sub_uid_close(true); + else + sub_gid_close(); + +@@ -1068,7 +1068,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + + out: + if (id_type == ID_TYPE_UID) { +- sub_uid_close(); ++ sub_uid_close(true); + sub_uid_unlock(); + } else { + sub_gid_close(); +@@ -1118,7 +1118,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + ret = remove_range(db, range->owner, range->start, range->count) == 1; + + if (id_type == ID_TYPE_UID) { +- sub_uid_close(); ++ sub_uid_close(true); + sub_uid_unlock(); + } else { + sub_gid_close(); +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index 3d1a0547..d16c8b9e 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -13,7 +13,7 @@ + + #include "../libsubid/subid.h" + +-extern int sub_uid_close(void); ++extern int sub_uid_close(bool process_selinux); + extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); + extern bool sub_uid_file_present (void); + extern bool local_sub_uid_assigned(const char *owner); +diff --git a/lib/user_busy.c b/lib/user_busy.c +index d689d34d..ab1dd5a4 100644 +--- a/lib/user_busy.c ++++ b/lib/user_busy.c +@@ -180,7 +180,7 @@ static int user_busy_processes (const char *name, uid_t uid) + if (proc == NULL) { + perror ("opendir /proc"); + #ifdef ENABLE_SUBIDS +- sub_uid_close(); ++ sub_uid_close(true); + #endif + return 0; + } +@@ -188,7 +188,7 @@ static int user_busy_processes (const char *name, uid_t uid) + perror ("stat (\"/\")"); + (void) closedir (proc); + #ifdef ENABLE_SUBIDS +- sub_uid_close(); ++ sub_uid_close(true); + #endif + return 0; + } +@@ -225,7 +225,7 @@ static int user_busy_processes (const char *name, uid_t uid) + if (check_status (name, tmp_d_name, uid) != 0) { + (void) closedir (proc); + #ifdef ENABLE_SUBIDS +- sub_uid_close(); ++ sub_uid_close(true); + #endif + fprintf (log_get_logfd(), + _("%s: user %s is currently used by process %d\n"), +@@ -248,7 +248,7 @@ static int user_busy_processes (const char *name, uid_t uid) + (void) closedir (proc); + (void) closedir (task_dir); + #ifdef ENABLE_SUBIDS +- sub_uid_close(); ++ sub_uid_close(true); + #endif + fprintf (log_get_logfd(), + _("%s: user %s is currently used by process %d\n"), +@@ -264,7 +264,7 @@ static int user_busy_processes (const char *name, uid_t uid) + + (void) closedir (proc); + #ifdef ENABLE_SUBIDS +- sub_uid_close(); ++ sub_uid_close(true); + #endif /* ENABLE_SUBIDS */ + return 0; + } +diff --git a/src/newuidmap.c b/src/newuidmap.c +index 894c5ec8..90bd6de5 100644 +--- a/src/newuidmap.c ++++ b/src/newuidmap.c +@@ -158,7 +158,7 @@ int main(int argc, char **argv) + verify_ranges(pw, ranges, mappings); + + write_mapping(proc_dir_fd, ranges, mappings, "uid_map", pw->pw_uid); +- sub_uid_close(); ++ sub_uid_close(true); + + return EXIT_SUCCESS; + } +diff --git a/src/newusers.c b/src/newusers.c +index 19a32863..d71a792b 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -977,7 +977,7 @@ static void close_files (void) + fail_exit (EXIT_FAILURE); + } + #ifdef ENABLE_SUBIDS +- if (is_sub_uid && (sub_uid_close () == 0)) { ++ if (is_sub_uid && (sub_uid_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +diff --git a/src/useradd.c b/src/useradd.c +index 7f596673..971fec55 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1579,7 +1579,7 @@ static void close_files (void) + close_group_files (); + + #ifdef ENABLE_SUBIDS +- if (is_sub_uid && (sub_uid_close () == 0)) { ++ if (is_sub_uid && (sub_uid_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +diff --git a/src/userdel.c b/src/userdel.c +index 1829ba4d..8fe9f4e2 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -449,7 +449,7 @@ static void close_files (void) + + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_close () == 0) { ++ if (sub_uid_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (E_SUB_UID_UPDATE); +diff --git a/src/usermod.c b/src/usermod.c +index dbcb32b2..440c2406 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1561,7 +1561,7 @@ static void close_files (void) + + #ifdef ENABLE_SUBIDS + if (vflg || Vflg) { +- if (sub_uid_close () == 0) { ++ if (sub_uid_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (E_SUB_UID_UPDATE); +-- +2.50.0 + + +From ab2a2656e442043d5b39e1320552ba9850aabd27 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:38:18 +0200 +Subject: [PATCH 07/15] lib/, src/: add SELinux control flag in sub_gid_close() + +Expand sub_gid_close() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/subordinateio.c | 14 +++++++------- + lib/subordinateio.h | 2 +- + src/newgidmap.c | 2 +- + src/newusers.c | 2 +- + src/useradd.c | 2 +- + src/userdel.c | 2 +- + src/usermod.c | 2 +- + 7 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 206a1348..e2c2375a 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -592,7 +592,7 @@ static bool have_range(struct commonio_db *db, + if (db == &subordinate_uid_db) + sub_uid_close(true); + else +- sub_gid_close(); ++ sub_gid_close(true); + } + + return ret; +@@ -775,9 +775,9 @@ int sub_gid_remove (const char *owner, gid_t start, unsigned long count) + return remove_range (&subordinate_gid_db, owner, start, count); + } + +-int sub_gid_close (void) ++int sub_gid_close (bool process_selinux) + { +- return commonio_close (&subordinate_gid_db, true); ++ return commonio_close (&subordinate_gid_db, process_selinux); + } + + int sub_gid_unlock (void) +@@ -909,7 +909,7 @@ out: + if (id_type == ID_TYPE_UID) + sub_uid_close(true); + else +- sub_gid_close(); ++ sub_gid_close(true); + + *in_ranges = ranges; + return count; +@@ -1000,7 +1000,7 @@ int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) + if (id_type == ID_TYPE_UID) + sub_uid_close(true); + else +- sub_gid_close(); ++ sub_gid_close(true); + + return n; + } +@@ -1071,7 +1071,7 @@ out: + sub_uid_close(true); + sub_uid_unlock(); + } else { +- sub_gid_close(); ++ sub_gid_close(true); + sub_gid_unlock(); + } + +@@ -1121,7 +1121,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + sub_uid_close(true); + sub_uid_unlock(); + } else { +- sub_gid_close(); ++ sub_gid_close(true); + sub_gid_unlock(); + } + +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index d16c8b9e..63f5b1fb 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -31,7 +31,7 @@ extern bool release_subid_range(struct subordinate_range *range, enum subid_type + extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); + extern void free_subordinate_ranges(struct subordinate_range **ranges, int count); + +-extern int sub_gid_close(void); ++extern int sub_gid_close(bool process_selinux); + extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); + extern bool sub_gid_file_present (void); + extern bool local_sub_gid_assigned(const char *owner); +diff --git a/src/newgidmap.c b/src/newgidmap.c +index 3463e850..7ce22b5a 100644 +--- a/src/newgidmap.c ++++ b/src/newgidmap.c +@@ -230,7 +230,7 @@ int main(int argc, char **argv) + + write_setgroups(proc_dir_fd, allow_setgroups); + write_mapping(proc_dir_fd, ranges, mappings, "gid_map", pw->pw_uid); +- sub_gid_close(); ++ sub_gid_close(true); + + return EXIT_SUCCESS; + } +diff --git a/src/newusers.c b/src/newusers.c +index d71a792b..8cd11a71 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -983,7 +983,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (EXIT_FAILURE); + } +- if (is_sub_gid && (sub_gid_close () == 0)) { ++ if (is_sub_gid && (sub_gid_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +diff --git a/src/useradd.c b/src/useradd.c +index 971fec55..3d2fdb35 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1585,7 +1585,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (E_SUB_UID_UPDATE); + } +- if (is_sub_gid && (sub_gid_close () == 0)) { ++ if (is_sub_gid && (sub_gid_close (true) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +diff --git a/src/userdel.c b/src/userdel.c +index 8fe9f4e2..7dcbd923 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -463,7 +463,7 @@ static void close_files (void) + } + + if (is_sub_gid) { +- if (sub_gid_close () == 0) { ++ if (sub_gid_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); + fail_exit (E_SUB_GID_UPDATE); +diff --git a/src/usermod.c b/src/usermod.c +index 440c2406..534bdc74 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1574,7 +1574,7 @@ static void close_files (void) + sub_uid_locked = false; + } + if (wflg || Wflg) { +- if (sub_gid_close () == 0) { ++ if (sub_gid_close (true) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); + fail_exit (E_SUB_GID_UPDATE); +-- +2.50.0 + + +From 9161c63be728bfba7545bac1e4cbde8a069ad4e6 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:44:06 +0200 +Subject: [PATCH 08/15] lib/: add SELinux control flag in commonio_unlock() + +Expand commonio_unlock() interface to add a control flag for SELinux +file context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/commonio.c | 4 ++-- + lib/commonio.h | 2 +- + lib/groupio.c | 2 +- + lib/pwio.c | 2 +- + lib/sgroupio.c | 2 +- + lib/shadowio.c | 2 +- + lib/subordinateio.c | 4 ++-- + 7 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/lib/commonio.c b/lib/commonio.c +index 7ee6df4d..19653e7e 100644 +--- a/lib/commonio.c ++++ b/lib/commonio.c +@@ -467,13 +467,13 @@ static void dec_lock_count (void) + } + + +-int commonio_unlock (struct commonio_db *db) ++int commonio_unlock (struct commonio_db *db, bool process_selinux) + { + char lock[1029]; + + if (db->isopen) { + db->readonly = true; +- if (commonio_close (db, true) == 0) { ++ if (commonio_close (db, process_selinux) == 0) { + if (db->locked) { + dec_lock_count (); + } +diff --git a/lib/commonio.h b/lib/commonio.h +index dadc0500..8b8f5cf4 100644 +--- a/lib/commonio.h ++++ b/lib/commonio.h +@@ -139,7 +139,7 @@ extern int commonio_remove (struct commonio_db *, const char *); + extern int commonio_rewind (struct commonio_db *); + extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); + extern int commonio_close (struct commonio_db *, bool); +-extern int commonio_unlock (struct commonio_db *); ++extern int commonio_unlock (struct commonio_db *, bool); + extern void commonio_del_entry (struct commonio_db *, + const struct commonio_entry *); + extern int commonio_sort_wrt (struct commonio_db *shadow, +diff --git a/lib/groupio.c b/lib/groupio.c +index 837e4c47..6ad4ae69 100644 +--- a/lib/groupio.c ++++ b/lib/groupio.c +@@ -191,7 +191,7 @@ int gr_close (bool process_selinux) + + int gr_unlock (void) + { +- return commonio_unlock (&group_db); ++ return commonio_unlock (&group_db, true); + } + + void __gr_set_changed (void) +diff --git a/lib/pwio.c b/lib/pwio.c +index c5c1cdb1..c5dcb904 100644 +--- a/lib/pwio.c ++++ b/lib/pwio.c +@@ -163,7 +163,7 @@ int pw_close (bool process_selinux) + + int pw_unlock (void) + { +- return commonio_unlock (&passwd_db); ++ return commonio_unlock (&passwd_db, true); + } + + /*@null@*/struct commonio_entry *__pw_get_head (void) +diff --git a/lib/sgroupio.c b/lib/sgroupio.c +index 025584ad..dbabcc36 100644 +--- a/lib/sgroupio.c ++++ b/lib/sgroupio.c +@@ -283,7 +283,7 @@ int sgr_close (bool process_selinux) + + int sgr_unlock (void) + { +- return commonio_unlock (&gshadow_db); ++ return commonio_unlock (&gshadow_db, true); + } + + void __sgr_set_changed (void) +diff --git a/lib/shadowio.c b/lib/shadowio.c +index a109576d..9866af6d 100644 +--- a/lib/shadowio.c ++++ b/lib/shadowio.c +@@ -211,7 +211,7 @@ int spw_unlock (void) + + if (!getdef_bool ("USE_TCB")) { + #endif /* WITH_TCB */ +- return commonio_unlock (&shadow_db); ++ return commonio_unlock (&shadow_db, true); + #ifdef WITH_TCB + } + if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index e2c2375a..9587e1a9 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -675,7 +675,7 @@ int sub_uid_close (bool process_selinux) + + int sub_uid_unlock (void) + { +- return commonio_unlock (&subordinate_uid_db); ++ return commonio_unlock (&subordinate_uid_db, true); + } + + uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count) +@@ -782,7 +782,7 @@ int sub_gid_close (bool process_selinux) + + int sub_gid_unlock (void) + { +- return commonio_unlock (&subordinate_gid_db); ++ return commonio_unlock (&subordinate_gid_db, true); + } + + gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) +-- +2.50.0 + + +From 9609c3ba7d4097c2ff63ee6ccfa6b74c41fbde5e Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:53:17 +0200 +Subject: [PATCH 09/15] lib/, src/: add SELinux control flag in pw_unlock() + +Expand pw_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/cleanup_user.c | 2 +- + lib/lockpw.c | 4 ++-- + lib/pwio.c | 4 ++-- + lib/pwio.h | 2 +- + src/chage.c | 4 ++-- + src/chfn.c | 4 ++-- + src/chpasswd.c | 4 ++-- + src/chsh.c | 4 ++-- + src/newusers.c | 4 ++-- + src/passwd.c | 4 ++-- + src/pwck.c | 4 ++-- + src/pwconv.c | 4 ++-- + src/pwunconv.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 16 files changed, 30 insertions(+), 30 deletions(-) + +diff --git a/lib/cleanup_user.c b/lib/cleanup_user.c +index 809caaf3..a661f5e9 100644 +--- a/lib/cleanup_user.c ++++ b/lib/cleanup_user.c +@@ -98,7 +98,7 @@ void cleanup_report_add_user_shadow (void *user_name) + */ + void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) + { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), pw_dbname ()); +diff --git a/lib/lockpw.c b/lib/lockpw.c +index 15e7c8f4..f73c434a 100644 +--- a/lib/lockpw.c ++++ b/lib/lockpw.c +@@ -56,7 +56,7 @@ int lckpwdf (void) + */ + + if (i == 15) { +- pw_unlock (); ++ pw_unlock (true); + return -1; + } + +@@ -78,7 +78,7 @@ int ulckpwdf (void) + * Unlock both files. + */ + +- return (pw_unlock () && spw_unlock ())? 0 : -1; ++ return (pw_unlock (true) && spw_unlock ())? 0 : -1; + } + #else + extern int ISO_C_forbids_an_empty_translation_unit; +diff --git a/lib/pwio.c b/lib/pwio.c +index c5dcb904..78146c37 100644 +--- a/lib/pwio.c ++++ b/lib/pwio.c +@@ -161,9 +161,9 @@ int pw_close (bool process_selinux) + return commonio_close (&passwd_db, process_selinux); + } + +-int pw_unlock (void) ++int pw_unlock (bool process_selinux) + { +- return commonio_unlock (&passwd_db, true); ++ return commonio_unlock (&passwd_db, process_selinux); + } + + /*@null@*/struct commonio_entry *__pw_get_head (void) +diff --git a/lib/pwio.h b/lib/pwio.h +index b051a7e7..0903b8bd 100644 +--- a/lib/pwio.h ++++ b/lib/pwio.h +@@ -26,7 +26,7 @@ extern /*@observer@*/ /*@null@*/const struct passwd *pw_next (void); + extern int pw_open (int mode); + extern int pw_remove (const char *name); + extern int pw_rewind (void); +-extern int pw_unlock (void); ++extern int pw_unlock (bool process_selinux); + extern int pw_update (const struct passwd *pw); + extern int pw_sort (void); + +diff --git a/src/chage.c b/src/chage.c +index a59428c5..d3a42ccf 100644 +--- a/src/chage.c ++++ b/src/chage.c +@@ -101,7 +101,7 @@ fail_exit (int code) + } + } + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -568,7 +568,7 @@ static void close_files (void) + /* continue */ + } + spw_locked = false; +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/chfn.c b/src/chfn.c +index abf88cc8..dca81486 100644 +--- a/src/chfn.c ++++ b/src/chfn.c +@@ -79,7 +79,7 @@ static void get_old_fields (const char *gecos); + static void fail_exit (int code) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -498,7 +498,7 @@ static void update_gecos (const char *user, char *gecos) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_NOPERM); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/chpasswd.c b/src/chpasswd.c +index e3d8dcef..5323c520 100644 +--- a/src/chpasswd.c ++++ b/src/chpasswd.c +@@ -81,7 +81,7 @@ static void close_files (void); + static void fail_exit (int code) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -400,7 +400,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (1); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/chsh.c b/src/chsh.c +index b5ae28da..4403d412 100644 +--- a/src/chsh.c ++++ b/src/chsh.c +@@ -78,7 +78,7 @@ static void + fail_exit (int code) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -433,7 +433,7 @@ static void update_shell (const char *user, char *newshell) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (1); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/newusers.c b/src/newusers.c +index 8cd11a71..669b6236 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -172,7 +172,7 @@ static void fail_exit (int code) + } + } + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -944,7 +944,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (EXIT_FAILURE); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/passwd.c b/src/passwd.c +index 01efb285..8a55d797 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -483,7 +483,7 @@ static void + fail_exit (int status) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -593,7 +593,7 @@ static void update_noshadow (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_FAILURE); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +diff --git a/src/pwck.c b/src/pwck.c +index 718b639f..f30c5289 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -96,7 +96,7 @@ static void fail_exit (int code) + } + + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + if (use_system_pw_file) { + SYSLOG ((LOG_ERR, "failed to unlock %s", +@@ -351,7 +351,7 @@ static void close_files (bool changed) + } + spw_locked = false; + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +diff --git a/src/pwconv.c b/src/pwconv.c +index 296b527a..82181bb4 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -83,7 +83,7 @@ static void process_flags (int argc, char **argv); + static void fail_exit (int status) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -299,7 +299,7 @@ int main (int argc, char **argv) + /* continue */ + } + +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/pwunconv.c b/src/pwunconv.c +index e15c8c06..72944fe5 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -54,7 +54,7 @@ static void fail_exit (int status) + } + } + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -227,7 +227,7 @@ int main (int argc, char **argv) + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/useradd.c b/src/useradd.c +index 3d2fdb35..aa070f2d 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -270,7 +270,7 @@ static void fail_exit (int code) + SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); + /* continue */ + } +- if (pw_locked && pw_unlock() == 0) { ++ if (pw_locked && pw_unlock(true) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); + /* continue */ +@@ -1606,7 +1606,7 @@ static void close_files (void) + } + spw_locked = false; + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index 7dcbd923..b4e87820 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -395,7 +395,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_PW_UPDATE); + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -484,7 +484,7 @@ static void close_files (void) + static void fail_exit (int code) + { + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index 534bdc74..6f761404 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -655,7 +655,7 @@ fail_exit (int code) + } + } + if (pw_locked) { +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -1544,7 +1544,7 @@ static void close_files (void) + /* continue */ + } + } +- if (pw_unlock () == 0) { ++ if (pw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +-- +2.50.0 + + +From bdce75b7b6f7ec69cda287b081de6ca83022ee79 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 15:57:21 +0200 +Subject: [PATCH 10/15] lib/, src/: add SELinux control flag in spw_unlock() + +Expand spw_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/cleanup_user.c | 2 +- + lib/lockpw.c | 2 +- + lib/shadowio.c | 4 ++-- + lib/shadowio.h | 2 +- + src/chage.c | 4 ++-- + src/chpasswd.c | 4 ++-- + src/newusers.c | 4 ++-- + src/passwd.c | 6 +++--- + src/pwck.c | 8 ++++---- + src/pwconv.c | 4 ++-- + src/pwunconv.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 14 files changed, 28 insertions(+), 28 deletions(-) + +diff --git a/lib/cleanup_user.c b/lib/cleanup_user.c +index a661f5e9..b3a5a66e 100644 +--- a/lib/cleanup_user.c ++++ b/lib/cleanup_user.c +@@ -117,7 +117,7 @@ void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) + */ + void cleanup_unlock_shadow (MAYBE_UNUSED void *arg) + { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), spw_dbname ()); +diff --git a/lib/lockpw.c b/lib/lockpw.c +index f73c434a..7c99d56e 100644 +--- a/lib/lockpw.c ++++ b/lib/lockpw.c +@@ -78,7 +78,7 @@ int ulckpwdf (void) + * Unlock both files. + */ + +- return (pw_unlock (true) && spw_unlock ())? 0 : -1; ++ return (pw_unlock (true) && spw_unlock (true))? 0 : -1; + } + #else + extern int ISO_C_forbids_an_empty_translation_unit; +diff --git a/lib/shadowio.c b/lib/shadowio.c +index 9866af6d..71089eda 100644 +--- a/lib/shadowio.c ++++ b/lib/shadowio.c +@@ -204,14 +204,14 @@ int spw_close (bool process_selinux) + return retval; + } + +-int spw_unlock (void) ++int spw_unlock (bool process_selinux) + { + #ifdef WITH_TCB + int retval = 0; + + if (!getdef_bool ("USE_TCB")) { + #endif /* WITH_TCB */ +- return commonio_unlock (&shadow_db, true); ++ return commonio_unlock (&shadow_db, process_selinux); + #ifdef WITH_TCB + } + if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { +diff --git a/lib/shadowio.h b/lib/shadowio.h +index e64d8d60..be645d0e 100644 +--- a/lib/shadowio.h ++++ b/lib/shadowio.h +@@ -23,7 +23,7 @@ extern /*@observer@*/ /*@null@*/const struct spwd *spw_next (void); + extern int spw_open (int mode); + extern int spw_remove (const char *name); + extern int spw_rewind (void); +-extern int spw_unlock (void); ++extern int spw_unlock (bool process_selinux); + extern int spw_update (const struct spwd *sp); + extern int spw_sort (void); + +diff --git a/src/chage.c b/src/chage.c +index d3a42ccf..e77a46de 100644 +--- a/src/chage.c ++++ b/src/chage.c +@@ -94,7 +94,7 @@ static void + fail_exit (int code) + { + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -562,7 +562,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_NOPERM); + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +diff --git a/src/chpasswd.c b/src/chpasswd.c +index 5323c520..2656b039 100644 +--- a/src/chpasswd.c ++++ b/src/chpasswd.c +@@ -89,7 +89,7 @@ static void fail_exit (int code) + } + + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -385,7 +385,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (1); + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +diff --git a/src/newusers.c b/src/newusers.c +index 669b6236..4cbb1639 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -165,7 +165,7 @@ static void usage (int status) + static void fail_exit (int code) + { + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -959,7 +959,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (EXIT_FAILURE); + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +diff --git a/src/passwd.c b/src/passwd.c +index 8a55d797..512dc572 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -491,7 +491,7 @@ fail_exit (int status) + } + + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -627,7 +627,7 @@ static void update_shadow (void) + /* Try to update the password in /etc/passwd instead. */ + (void) spw_close (true); + update_noshadow (); +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -688,7 +688,7 @@ static void update_shadow (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (E_FAILURE); + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +diff --git a/src/pwck.c b/src/pwck.c +index f30c5289..9c4cc29a 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -85,7 +85,7 @@ extern int allow_bad_names; + static void fail_exit (int code) + { + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + if (use_system_spw_file) { + SYSLOG ((LOG_ERR, "failed to unlock %s", +@@ -338,7 +338,7 @@ static void close_files (bool changed) + * Don't be anti-social - unlock the files when you're done. + */ + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -581,7 +581,7 @@ static void check_pw_file (bool *errors, bool *changed) + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); + *errors = true; +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -669,7 +669,7 @@ static void check_pw_file (bool *errors, bool *changed) + } else { + spw_opened = false; + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +diff --git a/src/pwconv.c b/src/pwconv.c +index 82181bb4..b0d668b5 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -91,7 +91,7 @@ static void fail_exit (int status) + } + + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -305,7 +305,7 @@ int main (int argc, char **argv) + /* continue */ + } + +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +diff --git a/src/pwunconv.c b/src/pwunconv.c +index 72944fe5..7a6d2be5 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -47,7 +47,7 @@ static void process_flags (int argc, char **argv); + static void fail_exit (int status) + { + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -222,7 +222,7 @@ int main (int argc, char **argv) + fail_exit (3); + } + +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +diff --git a/src/useradd.c b/src/useradd.c +index aa070f2d..9c8b774f 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -265,7 +265,7 @@ static void fail_exit (int code) + SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home)); + } + +- if (spw_locked && spw_unlock() == 0) { ++ if (spw_locked && spw_unlock(true) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); + /* continue */ +@@ -1593,7 +1593,7 @@ static void close_files (void) + } + #endif /* ENABLE_SUBIDS */ + if (is_shadow_pwd) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index b4e87820..478c22d5 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -409,7 +409,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (E_PW_UPDATE); + } +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -498,7 +498,7 @@ static void fail_exit (int code) + } + } + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index 6f761404..68373f35 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -648,7 +648,7 @@ fail_exit (int code) + } + #endif + if (spw_locked) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -1534,7 +1534,7 @@ static void close_files (void) + } + + if (is_shadow_pwd) { +- if (spw_unlock () == 0) { ++ if (spw_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +-- +2.50.0 + + +From 68eb3395a4bcbbdb820b6c8c17cc64fb08749d11 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 16:00:43 +0200 +Subject: [PATCH 11/15] lib/, src/: add SELinux control flag in gr_unlock() + +Expand gr_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/cleanup_group.c | 2 +- + lib/groupio.c | 4 ++-- + lib/groupio.h | 2 +- + src/chgpasswd.c | 4 ++-- + src/groupmems.c | 4 ++-- + src/grpck.c | 4 ++-- + src/grpconv.c | 4 ++-- + src/grpunconv.c | 4 ++-- + src/newusers.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 12 files changed, 22 insertions(+), 22 deletions(-) + +diff --git a/lib/cleanup_group.c b/lib/cleanup_group.c +index 54480092..a5846152 100644 +--- a/lib/cleanup_group.c ++++ b/lib/cleanup_group.c +@@ -181,7 +181,7 @@ void cleanup_report_del_group_gshadow (void *group_name) + */ + void cleanup_unlock_group (MAYBE_UNUSED void *arg) + { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), gr_dbname ()); +diff --git a/lib/groupio.c b/lib/groupio.c +index 6ad4ae69..f21aa618 100644 +--- a/lib/groupio.c ++++ b/lib/groupio.c +@@ -189,9 +189,9 @@ int gr_close (bool process_selinux) + return commonio_close (&group_db, process_selinux); + } + +-int gr_unlock (void) ++int gr_unlock (bool process_selinux) + { +- return commonio_unlock (&group_db, true); ++ return commonio_unlock (&group_db, process_selinux); + } + + void __gr_set_changed (void) +diff --git a/lib/groupio.h b/lib/groupio.h +index ef9242d0..eae13cd3 100644 +--- a/lib/groupio.h ++++ b/lib/groupio.h +@@ -26,7 +26,7 @@ extern /*@observer@*/ /*@null@*/const struct group *gr_next (void); + extern int gr_open (int mode); + extern int gr_remove (const char *name); + extern int gr_rewind (void); +-extern int gr_unlock (void); ++extern int gr_unlock (bool process_selinux); + extern int gr_update (const struct group *gr); + extern int gr_sort (void); + +diff --git a/src/chgpasswd.c b/src/chgpasswd.c +index 47402ecc..84553d81 100644 +--- a/src/chgpasswd.c ++++ b/src/chgpasswd.c +@@ -82,7 +82,7 @@ static void close_files (void); + static void fail_exit (int code) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -404,7 +404,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); + fail_exit (1); + } +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/groupmems.c b/src/groupmems.c +index 5976b074..0c59474f 100644 +--- a/src/groupmems.c ++++ b/src/groupmems.c +@@ -457,7 +457,7 @@ static void check_perms (void) + static void fail_exit (int code) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +@@ -528,7 +528,7 @@ static void close_files (void) + fail_exit (EXIT_GROUP_FILE); + } + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/grpck.c b/src/grpck.c +index 872f882f..bd2014fc 100644 +--- a/src/grpck.c ++++ b/src/grpck.c +@@ -92,7 +92,7 @@ static void check_sgr_file (bool *errors, bool *changed); + static void fail_exit (int status) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -349,7 +349,7 @@ static void close_files (bool changed) + } + #endif + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/grpconv.c b/src/grpconv.c +index d9c59fc9..3160b8b1 100644 +--- a/src/grpconv.c ++++ b/src/grpconv.c +@@ -56,7 +56,7 @@ static void process_flags (int argc, char **argv); + static void fail_exit (int status) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -253,7 +253,7 @@ int main (int argc, char **argv) + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ + } +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/grpunconv.c b/src/grpunconv.c +index 03fc824e..085c48ac 100644 +--- a/src/grpunconv.c ++++ b/src/grpunconv.c +@@ -55,7 +55,7 @@ static void process_flags (int argc, char **argv); + static void fail_exit (int status) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -209,7 +209,7 @@ int main (int argc, char **argv) + fail_exit (3); + } + +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/newusers.c b/src/newusers.c +index 4cbb1639..47f01661 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -179,7 +179,7 @@ static void fail_exit (int code) + } + } + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -991,7 +991,7 @@ static void close_files (void) + } + #endif /* ENABLE_SUBIDS */ + +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +diff --git a/src/useradd.c b/src/useradd.c +index 9c8b774f..75cfbde2 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -275,7 +275,7 @@ static void fail_exit (int code) + SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); + /* continue */ + } +- if (gr_locked && gr_unlock() == 0) { ++ if (gr_locked && gr_unlock(true) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); + /* continue */ +@@ -1690,7 +1690,7 @@ static void close_group_files (void) + */ + static void unlock_group_files (void) + { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index 478c22d5..12696732 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -422,7 +422,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); + fail_exit (E_GRP_UPDATE); + } +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -491,7 +491,7 @@ static void fail_exit (int code) + } + } + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index 68373f35..2e21a70f 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -632,7 +632,7 @@ static void + fail_exit (int code) + { + if (gr_locked) { +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -1522,7 +1522,7 @@ static void close_files (void) + } + } + #endif +- if (gr_unlock () == 0) { ++ if (gr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +-- +2.50.0 + + +From 37b636524cfb7c9b7dce8c56484fb60795ef2b91 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 16:03:58 +0200 +Subject: [PATCH 12/15] lib/, src/: add SELinux control flag in sgr_unlock() + +Expand sgr_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/cleanup_group.c | 2 +- + lib/sgroupio.c | 4 ++-- + lib/sgroupio.h | 2 +- + src/chgpasswd.c | 4 ++-- + src/groupmems.c | 4 ++-- + src/grpck.c | 4 ++-- + src/grpconv.c | 4 ++-- + src/grpunconv.c | 4 ++-- + src/newusers.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 12 files changed, 22 insertions(+), 22 deletions(-) + +diff --git a/lib/cleanup_group.c b/lib/cleanup_group.c +index a5846152..dc9f1eb2 100644 +--- a/lib/cleanup_group.c ++++ b/lib/cleanup_group.c +@@ -201,7 +201,7 @@ void cleanup_unlock_group (MAYBE_UNUSED void *arg) + */ + void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg) + { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), sgr_dbname ()); +diff --git a/lib/sgroupio.c b/lib/sgroupio.c +index dbabcc36..4239e23d 100644 +--- a/lib/sgroupio.c ++++ b/lib/sgroupio.c +@@ -281,9 +281,9 @@ int sgr_close (bool process_selinux) + return commonio_close (&gshadow_db, process_selinux); + } + +-int sgr_unlock (void) ++int sgr_unlock (bool process_selinux) + { +- return commonio_unlock (&gshadow_db, true); ++ return commonio_unlock (&gshadow_db, process_selinux); + } + + void __sgr_set_changed (void) +diff --git a/lib/sgroupio.h b/lib/sgroupio.h +index 0e25fc0b..256f6d54 100644 +--- a/lib/sgroupio.h ++++ b/lib/sgroupio.h +@@ -22,7 +22,7 @@ extern /*@null@*/const struct sgrp *sgr_next (void); + extern int sgr_open (int mode); + extern int sgr_remove (const char *name); + extern int sgr_rewind (void); +-extern int sgr_unlock (void); ++extern int sgr_unlock (bool process_selinux); + extern int sgr_update (const struct sgrp *sg); + extern int sgr_sort (void); + +diff --git a/src/chgpasswd.c b/src/chgpasswd.c +index 84553d81..27094f50 100644 +--- a/src/chgpasswd.c ++++ b/src/chgpasswd.c +@@ -91,7 +91,7 @@ static void fail_exit (int code) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -388,7 +388,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); + fail_exit (1); + } +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/groupmems.c b/src/groupmems.c +index 0c59474f..f39724c8 100644 +--- a/src/groupmems.c ++++ b/src/groupmems.c +@@ -468,7 +468,7 @@ static void fail_exit (int code) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +@@ -544,7 +544,7 @@ static void close_files (void) + fail_exit (EXIT_GROUP_FILE); + } + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/grpck.c b/src/grpck.c +index bd2014fc..bc178d52 100644 +--- a/src/grpck.c ++++ b/src/grpck.c +@@ -101,7 +101,7 @@ static void fail_exit (int status) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -340,7 +340,7 @@ static void close_files (bool changed) + */ + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/grpconv.c b/src/grpconv.c +index 3160b8b1..5958d3f5 100644 +--- a/src/grpconv.c ++++ b/src/grpconv.c +@@ -64,7 +64,7 @@ static void fail_exit (int status) + } + + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -248,7 +248,7 @@ int main (int argc, char **argv) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); + fail_exit (3); + } +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/grpunconv.c b/src/grpunconv.c +index 085c48ac..5256e0bc 100644 +--- a/src/grpunconv.c ++++ b/src/grpunconv.c +@@ -63,7 +63,7 @@ static void fail_exit (int status) + } + + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -215,7 +215,7 @@ int main (int argc, char **argv) + /* continue */ + } + +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/newusers.c b/src/newusers.c +index 47f01661..261a5911 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -187,7 +187,7 @@ static void fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -1009,7 +1009,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); + fail_exit (EXIT_FAILURE); + } +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +diff --git a/src/useradd.c b/src/useradd.c +index 75cfbde2..cb7ac88e 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -281,7 +281,7 @@ static void fail_exit (int code) + /* continue */ + } + #ifdef SHADOWGRP +- if (sgr_locked && sgr_unlock() == 0) { ++ if (sgr_locked && sgr_unlock(true) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); + /* continue */ +@@ -1704,7 +1704,7 @@ static void unlock_group_files (void) + gr_locked = false; + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index 12696732..80ed1a48 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -438,7 +438,7 @@ static void close_files (void) + fail_exit (E_GRP_UPDATE); + } + +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -506,7 +506,7 @@ static void fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index 2e21a70f..69ea8e55 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -640,7 +640,7 @@ fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -1511,7 +1511,7 @@ static void close_files (void) + #endif + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_unlock () == 0) { ++ if (sgr_unlock (true) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +-- +2.50.0 + + +From dee1a5a5782b8aafcc32c7f93a53ce591355d1b3 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 16:06:57 +0200 +Subject: [PATCH 13/15] src/vipw.c: add SELinux control flag in unlock + +All unlock functions require the SELinux control flag, thus add it as an +argument. + +Signed-off-by: Iker Pedrosa +--- + src/vipw.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/vipw.c b/src/vipw.c +index 3c840e9f..ba323e0e 100644 +--- a/src/vipw.c ++++ b/src/vipw.c +@@ -62,7 +62,7 @@ static const char *Prog; + static const char *filename, *fileeditname; + static bool filelocked = false; + static bool createedit = false; +-static int (*unlock) (void); ++static int (*unlock) (bool); + static bool quiet = false; + #ifdef WITH_TCB + static const char *user = NULL; +@@ -74,7 +74,7 @@ static bool tcb_mode = false; + static void usage (int status); + static int create_backup_file (FILE *, const char *, struct stat *); + static void vipwexit (const char *msg, int syserr, int ret); +-static void vipwedit (const char *, int (*)(void), int (*)(void)); ++static void vipwedit (const char *, int (*)(void), int (*)(bool)); + + /* + * usage - display usage message and exit +@@ -164,7 +164,7 @@ static void vipwexit (const char *msg, int syserr, int ret) + } + } + if (filelocked) { +- if ((*unlock) () == 0) { ++ if ((*unlock) (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, fileeditname); + SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname)); + /* continue */ +@@ -195,7 +195,7 @@ static void vipwexit (const char *msg, int syserr, int ret) + * + */ + static void +-vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) ++vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (bool)) + { + int status; + char *to_rename; +@@ -467,7 +467,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) + } + #endif /* WITH_TCB */ + +- if ((*file_unlock) () == 0) { ++ if ((*file_unlock) (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, fileeditname); + SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname)); + /* continue */ +-- +2.50.0 + + +From f297173f0247b9288c424e765e972eb13d4c9ded Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 16:10:09 +0200 +Subject: [PATCH 14/15] lib/, src/: add SELinux control flag in + sub_uid_unlock() + +Expand sub_uid_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/subordinateio.c | 12 ++++++------ + lib/subordinateio.h | 2 +- + src/newusers.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 6 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index 9587e1a9..eaa2dc99 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -673,9 +673,9 @@ int sub_uid_close (bool process_selinux) + return commonio_close (&subordinate_uid_db, process_selinux); + } + +-int sub_uid_unlock (void) ++int sub_uid_unlock (bool process_selinux) + { +- return commonio_unlock (&subordinate_uid_db, true); ++ return commonio_unlock (&subordinate_uid_db, process_selinux); + } + + uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count) +@@ -1022,7 +1022,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + } + if (!sub_uid_open(O_CREAT | O_RDWR)) { + printf("Failed opening subuids (errno %d)\n", errno); +- sub_uid_unlock(); ++ sub_uid_unlock(true); + return false; + } + db = &subordinate_uid_db; +@@ -1069,7 +1069,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + out: + if (id_type == ID_TYPE_UID) { + sub_uid_close(true); +- sub_uid_unlock(); ++ sub_uid_unlock(true); + } else { + sub_gid_close(true); + sub_gid_unlock(); +@@ -1094,7 +1094,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + } + if (!sub_uid_open(O_CREAT | O_RDWR)) { + printf("Failed opening subuids (errno %d)\n", errno); +- sub_uid_unlock(); ++ sub_uid_unlock(true); + return false; + } + db = &subordinate_uid_db; +@@ -1119,7 +1119,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + + if (id_type == ID_TYPE_UID) { + sub_uid_close(true); +- sub_uid_unlock(); ++ sub_uid_unlock(true); + } else { + sub_gid_close(true); + sub_gid_unlock(); +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index 63f5b1fb..7914613d 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -21,7 +21,7 @@ extern int sub_uid_lock (void); + extern int sub_uid_setdbname (const char *filename); + extern /*@observer@*/const char *sub_uid_dbname (void); + extern int sub_uid_open (int mode); +-extern int sub_uid_unlock (void); ++extern int sub_uid_unlock (bool process_selinux); + extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); + extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); + extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); +diff --git a/src/newusers.c b/src/newusers.c +index 261a5911..65bedf9b 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -196,7 +196,7 @@ static void fail_exit (int code) + #endif + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -1021,7 +1021,7 @@ static void close_files (void) + #endif + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +diff --git a/src/useradd.c b/src/useradd.c +index cb7ac88e..f65d24d1 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -288,7 +288,7 @@ static void fail_exit (int code) + } + #endif + #ifdef ENABLE_SUBIDS +- if (sub_uid_locked && sub_uid_unlock() == 0) { ++ if (sub_uid_locked && sub_uid_unlock(true) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); + /* continue */ +@@ -1623,7 +1623,7 @@ static void close_files (void) + + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index 80ed1a48..68e53b85 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -454,7 +454,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (E_SUB_UID_UPDATE); + } +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -515,7 +515,7 @@ static void fail_exit (int code) + #endif /* SHADOWGRP */ + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index 69ea8e55..fc6cc51c 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -663,7 +663,7 @@ fail_exit (int code) + } + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -1566,7 +1566,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); + fail_exit (E_SUB_UID_UPDATE); + } +- if (sub_uid_unlock () == 0) { ++ if (sub_uid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +-- +2.50.0 + + +From 7b2bbdd0347c34bc5e094caf26c55694fb5935e7 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 25 Apr 2025 16:12:40 +0200 +Subject: [PATCH 15/15] lib/, src/: add SELinux control flag in + sub_gid_unlock() + +Expand sub_gid_unlock() interface to add a control flag for SELinux file +context processing. + +Signed-off-by: Iker Pedrosa +--- + lib/subordinateio.c | 12 ++++++------ + lib/subordinateio.h | 2 +- + src/newusers.c | 4 ++-- + src/useradd.c | 4 ++-- + src/userdel.c | 4 ++-- + src/usermod.c | 4 ++-- + 6 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/lib/subordinateio.c b/lib/subordinateio.c +index eaa2dc99..d1ab03f3 100644 +--- a/lib/subordinateio.c ++++ b/lib/subordinateio.c +@@ -780,9 +780,9 @@ int sub_gid_close (bool process_selinux) + return commonio_close (&subordinate_gid_db, process_selinux); + } + +-int sub_gid_unlock (void) ++int sub_gid_unlock (bool process_selinux) + { +- return commonio_unlock (&subordinate_gid_db, true); ++ return commonio_unlock (&subordinate_gid_db, process_selinux); + } + + gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) +@@ -1034,7 +1034,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b + } + if (!sub_gid_open(O_CREAT | O_RDWR)) { + printf("Failed opening subgids (errno %d)\n", errno); +- sub_gid_unlock(); ++ sub_gid_unlock(true); + return false; + } + db = &subordinate_gid_db; +@@ -1072,7 +1072,7 @@ out: + sub_uid_unlock(true); + } else { + sub_gid_close(true); +- sub_gid_unlock(); ++ sub_gid_unlock(true); + } + + return ret; +@@ -1106,7 +1106,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + } + if (!sub_gid_open(O_CREAT | O_RDWR)) { + printf("Failed opening subgids (errno %d)\n", errno); +- sub_gid_unlock(); ++ sub_gid_unlock(true); + return false; + } + db = &subordinate_gid_db; +@@ -1122,7 +1122,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ + sub_uid_unlock(true); + } else { + sub_gid_close(true); +- sub_gid_unlock(); ++ sub_gid_unlock(true); + } + + return ret; +diff --git a/lib/subordinateio.h b/lib/subordinateio.h +index 7914613d..1ca4b66d 100644 +--- a/lib/subordinateio.h ++++ b/lib/subordinateio.h +@@ -39,7 +39,7 @@ extern int sub_gid_lock (void); + extern int sub_gid_setdbname (const char *filename); + extern /*@observer@*/const char *sub_gid_dbname (void); + extern int sub_gid_open (int mode); +-extern int sub_gid_unlock (void); ++extern int sub_gid_unlock (bool process_selinux); + extern int sub_gid_add (const char *owner, gid_t start, unsigned long count); + extern int sub_gid_remove (const char *owner, gid_t start, unsigned long count); + extern uid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count); +diff --git a/src/newusers.c b/src/newusers.c +index 65bedf9b..4eb6065c 100644 +--- a/src/newusers.c ++++ b/src/newusers.c +@@ -203,7 +203,7 @@ static void fail_exit (int code) + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -1029,7 +1029,7 @@ static void close_files (void) + sub_uid_locked = false; + } + if (is_sub_gid) { +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +diff --git a/src/useradd.c b/src/useradd.c +index f65d24d1..98c2d284 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -293,7 +293,7 @@ static void fail_exit (int code) + SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); + /* continue */ + } +- if (sub_gid_locked && sub_gid_unlock() == 0) { ++ if (sub_gid_locked && sub_gid_unlock(true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); + /* continue */ +@@ -1637,7 +1637,7 @@ static void close_files (void) + sub_uid_locked = false; + } + if (is_sub_gid) { +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + #ifdef WITH_AUDIT +diff --git a/src/userdel.c b/src/userdel.c +index 68e53b85..524c96a6 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -468,7 +468,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); + fail_exit (E_SUB_GID_UPDATE); + } +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -522,7 +522,7 @@ static void fail_exit (int code) + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +diff --git a/src/usermod.c b/src/usermod.c +index fc6cc51c..68000a0e 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -670,7 +670,7 @@ fail_exit (int code) + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -1579,7 +1579,7 @@ static void close_files (void) + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); + fail_exit (E_SUB_GID_UPDATE); + } +- if (sub_gid_unlock () == 0) { ++ if (sub_gid_unlock (true) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +-- +2.50.0 + +diff -up shadow-4.18.0/src/newusers.c.test-chroot2 shadow-4.18.0/src/newusers.c +--- shadow-4.18.0/src/newusers.c.test-chroot2 2025-07-08 11:22:16.257291774 +0200 ++++ shadow-4.18.0/src/newusers.c 2025-07-08 11:23:28.210122190 +0200 +@@ -60,6 +60,10 @@ + #include "string/strtok/stpsep.h" + #include "string/strtok/strsep2arr.h" + ++struct option_flags { ++ bool chroot; ++}; ++ + + /* + * Global variables +@@ -103,7 +107,7 @@ static bool sub_gid_locked = false; + + /* local function prototypes */ + NORETURN static void usage (int status); +-NORETURN static void fail_exit (int); ++NORETURN static void fail_exit (int, bool); + static int add_group (const char *, const char *, gid_t *, gid_t); + static int get_user_id (const char *, uid_t *); + static int add_user (const char *, uid_t, gid_t); +@@ -113,11 +117,11 @@ static int update_passwd (struct passwd + #endif /* !USE_PAM */ + #endif /* !ACCT_TOOLS_SETUID */ + static int add_passwd (struct passwd *, const char *); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (void); + static void check_perms (void); +-static void open_files (void); +-static void close_files (void); ++static void open_files (bool process_selinux); ++static void close_files (struct option_flags *flags); + + extern int allow_bad_names; + +@@ -170,24 +174,24 @@ static void usage (int status) + /* + * fail_exit - undo as much as possible + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } + } + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ + } + } + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -195,7 +199,7 @@ static void fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -204,14 +208,14 @@ static void fail_exit (int code) + #endif + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -637,7 +641,7 @@ static int add_passwd (struct passwd *pw + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + #ifndef ACCT_TOOLS_SETUID +@@ -696,6 +700,7 @@ static void process_flags (int argc, cha + rflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + #ifndef ACCT_TOOLS_SETUID + #ifndef USE_PAM +@@ -755,7 +760,7 @@ static void process_flags (int argc, cha + + SNPRINTF(buf, "%s: %s", Prog, argv[1]); + perror (buf); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, !flags->chroot); + } + } + +@@ -859,7 +864,7 @@ static void check_perms (void) + /* + * open_files - lock and open the password, group and shadow databases + */ +-static void open_files (void) ++static void open_files (bool process_selinux) + { + /* + * Lock the password files and open them for update. This will bring +@@ -871,7 +876,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + pw_locked = true; + if (is_shadow) { +@@ -879,7 +884,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + spw_locked = true; + } +@@ -887,7 +892,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + gr_locked = true; + #ifdef SHADOWGRP +@@ -896,7 +901,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + sgr_locked = true; + } +@@ -907,7 +912,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_uid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + sub_uid_locked = true; + } +@@ -916,7 +921,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_gid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + sub_gid_locked = true; + } +@@ -924,20 +929,20 @@ static void open_files (void) + + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (is_shadow && (spw_open (O_CREAT | O_RDWR) == 0)) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + #ifdef SHADOWGRP + if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + #endif + #ifdef ENABLE_SUBIDS +@@ -946,7 +951,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_uid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + if (is_sub_gid) { +@@ -954,7 +959,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_gid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ +@@ -963,14 +968,18 @@ static void open_files (void) + /* + * close_files - close and unlock the password, group and shadow databases + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (pw_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; ++ ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -978,14 +987,14 @@ static void close_files (void) + pw_locked = false; + + if (is_shadow) { +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -995,29 +1004,29 @@ static void close_files (void) + spw_locked = false; + } + +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + #ifdef ENABLE_SUBIDS +- if (is_sub_uid && (sub_uid_close (true) == 0)) { ++ if (is_sub_uid && (sub_uid_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } +- if (is_sub_gid && (sub_gid_close (true) == 0)) { ++ if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + #endif /* ENABLE_SUBIDS */ + +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +@@ -1028,14 +1037,14 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +@@ -1047,7 +1056,7 @@ static void close_files (void) + #endif + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -1055,7 +1064,7 @@ static void close_files (void) + sub_uid_locked = false; + } + if (is_sub_gid) { +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -1100,6 +1109,8 @@ int main (int argc, char **argv) + size_t nusers = 0; + #endif /* USE_PAM */ + #endif /* ACCT_TOOLS_SETUID */ ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -1113,7 +1124,8 @@ int main (int argc, char **argv) + + OPENLOG ("newusers"); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + check_perms (); + +@@ -1127,7 +1139,7 @@ int main (int argc, char **argv) + is_sub_gid = sub_gid_file_present () && !rflg; + #endif /* ENABLE_SUBIDS */ + +- open_files (); ++ open_files (process_selinux); + + /* + * Read each line. The line has the same format as a password file +@@ -1143,13 +1155,13 @@ int main (int argc, char **argv) + if (stpsep(buf, "\n") == NULL && feof(stdin) == 0) { + fprintf (stderr, _("%s: line %jd: line too long\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + if (STRSEP2ARR(buf, ":", fields) == -1) { + fprintf (stderr, _("%s: line %jd: invalid line\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + /* +@@ -1161,14 +1173,14 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot update the entry of user %s (not in the passwd database)\n"), + Prog, fields[0]); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + if (NULL == pw && get_user_id(fields[2], &uid) != 0) { + fprintf (stderr, + _("%s: line %jd: can't create user\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + /* +@@ -1188,7 +1200,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: can't create group\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + /* +@@ -1203,7 +1215,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: can't create user\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + /* +@@ -1215,7 +1227,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: user '%s' does not exist in %s\n"), + Prog, line, fields[0], pw_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + newpw = *pw; + +@@ -1230,7 +1242,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: %s\n"), + Prog, line, strerror(errno)); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + lines[nusers-1] = line; + usernames[nusers-1] = xstrdup(fields[0]); +@@ -1241,7 +1253,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: can't update password\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (!streq(fields[4], "")) { + newpw.pw_gecos = fields[4]; +@@ -1264,7 +1276,7 @@ int main (int argc, char **argv) + fprintf(stderr, + _("%s: line %jd: homedir must be an absolute path\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (mkdir (newpw.pw_dir, mode) != 0) { + fprintf (stderr, +@@ -1272,7 +1284,7 @@ int main (int argc, char **argv) + Prog, line, newpw.pw_dir, + strerror (errno)); + if (errno != EEXIST) { +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + if (chown(newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0) +@@ -1281,7 +1293,7 @@ int main (int argc, char **argv) + _("%s: line %jd: chown %s failed: %s\n"), + Prog, line, newpw.pw_dir, + strerror (errno)); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + +@@ -1292,7 +1304,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: line %jd: can't update entry\n"), + Prog, line); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + + #ifdef ENABLE_SUBIDS +@@ -1307,14 +1319,14 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: can't find subordinate user range\n"), + Prog); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) + { + fprintf (stderr, + _("%s: failed to prepare new %s entry\n"), + Prog, sub_uid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + +@@ -1328,13 +1340,13 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: can't find subordinate group range\n"), + Prog); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { + fprintf (stderr, + _("%s: failed to prepare new %s entry\n"), + Prog, sub_uid_dbname ()); +- fail_exit (EXIT_FAILURE); ++ fail_exit (EXIT_FAILURE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ +@@ -1347,7 +1359,7 @@ int main (int argc, char **argv) + * changes to be written out all at once, and then unlocked + * afterwards. + */ +- close_files (); ++ close_files (&flags); + + nscd_flush_cache ("passwd"); + nscd_flush_cache ("group"); +diff -up shadow-4.18.0/src/useradd.c.test-chroot2 shadow-4.18.0/src/useradd.c +--- shadow-4.18.0/src/useradd.c.test-chroot2 2025-07-08 11:22:16.257383838 +0200 ++++ shadow-4.18.0/src/useradd.c 2025-07-08 11:22:16.261386737 +0200 +@@ -92,6 +92,15 @@ + #ifndef LASTLOG_FILE + #define LASTLOG_FILE "/var/log/lastlog" + #endif ++ ++/* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ + /* + * Global variables + */ +@@ -219,40 +228,41 @@ static bool home_added = false; + #define DLOG_INIT "LOG_INIT" + + /* local function prototypes */ +-NORETURN static void fail_exit (int); +-static void get_defaults (void); ++NORETURN static void fail_exit (int, bool); ++static void get_defaults (struct option_flags *); + static void show_defaults (void); + static int set_defaults (void); +-static int get_groups (char *); +-static struct group * get_local_group (char * grp_name); ++static int get_groups (char *, struct option_flags *); ++static struct group * get_local_group (char * grp_name, bool process_selinux); + NORETURN static void usage (int status); + static void new_pwent (struct passwd *); + + static void new_spent (struct spwd *); +-static void grp_update (void); ++static void grp_update (bool); + +-static void process_flags (int argc, char **argv); +-static void close_files (void); +-static void close_group_files (void); +-static void unlock_group_files (void); +-static void open_files (void); +-static void open_group_files (void); +-static void open_shadow (void); ++static void process_flags (int argc, char **argv, struct option_flags *flags); ++static void close_files (struct option_flags *flags); ++static void close_group_files (bool process_selinux); ++static void unlock_group_files (bool process_selinux); ++static void open_files (bool process_selinux); ++static void open_group_files (bool process_selinux); ++static void open_shadow (bool process_selinux); + static void faillog_reset (uid_t); + #ifdef ENABLE_LASTLOG + static void lastlog_reset (uid_t); + #endif /* ENABLE_LASTLOG */ + static void tallylog_reset (const char *); +-static void usr_update (unsigned long subuid_count, unsigned long subgid_count); +-static void create_home (void); +-static void create_mail (void); ++static void usr_update (unsigned long subuid_count, unsigned long subgid_count, ++ struct option_flags *flags); ++static void create_home (struct option_flags *flags); ++static void create_mail (struct option_flags *flags); + static void check_uid_range(int rflg, uid_t user_id); + + + /* + * fail_exit - undo as much as possible + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + #ifdef WITH_AUDIT + int type; +@@ -265,35 +275,35 @@ static void fail_exit (int code) + SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home)); + } + +- if (spw_locked && spw_unlock(true) == 0) { ++ if (spw_locked && spw_unlock(process_selinux) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); + /* continue */ + } +- if (pw_locked && pw_unlock(true) == 0) { ++ if (pw_locked && pw_unlock(process_selinux) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); + /* continue */ + } +- if (gr_locked && gr_unlock(true) == 0) { ++ if (gr_locked && gr_unlock(process_selinux) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); + /* continue */ + } + #ifdef SHADOWGRP +- if (sgr_locked && sgr_unlock(true) == 0) { ++ if (sgr_locked && sgr_unlock(process_selinux) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); + /* continue */ + } + #endif + #ifdef ENABLE_SUBIDS +- if (sub_uid_locked && sub_uid_unlock(true) == 0) { ++ if (sub_uid_locked && sub_uid_unlock(process_selinux) == 0) { + fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); + SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); + /* continue */ + } +- if (sub_gid_locked && sub_gid_unlock(true) == 0) { ++ if (sub_gid_locked && sub_gid_unlock(process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); + /* continue */ +@@ -322,7 +332,7 @@ static void fail_exit (int code) + * file does not exist. + */ + static void +-get_defaults(void) ++get_defaults(struct option_flags *flags) + { + FILE *fp; + char *default_file = USER_DEFAULTS_FILE; +@@ -377,7 +387,7 @@ get_defaults(void) + ccp = cp; + + if (streq(buf, DGROUPS)) { +- if (get_groups (cp) != 0) { ++ if (get_groups (cp, flags) != 0) { + fprintf (stderr, + _("%s: the '%s=' configuration in %s has an invalid group, ignoring the bad group\n"), + Prog, DGROUPS, default_file); +@@ -736,11 +746,14 @@ err_free_new: + * converts it to a NULL-terminated array. Any unknown group + * names are reported as errors. + */ +-static int get_groups (char *list) ++static int get_groups (char *list, struct option_flags *flags) + { + struct group *grp; + bool errors = false; + int ngroups = 0; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + /* + * Free previous group list before creating a new one. +@@ -758,7 +771,7 @@ static int get_groups (char *list) + /* + * Open the group files + */ +- open_group_files (); ++ open_group_files (process_selinux); + + /* + * So long as there is some data to be converted, strip off +@@ -777,7 +790,7 @@ static int get_groups (char *list) + * Names starting with digits are treated as numerical + * GID values, otherwise the string is looked up as is. + */ +- grp = get_local_group(g); ++ grp = get_local_group(g, process_selinux); + + /* + * There must be a match, either by GID value or by +@@ -815,8 +828,8 @@ static int get_groups (char *list) + gr_free (grp); + } + +- close_group_files (); +- unlock_group_files (); ++ close_group_files (process_selinux); ++ unlock_group_files (process_selinux); + + user_groups[ngroups] = NULL; + +@@ -837,7 +850,7 @@ static int get_groups (char *list) + * If the name exists the group information is returned, otherwise NULL is + * returned. + */ +-static struct group * get_local_group(char * grp_name) ++static struct group * get_local_group(char * grp_name, bool process_selinux) + { + gid_t gid; + struct group *result_grp = NULL; +@@ -854,7 +867,7 @@ static struct group * get_local_group(ch + fprintf (stderr, + _("%s: Out of memory. Cannot find group '%s'.\n"), + Prog, grp_name); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + } + +@@ -986,7 +999,7 @@ static void new_spent (struct spwd *spen + * close_files() should be called afterwards to commit the changes + * and unlocking the group files. + */ +-static void grp_update (void) ++static void grp_update (bool process_selinux) + { + const struct group *grp; + struct group *ngrp; +@@ -1022,7 +1035,7 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +- fail_exit (E_GRP_UPDATE); /* XXX */ ++ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */ + } + + /* +@@ -1035,7 +1048,7 @@ static void grp_update (void) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), ngrp->gr_name); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef WITH_AUDIT + audit_logger_with_group (AUDIT_USER_MGMT, +@@ -1085,7 +1098,7 @@ static void grp_update (void) + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); +- fail_exit (E_GRP_UPDATE); /* XXX */ ++ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */ + } + + /* +@@ -1099,7 +1112,7 @@ static void grp_update (void) + Prog, sgr_dbname (), nsgrp->sg_namp); + SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); + +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef WITH_AUDIT + audit_logger_with_group (AUDIT_USER_MGMT, +@@ -1121,7 +1134,7 @@ static void grp_update (void) + * the values that the user will be created with accordingly. The + * values are checked for sanity. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + const struct group *grp; + bool anyflag = false; +@@ -1296,7 +1309,7 @@ static void process_flags (int argc, cha + gflg = true; + break; + case 'G': +- if (get_groups (optarg) != 0) { ++ if (get_groups (optarg, flags) != 0) { + exit (E_NOTFOUND); + } + if (NULL != user_groups[0]) { +@@ -1356,8 +1369,10 @@ static void process_flags (int argc, cha + rflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 's': + if ( ( !VALID (optarg) ) +@@ -1562,38 +1577,42 @@ static void process_flags (int argc, cha + * close_files() closes all of the files that were opened for this + * new user. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (pw_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } +- if (is_shadow_pwd && (spw_close (true) == 0)) { ++ if (is_shadow_pwd && (spw_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + +- close_group_files (); ++ close_group_files (process_selinux); + + #ifdef ENABLE_SUBIDS +- if (is_sub_uid && (sub_uid_close (true) == 0)) { ++ if (is_sub_uid && (sub_uid_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } +- if (is_sub_gid && (sub_gid_close (true) == 0)) { ++ if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + #endif /* ENABLE_SUBIDS */ + if (is_shadow_pwd) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + #ifdef WITH_AUDIT +@@ -1606,7 +1625,7 @@ static void close_files (void) + } + spw_locked = false; + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + #ifdef WITH_AUDIT +@@ -1619,11 +1638,11 @@ static void close_files (void) + } + pw_locked = false; + +- unlock_group_files (); ++ unlock_group_files (process_selinux); + + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + #ifdef WITH_AUDIT +@@ -1637,7 +1656,7 @@ static void close_files (void) + sub_uid_locked = false; + } + if (is_sub_gid) { +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + #ifdef WITH_AUDIT +@@ -1659,25 +1678,25 @@ static void close_files (void) + * close_group_files() closes all of the files that were opened related + * with groups. This causes any modified entries to be written out. + */ +-static void close_group_files (void) ++static void close_group_files (bool process_selinux) + { + if (!do_grp_update) + return; + +- if (gr_close(true) == 0) { ++ if (gr_close(process_selinux) == 0) { + fprintf(stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname()); + SYSLOG((LOG_ERR, "failure while writing changes to %s", gr_dbname())); +- fail_exit(E_GRP_UPDATE); ++ fail_exit(E_GRP_UPDATE, process_selinux); + } + #ifdef SHADOWGRP +- if (is_shadow_grp && sgr_close(true) == 0) { ++ if (is_shadow_grp && sgr_close(process_selinux) == 0) { + fprintf(stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname()); + SYSLOG((LOG_ERR, "failure while writing changes to %s", sgr_dbname())); +- fail_exit(E_GRP_UPDATE); ++ fail_exit(E_GRP_UPDATE, process_selinux); + } + #endif /* SHADOWGRP */ + } +@@ -1688,9 +1707,9 @@ static void close_group_files (void) + * unlock_group_files() unlocks all of the files that were locked related + * with groups. This causes any modified entries to be written out. + */ +-static void unlock_group_files (void) ++static void unlock_group_files (bool process_selinux) + { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + #ifdef WITH_AUDIT +@@ -1704,7 +1723,7 @@ static void unlock_group_files (void) + gr_locked = false; + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + #ifdef WITH_AUDIT +@@ -1725,7 +1744,7 @@ static void unlock_group_files (void) + * + * open_files() opens the two password files. + */ +-static void open_files (void) ++static void open_files (bool process_selinux) + { + if (pw_lock () == 0) { + fprintf (stderr, +@@ -1736,12 +1755,12 @@ static void open_files (void) + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + + /* shadow file will be opened by open_shadow(); */ + +- open_group_files (); ++ open_group_files (process_selinux); + + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +@@ -1749,14 +1768,14 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + sub_uid_locked = true; + if (sub_uid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + } + if (is_sub_gid) { +@@ -1764,31 +1783,31 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + sub_gid_locked = true; + if (sub_gid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ + } + +-static void open_group_files (void) ++static void open_group_files (bool process_selinux) + { + if (gr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + #ifdef SHADOWGRP +@@ -1797,20 +1816,20 @@ static void open_group_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + sgr_locked = true; + if (sgr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + } + #endif /* SHADOWGRP */ + } + +-static void open_shadow (void) ++static void open_shadow (bool process_selinux) + { + if (!is_shadow_pwd) { + return; +@@ -1819,14 +1838,14 @@ static void open_shadow (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + spw_locked = true; + if (spw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + } + +@@ -1880,7 +1899,7 @@ static void new_sgent (struct sgrp *sgen + * grp_add() writes the new records to the group files. + */ + +-static void grp_add (void) ++static void grp_add (bool process_selinux) + { + struct group grp; + +@@ -1909,7 +1928,7 @@ static void grp_add (void) + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef SHADOWGRP + /* +@@ -1925,7 +1944,7 @@ static void grp_add (void) + grp.gr_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #endif /* SHADOWGRP */ + SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); +@@ -2074,11 +2093,16 @@ static void tallylog_reset (const char * + * usr_update() creates the password file entries for this user + * and will update the group entries if required. + */ +-static void usr_update (unsigned long subuid_count, unsigned long subgid_count) ++static void ++usr_update (unsigned long subuid_count, unsigned long subgid_count, ++ struct option_flags *flags) + { + struct passwd pwent; + struct spwd spent; + char *tty; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + /* + * Fill in the password structure with any new fields, making +@@ -2119,7 +2143,7 @@ static void usr_update (unsigned long su + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + + /* +@@ -2129,7 +2153,7 @@ static void usr_update (unsigned long su + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), spent.sp_namp); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + #ifdef ENABLE_SUBIDS + if (is_sub_uid && !local_sub_uid_assigned(user_name) && +@@ -2137,14 +2161,14 @@ static void usr_update (unsigned long su + fprintf (stderr, + _("%s: failed to prepare the new %s entry\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + if (is_sub_gid && !local_sub_gid_assigned(user_name) && + (sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + #endif /* ENABLE_SUBIDS */ + +@@ -2163,7 +2187,7 @@ static void usr_update (unsigned long su + * Do any group file updates for this user. + */ + if (do_grp_update) { +- grp_update (); ++ grp_update (process_selinux); + } + } + +@@ -2174,11 +2198,14 @@ static void usr_update (unsigned long su + * already exist. It will be created mode 755 owned by the user + * with the user's default group. + */ +-static void create_home (void) ++static void create_home (struct option_flags *flags) + { + char path[strlen(prefix_user_home) + 2]; + char *bhome, *cp; + mode_t mode; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + if (access (prefix_user_home, F_OK) == 0) + return; +@@ -2189,15 +2216,17 @@ static void create_home (void) + fprintf(stderr, + _("%s: error while duplicating string %s\n"), + Prog, user_home); +- fail_exit(E_HOMEDIR); ++ fail_exit(E_HOMEDIR, process_selinux); + } + + #ifdef WITH_SELINUX +- if (set_selinux_file_context(prefix_user_home, S_IFDIR) != 0) { +- fprintf(stderr, +- _("%s: cannot set SELinux context for home directory %s\n"), +- Prog, user_home); +- fail_exit(E_HOMEDIR); ++ if (process_selinux) { ++ if (set_selinux_file_context(prefix_user_home, S_IFDIR) != 0) { ++ fprintf(stderr, ++ _("%s: cannot set SELinux context for home directory %s\n"), ++ Prog, user_home); ++ fail_exit(E_HOMEDIR, process_selinux); ++ } + } + #endif + +@@ -2227,14 +2256,14 @@ static void create_home (void) + fprintf(stderr, + _("%s: error while duplicating string in BTRFS check %s\n"), + Prog, path); +- fail_exit(E_HOMEDIR); ++ fail_exit(E_HOMEDIR, process_selinux); + } + stpcpy(&btrfs_check[strlen(path) - strlen(cp) - 1], ""); + if (is_btrfs(btrfs_check) <= 0) { + fprintf(stderr, + _("%s: home directory \"%s\" must be mounted on BTRFS\n"), + Prog, path); +- fail_exit(E_HOMEDIR); ++ fail_exit(E_HOMEDIR, process_selinux); + } + free(btrfs_check); + // make subvolume to mount for user instead of directory +@@ -2242,7 +2271,7 @@ static void create_home (void) + fprintf(stderr, + _("%s: failed to create BTRFS subvolume: %s\n"), + Prog, path); +- fail_exit(E_HOMEDIR); ++ fail_exit(E_HOMEDIR, process_selinux); + } + } + else +@@ -2250,7 +2279,7 @@ static void create_home (void) + if (mkdir(path, 0) != 0) { + fprintf(stderr, _("%s: cannot create directory %s\n"), + Prog, path); +- fail_exit(E_HOMEDIR); ++ fail_exit(E_HOMEDIR, process_selinux); + } + if (chown(path, 0, 0) < 0) { + fprintf(stderr, +@@ -2278,12 +2307,14 @@ static void create_home (void) + user_name, user_id, SHADOW_AUDIT_SUCCESS); + #endif + #ifdef WITH_SELINUX +- /* Reset SELinux to create files with default contexts */ +- if (reset_selinux_file_context() != 0) { +- fprintf(stderr, +- _("%s: cannot reset SELinux file creation context\n"), +- Prog); +- fail_exit(E_HOMEDIR); ++ if (process_selinux) { ++ /* Reset SELinux to create files with default contexts */ ++ if (reset_selinux_file_context() != 0) { ++ fprintf(stderr, ++ _("%s: cannot reset SELinux file creation context\n"), ++ Prog); ++ fail_exit(E_HOMEDIR, process_selinux); ++ } + } + #endif + } +@@ -2295,7 +2326,7 @@ static void create_home (void) + * exist. It will be created mode 660 owned by the user and group + * 'mail' + */ +-static void create_mail (void) ++static void create_mail (struct option_flags *flags) + { + int fd; + char *file; +@@ -2303,6 +2334,9 @@ static void create_mail (void) + mode_t mode; + const char *spool; + struct group *gr; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + if (!strcaseeq(create_mail_spool, "yes")) + return; +@@ -2322,11 +2356,13 @@ static void create_mail (void) + file = xaprintf("%s/%s", spool, user_name); + + #ifdef WITH_SELINUX +- if (set_selinux_file_context(file, S_IFREG) != 0) { +- fprintf(stderr, +- _("%s: cannot set SELinux context for mailbox file %s\n"), +- Prog, file); +- fail_exit(E_MAILBOXFILE); ++ if (process_selinux) { ++ if (set_selinux_file_context(file, S_IFREG) != 0) { ++ fprintf(stderr, ++ _("%s: cannot set SELinux context for mailbox file %s\n"), ++ Prog, file); ++ fail_exit(E_MAILBOXFILE, process_selinux); ++ } + } + #endif + +@@ -2362,12 +2398,14 @@ static void create_mail (void) + perror (_("Closing mailbox file")); + } + #ifdef WITH_SELINUX +- /* Reset SELinux to create files with default contexts */ +- if (reset_selinux_file_context() != 0) { +- fprintf(stderr, +- _("%s: cannot reset SELinux file creation context\n"), +- Prog); +- fail_exit(E_MAILBOXFILE); ++ if (process_selinux) { ++ /* Reset SELinux to create files with default contexts */ ++ if (reset_selinux_file_context() != 0) { ++ fprintf(stderr, ++ _("%s: cannot reset SELinux file creation context\n"), ++ Prog); ++ fail_exit(E_MAILBOXFILE, process_selinux); ++ } + } + #endif + } +@@ -2409,6 +2447,8 @@ int main (int argc, char **argv) + #endif + unsigned long subuid_count = 0; + unsigned long subgid_count = 0; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -2439,9 +2479,10 @@ int main (int argc, char **argv) + is_shadow_grp = sgr_file_present (); + #endif + +- get_defaults (); ++ get_defaults (&flags); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot && !flags.prefix; + + #ifdef ENABLE_SUBIDS + uid_min = getdef_ulong ("UID_MIN", 1000UL); +@@ -2470,7 +2511,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + retval = pam_start (Prog, pampw?pampw->pw_name:"root", &conv, &pamh); +@@ -2491,7 +2532,7 @@ int main (int argc, char **argv) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -2515,7 +2556,7 @@ int main (int argc, char **argv) + */ + if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ + fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); +- fail_exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE, process_selinux); + } + + /* +@@ -2530,7 +2571,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), + Prog, user_name); +- fail_exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE, process_selinux); + } + } + +@@ -2543,7 +2584,7 @@ int main (int argc, char **argv) + * - flush nscd caches for passwd and group services, + * - then close and update the files. + */ +- open_files (); ++ open_files (process_selinux); + + if (!oflg) { + /* first, seek for a valid uid to use for this user. +@@ -2552,14 +2593,14 @@ int main (int argc, char **argv) + if (!uflg) { + if (find_new_uid (rflg, &user_id, NULL) < 0) { + fprintf (stderr, _("%s: can't create user\n"), Prog); +- fail_exit (E_UID_IN_USE); ++ fail_exit (E_UID_IN_USE, process_selinux); + } + } else { + if (prefix_getpwuid (user_id) != NULL) { + fprintf (stderr, + _("%s: UID %lu is not unique\n"), + Prog, (unsigned long) user_id); +- fail_exit (E_UID_IN_USE); ++ fail_exit (E_UID_IN_USE, process_selinux); + } + } + } +@@ -2572,11 +2613,11 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Failed to create tcb directory for %s\n"), + Prog, user_name); +- fail_exit (E_UID_IN_USE); ++ fail_exit (E_UID_IN_USE, process_selinux); + } + } + #endif +- open_shadow (); ++ open_shadow (process_selinux); + + /* do we have to add a group for that user? This is why we need to + * open the group files in the open_files() function --gafton */ +@@ -2585,9 +2626,9 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: can't create group\n"), + Prog); +- fail_exit (4); ++ fail_exit (4, process_selinux); + } +- grp_add (); ++ grp_add (process_selinux); + } + + #ifdef ENABLE_SUBIDS +@@ -2596,7 +2637,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: can't create subordinate user IDs\n"), + Prog); +- fail_exit(E_SUB_UID_UPDATE); ++ fail_exit(E_SUB_UID_UPDATE, process_selinux); + } + } + if (is_sub_gid && subgid_count != 0) { +@@ -2604,14 +2645,14 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: can't create subordinate group IDs\n"), + Prog); +- fail_exit(E_SUB_GID_UPDATE); ++ fail_exit(E_SUB_GID_UPDATE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ + +- usr_update (subuid_count, subgid_count); ++ usr_update (subuid_count, subgid_count, &flags); + +- close_files (); ++ close_files (&flags); + + nscd_flush_cache ("passwd"); + nscd_flush_cache ("group"); +@@ -2637,13 +2678,13 @@ int main (int argc, char **argv) + "add-selinux-user-mapping", + user_name, user_id, SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +- fail_exit (E_SE_UPDATE); ++ fail_exit (E_SE_UPDATE, process_selinux); + } + } + #endif /* WITH_SELINUX */ + + if (mflg) { +- create_home (); ++ create_home (&flags); + if (home_added) { + copy_tree (def_template, prefix_user_home, false, true, + (uid_t)-1, user_id, (gid_t)-1, user_gid); +@@ -2660,7 +2701,7 @@ int main (int argc, char **argv) + + /* Do not create mail directory for system accounts */ + if (!rflg) { +- create_mail (); ++ create_mail (&flags); + } + + if (run_parts ("/etc/shadow-maint/useradd-post.d", user_name, +diff -up shadow-4.18.0/src/userdel.c.test-chroot2 shadow-4.18.0/src/userdel.c +--- shadow-4.18.0/src/userdel.c.test-chroot2 2025-07-08 11:22:16.257469516 +0200 ++++ shadow-4.18.0/src/userdel.c 2025-07-08 11:22:16.263226317 +0200 +@@ -73,6 +73,14 @@ + #endif /* ENABLE_SUBIDS */ + + /* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ ++/* + * Global variables + */ + static const char Prog[] = "userdel"; +@@ -87,7 +95,6 @@ static bool rflg = false; + #ifdef WITH_SELINUX + static bool Zflg = false; + #endif +-static bool Rflg = false; + + static bool is_shadow_pwd; + +@@ -109,12 +116,12 @@ static const char* prefix = ""; + + /* local function prototypes */ + static void usage (int status); +-static void update_groups (void); +-static void remove_usergroup (void); +-static void close_files (void); +-static void fail_exit (int); +-static void open_files (void); +-static void update_user (void); ++static void update_groups (bool process_selinux); ++static void remove_usergroup (bool process_selinux); ++static void close_files (struct option_flags *flags); ++static void fail_exit (int, bool); ++static void open_files (bool process_selinux); ++static void update_user (bool process_selinux); + static void user_cancel (const char *); + + #ifdef EXTRA_CHECK_HOME_DIR +@@ -162,7 +169,7 @@ static void usage (int status) + * name is their user name) and delete them too (only if USERGROUPS_ENAB + * is enabled). + */ +-static void update_groups (void) ++static void update_groups (bool process_selinux) + { + const struct group *grp; + struct group *ngrp; +@@ -219,7 +226,7 @@ static void update_groups (void) + } + + if (getdef_bool ("USERGROUPS_ENAB")) { +- remove_usergroup (); ++ remove_usergroup (process_selinux); + } + + #ifdef SHADOWGRP +@@ -291,7 +298,7 @@ static void update_groups (void) + * + it has no other members + * + it is not the primary group of any other user + */ +-static void remove_usergroup (void) ++static void remove_usergroup (bool process_selinux) + { + const struct group *grp; + const struct passwd *pwd = NULL; +@@ -346,7 +353,7 @@ static void remove_usergroup (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + #ifdef WITH_AUDIT +@@ -365,7 +372,7 @@ static void remove_usergroup (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef WITH_AUDIT + audit_logger_with_group (AUDIT_GRP_MGMT, +@@ -388,14 +395,18 @@ static void remove_usergroup (void) + * close_files() closes all of the files that were opened for this + * new user. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (pw_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -403,13 +414,13 @@ static void close_files (void) + pw_locked = false; + + if (is_shadow_pwd) { +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -417,12 +428,12 @@ static void close_files (void) + spw_locked = false; + } + +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -431,14 +442,14 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -449,12 +460,12 @@ static void close_files (void) + + #ifdef ENABLE_SUBIDS + if (is_sub_uid) { +- if (sub_uid_close (true) == 0) { ++ if (sub_uid_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -463,12 +474,12 @@ static void close_files (void) + } + + if (is_sub_gid) { +- if (sub_gid_close (true) == 0) { ++ if (sub_gid_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -481,24 +492,24 @@ static void close_files (void) + /* + * fail_exit - exit with a failure code after unlocking the files + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ + } + } + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ + } + } + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -506,7 +517,7 @@ static void fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -515,14 +526,14 @@ static void fail_exit (int code) + #endif /* SHADOWGRP */ + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -545,45 +556,45 @@ static void fail_exit (int code) + * open_files() opens the two password files. + */ + +-static void open_files (void) ++static void open_files (bool process_selinux) + { + if (pw_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + if (is_shadow_pwd) { + if (spw_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + spw_locked = true; + if (spw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + } + if (gr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef SHADOWGRP + if (is_shadow_grp) { +@@ -591,13 +602,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + sgr_locked= true; + if (sgr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + } + #endif /* SHADOWGRP */ +@@ -607,13 +618,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + sub_uid_locked = true; + if (sub_uid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + } + if (is_sub_gid) { +@@ -621,13 +632,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + sub_gid_locked = true; + if (sub_gid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ +@@ -639,13 +650,13 @@ static void open_files (void) + * update_user() deletes the password file entries for this user + * and will update the group entries as required. + */ +-static void update_user (void) ++static void update_user (bool process_selinux) + { + if (pw_remove (user_name) == 0) { + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + if ( is_shadow_pwd + && (spw_locate (user_name) != NULL) +@@ -653,20 +664,20 @@ static void update_user (void) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + #ifdef ENABLE_SUBIDS + if (is_sub_uid && sub_uid_remove(user_name, 0, ULONG_MAX) == 0) { + fprintf (stderr, + _("%s: cannot remove entry %lu from %s\n"), + Prog, (unsigned long)user_id, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + if (is_sub_gid && sub_gid_remove(user_name, 0, ULONG_MAX) == 0) { + fprintf (stderr, + _("%s: cannot remove entry %lu from %s\n"), + Prog, (unsigned long)user_id, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + #endif /* ENABLE_SUBIDS */ + #ifdef WITH_AUDIT +@@ -905,6 +916,8 @@ int main (int argc, char **argv) + int retval; + #endif /* USE_PAM */ + #endif /* ACCT_TOOLS_SETUID */ ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -954,9 +967,10 @@ int main (int argc, char **argv) + rflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ +- Rflg = true; ++ flags.chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags.prefix = true; + break; + #ifdef WITH_SELINUX + case 'Z': +@@ -982,6 +996,7 @@ int main (int argc, char **argv) + } + } + } ++ process_selinux = !flags.chroot && !flags.prefix; + + if ((optind + 1) != argc) { + usage (E_USAGE); +@@ -1046,7 +1061,7 @@ int main (int argc, char **argv) + pw_open(O_RDONLY); + pwd = pw_locate (user_name); /* we care only about local users */ + if (NULL == pwd) { +- pw_close(true); ++ pw_close(process_selinux); + fprintf (stderr, _("%s: user '%s' does not exist\n"), + Prog, user_name); + #ifdef WITH_AUDIT +@@ -1065,7 +1080,7 @@ int main (int argc, char **argv) + } else { + user_home = xstrdup(pwd->pw_dir); + } +- pw_close(true); ++ pw_close(process_selinux); + } + #ifdef WITH_TCB + if (shadowtcb_set_user (user_name) == SHADOWTCB_FAILURE) { +@@ -1077,7 +1092,7 @@ int main (int argc, char **argv) + * Note: This is a best effort basis. The user may log in between, + * a cron job may be started on her behalf, etc. + */ +- if (streq(prefix, "") && !Rflg && user_busy(user_name, user_id) != 0) { ++ if (streq(prefix, "") && !flags.chroot && user_busy(user_name, user_id) != 0) { + if (!fflg) { + #ifdef WITH_AUDIT + audit_logger (AUDIT_DEL_USER, Prog, +@@ -1093,9 +1108,9 @@ int main (int argc, char **argv) + * Do the hard stuff - open the files, create the user entries, + * create the home directory, then close and update the files. + */ +- open_files (); +- update_user (); +- update_groups (); ++ open_files (process_selinux); ++ update_user (process_selinux); ++ update_groups (process_selinux); + + if (rflg) { + if (remove_mailbox ()) { +@@ -1203,7 +1218,7 @@ int main (int argc, char **argv) + "delete-selinux-user-mapping", + user_name, user_id, SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +- fail_exit (E_SE_UPDATE); ++ fail_exit (E_SE_UPDATE, process_selinux); + } + } + #endif /* WITH_SELINUX */ +@@ -1214,7 +1229,7 @@ int main (int argc, char **argv) + */ + if (streq(prefix, "")) + user_cancel (user_name); +- close_files (); ++ close_files (&flags); + + if (run_parts ("/etc/shadow-maint/userdel-post.d", user_name, "userdel")) { + exit(1); +diff -up shadow-4.18.0/src/usermod.c.test-chroot2 shadow-4.18.0/src/usermod.c +--- shadow-4.18.0/src/usermod.c.test-chroot2 2025-07-08 11:22:16.257549046 +0200 ++++ shadow-4.18.0/src/usermod.c 2025-07-08 11:22:16.262408337 +0200 +@@ -97,6 +97,14 @@ + #define VALID(s) (!strpbrk(s, ":\n")) + + /* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ ++/* + * Global variables + */ + static const char Prog[] = "usermod"; +@@ -182,23 +190,23 @@ static bool sub_gid_locked = false; + /* local function prototypes */ + static int get_groups (char *); + NORETURN static void usage (int status); +-static void new_pwent (struct passwd *); +-static void new_spent (struct spwd *); +-NORETURN static void fail_exit (int); +-static void update_group_file(void); +-static void update_group(const struct group *grp); ++static void new_pwent (struct passwd *, bool); ++static void new_spent (struct spwd *, bool); ++NORETURN static void fail_exit (int, bool); ++static void update_group_file(bool); ++static void update_group(const struct group *grp, bool process_selinux); + + #ifdef SHADOWGRP +-static void update_gshadow_file(void); +-static void update_gshadow(const struct sgrp *sgrp); ++static void update_gshadow_file(bool process_selinux); ++static void update_gshadow(const struct sgrp *sgrp, bool process_selinux); + #endif +-static void grp_update (void); ++static void grp_update (bool process_selinux); + +-static void process_flags (int, char **); +-static void close_files (void); +-static void open_files (void); +-static void usr_update (void); +-static void move_home (void); ++static void process_flags (int, char **, struct option_flags *); ++static void close_files (struct option_flags *); ++static void open_files (bool process_selinux); ++static void usr_update (struct option_flags *flags); ++static void move_home (bool process_selinux); + #ifdef ENABLE_LASTLOG + static void update_lastlog (void); + #endif /* ENABLE_LASTLOG */ +@@ -466,7 +474,7 @@ static char *new_pw_passwd (char *pw_pas + * new_pwent() takes all of the values that have been entered and fills + * in a (struct passwd) with them. + */ +-static void new_pwent (struct passwd *pwent) ++static void new_pwent (struct passwd *pwent, bool process_selinux) + { + if (lflg) { + if (pw_locate (user_newname) != NULL) { +@@ -477,7 +485,7 @@ static void new_pwent (struct passwd *pw + fprintf (stderr, + _("%s: user '%s' already exists in %s\n"), + Prog, user_newname, pw_dbname ()); +- fail_exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE, process_selinux); + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_MGMT, Prog, +@@ -563,14 +571,14 @@ static void new_pwent (struct passwd *pw + * new_spent() takes all of the values that have been entered and fills + * in a (struct spwd) with them. + */ +-static void new_spent (struct spwd *spent) ++static void new_spent (struct spwd *spent, bool process_selinux) + { + if (lflg) { + if (spw_locate (user_newname) != NULL) { + fprintf (stderr, + _("%s: user '%s' already exists in %s\n"), + Prog, user_newname, spw_dbname ()); +- fail_exit (E_NAME_IN_USE); ++ fail_exit (E_NAME_IN_USE, process_selinux); + } + spent->sp_namp = xstrdup (user_newname); + } +@@ -629,10 +637,10 @@ static void new_spent (struct spwd *spen + */ + NORETURN + static void +-fail_exit (int code) ++fail_exit (int code, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -640,7 +648,7 @@ fail_exit (int code) + } + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -648,14 +656,14 @@ fail_exit (int code) + } + #endif + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } + } + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -663,14 +671,14 @@ fail_exit (int code) + } + #ifdef ENABLE_SUBIDS + if (sub_uid_locked) { +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ + } + } + if (sub_gid_locked) { +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -688,7 +696,7 @@ fail_exit (int code) + + + static void +-update_group_file(void) ++update_group_file(bool process_selinux) + { + const struct group *grp; + +@@ -697,12 +705,12 @@ update_group_file(void) + * the user is a member of. + */ + while ((grp = gr_next()) != NULL) +- update_group(grp); ++ update_group(grp, process_selinux); + } + + + static void +-update_group(const struct group *grp) ++update_group(const struct group *grp, bool process_selinux) + { + bool changed; + bool is_member; +@@ -735,7 +743,7 @@ update_group(const struct group *grp) + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + if (was_member) { +@@ -804,7 +812,7 @@ update_group(const struct group *grp) + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), ngrp->gr_name); + SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + free_ngrp: +@@ -814,7 +822,7 @@ free_ngrp: + + #ifdef SHADOWGRP + static void +-update_gshadow_file(void) ++update_gshadow_file(bool process_selinux) + { + const struct sgrp *sgrp; + +@@ -823,14 +831,14 @@ update_gshadow_file(void) + * that the user is a member of. + */ + while ((sgrp = sgr_next()) != NULL) +- update_gshadow(sgrp); ++ update_gshadow(sgrp, process_selinux); + } + #endif /* SHADOWGRP */ + + + #ifdef SHADOWGRP + static void +-update_gshadow(const struct sgrp *sgrp) ++update_gshadow(const struct sgrp *sgrp, bool process_selinux) + { + bool changed; + bool is_member; +@@ -873,7 +881,7 @@ update_gshadow(const struct sgrp *sgrp) + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + if (was_admin && lflg) { +@@ -960,7 +968,7 @@ update_gshadow(const struct sgrp *sgrp) + Prog, sgr_dbname (), nsgrp->sg_namp); + SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", + sgr_dbname (), nsgrp->sg_namp)); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + + free_nsgrp: +@@ -975,12 +983,12 @@ free_nsgrp: + * grp_update() takes the secondary group set given in user_groups and + * adds the user to each group given by that set. + */ +-static void grp_update (void) ++static void grp_update (bool process_selinux) + { +- update_group_file(); ++ update_group_file(process_selinux); + #ifdef SHADOWGRP + if (is_shadow_grp) { +- update_gshadow_file(); ++ update_gshadow_file(process_selinux); + } + #endif + } +@@ -993,7 +1001,7 @@ static void grp_update (void) + * are checked for sanity. + */ + static void +-process_flags(int argc, char **argv) ++process_flags(int argc, char **argv, struct option_flags *flags) + { + struct stat st; + bool anyflag = false; +@@ -1158,8 +1166,10 @@ process_flags(int argc, char **argv) + rflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 's': + if ( ( !VALID (optarg) ) +@@ -1467,51 +1477,55 @@ process_flags(int argc, char **argv) + * close_files() closes all of the files that were opened for this new + * user. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (pw_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } +- if (is_shadow_pwd && (spw_close (true) == 0)) { ++ if (is_shadow_pwd && (spw_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, + "failure while writing changes to %s", + spw_dbname ())); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + + if (Gflg || lflg) { +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, + "failure while writing changes to %s", + gr_dbname ())); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, + "failure while writing changes to %s", + sgr_dbname ())); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + } + #endif + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +@@ -1522,7 +1536,7 @@ static void close_files (void) + } + } + #endif +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +@@ -1534,7 +1548,7 @@ static void close_files (void) + } + + if (is_shadow_pwd) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -1544,7 +1558,7 @@ static void close_files (void) + /* continue */ + } + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +@@ -1561,12 +1575,12 @@ static void close_files (void) + + #ifdef ENABLE_SUBIDS + if (vflg || Vflg) { +- if (sub_uid_close (true) == 0) { ++ if (sub_uid_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } +- if (sub_uid_unlock (true) == 0) { ++ if (sub_uid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); + /* continue */ +@@ -1574,12 +1588,12 @@ static void close_files (void) + sub_uid_locked = false; + } + if (wflg || Wflg) { +- if (sub_gid_close (true) == 0) { ++ if (sub_gid_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } +- if (sub_gid_unlock (true) == 0) { ++ if (sub_gid_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); + /* continue */ +@@ -1604,33 +1618,33 @@ static void close_files (void) + * + * open_files() opens the two password files. + */ +-static void open_files (void) ++static void open_files (bool process_selinux) + { + if (pw_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + if (is_shadow_pwd && (spw_lock () == 0)) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + spw_locked = true; + if (is_shadow_pwd && (spw_open (O_CREAT | O_RDWR) == 0)) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + + if (Gflg || lflg) { +@@ -1642,28 +1656,28 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, gr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #ifdef SHADOWGRP + if (is_shadow_grp && (sgr_lock () == 0)) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + sgr_locked = true; + if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +- fail_exit (E_GRP_UPDATE); ++ fail_exit (E_GRP_UPDATE, process_selinux); + } + #endif + } +@@ -1673,14 +1687,14 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + sub_uid_locked = true; + if (sub_uid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_uid_dbname ()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + } + if (wflg || Wflg) { +@@ -1688,14 +1702,14 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + sub_gid_locked = true; + if (sub_gid_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, sub_gid_dbname ()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + } + #endif /* ENABLE_SUBIDS */ +@@ -1707,13 +1721,15 @@ static void open_files (void) + * usr_update() creates the password file entries for this user and + * will update the group entries if required. + */ +-static void usr_update (void) ++static void usr_update (struct option_flags *flags) + { + struct passwd pwent; + const struct passwd *pwd; +- + struct spwd spent; + const struct spwd *spwd = NULL; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + /* + * Locate the entry in /etc/passwd, which MUST exist. +@@ -1723,10 +1739,10 @@ static void usr_update (void) + fprintf (stderr, + _("%s: user '%s' does not exist in %s\n"), + Prog, user_name, pw_dbname ()); +- fail_exit (E_NOTFOUND); ++ fail_exit (E_NOTFOUND, process_selinux); + } + pwent = *pwd; +- new_pwent (&pwent); ++ new_pwent (&pwent, process_selinux); + + + /* If the shadow file does not exist, it won't be created */ +@@ -1735,7 +1751,7 @@ static void usr_update (void) + if (NULL != spwd) { + /* Update the shadow entry if it exists */ + spent = *spwd; +- new_spent (&spent); ++ new_spent (&spent, process_selinux); + } else if ( ( pflg + && streq(pwent.pw_passwd, SHADOW_PASSWD_STRING)) + || eflg || fflg) { +@@ -1766,7 +1782,7 @@ static void usr_update (void) + spent.sp_inact = -1; + spent.sp_expire = -1; + spent.sp_flag = SHADOW_SP_FLAG_UNSET; +- new_spent (&spent); ++ new_spent (&spent, process_selinux); + spwd = &spent; /* entry needs to be committed */ + } + } +@@ -1777,13 +1793,13 @@ static void usr_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + if (lflg && (pw_remove (user_name) == 0)) { + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, pw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + } + if ((NULL != spwd) && (lflg || eflg || fflg || pflg || Lflg || Uflg)) { +@@ -1791,13 +1807,13 @@ static void usr_update (void) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), spent.sp_namp); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + if (lflg && (spw_remove (user_name) == 0)) { + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, user_name, spw_dbname ()); +- fail_exit (E_PW_UPDATE); ++ fail_exit (E_PW_UPDATE, process_selinux); + } + } + } +@@ -1808,7 +1824,7 @@ static void usr_update (void) + * move_home() moves the user's home directory to a new location. The + * files will be copied if the directory cannot simply be renamed. + */ +-static void move_home (void) ++static void move_home (bool process_selinux) + { + struct stat sb; + +@@ -1820,7 +1836,7 @@ static void move_home (void) + fprintf (stderr, + _("%s: directory %s exists\n"), + Prog, user_newhome); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + + if (stat (prefix_user_home, &sb) == 0) { +@@ -1834,7 +1850,7 @@ static void move_home (void) + "not a directory. It is not removed and no " + "home directories are created.\n"), + Prog, user_home); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + + #ifdef WITH_AUDIT +@@ -1855,7 +1871,7 @@ static void move_home (void) + fprintf (stderr, + _("%s: Failed to change ownership of the home directory"), + Prog); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + #ifdef WITH_AUDIT + audit_logger (AUDIT_USER_MGMT, Prog, +@@ -1870,7 +1886,7 @@ static void move_home (void) + fprintf (stderr, + _("%s: error: cannot move subvolume from %s to %s - different device\n"), + Prog, prefix_user_home, prefix_user_newhome); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + #endif + +@@ -1901,7 +1917,7 @@ static void move_home (void) + fprintf (stderr, + _("%s: cannot rename directory %s to %s\n"), + Prog, prefix_user_home, prefix_user_newhome); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + } else { + fprintf (stderr, +@@ -2160,6 +2176,8 @@ int main (int argc, char **argv) + int retval; + #endif /* USE_PAM */ + #endif /* ACCT_TOOLS_SETUID */ ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -2189,7 +2207,8 @@ int main (int argc, char **argv) + is_sub_gid = sub_gid_file_present (); + #endif /* ENABLE_SUBIDS */ + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot && !flags.prefix; + + /* + * The home directory, the username and the user's UID should not +@@ -2251,13 +2270,13 @@ int main (int argc, char **argv) + * Do the hard stuff - open the files, change the user entries, + * change the home directory, then close and update the files. + */ +- open_files (); ++ open_files (process_selinux); + if ( cflg || dflg || eflg || fflg || gflg || Lflg || lflg || pflg + || sflg || uflg || Uflg) { +- usr_update (); ++ usr_update (&flags); + } + if (Gflg || lflg) { +- grp_update (); ++ grp_update (process_selinux); + } + #ifdef ENABLE_SUBIDS + if (Vflg) { +@@ -2273,7 +2292,7 @@ int main (int argc, char **argv) + (uintmax_t) ptr->range.first, + (uintmax_t) ptr->range.last, + sub_uid_dbname()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + } + } +@@ -2290,7 +2309,7 @@ int main (int argc, char **argv) + (uintmax_t) ptr->range.first, + (uintmax_t) ptr->range.last, + sub_uid_dbname()); +- fail_exit (E_SUB_UID_UPDATE); ++ fail_exit (E_SUB_UID_UPDATE, process_selinux); + } + } + } +@@ -2307,7 +2326,7 @@ int main (int argc, char **argv) + (uintmax_t) ptr->range.first, + (uintmax_t) ptr->range.last, + sub_gid_dbname()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + } + } +@@ -2324,12 +2343,12 @@ int main (int argc, char **argv) + (uintmax_t) ptr->range.first, + (uintmax_t) ptr->range.last, + sub_gid_dbname()); +- fail_exit (E_SUB_GID_UPDATE); ++ fail_exit (E_SUB_GID_UPDATE, process_selinux); + } + } + } + #endif /* ENABLE_SUBIDS */ +- close_files (); ++ close_files (&flags); + + #ifdef WITH_TCB + if ( (lflg || uflg) +@@ -2355,7 +2374,7 @@ int main (int argc, char **argv) + user_name, user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +- fail_exit (E_SE_UPDATE); ++ fail_exit (E_SE_UPDATE, process_selinux); + } + } else { + if (del_seuser (user_name) != 0) { +@@ -2368,14 +2387,14 @@ int main (int argc, char **argv) + user_name, user_id, + SHADOW_AUDIT_FAILURE); + #endif /* WITH_AUDIT */ +- fail_exit (E_SE_UPDATE); ++ fail_exit (E_SE_UPDATE, process_selinux); + } + } + } + #endif /* WITH_SELINUX */ + + if (mflg) { +- move_home (); ++ move_home (process_selinux); + } + + #ifndef NO_MOVE_MAILBOX +@@ -2420,7 +2439,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: Failed to change ownership of the home directory"), + Prog); +- fail_exit (E_HOMEDIR); ++ fail_exit (E_HOMEDIR, process_selinux); + } + } + } + +diff -up shadow-4.18.0/lib/cleanup_group.c.test-chroot3 shadow-4.18.0/lib/cleanup_group.c +--- shadow-4.18.0/lib/cleanup_group.c.test-chroot3 2025-07-04 11:15:02.302179208 +0200 ++++ shadow-4.18.0/lib/cleanup_group.c 2025-07-04 11:15:02.311510389 +0200 +@@ -179,9 +179,11 @@ void cleanup_report_del_group_gshadow (v + * + * It should be registered after the group file is successfully locked. + */ +-void cleanup_unlock_group (MAYBE_UNUSED void *arg) ++void cleanup_unlock_group (void *process_selinux) + { +- if (gr_unlock (true) == 0) { ++ bool process = *((bool *) process_selinux); ++ ++ if (gr_unlock (process) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), gr_dbname ()); +@@ -199,9 +201,11 @@ void cleanup_unlock_group (MAYBE_UNUSED + * + * It should be registered after the gshadow file is successfully locked. + */ +-void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg) ++void cleanup_unlock_gshadow (void *process_selinux) + { +- if (sgr_unlock (true) == 0) { ++ bool process = *((bool *) process_selinux); ++ ++ if (sgr_unlock (process) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), sgr_dbname ()); +diff -up shadow-4.18.0/lib/cleanup_user.c.test-chroot3 shadow-4.18.0/lib/cleanup_user.c +--- shadow-4.18.0/lib/cleanup_user.c.test-chroot3 2025-07-04 11:15:02.297132547 +0200 ++++ shadow-4.18.0/lib/cleanup_user.c 2025-07-04 11:15:02.311622726 +0200 +@@ -96,9 +96,11 @@ void cleanup_report_add_user_shadow (voi + * + * It should be registered after the passwd database is successfully locked. + */ +-void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) ++void cleanup_unlock_passwd (void *process_selinux) + { +- if (pw_unlock (true) == 0) { ++ bool process = *((bool *) process_selinux); ++ ++ if (pw_unlock (process) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), pw_dbname ()); +@@ -115,9 +117,11 @@ void cleanup_unlock_passwd (MAYBE_UNUSED + * + * It should be registered after the shadow database is successfully locked. + */ +-void cleanup_unlock_shadow (MAYBE_UNUSED void *arg) ++void cleanup_unlock_shadow (void *process_selinux) + { +- if (spw_unlock (true) == 0) { ++ bool process = *((bool *) process_selinux); ++ ++ if (spw_unlock (process) == 0) { + fprintf (log_get_logfd(), + _("%s: failed to unlock %s\n"), + log_get_progname(), spw_dbname ()); +diff -up shadow-4.18.0/lib/prototypes.h.test-chroot3 shadow-4.18.0/lib/prototypes.h +--- shadow-4.18.0/lib/prototypes.h.test-chroot3 2025-06-24 22:28:01.058453223 +0200 ++++ shadow-4.18.0/lib/prototypes.h 2025-07-04 11:15:02.311703893 +0200 +@@ -92,11 +92,11 @@ void cleanup_report_del_group_gshadow (v + void cleanup_report_mod_passwd (void *cleanup_info); + void cleanup_report_mod_group (void *cleanup_info); + void cleanup_report_mod_gshadow (void *cleanup_info); +-void cleanup_unlock_group (/*@null@*/void *MAYBE_UNUSED); ++void cleanup_unlock_group (void *process_selinux); + #ifdef SHADOWGRP +-void cleanup_unlock_gshadow (/*@null@*/void *MAYBE_UNUSED); ++void cleanup_unlock_gshadow (void *process_selinux); + #endif +-void cleanup_unlock_passwd (/*@null@*/void *MAYBE_UNUSED); ++void cleanup_unlock_passwd (void *process_selinux); + + /* console.c */ + extern bool console (const char *); +diff -up shadow-4.18.0/src/chgpasswd.c.test-chroot3 shadow-4.18.0/src/chgpasswd.c +--- shadow-4.18.0/src/chgpasswd.c.test-chroot3 2025-07-04 11:15:02.302260729 +0200 ++++ shadow-4.18.0/src/chgpasswd.c 2025-07-04 11:15:02.312527205 +0200 +@@ -38,6 +38,12 @@ + #include "string/strcmp/streq.h" + #include "string/strtok/stpsep.h" + ++/* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -68,21 +74,21 @@ static bool sgr_locked = false; + static bool gr_locked = false; + + /* local function prototypes */ +-NORETURN static void fail_exit (int code); ++NORETURN static void fail_exit (int code, bool process_selinux); + NORETURN static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (void); + static void check_perms (void); +-static void open_files (void); +-static void close_files (void); ++static void open_files (bool process_selinux); ++static void close_files (struct option_flags *flags); + + /* + * fail_exit - exit with a failure code after unlocking the files + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -91,7 +97,7 @@ static void fail_exit (int code) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -149,7 +155,7 @@ usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) +@@ -187,6 +193,7 @@ static void process_flags (int argc, cha + md5flg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': +@@ -336,7 +343,7 @@ static void check_perms (void) + /* + * open_files - lock and open the group databases + */ +-static void open_files (void) ++static void open_files (bool process_selinux) + { + /* + * Lock the group file and open it for reading and writing. This will +@@ -346,13 +353,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + #ifdef SHADOWGRP +@@ -362,13 +369,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + sgr_locked = true; + if (sgr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), + Prog, sgr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } + #endif +@@ -377,18 +384,21 @@ static void open_files (void) + /* + * close_files - close and unlock the group databases + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -397,14 +407,14 @@ static void close_files (void) + } + #endif + +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -428,6 +438,8 @@ int main (int argc, char **argv) + struct group newgr; + bool errors = false; + intmax_t line = 0; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -444,7 +456,8 @@ int main (int argc, char **argv) + + process_root_flag ("-R", argc, argv); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + OPENLOG (Prog); + +@@ -454,7 +467,7 @@ int main (int argc, char **argv) + is_shadow_grp = sgr_file_present (); + #endif + +- open_files (); ++ open_files (process_selinux); + + /* + * Read each line, separating the group name from the password. The +@@ -523,7 +536,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to crypt password with salt '%s': %s\n"), + Prog, salt, strerror (errno)); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } + +@@ -624,10 +637,10 @@ int main (int argc, char **argv) + if (errors) { + fprintf (stderr, + _("%s: error detected, changes ignored\n"), Prog); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + +- close_files (); ++ close_files (&flags); + + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_GROUP); +diff -up shadow-4.18.0/src/groupadd.c.test-chroot3 shadow-4.18.0/src/groupadd.c +--- shadow-4.18.0/src/groupadd.c.test-chroot3 2025-07-04 11:15:02.284218582 +0200 ++++ shadow-4.18.0/src/groupadd.c 2025-07-04 11:15:02.311806157 +0200 +@@ -54,6 +54,14 @@ + #define E_GRP_UPDATE 10 /* can't update group file */ + + /* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ ++/* + * Global variables + */ + static const char Prog[] = "groupadd"; +@@ -85,9 +93,9 @@ static void new_sgent (struct sgrp *sgen + #endif + static void grp_update (void); + static void check_new_name (void); +-static void close_files (void); +-static void open_files (void); +-static void process_flags (int argc, char **argv); ++static void close_files (struct option_flags *flags); ++static void open_files (struct option_flags *flags); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (void); + static void check_perms (void); + +@@ -271,10 +279,14 @@ check_new_name(void) + * close_files() closes all of the files that were opened for this new + * group. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* First, write the changes in the regular group database */ +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +@@ -289,13 +301,13 @@ static void close_files (void) + gr_dbname (), group_name, (unsigned int) group_id)); + del_cleanup (cleanup_report_add_group_group); + +- cleanup_unlock_group (NULL); ++ cleanup_unlock_group (&process_selinux); + del_cleanup (cleanup_unlock_group); + + /* Now, write the changes in the shadow database */ + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +@@ -310,7 +322,7 @@ static void close_files (void) + sgr_dbname (), group_name)); + del_cleanup (cleanup_report_add_group_gshadow); + +- cleanup_unlock_gshadow (NULL); ++ cleanup_unlock_gshadow (&process_selinux); + del_cleanup (cleanup_unlock_gshadow); + } + #endif /* SHADOWGRP */ +@@ -326,8 +338,12 @@ static void close_files (void) + * + * open_files() opens the two group files. + */ +-static void open_files (void) ++static void open_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* First, lock the databases */ + if (gr_lock () == 0) { + fprintf (stderr, +@@ -335,7 +351,7 @@ static void open_files (void) + Prog, gr_dbname ()); + fail_exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_group, NULL); ++ add_cleanup (cleanup_unlock_group, &process_selinux); + + #ifdef SHADOWGRP + if (is_shadow_grp) { +@@ -345,7 +361,7 @@ static void open_files (void) + Prog, sgr_dbname ()); + fail_exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_gshadow, NULL); ++ add_cleanup (cleanup_unlock_gshadow, &process_selinux); + } + #endif /* SHADOWGRP */ + +@@ -380,7 +396,7 @@ static void open_files (void) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -455,8 +471,10 @@ static void process_flags (int argc, cha + rflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 'U': + user_list = optarg; +@@ -583,6 +601,8 @@ static void check_perms (void) + */ + int main (int argc, char **argv) + { ++ struct option_flags flags; ++ + log_set_progname(Prog); + log_set_logfd(stderr); + +@@ -608,7 +628,7 @@ int main (int argc, char **argv) + /* + * Parse the command line options. + */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + check_perms (); + +@@ -625,7 +645,7 @@ int main (int argc, char **argv) + * Do the hard stuff - open the files, create the group entries, + * then close and update the files. + */ +- open_files (); ++ open_files (&flags); + + if (!gflg) { + if (find_new_gid (rflg, &group_id, NULL) < 0) { +@@ -634,7 +654,7 @@ int main (int argc, char **argv) + } + + grp_update (); +- close_files (); ++ close_files (&flags); + if (run_parts ("/etc/shadow-maint/groupadd-post.d", group_name, + Prog)) { + exit(1); +diff -up shadow-4.18.0/src/groupdel.c.test-chroot3 shadow-4.18.0/src/groupdel.c +--- shadow-4.18.0/src/groupdel.c.test-chroot3 2025-07-04 11:15:02.284261326 +0200 ++++ shadow-4.18.0/src/groupdel.c 2025-07-04 11:15:02.312079796 +0200 +@@ -33,6 +33,12 @@ + #endif + #include "shadowlog.h" + #include "run_part.h" ++ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ + /* + * Global variables + */ +@@ -61,10 +67,10 @@ static bool is_shadow_grp; + /* local function prototypes */ + NORETURN static void usage (int status); + static void grp_update (void); +-static void close_files (void); +-static void open_files (void); ++static void close_files (struct option_flags *flags); ++static void open_files (struct option_flags *flags); + static void group_busy (gid_t gid); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + + /* + * usage - display usage message and exit +@@ -146,10 +152,14 @@ static void grp_update (void) + * close_files() closes all of the files that were opened for this + * new group. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* First, write the changes in the regular group database */ +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +@@ -166,14 +176,14 @@ static void close_files (void) + group_name, gr_dbname ())); + del_cleanup (cleanup_report_del_group_group); + +- cleanup_unlock_group (NULL); ++ cleanup_unlock_group (&process_selinux); + del_cleanup (cleanup_unlock_group); + + + /* Then, write the changes in the shadow database */ + #ifdef SHADOWGRP + if (is_shadow_grp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +@@ -190,7 +200,7 @@ static void close_files (void) + group_name, sgr_dbname ())); + del_cleanup (cleanup_report_del_group_gshadow); + +- cleanup_unlock_gshadow (NULL); ++ cleanup_unlock_gshadow (&process_selinux); + del_cleanup (cleanup_unlock_gshadow); + } + #endif /* SHADOWGRP */ +@@ -204,8 +214,12 @@ static void close_files (void) + * + * open_files() opens the two group files. + */ +-static void open_files (void) ++static void open_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* First, lock the databases */ + if (gr_lock () == 0) { + fprintf (stderr, +@@ -213,7 +227,7 @@ static void open_files (void) + Prog, gr_dbname ()); + fail_exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_group, NULL); ++ add_cleanup (cleanup_unlock_group, &process_selinux); + #ifdef SHADOWGRP + if (is_shadow_grp) { + if (sgr_lock () == 0) { +@@ -222,7 +236,7 @@ static void open_files (void) + Prog, sgr_dbname ()); + fail_exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_gshadow, NULL); ++ add_cleanup (cleanup_unlock_gshadow, &process_selinux); + } + #endif + +@@ -296,7 +310,7 @@ static void group_busy (gid_t gid) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -317,8 +331,10 @@ static void process_flags (int argc, cha + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 'f': + check_group_busy = false; +@@ -352,6 +368,7 @@ int main (int argc, char **argv) + int retval; + #endif /* USE_PAM */ + #endif /* ACCT_TOOLS_SETUID */ ++ struct option_flags flags; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -375,7 +392,7 @@ int main (int argc, char **argv) + fail_exit (1); + } + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + #ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM +@@ -449,11 +466,11 @@ int main (int argc, char **argv) + * Do the hard stuff - open the files, delete the group entries, + * then close and update the files. + */ +- open_files (); ++ open_files (&flags); + + grp_update (); + +- close_files (); ++ close_files (&flags); + + if (run_parts ("/etc/shadow-maint/groupdel-post.d", group_name, + Prog)) { +diff -up shadow-4.18.0/src/groupmems.c.test-chroot3 shadow-4.18.0/src/groupmems.c +--- shadow-4.18.0/src/groupmems.c.test-chroot3 2025-07-04 11:15:02.302301588 +0200 ++++ shadow-4.18.0/src/groupmems.c 2025-07-04 11:15:57.404278255 +0200 +@@ -47,6 +47,13 @@ + #define EXIT_INVALID_GROUP 9 /* specified group does not exist */ + + /* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++}; ++ ++/* + * Global variables + */ + static const char Prog[] = "groupmems"; +@@ -68,15 +75,17 @@ static bool sgr_locked = false; + /* local function prototypes */ + static char *whoami (void); + static void add_user (const char *user, +- const struct group *grp); ++ const struct group *grp, ++ bool process_selinux); + static void remove_user (const char *user, +- const struct group *grp); +-static void purge_members (const struct group *grp); ++ const struct group *grp, ++ bool process_selinux); ++static void purge_members (const struct group *grp, bool process_selinux); + static void display_members (const char *const *members); + NORETURN static void usage (int status); +-static void process_flags (int argc, char **argv); +-static void check_perms (void); +-NORETURN static void fail_exit (int code); ++static void process_flags (int argc, char **argv, struct option_flags *flags); ++static void check_perms (bool process_selinux); ++NORETURN static void fail_exit (int code, bool process_selinux); + #define isroot() (getuid () == 0) + + static char *whoami (void) +@@ -99,7 +108,8 @@ static char *whoami (void) + * add_user - Add a user to the specified group + */ + static void add_user (const char *user, +- const struct group *grp) ++ const struct group *grp, ++ bool process_selinux) + { + struct group *newgrp; + +@@ -108,7 +118,7 @@ static void add_user (const char *user, + fprintf (stderr, + _("%s: user '%s' is already a member of '%s'\n"), + Prog, user, grp->gr_name); +- fail_exit (EXIT_MEMBER_EXISTS); ++ fail_exit (EXIT_MEMBER_EXISTS, process_selinux); + } + + newgrp = __gr_dup(grp); +@@ -116,7 +126,7 @@ static void add_user (const char *user, + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + + /* Add the user to the /etc/group group */ +@@ -146,7 +156,7 @@ static void add_user (const char *user, + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + /* Add the user to the members */ + newsg->sg_mem = add_list (newsg->sg_mem, user); +@@ -157,7 +167,7 @@ static void add_user (const char *user, + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), newsg->sg_namp); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + #endif +@@ -166,7 +176,7 @@ static void add_user (const char *user, + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), newgrp->gr_name); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + +@@ -174,7 +184,8 @@ static void add_user (const char *user, + * remove_user - Remove a user from a given group + */ + static void remove_user (const char *user, +- const struct group *grp) ++ const struct group *grp, ++ bool process_selinux) + { + struct group *newgrp; + +@@ -183,7 +194,7 @@ static void remove_user (const char *use + fprintf (stderr, + _("%s: user '%s' is not a member of '%s'\n"), + Prog, user, grp->gr_name); +- fail_exit (EXIT_NOT_MEMBER); ++ fail_exit (EXIT_NOT_MEMBER, process_selinux); + } + + newgrp = __gr_dup (grp); +@@ -191,7 +202,7 @@ static void remove_user (const char *use + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + + /* Remove the user from the /etc/group group */ +@@ -221,7 +232,7 @@ static void remove_user (const char *use + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + /* Remove the user from the members */ + newsg->sg_mem = del_list (newsg->sg_mem, user); +@@ -233,7 +244,7 @@ static void remove_user (const char *use + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), newsg->sg_namp); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + #endif +@@ -242,14 +253,14 @@ static void remove_user (const char *use + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), newgrp->gr_name); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + + /* + * purge_members - Remove every members of the specified group + */ +-static void purge_members (const struct group *grp) ++static void purge_members (const struct group *grp, bool process_selinux) + { + struct group *newgrp = __gr_dup (grp); + +@@ -257,7 +268,7 @@ static void purge_members (const struct + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, gr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + + /* Remove all the members of the /etc/group group */ +@@ -288,7 +299,7 @@ static void purge_members (const struct + fprintf (stderr, + _("%s: Out of memory. Cannot update %s.\n"), + Prog, sgr_dbname ()); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + /* Remove all the members of the /etc/gshadow + * group */ +@@ -302,7 +313,7 @@ static void purge_members (const struct + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), newsg->sg_namp); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + #endif +@@ -311,7 +322,7 @@ static void purge_members (const struct + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), newgrp->gr_name); +- fail_exit (13); ++ fail_exit (13, process_selinux); + } + } + +@@ -356,7 +367,7 @@ usage (int status) + /* + * process_flags - perform command line argument setting + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -396,6 +407,7 @@ static void process_flags (int argc, cha + ++exclusive; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + default: + usage (EXIT_USAGE); +@@ -411,12 +423,12 @@ static void process_flags (int argc, cha + && (getpwnam (adduser) == NULL)) { + fprintf (stderr, _("%s: user '%s' does not exist\n"), + Prog, adduser); +- fail_exit (EXIT_INVALID_USER); ++ fail_exit (EXIT_INVALID_USER, !flags->chroot); + } + + } + +-static void check_perms (void) ++static void check_perms (bool process_selinux) + { + if (!list) { + #ifdef ACCT_TOOLS_SETUID +@@ -430,7 +442,7 @@ static void check_perms (void) + fprintf (stderr, + _("%s: Cannot determine your user name.\n"), + Prog); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); +@@ -450,7 +462,7 @@ static void check_perms (void) + if (NULL != pamh) { + (void) pam_end (pamh, retval); + } +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + (void) pam_end (pamh, retval); + #endif /* USE_PAM */ +@@ -458,10 +470,10 @@ static void check_perms (void) + } + } + +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, gr_dbname ()); +@@ -472,7 +484,7 @@ static void fail_exit (int code) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, sgr_dbname ()); +@@ -485,14 +497,14 @@ static void fail_exit (int code) + exit (code); + } + +-static void open_files (void) ++static void open_files (bool process_selinux) + { + if (!list) { + if (gr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + gr_locked = true; + +@@ -502,7 +514,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + sgr_locked = true; + } +@@ -511,28 +523,32 @@ static void open_files (void) + + if (gr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + + #ifdef SHADOWGRP + if (is_shadowgrp) { + if (sgr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + } + #endif + } + +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if ((gr_close (true) == 0) && !list) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; ++ ++ if ((gr_close (process_selinux) == 0) && !list) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -542,13 +558,13 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadowgrp) { +- if ((sgr_close (true) == 0) && !list) { ++ if ((sgr_close (process_selinux) == 0) && !list) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +- fail_exit (EXIT_GROUP_FILE); ++ fail_exit (EXIT_GROUP_FILE, process_selinux); + } + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -563,6 +579,8 @@ int main (int argc, char **argv) + { + char *name; + const struct group *grp; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -579,44 +597,45 @@ int main (int argc, char **argv) + is_shadowgrp = sgr_file_present (); + #endif + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + if (NULL == thisgroup) { + name = whoami (); + if (!list && (NULL == name)) { + fprintf (stderr, _("%s: your groupname does not match your username\n"), Prog); +- fail_exit (EXIT_NOT_PRIMARY); ++ fail_exit (EXIT_NOT_PRIMARY, process_selinux); + } + } else { + name = thisgroup; + if (!list && !isroot ()) { + fprintf (stderr, _("%s: only root can use the -g/--group option\n"), Prog); +- fail_exit (EXIT_NOT_ROOT); ++ fail_exit (EXIT_NOT_ROOT, process_selinux); + } + } + +- check_perms (); ++ check_perms (process_selinux); + +- open_files (); ++ open_files (process_selinux); + + grp = gr_locate (name); + if (NULL == grp) { + fprintf (stderr, _("%s: group '%s' does not exist in %s\n"), + Prog, name, gr_dbname ()); +- fail_exit (EXIT_INVALID_GROUP); ++ fail_exit (EXIT_INVALID_GROUP, process_selinux); + } + + if (list) { + display_members ((const char *const *)grp->gr_mem); + } else if (NULL != adduser) { +- add_user (adduser, grp); ++ add_user (adduser, grp, process_selinux); + } else if (NULL != deluser) { +- remove_user (deluser, grp); ++ remove_user (deluser, grp, process_selinux); + } else if (purge) { +- purge_members (grp); ++ purge_members (grp, process_selinux); + } + +- close_files (); ++ close_files (&flags); + + exit (EXIT_SUCCESS); + } +diff -up shadow-4.18.0/src/groupmod.c.test-chroot3 shadow-4.18.0/src/groupmod.c +--- shadow-4.18.0/src/groupmod.c.test-chroot3 2025-07-04 11:15:02.284354823 +0200 ++++ shadow-4.18.0/src/groupmod.c 2025-07-04 11:15:02.311945828 +0200 +@@ -61,6 +61,10 @@ + #define E_PAM_USERNAME 12 /* can't determine your username for use with pam */ + #define E_PAM_ERROR 13 /* pam returned an error, see Syslog facility id groupmod */ + ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; + + /* + * Global variables +@@ -102,11 +106,11 @@ static void new_sgent (struct sgrp *); + static void grp_update (void); + static void check_new_gid (void); + static void check_new_name (void); +-static void process_flags (int, char **); +-static void lock_files (void); ++static void process_flags (int, char **, struct option_flags *); ++static void lock_files (struct option_flags *flags); + static void prepare_failure_reports (void); + static void open_files (void); +-static void close_files (void); ++static void close_files (struct option_flags *flags); + static void update_primary_groups (gid_t ogid, gid_t ngid); + + +@@ -405,7 +409,7 @@ check_new_name(void) + * values that the user will be created with accordingly. The values + * are checked for sanity. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -451,8 +455,10 @@ static void process_flags (int argc, cha + pflg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 'U': + user_list = optarg; +@@ -479,9 +485,13 @@ static void process_flags (int argc, cha + * close_files() closes all of the files that were opened for this new + * group. This causes any modified entries to be written out. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (gr_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +@@ -498,13 +508,13 @@ static void close_files (void) + gr_dbname (), info_group.action)); + del_cleanup (cleanup_report_mod_group); + +- cleanup_unlock_group (NULL); ++ cleanup_unlock_group (&process_selinux); + del_cleanup (cleanup_unlock_group); + + #ifdef SHADOWGRP + if ( is_shadow_grp + && (pflg || nflg || user_list)) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +@@ -528,13 +538,13 @@ static void close_files (void) + sgr_dbname (), info_gshadow.action)); + del_cleanup (cleanup_report_mod_gshadow); + +- cleanup_unlock_gshadow (NULL); ++ cleanup_unlock_gshadow (&process_selinux); + del_cleanup (cleanup_unlock_gshadow); + } + #endif /* SHADOWGRP */ + + if (gflg) { +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +@@ -551,7 +561,7 @@ static void close_files (void) + pw_dbname (), info_passwd.action)); + del_cleanup (cleanup_report_mod_passwd); + +- cleanup_unlock_passwd (NULL); ++ cleanup_unlock_passwd (&process_selinux); + del_cleanup (cleanup_unlock_passwd); + } + +@@ -657,15 +667,19 @@ static void prepare_failure_reports (voi + * + * lock_files() locks the group, gshadow, and passwd databases. + */ +-static void lock_files (void) ++static void lock_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + if (gr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); + exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_group, NULL); ++ add_cleanup (cleanup_unlock_group, &process_selinux); + + #ifdef SHADOWGRP + if ( is_shadow_grp +@@ -676,7 +690,7 @@ static void lock_files (void) + Prog, sgr_dbname ()); + exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_gshadow, NULL); ++ add_cleanup (cleanup_unlock_gshadow, &process_selinux); + } + #endif + +@@ -687,7 +701,7 @@ static void lock_files (void) + Prog, pw_dbname ()); + exit (E_GRP_UPDATE); + } +- add_cleanup (cleanup_unlock_passwd, NULL); ++ add_cleanup (cleanup_unlock_passwd, &process_selinux); + } + } + +@@ -771,6 +785,7 @@ int main (int argc, char **argv) + int retval; + #endif /* USE_PAM */ + #endif /* ACCT_TOOLS_SETUID */ ++ struct option_flags flags; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -794,7 +809,7 @@ int main (int argc, char **argv) + exit (E_CLEANUP_SERVICE); + } + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + #ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM +@@ -859,7 +874,7 @@ int main (int argc, char **argv) + check_new_name (); + } + +- lock_files (); ++ lock_files (&flags); + + /* + * Now if the group is not changed, it's our fault. +@@ -875,7 +890,7 @@ int main (int argc, char **argv) + + grp_update (); + +- close_files (); ++ close_files (&flags); + + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_GROUP); +diff -up shadow-4.18.0/src/grpck.c.test-chroot3 shadow-4.18.0/src/grpck.c +--- shadow-4.18.0/src/grpck.c.test-chroot3 2025-07-04 11:15:02.302354224 +0200 ++++ shadow-4.18.0/src/grpck.c 2025-07-04 11:15:02.313643179 +0200 +@@ -44,6 +44,13 @@ + #define E_CANT_UPDATE 5 + + /* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++}; ++ ++/* + * Global variables + */ + static const char Prog[] = "grpck"; +@@ -64,19 +71,20 @@ static bool sort_mode = false; + static bool silence_warnings = false; + + /* local function prototypes */ +-static void fail_exit (int status); ++static void fail_exit (int status, bool process_selinux); + NORETURN static void usage (int status); + static void delete_member (char **, const char *); +-static void process_flags (int argc, char **argv); +-static void open_files (void); +-static void close_files (bool changed); ++static void process_flags (int argc, char **argv, struct option_flags *flags); ++static void open_files (bool process_selinux); ++static void close_files (bool changed, struct option_flags *flags); + static int check_members (const char *groupname, + char **members, + const char *fmt_info, + const char *fmt_prompt, + const char *fmt_syslog, + bool *errors); +-static void check_grp_file (bool *errors, bool *changed); ++static void check_grp_file (bool *errors, bool *changed, ++ struct option_flags *flags); + #ifdef SHADOWGRP + static void compare_members_lists (const char *groupname, + char **members, +@@ -89,10 +97,10 @@ static void check_sgr_file (bool *errors + /* + * fail_exit - exit with an error code after unlocking files + */ +-static void fail_exit (int status) ++static void fail_exit (int status, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -101,7 +109,7 @@ static void fail_exit (int status) + + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -172,7 +180,7 @@ static void delete_member (char **list, + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -201,6 +209,7 @@ static void process_flags (int argc, cha + read_only = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 's': + sort_mode = true; +@@ -257,7 +266,7 @@ static void process_flags (int argc, cha + * In read-only mode, the databases are not locked and are opened + * only for reading. + */ +-static void open_files (void) ++static void open_files (bool process_selinux) + { + /* + * Lock the files if we aren't in "read-only" mode +@@ -267,7 +276,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, grp_file); +- fail_exit (E_CANT_LOCK); ++ fail_exit (E_CANT_LOCK, process_selinux); + } + gr_locked = true; + #ifdef SHADOWGRP +@@ -276,7 +285,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_file); +- fail_exit (E_CANT_LOCK); ++ fail_exit (E_CANT_LOCK, process_selinux); + } + sgr_locked = true; + } +@@ -293,7 +302,7 @@ static void open_files (void) + if (use_system_grp_file) { + SYSLOG ((LOG_WARN, "cannot open %s", grp_file)); + } +- fail_exit (E_CANT_OPEN); ++ fail_exit (E_CANT_OPEN, process_selinux); + } + #ifdef SHADOWGRP + if (is_shadow && (sgr_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0)) { +@@ -302,7 +311,7 @@ static void open_files (void) + if (use_system_sgr_file) { + SYSLOG ((LOG_WARN, "cannot open %s", sgr_file)); + } +- fail_exit (E_CANT_OPEN); ++ fail_exit (E_CANT_OPEN, process_selinux); + } + #endif + } +@@ -314,23 +323,27 @@ static void open_files (void) + * changes are committed in the databases. The databases are + * unlocked anyway. + */ +-static void close_files (bool changed) ++static void close_files (bool changed, struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; ++ + /* + * All done. If there were no change we can just abandon any + * changes to the files. + */ + if (changed) { +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), + Prog, grp_file); +- fail_exit (E_CANT_UPDATE); ++ fail_exit (E_CANT_UPDATE, process_selinux); + } + #ifdef SHADOWGRP +- if (is_shadow && (sgr_close (true) == 0)) { ++ if (is_shadow && (sgr_close (process_selinux) == 0)) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), + Prog, sgr_file); +- fail_exit (E_CANT_UPDATE); ++ fail_exit (E_CANT_UPDATE, process_selinux); + } + #endif + } +@@ -340,7 +353,7 @@ static void close_files (bool changed) + */ + #ifdef SHADOWGRP + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -349,7 +362,7 @@ static void close_files (bool changed) + } + #endif + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -455,13 +468,16 @@ static void compare_members_lists (const + /* + * check_grp_file - check the content of the group file + */ +-static void check_grp_file (bool *errors, bool *changed) ++static void check_grp_file (bool *errors, bool *changed, struct option_flags *flags) + { + struct commonio_entry *gre, *tgre; + struct group *grp; + #ifdef SHADOWGRP + const struct sgrp *sgr; + #endif ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Loop through the entire group file. +@@ -627,7 +643,7 @@ static void check_grp_file (bool *errors + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), sg.sg_namp); +- fail_exit (E_CANT_UPDATE); ++ fail_exit (E_CANT_UPDATE, process_selinux); + } + /* remove password from /etc/group */ + gr = *grp; +@@ -636,7 +652,7 @@ static void check_grp_file (bool *errors + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), gr.gr_name); +- fail_exit (E_CANT_UPDATE); ++ fail_exit (E_CANT_UPDATE, process_selinux); + } + } + } else { +@@ -819,6 +835,8 @@ int main (int argc, char **argv) + { + bool errors = false; + bool changed = false; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -832,9 +850,10 @@ int main (int argc, char **argv) + OPENLOG (Prog); + + /* Parse the command line arguments */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + +- open_files (); ++ open_files (process_selinux); + + if (sort_mode) { + gr_sort (); +@@ -845,7 +864,7 @@ int main (int argc, char **argv) + changed = true; + #endif + } else { +- check_grp_file (&errors, &changed); ++ check_grp_file (&errors, &changed, &flags); + #ifdef SHADOWGRP + if (is_shadow) { + check_sgr_file (&errors, &changed); +@@ -854,7 +873,7 @@ int main (int argc, char **argv) + } + + /* Commit the change in the database if needed */ +- close_files (changed); ++ close_files (changed, &flags); + + if (!read_only) { + nscd_flush_cache ("group"); + +diff -up shadow-4.18.0/src/chage.c.test-chroot4 shadow-4.18.0/src/chage.c +--- shadow-4.18.0/src/chage.c.test-chroot4 2025-07-04 11:17:37.593707379 +0200 ++++ shadow-4.18.0/src/chage.c 2025-07-04 11:17:37.613081862 +0200 +@@ -42,6 +42,10 @@ + #include "tcbfuncs.h" + #endif + ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; + + /* + * Global variables +@@ -79,29 +83,29 @@ NORETURN static void usage (int status); + static int new_fields (void); + static void print_day_as_date (long day); + static void list_fields (void); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (int argc, int opt_index); +-static void check_perms (void); +-static void open_files (bool readonly); +-static void close_files (void); +-NORETURN static void fail_exit (int code); ++static void check_perms (struct option_flags *flags); ++static void open_files (bool readonly, struct option_flags *flags); ++static void close_files (struct option_flags *flags); ++NORETURN static void fail_exit (int code, bool process_selinux); + + /* + * fail_exit - do some cleanup and exit with the given error code + */ + NORETURN + static void +-fail_exit (int code) ++fail_exit (int code, bool process_selinux) + { + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } + } + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -338,7 +342,7 @@ static void list_fields (void) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -419,8 +423,10 @@ static void process_flags (int argc, cha + } + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + case 'W': + Wflg = true; +@@ -472,8 +478,12 @@ static void check_flags (int argc, int o + * + * It will not return if the user is not allowed. + */ +-static void check_perms (void) ++static void check_perms (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* + * An unprivileged user can ask for their own aging information, but + * only root can change it, or list another user's aging +@@ -482,7 +492,7 @@ static void check_perms (void) + + if (!amroot && !lflg) { + fprintf (stderr, _("%s: Permission denied.\n"), Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + } + +@@ -492,8 +502,12 @@ static void check_perms (void) + * In read-only mode, the databases are not locked and are opened + * only for reading. + */ +-static void open_files (bool readonly) ++static void open_files (bool readonly, struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* + * Lock and open the password file. This loads all of the password + * file entries into memory. Then we get a pointer to the password +@@ -504,14 +518,14 @@ static void open_files (bool readonly) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + pw_locked = true; + } + if (pw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + /* +@@ -525,7 +539,7 @@ static void open_files (bool readonly) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + spw_locked = true; + } +@@ -533,42 +547,46 @@ static void open_files (bool readonly) + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + } + + /* + * close_files - close and unlock the password/shadow databases + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* + * Now close the shadow password file, which will cause all of the + * entries to be re-written. + */ +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + /* + * Close the password file. If any entries were modified, the file + * will be re-written. + */ +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } + spw_locked = false; +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -582,7 +600,8 @@ static void close_files (void) + * It will not return in case of error + */ + static void update_age (/*@null@*/const struct spwd *sp, +- /*@notnull@*/const struct passwd *pw) ++ /*@notnull@*/const struct passwd *pw, ++ bool process_selinux) + { + struct spwd spwent; + +@@ -603,7 +622,7 @@ static void update_age (/*@null@*/const + if (pw_update (&pwent) == 0) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pwent.pw_name); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + } else { + spwent.sp_namp = xstrdup (sp->sp_namp); +@@ -626,7 +645,7 @@ static void update_age (/*@null@*/const + if (spw_update (&spwent) == 0) { + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spwent.sp_namp); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + } +@@ -712,6 +731,8 @@ int main (int argc, char **argv) + uid_t ruid; + gid_t rgid; + const struct passwd *pw; ++ struct option_flags flags; ++ bool process_selinux; + + sanitize_env (); + check_fds (); +@@ -740,9 +761,10 @@ int main (int argc, char **argv) + } + #endif + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot && !flags.prefix; + +- check_perms (); ++ check_perms (&flags); + + if (!spw_file_present ()) { + fprintf (stderr, +@@ -753,13 +775,13 @@ int main (int argc, char **argv) + exit (E_SHADOW_NOTFOUND); + } + +- open_files (lflg); ++ open_files (lflg, &flags); + /* Drop privileges */ + if (lflg && ( (setregid (rgid, rgid) != 0) + || (setreuid (ruid, ruid) != 0))) { + fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), + Prog, strerror (errno)); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + pw = pw_locate (argv[optind]); +@@ -767,13 +789,13 @@ int main (int argc, char **argv) + fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), + Prog, argv[optind], pw_dbname ()); + closelog (); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + STRTCPY(user_name, pw->pw_name); + #ifdef WITH_TCB + if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) { +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + #endif + user_uid = pw->pw_uid; +@@ -788,11 +810,11 @@ int main (int argc, char **argv) + if (lflg) { + if (!amroot && (ruid != user_uid)) { + fprintf (stderr, _("%s: Permission denied.\n"), Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + /* Displaying fields is not of interest to audit */ + list_fields (); +- fail_exit (E_SUCCESS); ++ fail_exit (E_SUCCESS, process_selinux); + } + + /* +@@ -805,7 +827,7 @@ int main (int argc, char **argv) + if (new_fields () == 0) { + fprintf (stderr, _("%s: error changing fields\n"), + Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + #ifdef WITH_AUDIT + else { +@@ -847,9 +869,9 @@ int main (int argc, char **argv) + #endif + } + +- update_age (sp, pw); ++ update_age (sp, pw, process_selinux); + +- close_files (); ++ close_files (&flags); + + SYSLOG ((LOG_INFO, "changed password expiry for %s", user_name)); + +diff -up shadow-4.18.0/src/chfn.c.test-chroot4 shadow-4.18.0/src/chfn.c +--- shadow-4.18.0/src/chfn.c.test-chroot4 2025-07-04 11:17:37.590501245 +0200 ++++ shadow-4.18.0/src/chfn.c 2025-07-04 11:17:37.613576062 +0200 +@@ -39,6 +39,9 @@ + #include "string/strdup/xstrdup.h" + #include "string/strtok/stpsep.h" + ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables. +@@ -63,23 +66,23 @@ static bool pw_locked = false; + */ + + /* local function prototypes */ +-NORETURN static void fail_exit (int code); ++NORETURN static void fail_exit (int code, bool process_selinux); + NORETURN static void usage (int status); + static bool may_change_field (int); + static void new_fields (void); + static char *copy_field (char *, char *, char *); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_perms (const struct passwd *pw); +-static void update_gecos (const char *user, char *gecos); ++static void update_gecos (const char *user, char *gecos, struct option_flags *flags); + static void get_old_fields (const char *gecos); + + /* + * fail_exit - exit with an error and do some cleanup + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -250,7 +253,7 @@ static char *copy_field (char *in, char + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; /* flag currently being processed */ + static struct option long_options[] = { +@@ -316,6 +319,7 @@ static void process_flags (int argc, cha + STRTCPY(roomno, optarg); + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'u': + usage (E_SUCCESS); +@@ -423,10 +427,13 @@ static void check_perms (const struct pa + * + * Commit the user's entry after changing her gecos field. + */ +-static void update_gecos (const char *user, char *gecos) ++static void update_gecos (const char *user, char *gecos, struct option_flags *flags) + { + const struct passwd *pw; /* The user's password file entry */ + struct passwd pwent; /* modified password file entry */ ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Before going any further, raise the ulimit to prevent colliding +@@ -437,7 +444,7 @@ static void update_gecos (const char *us + if (setuid (0) != 0) { + fputs (_("Cannot change ID to root.\n"), stderr); + SYSLOG ((LOG_ERR, "can't setuid(0)")); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + pwd_init (); + +@@ -449,13 +456,13 @@ static void update_gecos (const char *us + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + /* +@@ -469,7 +476,7 @@ static void update_gecos (const char *us + fprintf (stderr, + _("%s: user '%s' does not exist in %s\n"), + Prog, user, pw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + /* +@@ -487,18 +494,18 @@ static void update_gecos (const char *us + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + + /* + * Changes have all been made, so commit them and unlock the file. + */ +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -562,7 +569,7 @@ static void get_old_fields (const char * + * + * It will not return if a field is not valid. + */ +-static void check_fields (void) ++static void check_fields (bool process_selinux) + { + int err; + err = valid_field (fullnm, ":,=\n"); +@@ -570,7 +577,7 @@ static void check_fields (void) + fprintf (stderr, _("%s: name with non-ASCII characters: '%s'\n"), Prog, fullnm); + } else if (err < 0) { + fprintf (stderr, _("%s: invalid name: '%s'\n"), Prog, fullnm); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + err = valid_field (roomno, ":,=\n"); + if (err > 0) { +@@ -578,17 +585,17 @@ static void check_fields (void) + } else if (err < 0) { + fprintf (stderr, _("%s: invalid room number: '%s'\n"), + Prog, roomno); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + if (valid_field (workph, ":,=\n") != 0) { + fprintf (stderr, _("%s: invalid work phone: '%s'\n"), + Prog, workph); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + if (valid_field (homeph, ":,=\n") != 0) { + fprintf (stderr, _("%s: invalid home phone: '%s'\n"), + Prog, homeph); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + err = valid_field (slop, ":\n"); + if (err > 0) { +@@ -597,7 +604,7 @@ static void check_fields (void) + fprintf (stderr, + _("%s: '%s' contains illegal characters\n"), + Prog, slop); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + } + +@@ -622,6 +629,8 @@ int main (int argc, char **argv) + char new_gecos[BUFSIZ]; + char *user; + const struct passwd *pw; ++ struct option_flags flags; ++ bool process_selinux; + + sanitize_env (); + check_fds (); +@@ -644,7 +653,7 @@ int main (int argc, char **argv) + OPENLOG (Prog); + + /* parse the command line options */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + /* + * Get the name of the user to check. It is either the command line +@@ -653,14 +662,14 @@ int main (int argc, char **argv) + if (optind < argc) { + if (!is_valid_user_name (argv[optind])) { + fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + user = argv[optind]; + pw = xgetpwnam (user); + if (NULL == pw) { + fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, + user); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + } else { + pw = get_my_pwent (); +@@ -670,7 +679,7 @@ int main (int argc, char **argv) + Prog); + SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", + (unsigned long) getuid ())); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + user = xstrdup (pw->pw_name); + } +@@ -695,7 +704,7 @@ int main (int argc, char **argv) + /* + * Check all of the fields for valid information + */ +- check_fields (); ++ check_fields (process_selinux); + + /* + * Build the new GECOS field by plastering all the pieces together, +@@ -704,14 +713,14 @@ int main (int argc, char **argv) + if ((strlen (fullnm) + strlen (roomno) + strlen (workph) + + strlen (homeph) + strlen (slop)) > (unsigned int) 80) { + fprintf (stderr, _("%s: fields too long\n"), Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + SNPRINTF(new_gecos, "%s,%s,%s,%s%s%s", + fullnm, roomno, workph, homeph, + (!streq(slop, "")) ? "," : "", slop); + + /* Rewrite the user's gecos in the passwd file */ +- update_gecos (user, new_gecos); ++ update_gecos (user, new_gecos, &flags); + + SYSLOG ((LOG_INFO, "changed user '%s' information", user)); + +diff -up shadow-4.18.0/src/chpasswd.c.test-chroot4 shadow-4.18.0/src/chpasswd.c +--- shadow-4.18.0/src/chpasswd.c.test-chroot4 2025-07-04 11:17:37.593768325 +0200 ++++ shadow-4.18.0/src/chpasswd.c 2025-07-04 11:18:06.785652711 +0200 +@@ -38,6 +38,11 @@ + + #define IS_CRYPT_METHOD(str) ((crypt_method != NULL && streq(crypt_method, str)) ? true : false) + ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ + /* + * Global variables + */ +@@ -67,21 +72,21 @@ static bool pw_locked = false; + static bool spw_locked = false; + + /* local function prototypes */ +-NORETURN static void fail_exit (int code); ++NORETURN static void fail_exit (int code, bool process_selinux); + NORETURN static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (void); + static void check_perms (void); +-static void open_files (void); +-static void close_files (void); ++static void open_files (struct option_flags *flags); ++static void close_files (struct option_flags *flags); + + /* + * fail_exit - exit with a failure code after unlocking the files + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -89,7 +94,7 @@ static void fail_exit (int code) + } + + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -147,7 +152,7 @@ usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) +@@ -187,8 +192,10 @@ static void process_flags (int argc, cha + md5flg = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags->prefix = true; + break; + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) + case 's': +@@ -335,8 +342,12 @@ static void check_perms (void) + /* + * open_files - lock and open the password databases + */ +-static void open_files (void) ++static void open_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + /* + * Lock the password file and open it for reading and writing. This + * will bring all of the entries into memory where they may be updated. +@@ -345,13 +356,13 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* Do the same for the shadowed database, if it exist */ +@@ -360,14 +371,14 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + spw_locked = true; + if (spw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } + } +@@ -375,17 +386,21 @@ static void open_files (void) + /* + * close_files - close and unlock the password databases + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; ++ + if (is_shadow_pwd) { +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -393,14 +408,14 @@ static void close_files (void) + spw_locked = false; + } + +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -456,6 +471,8 @@ int main (int argc, char **argv) + + bool errors = false; + intmax_t line = 0; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -470,7 +487,8 @@ int main (int argc, char **argv) + } + #endif /* WITH_SELINUX */ + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot && !flags.prefix; + + salt = get_salt(); + process_root_flag ("-R", argc, argv); +@@ -496,7 +514,7 @@ int main (int argc, char **argv) + { + is_shadow_pwd = spw_file_present (); + +- open_files (); ++ open_files (&flags); + } + + /* +@@ -573,7 +591,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to crypt password with salt '%s': %s\n"), + Prog, salt, strerror (errno)); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } + +@@ -690,7 +708,7 @@ int main (int argc, char **argv) + _("%s: error detected, changes ignored\n"), + Prog); + } +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + #ifdef ACCT_TOOLS_SETUID +@@ -700,7 +718,7 @@ int main (int argc, char **argv) + #endif /* ACCT_TOOLS_SETUID */ + { + /* Save the changes */ +- close_files (); ++ close_files (&flags); + } + + nscd_flush_cache ("passwd"); +diff -up shadow-4.18.0/src/grpconv.c.test-chroot4 shadow-4.18.0/src/grpconv.c +--- shadow-4.18.0/src/grpconv.c.test-chroot4 2025-07-04 11:17:37.598073521 +0200 ++++ shadow-4.18.0/src/grpconv.c 2025-07-04 11:17:37.612354766 +0200 +@@ -39,6 +39,12 @@ + #include "shadowlog.h" + #include "sssd.h" + ++/* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -49,14 +55,14 @@ static bool gr_locked = false; + static bool sgr_locked = false; + + /* local function prototypes */ +-static void fail_exit (int status); ++static void fail_exit (int status, bool process_selinux); + static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + +-static void fail_exit (int status) ++static void fail_exit (int status, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -64,7 +70,7 @@ static void fail_exit (int status) + } + + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -93,7 +99,7 @@ static void usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -112,6 +118,7 @@ static void process_flags (int argc, cha + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + default: + usage (E_USAGE); +@@ -129,6 +136,8 @@ int main (int argc, char **argv) + struct group grent; + const struct sgrp *sg; + struct sgrp sgent; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -141,30 +150,31 @@ int main (int argc, char **argv) + + OPENLOG (Prog); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + if (gr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + if (sgr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + sgr_locked = true; + if (sgr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -183,7 +193,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, sg->sg_namp, sgr_dbname ()); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + (void) sgr_rewind (); + } +@@ -221,7 +231,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, sgr_dbname (), sgent.sg_namp); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + /* remove password from /etc/group */ + grent = *gr; +@@ -230,30 +240,30 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), grent.gr_name); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + } + +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ + } +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +diff -up shadow-4.18.0/src/grpunconv.c.test-chroot4 shadow-4.18.0/src/grpunconv.c +--- shadow-4.18.0/src/grpunconv.c.test-chroot4 2025-07-04 11:17:37.598110132 +0200 ++++ shadow-4.18.0/src/grpunconv.c 2025-07-04 11:17:37.612706894 +0200 +@@ -38,6 +38,12 @@ + #include "sgroupio.h" + #include "shadowlog.h" + ++/* ++ * Structures ++ */ ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -48,14 +54,14 @@ static bool gr_locked = false; + static bool sgr_locked = false; + + /* local function prototypes */ +-static void fail_exit (int status); ++static void fail_exit (int status, bool process_selinux); + static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + +-static void fail_exit (int status) ++static void fail_exit (int status, bool process_selinux) + { + if (gr_locked) { +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ +@@ -63,7 +69,7 @@ static void fail_exit (int status) + } + + if (sgr_locked) { +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ +@@ -92,7 +98,7 @@ static void usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -111,6 +117,7 @@ static void process_flags (int argc, cha + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + default: + usage (E_USAGE); +@@ -127,6 +134,8 @@ int main (int argc, char **argv) + const struct group *gr; + struct group grent; + const struct sgrp *sg; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -139,7 +148,8 @@ int main (int argc, char **argv) + + OPENLOG (Prog); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + if (sgr_file_present () == 0) { + exit (0); /* no /etc/gshadow, nothing to do */ +@@ -149,26 +159,26 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, gr_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + gr_locked = true; + if (gr_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, gr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + if (sgr_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, sgr_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + sgr_locked = true; + if (sgr_open (O_RDONLY) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, sgr_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -186,19 +196,19 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, gr_dbname (), grent.gr_name); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + } + } + +- (void) sgr_close (true); /* was only open O_RDONLY */ ++ (void) sgr_close (process_selinux); /* was only open O_RDONLY */ + +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + + if (unlink (SGROUP_FILE) != 0) { +@@ -206,16 +216,16 @@ int main (int argc, char **argv) + _("%s: cannot delete %s\n"), + Prog, SGROUP_FILE); + SYSLOG ((LOG_ERR, "cannot delete %s", SGROUP_FILE)); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + +- if (gr_unlock (true) == 0) { ++ if (gr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); + /* continue */ + } + +- if (sgr_unlock (true) == 0) { ++ if (sgr_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); + /* continue */ + +From e7634eac3da8b6a2a046b7e8ab6148d07618c7f5 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 11:59:32 +0200 +Subject: [PATCH 01/12] src/chsh.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/chsh.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/src/chsh.c b/src/chsh.c +index 4403d412..f460e329 100644 +--- a/src/chsh.c ++++ b/src/chsh.c +@@ -47,6 +47,9 @@ + #define ETCDIR "/etc" + #endif + ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -66,9 +69,10 @@ NORETURN static void usage (int status); + static void new_fields (void); + static bool shell_is_listed (const char *); + static bool is_restricted_shell (const char *); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_perms (const struct passwd *pw); +-static void update_shell (const char *user, char *loginsh); ++static void update_shell (const char *user, char *loginsh, ++ struct option_flags *flags); + + /* + * fail_exit - do some cleanup and exit with the given error code +@@ -217,7 +221,7 @@ static bool shell_is_listed (const char *sh) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -234,6 +238,7 @@ static void process_flags (int argc, char **argv) + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 's': + sflg = true; +@@ -359,10 +364,13 @@ static void check_perms (const struct passwd *pw) + * + * It will not return in case of error. + */ +-static void update_shell (const char *user, char *newshell) ++static void update_shell (const char *user, char *newshell, struct option_flags *flags) + { + const struct passwd *pw; /* Password entry from /etc/passwd */ + struct passwd pwent; /* New password entry */ ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Before going any further, raise the ulimit to prevent +@@ -428,12 +436,12 @@ static void update_shell (const char *user, char *newshell) + /* + * Changes have all been made, so commit them and unlock the file. + */ +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (1); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -451,6 +459,7 @@ int main (int argc, char **argv) + { + char *user; /* User name */ + const struct passwd *pw; /* Password entry from /etc/passwd */ ++ struct option_flags flags; + + sanitize_env (); + check_fds (); +@@ -472,7 +481,7 @@ int main (int argc, char **argv) + OPENLOG (Prog); + + /* parse the command line options */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + /* + * Get the name of the user to check. It is either the command line +@@ -555,7 +564,7 @@ int main (int argc, char **argv) + } + } + +- update_shell (user, loginsh); ++ update_shell (user, loginsh, &flags); + + SYSLOG ((LOG_INFO, "changed user '%s' shell to '%s'", user, loginsh)); + +-- +2.50.0 + + +From cbcf54b3e5c77a4992bca0ae4f32f0060d120884 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 12:03:30 +0200 +Subject: [PATCH 02/12] src/chsh.c: SELinux file context for fail_exit() + +Do not process SELinux file context when running fail_exit() when chroot +or prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/chsh.c | 45 +++++++++++++++++++++++++-------------------- + 1 file changed, 25 insertions(+), 20 deletions(-) + +diff --git a/src/chsh.c b/src/chsh.c +index f460e329..77cd30e5 100644 +--- a/src/chsh.c ++++ b/src/chsh.c +@@ -64,13 +64,13 @@ static bool pw_locked = false; + /* external identifiers */ + + /* local function prototypes */ +-NORETURN static void fail_exit (int code); ++NORETURN static void fail_exit (int code, bool process_selinux); + NORETURN static void usage (int status); + static void new_fields (void); + static bool shell_is_listed (const char *); + static bool is_restricted_shell (const char *); + static void process_flags (int argc, char **argv, struct option_flags *flags); +-static void check_perms (const struct passwd *pw); ++static void check_perms (const struct passwd *pw, struct option_flags *flags); + static void update_shell (const char *user, char *loginsh, + struct option_flags *flags); + +@@ -79,10 +79,10 @@ static void update_shell (const char *user, char *loginsh, + */ + NORETURN + static void +-fail_exit (int code) ++fail_exit (int code, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -268,13 +268,16 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) + * + * It will not return if the user is not allowed. + */ +-static void check_perms (const struct passwd *pw) ++static void check_perms (const struct passwd *pw, struct option_flags *flags) + { + #ifdef USE_PAM + pam_handle_t *pamh = NULL; + int retval; + struct passwd *pampw; + #endif ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Non-privileged users are only allowed to change the shell if the +@@ -285,7 +288,7 @@ static void check_perms (const struct passwd *pw) + fprintf (stderr, + _("You may not change the shell for '%s'.\n"), + pw->pw_name); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -297,7 +300,7 @@ static void check_perms (const struct passwd *pw) + fprintf (stderr, + _("You may not change the shell for '%s'.\n"), + pw->pw_name); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + #ifdef WITH_SELINUX + /* +@@ -310,7 +313,7 @@ static void check_perms (const struct passwd *pw) + fprintf (stderr, + _("You may not change the shell for '%s'.\n"), + pw->pw_name); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + #endif + +@@ -381,7 +384,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags + if (setuid (0) != 0) { + SYSLOG ((LOG_ERR, "can't setuid(0)")); + fputs (_("Cannot change ID to root.\n"), stderr); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + pwd_init (); + +@@ -392,13 +395,13 @@ static void update_shell (const char *user, char *newshell, struct option_flags + if (pw_lock () == 0) { + fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -412,7 +415,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags + fprintf (stderr, + _("%s: user '%s' does not exist in %s\n"), + Prog, user, pw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -430,7 +433,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + /* +@@ -439,7 +442,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags + if (pw_close (process_selinux) == 0) { + fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); +@@ -460,6 +463,7 @@ int main (int argc, char **argv) + char *user; /* User name */ + const struct passwd *pw; /* Password entry from /etc/passwd */ + struct option_flags flags; ++ bool process_selinux; + + sanitize_env (); + check_fds (); +@@ -482,6 +486,7 @@ int main (int argc, char **argv) + + /* parse the command line options */ + process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + /* + * Get the name of the user to check. It is either the command line +@@ -490,14 +495,14 @@ int main (int argc, char **argv) + if (optind < argc) { + if (!is_valid_user_name (argv[optind])) { + fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + user = argv[optind]; + pw = xgetpwnam (user); + if (NULL == pw) { + fprintf (stderr, + _("%s: user '%s' does not exist\n"), Prog, user); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } else { + pw = get_my_pwent (); +@@ -507,12 +512,12 @@ int main (int argc, char **argv) + Prog); + SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", + (unsigned long) getuid ())); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + user = xstrdup (pw->pw_name); + } + +- check_perms (pw); ++ check_perms (pw, &flags); + + /* + * Now get the login shell. Either get it from the password +@@ -539,7 +544,7 @@ int main (int argc, char **argv) + */ + if (valid_field (loginsh, ":,=\n") != 0) { + fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + if (!streq(loginsh, "") + && (loginsh[0] != '/' +@@ -550,7 +555,7 @@ int main (int argc, char **argv) + fprintf (stderr, _("%s: Warning: %s is an invalid shell\n"), Prog, loginsh); + } else { + fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + } + +-- +2.50.0 + + +From 58600326353a2198df7f8753e2ad8ffa216b68cc Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 12:35:44 +0200 +Subject: [PATCH 03/12] src/passwd.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/passwd.c | 41 ++++++++++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 13 deletions(-) + +diff --git a/src/passwd.c b/src/passwd.c +index 512dc572..6d6f319e 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -53,6 +53,12 @@ + #define E_PWDBUSY 5 /* passwd file busy, try again later */ + #define E_BAD_ARG 6 /* invalid argument to option */ + #define E_PAM_ERR 10 /* PAM returned an error */ ++ ++struct option_flags { ++ bool chroot; ++ bool prefix; ++}; ++ + /* + * Global variables + */ +@@ -131,9 +137,9 @@ static void print_status (const struct passwd *); + NORETURN static void fail_exit (int); + NORETURN static void oom (void); + static char *update_crypt_pw (char *); +-static void update_noshadow (void); ++static void update_noshadow (struct option_flags *flags); + +-static void update_shadow (void); ++static void update_shadow (struct option_flags *flags); + + /* + * usage - print command usage and exit +@@ -549,10 +555,13 @@ static char *update_crypt_pw (char *cp) + } + + +-static void update_noshadow (void) ++static void update_noshadow (struct option_flags *flags) + { + const struct passwd *pw; + struct passwd *npw; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + if (pw_lock () == 0) { + (void) fprintf (stderr, +@@ -586,14 +595,14 @@ static void update_noshadow (void) + Prog, pw_dbname (), npw->pw_name); + fail_exit (E_FAILURE); + } +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); + fail_exit (E_FAILURE); + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +@@ -603,10 +612,13 @@ static void update_noshadow (void) + pw_locked = false; + } + +-static void update_shadow (void) ++static void update_shadow (struct option_flags *flags) + { + const struct spwd *sp; + struct spwd *nsp; ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot && !flags->prefix; + + if (spw_lock () == 0) { + (void) fprintf (stderr, +@@ -625,9 +637,9 @@ static void update_shadow (void) + sp = spw_locate (name); + if (NULL == sp) { + /* Try to update the password in /etc/passwd instead. */ +- (void) spw_close (true); +- update_noshadow (); +- if (spw_unlock (true) == 0) { ++ (void) spw_close (process_selinux); ++ update_noshadow (flags); ++ if (spw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -681,14 +693,14 @@ static void update_shadow (void) + Prog, spw_dbname (), nsp->sp_namp); + fail_exit (E_FAILURE); + } +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (E_FAILURE); + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -733,6 +745,7 @@ main(int argc, char **argv) + char *cp; /* Miscellaneous character pointing */ + + const struct spwd *sp; /* Shadow file entry for user */ ++ struct option_flags flags; + + sanitize_env (); + check_fds (); +@@ -849,8 +862,10 @@ main(int argc, char **argv) + } + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags.chroot = true; + break; + case 'P': /* no-op, handled in process_prefix_flag () */ ++ flags.prefix = true; + break; + case 'S': + Sflg = true; /* ok for users */ +@@ -1107,9 +1122,9 @@ main(int argc, char **argv) + exit (E_NOPERM); + } + if (spw_file_present ()) { +- update_shadow (); ++ update_shadow (&flags); + } else { +- update_noshadow (); ++ update_noshadow (&flags); + } + + nscd_flush_cache ("passwd"); +-- +2.50.0 + + +From d5a9144c809e808600c7dc730970efc04bc032fd Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 12:48:18 +0200 +Subject: [PATCH 04/12] src/passwd.c: SELinux file context for fail_exit() + +Do not process SELinux file context when running fail_exit() when chroot +or prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/passwd.c | 46 ++++++++++++++++++++++++---------------------- + 1 file changed, 24 insertions(+), 22 deletions(-) + +diff --git a/src/passwd.c b/src/passwd.c +index 6d6f319e..78859c96 100644 +--- a/src/passwd.c ++++ b/src/passwd.c +@@ -134,9 +134,9 @@ static int new_password (const struct passwd *); + static void check_password (const struct passwd *, const struct spwd *); + static /*@observer@*/const char *pw_status (const char *); + static void print_status (const struct passwd *); +-NORETURN static void fail_exit (int); +-NORETURN static void oom (void); +-static char *update_crypt_pw (char *); ++NORETURN static void fail_exit (int, bool); ++NORETURN static void oom (bool process_selinux); ++static char *update_crypt_pw (char *, bool); + static void update_noshadow (struct option_flags *flags); + + static void update_shadow (struct option_flags *flags); +@@ -486,10 +486,10 @@ static void print_status (const struct passwd *pw) + + NORETURN + static void +-fail_exit (int status) ++fail_exit (int status, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -497,7 +497,7 @@ fail_exit (int status) + } + + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -509,13 +509,13 @@ fail_exit (int status) + + NORETURN + static void +-oom (void) ++oom (bool process_selinux) + { + (void) fprintf (stderr, _("%s: out of memory\n"), Prog); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + +-static char *update_crypt_pw (char *cp) ++static char *update_crypt_pw (char *cp, bool process_selinux) + { + if (!use_pam) + { +@@ -533,7 +533,7 @@ static char *update_crypt_pw (char *cp) + _("%s: unlocking the password would result in a passwordless account.\n" + "You should set a password with usermod -p to unlock the password of this account.\n"), + Prog); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } else { + cp++; + } +@@ -575,32 +575,32 @@ static void update_noshadow (struct option_flags *flags) + _("%s: cannot open %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); +- fail_exit (E_MISSING); ++ fail_exit (E_MISSING, process_selinux); + } + pw = pw_locate (name); + if (NULL == pw) { + (void) fprintf (stderr, + _("%s: user '%s' does not exist in %s\n"), + Prog, name, pw_dbname ()); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + npw = __pw_dup (pw); + if (NULL == npw) { +- oom (); ++ oom (process_selinux); + } +- npw->pw_passwd = update_crypt_pw (npw->pw_passwd); ++ npw->pw_passwd = update_crypt_pw (npw->pw_passwd, process_selinux); + if (pw_update (npw) == 0) { + (void) fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), npw->pw_name); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + if (pw_close (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + if (pw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, +@@ -632,7 +632,7 @@ static void update_shadow (struct option_flags *flags) + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + sp = spw_locate (name); + if (NULL == sp) { +@@ -651,9 +651,9 @@ static void update_shadow (struct option_flags *flags) + } + nsp = __spw_dup (sp); + if (NULL == nsp) { +- oom (); ++ oom (process_selinux); + } +- nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp); ++ nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp, process_selinux); + if (xflg) { + nsp->sp_max = age_max; + } +@@ -691,14 +691,14 @@ static void update_shadow (struct option_flags *flags) + (void) fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), nsp->sp_namp); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + if (spw_close (process_selinux) == 0) { + (void) fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + if (spw_unlock (process_selinux) == 0) { + (void) fprintf (stderr, +@@ -746,6 +746,7 @@ main(int argc, char **argv) + + const struct spwd *sp; /* Shadow file entry for user */ + struct option_flags flags; ++ bool process_selinux; + + sanitize_env (); + check_fds (); +@@ -912,6 +913,7 @@ main(int argc, char **argv) + } + } + } ++ process_selinux = !flags.chroot && !flags.prefix; + + /* + * Now I have to get the user name. The name will be gotten from the +@@ -931,7 +933,7 @@ main(int argc, char **argv) + if (optind < argc) { + if (!is_valid_user_name (argv[optind])) { + fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); +- fail_exit (E_NOPERM); ++ fail_exit (E_NOPERM, process_selinux); + } + name = argv[optind]; + } else { +-- +2.50.0 + + +From a736c2af5702e98081bace5fde10a264f443d318 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 12:55:35 +0200 +Subject: [PATCH 05/12] src/pwck.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwck.c | 46 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 30 insertions(+), 16 deletions(-) + +diff --git a/src/pwck.c b/src/pwck.c +index 9c4cc29a..d0f2f1c9 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -48,6 +48,10 @@ + #define E_CANTUPDATE 5 + #define E_CANTSORT 6 + ++struct option_flags { ++ bool chroot; ++}; ++ + /* + * Global variables + */ +@@ -71,10 +75,11 @@ static bool quiet = false; /* don't report warnings, only errors */ + /* local function prototypes */ + static void fail_exit (int code); + NORETURN static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void open_files (void); +-static void close_files (bool changed); +-static void check_pw_file (bool *errors, bool *changed); ++static void close_files (bool changed, struct option_flags *flags); ++static void check_pw_file (bool *errors, bool *changed, ++ struct option_flags *flags); + static void check_spw_file (bool *errors, bool *changed); + + extern int allow_bad_names; +@@ -155,7 +160,7 @@ usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -188,6 +193,7 @@ static void process_flags (int argc, char **argv) + read_only = true; + break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 's': + sort_mode = true; +@@ -302,14 +308,18 @@ static void open_files (void) + * changes are committed in the databases. The databases are + * unlocked anyway. + */ +-static void close_files (bool changed) ++static void close_files (bool changed, struct option_flags *flags) + { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; ++ + /* + * All done. If there were no change we can just abandon any + * changes to the files. + */ + if (changed) { +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +@@ -320,7 +330,7 @@ static void close_files (bool changed) + } + fail_exit (E_CANTUPDATE); + } +- if (spw_opened && (spw_close (true) == 0)) { ++ if (spw_opened && (spw_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +@@ -338,7 +348,7 @@ static void close_files (bool changed) + * Don't be anti-social - unlock the files when you're done. + */ + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -351,7 +361,7 @@ static void close_files (bool changed) + } + spw_locked = false; + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, pw_dbname ()); +@@ -368,13 +378,16 @@ static void close_files (bool changed) + /* + * check_pw_file - check the content of the passwd file + */ +-static void check_pw_file (bool *errors, bool *changed) ++static void check_pw_file (bool *errors, bool *changed, struct option_flags *flags) + { + struct commonio_entry *pfe, *tpfe; + struct passwd *pwd; + const struct spwd *spw; + uid_t min_sys_id = getdef_ulong ("SYS_UID_MIN", 101UL); + uid_t max_sys_id = getdef_ulong ("SYS_UID_MAX", 999UL); ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Loop through the entire password file. +@@ -581,7 +594,7 @@ static void check_pw_file (bool *errors, bool *changed) + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); + *errors = true; +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -657,7 +670,7 @@ static void check_pw_file (bool *errors, bool *changed) + } + #ifdef WITH_TCB + if (getdef_bool ("USE_TCB") && spw_locked) { +- if (spw_opened && (spw_close (true) == 0)) { ++ if (spw_opened && (spw_close (process_selinux) == 0)) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); +@@ -669,7 +682,7 @@ static void check_pw_file (bool *errors, bool *changed) + } else { + spw_opened = false; + } +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, + _("%s: failed to unlock %s\n"), + Prog, spw_dbname ()); +@@ -840,6 +853,7 @@ int main (int argc, char **argv) + { + bool errors = false; + bool changed = false; ++ struct option_flags flags; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -853,7 +867,7 @@ int main (int argc, char **argv) + OPENLOG (Prog); + + /* Parse the command line arguments */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + open_files (); + +@@ -874,14 +888,14 @@ int main (int argc, char **argv) + } + changed = true; + } else { +- check_pw_file (&errors, &changed); ++ check_pw_file (&errors, &changed, &flags); + + if (is_shadow) { + check_spw_file (&errors, &changed); + } + } + +- close_files (changed); ++ close_files (changed, &flags); + + if (!read_only) { + nscd_flush_cache ("passwd"); +-- +2.50.0 + + +From 09957a9748ae6cd28e0826d4cacd939ac288ca1b Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 12:58:58 +0200 +Subject: [PATCH 06/12] src/pwck.c: SELinux file context for fail_exit() + +Do not process SELinux file context when running fail_exit() when chroot +or prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwck.c | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/src/pwck.c b/src/pwck.c +index d0f2f1c9..f1e9c085 100644 +--- a/src/pwck.c ++++ b/src/pwck.c +@@ -73,10 +73,10 @@ static bool sort_mode = false; + static bool quiet = false; /* don't report warnings, only errors */ + + /* local function prototypes */ +-static void fail_exit (int code); ++static void fail_exit (int code, bool process_selinux); + NORETURN static void usage (int status); + static void process_flags (int argc, char **argv, struct option_flags *flags); +-static void open_files (void); ++static void open_files (struct option_flags *flags); + static void close_files (bool changed, struct option_flags *flags); + static void check_pw_file (bool *errors, bool *changed, + struct option_flags *flags); +@@ -87,10 +87,10 @@ extern int allow_bad_names; + /* + * fail_exit - do some cleanup and exit with the given error code + */ +-static void fail_exit (int code) ++static void fail_exit (int code, bool process_selinux) + { + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + if (use_system_spw_file) { + SYSLOG ((LOG_ERR, "failed to unlock %s", +@@ -101,7 +101,7 @@ static void fail_exit (int code) + } + + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + if (use_system_pw_file) { + SYSLOG ((LOG_ERR, "failed to unlock %s", +@@ -246,12 +246,15 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) + * In read-only mode, the databases are not locked and are opened + * only for reading. + */ +-static void open_files (void) ++static void open_files (struct option_flags *flags) + { + bool use_tcb = false; + #ifdef WITH_TCB + use_tcb = getdef_bool ("USE_TCB"); + #endif /* WITH_TCB */ ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + /* + * Lock the files if we aren't in "read-only" mode +@@ -261,7 +264,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_CANTLOCK); ++ fail_exit (E_CANTLOCK, process_selinux); + } + pw_locked = true; + if (is_shadow && !use_tcb) { +@@ -269,7 +272,7 @@ static void open_files (void) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_CANTLOCK); ++ fail_exit (E_CANTLOCK, process_selinux); + } + spw_locked = true; + } +@@ -285,7 +288,7 @@ static void open_files (void) + if (use_system_pw_file) { + SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); + } +- fail_exit (E_CANTOPEN); ++ fail_exit (E_CANTOPEN, process_selinux); + } + if (is_shadow && !use_tcb) { + if (spw_open (read_only ? O_RDONLY : O_RDWR) == 0) { +@@ -295,7 +298,7 @@ static void open_files (void) + SYSLOG ((LOG_WARN, "cannot open %s", + spw_dbname ())); + } +- fail_exit (E_CANTOPEN); ++ fail_exit (E_CANTOPEN, process_selinux); + } + spw_opened = true; + } +@@ -328,7 +331,7 @@ static void close_files (bool changed, struct option_flags *flags) + "failure while writing changes to %s", + pw_dbname ())); + } +- fail_exit (E_CANTUPDATE); ++ fail_exit (E_CANTUPDATE, process_selinux); + } + if (spw_opened && (spw_close (process_selinux) == 0)) { + fprintf (stderr, +@@ -339,7 +342,7 @@ static void close_files (bool changed, struct option_flags *flags) + "failure while writing changes to %s", + spw_dbname ())); + } +- fail_exit (E_CANTUPDATE); ++ fail_exit (E_CANTUPDATE, process_selinux); + } + spw_opened = false; + } +@@ -644,7 +647,7 @@ static void check_pw_file (bool *errors, bool *changed, struct option_flags *fla + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), sp.sp_namp); +- fail_exit (E_CANTUPDATE); ++ fail_exit (E_CANTUPDATE, process_selinux); + } + /* remove password from /etc/passwd */ + pw = *pwd; +@@ -653,7 +656,7 @@ static void check_pw_file (bool *errors, bool *changed, struct option_flags *fla + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pw.pw_name); +- fail_exit (E_CANTUPDATE); ++ fail_exit (E_CANTUPDATE, process_selinux); + } + } + } else { +@@ -854,6 +857,7 @@ int main (int argc, char **argv) + bool errors = false; + bool changed = false; + struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -868,22 +872,23 @@ int main (int argc, char **argv) + + /* Parse the command line arguments */ + process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + +- open_files (); ++ open_files (&flags); + + if (sort_mode) { + if (pw_sort () != 0) { + fprintf (stderr, + _("%s: cannot sort entries in %s\n"), + Prog, pw_dbname ()); +- fail_exit (E_CANTSORT); ++ fail_exit (E_CANTSORT, process_selinux); + } + if (is_shadow) { + if (spw_sort () != 0) { + fprintf (stderr, + _("%s: cannot sort entries in %s\n"), + Prog, spw_dbname ()); +- fail_exit (E_CANTSORT); ++ fail_exit (E_CANTSORT, process_selinux); + } + } + changed = true; +-- +2.50.0 + + +From 0c39283e9298fc130c55516fd0a4a0c6b6003bc9 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 13:04:26 +0200 +Subject: [PATCH 07/12] src/pwconv.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwconv.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/src/pwconv.c b/src/pwconv.c +index b0d668b5..6c81cc6e 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -67,6 +67,11 @@ + #define E_MISSING 4 /* unexpected failure, passwd file missing */ + #define E_PWDBUSY 5 /* passwd file(s) busy */ + #define E_BADENTRY 6 /* bad shadow entry */ ++ ++struct option_flags { ++ bool chroot; ++}; ++ + /* + * Global variables + */ +@@ -78,7 +83,7 @@ static bool pw_locked = false; + /* local function prototypes */ + static void fail_exit (int status); + static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + + static void fail_exit (int status) + { +@@ -120,7 +125,7 @@ static void usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -139,6 +144,7 @@ static void process_flags (int argc, char **argv) + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + default: + usage (E_USAGE); +@@ -156,6 +162,8 @@ int main (int argc, char **argv) + struct passwd pwent; + const struct spwd *sp; + struct spwd spent; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -168,7 +176,8 @@ int main (int argc, char **argv) + + OPENLOG (Prog); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + #ifdef WITH_TCB + if (getdef_bool("USE_TCB")) { +@@ -274,14 +283,14 @@ int main (int argc, char **argv) + } + } + +- if (spw_close (true) == 0) { ++ if (spw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); + fail_exit (E_FAILURE); + } +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +@@ -299,13 +308,13 @@ int main (int argc, char **argv) + /* continue */ + } + +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ + } + +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +-- +2.50.0 + + +From 997a523d41bb513f37ca88cab35cba9281f036b6 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 13:05:52 +0200 +Subject: [PATCH 08/12] src/pwconv.c: SELinux file context for fail_exit() + +Do not process SELinux file context when running fail_exit() when chroot +or prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwconv.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/src/pwconv.c b/src/pwconv.c +index 6c81cc6e..1dc1fd86 100644 +--- a/src/pwconv.c ++++ b/src/pwconv.c +@@ -81,14 +81,14 @@ static bool spw_locked = false; + static bool pw_locked = false; + + /* local function prototypes */ +-static void fail_exit (int status); ++static void fail_exit (int status, bool process_selinux); + static void usage (int status); + static void process_flags (int argc, char **argv, struct option_flags *flags); + +-static void fail_exit (int status) ++static void fail_exit (int status, bool process_selinux) + { + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -96,7 +96,7 @@ static void fail_exit (int status) + } + + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ +@@ -190,26 +190,26 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (E_PWDBUSY); ++ fail_exit (E_PWDBUSY, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, pw_dbname ()); +- fail_exit (E_MISSING); ++ fail_exit (E_MISSING, process_selinux); + } + + if (spw_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (E_PWDBUSY); ++ fail_exit (E_PWDBUSY, process_selinux); + } + spw_locked = true; + if (spw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), Prog, spw_dbname ()); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + + /* +@@ -228,7 +228,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot remove entry '%s' from %s\n"), + Prog, sp->sp_namp, spw_dbname ()); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + (void) spw_rewind(); + } +@@ -269,7 +269,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, spw_dbname (), spent.sp_namp); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + + /* remove password from /etc/passwd */ +@@ -279,7 +279,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + } + +@@ -288,14 +288,14 @@ int main (int argc, char **argv) + _("%s: failure while writing changes to %s\n"), + Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (E_FAILURE); ++ fail_exit (E_FAILURE, process_selinux); + } + + /* /etc/passwd- (backup file) */ +-- +2.50.0 + + +From 13e902a1b368049cb4c6853a7470f66efbac6e72 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 13:08:10 +0200 +Subject: [PATCH 09/12] src/pwunconv.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwunconv.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/src/pwunconv.c b/src/pwunconv.c +index 7a6d2be5..d46bde6d 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -30,6 +30,9 @@ + #include "sssd.h" + #include "string/strcmp/streq.h" + ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -42,7 +45,7 @@ static bool pw_locked = false; + /* local function prototypes */ + static void fail_exit (int status); + static void usage (int status); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + + static void fail_exit (int status) + { +@@ -82,7 +85,7 @@ static void usage (int status) + * + * It will not return if an error is encountered. + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + /* + * Parse the command line options. +@@ -101,6 +104,7 @@ static void process_flags (int argc, char **argv) + usage (E_SUCCESS); + /*@notreached@*/break; + case 'R': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + default: + usage (E_USAGE); +@@ -117,6 +121,8 @@ int main (int argc, char **argv) + const struct passwd *pw; + struct passwd pwent; + const struct spwd *spwd; ++ struct option_flags flags; ++ bool process_selinux; + + log_set_progname(Prog); + log_set_logfd(stderr); +@@ -129,7 +135,8 @@ int main (int argc, char **argv) + + OPENLOG (Prog); + +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); ++ process_selinux = !flags.chroot; + + #ifdef WITH_TCB + if (getdef_bool("USE_TCB")) { +@@ -205,9 +212,9 @@ int main (int argc, char **argv) + } + } + +- (void) spw_close (true); /* was only open O_RDONLY */ ++ (void) spw_close (process_selinux); /* was only open O_RDONLY */ + +- if (pw_close (true) == 0) { ++ if (pw_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); +@@ -222,12 +229,12 @@ int main (int argc, char **argv) + fail_exit (3); + } + +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +-- +2.50.0 + + +From 849e748fe08129684da13acba13a247f0aa98eff Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 13:09:12 +0200 +Subject: [PATCH 10/12] src/pwunconv.c: SELinux file context for fail_exit() + +Do not process SELinux file context when running fail_exit() when chroot +or prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/pwunconv.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/pwunconv.c b/src/pwunconv.c +index d46bde6d..d3e10f68 100644 +--- a/src/pwunconv.c ++++ b/src/pwunconv.c +@@ -43,21 +43,21 @@ static bool spw_locked = false; + static bool pw_locked = false; + + /* local function prototypes */ +-static void fail_exit (int status); ++static void fail_exit (int status, bool process_selinux); + static void usage (int status); + static void process_flags (int argc, char **argv, struct option_flags *flags); + +-static void fail_exit (int status) ++static void fail_exit (int status, bool process_selinux) + { + if (spw_locked) { +- if (spw_unlock (true) == 0) { ++ if (spw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); + /* continue */ + } + } + if (pw_locked) { +- if (pw_unlock (true) == 0) { ++ if (pw_unlock (process_selinux) == 0) { + fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); + /* continue */ +@@ -154,28 +154,28 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, pw_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + pw_locked = true; + if (pw_open (O_CREAT | O_RDWR) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, pw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + if (spw_lock () == 0) { + fprintf (stderr, + _("%s: cannot lock %s; try again later.\n"), + Prog, spw_dbname ()); +- fail_exit (5); ++ fail_exit (5, process_selinux); + } + spw_locked = true; + if (spw_open (O_RDONLY) == 0) { + fprintf (stderr, + _("%s: cannot open %s\n"), + Prog, spw_dbname ()); +- fail_exit (1); ++ fail_exit (1, process_selinux); + } + + (void) pw_rewind (); +@@ -208,7 +208,7 @@ int main (int argc, char **argv) + fprintf (stderr, + _("%s: failed to prepare the new %s entry '%s'\n"), + Prog, pw_dbname (), pwent.pw_name); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + } + +@@ -219,14 +219,14 @@ int main (int argc, char **argv) + _("%s: failure while writing changes to %s\n"), + Prog, pw_dbname ()); + SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + + if (unlink (SHADOW) != 0) { + fprintf (stderr, + _("%s: cannot delete %s\n"), Prog, SHADOW); + SYSLOG ((LOG_ERR, "cannot delete %s", SHADOW)); +- fail_exit (3); ++ fail_exit (3, process_selinux); + } + + if (spw_unlock (process_selinux) == 0) { +-- +2.50.0 + + +From b1bcf1cf8245b195cff7586770ad861f89cb7c92 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 3 Jul 2025 14:29:55 +0200 +Subject: [PATCH 11/12] src/gpasswd.c: chroot or prefix SELinux file context + +Do not process SELinux file context during file closure when chroot or +prefix options are selected. + +Signed-off-by: Iker Pedrosa +--- + src/gpasswd.c | 44 ++++++++++++++++++++++++++++---------------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +diff --git a/src/gpasswd.c b/src/gpasswd.c +index a49b9140..94b2bb32 100644 +--- a/src/gpasswd.c ++++ b/src/gpasswd.c +@@ -40,6 +40,9 @@ + #include "string/strcpy/strtcpy.h" + #include "string/strdup/xstrdup.h" + ++struct option_flags { ++ bool chroot; ++}; + + /* + * Global variables +@@ -87,17 +90,17 @@ NORETURN static void failure(void); + static void usage (int status); + static void catch_signals (int killed); + static bool is_valid_user_list (const char *users); +-static void process_flags (int argc, char **argv); ++static void process_flags (int argc, char **argv, struct option_flags *flags); + static void check_flags (int argc, int opt_index); + static void open_files (void); +-static void close_files (void); ++static void close_files (struct option_flags *flags); + #ifdef SHADOWGRP +-static void get_group (struct group *gr, struct sgrp *sg); ++static void get_group (struct group *gr, struct sgrp *sg, struct option_flags *flags); + static void check_perms (const struct group *gr, const struct sgrp *sg); + static void update_group (struct group *gr, struct sgrp *sg); + static void change_passwd (struct group *gr, struct sgrp *sg); + #else +-static void get_group (struct group *gr); ++static void get_group (struct group *gr, struct option_flags *flags); + static void check_perms (const struct group *gr); + static void update_group (struct group *gr); + static void change_passwd (struct group *gr); +@@ -211,7 +214,7 @@ static void failure(void) + /* + * process_flags - process the command line options and arguments + */ +-static void process_flags (int argc, char **argv) ++static void process_flags (int argc, char **argv, struct option_flags *flags) + { + int c; + static struct option long_options[] = { +@@ -272,6 +275,7 @@ static void process_flags (int argc, char **argv) + Mflg = true; + break; + case 'Q': /* no-op, handled in process_root_flag () */ ++ flags->chroot = true; + break; + case 'r': /* remove group password */ + rflg = true; +@@ -591,9 +595,13 @@ static void log_gpasswd_success_group (MAYBE_UNUSED void *arg) + * + * It will call exit in case of error. + */ +-static void close_files (void) ++static void close_files (struct option_flags *flags) + { +- if (gr_close (true) == 0) { ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; ++ ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, gr_dbname ()); +@@ -607,7 +615,7 @@ static void close_files (void) + + #ifdef SHADOWGRP + if (is_shadowgrp) { +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while writing changes to %s\n"), + Prog, sgr_dbname ()); +@@ -695,15 +703,18 @@ static void update_group (struct group *gr) + * Note: If !is_shadowgrp, *sg will not be initialized. + */ + #ifdef SHADOWGRP +-static void get_group (struct group *gr, struct sgrp *sg) ++static void get_group (struct group *gr, struct sgrp *sg, struct option_flags *flags) + #else +-static void get_group (struct group *gr) ++static void get_group (struct group *gr, struct option_flags *flags) + #endif + { + struct group const*tmpgr = NULL; + #ifdef SHADOWGRP + struct sgrp const*tmpsg = NULL; + #endif ++ bool process_selinux; ++ ++ process_selinux = !flags->chroot; + + if (gr_open (O_RDONLY) == 0) { + fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); +@@ -724,7 +735,7 @@ static void get_group (struct group *gr) + gr->gr_passwd = xstrdup (tmpgr->gr_passwd); + gr->gr_mem = dup_list (tmpgr->gr_mem); + +- if (gr_close (true) == 0) { ++ if (gr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while closing read-only %s\n"), + Prog, gr_dbname ()); +@@ -762,7 +773,7 @@ static void get_group (struct group *gr) + sg->sg_adm[0] = NULL; + + } +- if (sgr_close (true) == 0) { ++ if (sgr_close (process_selinux) == 0) { + fprintf (stderr, + _("%s: failure while closing read-only %s\n"), + Prog, sgr_dbname ()); +@@ -864,6 +875,7 @@ int main (int argc, char **argv) + struct sgrp sgent; + #endif + struct passwd *pw = NULL; ++ struct option_flags flags; + + #ifdef WITH_AUDIT + audit_help_open (); +@@ -924,15 +936,15 @@ int main (int argc, char **argv) + } + + /* Parse the options */ +- process_flags (argc, argv); ++ process_flags (argc, argv, &flags); + + /* + * Replicate the group so it can be modified later on. + */ + #ifdef SHADOWGRP +- get_group (&grent, &sgent); ++ get_group (&grent, &sgent, &flags); + #else +- get_group (&grent); ++ get_group (&grent, &flags); + #endif + + /* +@@ -1095,7 +1107,7 @@ int main (int argc, char **argv) + update_group (&grent); + #endif + +- close_files (); ++ close_files (&flags); + + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_GROUP); +-- +2.50.0 + + +From 2c250fae8866a682bac686dcaa198b325d198cf9 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Fri, 4 Jul 2025 10:03:42 +0200 +Subject: [PATCH 12/12] man/: update `--root` flag with no SELinux support + +Signed-off-by: Iker Pedrosa +--- + man/chage.1.xml | 1 + + man/chfn.1.xml | 1 + + man/chgpasswd.8.xml | 1 + + man/chpasswd.8.xml | 1 + + man/chsh.1.xml | 1 + + man/faillog.8.xml | 1 + + man/gpasswd.1.xml | 1 + + man/groupadd.8.xml | 1 + + man/groupdel.8.xml | 1 + + man/groupmems.8.xml | 1 + + man/groupmod.8.xml | 1 + + man/grpck.8.xml | 1 + + man/lastlog.8.xml | 1 + + man/newusers.8.xml | 1 + + man/passwd.1.xml | 1 + + man/pwck.8.xml | 1 + + man/pwconv.8.xml | 1 + + man/useradd.8.xml | 1 + + man/userdel.8.xml | 1 + + man/usermod.8.xml | 1 + + man/vipw.8.xml | 1 + + 21 files changed, 21 insertions(+) + +diff --git a/man/chage.1.xml b/man/chage.1.xml +index 4ccdf483..a3fff291 100644 +--- a/man/chage.1.xml ++++ b/man/chage.1.xml +@@ -205,6 +205,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/chfn.1.xml b/man/chfn.1.xml +index 2fa49feb..d199ef03 100644 +--- a/man/chfn.1.xml ++++ b/man/chfn.1.xml +@@ -138,6 +138,7 @@ + Apply changes in the CHROOT_DIR + directory and use the configuration files from the + CHROOT_DIR directory. ++ No SELINUX support. + + + +diff --git a/man/chgpasswd.8.xml b/man/chgpasswd.8.xml +index f4a83c24..184c1696 100644 +--- a/man/chgpasswd.8.xml ++++ b/man/chgpasswd.8.xml +@@ -134,6 +134,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/chpasswd.8.xml b/man/chpasswd.8.xml +index cffd9df1..440c8342 100644 +--- a/man/chpasswd.8.xml ++++ b/man/chpasswd.8.xml +@@ -176,6 +176,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/chsh.1.xml b/man/chsh.1.xml +index db2d0ceb..8f253731 100644 +--- a/man/chsh.1.xml ++++ b/man/chsh.1.xml +@@ -89,6 +89,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/faillog.8.xml b/man/faillog.8.xml +index effe43a9..7d453fd2 100644 +--- a/man/faillog.8.xml ++++ b/man/faillog.8.xml +@@ -162,6 +162,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/gpasswd.1.xml b/man/gpasswd.1.xml +index 9b89d915..f918442f 100644 +--- a/man/gpasswd.1.xml ++++ b/man/gpasswd.1.xml +@@ -165,6 +165,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/groupadd.8.xml b/man/groupadd.8.xml +index 9abf159a..2dea7ae5 100644 +--- a/man/groupadd.8.xml ++++ b/man/groupadd.8.xml +@@ -206,6 +206,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/groupdel.8.xml b/man/groupdel.8.xml +index 8d41b883..31f29994 100644 +--- a/man/groupdel.8.xml ++++ b/man/groupdel.8.xml +@@ -94,6 +94,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/groupmems.8.xml b/man/groupmems.8.xml +index cbc84622..0def6c99 100644 +--- a/man/groupmems.8.xml ++++ b/man/groupmems.8.xml +@@ -147,6 +147,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/groupmod.8.xml b/man/groupmod.8.xml +index 2d51f271..ca287441 100644 +--- a/man/groupmod.8.xml ++++ b/man/groupmod.8.xml +@@ -169,6 +169,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/grpck.8.xml b/man/grpck.8.xml +index 31aa6ca3..9feb190e 100644 +--- a/man/grpck.8.xml ++++ b/man/grpck.8.xml +@@ -154,6 +154,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml +index cefe5ac2..b0589203 100644 +--- a/man/lastlog.8.xml ++++ b/man/lastlog.8.xml +@@ -109,6 +109,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/newusers.8.xml b/man/newusers.8.xml +index 6812c750..e0380608 100644 +--- a/man/newusers.8.xml ++++ b/man/newusers.8.xml +@@ -313,6 +313,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/passwd.1.xml b/man/passwd.1.xml +index 65dca040..def35609 100644 +--- a/man/passwd.1.xml ++++ b/man/passwd.1.xml +@@ -279,6 +279,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/pwck.8.xml b/man/pwck.8.xml +index 4eb820d6..998bb44a 100644 +--- a/man/pwck.8.xml ++++ b/man/pwck.8.xml +@@ -202,6 +202,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/pwconv.8.xml b/man/pwconv.8.xml +index c4aedef6..9be3f7c5 100644 +--- a/man/pwconv.8.xml ++++ b/man/pwconv.8.xml +@@ -183,6 +183,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/useradd.8.xml b/man/useradd.8.xml +index fd9ff697..e6db7f6d 100644 +--- a/man/useradd.8.xml ++++ b/man/useradd.8.xml +@@ -515,6 +515,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/userdel.8.xml b/man/userdel.8.xml +index 32851f11..de8eff24 100644 +--- a/man/userdel.8.xml ++++ b/man/userdel.8.xml +@@ -120,6 +120,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/usermod.8.xml b/man/usermod.8.xml +index 61b5e3a9..2c704ab5 100644 +--- a/man/usermod.8.xml ++++ b/man/usermod.8.xml +@@ -337,6 +337,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +diff --git a/man/vipw.8.xml b/man/vipw.8.xml +index fb80582b..975fba37 100644 +--- a/man/vipw.8.xml ++++ b/man/vipw.8.xml +@@ -120,6 +120,7 @@ + directory and use the configuration files from the + CHROOT_DIR directory. + Only absolute paths are supported. ++ No SELINUX support. + + + +-- +2.50.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 34baef4..e406acd 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.18.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -24,6 +24,8 @@ Source7: passwd.pamd Patch0: shadow-4.15.0-manfix.patch # Probably non-upstreamable Patch1: shadow-4.18.0-account-tools-setuid.patch +# https://github.com/shadow-maint/shadow/commit/db0e0b9112332a45131912021317ab5ab4fd6e40 +Patch2: shadow-4.18.0-selinux-chroot-prefix.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -269,6 +271,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Oct 31 2025 Iker Pedrosa - 2:4.18.0-4 +- Stop setting SELinux labels in chroot and prefix environments + Resolves: #2249524 + * Tue Jul 29 2025 Alexey Tikhonov - 2:4.18.0-3 - Revert "Stop assigning subids by default" Resolves: #2382662 From 20b52960271fc47cb5b8bbcd2a20954bc10f402b Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 25 Nov 2025 10:30:54 +0100 Subject: [PATCH 099/118] Test CI Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 7 ++++++- test.patch | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 test.patch diff --git a/shadow-utils.spec b/shadow-utils.spec index e406acd..cf4fbf3 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.18.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,6 +26,8 @@ Patch0: shadow-4.15.0-manfix.patch Patch1: shadow-4.18.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/db0e0b9112332a45131912021317ab5ab4fd6e40 Patch2: shadow-4.18.0-selinux-chroot-prefix.patch +# Test patch +Patch3: test.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -271,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Nov 25 2025 Iker Pedrosa - 2:4.18.0-5 +- Test CI + * Fri Oct 31 2025 Iker Pedrosa - 2:4.18.0-4 - Stop setting SELinux labels in chroot and prefix environments Resolves: #2249524 diff --git a/test.patch b/test.patch new file mode 100644 index 0000000..346d1b1 --- /dev/null +++ b/test.patch @@ -0,0 +1,26 @@ +From 012684d388881727d6ce457d710a03d6df216409 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Tue, 25 Nov 2025 09:52:03 +0100 +Subject: [PATCH] Test + +Signed-off-by: Iker Pedrosa +--- + src/useradd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/useradd.c b/src/useradd.c +index f7e46d6b..e2e95693 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -2440,7 +2440,7 @@ int main (int argc, char **argv) + #endif + unsigned long subuid_count = 0; + unsigned long subgid_count = 0; +- struct option_flags flags; ++ struct option_flags flags = {0}; + bool process_selinux; + + log_set_progname(Prog); +-- +2.52.0 + From 71c7bce53c2f1bb06b9eb5c9a23c9fecb17eeb61 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 25 Nov 2025 10:08:41 -0800 Subject: [PATCH 100/118] Revert changes from -5 (they were only meant for testing) --- shadow-utils.spec | 7 ++++--- test.patch | 26 -------------------------- 2 files changed, 4 insertions(+), 29 deletions(-) delete mode 100644 test.patch diff --git a/shadow-utils.spec b/shadow-utils.spec index cf4fbf3..483eb21 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.18.0 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,8 +26,6 @@ Patch0: shadow-4.15.0-manfix.patch Patch1: shadow-4.18.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/db0e0b9112332a45131912021317ab5ab4fd6e40 Patch2: shadow-4.18.0-selinux-chroot-prefix.patch -# Test patch -Patch3: test.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -273,6 +271,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Nov 25 2025 Adam Williamson - 2:4.18.0-6 +- Revert changes from -5 (they were only meant for testing) + * Tue Nov 25 2025 Iker Pedrosa - 2:4.18.0-5 - Test CI diff --git a/test.patch b/test.patch deleted file mode 100644 index 346d1b1..0000000 --- a/test.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 012684d388881727d6ce457d710a03d6df216409 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Tue, 25 Nov 2025 09:52:03 +0100 -Subject: [PATCH] Test - -Signed-off-by: Iker Pedrosa ---- - src/useradd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/useradd.c b/src/useradd.c -index f7e46d6b..e2e95693 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -2440,7 +2440,7 @@ int main (int argc, char **argv) - #endif - unsigned long subuid_count = 0; - unsigned long subgid_count = 0; -- struct option_flags flags; -+ struct option_flags flags = {0}; - bool process_selinux; - - log_set_progname(Prog); --- -2.52.0 - From 8953fddc447d650561e9786be46815400352e4af Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 25 Nov 2025 12:50:30 -0800 Subject: [PATCH 101/118] Also revert changes from -4 (last known good was -3) --- shadow-4.18.0-selinux-chroot-prefix.patch | 10433 -------------------- shadow-utils.spec | 5 +- 2 files changed, 3 insertions(+), 10435 deletions(-) delete mode 100644 shadow-4.18.0-selinux-chroot-prefix.patch diff --git a/shadow-4.18.0-selinux-chroot-prefix.patch b/shadow-4.18.0-selinux-chroot-prefix.patch deleted file mode 100644 index a5db17b..0000000 --- a/shadow-4.18.0-selinux-chroot-prefix.patch +++ /dev/null @@ -1,10433 +0,0 @@ -From 218cc94da84459bfa5b8417d933e8898e24ecff6 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:13:12 +0200 -Subject: [PATCH 01/15] lib/: add SELinux control flag in commonio_close() - -Expand commonio_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/commonio.c | 16 ++++++++++------ - lib/commonio.h | 2 +- - lib/groupio.c | 2 +- - lib/pwio.c | 2 +- - lib/sgroupio.c | 2 +- - lib/shadowio.c | 2 +- - lib/subordinateio.c | 4 ++-- - 7 files changed, 17 insertions(+), 13 deletions(-) - -diff --git a/lib/commonio.c b/lib/commonio.c -index 7304ec00..7ee6df4d 100644 ---- a/lib/commonio.c -+++ b/lib/commonio.c -@@ -473,7 +473,7 @@ int commonio_unlock (struct commonio_db *db) - - if (db->isopen) { - db->readonly = true; -- if (commonio_close (db) == 0) { -+ if (commonio_close (db, true) == 0) { - if (db->locked) { - dec_lock_count (); - } -@@ -885,7 +885,7 @@ static int write_all (const struct commonio_db *db) - } - - --int commonio_close (struct commonio_db *db) -+int commonio_close (struct commonio_db *db, bool process_selinux) - { - bool errors = false; - char buf[1024]; -@@ -927,7 +927,8 @@ int commonio_close (struct commonio_db *db) - } - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (db->filename, S_IFREG) != 0) { -+ if (process_selinux -+ && set_selinux_file_context (db->filename, S_IFREG) != 0) { - errors = true; - } - #endif -@@ -942,7 +943,8 @@ int commonio_close (struct commonio_db *db) - db->fp = NULL; - - #ifdef WITH_SELINUX -- if (reset_selinux_file_context () != 0) { -+ if (process_selinux -+ && reset_selinux_file_context () != 0) { - errors = true; - } - #endif -@@ -961,7 +963,8 @@ int commonio_close (struct commonio_db *db) - goto fail; - - #ifdef WITH_SELINUX -- if (set_selinux_file_context (db->filename, S_IFREG) != 0) { -+ if (process_selinux -+ && set_selinux_file_context (db->filename, S_IFREG) != 0) { - errors = true; - } - #endif -@@ -999,7 +1002,8 @@ int commonio_close (struct commonio_db *db) - } - - #ifdef WITH_SELINUX -- if (reset_selinux_file_context () != 0) { -+ if (process_selinux -+ && reset_selinux_file_context () != 0) { - goto fail; - } - #endif -diff --git a/lib/commonio.h b/lib/commonio.h -index fedbefa3..dadc0500 100644 ---- a/lib/commonio.h -+++ b/lib/commonio.h -@@ -138,7 +138,7 @@ extern int commonio_append (struct commonio_db *, const void *); - extern int commonio_remove (struct commonio_db *, const char *); - extern int commonio_rewind (struct commonio_db *); - extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); --extern int commonio_close (struct commonio_db *); -+extern int commonio_close (struct commonio_db *, bool); - extern int commonio_unlock (struct commonio_db *); - extern void commonio_del_entry (struct commonio_db *, - const struct commonio_entry *); -diff --git a/lib/groupio.c b/lib/groupio.c -index 72391433..5076fd3d 100644 ---- a/lib/groupio.c -+++ b/lib/groupio.c -@@ -186,7 +186,7 @@ int gr_rewind (void) - - int gr_close (void) - { -- return commonio_close (&group_db); -+ return commonio_close (&group_db, true); - } - - int gr_unlock (void) -diff --git a/lib/pwio.c b/lib/pwio.c -index 415447d6..6f666ec6 100644 ---- a/lib/pwio.c -+++ b/lib/pwio.c -@@ -158,7 +158,7 @@ int pw_rewind (void) - - int pw_close (void) - { -- return commonio_close (&passwd_db); -+ return commonio_close (&passwd_db, true); - } - - int pw_unlock (void) -diff --git a/lib/sgroupio.c b/lib/sgroupio.c -index ef82976d..659dcd06 100644 ---- a/lib/sgroupio.c -+++ b/lib/sgroupio.c -@@ -278,7 +278,7 @@ int sgr_rewind (void) - - int sgr_close (void) - { -- return commonio_close (&gshadow_db); -+ return commonio_close (&gshadow_db, true); - } - - int sgr_unlock (void) -diff --git a/lib/shadowio.c b/lib/shadowio.c -index 8b1c1d2c..55d33da2 100644 ---- a/lib/shadowio.c -+++ b/lib/shadowio.c -@@ -195,7 +195,7 @@ int spw_close (void) - return 0; - } - #endif /* WITH_TCB */ -- retval = commonio_close (&shadow_db); -+ retval = commonio_close (&shadow_db, true); - #ifdef WITH_TCB - if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { - return 0; -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 27f888b9..3638ec61 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -670,7 +670,7 @@ int sub_uid_remove (const char *owner, uid_t start, unsigned long count) - - int sub_uid_close (void) - { -- return commonio_close (&subordinate_uid_db); -+ return commonio_close (&subordinate_uid_db, true); - } - - int sub_uid_unlock (void) -@@ -777,7 +777,7 @@ int sub_gid_remove (const char *owner, gid_t start, unsigned long count) - - int sub_gid_close (void) - { -- return commonio_close (&subordinate_gid_db); -+ return commonio_close (&subordinate_gid_db, true); - } - - int sub_gid_unlock (void) --- -2.50.0 - - -From 7e7dbe0e65d2795c15c42bb04c7c03b9ff86ea84 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:19:29 +0200 -Subject: [PATCH 02/15] lib/, src/: add SELinux control flag in pw_close() - -Expand pw_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/pwio.c | 4 ++-- - lib/pwio.h | 3 ++- - src/chage.c | 2 +- - src/chfn.c | 2 +- - src/chpasswd.c | 2 +- - src/chsh.c | 2 +- - src/groupmod.c | 2 +- - src/newusers.c | 2 +- - src/passwd.c | 2 +- - src/pwck.c | 2 +- - src/pwconv.c | 2 +- - src/pwunconv.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 6 +++--- - src/usermod.c | 2 +- - 15 files changed, 19 insertions(+), 18 deletions(-) - -diff --git a/lib/pwio.c b/lib/pwio.c -index 6f666ec6..c5c1cdb1 100644 ---- a/lib/pwio.c -+++ b/lib/pwio.c -@@ -156,9 +156,9 @@ int pw_rewind (void) - return commonio_next (&passwd_db); - } - --int pw_close (void) -+int pw_close (bool process_selinux) - { -- return commonio_close (&passwd_db, true); -+ return commonio_close (&passwd_db, process_selinux); - } - - int pw_unlock (void) -diff --git a/lib/pwio.h b/lib/pwio.h -index 882a7c7a..b051a7e7 100644 ---- a/lib/pwio.h -+++ b/lib/pwio.h -@@ -14,8 +14,9 @@ - - #include - #include -+#include - --extern int pw_close (void); -+extern int pw_close (bool process_selinux); - extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate (const char *name); - extern /*@observer@*/ /*@null@*/const struct passwd *pw_locate_uid (uid_t uid); - extern int pw_lock (void); -diff --git a/src/chage.c b/src/chage.c -index 4b9c96d6..1ebe34c5 100644 ---- a/src/chage.c -+++ b/src/chage.c -@@ -557,7 +557,7 @@ static void close_files (void) - * Close the password file. If any entries were modified, the file - * will be re-written. - */ -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_NOPERM); -diff --git a/src/chfn.c b/src/chfn.c -index 58502929..abf88cc8 100644 ---- a/src/chfn.c -+++ b/src/chfn.c -@@ -493,7 +493,7 @@ static void update_gecos (const char *user, char *gecos) - /* - * Changes have all been made, so commit them and unlock the file. - */ -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_NOPERM); -diff --git a/src/chpasswd.c b/src/chpasswd.c -index 315e91ce..17f3d6d5 100644 ---- a/src/chpasswd.c -+++ b/src/chpasswd.c -@@ -393,7 +393,7 @@ static void close_files (void) - spw_locked = false; - } - -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/chsh.c b/src/chsh.c -index 236ff784..b5ae28da 100644 ---- a/src/chsh.c -+++ b/src/chsh.c -@@ -428,7 +428,7 @@ static void update_shell (const char *user, char *newshell) - /* - * Changes have all been made, so commit them and unlock the file. - */ -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (1); -diff --git a/src/groupmod.c b/src/groupmod.c -index cce6fd49..14b7e746 100644 ---- a/src/groupmod.c -+++ b/src/groupmod.c -@@ -534,7 +534,7 @@ static void close_files (void) - #endif /* SHADOWGRP */ - - if (gflg) { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/newusers.c b/src/newusers.c -index 38cbdddb..a738f944 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -939,7 +939,7 @@ static void open_files (void) - */ - static void close_files (void) - { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (EXIT_FAILURE); -diff --git a/src/passwd.c b/src/passwd.c -index cdd817a2..8bdff6dd 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -586,7 +586,7 @@ static void update_noshadow (void) - Prog, pw_dbname (), npw->pw_name); - fail_exit (E_FAILURE); - } -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/pwck.c b/src/pwck.c -index 6272839f..b1c6970f 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -309,7 +309,7 @@ static void close_files (bool changed) - * changes to the files. - */ - if (changed) { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/pwconv.c b/src/pwconv.c -index 1bb92752..da3a5820 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -281,7 +281,7 @@ int main (int argc, char **argv) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_FAILURE); - } -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/pwunconv.c b/src/pwunconv.c -index 2e4d3d75..8423cda4 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -207,7 +207,7 @@ int main (int argc, char **argv) - - (void) spw_close (); /* was only open O_RDONLY */ - -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -diff --git a/src/useradd.c b/src/useradd.c -index 36b9b8f8..8c9e9003 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1564,7 +1564,7 @@ static void process_flags (int argc, char **argv) - */ - static void close_files (void) - { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_PW_UPDATE); -diff --git a/src/userdel.c b/src/userdel.c -index 72ce11fa..b5a02b3c 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -390,7 +390,7 @@ static void remove_usergroup (void) - */ - static void close_files (void) - { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_PW_UPDATE); -@@ -1046,7 +1046,7 @@ int main (int argc, char **argv) - pw_open(O_RDONLY); - pwd = pw_locate (user_name); /* we care only about local users */ - if (NULL == pwd) { -- pw_close(); -+ pw_close(true); - fprintf (stderr, _("%s: user '%s' does not exist\n"), - Prog, user_name); - #ifdef WITH_AUDIT -@@ -1065,7 +1065,7 @@ int main (int argc, char **argv) - } else { - user_home = xstrdup(pwd->pw_dir); - } -- pw_close(); -+ pw_close(true); - } - #ifdef WITH_TCB - if (shadowtcb_set_user (user_name) == SHADOWTCB_FAILURE) { -diff --git a/src/usermod.c b/src/usermod.c -index a0f4d7dd..180b7da0 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1469,7 +1469,7 @@ process_flags(int argc, char **argv) - */ - static void close_files (void) - { -- if (pw_close () == 0) { -+ if (pw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); --- -2.50.0 - - -From abffb267659bb1f9d49af5cba69c7a9ba2489e3d Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:23:11 +0200 -Subject: [PATCH 03/15] lib/, src/: add SELinux control flag in spw_close() - -Expand spw_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/shadowio.c | 4 ++-- - lib/shadowio.h | 2 +- - src/chage.c | 2 +- - src/chpasswd.c | 2 +- - src/newusers.c | 2 +- - src/passwd.c | 4 ++-- - src/pwck.c | 4 ++-- - src/pwconv.c | 2 +- - src/pwunconv.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 2 +- - src/usermod.c | 2 +- - 12 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/lib/shadowio.c b/lib/shadowio.c -index 55d33da2..a109576d 100644 ---- a/lib/shadowio.c -+++ b/lib/shadowio.c -@@ -185,7 +185,7 @@ int spw_rewind (void) - return commonio_next (&shadow_db); - } - --int spw_close (void) -+int spw_close (bool process_selinux) - { - int retval = 0; - #ifdef WITH_TCB -@@ -195,7 +195,7 @@ int spw_close (void) - return 0; - } - #endif /* WITH_TCB */ -- retval = commonio_close (&shadow_db, true); -+ retval = commonio_close (&shadow_db, process_selinux); - #ifdef WITH_TCB - if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { - return 0; -diff --git a/lib/shadowio.h b/lib/shadowio.h -index 4dbeb6d6..e64d8d60 100644 ---- a/lib/shadowio.h -+++ b/lib/shadowio.h -@@ -13,7 +13,7 @@ - - #include "defines.h" - --extern int spw_close (void); -+extern int spw_close (bool process_selinux); - extern bool spw_file_present (void); - extern /*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name); - extern int spw_lock (void); -diff --git a/src/chage.c b/src/chage.c -index 1ebe34c5..a59428c5 100644 ---- a/src/chage.c -+++ b/src/chage.c -@@ -546,7 +546,7 @@ static void close_files (void) - * Now close the shadow password file, which will cause all of the - * entries to be re-written. - */ -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -diff --git a/src/chpasswd.c b/src/chpasswd.c -index 17f3d6d5..e3d8dcef 100644 ---- a/src/chpasswd.c -+++ b/src/chpasswd.c -@@ -378,7 +378,7 @@ static void open_files (void) - static void close_files (void) - { - if (is_shadow_pwd) { -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -diff --git a/src/newusers.c b/src/newusers.c -index a738f944..43672dd2 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -952,7 +952,7 @@ static void close_files (void) - pw_locked = false; - - if (is_shadow) { -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -diff --git a/src/passwd.c b/src/passwd.c -index 8bdff6dd..01efb285 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -625,7 +625,7 @@ static void update_shadow (void) - sp = spw_locate (name); - if (NULL == sp) { - /* Try to update the password in /etc/passwd instead. */ -- (void) spw_close (); -+ (void) spw_close (true); - update_noshadow (); - if (spw_unlock () == 0) { - (void) fprintf (stderr, -@@ -681,7 +681,7 @@ static void update_shadow (void) - Prog, spw_dbname (), nsp->sp_namp); - fail_exit (E_FAILURE); - } -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -diff --git a/src/pwck.c b/src/pwck.c -index b1c6970f..718b639f 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -320,7 +320,7 @@ static void close_files (bool changed) - } - fail_exit (E_CANTUPDATE); - } -- if (spw_opened && (spw_close () == 0)) { -+ if (spw_opened && (spw_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -@@ -657,7 +657,7 @@ static void check_pw_file (bool *errors, bool *changed) - } - #ifdef WITH_TCB - if (getdef_bool ("USE_TCB") && spw_locked) { -- if (spw_opened && (spw_close () == 0)) { -+ if (spw_opened && (spw_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -diff --git a/src/pwconv.c b/src/pwconv.c -index da3a5820..296b527a 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -274,7 +274,7 @@ int main (int argc, char **argv) - } - } - -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -diff --git a/src/pwunconv.c b/src/pwunconv.c -index 8423cda4..e15c8c06 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -205,7 +205,7 @@ int main (int argc, char **argv) - } - } - -- (void) spw_close (); /* was only open O_RDONLY */ -+ (void) spw_close (true); /* was only open O_RDONLY */ - - if (pw_close (true) == 0) { - fprintf (stderr, -diff --git a/src/useradd.c b/src/useradd.c -index 8c9e9003..8a7df6cf 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1569,7 +1569,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_PW_UPDATE); - } -- if (is_shadow_pwd && (spw_close () == 0)) { -+ if (is_shadow_pwd && (spw_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -diff --git a/src/userdel.c b/src/userdel.c -index b5a02b3c..b87f2459 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -403,7 +403,7 @@ static void close_files (void) - pw_locked = false; - - if (is_shadow_pwd) { -- if (spw_close () == 0) { -+ if (spw_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -diff --git a/src/usermod.c b/src/usermod.c -index 180b7da0..d741508a 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1476,7 +1476,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_PW_UPDATE); - } -- if (is_shadow_pwd && (spw_close () == 0)) { -+ if (is_shadow_pwd && (spw_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); --- -2.50.0 - - -From 16bd1d985900fe83a1f7c9001fa3b9f18e0f06f0 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:28:42 +0200 -Subject: [PATCH 04/15] lib/, src/: add SELinux control flag in gr_close() - -Expand gr_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/groupio.c | 4 ++-- - lib/groupio.h | 3 ++- - src/chgpasswd.c | 2 +- - src/gpasswd.c | 4 ++-- - src/groupadd.c | 2 +- - src/groupdel.c | 2 +- - src/groupmems.c | 2 +- - src/groupmod.c | 2 +- - src/grpck.c | 2 +- - src/grpconv.c | 2 +- - src/grpunconv.c | 2 +- - src/newusers.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 2 +- - src/usermod.c | 2 +- - 15 files changed, 18 insertions(+), 17 deletions(-) - -diff --git a/lib/groupio.c b/lib/groupio.c -index 5076fd3d..837e4c47 100644 ---- a/lib/groupio.c -+++ b/lib/groupio.c -@@ -184,9 +184,9 @@ int gr_rewind (void) - return commonio_next (&group_db); - } - --int gr_close (void) -+int gr_close (bool process_selinux) - { -- return commonio_close (&group_db, true); -+ return commonio_close (&group_db, process_selinux); - } - - int gr_unlock (void) -diff --git a/lib/groupio.h b/lib/groupio.h -index 2014de0c..ef9242d0 100644 ---- a/lib/groupio.h -+++ b/lib/groupio.h -@@ -14,8 +14,9 @@ - - #include - #include -+#include - --extern int gr_close (void); -+extern int gr_close (bool process_selinux); - extern /*@observer@*/ /*@null@*/const struct group *gr_locate (const char *name); - extern /*@observer@*/ /*@null@*/const struct group *gr_locate_gid (gid_t gid); - extern int gr_lock (void); -diff --git a/src/chgpasswd.c b/src/chgpasswd.c -index e7759657..9b686ef0 100644 ---- a/src/chgpasswd.c -+++ b/src/chgpasswd.c -@@ -397,7 +397,7 @@ static void close_files (void) - } - #endif - -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/gpasswd.c b/src/gpasswd.c -index 460bd14c..1013f004 100644 ---- a/src/gpasswd.c -+++ b/src/gpasswd.c -@@ -593,7 +593,7 @@ static void log_gpasswd_success_group (MAYBE_UNUSED void *arg) - */ - static void close_files (void) - { -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -@@ -724,7 +724,7 @@ static void get_group (struct group *gr) - gr->gr_passwd = xstrdup (tmpgr->gr_passwd); - gr->gr_mem = dup_list (tmpgr->gr_mem); - -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while closing read-only %s\n"), - Prog, gr_dbname ()); -diff --git a/src/groupadd.c b/src/groupadd.c -index a0d5adeb..d9a9d36c 100644 ---- a/src/groupadd.c -+++ b/src/groupadd.c -@@ -274,7 +274,7 @@ check_new_name(void) - static void close_files (void) - { - /* First, write the changes in the regular group database */ -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/groupdel.c b/src/groupdel.c -index 3d289fef..c52a2ae7 100644 ---- a/src/groupdel.c -+++ b/src/groupdel.c -@@ -149,7 +149,7 @@ static void grp_update (void) - static void close_files (void) - { - /* First, write the changes in the regular group database */ -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/groupmems.c b/src/groupmems.c -index d37b237f..fff9ae10 100644 ---- a/src/groupmems.c -+++ b/src/groupmems.c -@@ -522,7 +522,7 @@ static void open_files (void) - - static void close_files (void) - { -- if ((gr_close () == 0) && !list) { -+ if ((gr_close (true) == 0) && !list) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); - fail_exit (EXIT_GROUP_FILE); -diff --git a/src/groupmod.c b/src/groupmod.c -index 14b7e746..49b68c55 100644 ---- a/src/groupmod.c -+++ b/src/groupmod.c -@@ -481,7 +481,7 @@ static void process_flags (int argc, char **argv) - */ - static void close_files (void) - { -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/grpck.c b/src/grpck.c -index 5fcf6fad..db8f1e68 100644 ---- a/src/grpck.c -+++ b/src/grpck.c -@@ -321,7 +321,7 @@ static void close_files (bool changed) - * changes to the files. - */ - if (changed) { -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), - Prog, grp_file); - fail_exit (E_CANT_UPDATE); -diff --git a/src/grpconv.c b/src/grpconv.c -index 1b31cb85..e7928a4a 100644 ---- a/src/grpconv.c -+++ b/src/grpconv.c -@@ -241,7 +241,7 @@ int main (int argc, char **argv) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); - fail_exit (3); - } -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/grpunconv.c b/src/grpunconv.c -index ea65a329..63597da1 100644 ---- a/src/grpunconv.c -+++ b/src/grpunconv.c -@@ -193,7 +193,7 @@ int main (int argc, char **argv) - - (void) sgr_close (); /* was only open O_RDONLY */ - -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/newusers.c b/src/newusers.c -index 43672dd2..29d3a536 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -969,7 +969,7 @@ static void close_files (void) - spw_locked = false; - } - -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -diff --git a/src/useradd.c b/src/useradd.c -index 8a7df6cf..f52e5483 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1664,7 +1664,7 @@ static void close_group_files (void) - if (!do_grp_update) - return; - -- if (gr_close() == 0) { -+ if (gr_close(true) == 0) { - fprintf(stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname()); -diff --git a/src/userdel.c b/src/userdel.c -index b87f2459..b0e0d541 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -417,7 +417,7 @@ static void close_files (void) - spw_locked = false; - } - -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); - fail_exit (E_GRP_UPDATE); -diff --git a/src/usermod.c b/src/usermod.c -index d741508a..d1d26eaa 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1487,7 +1487,7 @@ static void close_files (void) - } - - if (Gflg || lflg) { -- if (gr_close () == 0) { -+ if (gr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); --- -2.50.0 - - -From f4a67dd6281a513b56c15aa1a3f292ca05674f13 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:32:05 +0200 -Subject: [PATCH 05/15] lib/, src/: add SELinux control flag in sgr_close() - -Expand sgr_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/sgroupio.c | 4 ++-- - lib/sgroupio.h | 2 +- - src/chgpasswd.c | 2 +- - src/gpasswd.c | 4 ++-- - src/groupadd.c | 2 +- - src/groupdel.c | 2 +- - src/groupmems.c | 2 +- - src/groupmod.c | 2 +- - src/grpck.c | 2 +- - src/grpconv.c | 2 +- - src/grpunconv.c | 2 +- - src/newusers.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 2 +- - src/usermod.c | 2 +- - 15 files changed, 17 insertions(+), 17 deletions(-) - -diff --git a/lib/sgroupio.c b/lib/sgroupio.c -index 659dcd06..025584ad 100644 ---- a/lib/sgroupio.c -+++ b/lib/sgroupio.c -@@ -276,9 +276,9 @@ int sgr_rewind (void) - return commonio_next (&gshadow_db); - } - --int sgr_close (void) -+int sgr_close (bool process_selinux) - { -- return commonio_close (&gshadow_db, true); -+ return commonio_close (&gshadow_db, process_selinux); - } - - int sgr_unlock (void) -diff --git a/lib/sgroupio.h b/lib/sgroupio.h -index 3474a985..0e25fc0b 100644 ---- a/lib/sgroupio.h -+++ b/lib/sgroupio.h -@@ -12,7 +12,7 @@ - #ifndef _SGROUPIO_H - #define _SGROUPIO_H - --extern int sgr_close (void); -+extern int sgr_close (bool process_selinux); - extern bool sgr_file_present (void); - extern /*@observer@*/ /*@null@*/const struct sgrp *sgr_locate (const char *name); - extern int sgr_lock (void); -diff --git a/src/chgpasswd.c b/src/chgpasswd.c -index 9b686ef0..47402ecc 100644 ---- a/src/chgpasswd.c -+++ b/src/chgpasswd.c -@@ -381,7 +381,7 @@ static void close_files (void) - { - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/gpasswd.c b/src/gpasswd.c -index 1013f004..a49b9140 100644 ---- a/src/gpasswd.c -+++ b/src/gpasswd.c -@@ -607,7 +607,7 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadowgrp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -@@ -762,7 +762,7 @@ static void get_group (struct group *gr) - sg->sg_adm[0] = NULL; - - } -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while closing read-only %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/groupadd.c b/src/groupadd.c -index d9a9d36c..7cfb0eb5 100644 ---- a/src/groupadd.c -+++ b/src/groupadd.c -@@ -295,7 +295,7 @@ static void close_files (void) - /* Now, write the changes in the shadow database */ - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/groupdel.c b/src/groupdel.c -index c52a2ae7..56123a7b 100644 ---- a/src/groupdel.c -+++ b/src/groupdel.c -@@ -173,7 +173,7 @@ static void close_files (void) - /* Then, write the changes in the shadow database */ - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/groupmems.c b/src/groupmems.c -index fff9ae10..5976b074 100644 ---- a/src/groupmems.c -+++ b/src/groupmems.c -@@ -538,7 +538,7 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadowgrp) { -- if ((sgr_close () == 0) && !list) { -+ if ((sgr_close (true) == 0) && !list) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); - fail_exit (EXIT_GROUP_FILE); -diff --git a/src/groupmod.c b/src/groupmod.c -index 49b68c55..3c258feb 100644 ---- a/src/groupmod.c -+++ b/src/groupmod.c -@@ -504,7 +504,7 @@ static void close_files (void) - #ifdef SHADOWGRP - if ( is_shadow_grp - && (pflg || nflg || user_list)) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/grpck.c b/src/grpck.c -index db8f1e68..872f882f 100644 ---- a/src/grpck.c -+++ b/src/grpck.c -@@ -327,7 +327,7 @@ static void close_files (bool changed) - fail_exit (E_CANT_UPDATE); - } - #ifdef SHADOWGRP -- if (is_shadow && (sgr_close () == 0)) { -+ if (is_shadow && (sgr_close (true) == 0)) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), - Prog, sgr_file); - fail_exit (E_CANT_UPDATE); -diff --git a/src/grpconv.c b/src/grpconv.c -index e7928a4a..d9c59fc9 100644 ---- a/src/grpconv.c -+++ b/src/grpconv.c -@@ -234,7 +234,7 @@ int main (int argc, char **argv) - } - } - -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/grpunconv.c b/src/grpunconv.c -index 63597da1..03fc824e 100644 ---- a/src/grpunconv.c -+++ b/src/grpunconv.c -@@ -191,7 +191,7 @@ int main (int argc, char **argv) - } - } - -- (void) sgr_close (); /* was only open O_RDONLY */ -+ (void) sgr_close (true); /* was only open O_RDONLY */ - - if (gr_close (true) == 0) { - fprintf (stderr, -diff --git a/src/newusers.c b/src/newusers.c -index 29d3a536..19a32863 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -1002,7 +1002,7 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/useradd.c b/src/useradd.c -index f52e5483..7f596673 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1672,7 +1672,7 @@ static void close_group_files (void) - fail_exit(E_GRP_UPDATE); - } - #ifdef SHADOWGRP -- if (is_shadow_grp && sgr_close() == 0) { -+ if (is_shadow_grp && sgr_close(true) == 0) { - fprintf(stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname()); -diff --git a/src/userdel.c b/src/userdel.c -index b0e0d541..1829ba4d 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -431,7 +431,7 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -diff --git a/src/usermod.c b/src/usermod.c -index d1d26eaa..dbcb32b2 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1498,7 +1498,7 @@ static void close_files (void) - } - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close () == 0) { -+ if (sgr_close (true) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); --- -2.50.0 - - -From f3dce7ede9c3f267e810fec3500498e76a305d8a Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:35:48 +0200 -Subject: [PATCH 06/15] lib/, src/: add SELinux control flag in sub_uid_close() - -Expand sub_uid_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/subordinateio.c | 14 +++++++------- - lib/subordinateio.h | 2 +- - lib/user_busy.c | 10 +++++----- - src/newuidmap.c | 2 +- - src/newusers.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 2 +- - src/usermod.c | 2 +- - 8 files changed, 18 insertions(+), 18 deletions(-) - -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 3638ec61..206a1348 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -590,7 +590,7 @@ static bool have_range(struct commonio_db *db, - - if (doclose) { - if (db == &subordinate_uid_db) -- sub_uid_close(); -+ sub_uid_close(true); - else - sub_gid_close(); - } -@@ -668,9 +668,9 @@ int sub_uid_remove (const char *owner, uid_t start, unsigned long count) - return remove_range (&subordinate_uid_db, owner, start, count); - } - --int sub_uid_close (void) -+int sub_uid_close (bool process_selinux) - { -- return commonio_close (&subordinate_uid_db, true); -+ return commonio_close (&subordinate_uid_db, process_selinux); - } - - int sub_uid_unlock (void) -@@ -907,7 +907,7 @@ int list_owner_ranges(const char *owner, enum subid_type id_type, struct subid_r - - out: - if (id_type == ID_TYPE_UID) -- sub_uid_close(); -+ sub_uid_close(true); - else - sub_gid_close(); - -@@ -998,7 +998,7 @@ int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) - } - - if (id_type == ID_TYPE_UID) -- sub_uid_close(); -+ sub_uid_close(true); - else - sub_gid_close(); - -@@ -1068,7 +1068,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - - out: - if (id_type == ID_TYPE_UID) { -- sub_uid_close(); -+ sub_uid_close(true); - sub_uid_unlock(); - } else { - sub_gid_close(); -@@ -1118,7 +1118,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - ret = remove_range(db, range->owner, range->start, range->count) == 1; - - if (id_type == ID_TYPE_UID) { -- sub_uid_close(); -+ sub_uid_close(true); - sub_uid_unlock(); - } else { - sub_gid_close(); -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index 3d1a0547..d16c8b9e 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -13,7 +13,7 @@ - - #include "../libsubid/subid.h" - --extern int sub_uid_close(void); -+extern int sub_uid_close(bool process_selinux); - extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); - extern bool sub_uid_file_present (void); - extern bool local_sub_uid_assigned(const char *owner); -diff --git a/lib/user_busy.c b/lib/user_busy.c -index d689d34d..ab1dd5a4 100644 ---- a/lib/user_busy.c -+++ b/lib/user_busy.c -@@ -180,7 +180,7 @@ static int user_busy_processes (const char *name, uid_t uid) - if (proc == NULL) { - perror ("opendir /proc"); - #ifdef ENABLE_SUBIDS -- sub_uid_close(); -+ sub_uid_close(true); - #endif - return 0; - } -@@ -188,7 +188,7 @@ static int user_busy_processes (const char *name, uid_t uid) - perror ("stat (\"/\")"); - (void) closedir (proc); - #ifdef ENABLE_SUBIDS -- sub_uid_close(); -+ sub_uid_close(true); - #endif - return 0; - } -@@ -225,7 +225,7 @@ static int user_busy_processes (const char *name, uid_t uid) - if (check_status (name, tmp_d_name, uid) != 0) { - (void) closedir (proc); - #ifdef ENABLE_SUBIDS -- sub_uid_close(); -+ sub_uid_close(true); - #endif - fprintf (log_get_logfd(), - _("%s: user %s is currently used by process %d\n"), -@@ -248,7 +248,7 @@ static int user_busy_processes (const char *name, uid_t uid) - (void) closedir (proc); - (void) closedir (task_dir); - #ifdef ENABLE_SUBIDS -- sub_uid_close(); -+ sub_uid_close(true); - #endif - fprintf (log_get_logfd(), - _("%s: user %s is currently used by process %d\n"), -@@ -264,7 +264,7 @@ static int user_busy_processes (const char *name, uid_t uid) - - (void) closedir (proc); - #ifdef ENABLE_SUBIDS -- sub_uid_close(); -+ sub_uid_close(true); - #endif /* ENABLE_SUBIDS */ - return 0; - } -diff --git a/src/newuidmap.c b/src/newuidmap.c -index 894c5ec8..90bd6de5 100644 ---- a/src/newuidmap.c -+++ b/src/newuidmap.c -@@ -158,7 +158,7 @@ int main(int argc, char **argv) - verify_ranges(pw, ranges, mappings); - - write_mapping(proc_dir_fd, ranges, mappings, "uid_map", pw->pw_uid); -- sub_uid_close(); -+ sub_uid_close(true); - - return EXIT_SUCCESS; - } -diff --git a/src/newusers.c b/src/newusers.c -index 19a32863..d71a792b 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -977,7 +977,7 @@ static void close_files (void) - fail_exit (EXIT_FAILURE); - } - #ifdef ENABLE_SUBIDS -- if (is_sub_uid && (sub_uid_close () == 0)) { -+ if (is_sub_uid && (sub_uid_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -diff --git a/src/useradd.c b/src/useradd.c -index 7f596673..971fec55 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1579,7 +1579,7 @@ static void close_files (void) - close_group_files (); - - #ifdef ENABLE_SUBIDS -- if (is_sub_uid && (sub_uid_close () == 0)) { -+ if (is_sub_uid && (sub_uid_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -diff --git a/src/userdel.c b/src/userdel.c -index 1829ba4d..8fe9f4e2 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -449,7 +449,7 @@ static void close_files (void) - - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_close () == 0) { -+ if (sub_uid_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (E_SUB_UID_UPDATE); -diff --git a/src/usermod.c b/src/usermod.c -index dbcb32b2..440c2406 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1561,7 +1561,7 @@ static void close_files (void) - - #ifdef ENABLE_SUBIDS - if (vflg || Vflg) { -- if (sub_uid_close () == 0) { -+ if (sub_uid_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (E_SUB_UID_UPDATE); --- -2.50.0 - - -From ab2a2656e442043d5b39e1320552ba9850aabd27 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:38:18 +0200 -Subject: [PATCH 07/15] lib/, src/: add SELinux control flag in sub_gid_close() - -Expand sub_gid_close() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/subordinateio.c | 14 +++++++------- - lib/subordinateio.h | 2 +- - src/newgidmap.c | 2 +- - src/newusers.c | 2 +- - src/useradd.c | 2 +- - src/userdel.c | 2 +- - src/usermod.c | 2 +- - 7 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 206a1348..e2c2375a 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -592,7 +592,7 @@ static bool have_range(struct commonio_db *db, - if (db == &subordinate_uid_db) - sub_uid_close(true); - else -- sub_gid_close(); -+ sub_gid_close(true); - } - - return ret; -@@ -775,9 +775,9 @@ int sub_gid_remove (const char *owner, gid_t start, unsigned long count) - return remove_range (&subordinate_gid_db, owner, start, count); - } - --int sub_gid_close (void) -+int sub_gid_close (bool process_selinux) - { -- return commonio_close (&subordinate_gid_db, true); -+ return commonio_close (&subordinate_gid_db, process_selinux); - } - - int sub_gid_unlock (void) -@@ -909,7 +909,7 @@ out: - if (id_type == ID_TYPE_UID) - sub_uid_close(true); - else -- sub_gid_close(); -+ sub_gid_close(true); - - *in_ranges = ranges; - return count; -@@ -1000,7 +1000,7 @@ int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids) - if (id_type == ID_TYPE_UID) - sub_uid_close(true); - else -- sub_gid_close(); -+ sub_gid_close(true); - - return n; - } -@@ -1071,7 +1071,7 @@ out: - sub_uid_close(true); - sub_uid_unlock(); - } else { -- sub_gid_close(); -+ sub_gid_close(true); - sub_gid_unlock(); - } - -@@ -1121,7 +1121,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - sub_uid_close(true); - sub_uid_unlock(); - } else { -- sub_gid_close(); -+ sub_gid_close(true); - sub_gid_unlock(); - } - -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index d16c8b9e..63f5b1fb 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -31,7 +31,7 @@ extern bool release_subid_range(struct subordinate_range *range, enum subid_type - extern int find_subid_owners(unsigned long id, enum subid_type id_type, uid_t **uids); - extern void free_subordinate_ranges(struct subordinate_range **ranges, int count); - --extern int sub_gid_close(void); -+extern int sub_gid_close(bool process_selinux); - extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); - extern bool sub_gid_file_present (void); - extern bool local_sub_gid_assigned(const char *owner); -diff --git a/src/newgidmap.c b/src/newgidmap.c -index 3463e850..7ce22b5a 100644 ---- a/src/newgidmap.c -+++ b/src/newgidmap.c -@@ -230,7 +230,7 @@ int main(int argc, char **argv) - - write_setgroups(proc_dir_fd, allow_setgroups); - write_mapping(proc_dir_fd, ranges, mappings, "gid_map", pw->pw_uid); -- sub_gid_close(); -+ sub_gid_close(true); - - return EXIT_SUCCESS; - } -diff --git a/src/newusers.c b/src/newusers.c -index d71a792b..8cd11a71 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -983,7 +983,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (EXIT_FAILURE); - } -- if (is_sub_gid && (sub_gid_close () == 0)) { -+ if (is_sub_gid && (sub_gid_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -diff --git a/src/useradd.c b/src/useradd.c -index 971fec55..3d2fdb35 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1585,7 +1585,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (E_SUB_UID_UPDATE); - } -- if (is_sub_gid && (sub_gid_close () == 0)) { -+ if (is_sub_gid && (sub_gid_close (true) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -diff --git a/src/userdel.c b/src/userdel.c -index 8fe9f4e2..7dcbd923 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -463,7 +463,7 @@ static void close_files (void) - } - - if (is_sub_gid) { -- if (sub_gid_close () == 0) { -+ if (sub_gid_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); - fail_exit (E_SUB_GID_UPDATE); -diff --git a/src/usermod.c b/src/usermod.c -index 440c2406..534bdc74 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1574,7 +1574,7 @@ static void close_files (void) - sub_uid_locked = false; - } - if (wflg || Wflg) { -- if (sub_gid_close () == 0) { -+ if (sub_gid_close (true) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); - fail_exit (E_SUB_GID_UPDATE); --- -2.50.0 - - -From 9161c63be728bfba7545bac1e4cbde8a069ad4e6 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:44:06 +0200 -Subject: [PATCH 08/15] lib/: add SELinux control flag in commonio_unlock() - -Expand commonio_unlock() interface to add a control flag for SELinux -file context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/commonio.c | 4 ++-- - lib/commonio.h | 2 +- - lib/groupio.c | 2 +- - lib/pwio.c | 2 +- - lib/sgroupio.c | 2 +- - lib/shadowio.c | 2 +- - lib/subordinateio.c | 4 ++-- - 7 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/lib/commonio.c b/lib/commonio.c -index 7ee6df4d..19653e7e 100644 ---- a/lib/commonio.c -+++ b/lib/commonio.c -@@ -467,13 +467,13 @@ static void dec_lock_count (void) - } - - --int commonio_unlock (struct commonio_db *db) -+int commonio_unlock (struct commonio_db *db, bool process_selinux) - { - char lock[1029]; - - if (db->isopen) { - db->readonly = true; -- if (commonio_close (db, true) == 0) { -+ if (commonio_close (db, process_selinux) == 0) { - if (db->locked) { - dec_lock_count (); - } -diff --git a/lib/commonio.h b/lib/commonio.h -index dadc0500..8b8f5cf4 100644 ---- a/lib/commonio.h -+++ b/lib/commonio.h -@@ -139,7 +139,7 @@ extern int commonio_remove (struct commonio_db *, const char *); - extern int commonio_rewind (struct commonio_db *); - extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); - extern int commonio_close (struct commonio_db *, bool); --extern int commonio_unlock (struct commonio_db *); -+extern int commonio_unlock (struct commonio_db *, bool); - extern void commonio_del_entry (struct commonio_db *, - const struct commonio_entry *); - extern int commonio_sort_wrt (struct commonio_db *shadow, -diff --git a/lib/groupio.c b/lib/groupio.c -index 837e4c47..6ad4ae69 100644 ---- a/lib/groupio.c -+++ b/lib/groupio.c -@@ -191,7 +191,7 @@ int gr_close (bool process_selinux) - - int gr_unlock (void) - { -- return commonio_unlock (&group_db); -+ return commonio_unlock (&group_db, true); - } - - void __gr_set_changed (void) -diff --git a/lib/pwio.c b/lib/pwio.c -index c5c1cdb1..c5dcb904 100644 ---- a/lib/pwio.c -+++ b/lib/pwio.c -@@ -163,7 +163,7 @@ int pw_close (bool process_selinux) - - int pw_unlock (void) - { -- return commonio_unlock (&passwd_db); -+ return commonio_unlock (&passwd_db, true); - } - - /*@null@*/struct commonio_entry *__pw_get_head (void) -diff --git a/lib/sgroupio.c b/lib/sgroupio.c -index 025584ad..dbabcc36 100644 ---- a/lib/sgroupio.c -+++ b/lib/sgroupio.c -@@ -283,7 +283,7 @@ int sgr_close (bool process_selinux) - - int sgr_unlock (void) - { -- return commonio_unlock (&gshadow_db); -+ return commonio_unlock (&gshadow_db, true); - } - - void __sgr_set_changed (void) -diff --git a/lib/shadowio.c b/lib/shadowio.c -index a109576d..9866af6d 100644 ---- a/lib/shadowio.c -+++ b/lib/shadowio.c -@@ -211,7 +211,7 @@ int spw_unlock (void) - - if (!getdef_bool ("USE_TCB")) { - #endif /* WITH_TCB */ -- return commonio_unlock (&shadow_db); -+ return commonio_unlock (&shadow_db, true); - #ifdef WITH_TCB - } - if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index e2c2375a..9587e1a9 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -675,7 +675,7 @@ int sub_uid_close (bool process_selinux) - - int sub_uid_unlock (void) - { -- return commonio_unlock (&subordinate_uid_db); -+ return commonio_unlock (&subordinate_uid_db, true); - } - - uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count) -@@ -782,7 +782,7 @@ int sub_gid_close (bool process_selinux) - - int sub_gid_unlock (void) - { -- return commonio_unlock (&subordinate_gid_db); -+ return commonio_unlock (&subordinate_gid_db, true); - } - - gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) --- -2.50.0 - - -From 9609c3ba7d4097c2ff63ee6ccfa6b74c41fbde5e Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:53:17 +0200 -Subject: [PATCH 09/15] lib/, src/: add SELinux control flag in pw_unlock() - -Expand pw_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/cleanup_user.c | 2 +- - lib/lockpw.c | 4 ++-- - lib/pwio.c | 4 ++-- - lib/pwio.h | 2 +- - src/chage.c | 4 ++-- - src/chfn.c | 4 ++-- - src/chpasswd.c | 4 ++-- - src/chsh.c | 4 ++-- - src/newusers.c | 4 ++-- - src/passwd.c | 4 ++-- - src/pwck.c | 4 ++-- - src/pwconv.c | 4 ++-- - src/pwunconv.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 16 files changed, 30 insertions(+), 30 deletions(-) - -diff --git a/lib/cleanup_user.c b/lib/cleanup_user.c -index 809caaf3..a661f5e9 100644 ---- a/lib/cleanup_user.c -+++ b/lib/cleanup_user.c -@@ -98,7 +98,7 @@ void cleanup_report_add_user_shadow (void *user_name) - */ - void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) - { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), pw_dbname ()); -diff --git a/lib/lockpw.c b/lib/lockpw.c -index 15e7c8f4..f73c434a 100644 ---- a/lib/lockpw.c -+++ b/lib/lockpw.c -@@ -56,7 +56,7 @@ int lckpwdf (void) - */ - - if (i == 15) { -- pw_unlock (); -+ pw_unlock (true); - return -1; - } - -@@ -78,7 +78,7 @@ int ulckpwdf (void) - * Unlock both files. - */ - -- return (pw_unlock () && spw_unlock ())? 0 : -1; -+ return (pw_unlock (true) && spw_unlock ())? 0 : -1; - } - #else - extern int ISO_C_forbids_an_empty_translation_unit; -diff --git a/lib/pwio.c b/lib/pwio.c -index c5dcb904..78146c37 100644 ---- a/lib/pwio.c -+++ b/lib/pwio.c -@@ -161,9 +161,9 @@ int pw_close (bool process_selinux) - return commonio_close (&passwd_db, process_selinux); - } - --int pw_unlock (void) -+int pw_unlock (bool process_selinux) - { -- return commonio_unlock (&passwd_db, true); -+ return commonio_unlock (&passwd_db, process_selinux); - } - - /*@null@*/struct commonio_entry *__pw_get_head (void) -diff --git a/lib/pwio.h b/lib/pwio.h -index b051a7e7..0903b8bd 100644 ---- a/lib/pwio.h -+++ b/lib/pwio.h -@@ -26,7 +26,7 @@ extern /*@observer@*/ /*@null@*/const struct passwd *pw_next (void); - extern int pw_open (int mode); - extern int pw_remove (const char *name); - extern int pw_rewind (void); --extern int pw_unlock (void); -+extern int pw_unlock (bool process_selinux); - extern int pw_update (const struct passwd *pw); - extern int pw_sort (void); - -diff --git a/src/chage.c b/src/chage.c -index a59428c5..d3a42ccf 100644 ---- a/src/chage.c -+++ b/src/chage.c -@@ -101,7 +101,7 @@ fail_exit (int code) - } - } - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -568,7 +568,7 @@ static void close_files (void) - /* continue */ - } - spw_locked = false; -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/chfn.c b/src/chfn.c -index abf88cc8..dca81486 100644 ---- a/src/chfn.c -+++ b/src/chfn.c -@@ -79,7 +79,7 @@ static void get_old_fields (const char *gecos); - static void fail_exit (int code) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -498,7 +498,7 @@ static void update_gecos (const char *user, char *gecos) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_NOPERM); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/chpasswd.c b/src/chpasswd.c -index e3d8dcef..5323c520 100644 ---- a/src/chpasswd.c -+++ b/src/chpasswd.c -@@ -81,7 +81,7 @@ static void close_files (void); - static void fail_exit (int code) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -400,7 +400,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (1); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/chsh.c b/src/chsh.c -index b5ae28da..4403d412 100644 ---- a/src/chsh.c -+++ b/src/chsh.c -@@ -78,7 +78,7 @@ static void - fail_exit (int code) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -433,7 +433,7 @@ static void update_shell (const char *user, char *newshell) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (1); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/newusers.c b/src/newusers.c -index 8cd11a71..669b6236 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -172,7 +172,7 @@ static void fail_exit (int code) - } - } - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -944,7 +944,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (EXIT_FAILURE); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/passwd.c b/src/passwd.c -index 01efb285..8a55d797 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -483,7 +483,7 @@ static void - fail_exit (int status) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -593,7 +593,7 @@ static void update_noshadow (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_FAILURE); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); -diff --git a/src/pwck.c b/src/pwck.c -index 718b639f..f30c5289 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -96,7 +96,7 @@ static void fail_exit (int code) - } - - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - if (use_system_pw_file) { - SYSLOG ((LOG_ERR, "failed to unlock %s", -@@ -351,7 +351,7 @@ static void close_files (bool changed) - } - spw_locked = false; - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); -diff --git a/src/pwconv.c b/src/pwconv.c -index 296b527a..82181bb4 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -83,7 +83,7 @@ static void process_flags (int argc, char **argv); - static void fail_exit (int status) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -299,7 +299,7 @@ int main (int argc, char **argv) - /* continue */ - } - -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/pwunconv.c b/src/pwunconv.c -index e15c8c06..72944fe5 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -54,7 +54,7 @@ static void fail_exit (int status) - } - } - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -227,7 +227,7 @@ int main (int argc, char **argv) - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/useradd.c b/src/useradd.c -index 3d2fdb35..aa070f2d 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -270,7 +270,7 @@ static void fail_exit (int code) - SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); - /* continue */ - } -- if (pw_locked && pw_unlock() == 0) { -+ if (pw_locked && pw_unlock(true) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); - /* continue */ -@@ -1606,7 +1606,7 @@ static void close_files (void) - } - spw_locked = false; - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index 7dcbd923..b4e87820 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -395,7 +395,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_PW_UPDATE); - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -484,7 +484,7 @@ static void close_files (void) - static void fail_exit (int code) - { - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index 534bdc74..6f761404 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -655,7 +655,7 @@ fail_exit (int code) - } - } - if (pw_locked) { -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -1544,7 +1544,7 @@ static void close_files (void) - /* continue */ - } - } -- if (pw_unlock () == 0) { -+ if (pw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); --- -2.50.0 - - -From bdce75b7b6f7ec69cda287b081de6ca83022ee79 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 15:57:21 +0200 -Subject: [PATCH 10/15] lib/, src/: add SELinux control flag in spw_unlock() - -Expand spw_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/cleanup_user.c | 2 +- - lib/lockpw.c | 2 +- - lib/shadowio.c | 4 ++-- - lib/shadowio.h | 2 +- - src/chage.c | 4 ++-- - src/chpasswd.c | 4 ++-- - src/newusers.c | 4 ++-- - src/passwd.c | 6 +++--- - src/pwck.c | 8 ++++---- - src/pwconv.c | 4 ++-- - src/pwunconv.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 14 files changed, 28 insertions(+), 28 deletions(-) - -diff --git a/lib/cleanup_user.c b/lib/cleanup_user.c -index a661f5e9..b3a5a66e 100644 ---- a/lib/cleanup_user.c -+++ b/lib/cleanup_user.c -@@ -117,7 +117,7 @@ void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) - */ - void cleanup_unlock_shadow (MAYBE_UNUSED void *arg) - { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), spw_dbname ()); -diff --git a/lib/lockpw.c b/lib/lockpw.c -index f73c434a..7c99d56e 100644 ---- a/lib/lockpw.c -+++ b/lib/lockpw.c -@@ -78,7 +78,7 @@ int ulckpwdf (void) - * Unlock both files. - */ - -- return (pw_unlock (true) && spw_unlock ())? 0 : -1; -+ return (pw_unlock (true) && spw_unlock (true))? 0 : -1; - } - #else - extern int ISO_C_forbids_an_empty_translation_unit; -diff --git a/lib/shadowio.c b/lib/shadowio.c -index 9866af6d..71089eda 100644 ---- a/lib/shadowio.c -+++ b/lib/shadowio.c -@@ -204,14 +204,14 @@ int spw_close (bool process_selinux) - return retval; - } - --int spw_unlock (void) -+int spw_unlock (bool process_selinux) - { - #ifdef WITH_TCB - int retval = 0; - - if (!getdef_bool ("USE_TCB")) { - #endif /* WITH_TCB */ -- return commonio_unlock (&shadow_db, true); -+ return commonio_unlock (&shadow_db, process_selinux); - #ifdef WITH_TCB - } - if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { -diff --git a/lib/shadowio.h b/lib/shadowio.h -index e64d8d60..be645d0e 100644 ---- a/lib/shadowio.h -+++ b/lib/shadowio.h -@@ -23,7 +23,7 @@ extern /*@observer@*/ /*@null@*/const struct spwd *spw_next (void); - extern int spw_open (int mode); - extern int spw_remove (const char *name); - extern int spw_rewind (void); --extern int spw_unlock (void); -+extern int spw_unlock (bool process_selinux); - extern int spw_update (const struct spwd *sp); - extern int spw_sort (void); - -diff --git a/src/chage.c b/src/chage.c -index d3a42ccf..e77a46de 100644 ---- a/src/chage.c -+++ b/src/chage.c -@@ -94,7 +94,7 @@ static void - fail_exit (int code) - { - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -562,7 +562,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_NOPERM); - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -diff --git a/src/chpasswd.c b/src/chpasswd.c -index 5323c520..2656b039 100644 ---- a/src/chpasswd.c -+++ b/src/chpasswd.c -@@ -89,7 +89,7 @@ static void fail_exit (int code) - } - - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -385,7 +385,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (1); - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -diff --git a/src/newusers.c b/src/newusers.c -index 669b6236..4cbb1639 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -165,7 +165,7 @@ static void usage (int status) - static void fail_exit (int code) - { - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -959,7 +959,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (EXIT_FAILURE); - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -diff --git a/src/passwd.c b/src/passwd.c -index 8a55d797..512dc572 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -491,7 +491,7 @@ fail_exit (int status) - } - - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -627,7 +627,7 @@ static void update_shadow (void) - /* Try to update the password in /etc/passwd instead. */ - (void) spw_close (true); - update_noshadow (); -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -688,7 +688,7 @@ static void update_shadow (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_FAILURE); - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -diff --git a/src/pwck.c b/src/pwck.c -index f30c5289..9c4cc29a 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -85,7 +85,7 @@ extern int allow_bad_names; - static void fail_exit (int code) - { - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - if (use_system_spw_file) { - SYSLOG ((LOG_ERR, "failed to unlock %s", -@@ -338,7 +338,7 @@ static void close_files (bool changed) - * Don't be anti-social - unlock the files when you're done. - */ - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -581,7 +581,7 @@ static void check_pw_file (bool *errors, bool *changed) - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); - *errors = true; -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -669,7 +669,7 @@ static void check_pw_file (bool *errors, bool *changed) - } else { - spw_opened = false; - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -diff --git a/src/pwconv.c b/src/pwconv.c -index 82181bb4..b0d668b5 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -91,7 +91,7 @@ static void fail_exit (int status) - } - - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -305,7 +305,7 @@ int main (int argc, char **argv) - /* continue */ - } - -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -diff --git a/src/pwunconv.c b/src/pwunconv.c -index 72944fe5..7a6d2be5 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -47,7 +47,7 @@ static void process_flags (int argc, char **argv); - static void fail_exit (int status) - { - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -222,7 +222,7 @@ int main (int argc, char **argv) - fail_exit (3); - } - -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -diff --git a/src/useradd.c b/src/useradd.c -index aa070f2d..9c8b774f 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -265,7 +265,7 @@ static void fail_exit (int code) - SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home)); - } - -- if (spw_locked && spw_unlock() == 0) { -+ if (spw_locked && spw_unlock(true) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); - /* continue */ -@@ -1593,7 +1593,7 @@ static void close_files (void) - } - #endif /* ENABLE_SUBIDS */ - if (is_shadow_pwd) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index b4e87820..478c22d5 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -409,7 +409,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_PW_UPDATE); - } -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -498,7 +498,7 @@ static void fail_exit (int code) - } - } - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index 6f761404..68373f35 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -648,7 +648,7 @@ fail_exit (int code) - } - #endif - if (spw_locked) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -1534,7 +1534,7 @@ static void close_files (void) - } - - if (is_shadow_pwd) { -- if (spw_unlock () == 0) { -+ if (spw_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); --- -2.50.0 - - -From 68eb3395a4bcbbdb820b6c8c17cc64fb08749d11 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 16:00:43 +0200 -Subject: [PATCH 11/15] lib/, src/: add SELinux control flag in gr_unlock() - -Expand gr_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/cleanup_group.c | 2 +- - lib/groupio.c | 4 ++-- - lib/groupio.h | 2 +- - src/chgpasswd.c | 4 ++-- - src/groupmems.c | 4 ++-- - src/grpck.c | 4 ++-- - src/grpconv.c | 4 ++-- - src/grpunconv.c | 4 ++-- - src/newusers.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 12 files changed, 22 insertions(+), 22 deletions(-) - -diff --git a/lib/cleanup_group.c b/lib/cleanup_group.c -index 54480092..a5846152 100644 ---- a/lib/cleanup_group.c -+++ b/lib/cleanup_group.c -@@ -181,7 +181,7 @@ void cleanup_report_del_group_gshadow (void *group_name) - */ - void cleanup_unlock_group (MAYBE_UNUSED void *arg) - { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), gr_dbname ()); -diff --git a/lib/groupio.c b/lib/groupio.c -index 6ad4ae69..f21aa618 100644 ---- a/lib/groupio.c -+++ b/lib/groupio.c -@@ -189,9 +189,9 @@ int gr_close (bool process_selinux) - return commonio_close (&group_db, process_selinux); - } - --int gr_unlock (void) -+int gr_unlock (bool process_selinux) - { -- return commonio_unlock (&group_db, true); -+ return commonio_unlock (&group_db, process_selinux); - } - - void __gr_set_changed (void) -diff --git a/lib/groupio.h b/lib/groupio.h -index ef9242d0..eae13cd3 100644 ---- a/lib/groupio.h -+++ b/lib/groupio.h -@@ -26,7 +26,7 @@ extern /*@observer@*/ /*@null@*/const struct group *gr_next (void); - extern int gr_open (int mode); - extern int gr_remove (const char *name); - extern int gr_rewind (void); --extern int gr_unlock (void); -+extern int gr_unlock (bool process_selinux); - extern int gr_update (const struct group *gr); - extern int gr_sort (void); - -diff --git a/src/chgpasswd.c b/src/chgpasswd.c -index 47402ecc..84553d81 100644 ---- a/src/chgpasswd.c -+++ b/src/chgpasswd.c -@@ -82,7 +82,7 @@ static void close_files (void); - static void fail_exit (int code) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -404,7 +404,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); - fail_exit (1); - } -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/groupmems.c b/src/groupmems.c -index 5976b074..0c59474f 100644 ---- a/src/groupmems.c -+++ b/src/groupmems.c -@@ -457,7 +457,7 @@ static void check_perms (void) - static void fail_exit (int code) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); -@@ -528,7 +528,7 @@ static void close_files (void) - fail_exit (EXIT_GROUP_FILE); - } - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/grpck.c b/src/grpck.c -index 872f882f..bd2014fc 100644 ---- a/src/grpck.c -+++ b/src/grpck.c -@@ -92,7 +92,7 @@ static void check_sgr_file (bool *errors, bool *changed); - static void fail_exit (int status) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -349,7 +349,7 @@ static void close_files (bool changed) - } - #endif - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/grpconv.c b/src/grpconv.c -index d9c59fc9..3160b8b1 100644 ---- a/src/grpconv.c -+++ b/src/grpconv.c -@@ -56,7 +56,7 @@ static void process_flags (int argc, char **argv); - static void fail_exit (int status) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -253,7 +253,7 @@ int main (int argc, char **argv) - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ - } -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/grpunconv.c b/src/grpunconv.c -index 03fc824e..085c48ac 100644 ---- a/src/grpunconv.c -+++ b/src/grpunconv.c -@@ -55,7 +55,7 @@ static void process_flags (int argc, char **argv); - static void fail_exit (int status) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -209,7 +209,7 @@ int main (int argc, char **argv) - fail_exit (3); - } - -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/newusers.c b/src/newusers.c -index 4cbb1639..47f01661 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -179,7 +179,7 @@ static void fail_exit (int code) - } - } - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -991,7 +991,7 @@ static void close_files (void) - } - #endif /* ENABLE_SUBIDS */ - -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); -diff --git a/src/useradd.c b/src/useradd.c -index 9c8b774f..75cfbde2 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -275,7 +275,7 @@ static void fail_exit (int code) - SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); - /* continue */ - } -- if (gr_locked && gr_unlock() == 0) { -+ if (gr_locked && gr_unlock(true) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); - /* continue */ -@@ -1690,7 +1690,7 @@ static void close_group_files (void) - */ - static void unlock_group_files (void) - { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index 478c22d5..12696732 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -422,7 +422,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); - fail_exit (E_GRP_UPDATE); - } -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -491,7 +491,7 @@ static void fail_exit (int code) - } - } - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index 68373f35..2e21a70f 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -632,7 +632,7 @@ static void - fail_exit (int code) - { - if (gr_locked) { -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -1522,7 +1522,7 @@ static void close_files (void) - } - } - #endif -- if (gr_unlock () == 0) { -+ if (gr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); --- -2.50.0 - - -From 37b636524cfb7c9b7dce8c56484fb60795ef2b91 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 16:03:58 +0200 -Subject: [PATCH 12/15] lib/, src/: add SELinux control flag in sgr_unlock() - -Expand sgr_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/cleanup_group.c | 2 +- - lib/sgroupio.c | 4 ++-- - lib/sgroupio.h | 2 +- - src/chgpasswd.c | 4 ++-- - src/groupmems.c | 4 ++-- - src/grpck.c | 4 ++-- - src/grpconv.c | 4 ++-- - src/grpunconv.c | 4 ++-- - src/newusers.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 12 files changed, 22 insertions(+), 22 deletions(-) - -diff --git a/lib/cleanup_group.c b/lib/cleanup_group.c -index a5846152..dc9f1eb2 100644 ---- a/lib/cleanup_group.c -+++ b/lib/cleanup_group.c -@@ -201,7 +201,7 @@ void cleanup_unlock_group (MAYBE_UNUSED void *arg) - */ - void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg) - { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), sgr_dbname ()); -diff --git a/lib/sgroupio.c b/lib/sgroupio.c -index dbabcc36..4239e23d 100644 ---- a/lib/sgroupio.c -+++ b/lib/sgroupio.c -@@ -281,9 +281,9 @@ int sgr_close (bool process_selinux) - return commonio_close (&gshadow_db, process_selinux); - } - --int sgr_unlock (void) -+int sgr_unlock (bool process_selinux) - { -- return commonio_unlock (&gshadow_db, true); -+ return commonio_unlock (&gshadow_db, process_selinux); - } - - void __sgr_set_changed (void) -diff --git a/lib/sgroupio.h b/lib/sgroupio.h -index 0e25fc0b..256f6d54 100644 ---- a/lib/sgroupio.h -+++ b/lib/sgroupio.h -@@ -22,7 +22,7 @@ extern /*@null@*/const struct sgrp *sgr_next (void); - extern int sgr_open (int mode); - extern int sgr_remove (const char *name); - extern int sgr_rewind (void); --extern int sgr_unlock (void); -+extern int sgr_unlock (bool process_selinux); - extern int sgr_update (const struct sgrp *sg); - extern int sgr_sort (void); - -diff --git a/src/chgpasswd.c b/src/chgpasswd.c -index 84553d81..27094f50 100644 ---- a/src/chgpasswd.c -+++ b/src/chgpasswd.c -@@ -91,7 +91,7 @@ static void fail_exit (int code) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -388,7 +388,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); - fail_exit (1); - } -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/groupmems.c b/src/groupmems.c -index 0c59474f..f39724c8 100644 ---- a/src/groupmems.c -+++ b/src/groupmems.c -@@ -468,7 +468,7 @@ static void fail_exit (int code) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); -@@ -544,7 +544,7 @@ static void close_files (void) - fail_exit (EXIT_GROUP_FILE); - } - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/grpck.c b/src/grpck.c -index bd2014fc..bc178d52 100644 ---- a/src/grpck.c -+++ b/src/grpck.c -@@ -101,7 +101,7 @@ static void fail_exit (int status) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -340,7 +340,7 @@ static void close_files (bool changed) - */ - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/grpconv.c b/src/grpconv.c -index 3160b8b1..5958d3f5 100644 ---- a/src/grpconv.c -+++ b/src/grpconv.c -@@ -64,7 +64,7 @@ static void fail_exit (int status) - } - - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -248,7 +248,7 @@ int main (int argc, char **argv) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); - fail_exit (3); - } -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/grpunconv.c b/src/grpunconv.c -index 085c48ac..5256e0bc 100644 ---- a/src/grpunconv.c -+++ b/src/grpunconv.c -@@ -63,7 +63,7 @@ static void fail_exit (int status) - } - - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -215,7 +215,7 @@ int main (int argc, char **argv) - /* continue */ - } - -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/newusers.c b/src/newusers.c -index 47f01661..261a5911 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -187,7 +187,7 @@ static void fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -1009,7 +1009,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); - fail_exit (EXIT_FAILURE); - } -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); -diff --git a/src/useradd.c b/src/useradd.c -index 75cfbde2..cb7ac88e 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -281,7 +281,7 @@ static void fail_exit (int code) - /* continue */ - } - #ifdef SHADOWGRP -- if (sgr_locked && sgr_unlock() == 0) { -+ if (sgr_locked && sgr_unlock(true) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); - /* continue */ -@@ -1704,7 +1704,7 @@ static void unlock_group_files (void) - gr_locked = false; - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index 12696732..80ed1a48 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -438,7 +438,7 @@ static void close_files (void) - fail_exit (E_GRP_UPDATE); - } - -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -506,7 +506,7 @@ static void fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index 2e21a70f..69ea8e55 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -640,7 +640,7 @@ fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -1511,7 +1511,7 @@ static void close_files (void) - #endif - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_unlock () == 0) { -+ if (sgr_unlock (true) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); --- -2.50.0 - - -From dee1a5a5782b8aafcc32c7f93a53ce591355d1b3 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 16:06:57 +0200 -Subject: [PATCH 13/15] src/vipw.c: add SELinux control flag in unlock - -All unlock functions require the SELinux control flag, thus add it as an -argument. - -Signed-off-by: Iker Pedrosa ---- - src/vipw.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/vipw.c b/src/vipw.c -index 3c840e9f..ba323e0e 100644 ---- a/src/vipw.c -+++ b/src/vipw.c -@@ -62,7 +62,7 @@ static const char *Prog; - static const char *filename, *fileeditname; - static bool filelocked = false; - static bool createedit = false; --static int (*unlock) (void); -+static int (*unlock) (bool); - static bool quiet = false; - #ifdef WITH_TCB - static const char *user = NULL; -@@ -74,7 +74,7 @@ static bool tcb_mode = false; - static void usage (int status); - static int create_backup_file (FILE *, const char *, struct stat *); - static void vipwexit (const char *msg, int syserr, int ret); --static void vipwedit (const char *, int (*)(void), int (*)(void)); -+static void vipwedit (const char *, int (*)(void), int (*)(bool)); - - /* - * usage - display usage message and exit -@@ -164,7 +164,7 @@ static void vipwexit (const char *msg, int syserr, int ret) - } - } - if (filelocked) { -- if ((*unlock) () == 0) { -+ if ((*unlock) (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, fileeditname); - SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname)); - /* continue */ -@@ -195,7 +195,7 @@ static void vipwexit (const char *msg, int syserr, int ret) - * - */ - static void --vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) -+vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (bool)) - { - int status; - char *to_rename; -@@ -467,7 +467,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) - } - #endif /* WITH_TCB */ - -- if ((*file_unlock) () == 0) { -+ if ((*file_unlock) (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, fileeditname); - SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname)); - /* continue */ --- -2.50.0 - - -From f297173f0247b9288c424e765e972eb13d4c9ded Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 16:10:09 +0200 -Subject: [PATCH 14/15] lib/, src/: add SELinux control flag in - sub_uid_unlock() - -Expand sub_uid_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/subordinateio.c | 12 ++++++------ - lib/subordinateio.h | 2 +- - src/newusers.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 6 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index 9587e1a9..eaa2dc99 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -673,9 +673,9 @@ int sub_uid_close (bool process_selinux) - return commonio_close (&subordinate_uid_db, process_selinux); - } - --int sub_uid_unlock (void) -+int sub_uid_unlock (bool process_selinux) - { -- return commonio_unlock (&subordinate_uid_db, true); -+ return commonio_unlock (&subordinate_uid_db, process_selinux); - } - - uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count) -@@ -1022,7 +1022,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - } - if (!sub_uid_open(O_CREAT | O_RDWR)) { - printf("Failed opening subuids (errno %d)\n", errno); -- sub_uid_unlock(); -+ sub_uid_unlock(true); - return false; - } - db = &subordinate_uid_db; -@@ -1069,7 +1069,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - out: - if (id_type == ID_TYPE_UID) { - sub_uid_close(true); -- sub_uid_unlock(); -+ sub_uid_unlock(true); - } else { - sub_gid_close(true); - sub_gid_unlock(); -@@ -1094,7 +1094,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - } - if (!sub_uid_open(O_CREAT | O_RDWR)) { - printf("Failed opening subuids (errno %d)\n", errno); -- sub_uid_unlock(); -+ sub_uid_unlock(true); - return false; - } - db = &subordinate_uid_db; -@@ -1119,7 +1119,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - - if (id_type == ID_TYPE_UID) { - sub_uid_close(true); -- sub_uid_unlock(); -+ sub_uid_unlock(true); - } else { - sub_gid_close(true); - sub_gid_unlock(); -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index 63f5b1fb..7914613d 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -21,7 +21,7 @@ extern int sub_uid_lock (void); - extern int sub_uid_setdbname (const char *filename); - extern /*@observer@*/const char *sub_uid_dbname (void); - extern int sub_uid_open (int mode); --extern int sub_uid_unlock (void); -+extern int sub_uid_unlock (bool process_selinux); - extern int sub_uid_add (const char *owner, uid_t start, unsigned long count); - extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count); - extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); -diff --git a/src/newusers.c b/src/newusers.c -index 261a5911..65bedf9b 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -196,7 +196,7 @@ static void fail_exit (int code) - #endif - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -1021,7 +1021,7 @@ static void close_files (void) - #endif - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -diff --git a/src/useradd.c b/src/useradd.c -index cb7ac88e..f65d24d1 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -288,7 +288,7 @@ static void fail_exit (int code) - } - #endif - #ifdef ENABLE_SUBIDS -- if (sub_uid_locked && sub_uid_unlock() == 0) { -+ if (sub_uid_locked && sub_uid_unlock(true) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); - /* continue */ -@@ -1623,7 +1623,7 @@ static void close_files (void) - - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index 80ed1a48..68e53b85 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -454,7 +454,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (E_SUB_UID_UPDATE); - } -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -515,7 +515,7 @@ static void fail_exit (int code) - #endif /* SHADOWGRP */ - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index 69ea8e55..fc6cc51c 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -663,7 +663,7 @@ fail_exit (int code) - } - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -1566,7 +1566,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); - fail_exit (E_SUB_UID_UPDATE); - } -- if (sub_uid_unlock () == 0) { -+ if (sub_uid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ --- -2.50.0 - - -From 7b2bbdd0347c34bc5e094caf26c55694fb5935e7 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 25 Apr 2025 16:12:40 +0200 -Subject: [PATCH 15/15] lib/, src/: add SELinux control flag in - sub_gid_unlock() - -Expand sub_gid_unlock() interface to add a control flag for SELinux file -context processing. - -Signed-off-by: Iker Pedrosa ---- - lib/subordinateio.c | 12 ++++++------ - lib/subordinateio.h | 2 +- - src/newusers.c | 4 ++-- - src/useradd.c | 4 ++-- - src/userdel.c | 4 ++-- - src/usermod.c | 4 ++-- - 6 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/lib/subordinateio.c b/lib/subordinateio.c -index eaa2dc99..d1ab03f3 100644 ---- a/lib/subordinateio.c -+++ b/lib/subordinateio.c -@@ -780,9 +780,9 @@ int sub_gid_close (bool process_selinux) - return commonio_close (&subordinate_gid_db, process_selinux); - } - --int sub_gid_unlock (void) -+int sub_gid_unlock (bool process_selinux) - { -- return commonio_unlock (&subordinate_gid_db, true); -+ return commonio_unlock (&subordinate_gid_db, process_selinux); - } - - gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count) -@@ -1034,7 +1034,7 @@ bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, b - } - if (!sub_gid_open(O_CREAT | O_RDWR)) { - printf("Failed opening subgids (errno %d)\n", errno); -- sub_gid_unlock(); -+ sub_gid_unlock(true); - return false; - } - db = &subordinate_gid_db; -@@ -1072,7 +1072,7 @@ out: - sub_uid_unlock(true); - } else { - sub_gid_close(true); -- sub_gid_unlock(); -+ sub_gid_unlock(true); - } - - return ret; -@@ -1106,7 +1106,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - } - if (!sub_gid_open(O_CREAT | O_RDWR)) { - printf("Failed opening subgids (errno %d)\n", errno); -- sub_gid_unlock(); -+ sub_gid_unlock(true); - return false; - } - db = &subordinate_gid_db; -@@ -1122,7 +1122,7 @@ bool release_subid_range(struct subordinate_range *range, enum subid_type id_typ - sub_uid_unlock(true); - } else { - sub_gid_close(true); -- sub_gid_unlock(); -+ sub_gid_unlock(true); - } - - return ret; -diff --git a/lib/subordinateio.h b/lib/subordinateio.h -index 7914613d..1ca4b66d 100644 ---- a/lib/subordinateio.h -+++ b/lib/subordinateio.h -@@ -39,7 +39,7 @@ extern int sub_gid_lock (void); - extern int sub_gid_setdbname (const char *filename); - extern /*@observer@*/const char *sub_gid_dbname (void); - extern int sub_gid_open (int mode); --extern int sub_gid_unlock (void); -+extern int sub_gid_unlock (bool process_selinux); - extern int sub_gid_add (const char *owner, gid_t start, unsigned long count); - extern int sub_gid_remove (const char *owner, gid_t start, unsigned long count); - extern uid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count); -diff --git a/src/newusers.c b/src/newusers.c -index 65bedf9b..4eb6065c 100644 ---- a/src/newusers.c -+++ b/src/newusers.c -@@ -203,7 +203,7 @@ static void fail_exit (int code) - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -1029,7 +1029,7 @@ static void close_files (void) - sub_uid_locked = false; - } - if (is_sub_gid) { -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -diff --git a/src/useradd.c b/src/useradd.c -index f65d24d1..98c2d284 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -293,7 +293,7 @@ static void fail_exit (int code) - SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); - /* continue */ - } -- if (sub_gid_locked && sub_gid_unlock() == 0) { -+ if (sub_gid_locked && sub_gid_unlock(true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); - /* continue */ -@@ -1637,7 +1637,7 @@ static void close_files (void) - sub_uid_locked = false; - } - if (is_sub_gid) { -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - #ifdef WITH_AUDIT -diff --git a/src/userdel.c b/src/userdel.c -index 68e53b85..524c96a6 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -468,7 +468,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); - fail_exit (E_SUB_GID_UPDATE); - } -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -522,7 +522,7 @@ static void fail_exit (int code) - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -diff --git a/src/usermod.c b/src/usermod.c -index fc6cc51c..68000a0e 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -670,7 +670,7 @@ fail_exit (int code) - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -1579,7 +1579,7 @@ static void close_files (void) - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); - fail_exit (E_SUB_GID_UPDATE); - } -- if (sub_gid_unlock () == 0) { -+ if (sub_gid_unlock (true) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ --- -2.50.0 - -diff -up shadow-4.18.0/src/newusers.c.test-chroot2 shadow-4.18.0/src/newusers.c ---- shadow-4.18.0/src/newusers.c.test-chroot2 2025-07-08 11:22:16.257291774 +0200 -+++ shadow-4.18.0/src/newusers.c 2025-07-08 11:23:28.210122190 +0200 -@@ -60,6 +60,10 @@ - #include "string/strtok/stpsep.h" - #include "string/strtok/strsep2arr.h" - -+struct option_flags { -+ bool chroot; -+}; -+ - - /* - * Global variables -@@ -103,7 +107,7 @@ static bool sub_gid_locked = false; - - /* local function prototypes */ - NORETURN static void usage (int status); --NORETURN static void fail_exit (int); -+NORETURN static void fail_exit (int, bool); - static int add_group (const char *, const char *, gid_t *, gid_t); - static int get_user_id (const char *, uid_t *); - static int add_user (const char *, uid_t, gid_t); -@@ -113,11 +117,11 @@ static int update_passwd (struct passwd - #endif /* !USE_PAM */ - #endif /* !ACCT_TOOLS_SETUID */ - static int add_passwd (struct passwd *, const char *); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (void); - static void check_perms (void); --static void open_files (void); --static void close_files (void); -+static void open_files (bool process_selinux); -+static void close_files (struct option_flags *flags); - - extern int allow_bad_names; - -@@ -170,24 +174,24 @@ static void usage (int status) - /* - * fail_exit - undo as much as possible - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } - } - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ - } - } - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -195,7 +199,7 @@ static void fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -204,14 +208,14 @@ static void fail_exit (int code) - #endif - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -637,7 +641,7 @@ static int add_passwd (struct passwd *pw - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - #ifndef ACCT_TOOLS_SETUID -@@ -696,6 +700,7 @@ static void process_flags (int argc, cha - rflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - #ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM -@@ -755,7 +760,7 @@ static void process_flags (int argc, cha - - SNPRINTF(buf, "%s: %s", Prog, argv[1]); - perror (buf); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, !flags->chroot); - } - } - -@@ -859,7 +864,7 @@ static void check_perms (void) - /* - * open_files - lock and open the password, group and shadow databases - */ --static void open_files (void) -+static void open_files (bool process_selinux) - { - /* - * Lock the password files and open them for update. This will bring -@@ -871,7 +876,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - pw_locked = true; - if (is_shadow) { -@@ -879,7 +884,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - spw_locked = true; - } -@@ -887,7 +892,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - gr_locked = true; - #ifdef SHADOWGRP -@@ -896,7 +901,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - sgr_locked = true; - } -@@ -907,7 +912,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_uid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - sub_uid_locked = true; - } -@@ -916,7 +921,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_gid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - sub_gid_locked = true; - } -@@ -924,20 +929,20 @@ static void open_files (void) - - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (is_shadow && (spw_open (O_CREAT | O_RDWR) == 0)) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - #ifdef SHADOWGRP - if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - #endif - #ifdef ENABLE_SUBIDS -@@ -946,7 +951,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_uid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - if (is_sub_gid) { -@@ -954,7 +959,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_gid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ -@@ -963,14 +968,18 @@ static void open_files (void) - /* - * close_files - close and unlock the password, group and shadow databases - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (pw_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; -+ -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -978,14 +987,14 @@ static void close_files (void) - pw_locked = false; - - if (is_shadow) { -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -995,29 +1004,29 @@ static void close_files (void) - spw_locked = false; - } - -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - #ifdef ENABLE_SUBIDS -- if (is_sub_uid && (sub_uid_close (true) == 0)) { -+ if (is_sub_uid && (sub_uid_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } -- if (is_sub_gid && (sub_gid_close (true) == 0)) { -+ if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - #endif /* ENABLE_SUBIDS */ - -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); -@@ -1028,14 +1037,14 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); -@@ -1047,7 +1056,7 @@ static void close_files (void) - #endif - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -1055,7 +1064,7 @@ static void close_files (void) - sub_uid_locked = false; - } - if (is_sub_gid) { -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -1100,6 +1109,8 @@ int main (int argc, char **argv) - size_t nusers = 0; - #endif /* USE_PAM */ - #endif /* ACCT_TOOLS_SETUID */ -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -1113,7 +1124,8 @@ int main (int argc, char **argv) - - OPENLOG ("newusers"); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - check_perms (); - -@@ -1127,7 +1139,7 @@ int main (int argc, char **argv) - is_sub_gid = sub_gid_file_present () && !rflg; - #endif /* ENABLE_SUBIDS */ - -- open_files (); -+ open_files (process_selinux); - - /* - * Read each line. The line has the same format as a password file -@@ -1143,13 +1155,13 @@ int main (int argc, char **argv) - if (stpsep(buf, "\n") == NULL && feof(stdin) == 0) { - fprintf (stderr, _("%s: line %jd: line too long\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - if (STRSEP2ARR(buf, ":", fields) == -1) { - fprintf (stderr, _("%s: line %jd: invalid line\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - /* -@@ -1161,14 +1173,14 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot update the entry of user %s (not in the passwd database)\n"), - Prog, fields[0]); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - if (NULL == pw && get_user_id(fields[2], &uid) != 0) { - fprintf (stderr, - _("%s: line %jd: can't create user\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - /* -@@ -1188,7 +1200,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: can't create group\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - /* -@@ -1203,7 +1215,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: can't create user\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - /* -@@ -1215,7 +1227,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: user '%s' does not exist in %s\n"), - Prog, line, fields[0], pw_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - newpw = *pw; - -@@ -1230,7 +1242,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: %s\n"), - Prog, line, strerror(errno)); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - lines[nusers-1] = line; - usernames[nusers-1] = xstrdup(fields[0]); -@@ -1241,7 +1253,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: can't update password\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (!streq(fields[4], "")) { - newpw.pw_gecos = fields[4]; -@@ -1264,7 +1276,7 @@ int main (int argc, char **argv) - fprintf(stderr, - _("%s: line %jd: homedir must be an absolute path\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (mkdir (newpw.pw_dir, mode) != 0) { - fprintf (stderr, -@@ -1272,7 +1284,7 @@ int main (int argc, char **argv) - Prog, line, newpw.pw_dir, - strerror (errno)); - if (errno != EEXIST) { -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - if (chown(newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0) -@@ -1281,7 +1293,7 @@ int main (int argc, char **argv) - _("%s: line %jd: chown %s failed: %s\n"), - Prog, line, newpw.pw_dir, - strerror (errno)); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - -@@ -1292,7 +1304,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: line %jd: can't update entry\n"), - Prog, line); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - - #ifdef ENABLE_SUBIDS -@@ -1307,14 +1319,14 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: can't find subordinate user range\n"), - Prog); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) - { - fprintf (stderr, - _("%s: failed to prepare new %s entry\n"), - Prog, sub_uid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - -@@ -1328,13 +1340,13 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: can't find subordinate group range\n"), - Prog); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { - fprintf (stderr, - _("%s: failed to prepare new %s entry\n"), - Prog, sub_uid_dbname ()); -- fail_exit (EXIT_FAILURE); -+ fail_exit (EXIT_FAILURE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ -@@ -1347,7 +1359,7 @@ int main (int argc, char **argv) - * changes to be written out all at once, and then unlocked - * afterwards. - */ -- close_files (); -+ close_files (&flags); - - nscd_flush_cache ("passwd"); - nscd_flush_cache ("group"); -diff -up shadow-4.18.0/src/useradd.c.test-chroot2 shadow-4.18.0/src/useradd.c ---- shadow-4.18.0/src/useradd.c.test-chroot2 2025-07-08 11:22:16.257383838 +0200 -+++ shadow-4.18.0/src/useradd.c 2025-07-08 11:22:16.261386737 +0200 -@@ -92,6 +92,15 @@ - #ifndef LASTLOG_FILE - #define LASTLOG_FILE "/var/log/lastlog" - #endif -+ -+/* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ - /* - * Global variables - */ -@@ -219,40 +228,41 @@ static bool home_added = false; - #define DLOG_INIT "LOG_INIT" - - /* local function prototypes */ --NORETURN static void fail_exit (int); --static void get_defaults (void); -+NORETURN static void fail_exit (int, bool); -+static void get_defaults (struct option_flags *); - static void show_defaults (void); - static int set_defaults (void); --static int get_groups (char *); --static struct group * get_local_group (char * grp_name); -+static int get_groups (char *, struct option_flags *); -+static struct group * get_local_group (char * grp_name, bool process_selinux); - NORETURN static void usage (int status); - static void new_pwent (struct passwd *); - - static void new_spent (struct spwd *); --static void grp_update (void); -+static void grp_update (bool); - --static void process_flags (int argc, char **argv); --static void close_files (void); --static void close_group_files (void); --static void unlock_group_files (void); --static void open_files (void); --static void open_group_files (void); --static void open_shadow (void); -+static void process_flags (int argc, char **argv, struct option_flags *flags); -+static void close_files (struct option_flags *flags); -+static void close_group_files (bool process_selinux); -+static void unlock_group_files (bool process_selinux); -+static void open_files (bool process_selinux); -+static void open_group_files (bool process_selinux); -+static void open_shadow (bool process_selinux); - static void faillog_reset (uid_t); - #ifdef ENABLE_LASTLOG - static void lastlog_reset (uid_t); - #endif /* ENABLE_LASTLOG */ - static void tallylog_reset (const char *); --static void usr_update (unsigned long subuid_count, unsigned long subgid_count); --static void create_home (void); --static void create_mail (void); -+static void usr_update (unsigned long subuid_count, unsigned long subgid_count, -+ struct option_flags *flags); -+static void create_home (struct option_flags *flags); -+static void create_mail (struct option_flags *flags); - static void check_uid_range(int rflg, uid_t user_id); - - - /* - * fail_exit - undo as much as possible - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - #ifdef WITH_AUDIT - int type; -@@ -265,35 +275,35 @@ static void fail_exit (int code) - SYSLOG((LOG_ERR, "failed to remove %s", prefix_user_home)); - } - -- if (spw_locked && spw_unlock(true) == 0) { -+ if (spw_locked && spw_unlock(process_selinux) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", spw_dbname())); - /* continue */ - } -- if (pw_locked && pw_unlock(true) == 0) { -+ if (pw_locked && pw_unlock(process_selinux) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", pw_dbname())); - /* continue */ - } -- if (gr_locked && gr_unlock(true) == 0) { -+ if (gr_locked && gr_unlock(process_selinux) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", gr_dbname())); - /* continue */ - } - #ifdef SHADOWGRP -- if (sgr_locked && sgr_unlock(true) == 0) { -+ if (sgr_locked && sgr_unlock(process_selinux) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sgr_dbname())); - /* continue */ - } - #endif - #ifdef ENABLE_SUBIDS -- if (sub_uid_locked && sub_uid_unlock(true) == 0) { -+ if (sub_uid_locked && sub_uid_unlock(process_selinux) == 0) { - fprintf(stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname()); - SYSLOG((LOG_ERR, "failed to unlock %s", sub_uid_dbname())); - /* continue */ - } -- if (sub_gid_locked && sub_gid_unlock(true) == 0) { -+ if (sub_gid_locked && sub_gid_unlock(process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname())); - /* continue */ -@@ -322,7 +332,7 @@ static void fail_exit (int code) - * file does not exist. - */ - static void --get_defaults(void) -+get_defaults(struct option_flags *flags) - { - FILE *fp; - char *default_file = USER_DEFAULTS_FILE; -@@ -377,7 +387,7 @@ get_defaults(void) - ccp = cp; - - if (streq(buf, DGROUPS)) { -- if (get_groups (cp) != 0) { -+ if (get_groups (cp, flags) != 0) { - fprintf (stderr, - _("%s: the '%s=' configuration in %s has an invalid group, ignoring the bad group\n"), - Prog, DGROUPS, default_file); -@@ -736,11 +746,14 @@ err_free_new: - * converts it to a NULL-terminated array. Any unknown group - * names are reported as errors. - */ --static int get_groups (char *list) -+static int get_groups (char *list, struct option_flags *flags) - { - struct group *grp; - bool errors = false; - int ngroups = 0; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - /* - * Free previous group list before creating a new one. -@@ -758,7 +771,7 @@ static int get_groups (char *list) - /* - * Open the group files - */ -- open_group_files (); -+ open_group_files (process_selinux); - - /* - * So long as there is some data to be converted, strip off -@@ -777,7 +790,7 @@ static int get_groups (char *list) - * Names starting with digits are treated as numerical - * GID values, otherwise the string is looked up as is. - */ -- grp = get_local_group(g); -+ grp = get_local_group(g, process_selinux); - - /* - * There must be a match, either by GID value or by -@@ -815,8 +828,8 @@ static int get_groups (char *list) - gr_free (grp); - } - -- close_group_files (); -- unlock_group_files (); -+ close_group_files (process_selinux); -+ unlock_group_files (process_selinux); - - user_groups[ngroups] = NULL; - -@@ -837,7 +850,7 @@ static int get_groups (char *list) - * If the name exists the group information is returned, otherwise NULL is - * returned. - */ --static struct group * get_local_group(char * grp_name) -+static struct group * get_local_group(char * grp_name, bool process_selinux) - { - gid_t gid; - struct group *result_grp = NULL; -@@ -854,7 +867,7 @@ static struct group * get_local_group(ch - fprintf (stderr, - _("%s: Out of memory. Cannot find group '%s'.\n"), - Prog, grp_name); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - } - -@@ -986,7 +999,7 @@ static void new_spent (struct spwd *spen - * close_files() should be called afterwards to commit the changes - * and unlocking the group files. - */ --static void grp_update (void) -+static void grp_update (bool process_selinux) - { - const struct group *grp; - struct group *ngrp; -@@ -1022,7 +1035,7 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); -- fail_exit (E_GRP_UPDATE); /* XXX */ -+ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */ - } - - /* -@@ -1035,7 +1048,7 @@ static void grp_update (void) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), ngrp->gr_name); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name)); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef WITH_AUDIT - audit_logger_with_group (AUDIT_USER_MGMT, -@@ -1085,7 +1098,7 @@ static void grp_update (void) - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); -- fail_exit (E_GRP_UPDATE); /* XXX */ -+ fail_exit (E_GRP_UPDATE, process_selinux); /* XXX */ - } - - /* -@@ -1099,7 +1112,7 @@ static void grp_update (void) - Prog, sgr_dbname (), nsgrp->sg_namp); - SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name)); - -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef WITH_AUDIT - audit_logger_with_group (AUDIT_USER_MGMT, -@@ -1121,7 +1134,7 @@ static void grp_update (void) - * the values that the user will be created with accordingly. The - * values are checked for sanity. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - const struct group *grp; - bool anyflag = false; -@@ -1296,7 +1309,7 @@ static void process_flags (int argc, cha - gflg = true; - break; - case 'G': -- if (get_groups (optarg) != 0) { -+ if (get_groups (optarg, flags) != 0) { - exit (E_NOTFOUND); - } - if (NULL != user_groups[0]) { -@@ -1356,8 +1369,10 @@ static void process_flags (int argc, cha - rflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 's': - if ( ( !VALID (optarg) ) -@@ -1562,38 +1577,42 @@ static void process_flags (int argc, cha - * close_files() closes all of the files that were opened for this - * new user. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (pw_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } -- if (is_shadow_pwd && (spw_close (true) == 0)) { -+ if (is_shadow_pwd && (spw_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - -- close_group_files (); -+ close_group_files (process_selinux); - - #ifdef ENABLE_SUBIDS -- if (is_sub_uid && (sub_uid_close (true) == 0)) { -+ if (is_sub_uid && (sub_uid_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } -- if (is_sub_gid && (sub_gid_close (true) == 0)) { -+ if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - #endif /* ENABLE_SUBIDS */ - if (is_shadow_pwd) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - #ifdef WITH_AUDIT -@@ -1606,7 +1625,7 @@ static void close_files (void) - } - spw_locked = false; - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - #ifdef WITH_AUDIT -@@ -1619,11 +1638,11 @@ static void close_files (void) - } - pw_locked = false; - -- unlock_group_files (); -+ unlock_group_files (process_selinux); - - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - #ifdef WITH_AUDIT -@@ -1637,7 +1656,7 @@ static void close_files (void) - sub_uid_locked = false; - } - if (is_sub_gid) { -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - #ifdef WITH_AUDIT -@@ -1659,25 +1678,25 @@ static void close_files (void) - * close_group_files() closes all of the files that were opened related - * with groups. This causes any modified entries to be written out. - */ --static void close_group_files (void) -+static void close_group_files (bool process_selinux) - { - if (!do_grp_update) - return; - -- if (gr_close(true) == 0) { -+ if (gr_close(process_selinux) == 0) { - fprintf(stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname()); - SYSLOG((LOG_ERR, "failure while writing changes to %s", gr_dbname())); -- fail_exit(E_GRP_UPDATE); -+ fail_exit(E_GRP_UPDATE, process_selinux); - } - #ifdef SHADOWGRP -- if (is_shadow_grp && sgr_close(true) == 0) { -+ if (is_shadow_grp && sgr_close(process_selinux) == 0) { - fprintf(stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname()); - SYSLOG((LOG_ERR, "failure while writing changes to %s", sgr_dbname())); -- fail_exit(E_GRP_UPDATE); -+ fail_exit(E_GRP_UPDATE, process_selinux); - } - #endif /* SHADOWGRP */ - } -@@ -1688,9 +1707,9 @@ static void close_group_files (void) - * unlock_group_files() unlocks all of the files that were locked related - * with groups. This causes any modified entries to be written out. - */ --static void unlock_group_files (void) -+static void unlock_group_files (bool process_selinux) - { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - #ifdef WITH_AUDIT -@@ -1704,7 +1723,7 @@ static void unlock_group_files (void) - gr_locked = false; - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - #ifdef WITH_AUDIT -@@ -1725,7 +1744,7 @@ static void unlock_group_files (void) - * - * open_files() opens the two password files. - */ --static void open_files (void) -+static void open_files (bool process_selinux) - { - if (pw_lock () == 0) { - fprintf (stderr, -@@ -1736,12 +1755,12 @@ static void open_files (void) - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - - /* shadow file will be opened by open_shadow(); */ - -- open_group_files (); -+ open_group_files (process_selinux); - - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -@@ -1749,14 +1768,14 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - sub_uid_locked = true; - if (sub_uid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - } - if (is_sub_gid) { -@@ -1764,31 +1783,31 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - sub_gid_locked = true; - if (sub_gid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ - } - --static void open_group_files (void) -+static void open_group_files (bool process_selinux) - { - if (gr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - #ifdef SHADOWGRP -@@ -1797,20 +1816,20 @@ static void open_group_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - sgr_locked = true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - } - #endif /* SHADOWGRP */ - } - --static void open_shadow (void) -+static void open_shadow (bool process_selinux) - { - if (!is_shadow_pwd) { - return; -@@ -1819,14 +1838,14 @@ static void open_shadow (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - spw_locked = true; - if (spw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - } - -@@ -1880,7 +1899,7 @@ static void new_sgent (struct sgrp *sgen - * grp_add() writes the new records to the group files. - */ - --static void grp_add (void) -+static void grp_add (bool process_selinux) - { - struct group grp; - -@@ -1909,7 +1928,7 @@ static void grp_add (void) - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef SHADOWGRP - /* -@@ -1925,7 +1944,7 @@ static void grp_add (void) - grp.gr_name, AUDIT_NO_ID, - SHADOW_AUDIT_FAILURE); - #endif -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #endif /* SHADOWGRP */ - SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid)); -@@ -2074,11 +2093,16 @@ static void tallylog_reset (const char * - * usr_update() creates the password file entries for this user - * and will update the group entries if required. - */ --static void usr_update (unsigned long subuid_count, unsigned long subgid_count) -+static void -+usr_update (unsigned long subuid_count, unsigned long subgid_count, -+ struct option_flags *flags) - { - struct passwd pwent; - struct spwd spent; - char *tty; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - /* - * Fill in the password structure with any new fields, making -@@ -2119,7 +2143,7 @@ static void usr_update (unsigned long su - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - - /* -@@ -2129,7 +2153,7 @@ static void usr_update (unsigned long su - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), spent.sp_namp); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - #ifdef ENABLE_SUBIDS - if (is_sub_uid && !local_sub_uid_assigned(user_name) && -@@ -2137,14 +2161,14 @@ static void usr_update (unsigned long su - fprintf (stderr, - _("%s: failed to prepare the new %s entry\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - if (is_sub_gid && !local_sub_gid_assigned(user_name) && - (sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - #endif /* ENABLE_SUBIDS */ - -@@ -2163,7 +2187,7 @@ static void usr_update (unsigned long su - * Do any group file updates for this user. - */ - if (do_grp_update) { -- grp_update (); -+ grp_update (process_selinux); - } - } - -@@ -2174,11 +2198,14 @@ static void usr_update (unsigned long su - * already exist. It will be created mode 755 owned by the user - * with the user's default group. - */ --static void create_home (void) -+static void create_home (struct option_flags *flags) - { - char path[strlen(prefix_user_home) + 2]; - char *bhome, *cp; - mode_t mode; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - if (access (prefix_user_home, F_OK) == 0) - return; -@@ -2189,15 +2216,17 @@ static void create_home (void) - fprintf(stderr, - _("%s: error while duplicating string %s\n"), - Prog, user_home); -- fail_exit(E_HOMEDIR); -+ fail_exit(E_HOMEDIR, process_selinux); - } - - #ifdef WITH_SELINUX -- if (set_selinux_file_context(prefix_user_home, S_IFDIR) != 0) { -- fprintf(stderr, -- _("%s: cannot set SELinux context for home directory %s\n"), -- Prog, user_home); -- fail_exit(E_HOMEDIR); -+ if (process_selinux) { -+ if (set_selinux_file_context(prefix_user_home, S_IFDIR) != 0) { -+ fprintf(stderr, -+ _("%s: cannot set SELinux context for home directory %s\n"), -+ Prog, user_home); -+ fail_exit(E_HOMEDIR, process_selinux); -+ } - } - #endif - -@@ -2227,14 +2256,14 @@ static void create_home (void) - fprintf(stderr, - _("%s: error while duplicating string in BTRFS check %s\n"), - Prog, path); -- fail_exit(E_HOMEDIR); -+ fail_exit(E_HOMEDIR, process_selinux); - } - stpcpy(&btrfs_check[strlen(path) - strlen(cp) - 1], ""); - if (is_btrfs(btrfs_check) <= 0) { - fprintf(stderr, - _("%s: home directory \"%s\" must be mounted on BTRFS\n"), - Prog, path); -- fail_exit(E_HOMEDIR); -+ fail_exit(E_HOMEDIR, process_selinux); - } - free(btrfs_check); - // make subvolume to mount for user instead of directory -@@ -2242,7 +2271,7 @@ static void create_home (void) - fprintf(stderr, - _("%s: failed to create BTRFS subvolume: %s\n"), - Prog, path); -- fail_exit(E_HOMEDIR); -+ fail_exit(E_HOMEDIR, process_selinux); - } - } - else -@@ -2250,7 +2279,7 @@ static void create_home (void) - if (mkdir(path, 0) != 0) { - fprintf(stderr, _("%s: cannot create directory %s\n"), - Prog, path); -- fail_exit(E_HOMEDIR); -+ fail_exit(E_HOMEDIR, process_selinux); - } - if (chown(path, 0, 0) < 0) { - fprintf(stderr, -@@ -2278,12 +2307,14 @@ static void create_home (void) - user_name, user_id, SHADOW_AUDIT_SUCCESS); - #endif - #ifdef WITH_SELINUX -- /* Reset SELinux to create files with default contexts */ -- if (reset_selinux_file_context() != 0) { -- fprintf(stderr, -- _("%s: cannot reset SELinux file creation context\n"), -- Prog); -- fail_exit(E_HOMEDIR); -+ if (process_selinux) { -+ /* Reset SELinux to create files with default contexts */ -+ if (reset_selinux_file_context() != 0) { -+ fprintf(stderr, -+ _("%s: cannot reset SELinux file creation context\n"), -+ Prog); -+ fail_exit(E_HOMEDIR, process_selinux); -+ } - } - #endif - } -@@ -2295,7 +2326,7 @@ static void create_home (void) - * exist. It will be created mode 660 owned by the user and group - * 'mail' - */ --static void create_mail (void) -+static void create_mail (struct option_flags *flags) - { - int fd; - char *file; -@@ -2303,6 +2334,9 @@ static void create_mail (void) - mode_t mode; - const char *spool; - struct group *gr; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - if (!strcaseeq(create_mail_spool, "yes")) - return; -@@ -2322,11 +2356,13 @@ static void create_mail (void) - file = xaprintf("%s/%s", spool, user_name); - - #ifdef WITH_SELINUX -- if (set_selinux_file_context(file, S_IFREG) != 0) { -- fprintf(stderr, -- _("%s: cannot set SELinux context for mailbox file %s\n"), -- Prog, file); -- fail_exit(E_MAILBOXFILE); -+ if (process_selinux) { -+ if (set_selinux_file_context(file, S_IFREG) != 0) { -+ fprintf(stderr, -+ _("%s: cannot set SELinux context for mailbox file %s\n"), -+ Prog, file); -+ fail_exit(E_MAILBOXFILE, process_selinux); -+ } - } - #endif - -@@ -2362,12 +2398,14 @@ static void create_mail (void) - perror (_("Closing mailbox file")); - } - #ifdef WITH_SELINUX -- /* Reset SELinux to create files with default contexts */ -- if (reset_selinux_file_context() != 0) { -- fprintf(stderr, -- _("%s: cannot reset SELinux file creation context\n"), -- Prog); -- fail_exit(E_MAILBOXFILE); -+ if (process_selinux) { -+ /* Reset SELinux to create files with default contexts */ -+ if (reset_selinux_file_context() != 0) { -+ fprintf(stderr, -+ _("%s: cannot reset SELinux file creation context\n"), -+ Prog); -+ fail_exit(E_MAILBOXFILE, process_selinux); -+ } - } - #endif - } -@@ -2409,6 +2447,8 @@ int main (int argc, char **argv) - #endif - unsigned long subuid_count = 0; - unsigned long subgid_count = 0; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -2439,9 +2479,10 @@ int main (int argc, char **argv) - is_shadow_grp = sgr_file_present (); - #endif - -- get_defaults (); -+ get_defaults (&flags); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot && !flags.prefix; - - #ifdef ENABLE_SUBIDS - uid_min = getdef_ulong ("UID_MIN", 1000UL); -@@ -2470,7 +2511,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - retval = pam_start (Prog, pampw?pampw->pw_name:"root", &conv, &pamh); -@@ -2491,7 +2532,7 @@ int main (int argc, char **argv) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -2515,7 +2556,7 @@ int main (int argc, char **argv) - */ - if (prefix_getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */ - fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name); -- fail_exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE, process_selinux); - } - - /* -@@ -2530,7 +2571,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: group %s exists - if you want to add this user to that group, use -g.\n"), - Prog, user_name); -- fail_exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE, process_selinux); - } - } - -@@ -2543,7 +2584,7 @@ int main (int argc, char **argv) - * - flush nscd caches for passwd and group services, - * - then close and update the files. - */ -- open_files (); -+ open_files (process_selinux); - - if (!oflg) { - /* first, seek for a valid uid to use for this user. -@@ -2552,14 +2593,14 @@ int main (int argc, char **argv) - if (!uflg) { - if (find_new_uid (rflg, &user_id, NULL) < 0) { - fprintf (stderr, _("%s: can't create user\n"), Prog); -- fail_exit (E_UID_IN_USE); -+ fail_exit (E_UID_IN_USE, process_selinux); - } - } else { - if (prefix_getpwuid (user_id) != NULL) { - fprintf (stderr, - _("%s: UID %lu is not unique\n"), - Prog, (unsigned long) user_id); -- fail_exit (E_UID_IN_USE); -+ fail_exit (E_UID_IN_USE, process_selinux); - } - } - } -@@ -2572,11 +2613,11 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Failed to create tcb directory for %s\n"), - Prog, user_name); -- fail_exit (E_UID_IN_USE); -+ fail_exit (E_UID_IN_USE, process_selinux); - } - } - #endif -- open_shadow (); -+ open_shadow (process_selinux); - - /* do we have to add a group for that user? This is why we need to - * open the group files in the open_files() function --gafton */ -@@ -2585,9 +2626,9 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: can't create group\n"), - Prog); -- fail_exit (4); -+ fail_exit (4, process_selinux); - } -- grp_add (); -+ grp_add (process_selinux); - } - - #ifdef ENABLE_SUBIDS -@@ -2596,7 +2637,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: can't create subordinate user IDs\n"), - Prog); -- fail_exit(E_SUB_UID_UPDATE); -+ fail_exit(E_SUB_UID_UPDATE, process_selinux); - } - } - if (is_sub_gid && subgid_count != 0) { -@@ -2604,14 +2645,14 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: can't create subordinate group IDs\n"), - Prog); -- fail_exit(E_SUB_GID_UPDATE); -+ fail_exit(E_SUB_GID_UPDATE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ - -- usr_update (subuid_count, subgid_count); -+ usr_update (subuid_count, subgid_count, &flags); - -- close_files (); -+ close_files (&flags); - - nscd_flush_cache ("passwd"); - nscd_flush_cache ("group"); -@@ -2637,13 +2678,13 @@ int main (int argc, char **argv) - "add-selinux-user-mapping", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -+ fail_exit (E_SE_UPDATE, process_selinux); - } - } - #endif /* WITH_SELINUX */ - - if (mflg) { -- create_home (); -+ create_home (&flags); - if (home_added) { - copy_tree (def_template, prefix_user_home, false, true, - (uid_t)-1, user_id, (gid_t)-1, user_gid); -@@ -2660,7 +2701,7 @@ int main (int argc, char **argv) - - /* Do not create mail directory for system accounts */ - if (!rflg) { -- create_mail (); -+ create_mail (&flags); - } - - if (run_parts ("/etc/shadow-maint/useradd-post.d", user_name, -diff -up shadow-4.18.0/src/userdel.c.test-chroot2 shadow-4.18.0/src/userdel.c ---- shadow-4.18.0/src/userdel.c.test-chroot2 2025-07-08 11:22:16.257469516 +0200 -+++ shadow-4.18.0/src/userdel.c 2025-07-08 11:22:16.263226317 +0200 -@@ -73,6 +73,14 @@ - #endif /* ENABLE_SUBIDS */ - - /* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ -+/* - * Global variables - */ - static const char Prog[] = "userdel"; -@@ -87,7 +95,6 @@ static bool rflg = false; - #ifdef WITH_SELINUX - static bool Zflg = false; - #endif --static bool Rflg = false; - - static bool is_shadow_pwd; - -@@ -109,12 +116,12 @@ static const char* prefix = ""; - - /* local function prototypes */ - static void usage (int status); --static void update_groups (void); --static void remove_usergroup (void); --static void close_files (void); --static void fail_exit (int); --static void open_files (void); --static void update_user (void); -+static void update_groups (bool process_selinux); -+static void remove_usergroup (bool process_selinux); -+static void close_files (struct option_flags *flags); -+static void fail_exit (int, bool); -+static void open_files (bool process_selinux); -+static void update_user (bool process_selinux); - static void user_cancel (const char *); - - #ifdef EXTRA_CHECK_HOME_DIR -@@ -162,7 +169,7 @@ static void usage (int status) - * name is their user name) and delete them too (only if USERGROUPS_ENAB - * is enabled). - */ --static void update_groups (void) -+static void update_groups (bool process_selinux) - { - const struct group *grp; - struct group *ngrp; -@@ -219,7 +226,7 @@ static void update_groups (void) - } - - if (getdef_bool ("USERGROUPS_ENAB")) { -- remove_usergroup (); -+ remove_usergroup (process_selinux); - } - - #ifdef SHADOWGRP -@@ -291,7 +298,7 @@ static void update_groups (void) - * + it has no other members - * + it is not the primary group of any other user - */ --static void remove_usergroup (void) -+static void remove_usergroup (bool process_selinux) - { - const struct group *grp; - const struct passwd *pwd = NULL; -@@ -346,7 +353,7 @@ static void remove_usergroup (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - #ifdef WITH_AUDIT -@@ -365,7 +372,7 @@ static void remove_usergroup (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef WITH_AUDIT - audit_logger_with_group (AUDIT_GRP_MGMT, -@@ -388,14 +395,18 @@ static void remove_usergroup (void) - * close_files() closes all of the files that were opened for this - * new user. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (pw_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -403,13 +414,13 @@ static void close_files (void) - pw_locked = false; - - if (is_shadow_pwd) { -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -417,12 +428,12 @@ static void close_files (void) - spw_locked = false; - } - -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -431,14 +442,14 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -449,12 +460,12 @@ static void close_files (void) - - #ifdef ENABLE_SUBIDS - if (is_sub_uid) { -- if (sub_uid_close (true) == 0) { -+ if (sub_uid_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -463,12 +474,12 @@ static void close_files (void) - } - - if (is_sub_gid) { -- if (sub_gid_close (true) == 0) { -+ if (sub_gid_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -481,24 +492,24 @@ static void close_files (void) - /* - * fail_exit - exit with a failure code after unlocking the files - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ - } - } - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ - } - } - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -506,7 +517,7 @@ static void fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -515,14 +526,14 @@ static void fail_exit (int code) - #endif /* SHADOWGRP */ - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -545,45 +556,45 @@ static void fail_exit (int code) - * open_files() opens the two password files. - */ - --static void open_files (void) -+static void open_files (bool process_selinux) - { - if (pw_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - if (is_shadow_pwd) { - if (spw_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - spw_locked = true; - if (spw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - } - if (gr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef SHADOWGRP - if (is_shadow_grp) { -@@ -591,13 +602,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - sgr_locked= true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - } - #endif /* SHADOWGRP */ -@@ -607,13 +618,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - sub_uid_locked = true; - if (sub_uid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - } - if (is_sub_gid) { -@@ -621,13 +632,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - sub_gid_locked = true; - if (sub_gid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ -@@ -639,13 +650,13 @@ static void open_files (void) - * update_user() deletes the password file entries for this user - * and will update the group entries as required. - */ --static void update_user (void) -+static void update_user (bool process_selinux) - { - if (pw_remove (user_name) == 0) { - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - if ( is_shadow_pwd - && (spw_locate (user_name) != NULL) -@@ -653,20 +664,20 @@ static void update_user (void) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - #ifdef ENABLE_SUBIDS - if (is_sub_uid && sub_uid_remove(user_name, 0, ULONG_MAX) == 0) { - fprintf (stderr, - _("%s: cannot remove entry %lu from %s\n"), - Prog, (unsigned long)user_id, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - if (is_sub_gid && sub_gid_remove(user_name, 0, ULONG_MAX) == 0) { - fprintf (stderr, - _("%s: cannot remove entry %lu from %s\n"), - Prog, (unsigned long)user_id, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - #endif /* ENABLE_SUBIDS */ - #ifdef WITH_AUDIT -@@ -905,6 +916,8 @@ int main (int argc, char **argv) - int retval; - #endif /* USE_PAM */ - #endif /* ACCT_TOOLS_SETUID */ -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -954,9 +967,10 @@ int main (int argc, char **argv) - rflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -- Rflg = true; -+ flags.chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags.prefix = true; - break; - #ifdef WITH_SELINUX - case 'Z': -@@ -982,6 +996,7 @@ int main (int argc, char **argv) - } - } - } -+ process_selinux = !flags.chroot && !flags.prefix; - - if ((optind + 1) != argc) { - usage (E_USAGE); -@@ -1046,7 +1061,7 @@ int main (int argc, char **argv) - pw_open(O_RDONLY); - pwd = pw_locate (user_name); /* we care only about local users */ - if (NULL == pwd) { -- pw_close(true); -+ pw_close(process_selinux); - fprintf (stderr, _("%s: user '%s' does not exist\n"), - Prog, user_name); - #ifdef WITH_AUDIT -@@ -1065,7 +1080,7 @@ int main (int argc, char **argv) - } else { - user_home = xstrdup(pwd->pw_dir); - } -- pw_close(true); -+ pw_close(process_selinux); - } - #ifdef WITH_TCB - if (shadowtcb_set_user (user_name) == SHADOWTCB_FAILURE) { -@@ -1077,7 +1092,7 @@ int main (int argc, char **argv) - * Note: This is a best effort basis. The user may log in between, - * a cron job may be started on her behalf, etc. - */ -- if (streq(prefix, "") && !Rflg && user_busy(user_name, user_id) != 0) { -+ if (streq(prefix, "") && !flags.chroot && user_busy(user_name, user_id) != 0) { - if (!fflg) { - #ifdef WITH_AUDIT - audit_logger (AUDIT_DEL_USER, Prog, -@@ -1093,9 +1108,9 @@ int main (int argc, char **argv) - * Do the hard stuff - open the files, create the user entries, - * create the home directory, then close and update the files. - */ -- open_files (); -- update_user (); -- update_groups (); -+ open_files (process_selinux); -+ update_user (process_selinux); -+ update_groups (process_selinux); - - if (rflg) { - if (remove_mailbox ()) { -@@ -1203,7 +1218,7 @@ int main (int argc, char **argv) - "delete-selinux-user-mapping", - user_name, user_id, SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -+ fail_exit (E_SE_UPDATE, process_selinux); - } - } - #endif /* WITH_SELINUX */ -@@ -1214,7 +1229,7 @@ int main (int argc, char **argv) - */ - if (streq(prefix, "")) - user_cancel (user_name); -- close_files (); -+ close_files (&flags); - - if (run_parts ("/etc/shadow-maint/userdel-post.d", user_name, "userdel")) { - exit(1); -diff -up shadow-4.18.0/src/usermod.c.test-chroot2 shadow-4.18.0/src/usermod.c ---- shadow-4.18.0/src/usermod.c.test-chroot2 2025-07-08 11:22:16.257549046 +0200 -+++ shadow-4.18.0/src/usermod.c 2025-07-08 11:22:16.262408337 +0200 -@@ -97,6 +97,14 @@ - #define VALID(s) (!strpbrk(s, ":\n")) - - /* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ -+/* - * Global variables - */ - static const char Prog[] = "usermod"; -@@ -182,23 +190,23 @@ static bool sub_gid_locked = false; - /* local function prototypes */ - static int get_groups (char *); - NORETURN static void usage (int status); --static void new_pwent (struct passwd *); --static void new_spent (struct spwd *); --NORETURN static void fail_exit (int); --static void update_group_file(void); --static void update_group(const struct group *grp); -+static void new_pwent (struct passwd *, bool); -+static void new_spent (struct spwd *, bool); -+NORETURN static void fail_exit (int, bool); -+static void update_group_file(bool); -+static void update_group(const struct group *grp, bool process_selinux); - - #ifdef SHADOWGRP --static void update_gshadow_file(void); --static void update_gshadow(const struct sgrp *sgrp); -+static void update_gshadow_file(bool process_selinux); -+static void update_gshadow(const struct sgrp *sgrp, bool process_selinux); - #endif --static void grp_update (void); -+static void grp_update (bool process_selinux); - --static void process_flags (int, char **); --static void close_files (void); --static void open_files (void); --static void usr_update (void); --static void move_home (void); -+static void process_flags (int, char **, struct option_flags *); -+static void close_files (struct option_flags *); -+static void open_files (bool process_selinux); -+static void usr_update (struct option_flags *flags); -+static void move_home (bool process_selinux); - #ifdef ENABLE_LASTLOG - static void update_lastlog (void); - #endif /* ENABLE_LASTLOG */ -@@ -466,7 +474,7 @@ static char *new_pw_passwd (char *pw_pas - * new_pwent() takes all of the values that have been entered and fills - * in a (struct passwd) with them. - */ --static void new_pwent (struct passwd *pwent) -+static void new_pwent (struct passwd *pwent, bool process_selinux) - { - if (lflg) { - if (pw_locate (user_newname) != NULL) { -@@ -477,7 +485,7 @@ static void new_pwent (struct passwd *pw - fprintf (stderr, - _("%s: user '%s' already exists in %s\n"), - Prog, user_newname, pw_dbname ()); -- fail_exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE, process_selinux); - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_MGMT, Prog, -@@ -563,14 +571,14 @@ static void new_pwent (struct passwd *pw - * new_spent() takes all of the values that have been entered and fills - * in a (struct spwd) with them. - */ --static void new_spent (struct spwd *spent) -+static void new_spent (struct spwd *spent, bool process_selinux) - { - if (lflg) { - if (spw_locate (user_newname) != NULL) { - fprintf (stderr, - _("%s: user '%s' already exists in %s\n"), - Prog, user_newname, spw_dbname ()); -- fail_exit (E_NAME_IN_USE); -+ fail_exit (E_NAME_IN_USE, process_selinux); - } - spent->sp_namp = xstrdup (user_newname); - } -@@ -629,10 +637,10 @@ static void new_spent (struct spwd *spen - */ - NORETURN - static void --fail_exit (int code) -+fail_exit (int code, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -640,7 +648,7 @@ fail_exit (int code) - } - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -648,14 +656,14 @@ fail_exit (int code) - } - #endif - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } - } - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -663,14 +671,14 @@ fail_exit (int code) - } - #ifdef ENABLE_SUBIDS - if (sub_uid_locked) { -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ - } - } - if (sub_gid_locked) { -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -688,7 +696,7 @@ fail_exit (int code) - - - static void --update_group_file(void) -+update_group_file(bool process_selinux) - { - const struct group *grp; - -@@ -697,12 +705,12 @@ update_group_file(void) - * the user is a member of. - */ - while ((grp = gr_next()) != NULL) -- update_group(grp); -+ update_group(grp, process_selinux); - } - - - static void --update_group(const struct group *grp) -+update_group(const struct group *grp, bool process_selinux) - { - bool changed; - bool is_member; -@@ -735,7 +743,7 @@ update_group(const struct group *grp) - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - if (was_member) { -@@ -804,7 +812,7 @@ update_group(const struct group *grp) - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), ngrp->gr_name); - SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", gr_dbname (), ngrp->gr_name)); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - free_ngrp: -@@ -814,7 +822,7 @@ free_ngrp: - - #ifdef SHADOWGRP - static void --update_gshadow_file(void) -+update_gshadow_file(bool process_selinux) - { - const struct sgrp *sgrp; - -@@ -823,14 +831,14 @@ update_gshadow_file(void) - * that the user is a member of. - */ - while ((sgrp = sgr_next()) != NULL) -- update_gshadow(sgrp); -+ update_gshadow(sgrp, process_selinux); - } - #endif /* SHADOWGRP */ - - - #ifdef SHADOWGRP - static void --update_gshadow(const struct sgrp *sgrp) -+update_gshadow(const struct sgrp *sgrp, bool process_selinux) - { - bool changed; - bool is_member; -@@ -873,7 +881,7 @@ update_gshadow(const struct sgrp *sgrp) - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - if (was_admin && lflg) { -@@ -960,7 +968,7 @@ update_gshadow(const struct sgrp *sgrp) - Prog, sgr_dbname (), nsgrp->sg_namp); - SYSLOG ((LOG_WARN, "failed to prepare the new %s entry '%s'", - sgr_dbname (), nsgrp->sg_namp)); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - - free_nsgrp: -@@ -975,12 +983,12 @@ free_nsgrp: - * grp_update() takes the secondary group set given in user_groups and - * adds the user to each group given by that set. - */ --static void grp_update (void) -+static void grp_update (bool process_selinux) - { -- update_group_file(); -+ update_group_file(process_selinux); - #ifdef SHADOWGRP - if (is_shadow_grp) { -- update_gshadow_file(); -+ update_gshadow_file(process_selinux); - } - #endif - } -@@ -993,7 +1001,7 @@ static void grp_update (void) - * are checked for sanity. - */ - static void --process_flags(int argc, char **argv) -+process_flags(int argc, char **argv, struct option_flags *flags) - { - struct stat st; - bool anyflag = false; -@@ -1158,8 +1166,10 @@ process_flags(int argc, char **argv) - rflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 's': - if ( ( !VALID (optarg) ) -@@ -1467,51 +1477,55 @@ process_flags(int argc, char **argv) - * close_files() closes all of the files that were opened for this new - * user. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (pw_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } -- if (is_shadow_pwd && (spw_close (true) == 0)) { -+ if (is_shadow_pwd && (spw_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, - "failure while writing changes to %s", - spw_dbname ())); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - - if (Gflg || lflg) { -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, - "failure while writing changes to %s", - gr_dbname ())); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, - "failure while writing changes to %s", - sgr_dbname ())); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - } - #endif - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); -@@ -1522,7 +1536,7 @@ static void close_files (void) - } - } - #endif -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); -@@ -1534,7 +1548,7 @@ static void close_files (void) - } - - if (is_shadow_pwd) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -1544,7 +1558,7 @@ static void close_files (void) - /* continue */ - } - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); -@@ -1561,12 +1575,12 @@ static void close_files (void) - - #ifdef ENABLE_SUBIDS - if (vflg || Vflg) { -- if (sub_uid_close (true) == 0) { -+ if (sub_uid_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } -- if (sub_uid_unlock (true) == 0) { -+ if (sub_uid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); - /* continue */ -@@ -1574,12 +1588,12 @@ static void close_files (void) - sub_uid_locked = false; - } - if (wflg || Wflg) { -- if (sub_gid_close (true) == 0) { -+ if (sub_gid_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } -- if (sub_gid_unlock (true) == 0) { -+ if (sub_gid_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); - /* continue */ -@@ -1604,33 +1618,33 @@ static void close_files (void) - * - * open_files() opens the two password files. - */ --static void open_files (void) -+static void open_files (bool process_selinux) - { - if (pw_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - if (is_shadow_pwd && (spw_lock () == 0)) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - spw_locked = true; - if (is_shadow_pwd && (spw_open (O_CREAT | O_RDWR) == 0)) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - - if (Gflg || lflg) { -@@ -1642,28 +1656,28 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, gr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #ifdef SHADOWGRP - if (is_shadow_grp && (sgr_lock () == 0)) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - sgr_locked = true; - if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); -- fail_exit (E_GRP_UPDATE); -+ fail_exit (E_GRP_UPDATE, process_selinux); - } - #endif - } -@@ -1673,14 +1687,14 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - sub_uid_locked = true; - if (sub_uid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_uid_dbname ()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - } - if (wflg || Wflg) { -@@ -1688,14 +1702,14 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - sub_gid_locked = true; - if (sub_gid_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, sub_gid_dbname ()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - } - #endif /* ENABLE_SUBIDS */ -@@ -1707,13 +1721,15 @@ static void open_files (void) - * usr_update() creates the password file entries for this user and - * will update the group entries if required. - */ --static void usr_update (void) -+static void usr_update (struct option_flags *flags) - { - struct passwd pwent; - const struct passwd *pwd; -- - struct spwd spent; - const struct spwd *spwd = NULL; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - /* - * Locate the entry in /etc/passwd, which MUST exist. -@@ -1723,10 +1739,10 @@ static void usr_update (void) - fprintf (stderr, - _("%s: user '%s' does not exist in %s\n"), - Prog, user_name, pw_dbname ()); -- fail_exit (E_NOTFOUND); -+ fail_exit (E_NOTFOUND, process_selinux); - } - pwent = *pwd; -- new_pwent (&pwent); -+ new_pwent (&pwent, process_selinux); - - - /* If the shadow file does not exist, it won't be created */ -@@ -1735,7 +1751,7 @@ static void usr_update (void) - if (NULL != spwd) { - /* Update the shadow entry if it exists */ - spent = *spwd; -- new_spent (&spent); -+ new_spent (&spent, process_selinux); - } else if ( ( pflg - && streq(pwent.pw_passwd, SHADOW_PASSWD_STRING)) - || eflg || fflg) { -@@ -1766,7 +1782,7 @@ static void usr_update (void) - spent.sp_inact = -1; - spent.sp_expire = -1; - spent.sp_flag = SHADOW_SP_FLAG_UNSET; -- new_spent (&spent); -+ new_spent (&spent, process_selinux); - spwd = &spent; /* entry needs to be committed */ - } - } -@@ -1777,13 +1793,13 @@ static void usr_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - if (lflg && (pw_remove (user_name) == 0)) { - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, pw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - } - if ((NULL != spwd) && (lflg || eflg || fflg || pflg || Lflg || Uflg)) { -@@ -1791,13 +1807,13 @@ static void usr_update (void) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), spent.sp_namp); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - if (lflg && (spw_remove (user_name) == 0)) { - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, user_name, spw_dbname ()); -- fail_exit (E_PW_UPDATE); -+ fail_exit (E_PW_UPDATE, process_selinux); - } - } - } -@@ -1808,7 +1824,7 @@ static void usr_update (void) - * move_home() moves the user's home directory to a new location. The - * files will be copied if the directory cannot simply be renamed. - */ --static void move_home (void) -+static void move_home (bool process_selinux) - { - struct stat sb; - -@@ -1820,7 +1836,7 @@ static void move_home (void) - fprintf (stderr, - _("%s: directory %s exists\n"), - Prog, user_newhome); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - - if (stat (prefix_user_home, &sb) == 0) { -@@ -1834,7 +1850,7 @@ static void move_home (void) - "not a directory. It is not removed and no " - "home directories are created.\n"), - Prog, user_home); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - - #ifdef WITH_AUDIT -@@ -1855,7 +1871,7 @@ static void move_home (void) - fprintf (stderr, - _("%s: Failed to change ownership of the home directory"), - Prog); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - #ifdef WITH_AUDIT - audit_logger (AUDIT_USER_MGMT, Prog, -@@ -1870,7 +1886,7 @@ static void move_home (void) - fprintf (stderr, - _("%s: error: cannot move subvolume from %s to %s - different device\n"), - Prog, prefix_user_home, prefix_user_newhome); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - #endif - -@@ -1901,7 +1917,7 @@ static void move_home (void) - fprintf (stderr, - _("%s: cannot rename directory %s to %s\n"), - Prog, prefix_user_home, prefix_user_newhome); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - } else { - fprintf (stderr, -@@ -2160,6 +2176,8 @@ int main (int argc, char **argv) - int retval; - #endif /* USE_PAM */ - #endif /* ACCT_TOOLS_SETUID */ -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -2189,7 +2207,8 @@ int main (int argc, char **argv) - is_sub_gid = sub_gid_file_present (); - #endif /* ENABLE_SUBIDS */ - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot && !flags.prefix; - - /* - * The home directory, the username and the user's UID should not -@@ -2251,13 +2270,13 @@ int main (int argc, char **argv) - * Do the hard stuff - open the files, change the user entries, - * change the home directory, then close and update the files. - */ -- open_files (); -+ open_files (process_selinux); - if ( cflg || dflg || eflg || fflg || gflg || Lflg || lflg || pflg - || sflg || uflg || Uflg) { -- usr_update (); -+ usr_update (&flags); - } - if (Gflg || lflg) { -- grp_update (); -+ grp_update (process_selinux); - } - #ifdef ENABLE_SUBIDS - if (Vflg) { -@@ -2273,7 +2292,7 @@ int main (int argc, char **argv) - (uintmax_t) ptr->range.first, - (uintmax_t) ptr->range.last, - sub_uid_dbname()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - } - } -@@ -2290,7 +2309,7 @@ int main (int argc, char **argv) - (uintmax_t) ptr->range.first, - (uintmax_t) ptr->range.last, - sub_uid_dbname()); -- fail_exit (E_SUB_UID_UPDATE); -+ fail_exit (E_SUB_UID_UPDATE, process_selinux); - } - } - } -@@ -2307,7 +2326,7 @@ int main (int argc, char **argv) - (uintmax_t) ptr->range.first, - (uintmax_t) ptr->range.last, - sub_gid_dbname()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - } - } -@@ -2324,12 +2343,12 @@ int main (int argc, char **argv) - (uintmax_t) ptr->range.first, - (uintmax_t) ptr->range.last, - sub_gid_dbname()); -- fail_exit (E_SUB_GID_UPDATE); -+ fail_exit (E_SUB_GID_UPDATE, process_selinux); - } - } - } - #endif /* ENABLE_SUBIDS */ -- close_files (); -+ close_files (&flags); - - #ifdef WITH_TCB - if ( (lflg || uflg) -@@ -2355,7 +2374,7 @@ int main (int argc, char **argv) - user_name, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -+ fail_exit (E_SE_UPDATE, process_selinux); - } - } else { - if (del_seuser (user_name) != 0) { -@@ -2368,14 +2387,14 @@ int main (int argc, char **argv) - user_name, user_id, - SHADOW_AUDIT_FAILURE); - #endif /* WITH_AUDIT */ -- fail_exit (E_SE_UPDATE); -+ fail_exit (E_SE_UPDATE, process_selinux); - } - } - } - #endif /* WITH_SELINUX */ - - if (mflg) { -- move_home (); -+ move_home (process_selinux); - } - - #ifndef NO_MOVE_MAILBOX -@@ -2420,7 +2439,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: Failed to change ownership of the home directory"), - Prog); -- fail_exit (E_HOMEDIR); -+ fail_exit (E_HOMEDIR, process_selinux); - } - } - } - -diff -up shadow-4.18.0/lib/cleanup_group.c.test-chroot3 shadow-4.18.0/lib/cleanup_group.c ---- shadow-4.18.0/lib/cleanup_group.c.test-chroot3 2025-07-04 11:15:02.302179208 +0200 -+++ shadow-4.18.0/lib/cleanup_group.c 2025-07-04 11:15:02.311510389 +0200 -@@ -179,9 +179,11 @@ void cleanup_report_del_group_gshadow (v - * - * It should be registered after the group file is successfully locked. - */ --void cleanup_unlock_group (MAYBE_UNUSED void *arg) -+void cleanup_unlock_group (void *process_selinux) - { -- if (gr_unlock (true) == 0) { -+ bool process = *((bool *) process_selinux); -+ -+ if (gr_unlock (process) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), gr_dbname ()); -@@ -199,9 +201,11 @@ void cleanup_unlock_group (MAYBE_UNUSED - * - * It should be registered after the gshadow file is successfully locked. - */ --void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg) -+void cleanup_unlock_gshadow (void *process_selinux) - { -- if (sgr_unlock (true) == 0) { -+ bool process = *((bool *) process_selinux); -+ -+ if (sgr_unlock (process) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), sgr_dbname ()); -diff -up shadow-4.18.0/lib/cleanup_user.c.test-chroot3 shadow-4.18.0/lib/cleanup_user.c ---- shadow-4.18.0/lib/cleanup_user.c.test-chroot3 2025-07-04 11:15:02.297132547 +0200 -+++ shadow-4.18.0/lib/cleanup_user.c 2025-07-04 11:15:02.311622726 +0200 -@@ -96,9 +96,11 @@ void cleanup_report_add_user_shadow (voi - * - * It should be registered after the passwd database is successfully locked. - */ --void cleanup_unlock_passwd (MAYBE_UNUSED void *arg) -+void cleanup_unlock_passwd (void *process_selinux) - { -- if (pw_unlock (true) == 0) { -+ bool process = *((bool *) process_selinux); -+ -+ if (pw_unlock (process) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), pw_dbname ()); -@@ -115,9 +117,11 @@ void cleanup_unlock_passwd (MAYBE_UNUSED - * - * It should be registered after the shadow database is successfully locked. - */ --void cleanup_unlock_shadow (MAYBE_UNUSED void *arg) -+void cleanup_unlock_shadow (void *process_selinux) - { -- if (spw_unlock (true) == 0) { -+ bool process = *((bool *) process_selinux); -+ -+ if (spw_unlock (process) == 0) { - fprintf (log_get_logfd(), - _("%s: failed to unlock %s\n"), - log_get_progname(), spw_dbname ()); -diff -up shadow-4.18.0/lib/prototypes.h.test-chroot3 shadow-4.18.0/lib/prototypes.h ---- shadow-4.18.0/lib/prototypes.h.test-chroot3 2025-06-24 22:28:01.058453223 +0200 -+++ shadow-4.18.0/lib/prototypes.h 2025-07-04 11:15:02.311703893 +0200 -@@ -92,11 +92,11 @@ void cleanup_report_del_group_gshadow (v - void cleanup_report_mod_passwd (void *cleanup_info); - void cleanup_report_mod_group (void *cleanup_info); - void cleanup_report_mod_gshadow (void *cleanup_info); --void cleanup_unlock_group (/*@null@*/void *MAYBE_UNUSED); -+void cleanup_unlock_group (void *process_selinux); - #ifdef SHADOWGRP --void cleanup_unlock_gshadow (/*@null@*/void *MAYBE_UNUSED); -+void cleanup_unlock_gshadow (void *process_selinux); - #endif --void cleanup_unlock_passwd (/*@null@*/void *MAYBE_UNUSED); -+void cleanup_unlock_passwd (void *process_selinux); - - /* console.c */ - extern bool console (const char *); -diff -up shadow-4.18.0/src/chgpasswd.c.test-chroot3 shadow-4.18.0/src/chgpasswd.c ---- shadow-4.18.0/src/chgpasswd.c.test-chroot3 2025-07-04 11:15:02.302260729 +0200 -+++ shadow-4.18.0/src/chgpasswd.c 2025-07-04 11:15:02.312527205 +0200 -@@ -38,6 +38,12 @@ - #include "string/strcmp/streq.h" - #include "string/strtok/stpsep.h" - -+/* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -68,21 +74,21 @@ static bool sgr_locked = false; - static bool gr_locked = false; - - /* local function prototypes */ --NORETURN static void fail_exit (int code); -+NORETURN static void fail_exit (int code, bool process_selinux); - NORETURN static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (void); - static void check_perms (void); --static void open_files (void); --static void close_files (void); -+static void open_files (bool process_selinux); -+static void close_files (struct option_flags *flags); - - /* - * fail_exit - exit with a failure code after unlocking the files - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -91,7 +97,7 @@ static void fail_exit (int code) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -149,7 +155,7 @@ usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -@@ -187,6 +193,7 @@ static void process_flags (int argc, cha - md5flg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': -@@ -336,7 +343,7 @@ static void check_perms (void) - /* - * open_files - lock and open the group databases - */ --static void open_files (void) -+static void open_files (bool process_selinux) - { - /* - * Lock the group file and open it for reading and writing. This will -@@ -346,13 +353,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - #ifdef SHADOWGRP -@@ -362,13 +369,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - sgr_locked = true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), - Prog, sgr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } - #endif -@@ -377,18 +384,21 @@ static void open_files (void) - /* - * close_files - close and unlock the group databases - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -397,14 +407,14 @@ static void close_files (void) - } - #endif - -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -428,6 +438,8 @@ int main (int argc, char **argv) - struct group newgr; - bool errors = false; - intmax_t line = 0; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -444,7 +456,8 @@ int main (int argc, char **argv) - - process_root_flag ("-R", argc, argv); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - OPENLOG (Prog); - -@@ -454,7 +467,7 @@ int main (int argc, char **argv) - is_shadow_grp = sgr_file_present (); - #endif - -- open_files (); -+ open_files (process_selinux); - - /* - * Read each line, separating the group name from the password. The -@@ -523,7 +536,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to crypt password with salt '%s': %s\n"), - Prog, salt, strerror (errno)); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } - -@@ -624,10 +637,10 @@ int main (int argc, char **argv) - if (errors) { - fprintf (stderr, - _("%s: error detected, changes ignored\n"), Prog); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - -- close_files (); -+ close_files (&flags); - - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_GROUP); -diff -up shadow-4.18.0/src/groupadd.c.test-chroot3 shadow-4.18.0/src/groupadd.c ---- shadow-4.18.0/src/groupadd.c.test-chroot3 2025-07-04 11:15:02.284218582 +0200 -+++ shadow-4.18.0/src/groupadd.c 2025-07-04 11:15:02.311806157 +0200 -@@ -54,6 +54,14 @@ - #define E_GRP_UPDATE 10 /* can't update group file */ - - /* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ -+/* - * Global variables - */ - static const char Prog[] = "groupadd"; -@@ -85,9 +93,9 @@ static void new_sgent (struct sgrp *sgen - #endif - static void grp_update (void); - static void check_new_name (void); --static void close_files (void); --static void open_files (void); --static void process_flags (int argc, char **argv); -+static void close_files (struct option_flags *flags); -+static void open_files (struct option_flags *flags); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (void); - static void check_perms (void); - -@@ -271,10 +279,14 @@ check_new_name(void) - * close_files() closes all of the files that were opened for this new - * group. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* First, write the changes in the regular group database */ -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -@@ -289,13 +301,13 @@ static void close_files (void) - gr_dbname (), group_name, (unsigned int) group_id)); - del_cleanup (cleanup_report_add_group_group); - -- cleanup_unlock_group (NULL); -+ cleanup_unlock_group (&process_selinux); - del_cleanup (cleanup_unlock_group); - - /* Now, write the changes in the shadow database */ - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -@@ -310,7 +322,7 @@ static void close_files (void) - sgr_dbname (), group_name)); - del_cleanup (cleanup_report_add_group_gshadow); - -- cleanup_unlock_gshadow (NULL); -+ cleanup_unlock_gshadow (&process_selinux); - del_cleanup (cleanup_unlock_gshadow); - } - #endif /* SHADOWGRP */ -@@ -326,8 +338,12 @@ static void close_files (void) - * - * open_files() opens the two group files. - */ --static void open_files (void) -+static void open_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* First, lock the databases */ - if (gr_lock () == 0) { - fprintf (stderr, -@@ -335,7 +351,7 @@ static void open_files (void) - Prog, gr_dbname ()); - fail_exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_group, NULL); -+ add_cleanup (cleanup_unlock_group, &process_selinux); - - #ifdef SHADOWGRP - if (is_shadow_grp) { -@@ -345,7 +361,7 @@ static void open_files (void) - Prog, sgr_dbname ()); - fail_exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_gshadow, NULL); -+ add_cleanup (cleanup_unlock_gshadow, &process_selinux); - } - #endif /* SHADOWGRP */ - -@@ -380,7 +396,7 @@ static void open_files (void) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -455,8 +471,10 @@ static void process_flags (int argc, cha - rflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 'U': - user_list = optarg; -@@ -583,6 +601,8 @@ static void check_perms (void) - */ - int main (int argc, char **argv) - { -+ struct option_flags flags; -+ - log_set_progname(Prog); - log_set_logfd(stderr); - -@@ -608,7 +628,7 @@ int main (int argc, char **argv) - /* - * Parse the command line options. - */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - check_perms (); - -@@ -625,7 +645,7 @@ int main (int argc, char **argv) - * Do the hard stuff - open the files, create the group entries, - * then close and update the files. - */ -- open_files (); -+ open_files (&flags); - - if (!gflg) { - if (find_new_gid (rflg, &group_id, NULL) < 0) { -@@ -634,7 +654,7 @@ int main (int argc, char **argv) - } - - grp_update (); -- close_files (); -+ close_files (&flags); - if (run_parts ("/etc/shadow-maint/groupadd-post.d", group_name, - Prog)) { - exit(1); -diff -up shadow-4.18.0/src/groupdel.c.test-chroot3 shadow-4.18.0/src/groupdel.c ---- shadow-4.18.0/src/groupdel.c.test-chroot3 2025-07-04 11:15:02.284261326 +0200 -+++ shadow-4.18.0/src/groupdel.c 2025-07-04 11:15:02.312079796 +0200 -@@ -33,6 +33,12 @@ - #endif - #include "shadowlog.h" - #include "run_part.h" -+ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ - /* - * Global variables - */ -@@ -61,10 +67,10 @@ static bool is_shadow_grp; - /* local function prototypes */ - NORETURN static void usage (int status); - static void grp_update (void); --static void close_files (void); --static void open_files (void); -+static void close_files (struct option_flags *flags); -+static void open_files (struct option_flags *flags); - static void group_busy (gid_t gid); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - - /* - * usage - display usage message and exit -@@ -146,10 +152,14 @@ static void grp_update (void) - * close_files() closes all of the files that were opened for this - * new group. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* First, write the changes in the regular group database */ -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -@@ -166,14 +176,14 @@ static void close_files (void) - group_name, gr_dbname ())); - del_cleanup (cleanup_report_del_group_group); - -- cleanup_unlock_group (NULL); -+ cleanup_unlock_group (&process_selinux); - del_cleanup (cleanup_unlock_group); - - - /* Then, write the changes in the shadow database */ - #ifdef SHADOWGRP - if (is_shadow_grp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -@@ -190,7 +200,7 @@ static void close_files (void) - group_name, sgr_dbname ())); - del_cleanup (cleanup_report_del_group_gshadow); - -- cleanup_unlock_gshadow (NULL); -+ cleanup_unlock_gshadow (&process_selinux); - del_cleanup (cleanup_unlock_gshadow); - } - #endif /* SHADOWGRP */ -@@ -204,8 +214,12 @@ static void close_files (void) - * - * open_files() opens the two group files. - */ --static void open_files (void) -+static void open_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* First, lock the databases */ - if (gr_lock () == 0) { - fprintf (stderr, -@@ -213,7 +227,7 @@ static void open_files (void) - Prog, gr_dbname ()); - fail_exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_group, NULL); -+ add_cleanup (cleanup_unlock_group, &process_selinux); - #ifdef SHADOWGRP - if (is_shadow_grp) { - if (sgr_lock () == 0) { -@@ -222,7 +236,7 @@ static void open_files (void) - Prog, sgr_dbname ()); - fail_exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_gshadow, NULL); -+ add_cleanup (cleanup_unlock_gshadow, &process_selinux); - } - #endif - -@@ -296,7 +310,7 @@ static void group_busy (gid_t gid) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -317,8 +331,10 @@ static void process_flags (int argc, cha - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 'f': - check_group_busy = false; -@@ -352,6 +368,7 @@ int main (int argc, char **argv) - int retval; - #endif /* USE_PAM */ - #endif /* ACCT_TOOLS_SETUID */ -+ struct option_flags flags; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -375,7 +392,7 @@ int main (int argc, char **argv) - fail_exit (1); - } - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM -@@ -449,11 +466,11 @@ int main (int argc, char **argv) - * Do the hard stuff - open the files, delete the group entries, - * then close and update the files. - */ -- open_files (); -+ open_files (&flags); - - grp_update (); - -- close_files (); -+ close_files (&flags); - - if (run_parts ("/etc/shadow-maint/groupdel-post.d", group_name, - Prog)) { -diff -up shadow-4.18.0/src/groupmems.c.test-chroot3 shadow-4.18.0/src/groupmems.c ---- shadow-4.18.0/src/groupmems.c.test-chroot3 2025-07-04 11:15:02.302301588 +0200 -+++ shadow-4.18.0/src/groupmems.c 2025-07-04 11:15:57.404278255 +0200 -@@ -47,6 +47,13 @@ - #define EXIT_INVALID_GROUP 9 /* specified group does not exist */ - - /* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+}; -+ -+/* - * Global variables - */ - static const char Prog[] = "groupmems"; -@@ -68,15 +75,17 @@ static bool sgr_locked = false; - /* local function prototypes */ - static char *whoami (void); - static void add_user (const char *user, -- const struct group *grp); -+ const struct group *grp, -+ bool process_selinux); - static void remove_user (const char *user, -- const struct group *grp); --static void purge_members (const struct group *grp); -+ const struct group *grp, -+ bool process_selinux); -+static void purge_members (const struct group *grp, bool process_selinux); - static void display_members (const char *const *members); - NORETURN static void usage (int status); --static void process_flags (int argc, char **argv); --static void check_perms (void); --NORETURN static void fail_exit (int code); -+static void process_flags (int argc, char **argv, struct option_flags *flags); -+static void check_perms (bool process_selinux); -+NORETURN static void fail_exit (int code, bool process_selinux); - #define isroot() (getuid () == 0) - - static char *whoami (void) -@@ -99,7 +108,8 @@ static char *whoami (void) - * add_user - Add a user to the specified group - */ - static void add_user (const char *user, -- const struct group *grp) -+ const struct group *grp, -+ bool process_selinux) - { - struct group *newgrp; - -@@ -108,7 +118,7 @@ static void add_user (const char *user, - fprintf (stderr, - _("%s: user '%s' is already a member of '%s'\n"), - Prog, user, grp->gr_name); -- fail_exit (EXIT_MEMBER_EXISTS); -+ fail_exit (EXIT_MEMBER_EXISTS, process_selinux); - } - - newgrp = __gr_dup(grp); -@@ -116,7 +126,7 @@ static void add_user (const char *user, - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - - /* Add the user to the /etc/group group */ -@@ -146,7 +156,7 @@ static void add_user (const char *user, - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - /* Add the user to the members */ - newsg->sg_mem = add_list (newsg->sg_mem, user); -@@ -157,7 +167,7 @@ static void add_user (const char *user, - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), newsg->sg_namp); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - #endif -@@ -166,7 +176,7 @@ static void add_user (const char *user, - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), newgrp->gr_name); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - -@@ -174,7 +184,8 @@ static void add_user (const char *user, - * remove_user - Remove a user from a given group - */ - static void remove_user (const char *user, -- const struct group *grp) -+ const struct group *grp, -+ bool process_selinux) - { - struct group *newgrp; - -@@ -183,7 +194,7 @@ static void remove_user (const char *use - fprintf (stderr, - _("%s: user '%s' is not a member of '%s'\n"), - Prog, user, grp->gr_name); -- fail_exit (EXIT_NOT_MEMBER); -+ fail_exit (EXIT_NOT_MEMBER, process_selinux); - } - - newgrp = __gr_dup (grp); -@@ -191,7 +202,7 @@ static void remove_user (const char *use - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - - /* Remove the user from the /etc/group group */ -@@ -221,7 +232,7 @@ static void remove_user (const char *use - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - /* Remove the user from the members */ - newsg->sg_mem = del_list (newsg->sg_mem, user); -@@ -233,7 +244,7 @@ static void remove_user (const char *use - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), newsg->sg_namp); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - #endif -@@ -242,14 +253,14 @@ static void remove_user (const char *use - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), newgrp->gr_name); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - - /* - * purge_members - Remove every members of the specified group - */ --static void purge_members (const struct group *grp) -+static void purge_members (const struct group *grp, bool process_selinux) - { - struct group *newgrp = __gr_dup (grp); - -@@ -257,7 +268,7 @@ static void purge_members (const struct - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, gr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - - /* Remove all the members of the /etc/group group */ -@@ -288,7 +299,7 @@ static void purge_members (const struct - fprintf (stderr, - _("%s: Out of memory. Cannot update %s.\n"), - Prog, sgr_dbname ()); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - /* Remove all the members of the /etc/gshadow - * group */ -@@ -302,7 +313,7 @@ static void purge_members (const struct - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), newsg->sg_namp); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - #endif -@@ -311,7 +322,7 @@ static void purge_members (const struct - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), newgrp->gr_name); -- fail_exit (13); -+ fail_exit (13, process_selinux); - } - } - -@@ -356,7 +367,7 @@ usage (int status) - /* - * process_flags - perform command line argument setting - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -396,6 +407,7 @@ static void process_flags (int argc, cha - ++exclusive; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - default: - usage (EXIT_USAGE); -@@ -411,12 +423,12 @@ static void process_flags (int argc, cha - && (getpwnam (adduser) == NULL)) { - fprintf (stderr, _("%s: user '%s' does not exist\n"), - Prog, adduser); -- fail_exit (EXIT_INVALID_USER); -+ fail_exit (EXIT_INVALID_USER, !flags->chroot); - } - - } - --static void check_perms (void) -+static void check_perms (bool process_selinux) - { - if (!list) { - #ifdef ACCT_TOOLS_SETUID -@@ -430,7 +442,7 @@ static void check_perms (void) - fprintf (stderr, - _("%s: Cannot determine your user name.\n"), - Prog); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - retval = pam_start (Prog, pampw->pw_name, &conv, &pamh); -@@ -450,7 +462,7 @@ static void check_perms (void) - if (NULL != pamh) { - (void) pam_end (pamh, retval); - } -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - (void) pam_end (pamh, retval); - #endif /* USE_PAM */ -@@ -458,10 +470,10 @@ static void check_perms (void) - } - } - --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, gr_dbname ()); -@@ -472,7 +484,7 @@ static void fail_exit (int code) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, sgr_dbname ()); -@@ -485,14 +497,14 @@ static void fail_exit (int code) - exit (code); - } - --static void open_files (void) -+static void open_files (bool process_selinux) - { - if (!list) { - if (gr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - gr_locked = true; - -@@ -502,7 +514,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - sgr_locked = true; - } -@@ -511,28 +523,32 @@ static void open_files (void) - - if (gr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - - #ifdef SHADOWGRP - if (is_shadowgrp) { - if (sgr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - } - #endif - } - --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if ((gr_close (true) == 0) && !list) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; -+ -+ if ((gr_close (process_selinux) == 0) && !list) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -542,13 +558,13 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadowgrp) { -- if ((sgr_close (true) == 0) && !list) { -+ if ((sgr_close (process_selinux) == 0) && !list) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (EXIT_GROUP_FILE); -+ fail_exit (EXIT_GROUP_FILE, process_selinux); - } - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -563,6 +579,8 @@ int main (int argc, char **argv) - { - char *name; - const struct group *grp; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -579,44 +597,45 @@ int main (int argc, char **argv) - is_shadowgrp = sgr_file_present (); - #endif - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - if (NULL == thisgroup) { - name = whoami (); - if (!list && (NULL == name)) { - fprintf (stderr, _("%s: your groupname does not match your username\n"), Prog); -- fail_exit (EXIT_NOT_PRIMARY); -+ fail_exit (EXIT_NOT_PRIMARY, process_selinux); - } - } else { - name = thisgroup; - if (!list && !isroot ()) { - fprintf (stderr, _("%s: only root can use the -g/--group option\n"), Prog); -- fail_exit (EXIT_NOT_ROOT); -+ fail_exit (EXIT_NOT_ROOT, process_selinux); - } - } - -- check_perms (); -+ check_perms (process_selinux); - -- open_files (); -+ open_files (process_selinux); - - grp = gr_locate (name); - if (NULL == grp) { - fprintf (stderr, _("%s: group '%s' does not exist in %s\n"), - Prog, name, gr_dbname ()); -- fail_exit (EXIT_INVALID_GROUP); -+ fail_exit (EXIT_INVALID_GROUP, process_selinux); - } - - if (list) { - display_members ((const char *const *)grp->gr_mem); - } else if (NULL != adduser) { -- add_user (adduser, grp); -+ add_user (adduser, grp, process_selinux); - } else if (NULL != deluser) { -- remove_user (deluser, grp); -+ remove_user (deluser, grp, process_selinux); - } else if (purge) { -- purge_members (grp); -+ purge_members (grp, process_selinux); - } - -- close_files (); -+ close_files (&flags); - - exit (EXIT_SUCCESS); - } -diff -up shadow-4.18.0/src/groupmod.c.test-chroot3 shadow-4.18.0/src/groupmod.c ---- shadow-4.18.0/src/groupmod.c.test-chroot3 2025-07-04 11:15:02.284354823 +0200 -+++ shadow-4.18.0/src/groupmod.c 2025-07-04 11:15:02.311945828 +0200 -@@ -61,6 +61,10 @@ - #define E_PAM_USERNAME 12 /* can't determine your username for use with pam */ - #define E_PAM_ERROR 13 /* pam returned an error, see Syslog facility id groupmod */ - -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; - - /* - * Global variables -@@ -102,11 +106,11 @@ static void new_sgent (struct sgrp *); - static void grp_update (void); - static void check_new_gid (void); - static void check_new_name (void); --static void process_flags (int, char **); --static void lock_files (void); -+static void process_flags (int, char **, struct option_flags *); -+static void lock_files (struct option_flags *flags); - static void prepare_failure_reports (void); - static void open_files (void); --static void close_files (void); -+static void close_files (struct option_flags *flags); - static void update_primary_groups (gid_t ogid, gid_t ngid); - - -@@ -405,7 +409,7 @@ check_new_name(void) - * values that the user will be created with accordingly. The values - * are checked for sanity. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -451,8 +455,10 @@ static void process_flags (int argc, cha - pflg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 'U': - user_list = optarg; -@@ -479,9 +485,13 @@ static void process_flags (int argc, cha - * close_files() closes all of the files that were opened for this new - * group. This causes any modified entries to be written out. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (gr_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -@@ -498,13 +508,13 @@ static void close_files (void) - gr_dbname (), info_group.action)); - del_cleanup (cleanup_report_mod_group); - -- cleanup_unlock_group (NULL); -+ cleanup_unlock_group (&process_selinux); - del_cleanup (cleanup_unlock_group); - - #ifdef SHADOWGRP - if ( is_shadow_grp - && (pflg || nflg || user_list)) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -@@ -528,13 +538,13 @@ static void close_files (void) - sgr_dbname (), info_gshadow.action)); - del_cleanup (cleanup_report_mod_gshadow); - -- cleanup_unlock_gshadow (NULL); -+ cleanup_unlock_gshadow (&process_selinux); - del_cleanup (cleanup_unlock_gshadow); - } - #endif /* SHADOWGRP */ - - if (gflg) { -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -@@ -551,7 +561,7 @@ static void close_files (void) - pw_dbname (), info_passwd.action)); - del_cleanup (cleanup_report_mod_passwd); - -- cleanup_unlock_passwd (NULL); -+ cleanup_unlock_passwd (&process_selinux); - del_cleanup (cleanup_unlock_passwd); - } - -@@ -657,15 +667,19 @@ static void prepare_failure_reports (voi - * - * lock_files() locks the group, gshadow, and passwd databases. - */ --static void lock_files (void) -+static void lock_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - if (gr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); - exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_group, NULL); -+ add_cleanup (cleanup_unlock_group, &process_selinux); - - #ifdef SHADOWGRP - if ( is_shadow_grp -@@ -676,7 +690,7 @@ static void lock_files (void) - Prog, sgr_dbname ()); - exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_gshadow, NULL); -+ add_cleanup (cleanup_unlock_gshadow, &process_selinux); - } - #endif - -@@ -687,7 +701,7 @@ static void lock_files (void) - Prog, pw_dbname ()); - exit (E_GRP_UPDATE); - } -- add_cleanup (cleanup_unlock_passwd, NULL); -+ add_cleanup (cleanup_unlock_passwd, &process_selinux); - } - } - -@@ -771,6 +785,7 @@ int main (int argc, char **argv) - int retval; - #endif /* USE_PAM */ - #endif /* ACCT_TOOLS_SETUID */ -+ struct option_flags flags; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -794,7 +809,7 @@ int main (int argc, char **argv) - exit (E_CLEANUP_SERVICE); - } - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM -@@ -859,7 +874,7 @@ int main (int argc, char **argv) - check_new_name (); - } - -- lock_files (); -+ lock_files (&flags); - - /* - * Now if the group is not changed, it's our fault. -@@ -875,7 +890,7 @@ int main (int argc, char **argv) - - grp_update (); - -- close_files (); -+ close_files (&flags); - - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_GROUP); -diff -up shadow-4.18.0/src/grpck.c.test-chroot3 shadow-4.18.0/src/grpck.c ---- shadow-4.18.0/src/grpck.c.test-chroot3 2025-07-04 11:15:02.302354224 +0200 -+++ shadow-4.18.0/src/grpck.c 2025-07-04 11:15:02.313643179 +0200 -@@ -44,6 +44,13 @@ - #define E_CANT_UPDATE 5 - - /* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+}; -+ -+/* - * Global variables - */ - static const char Prog[] = "grpck"; -@@ -64,19 +71,20 @@ static bool sort_mode = false; - static bool silence_warnings = false; - - /* local function prototypes */ --static void fail_exit (int status); -+static void fail_exit (int status, bool process_selinux); - NORETURN static void usage (int status); - static void delete_member (char **, const char *); --static void process_flags (int argc, char **argv); --static void open_files (void); --static void close_files (bool changed); -+static void process_flags (int argc, char **argv, struct option_flags *flags); -+static void open_files (bool process_selinux); -+static void close_files (bool changed, struct option_flags *flags); - static int check_members (const char *groupname, - char **members, - const char *fmt_info, - const char *fmt_prompt, - const char *fmt_syslog, - bool *errors); --static void check_grp_file (bool *errors, bool *changed); -+static void check_grp_file (bool *errors, bool *changed, -+ struct option_flags *flags); - #ifdef SHADOWGRP - static void compare_members_lists (const char *groupname, - char **members, -@@ -89,10 +97,10 @@ static void check_sgr_file (bool *errors - /* - * fail_exit - exit with an error code after unlocking files - */ --static void fail_exit (int status) -+static void fail_exit (int status, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -101,7 +109,7 @@ static void fail_exit (int status) - - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -172,7 +180,7 @@ static void delete_member (char **list, - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -201,6 +209,7 @@ static void process_flags (int argc, cha - read_only = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 's': - sort_mode = true; -@@ -257,7 +266,7 @@ static void process_flags (int argc, cha - * In read-only mode, the databases are not locked and are opened - * only for reading. - */ --static void open_files (void) -+static void open_files (bool process_selinux) - { - /* - * Lock the files if we aren't in "read-only" mode -@@ -267,7 +276,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, grp_file); -- fail_exit (E_CANT_LOCK); -+ fail_exit (E_CANT_LOCK, process_selinux); - } - gr_locked = true; - #ifdef SHADOWGRP -@@ -276,7 +285,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_file); -- fail_exit (E_CANT_LOCK); -+ fail_exit (E_CANT_LOCK, process_selinux); - } - sgr_locked = true; - } -@@ -293,7 +302,7 @@ static void open_files (void) - if (use_system_grp_file) { - SYSLOG ((LOG_WARN, "cannot open %s", grp_file)); - } -- fail_exit (E_CANT_OPEN); -+ fail_exit (E_CANT_OPEN, process_selinux); - } - #ifdef SHADOWGRP - if (is_shadow && (sgr_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0)) { -@@ -302,7 +311,7 @@ static void open_files (void) - if (use_system_sgr_file) { - SYSLOG ((LOG_WARN, "cannot open %s", sgr_file)); - } -- fail_exit (E_CANT_OPEN); -+ fail_exit (E_CANT_OPEN, process_selinux); - } - #endif - } -@@ -314,23 +323,27 @@ static void open_files (void) - * changes are committed in the databases. The databases are - * unlocked anyway. - */ --static void close_files (bool changed) -+static void close_files (bool changed, struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; -+ - /* - * All done. If there were no change we can just abandon any - * changes to the files. - */ - if (changed) { -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), - Prog, grp_file); -- fail_exit (E_CANT_UPDATE); -+ fail_exit (E_CANT_UPDATE, process_selinux); - } - #ifdef SHADOWGRP -- if (is_shadow && (sgr_close (true) == 0)) { -+ if (is_shadow && (sgr_close (process_selinux) == 0)) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), - Prog, sgr_file); -- fail_exit (E_CANT_UPDATE); -+ fail_exit (E_CANT_UPDATE, process_selinux); - } - #endif - } -@@ -340,7 +353,7 @@ static void close_files (bool changed) - */ - #ifdef SHADOWGRP - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -349,7 +362,7 @@ static void close_files (bool changed) - } - #endif - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -455,13 +468,16 @@ static void compare_members_lists (const - /* - * check_grp_file - check the content of the group file - */ --static void check_grp_file (bool *errors, bool *changed) -+static void check_grp_file (bool *errors, bool *changed, struct option_flags *flags) - { - struct commonio_entry *gre, *tgre; - struct group *grp; - #ifdef SHADOWGRP - const struct sgrp *sgr; - #endif -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Loop through the entire group file. -@@ -627,7 +643,7 @@ static void check_grp_file (bool *errors - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), sg.sg_namp); -- fail_exit (E_CANT_UPDATE); -+ fail_exit (E_CANT_UPDATE, process_selinux); - } - /* remove password from /etc/group */ - gr = *grp; -@@ -636,7 +652,7 @@ static void check_grp_file (bool *errors - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), gr.gr_name); -- fail_exit (E_CANT_UPDATE); -+ fail_exit (E_CANT_UPDATE, process_selinux); - } - } - } else { -@@ -819,6 +835,8 @@ int main (int argc, char **argv) - { - bool errors = false; - bool changed = false; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -832,9 +850,10 @@ int main (int argc, char **argv) - OPENLOG (Prog); - - /* Parse the command line arguments */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - -- open_files (); -+ open_files (process_selinux); - - if (sort_mode) { - gr_sort (); -@@ -845,7 +864,7 @@ int main (int argc, char **argv) - changed = true; - #endif - } else { -- check_grp_file (&errors, &changed); -+ check_grp_file (&errors, &changed, &flags); - #ifdef SHADOWGRP - if (is_shadow) { - check_sgr_file (&errors, &changed); -@@ -854,7 +873,7 @@ int main (int argc, char **argv) - } - - /* Commit the change in the database if needed */ -- close_files (changed); -+ close_files (changed, &flags); - - if (!read_only) { - nscd_flush_cache ("group"); - -diff -up shadow-4.18.0/src/chage.c.test-chroot4 shadow-4.18.0/src/chage.c ---- shadow-4.18.0/src/chage.c.test-chroot4 2025-07-04 11:17:37.593707379 +0200 -+++ shadow-4.18.0/src/chage.c 2025-07-04 11:17:37.613081862 +0200 -@@ -42,6 +42,10 @@ - #include "tcbfuncs.h" - #endif - -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; - - /* - * Global variables -@@ -79,29 +83,29 @@ NORETURN static void usage (int status); - static int new_fields (void); - static void print_day_as_date (long day); - static void list_fields (void); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (int argc, int opt_index); --static void check_perms (void); --static void open_files (bool readonly); --static void close_files (void); --NORETURN static void fail_exit (int code); -+static void check_perms (struct option_flags *flags); -+static void open_files (bool readonly, struct option_flags *flags); -+static void close_files (struct option_flags *flags); -+NORETURN static void fail_exit (int code, bool process_selinux); - - /* - * fail_exit - do some cleanup and exit with the given error code - */ - NORETURN - static void --fail_exit (int code) -+fail_exit (int code, bool process_selinux) - { - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } - } - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -338,7 +342,7 @@ static void list_fields (void) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -419,8 +423,10 @@ static void process_flags (int argc, cha - } - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - case 'W': - Wflg = true; -@@ -472,8 +478,12 @@ static void check_flags (int argc, int o - * - * It will not return if the user is not allowed. - */ --static void check_perms (void) -+static void check_perms (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* - * An unprivileged user can ask for their own aging information, but - * only root can change it, or list another user's aging -@@ -482,7 +492,7 @@ static void check_perms (void) - - if (!amroot && !lflg) { - fprintf (stderr, _("%s: Permission denied.\n"), Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - } - -@@ -492,8 +502,12 @@ static void check_perms (void) - * In read-only mode, the databases are not locked and are opened - * only for reading. - */ --static void open_files (bool readonly) -+static void open_files (bool readonly, struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* - * Lock and open the password file. This loads all of the password - * file entries into memory. Then we get a pointer to the password -@@ -504,14 +518,14 @@ static void open_files (bool readonly) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - pw_locked = true; - } - if (pw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - /* -@@ -525,7 +539,7 @@ static void open_files (bool readonly) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - spw_locked = true; - } -@@ -533,42 +547,46 @@ static void open_files (bool readonly) - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - } - - /* - * close_files - close and unlock the password/shadow databases - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* - * Now close the shadow password file, which will cause all of the - * entries to be re-written. - */ -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - /* - * Close the password file. If any entries were modified, the file - * will be re-written. - */ -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } - spw_locked = false; -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -582,7 +600,8 @@ static void close_files (void) - * It will not return in case of error - */ - static void update_age (/*@null@*/const struct spwd *sp, -- /*@notnull@*/const struct passwd *pw) -+ /*@notnull@*/const struct passwd *pw, -+ bool process_selinux) - { - struct spwd spwent; - -@@ -603,7 +622,7 @@ static void update_age (/*@null@*/const - if (pw_update (&pwent) == 0) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pwent.pw_name); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - } else { - spwent.sp_namp = xstrdup (sp->sp_namp); -@@ -626,7 +645,7 @@ static void update_age (/*@null@*/const - if (spw_update (&spwent) == 0) { - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spwent.sp_namp); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - } -@@ -712,6 +731,8 @@ int main (int argc, char **argv) - uid_t ruid; - gid_t rgid; - const struct passwd *pw; -+ struct option_flags flags; -+ bool process_selinux; - - sanitize_env (); - check_fds (); -@@ -740,9 +761,10 @@ int main (int argc, char **argv) - } - #endif - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot && !flags.prefix; - -- check_perms (); -+ check_perms (&flags); - - if (!spw_file_present ()) { - fprintf (stderr, -@@ -753,13 +775,13 @@ int main (int argc, char **argv) - exit (E_SHADOW_NOTFOUND); - } - -- open_files (lflg); -+ open_files (lflg, &flags); - /* Drop privileges */ - if (lflg && ( (setregid (rgid, rgid) != 0) - || (setreuid (ruid, ruid) != 0))) { - fprintf (stderr, _("%s: failed to drop privileges (%s)\n"), - Prog, strerror (errno)); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - pw = pw_locate (argv[optind]); -@@ -767,13 +789,13 @@ int main (int argc, char **argv) - fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), - Prog, argv[optind], pw_dbname ()); - closelog (); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - STRTCPY(user_name, pw->pw_name); - #ifdef WITH_TCB - if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) { -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - #endif - user_uid = pw->pw_uid; -@@ -788,11 +810,11 @@ int main (int argc, char **argv) - if (lflg) { - if (!amroot && (ruid != user_uid)) { - fprintf (stderr, _("%s: Permission denied.\n"), Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - /* Displaying fields is not of interest to audit */ - list_fields (); -- fail_exit (E_SUCCESS); -+ fail_exit (E_SUCCESS, process_selinux); - } - - /* -@@ -805,7 +827,7 @@ int main (int argc, char **argv) - if (new_fields () == 0) { - fprintf (stderr, _("%s: error changing fields\n"), - Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - #ifdef WITH_AUDIT - else { -@@ -847,9 +869,9 @@ int main (int argc, char **argv) - #endif - } - -- update_age (sp, pw); -+ update_age (sp, pw, process_selinux); - -- close_files (); -+ close_files (&flags); - - SYSLOG ((LOG_INFO, "changed password expiry for %s", user_name)); - -diff -up shadow-4.18.0/src/chfn.c.test-chroot4 shadow-4.18.0/src/chfn.c ---- shadow-4.18.0/src/chfn.c.test-chroot4 2025-07-04 11:17:37.590501245 +0200 -+++ shadow-4.18.0/src/chfn.c 2025-07-04 11:17:37.613576062 +0200 -@@ -39,6 +39,9 @@ - #include "string/strdup/xstrdup.h" - #include "string/strtok/stpsep.h" - -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables. -@@ -63,23 +66,23 @@ static bool pw_locked = false; - */ - - /* local function prototypes */ --NORETURN static void fail_exit (int code); -+NORETURN static void fail_exit (int code, bool process_selinux); - NORETURN static void usage (int status); - static bool may_change_field (int); - static void new_fields (void); - static char *copy_field (char *, char *, char *); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_perms (const struct passwd *pw); --static void update_gecos (const char *user, char *gecos); -+static void update_gecos (const char *user, char *gecos, struct option_flags *flags); - static void get_old_fields (const char *gecos); - - /* - * fail_exit - exit with an error and do some cleanup - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -250,7 +253,7 @@ static char *copy_field (char *in, char - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; /* flag currently being processed */ - static struct option long_options[] = { -@@ -316,6 +319,7 @@ static void process_flags (int argc, cha - STRTCPY(roomno, optarg); - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'u': - usage (E_SUCCESS); -@@ -423,10 +427,13 @@ static void check_perms (const struct pa - * - * Commit the user's entry after changing her gecos field. - */ --static void update_gecos (const char *user, char *gecos) -+static void update_gecos (const char *user, char *gecos, struct option_flags *flags) - { - const struct passwd *pw; /* The user's password file entry */ - struct passwd pwent; /* modified password file entry */ -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Before going any further, raise the ulimit to prevent colliding -@@ -437,7 +444,7 @@ static void update_gecos (const char *us - if (setuid (0) != 0) { - fputs (_("Cannot change ID to root.\n"), stderr); - SYSLOG ((LOG_ERR, "can't setuid(0)")); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - pwd_init (); - -@@ -449,13 +456,13 @@ static void update_gecos (const char *us - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - /* -@@ -469,7 +476,7 @@ static void update_gecos (const char *us - fprintf (stderr, - _("%s: user '%s' does not exist in %s\n"), - Prog, user, pw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - /* -@@ -487,18 +494,18 @@ static void update_gecos (const char *us - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - - /* - * Changes have all been made, so commit them and unlock the file. - */ -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -562,7 +569,7 @@ static void get_old_fields (const char * - * - * It will not return if a field is not valid. - */ --static void check_fields (void) -+static void check_fields (bool process_selinux) - { - int err; - err = valid_field (fullnm, ":,=\n"); -@@ -570,7 +577,7 @@ static void check_fields (void) - fprintf (stderr, _("%s: name with non-ASCII characters: '%s'\n"), Prog, fullnm); - } else if (err < 0) { - fprintf (stderr, _("%s: invalid name: '%s'\n"), Prog, fullnm); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - err = valid_field (roomno, ":,=\n"); - if (err > 0) { -@@ -578,17 +585,17 @@ static void check_fields (void) - } else if (err < 0) { - fprintf (stderr, _("%s: invalid room number: '%s'\n"), - Prog, roomno); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - if (valid_field (workph, ":,=\n") != 0) { - fprintf (stderr, _("%s: invalid work phone: '%s'\n"), - Prog, workph); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - if (valid_field (homeph, ":,=\n") != 0) { - fprintf (stderr, _("%s: invalid home phone: '%s'\n"), - Prog, homeph); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - err = valid_field (slop, ":\n"); - if (err > 0) { -@@ -597,7 +604,7 @@ static void check_fields (void) - fprintf (stderr, - _("%s: '%s' contains illegal characters\n"), - Prog, slop); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - } - -@@ -622,6 +629,8 @@ int main (int argc, char **argv) - char new_gecos[BUFSIZ]; - char *user; - const struct passwd *pw; -+ struct option_flags flags; -+ bool process_selinux; - - sanitize_env (); - check_fds (); -@@ -644,7 +653,7 @@ int main (int argc, char **argv) - OPENLOG (Prog); - - /* parse the command line options */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - /* - * Get the name of the user to check. It is either the command line -@@ -653,14 +662,14 @@ int main (int argc, char **argv) - if (optind < argc) { - if (!is_valid_user_name (argv[optind])) { - fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - user = argv[optind]; - pw = xgetpwnam (user); - if (NULL == pw) { - fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, - user); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - } else { - pw = get_my_pwent (); -@@ -670,7 +679,7 @@ int main (int argc, char **argv) - Prog); - SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", - (unsigned long) getuid ())); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - user = xstrdup (pw->pw_name); - } -@@ -695,7 +704,7 @@ int main (int argc, char **argv) - /* - * Check all of the fields for valid information - */ -- check_fields (); -+ check_fields (process_selinux); - - /* - * Build the new GECOS field by plastering all the pieces together, -@@ -704,14 +713,14 @@ int main (int argc, char **argv) - if ((strlen (fullnm) + strlen (roomno) + strlen (workph) + - strlen (homeph) + strlen (slop)) > (unsigned int) 80) { - fprintf (stderr, _("%s: fields too long\n"), Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - SNPRINTF(new_gecos, "%s,%s,%s,%s%s%s", - fullnm, roomno, workph, homeph, - (!streq(slop, "")) ? "," : "", slop); - - /* Rewrite the user's gecos in the passwd file */ -- update_gecos (user, new_gecos); -+ update_gecos (user, new_gecos, &flags); - - SYSLOG ((LOG_INFO, "changed user '%s' information", user)); - -diff -up shadow-4.18.0/src/chpasswd.c.test-chroot4 shadow-4.18.0/src/chpasswd.c ---- shadow-4.18.0/src/chpasswd.c.test-chroot4 2025-07-04 11:17:37.593768325 +0200 -+++ shadow-4.18.0/src/chpasswd.c 2025-07-04 11:18:06.785652711 +0200 -@@ -38,6 +38,11 @@ - - #define IS_CRYPT_METHOD(str) ((crypt_method != NULL && streq(crypt_method, str)) ? true : false) - -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ - /* - * Global variables - */ -@@ -67,21 +72,21 @@ static bool pw_locked = false; - static bool spw_locked = false; - - /* local function prototypes */ --NORETURN static void fail_exit (int code); -+NORETURN static void fail_exit (int code, bool process_selinux); - NORETURN static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (void); - static void check_perms (void); --static void open_files (void); --static void close_files (void); -+static void open_files (struct option_flags *flags); -+static void close_files (struct option_flags *flags); - - /* - * fail_exit - exit with a failure code after unlocking the files - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -89,7 +94,7 @@ static void fail_exit (int code) - } - - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -147,7 +152,7 @@ usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) -@@ -187,8 +192,10 @@ static void process_flags (int argc, cha - md5flg = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags->prefix = true; - break; - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': -@@ -335,8 +342,12 @@ static void check_perms (void) - /* - * open_files - lock and open the password databases - */ --static void open_files (void) -+static void open_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - /* - * Lock the password file and open it for reading and writing. This - * will bring all of the entries into memory where they may be updated. -@@ -345,13 +356,13 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* Do the same for the shadowed database, if it exist */ -@@ -360,14 +371,14 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - spw_locked = true; - if (spw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } - } -@@ -375,17 +386,21 @@ static void open_files (void) - /* - * close_files - close and unlock the password databases - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; -+ - if (is_shadow_pwd) { -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -393,14 +408,14 @@ static void close_files (void) - spw_locked = false; - } - -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -456,6 +471,8 @@ int main (int argc, char **argv) - - bool errors = false; - intmax_t line = 0; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -470,7 +487,8 @@ int main (int argc, char **argv) - } - #endif /* WITH_SELINUX */ - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot && !flags.prefix; - - salt = get_salt(); - process_root_flag ("-R", argc, argv); -@@ -496,7 +514,7 @@ int main (int argc, char **argv) - { - is_shadow_pwd = spw_file_present (); - -- open_files (); -+ open_files (&flags); - } - - /* -@@ -573,7 +591,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to crypt password with salt '%s': %s\n"), - Prog, salt, strerror (errno)); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } - -@@ -690,7 +708,7 @@ int main (int argc, char **argv) - _("%s: error detected, changes ignored\n"), - Prog); - } -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - #ifdef ACCT_TOOLS_SETUID -@@ -700,7 +718,7 @@ int main (int argc, char **argv) - #endif /* ACCT_TOOLS_SETUID */ - { - /* Save the changes */ -- close_files (); -+ close_files (&flags); - } - - nscd_flush_cache ("passwd"); -diff -up shadow-4.18.0/src/grpconv.c.test-chroot4 shadow-4.18.0/src/grpconv.c ---- shadow-4.18.0/src/grpconv.c.test-chroot4 2025-07-04 11:17:37.598073521 +0200 -+++ shadow-4.18.0/src/grpconv.c 2025-07-04 11:17:37.612354766 +0200 -@@ -39,6 +39,12 @@ - #include "shadowlog.h" - #include "sssd.h" - -+/* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -49,14 +55,14 @@ static bool gr_locked = false; - static bool sgr_locked = false; - - /* local function prototypes */ --static void fail_exit (int status); -+static void fail_exit (int status, bool process_selinux); - static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - --static void fail_exit (int status) -+static void fail_exit (int status, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -64,7 +70,7 @@ static void fail_exit (int status) - } - - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -93,7 +99,7 @@ static void usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -112,6 +118,7 @@ static void process_flags (int argc, cha - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - default: - usage (E_USAGE); -@@ -129,6 +136,8 @@ int main (int argc, char **argv) - struct group grent; - const struct sgrp *sg; - struct sgrp sgent; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -141,30 +150,31 @@ int main (int argc, char **argv) - - OPENLOG (Prog); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - if (gr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - if (sgr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - sgr_locked = true; - if (sgr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -183,7 +193,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, sg->sg_namp, sgr_dbname ()); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - (void) sgr_rewind (); - } -@@ -221,7 +231,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, sgr_dbname (), sgent.sg_namp); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - /* remove password from /etc/group */ - grent = *gr; -@@ -230,30 +240,30 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), grent.gr_name); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - } - -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ - } -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -diff -up shadow-4.18.0/src/grpunconv.c.test-chroot4 shadow-4.18.0/src/grpunconv.c ---- shadow-4.18.0/src/grpunconv.c.test-chroot4 2025-07-04 11:17:37.598110132 +0200 -+++ shadow-4.18.0/src/grpunconv.c 2025-07-04 11:17:37.612706894 +0200 -@@ -38,6 +38,12 @@ - #include "sgroupio.h" - #include "shadowlog.h" - -+/* -+ * Structures -+ */ -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -48,14 +54,14 @@ static bool gr_locked = false; - static bool sgr_locked = false; - - /* local function prototypes */ --static void fail_exit (int status); -+static void fail_exit (int status, bool process_selinux); - static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - --static void fail_exit (int status) -+static void fail_exit (int status, bool process_selinux) - { - if (gr_locked) { -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ -@@ -63,7 +69,7 @@ static void fail_exit (int status) - } - - if (sgr_locked) { -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ -@@ -92,7 +98,7 @@ static void usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -111,6 +117,7 @@ static void process_flags (int argc, cha - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - default: - usage (E_USAGE); -@@ -127,6 +134,8 @@ int main (int argc, char **argv) - const struct group *gr; - struct group grent; - const struct sgrp *sg; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -139,7 +148,8 @@ int main (int argc, char **argv) - - OPENLOG (Prog); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - if (sgr_file_present () == 0) { - exit (0); /* no /etc/gshadow, nothing to do */ -@@ -149,26 +159,26 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, gr_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - gr_locked = true; - if (gr_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, gr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - if (sgr_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, sgr_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - sgr_locked = true; - if (sgr_open (O_RDONLY) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, sgr_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -186,19 +196,19 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, gr_dbname (), grent.gr_name); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - } - } - -- (void) sgr_close (true); /* was only open O_RDONLY */ -+ (void) sgr_close (process_selinux); /* was only open O_RDONLY */ - -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - - if (unlink (SGROUP_FILE) != 0) { -@@ -206,16 +216,16 @@ int main (int argc, char **argv) - _("%s: cannot delete %s\n"), - Prog, SGROUP_FILE); - SYSLOG ((LOG_ERR, "cannot delete %s", SGROUP_FILE)); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - -- if (gr_unlock (true) == 0) { -+ if (gr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); - /* continue */ - } - -- if (sgr_unlock (true) == 0) { -+ if (sgr_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); - /* continue */ - -From e7634eac3da8b6a2a046b7e8ab6148d07618c7f5 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 11:59:32 +0200 -Subject: [PATCH 01/12] src/chsh.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/chsh.c | 25 +++++++++++++++++-------- - 1 file changed, 17 insertions(+), 8 deletions(-) - -diff --git a/src/chsh.c b/src/chsh.c -index 4403d412..f460e329 100644 ---- a/src/chsh.c -+++ b/src/chsh.c -@@ -47,6 +47,9 @@ - #define ETCDIR "/etc" - #endif - -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -66,9 +69,10 @@ NORETURN static void usage (int status); - static void new_fields (void); - static bool shell_is_listed (const char *); - static bool is_restricted_shell (const char *); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_perms (const struct passwd *pw); --static void update_shell (const char *user, char *loginsh); -+static void update_shell (const char *user, char *loginsh, -+ struct option_flags *flags); - - /* - * fail_exit - do some cleanup and exit with the given error code -@@ -217,7 +221,7 @@ static bool shell_is_listed (const char *sh) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -234,6 +238,7 @@ static void process_flags (int argc, char **argv) - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 's': - sflg = true; -@@ -359,10 +364,13 @@ static void check_perms (const struct passwd *pw) - * - * It will not return in case of error. - */ --static void update_shell (const char *user, char *newshell) -+static void update_shell (const char *user, char *newshell, struct option_flags *flags) - { - const struct passwd *pw; /* Password entry from /etc/passwd */ - struct passwd pwent; /* New password entry */ -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Before going any further, raise the ulimit to prevent -@@ -428,12 +436,12 @@ static void update_shell (const char *user, char *newshell) - /* - * Changes have all been made, so commit them and unlock the file. - */ -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (1); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -451,6 +459,7 @@ int main (int argc, char **argv) - { - char *user; /* User name */ - const struct passwd *pw; /* Password entry from /etc/passwd */ -+ struct option_flags flags; - - sanitize_env (); - check_fds (); -@@ -472,7 +481,7 @@ int main (int argc, char **argv) - OPENLOG (Prog); - - /* parse the command line options */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - /* - * Get the name of the user to check. It is either the command line -@@ -555,7 +564,7 @@ int main (int argc, char **argv) - } - } - -- update_shell (user, loginsh); -+ update_shell (user, loginsh, &flags); - - SYSLOG ((LOG_INFO, "changed user '%s' shell to '%s'", user, loginsh)); - --- -2.50.0 - - -From cbcf54b3e5c77a4992bca0ae4f32f0060d120884 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 12:03:30 +0200 -Subject: [PATCH 02/12] src/chsh.c: SELinux file context for fail_exit() - -Do not process SELinux file context when running fail_exit() when chroot -or prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/chsh.c | 45 +++++++++++++++++++++++++-------------------- - 1 file changed, 25 insertions(+), 20 deletions(-) - -diff --git a/src/chsh.c b/src/chsh.c -index f460e329..77cd30e5 100644 ---- a/src/chsh.c -+++ b/src/chsh.c -@@ -64,13 +64,13 @@ static bool pw_locked = false; - /* external identifiers */ - - /* local function prototypes */ --NORETURN static void fail_exit (int code); -+NORETURN static void fail_exit (int code, bool process_selinux); - NORETURN static void usage (int status); - static void new_fields (void); - static bool shell_is_listed (const char *); - static bool is_restricted_shell (const char *); - static void process_flags (int argc, char **argv, struct option_flags *flags); --static void check_perms (const struct passwd *pw); -+static void check_perms (const struct passwd *pw, struct option_flags *flags); - static void update_shell (const char *user, char *loginsh, - struct option_flags *flags); - -@@ -79,10 +79,10 @@ static void update_shell (const char *user, char *loginsh, - */ - NORETURN - static void --fail_exit (int code) -+fail_exit (int code, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -268,13 +268,16 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) - * - * It will not return if the user is not allowed. - */ --static void check_perms (const struct passwd *pw) -+static void check_perms (const struct passwd *pw, struct option_flags *flags) - { - #ifdef USE_PAM - pam_handle_t *pamh = NULL; - int retval; - struct passwd *pampw; - #endif -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Non-privileged users are only allowed to change the shell if the -@@ -285,7 +288,7 @@ static void check_perms (const struct passwd *pw) - fprintf (stderr, - _("You may not change the shell for '%s'.\n"), - pw->pw_name); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -297,7 +300,7 @@ static void check_perms (const struct passwd *pw) - fprintf (stderr, - _("You may not change the shell for '%s'.\n"), - pw->pw_name); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - #ifdef WITH_SELINUX - /* -@@ -310,7 +313,7 @@ static void check_perms (const struct passwd *pw) - fprintf (stderr, - _("You may not change the shell for '%s'.\n"), - pw->pw_name); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - #endif - -@@ -381,7 +384,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags - if (setuid (0) != 0) { - SYSLOG ((LOG_ERR, "can't setuid(0)")); - fputs (_("Cannot change ID to root.\n"), stderr); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - pwd_init (); - -@@ -392,13 +395,13 @@ static void update_shell (const char *user, char *newshell, struct option_flags - if (pw_lock () == 0) { - fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -412,7 +415,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags - fprintf (stderr, - _("%s: user '%s' does not exist in %s\n"), - Prog, user, pw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -430,7 +433,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - /* -@@ -439,7 +442,7 @@ static void update_shell (const char *user, char *newshell, struct option_flags - if (pw_close (process_selinux) == 0) { - fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); -@@ -460,6 +463,7 @@ int main (int argc, char **argv) - char *user; /* User name */ - const struct passwd *pw; /* Password entry from /etc/passwd */ - struct option_flags flags; -+ bool process_selinux; - - sanitize_env (); - check_fds (); -@@ -482,6 +486,7 @@ int main (int argc, char **argv) - - /* parse the command line options */ - process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - /* - * Get the name of the user to check. It is either the command line -@@ -490,14 +495,14 @@ int main (int argc, char **argv) - if (optind < argc) { - if (!is_valid_user_name (argv[optind])) { - fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - user = argv[optind]; - pw = xgetpwnam (user); - if (NULL == pw) { - fprintf (stderr, - _("%s: user '%s' does not exist\n"), Prog, user); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } else { - pw = get_my_pwent (); -@@ -507,12 +512,12 @@ int main (int argc, char **argv) - Prog); - SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", - (unsigned long) getuid ())); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - user = xstrdup (pw->pw_name); - } - -- check_perms (pw); -+ check_perms (pw, &flags); - - /* - * Now get the login shell. Either get it from the password -@@ -539,7 +544,7 @@ int main (int argc, char **argv) - */ - if (valid_field (loginsh, ":,=\n") != 0) { - fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - if (!streq(loginsh, "") - && (loginsh[0] != '/' -@@ -550,7 +555,7 @@ int main (int argc, char **argv) - fprintf (stderr, _("%s: Warning: %s is an invalid shell\n"), Prog, loginsh); - } else { - fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - } - --- -2.50.0 - - -From 58600326353a2198df7f8753e2ad8ffa216b68cc Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 12:35:44 +0200 -Subject: [PATCH 03/12] src/passwd.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/passwd.c | 41 ++++++++++++++++++++++++++++------------- - 1 file changed, 28 insertions(+), 13 deletions(-) - -diff --git a/src/passwd.c b/src/passwd.c -index 512dc572..6d6f319e 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -53,6 +53,12 @@ - #define E_PWDBUSY 5 /* passwd file busy, try again later */ - #define E_BAD_ARG 6 /* invalid argument to option */ - #define E_PAM_ERR 10 /* PAM returned an error */ -+ -+struct option_flags { -+ bool chroot; -+ bool prefix; -+}; -+ - /* - * Global variables - */ -@@ -131,9 +137,9 @@ static void print_status (const struct passwd *); - NORETURN static void fail_exit (int); - NORETURN static void oom (void); - static char *update_crypt_pw (char *); --static void update_noshadow (void); -+static void update_noshadow (struct option_flags *flags); - --static void update_shadow (void); -+static void update_shadow (struct option_flags *flags); - - /* - * usage - print command usage and exit -@@ -549,10 +555,13 @@ static char *update_crypt_pw (char *cp) - } - - --static void update_noshadow (void) -+static void update_noshadow (struct option_flags *flags) - { - const struct passwd *pw; - struct passwd *npw; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - if (pw_lock () == 0) { - (void) fprintf (stderr, -@@ -586,14 +595,14 @@ static void update_noshadow (void) - Prog, pw_dbname (), npw->pw_name); - fail_exit (E_FAILURE); - } -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); - fail_exit (E_FAILURE); - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); -@@ -603,10 +612,13 @@ static void update_noshadow (void) - pw_locked = false; - } - --static void update_shadow (void) -+static void update_shadow (struct option_flags *flags) - { - const struct spwd *sp; - struct spwd *nsp; -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot && !flags->prefix; - - if (spw_lock () == 0) { - (void) fprintf (stderr, -@@ -625,9 +637,9 @@ static void update_shadow (void) - sp = spw_locate (name); - if (NULL == sp) { - /* Try to update the password in /etc/passwd instead. */ -- (void) spw_close (true); -- update_noshadow (); -- if (spw_unlock (true) == 0) { -+ (void) spw_close (process_selinux); -+ update_noshadow (flags); -+ if (spw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -681,14 +693,14 @@ static void update_shadow (void) - Prog, spw_dbname (), nsp->sp_namp); - fail_exit (E_FAILURE); - } -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_FAILURE); - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -733,6 +745,7 @@ main(int argc, char **argv) - char *cp; /* Miscellaneous character pointing */ - - const struct spwd *sp; /* Shadow file entry for user */ -+ struct option_flags flags; - - sanitize_env (); - check_fds (); -@@ -849,8 +862,10 @@ main(int argc, char **argv) - } - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags.chroot = true; - break; - case 'P': /* no-op, handled in process_prefix_flag () */ -+ flags.prefix = true; - break; - case 'S': - Sflg = true; /* ok for users */ -@@ -1107,9 +1122,9 @@ main(int argc, char **argv) - exit (E_NOPERM); - } - if (spw_file_present ()) { -- update_shadow (); -+ update_shadow (&flags); - } else { -- update_noshadow (); -+ update_noshadow (&flags); - } - - nscd_flush_cache ("passwd"); --- -2.50.0 - - -From d5a9144c809e808600c7dc730970efc04bc032fd Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 12:48:18 +0200 -Subject: [PATCH 04/12] src/passwd.c: SELinux file context for fail_exit() - -Do not process SELinux file context when running fail_exit() when chroot -or prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/passwd.c | 46 ++++++++++++++++++++++++---------------------- - 1 file changed, 24 insertions(+), 22 deletions(-) - -diff --git a/src/passwd.c b/src/passwd.c -index 6d6f319e..78859c96 100644 ---- a/src/passwd.c -+++ b/src/passwd.c -@@ -134,9 +134,9 @@ static int new_password (const struct passwd *); - static void check_password (const struct passwd *, const struct spwd *); - static /*@observer@*/const char *pw_status (const char *); - static void print_status (const struct passwd *); --NORETURN static void fail_exit (int); --NORETURN static void oom (void); --static char *update_crypt_pw (char *); -+NORETURN static void fail_exit (int, bool); -+NORETURN static void oom (bool process_selinux); -+static char *update_crypt_pw (char *, bool); - static void update_noshadow (struct option_flags *flags); - - static void update_shadow (struct option_flags *flags); -@@ -486,10 +486,10 @@ static void print_status (const struct passwd *pw) - - NORETURN - static void --fail_exit (int status) -+fail_exit (int status, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -497,7 +497,7 @@ fail_exit (int status) - } - - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -509,13 +509,13 @@ fail_exit (int status) - - NORETURN - static void --oom (void) -+oom (bool process_selinux) - { - (void) fprintf (stderr, _("%s: out of memory\n"), Prog); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - --static char *update_crypt_pw (char *cp) -+static char *update_crypt_pw (char *cp, bool process_selinux) - { - if (!use_pam) - { -@@ -533,7 +533,7 @@ static char *update_crypt_pw (char *cp) - _("%s: unlocking the password would result in a passwordless account.\n" - "You should set a password with usermod -p to unlock the password of this account.\n"), - Prog); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } else { - cp++; - } -@@ -575,32 +575,32 @@ static void update_noshadow (struct option_flags *flags) - _("%s: cannot open %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); -- fail_exit (E_MISSING); -+ fail_exit (E_MISSING, process_selinux); - } - pw = pw_locate (name); - if (NULL == pw) { - (void) fprintf (stderr, - _("%s: user '%s' does not exist in %s\n"), - Prog, name, pw_dbname ()); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - npw = __pw_dup (pw); - if (NULL == npw) { -- oom (); -+ oom (process_selinux); - } -- npw->pw_passwd = update_crypt_pw (npw->pw_passwd); -+ npw->pw_passwd = update_crypt_pw (npw->pw_passwd, process_selinux); - if (pw_update (npw) == 0) { - (void) fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), npw->pw_name); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - if (pw_close (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - if (pw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, -@@ -632,7 +632,7 @@ static void update_shadow (struct option_flags *flags) - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - sp = spw_locate (name); - if (NULL == sp) { -@@ -651,9 +651,9 @@ static void update_shadow (struct option_flags *flags) - } - nsp = __spw_dup (sp); - if (NULL == nsp) { -- oom (); -+ oom (process_selinux); - } -- nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp); -+ nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp, process_selinux); - if (xflg) { - nsp->sp_max = age_max; - } -@@ -691,14 +691,14 @@ static void update_shadow (struct option_flags *flags) - (void) fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), nsp->sp_namp); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - if (spw_close (process_selinux) == 0) { - (void) fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - if (spw_unlock (process_selinux) == 0) { - (void) fprintf (stderr, -@@ -746,6 +746,7 @@ main(int argc, char **argv) - - const struct spwd *sp; /* Shadow file entry for user */ - struct option_flags flags; -+ bool process_selinux; - - sanitize_env (); - check_fds (); -@@ -912,6 +913,7 @@ main(int argc, char **argv) - } - } - } -+ process_selinux = !flags.chroot && !flags.prefix; - - /* - * Now I have to get the user name. The name will be gotten from the -@@ -931,7 +933,7 @@ main(int argc, char **argv) - if (optind < argc) { - if (!is_valid_user_name (argv[optind])) { - fprintf (stderr, _("%s: Provided user name is not a valid name\n"), Prog); -- fail_exit (E_NOPERM); -+ fail_exit (E_NOPERM, process_selinux); - } - name = argv[optind]; - } else { --- -2.50.0 - - -From a736c2af5702e98081bace5fde10a264f443d318 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 12:55:35 +0200 -Subject: [PATCH 05/12] src/pwck.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwck.c | 46 ++++++++++++++++++++++++++++++---------------- - 1 file changed, 30 insertions(+), 16 deletions(-) - -diff --git a/src/pwck.c b/src/pwck.c -index 9c4cc29a..d0f2f1c9 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -48,6 +48,10 @@ - #define E_CANTUPDATE 5 - #define E_CANTSORT 6 - -+struct option_flags { -+ bool chroot; -+}; -+ - /* - * Global variables - */ -@@ -71,10 +75,11 @@ static bool quiet = false; /* don't report warnings, only errors */ - /* local function prototypes */ - static void fail_exit (int code); - NORETURN static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void open_files (void); --static void close_files (bool changed); --static void check_pw_file (bool *errors, bool *changed); -+static void close_files (bool changed, struct option_flags *flags); -+static void check_pw_file (bool *errors, bool *changed, -+ struct option_flags *flags); - static void check_spw_file (bool *errors, bool *changed); - - extern int allow_bad_names; -@@ -155,7 +160,7 @@ usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -188,6 +193,7 @@ static void process_flags (int argc, char **argv) - read_only = true; - break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 's': - sort_mode = true; -@@ -302,14 +308,18 @@ static void open_files (void) - * changes are committed in the databases. The databases are - * unlocked anyway. - */ --static void close_files (bool changed) -+static void close_files (bool changed, struct option_flags *flags) - { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; -+ - /* - * All done. If there were no change we can just abandon any - * changes to the files. - */ - if (changed) { -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -@@ -320,7 +330,7 @@ static void close_files (bool changed) - } - fail_exit (E_CANTUPDATE); - } -- if (spw_opened && (spw_close (true) == 0)) { -+ if (spw_opened && (spw_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -@@ -338,7 +348,7 @@ static void close_files (bool changed) - * Don't be anti-social - unlock the files when you're done. - */ - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -351,7 +361,7 @@ static void close_files (bool changed) - } - spw_locked = false; - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, pw_dbname ()); -@@ -368,13 +378,16 @@ static void close_files (bool changed) - /* - * check_pw_file - check the content of the passwd file - */ --static void check_pw_file (bool *errors, bool *changed) -+static void check_pw_file (bool *errors, bool *changed, struct option_flags *flags) - { - struct commonio_entry *pfe, *tpfe; - struct passwd *pwd; - const struct spwd *spw; - uid_t min_sys_id = getdef_ulong ("SYS_UID_MIN", 101UL); - uid_t max_sys_id = getdef_ulong ("SYS_UID_MAX", 999UL); -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Loop through the entire password file. -@@ -581,7 +594,7 @@ static void check_pw_file (bool *errors, bool *changed) - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); - *errors = true; -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -657,7 +670,7 @@ static void check_pw_file (bool *errors, bool *changed) - } - #ifdef WITH_TCB - if (getdef_bool ("USE_TCB") && spw_locked) { -- if (spw_opened && (spw_close (true) == 0)) { -+ if (spw_opened && (spw_close (process_selinux) == 0)) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); -@@ -669,7 +682,7 @@ static void check_pw_file (bool *errors, bool *changed) - } else { - spw_opened = false; - } -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, - _("%s: failed to unlock %s\n"), - Prog, spw_dbname ()); -@@ -840,6 +853,7 @@ int main (int argc, char **argv) - { - bool errors = false; - bool changed = false; -+ struct option_flags flags; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -853,7 +867,7 @@ int main (int argc, char **argv) - OPENLOG (Prog); - - /* Parse the command line arguments */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - open_files (); - -@@ -874,14 +888,14 @@ int main (int argc, char **argv) - } - changed = true; - } else { -- check_pw_file (&errors, &changed); -+ check_pw_file (&errors, &changed, &flags); - - if (is_shadow) { - check_spw_file (&errors, &changed); - } - } - -- close_files (changed); -+ close_files (changed, &flags); - - if (!read_only) { - nscd_flush_cache ("passwd"); --- -2.50.0 - - -From 09957a9748ae6cd28e0826d4cacd939ac288ca1b Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 12:58:58 +0200 -Subject: [PATCH 06/12] src/pwck.c: SELinux file context for fail_exit() - -Do not process SELinux file context when running fail_exit() when chroot -or prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwck.c | 39 ++++++++++++++++++++++----------------- - 1 file changed, 22 insertions(+), 17 deletions(-) - -diff --git a/src/pwck.c b/src/pwck.c -index d0f2f1c9..f1e9c085 100644 ---- a/src/pwck.c -+++ b/src/pwck.c -@@ -73,10 +73,10 @@ static bool sort_mode = false; - static bool quiet = false; /* don't report warnings, only errors */ - - /* local function prototypes */ --static void fail_exit (int code); -+static void fail_exit (int code, bool process_selinux); - NORETURN static void usage (int status); - static void process_flags (int argc, char **argv, struct option_flags *flags); --static void open_files (void); -+static void open_files (struct option_flags *flags); - static void close_files (bool changed, struct option_flags *flags); - static void check_pw_file (bool *errors, bool *changed, - struct option_flags *flags); -@@ -87,10 +87,10 @@ extern int allow_bad_names; - /* - * fail_exit - do some cleanup and exit with the given error code - */ --static void fail_exit (int code) -+static void fail_exit (int code, bool process_selinux) - { - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - if (use_system_spw_file) { - SYSLOG ((LOG_ERR, "failed to unlock %s", -@@ -101,7 +101,7 @@ static void fail_exit (int code) - } - - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - if (use_system_pw_file) { - SYSLOG ((LOG_ERR, "failed to unlock %s", -@@ -246,12 +246,15 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) - * In read-only mode, the databases are not locked and are opened - * only for reading. - */ --static void open_files (void) -+static void open_files (struct option_flags *flags) - { - bool use_tcb = false; - #ifdef WITH_TCB - use_tcb = getdef_bool ("USE_TCB"); - #endif /* WITH_TCB */ -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - /* - * Lock the files if we aren't in "read-only" mode -@@ -261,7 +264,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_CANTLOCK); -+ fail_exit (E_CANTLOCK, process_selinux); - } - pw_locked = true; - if (is_shadow && !use_tcb) { -@@ -269,7 +272,7 @@ static void open_files (void) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_CANTLOCK); -+ fail_exit (E_CANTLOCK, process_selinux); - } - spw_locked = true; - } -@@ -285,7 +288,7 @@ static void open_files (void) - if (use_system_pw_file) { - SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); - } -- fail_exit (E_CANTOPEN); -+ fail_exit (E_CANTOPEN, process_selinux); - } - if (is_shadow && !use_tcb) { - if (spw_open (read_only ? O_RDONLY : O_RDWR) == 0) { -@@ -295,7 +298,7 @@ static void open_files (void) - SYSLOG ((LOG_WARN, "cannot open %s", - spw_dbname ())); - } -- fail_exit (E_CANTOPEN); -+ fail_exit (E_CANTOPEN, process_selinux); - } - spw_opened = true; - } -@@ -328,7 +331,7 @@ static void close_files (bool changed, struct option_flags *flags) - "failure while writing changes to %s", - pw_dbname ())); - } -- fail_exit (E_CANTUPDATE); -+ fail_exit (E_CANTUPDATE, process_selinux); - } - if (spw_opened && (spw_close (process_selinux) == 0)) { - fprintf (stderr, -@@ -339,7 +342,7 @@ static void close_files (bool changed, struct option_flags *flags) - "failure while writing changes to %s", - spw_dbname ())); - } -- fail_exit (E_CANTUPDATE); -+ fail_exit (E_CANTUPDATE, process_selinux); - } - spw_opened = false; - } -@@ -644,7 +647,7 @@ static void check_pw_file (bool *errors, bool *changed, struct option_flags *fla - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), sp.sp_namp); -- fail_exit (E_CANTUPDATE); -+ fail_exit (E_CANTUPDATE, process_selinux); - } - /* remove password from /etc/passwd */ - pw = *pwd; -@@ -653,7 +656,7 @@ static void check_pw_file (bool *errors, bool *changed, struct option_flags *fla - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pw.pw_name); -- fail_exit (E_CANTUPDATE); -+ fail_exit (E_CANTUPDATE, process_selinux); - } - } - } else { -@@ -854,6 +857,7 @@ int main (int argc, char **argv) - bool errors = false; - bool changed = false; - struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -868,22 +872,23 @@ int main (int argc, char **argv) - - /* Parse the command line arguments */ - process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - -- open_files (); -+ open_files (&flags); - - if (sort_mode) { - if (pw_sort () != 0) { - fprintf (stderr, - _("%s: cannot sort entries in %s\n"), - Prog, pw_dbname ()); -- fail_exit (E_CANTSORT); -+ fail_exit (E_CANTSORT, process_selinux); - } - if (is_shadow) { - if (spw_sort () != 0) { - fprintf (stderr, - _("%s: cannot sort entries in %s\n"), - Prog, spw_dbname ()); -- fail_exit (E_CANTSORT); -+ fail_exit (E_CANTSORT, process_selinux); - } - } - changed = true; --- -2.50.0 - - -From 0c39283e9298fc130c55516fd0a4a0c6b6003bc9 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 13:04:26 +0200 -Subject: [PATCH 07/12] src/pwconv.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwconv.c | 23 ++++++++++++++++------- - 1 file changed, 16 insertions(+), 7 deletions(-) - -diff --git a/src/pwconv.c b/src/pwconv.c -index b0d668b5..6c81cc6e 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -67,6 +67,11 @@ - #define E_MISSING 4 /* unexpected failure, passwd file missing */ - #define E_PWDBUSY 5 /* passwd file(s) busy */ - #define E_BADENTRY 6 /* bad shadow entry */ -+ -+struct option_flags { -+ bool chroot; -+}; -+ - /* - * Global variables - */ -@@ -78,7 +83,7 @@ static bool pw_locked = false; - /* local function prototypes */ - static void fail_exit (int status); - static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - - static void fail_exit (int status) - { -@@ -120,7 +125,7 @@ static void usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -139,6 +144,7 @@ static void process_flags (int argc, char **argv) - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - default: - usage (E_USAGE); -@@ -156,6 +162,8 @@ int main (int argc, char **argv) - struct passwd pwent; - const struct spwd *sp; - struct spwd spent; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -168,7 +176,8 @@ int main (int argc, char **argv) - - OPENLOG (Prog); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - #ifdef WITH_TCB - if (getdef_bool("USE_TCB")) { -@@ -274,14 +283,14 @@ int main (int argc, char **argv) - } - } - -- if (spw_close (true) == 0) { -+ if (spw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); - fail_exit (E_FAILURE); - } -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -@@ -299,13 +308,13 @@ int main (int argc, char **argv) - /* continue */ - } - -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ - } - -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ --- -2.50.0 - - -From 997a523d41bb513f37ca88cab35cba9281f036b6 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 13:05:52 +0200 -Subject: [PATCH 08/12] src/pwconv.c: SELinux file context for fail_exit() - -Do not process SELinux file context when running fail_exit() when chroot -or prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwconv.c | 26 +++++++++++++------------- - 1 file changed, 13 insertions(+), 13 deletions(-) - -diff --git a/src/pwconv.c b/src/pwconv.c -index 6c81cc6e..1dc1fd86 100644 ---- a/src/pwconv.c -+++ b/src/pwconv.c -@@ -81,14 +81,14 @@ static bool spw_locked = false; - static bool pw_locked = false; - - /* local function prototypes */ --static void fail_exit (int status); -+static void fail_exit (int status, bool process_selinux); - static void usage (int status); - static void process_flags (int argc, char **argv, struct option_flags *flags); - --static void fail_exit (int status) -+static void fail_exit (int status, bool process_selinux) - { - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -96,7 +96,7 @@ static void fail_exit (int status) - } - - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ -@@ -190,26 +190,26 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (E_PWDBUSY); -+ fail_exit (E_PWDBUSY, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, pw_dbname ()); -- fail_exit (E_MISSING); -+ fail_exit (E_MISSING, process_selinux); - } - - if (spw_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (E_PWDBUSY); -+ fail_exit (E_PWDBUSY, process_selinux); - } - spw_locked = true; - if (spw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), Prog, spw_dbname ()); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - - /* -@@ -228,7 +228,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot remove entry '%s' from %s\n"), - Prog, sp->sp_namp, spw_dbname ()); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - (void) spw_rewind(); - } -@@ -269,7 +269,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, spw_dbname (), spent.sp_namp); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - - /* remove password from /etc/passwd */ -@@ -279,7 +279,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - } - -@@ -288,14 +288,14 @@ int main (int argc, char **argv) - _("%s: failure while writing changes to %s\n"), - Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (E_FAILURE); -+ fail_exit (E_FAILURE, process_selinux); - } - - /* /etc/passwd- (backup file) */ --- -2.50.0 - - -From 13e902a1b368049cb4c6853a7470f66efbac6e72 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 13:08:10 +0200 -Subject: [PATCH 09/12] src/pwunconv.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwunconv.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/src/pwunconv.c b/src/pwunconv.c -index 7a6d2be5..d46bde6d 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -30,6 +30,9 @@ - #include "sssd.h" - #include "string/strcmp/streq.h" - -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -42,7 +45,7 @@ static bool pw_locked = false; - /* local function prototypes */ - static void fail_exit (int status); - static void usage (int status); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - - static void fail_exit (int status) - { -@@ -82,7 +85,7 @@ static void usage (int status) - * - * It will not return if an error is encountered. - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - /* - * Parse the command line options. -@@ -101,6 +104,7 @@ static void process_flags (int argc, char **argv) - usage (E_SUCCESS); - /*@notreached@*/break; - case 'R': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - default: - usage (E_USAGE); -@@ -117,6 +121,8 @@ int main (int argc, char **argv) - const struct passwd *pw; - struct passwd pwent; - const struct spwd *spwd; -+ struct option_flags flags; -+ bool process_selinux; - - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -129,7 +135,8 @@ int main (int argc, char **argv) - - OPENLOG (Prog); - -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); -+ process_selinux = !flags.chroot; - - #ifdef WITH_TCB - if (getdef_bool("USE_TCB")) { -@@ -205,9 +212,9 @@ int main (int argc, char **argv) - } - } - -- (void) spw_close (true); /* was only open O_RDONLY */ -+ (void) spw_close (process_selinux); /* was only open O_RDONLY */ - -- if (pw_close (true) == 0) { -+ if (pw_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); -@@ -222,12 +229,12 @@ int main (int argc, char **argv) - fail_exit (3); - } - -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ --- -2.50.0 - - -From 849e748fe08129684da13acba13a247f0aa98eff Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 13:09:12 +0200 -Subject: [PATCH 10/12] src/pwunconv.c: SELinux file context for fail_exit() - -Do not process SELinux file context when running fail_exit() when chroot -or prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/pwunconv.c | 22 +++++++++++----------- - 1 file changed, 11 insertions(+), 11 deletions(-) - -diff --git a/src/pwunconv.c b/src/pwunconv.c -index d46bde6d..d3e10f68 100644 ---- a/src/pwunconv.c -+++ b/src/pwunconv.c -@@ -43,21 +43,21 @@ static bool spw_locked = false; - static bool pw_locked = false; - - /* local function prototypes */ --static void fail_exit (int status); -+static void fail_exit (int status, bool process_selinux); - static void usage (int status); - static void process_flags (int argc, char **argv, struct option_flags *flags); - --static void fail_exit (int status) -+static void fail_exit (int status, bool process_selinux) - { - if (spw_locked) { -- if (spw_unlock (true) == 0) { -+ if (spw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); - /* continue */ - } - } - if (pw_locked) { -- if (pw_unlock (true) == 0) { -+ if (pw_unlock (process_selinux) == 0) { - fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); - /* continue */ -@@ -154,28 +154,28 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, pw_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - pw_locked = true; - if (pw_open (O_CREAT | O_RDWR) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, pw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - if (spw_lock () == 0) { - fprintf (stderr, - _("%s: cannot lock %s; try again later.\n"), - Prog, spw_dbname ()); -- fail_exit (5); -+ fail_exit (5, process_selinux); - } - spw_locked = true; - if (spw_open (O_RDONLY) == 0) { - fprintf (stderr, - _("%s: cannot open %s\n"), - Prog, spw_dbname ()); -- fail_exit (1); -+ fail_exit (1, process_selinux); - } - - (void) pw_rewind (); -@@ -208,7 +208,7 @@ int main (int argc, char **argv) - fprintf (stderr, - _("%s: failed to prepare the new %s entry '%s'\n"), - Prog, pw_dbname (), pwent.pw_name); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - } - -@@ -219,14 +219,14 @@ int main (int argc, char **argv) - _("%s: failure while writing changes to %s\n"), - Prog, pw_dbname ()); - SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - - if (unlink (SHADOW) != 0) { - fprintf (stderr, - _("%s: cannot delete %s\n"), Prog, SHADOW); - SYSLOG ((LOG_ERR, "cannot delete %s", SHADOW)); -- fail_exit (3); -+ fail_exit (3, process_selinux); - } - - if (spw_unlock (process_selinux) == 0) { --- -2.50.0 - - -From b1bcf1cf8245b195cff7586770ad861f89cb7c92 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Thu, 3 Jul 2025 14:29:55 +0200 -Subject: [PATCH 11/12] src/gpasswd.c: chroot or prefix SELinux file context - -Do not process SELinux file context during file closure when chroot or -prefix options are selected. - -Signed-off-by: Iker Pedrosa ---- - src/gpasswd.c | 44 ++++++++++++++++++++++++++++---------------- - 1 file changed, 28 insertions(+), 16 deletions(-) - -diff --git a/src/gpasswd.c b/src/gpasswd.c -index a49b9140..94b2bb32 100644 ---- a/src/gpasswd.c -+++ b/src/gpasswd.c -@@ -40,6 +40,9 @@ - #include "string/strcpy/strtcpy.h" - #include "string/strdup/xstrdup.h" - -+struct option_flags { -+ bool chroot; -+}; - - /* - * Global variables -@@ -87,17 +90,17 @@ NORETURN static void failure(void); - static void usage (int status); - static void catch_signals (int killed); - static bool is_valid_user_list (const char *users); --static void process_flags (int argc, char **argv); -+static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (int argc, int opt_index); - static void open_files (void); --static void close_files (void); -+static void close_files (struct option_flags *flags); - #ifdef SHADOWGRP --static void get_group (struct group *gr, struct sgrp *sg); -+static void get_group (struct group *gr, struct sgrp *sg, struct option_flags *flags); - static void check_perms (const struct group *gr, const struct sgrp *sg); - static void update_group (struct group *gr, struct sgrp *sg); - static void change_passwd (struct group *gr, struct sgrp *sg); - #else --static void get_group (struct group *gr); -+static void get_group (struct group *gr, struct option_flags *flags); - static void check_perms (const struct group *gr); - static void update_group (struct group *gr); - static void change_passwd (struct group *gr); -@@ -211,7 +214,7 @@ static void failure(void) - /* - * process_flags - process the command line options and arguments - */ --static void process_flags (int argc, char **argv) -+static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; - static struct option long_options[] = { -@@ -272,6 +275,7 @@ static void process_flags (int argc, char **argv) - Mflg = true; - break; - case 'Q': /* no-op, handled in process_root_flag () */ -+ flags->chroot = true; - break; - case 'r': /* remove group password */ - rflg = true; -@@ -591,9 +595,13 @@ static void log_gpasswd_success_group (MAYBE_UNUSED void *arg) - * - * It will call exit in case of error. - */ --static void close_files (void) -+static void close_files (struct option_flags *flags) - { -- if (gr_close (true) == 0) { -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; -+ -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, gr_dbname ()); -@@ -607,7 +615,7 @@ static void close_files (void) - - #ifdef SHADOWGRP - if (is_shadowgrp) { -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while writing changes to %s\n"), - Prog, sgr_dbname ()); -@@ -695,15 +703,18 @@ static void update_group (struct group *gr) - * Note: If !is_shadowgrp, *sg will not be initialized. - */ - #ifdef SHADOWGRP --static void get_group (struct group *gr, struct sgrp *sg) -+static void get_group (struct group *gr, struct sgrp *sg, struct option_flags *flags) - #else --static void get_group (struct group *gr) -+static void get_group (struct group *gr, struct option_flags *flags) - #endif - { - struct group const*tmpgr = NULL; - #ifdef SHADOWGRP - struct sgrp const*tmpsg = NULL; - #endif -+ bool process_selinux; -+ -+ process_selinux = !flags->chroot; - - if (gr_open (O_RDONLY) == 0) { - fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); -@@ -724,7 +735,7 @@ static void get_group (struct group *gr) - gr->gr_passwd = xstrdup (tmpgr->gr_passwd); - gr->gr_mem = dup_list (tmpgr->gr_mem); - -- if (gr_close (true) == 0) { -+ if (gr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while closing read-only %s\n"), - Prog, gr_dbname ()); -@@ -762,7 +773,7 @@ static void get_group (struct group *gr) - sg->sg_adm[0] = NULL; - - } -- if (sgr_close (true) == 0) { -+ if (sgr_close (process_selinux) == 0) { - fprintf (stderr, - _("%s: failure while closing read-only %s\n"), - Prog, sgr_dbname ()); -@@ -864,6 +875,7 @@ int main (int argc, char **argv) - struct sgrp sgent; - #endif - struct passwd *pw = NULL; -+ struct option_flags flags; - - #ifdef WITH_AUDIT - audit_help_open (); -@@ -924,15 +936,15 @@ int main (int argc, char **argv) - } - - /* Parse the options */ -- process_flags (argc, argv); -+ process_flags (argc, argv, &flags); - - /* - * Replicate the group so it can be modified later on. - */ - #ifdef SHADOWGRP -- get_group (&grent, &sgent); -+ get_group (&grent, &sgent, &flags); - #else -- get_group (&grent); -+ get_group (&grent, &flags); - #endif - - /* -@@ -1095,7 +1107,7 @@ int main (int argc, char **argv) - update_group (&grent); - #endif - -- close_files (); -+ close_files (&flags); - - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_GROUP); --- -2.50.0 - - -From 2c250fae8866a682bac686dcaa198b325d198cf9 Mon Sep 17 00:00:00 2001 -From: Iker Pedrosa -Date: Fri, 4 Jul 2025 10:03:42 +0200 -Subject: [PATCH 12/12] man/: update `--root` flag with no SELinux support - -Signed-off-by: Iker Pedrosa ---- - man/chage.1.xml | 1 + - man/chfn.1.xml | 1 + - man/chgpasswd.8.xml | 1 + - man/chpasswd.8.xml | 1 + - man/chsh.1.xml | 1 + - man/faillog.8.xml | 1 + - man/gpasswd.1.xml | 1 + - man/groupadd.8.xml | 1 + - man/groupdel.8.xml | 1 + - man/groupmems.8.xml | 1 + - man/groupmod.8.xml | 1 + - man/grpck.8.xml | 1 + - man/lastlog.8.xml | 1 + - man/newusers.8.xml | 1 + - man/passwd.1.xml | 1 + - man/pwck.8.xml | 1 + - man/pwconv.8.xml | 1 + - man/useradd.8.xml | 1 + - man/userdel.8.xml | 1 + - man/usermod.8.xml | 1 + - man/vipw.8.xml | 1 + - 21 files changed, 21 insertions(+) - -diff --git a/man/chage.1.xml b/man/chage.1.xml -index 4ccdf483..a3fff291 100644 ---- a/man/chage.1.xml -+++ b/man/chage.1.xml -@@ -205,6 +205,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/chfn.1.xml b/man/chfn.1.xml -index 2fa49feb..d199ef03 100644 ---- a/man/chfn.1.xml -+++ b/man/chfn.1.xml -@@ -138,6 +138,7 @@ - Apply changes in the CHROOT_DIR - directory and use the configuration files from the - CHROOT_DIR directory. -+ No SELINUX support. - - - -diff --git a/man/chgpasswd.8.xml b/man/chgpasswd.8.xml -index f4a83c24..184c1696 100644 ---- a/man/chgpasswd.8.xml -+++ b/man/chgpasswd.8.xml -@@ -134,6 +134,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/chpasswd.8.xml b/man/chpasswd.8.xml -index cffd9df1..440c8342 100644 ---- a/man/chpasswd.8.xml -+++ b/man/chpasswd.8.xml -@@ -176,6 +176,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/chsh.1.xml b/man/chsh.1.xml -index db2d0ceb..8f253731 100644 ---- a/man/chsh.1.xml -+++ b/man/chsh.1.xml -@@ -89,6 +89,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/faillog.8.xml b/man/faillog.8.xml -index effe43a9..7d453fd2 100644 ---- a/man/faillog.8.xml -+++ b/man/faillog.8.xml -@@ -162,6 +162,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/gpasswd.1.xml b/man/gpasswd.1.xml -index 9b89d915..f918442f 100644 ---- a/man/gpasswd.1.xml -+++ b/man/gpasswd.1.xml -@@ -165,6 +165,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/groupadd.8.xml b/man/groupadd.8.xml -index 9abf159a..2dea7ae5 100644 ---- a/man/groupadd.8.xml -+++ b/man/groupadd.8.xml -@@ -206,6 +206,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/groupdel.8.xml b/man/groupdel.8.xml -index 8d41b883..31f29994 100644 ---- a/man/groupdel.8.xml -+++ b/man/groupdel.8.xml -@@ -94,6 +94,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/groupmems.8.xml b/man/groupmems.8.xml -index cbc84622..0def6c99 100644 ---- a/man/groupmems.8.xml -+++ b/man/groupmems.8.xml -@@ -147,6 +147,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/groupmod.8.xml b/man/groupmod.8.xml -index 2d51f271..ca287441 100644 ---- a/man/groupmod.8.xml -+++ b/man/groupmod.8.xml -@@ -169,6 +169,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/grpck.8.xml b/man/grpck.8.xml -index 31aa6ca3..9feb190e 100644 ---- a/man/grpck.8.xml -+++ b/man/grpck.8.xml -@@ -154,6 +154,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/lastlog.8.xml b/man/lastlog.8.xml -index cefe5ac2..b0589203 100644 ---- a/man/lastlog.8.xml -+++ b/man/lastlog.8.xml -@@ -109,6 +109,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/newusers.8.xml b/man/newusers.8.xml -index 6812c750..e0380608 100644 ---- a/man/newusers.8.xml -+++ b/man/newusers.8.xml -@@ -313,6 +313,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/passwd.1.xml b/man/passwd.1.xml -index 65dca040..def35609 100644 ---- a/man/passwd.1.xml -+++ b/man/passwd.1.xml -@@ -279,6 +279,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/pwck.8.xml b/man/pwck.8.xml -index 4eb820d6..998bb44a 100644 ---- a/man/pwck.8.xml -+++ b/man/pwck.8.xml -@@ -202,6 +202,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/pwconv.8.xml b/man/pwconv.8.xml -index c4aedef6..9be3f7c5 100644 ---- a/man/pwconv.8.xml -+++ b/man/pwconv.8.xml -@@ -183,6 +183,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/useradd.8.xml b/man/useradd.8.xml -index fd9ff697..e6db7f6d 100644 ---- a/man/useradd.8.xml -+++ b/man/useradd.8.xml -@@ -515,6 +515,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/userdel.8.xml b/man/userdel.8.xml -index 32851f11..de8eff24 100644 ---- a/man/userdel.8.xml -+++ b/man/userdel.8.xml -@@ -120,6 +120,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/usermod.8.xml b/man/usermod.8.xml -index 61b5e3a9..2c704ab5 100644 ---- a/man/usermod.8.xml -+++ b/man/usermod.8.xml -@@ -337,6 +337,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - -diff --git a/man/vipw.8.xml b/man/vipw.8.xml -index fb80582b..975fba37 100644 ---- a/man/vipw.8.xml -+++ b/man/vipw.8.xml -@@ -120,6 +120,7 @@ - directory and use the configuration files from the - CHROOT_DIR directory. - Only absolute paths are supported. -+ No SELINUX support. - - - --- -2.50.0 - diff --git a/shadow-utils.spec b/shadow-utils.spec index 483eb21..c6773d9 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -24,8 +24,6 @@ Source7: passwd.pamd Patch0: shadow-4.15.0-manfix.patch # Probably non-upstreamable Patch1: shadow-4.18.0-account-tools-setuid.patch -# https://github.com/shadow-maint/shadow/commit/db0e0b9112332a45131912021317ab5ab4fd6e40 -Patch2: shadow-4.18.0-selinux-chroot-prefix.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -271,6 +269,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Nov 25 2025 Adam Williamson - 2:4.18.0-7 +- Also revert changes from -4 (last known good was -3) + * Tue Nov 25 2025 Adam Williamson - 2:4.18.0-6 - Revert changes from -5 (they were only meant for testing) From d39147a22233042f440eae625add65ddefeaa4bc Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Tue, 25 Nov 2025 13:25:22 -0800 Subject: [PATCH 102/118] Really bump release, d'oh --- shadow-utils.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index c6773d9..1769e3c 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.18.0 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow From 43599b7b5e1d8f42c88fd974404fbb9bbb69a21c Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 9 Jan 2026 14:55:44 +0100 Subject: [PATCH 103/118] Rebase to version 4.19.0 Resolves: #2426288 and #2249524 Signed-off-by: Iker Pedrosa --- .gitignore | 2 + ...> shadow-4.19.0-account-tools-setuid.patch | 113 +++++++++--------- shadow-utils.spec | 16 ++- sources | 4 +- 4 files changed, 69 insertions(+), 66 deletions(-) rename shadow-4.18.0-account-tools-setuid.patch => shadow-4.19.0-account-tools-setuid.patch (73%) diff --git a/.gitignore b/.gitignore index f4e82f2..0ceb6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.17.4.tar.xz.asc /shadow-4.18.0.tar.xz /shadow-4.18.0.tar.xz.asc +/shadow-4.19.0.tar.xz +/shadow-4.19.0.tar.xz.asc diff --git a/shadow-4.18.0-account-tools-setuid.patch b/shadow-4.19.0-account-tools-setuid.patch similarity index 73% rename from shadow-4.18.0-account-tools-setuid.patch rename to shadow-4.19.0-account-tools-setuid.patch index 9c018f7..9452582 100644 --- a/shadow-4.18.0-account-tools-setuid.patch +++ b/shadow-4.19.0-account-tools-setuid.patch @@ -1,7 +1,7 @@ -diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1/src/chpasswd.c ---- shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid 2025-06-08 15:58:36.650175673 +0200 -+++ shadow-4.18.0-rc1/src/chpasswd.c 2025-06-09 10:09:17.902939220 +0200 -@@ -448,9 +448,11 @@ int main (int argc, char **argv) +diff -up shadow-4.19.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.19.0-rc1/src/chpasswd.c +--- shadow-4.19.0-rc1/src/chpasswd.c.account-tools-setuid 2025-12-07 16:56:38.563285789 +0100 ++++ shadow-4.19.0-rc1/src/chpasswd.c 2025-12-09 14:54:29.232282499 +0100 +@@ -466,9 +466,11 @@ int main (int argc, char **argv) char *newpwd; const char *salt; @@ -13,7 +13,7 @@ diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1 bool errors = false; intmax_t line = 0; -@@ -474,19 +476,23 @@ int main (int argc, char **argv) +@@ -495,19 +497,23 @@ int main (int argc, char **argv) process_root_flag ("-R", argc, argv); prefix = process_prefix_flag ("-P", argc, argv); @@ -37,7 +37,7 @@ diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1 { is_shadow_pwd = spw_file_present (); -@@ -543,6 +549,7 @@ int main (int argc, char **argv) +@@ -562,6 +568,7 @@ int main (int argc, char **argv) } newpwd = cp; @@ -45,15 +45,15 @@ diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1 #ifdef USE_PAM if (use_pam) { if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { -@@ -553,6 +560,7 @@ int main (int argc, char **argv) +@@ -572,6 +579,7 @@ int main (int argc, char **argv) } } else #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ { - const struct spwd *sp; - struct spwd newsp; -@@ -672,9 +680,11 @@ int main (int argc, char **argv) + + /* +@@ -706,9 +714,11 @@ int main (int argc, char **argv) * password database. */ if (errors) { @@ -65,8 +65,8 @@ diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1 { fprintf (stderr, _("%s: error detected, changes ignored\n"), -@@ -683,9 +693,11 @@ int main (int argc, char **argv) - fail_exit (1); +@@ -717,9 +727,11 @@ int main (int argc, char **argv) + fail_exit (1, process_selinux); } +#ifdef ACCT_TOOLS_SETUID @@ -76,10 +76,10 @@ diff -up shadow-4.18.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.18.0-rc1 +#endif /* ACCT_TOOLS_SETUID */ { /* Save the changes */ - close_files (); -diff -up shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.18.0-rc1/src/groupmems.c ---- shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid 2025-06-08 15:58:36.651250652 +0200 -+++ shadow-4.18.0-rc1/src/groupmems.c 2025-06-09 10:08:59.836763261 +0200 + close_files (&flags); +diff -up shadow-4.19.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.19.0-rc1/src/groupmems.c +--- shadow-4.19.0-rc1/src/groupmems.c.account-tools-setuid 2025-12-07 16:56:38.564285805 +0100 ++++ shadow-4.19.0-rc1/src/groupmems.c 2025-12-09 14:57:23.767054141 +0100 @@ -14,9 +14,11 @@ #include #include @@ -91,17 +91,17 @@ diff -up shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.18.0-rc +#endif /* ACCT_TOOLS_SETUID */ #include - #include "alloc/x/xmalloc.h" -@@ -417,6 +419,7 @@ static void process_flags (int argc, cha - static void check_perms (void) + #include "alloc/malloc.h" +@@ -432,6 +434,7 @@ static void + check_perms(MAYBE_UNUSED bool process_selinux) { if (!list) { +#ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM pam_handle_t *pamh = NULL; int retval; -@@ -450,7 +453,8 @@ static void check_perms (void) - fail_exit (1); +@@ -465,7 +468,8 @@ check_perms(MAYBE_UNUSED bool process_se + fail_exit (1, process_selinux); } (void) pam_end (pamh, retval); -#endif @@ -110,10 +110,10 @@ diff -up shadow-4.18.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.18.0-rc } } -diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1/src/newusers.c ---- shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid 2025-06-08 15:58:36.652250643 +0200 -+++ shadow-4.18.0-rc1/src/newusers.c 2025-06-09 10:08:59.836928828 +0200 -@@ -67,6 +67,7 @@ +diff -up shadow-4.19.0-rc1/src/newusers.c.account-tools-setuid shadow-4.19.0-rc1/src/newusers.c +--- shadow-4.19.0-rc1/src/newusers.c.account-tools-setuid 2025-12-07 16:56:38.565285821 +0100 ++++ shadow-4.19.0-rc1/src/newusers.c 2025-12-09 15:07:40.115500988 +0100 +@@ -74,6 +74,7 @@ struct option_flags { static const char Prog[] = "newusers"; static bool rflg = false; /* create a system account */ @@ -121,7 +121,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM static /*@null@*//*@observer@*/char *crypt_method = NULL; #define cflg (NULL != crypt_method) -@@ -83,6 +84,7 @@ static long bcrypt_rounds = 13; +@@ -90,6 +91,7 @@ static long bcrypt_rounds = 13; static long yescrypt_cost = 5; #endif /* USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -129,7 +129,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 static bool is_shadow; #ifdef SHADOWGRP -@@ -105,9 +107,11 @@ NORETURN static void fail_exit (int); +@@ -112,9 +114,11 @@ NORETURN static void fail_exit (int, boo static int add_group (const char *, const char *, gid_t *, gid_t); static int get_user_id (const char *, uid_t *); static int add_user (const char *, uid_t, gid_t); @@ -139,9 +139,9 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #endif /* !USE_PAM */ +#endif /* !ACCT_TOOLS_SETUID */ static int add_passwd (struct passwd *, const char *); - static void process_flags (int argc, char **argv); + static void process_flags (int argc, char **argv, struct option_flags *flags); static void check_flags (void); -@@ -129,6 +133,7 @@ static void usage (int status) +@@ -136,6 +140,7 @@ static void usage (int status) "Options:\n"), Prog); (void) fputs (_(" -b, --badname allow bad names\n"), usageout); @@ -149,7 +149,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM (void) fprintf (usageout, _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -@@ -144,9 +149,11 @@ static void usage (int status) +@@ -151,9 +156,11 @@ static void usage (int status) #endif ); #endif /* !USE_PAM */ @@ -161,7 +161,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -@@ -154,6 +161,7 @@ static void usage (int status) +@@ -161,6 +168,7 @@ static void usage (int status) usageout); #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -169,7 +169,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 (void) fputs ("\n", usageout); exit (status); -@@ -419,6 +427,7 @@ static int add_user (const char *name, u +@@ -426,6 +434,7 @@ static int add_user (const char *name, u return (pw_update (&pwent) == 0) ? -1 : 0; } @@ -177,7 +177,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM /* * update_passwd - update the password in the passwd entry -@@ -471,6 +480,7 @@ static int update_passwd (struct passwd +@@ -478,6 +487,7 @@ static int update_passwd (struct passwd return 0; } #endif /* !USE_PAM */ @@ -185,7 +185,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 /* * add_passwd - add or update the encrypted password -@@ -479,10 +489,13 @@ static int add_passwd (struct passwd *pw +@@ -487,10 +497,13 @@ add_passwd(struct passwd *pwd, MAYBE_UNU { const struct spwd *sp; struct spwd spent; @@ -199,7 +199,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM void *crypt_arg = NULL; if (NULL != crypt_method) { -@@ -520,13 +533,14 @@ static int add_passwd (struct passwd *pw +@@ -528,13 +541,14 @@ add_passwd(struct passwd *pwd, MAYBE_UNU return update_passwd (pwd, password); } #endif /* USE_PAM */ @@ -215,7 +215,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 if (NULL != sp) { spent = *sp; if ( (NULL != crypt_method) -@@ -563,7 +577,7 @@ static int add_passwd (struct passwd *pw +@@ -571,7 +585,7 @@ add_passwd(struct passwd *pwd, MAYBE_UNU if (!streq(pwd->pw_passwd, "x")) { return update_passwd (pwd, password); } @@ -224,7 +224,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 /* * If there is already a shadow entry, do not touch it. * If there is already a passwd entry with a password, do not -@@ -574,14 +588,14 @@ static int add_passwd (struct passwd *pw +@@ -582,14 +596,14 @@ add_passwd(struct passwd *pwd, MAYBE_UNU || !streq(pwd->pw_passwd, "x")) { return 0; } @@ -241,14 +241,14 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 if ((crypt_method != NULL) && streq(crypt_method, "NONE")) { spent.sp_pwdp = (char *)password; } else { -@@ -626,35 +640,41 @@ static int add_passwd (struct passwd *pw - static void process_flags (int argc, char **argv) +@@ -647,32 +647,38 @@ add_passwd(struct passwd *pwd, MAYBE_UNU + static void process_flags (int argc, char **argv, struct option_flags *flags) { int c; +#ifndef ACCT_TOOLS_SETUID #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - int bad_s; + int bad_s; #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ +#endif /* !ACCT_TOOLS_SETUID */ @@ -277,15 +277,12 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 +#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) "c:bhrs:", - #else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ +-#else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ ++#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ "c:bhr", #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ --#else /* USE_PAM */ -+#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ - "bhr", - #endif - long_options, NULL)) != -1) { -@@ -662,11 +682,13 @@ static void process_flags (int argc, cha + #else /* USE_PAM */ +@@ -670,11 +690,13 @@ static void process_flags (int argc, cha case 'b': allow_bad_names = true; break; @@ -299,15 +296,15 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 case 'h': usage (EXIT_SUCCESS); break; -@@ -675,6 +697,7 @@ static void process_flags (int argc, cha - break; +@@ -684,6 +706,7 @@ static void process_flags (int argc, cha case 'R': /* no-op, handled in process_root_flag () */ + flags->chroot = true; break; +#ifndef ACCT_TOOLS_SETUID #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) case 's': -@@ -714,6 +737,7 @@ static void process_flags (int argc, cha +@@ -723,6 +746,7 @@ static void process_flags (int argc, cha break; #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ #endif /* !USE_PAM */ @@ -315,7 +312,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 default: usage (EXIT_FAILURE); break; -@@ -746,6 +770,7 @@ static void process_flags (int argc, cha +@@ -755,6 +779,7 @@ static void process_flags (int argc, cha */ static void check_flags (void) { @@ -323,7 +320,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 #ifndef USE_PAM #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) if (sflg && !cflg) { -@@ -778,6 +803,7 @@ static void check_flags (void) +@@ -787,6 +812,7 @@ static void check_flags (void) } } #endif /* !USE_PAM */ @@ -331,7 +328,7 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 } /* -@@ -1066,12 +1092,14 @@ int main (int argc, char **argv) +@@ -1065,12 +1091,14 @@ int main (int argc, char **argv) intmax_t line = 0; uid_t uid; gid_t gid; @@ -343,10 +340,10 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 size_t nusers = 0; #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ + struct option_flags flags = {.chroot = false}; + bool process_selinux; - log_set_progname(Prog); - log_set_logfd(stderr); -@@ -1191,6 +1219,7 @@ int main (int argc, char **argv) +@@ -1193,6 +1221,7 @@ int main (int argc, char **argv) } newpw = *pw; @@ -359,10 +356,10 @@ diff -up shadow-4.18.0-rc1/src/newusers.c.account-tools-setuid shadow-4.18.0-rc1 passwords[nusers-1] = xstrdup(fields[1]); #endif /* USE_PAM */ +#endif /* ACCT_TOOLS_SETUID */ - if (add_passwd (&newpw, fields[1]) != 0) { + if (!streq(fields[1], "") && add_passwd(&newpw, fields[1]) != 0) { fprintf (stderr, _("%s: line %jd: can't update password\n"), -@@ -1323,6 +1353,7 @@ int main (int argc, char **argv) +@@ -1321,6 +1351,7 @@ int main (int argc, char **argv) nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); diff --git a/shadow-utils.spec b/shadow-utils.spec index 1769e3c..9aff11f 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.18.0 -Release: 7%{?dist} +Version: 4.19.0 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.18.0/shadow-4.18.0.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.18.0/shadow-4.18.0.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.19.0/shadow-4.19.0.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.19.0/shadow-4.19.0.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -23,7 +23,7 @@ Source7: passwd.pamd # Misc manual page changes - non-upstreamable Patch0: shadow-4.15.0-manfix.patch # Probably non-upstreamable -Patch1: shadow-4.18.0-account-tools-setuid.patch +Patch1: shadow-4.19.0-account-tools-setuid.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -101,7 +101,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.18.0 +%autosetup -p 1 -S git -n shadow-4.19.0 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -269,6 +269,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-1 +- Rebase to version 4.19.0 + Resolves: #2426288 and #2249524 + * Tue Nov 25 2025 Adam Williamson - 2:4.18.0-7 - Also revert changes from -4 (last known good was -3) diff --git a/sources b/sources index 8e3da98..22ae907 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.18.0.tar.xz) = e724670362949ccb570bb300322eb280c28ad609d631072b8db15a5e6eeba9fb9ac5d3df1df270f8b894235e4995b56c0e8f9aadb34d66bb5cea9b7a4f55e6ce -SHA512 (shadow-4.18.0.tar.xz.asc) = bb82b3d54eec0f11ace57609281974b315bba1240eafdae3b6513c7d7dfbcf10c3ae855c74c9eae33539709072046787e4b3e86dfb8bbfbf4bf23446daeb3422 +SHA512 (shadow-4.19.0.tar.xz) = 0846c34f426101213ab6277bbcdc58c28b3a54df2f68d1c1addcc8c5aa79ce3e15d5d8dfcb9cc6dbd1b758e0cd8676c68ca65268f5a037d4c24aa7d358c9a390 +SHA512 (shadow-4.19.0.tar.xz.asc) = 34c1a764d06a5d24533cbb57310de7462eb632c1de904901699d48f44401b1b1f4751db35f2b0e2b9a057cf1a777ccddbae4bc6b19a6db865ebc3e30fde0d060 From 19e27b9aa53dde8f63e79bde6d7a7cdb2725a875 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Fri, 9 Jan 2026 15:01:29 +0100 Subject: [PATCH 104/118] Enable unit-tests Signed-off-by: Iker Pedrosa --- shadow-utils.spec | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 9aff11f..78bf8a9 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.19.0 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -45,6 +45,7 @@ BuildRequires: git BuildRequires: itstool BuildRequires: libacl-devel BuildRequires: libattr-devel +BuildRequires: libcmocka-devel BuildRequires: libeconf-devel BuildRequires: libselinux-devel >= 1.25.2-1 BuildRequires: libsemanage-devel @@ -130,6 +131,9 @@ autoreconf --without-sssd %make_build +%check +make check + %install %make_install gnulocaledir=$RPM_BUILD_ROOT%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/default @@ -269,6 +273,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-2 +- Enable unit-tests + * Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-1 - Rebase to version 4.19.0 Resolves: #2426288 and #2249524 From f47e36e72a473fbb90a92bc73f63042fea7e87df Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 12 Jan 2026 11:42:00 +0100 Subject: [PATCH 105/118] useradd: Support config for creating home dirs as Btrfs subvolumes Signed-off-by: Iker Pedrosa --- shadow-4-19-useradd-support-btrfs.patch | 149 ++++++++++++++++++++++++ shadow-utils.spec | 7 +- 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 shadow-4-19-useradd-support-btrfs.patch diff --git a/shadow-4-19-useradd-support-btrfs.patch b/shadow-4-19-useradd-support-btrfs.patch new file mode 100644 index 0000000..b801289 --- /dev/null +++ b/shadow-4-19-useradd-support-btrfs.patch @@ -0,0 +1,149 @@ +From 3e8c105f0703264e947d8c034b90419794955d49 Mon Sep 17 00:00:00 2001 +From: Hadi Chokr +Date: Fri, 12 Dec 2025 11:18:06 +0100 +Subject: [PATCH] src/useradd: Support config for creating home dirs as Btrfs + subvolumes + +Closes: #1162 + +Co-authored-by: Neal Gompa +Signed-off-by: Hadi Chokr +Signed-off-by: Neal Gompa +Reviewed-by: Alejandro Colomar +--- + man/useradd.8.xml | 27 +++++++++++++++++++++++++++ + src/useradd.c | 24 ++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + +diff --git a/man/useradd.8.xml b/man/useradd.8.xml +index e6db7f6d..c745a620 100644 +--- a/man/useradd.8.xml ++++ b/man/useradd.8.xml +@@ -134,6 +134,33 @@ + + + ++ ++ ++ ++ ++ ++ ++ Create the user's home directory as a Btrfs subvolume. ++ ++ ++ If this option is not specified, ++ useradd will follow the default behavior ++ defined by the variable ++ in /etc/default/useradd. ++ If this variable is not set, the default value is no. ++ ++ ++ When the command-line option ++ is specified, ++ a Btrfs subvolume is created ++ regardless of any configuration file settings. ++ ++ ++ Note: this feature works only if the underlying filesystem supports ++ Btrfs subvolumes. ++ ++ ++ + + + ,  COMMENT +diff --git a/src/useradd.c b/src/useradd.c +index 899efe3c..8433ed8a 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -114,6 +114,7 @@ static const char *def_shell = "/bin/bash"; + static const char *def_template = SKEL_DIR; + static const char *def_usrtemplate = USRSKELDIR; + static const char *def_create_mail_spool = "yes"; ++static const char *def_btrfs_subvolume_home = "no"; + static const char *def_log_init = "yes"; + + static long def_inactive = -1; +@@ -222,6 +223,7 @@ static bool home_added = false; + #define DSKEL "SKEL" + #define DUSRSKEL "USRSKEL" + #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL" ++#define DBTRFS_SUBVOLUME_HOME "BTRFS_SUBVOLUME_HOME" + #define DLOG_INIT "LOG_INIT" + + /* local function prototypes */ +@@ -456,6 +458,7 @@ get_defaults(const struct option_flags *flags) + def_usrtemplate = xstrdup(ccp); + } + } ++ + /* + * Create by default user mail spool or not ? + */ +@@ -466,6 +469,15 @@ get_defaults(const struct option_flags *flags) + def_create_mail_spool = xstrdup(ccp); + } + ++ /* ++ * Create home directories as Btrfs subvolumes by default? ++ */ ++ else if (streq(buf, DBTRFS_SUBVOLUME_HOME)) { ++ if (streq(ccp, "")) ++ ccp = "no"; ++ def_btrfs_subvolume_home = xstrdup(ccp); ++ } ++ + /* + * By default do we add the user to the lastlog and faillog databases ? + */ +@@ -500,6 +512,7 @@ static void show_defaults (void) + printf ("SKEL=%s\n", def_template); + printf ("USRSKEL=%s\n", def_usrtemplate); + printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); ++ printf ("BTRFS_SUBVOLUME_HOME=%s\n", def_btrfs_subvolume_home); + printf ("LOG_INIT=%s\n", def_log_init); + } + +@@ -523,6 +536,7 @@ set_defaults(void) + bool out_skel = false; + bool out_usrskel = false; + bool out_create_mail_spool = false; ++ bool out_btrfs_subvolume_home = false; + bool out_log_init = false; + char buf[1024]; + char *new_file = NULL; +@@ -639,6 +653,11 @@ set_defaults(void) + DCREATE_MAIL_SPOOL "=%s\n", + def_create_mail_spool); + out_create_mail_spool = true; ++ } else if (!out_btrfs_subvolume_home && streq(buf, DBTRFS_SUBVOLUME_HOME)) { ++ fprintf(ofp, ++ DBTRFS_SUBVOLUME_HOME "=%s\n", ++ def_btrfs_subvolume_home); ++ out_btrfs_subvolume_home = true; + } else if (!out_log_init && streq(buf, DLOG_INIT)) { + fprintf(ofp, DLOG_INIT "=%s\n", def_log_init); + out_log_init = true; +@@ -673,6 +692,8 @@ set_defaults(void) + + if (!out_create_mail_spool) + fprintf (ofp, DCREATE_MAIL_SPOOL "=%s\n", def_create_mail_spool); ++ if (!out_btrfs_subvolume_home) ++ fprintf (ofp, DBTRFS_SUBVOLUME_HOME "=%s\n", def_btrfs_subvolume_home); + if (!out_log_init) + fprintf (ofp, DLOG_INIT "=%s\n", def_log_init); + /* +@@ -1431,6 +1452,9 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) + } + } + ++ if (!subvolflg && strcaseeq(def_btrfs_subvolume_home, "yes")) ++ subvolflg = true; ++ + if (!gflg && !Nflg && !Uflg) { + /* Get the settings from login.defs */ + Uflg = getdef_bool ("USERGROUPS_ENAB"); +-- +2.52.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 78bf8a9..f625b8e 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.19.0 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -24,6 +24,8 @@ Source7: passwd.pamd Patch0: shadow-4.15.0-manfix.patch # Probably non-upstreamable Patch1: shadow-4.19.0-account-tools-setuid.patch +# https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 +Patch2: shadow-4-19-useradd-support-btrfs.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -273,6 +275,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Jan 12 2026 Iker Pedrosa - 2:4.19.0-3 +- useradd: Support config for creating home dirs as Btrfs subvolumes + * Fri Jan 9 2026 Iker Pedrosa - 2:4.19.0-2 - Enable unit-tests From c78272db1abeab24ef3676dc669f5752bd571108 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 17 Jan 2026 17:57:49 +0000 Subject: [PATCH 106/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index f625b8e..f58ceee 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.19.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -275,6 +275,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Sat Jan 17 2026 Fedora Release Engineering - 2:4.19.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild + * Mon Jan 12 2026 Iker Pedrosa - 2:4.19.0-3 - useradd: Support config for creating home dirs as Btrfs subvolumes From be2ac1934789e9a3a5ac74f6803ac101ccb16791 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 26 Jan 2026 10:03:00 +0100 Subject: [PATCH 107/118] - chkhash.c: fix support for ! and * in hashes - usermod.c: add back optimizations Signed-off-by: Iker Pedrosa --- shadow-4.19.0-chkhash1.patch | 88 +++++++++++ shadow-4.19.0-chkhash2.patch | 137 ++++++++++++++++++ shadow-4.19.0-usermod-add-optimizations.patch | 75 ++++++++++ shadow-utils.spec | 12 +- 4 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 shadow-4.19.0-chkhash1.patch create mode 100644 shadow-4.19.0-chkhash2.patch create mode 100644 shadow-4.19.0-usermod-add-optimizations.patch diff --git a/shadow-4.19.0-chkhash1.patch b/shadow-4.19.0-chkhash1.patch new file mode 100644 index 0000000..986f10b --- /dev/null +++ b/shadow-4.19.0-chkhash1.patch @@ -0,0 +1,88 @@ +From 87ec7a52ab25dd6e91253c274fd651f16844cf2a Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Wed, 7 Jan 2026 23:39:53 +0100 +Subject: [PATCH 1/2] lib/chkhash.c: is_valid_hash(): Accept a leading '!' + +A leading '!' means that the account is locked. + +Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") +Link: +Link: +Reported-by: Chris Hofstaedtler +Reviewed-by: Chris Hofstaedtler +Cc: vinz +Signed-off-by: Alejandro Colomar +--- + lib/chkhash.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index 66870500..cb45f3aa 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -7,6 +7,8 @@ + #include + #include + ++#include "string/strcmp/strprefix.h" ++ + + /* + * match_regex - return true if match, false if not +@@ -37,6 +39,8 @@ match_regex(const char *pattern, const char *string) + bool + is_valid_hash(const char *hash) + { ++ hash = strprefix(hash, "!") ?: hash; ++ + // Minimum hash length + if (strlen(hash) < 13) + return false; +-- +2.52.0 + + +From ddc2549f87e3001f663d5179e9b6d7fe2e1f3b3f Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Wed, 7 Jan 2026 23:44:26 +0100 +Subject: [PATCH 2/2] lib/chkhash.c: is_valid_hash(): Accept '*' as the hash + +This is widely accepted as an invalid hash, to remove password access +for an account (that is, no passwords will match the "hash"). + +Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") +Closes: +Closes: +Reported-by: Chris Hofstaedtler +Reviewed-by: Chris Hofstaedtler +Cc: vinz +Signed-off-by: Alejandro Colomar +--- + lib/chkhash.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index cb45f3aa..71e0fb4e 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -7,6 +7,7 @@ + #include + #include + ++#include "string/strcmp/streq.h" + #include "string/strcmp/strprefix.h" + + +@@ -41,6 +42,9 @@ is_valid_hash(const char *hash) + { + hash = strprefix(hash, "!") ?: hash; + ++ if (streq(hash, "*")) ++ return true; ++ + // Minimum hash length + if (strlen(hash) < 13) + return false; +-- +2.52.0 + diff --git a/shadow-4.19.0-chkhash2.patch b/shadow-4.19.0-chkhash2.patch new file mode 100644 index 0000000..1742544 --- /dev/null +++ b/shadow-4.19.0-chkhash2.patch @@ -0,0 +1,137 @@ +From 9b67543987e3d140c86f1b8e2b5db5c10d8bc3c5 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 15 Jan 2026 01:11:52 +0100 +Subject: [PATCH 1/4] lib/chkhash.c: is_valid_hash(): Accept an empty hash + +It represents a passwordless account. +That is discouraged, but accepted. + +Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") +Link: +Reported-by: Marc 'Zugschlus' Haber +Reported-by: "Serge E. Hallyn" +Reported-by: Adam Williamson +Co-authored-by: "Serge E. Hallyn" +Signed-off-by: Alejandro Colomar +--- + lib/chkhash.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index 71e0fb4e..d0a8dc01 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -42,6 +42,10 @@ is_valid_hash(const char *hash) + { + hash = strprefix(hash, "!") ?: hash; + ++ // Passwordless account; discouraged ++ if (streq(hash, "")) ++ return true; ++ + if (streq(hash, "*")) + return true; + +-- +2.52.0 + + +From bce404a7a831de911cf20fc8d4c548957f70bc72 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 15 Jan 2026 01:14:46 +0100 +Subject: [PATCH 2/4] lib/chkhash.c: is_valid_hash(): Update comment + +This checks the entire shadow(5) 2nd field, which is more than just +a hash. + +Reported-by: Tobias Stoeckmann +Signed-off-by: Alejandro Colomar +--- + lib/chkhash.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index d0a8dc01..1723f862 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -31,9 +31,7 @@ match_regex(const char *pattern, const char *string) + + + /* +- * is_valid_hash - check if the given string is a valid password hash +- * +- * Returns true if the string appears to be a valid hash, false otherwise. ++ * is_valid_hash - check if the string is a valid shadow(5) 2nd field. + * + * regex from: https://man.archlinux.org/man/crypt.5.en + */ +-- +2.52.0 + + +From 9a86c515a1e7caeeb9e60fa63871170a2dfd98f0 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Thu, 15 Jan 2026 01:24:10 +0100 +Subject: [PATCH 3/4] lib/chkhash.c: is_valid_hash(): Comment meaning of !hash + and * + +Signed-off-by: Alejandro Colomar +--- + lib/chkhash.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index 1723f862..101f2004 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -38,12 +38,14 @@ match_regex(const char *pattern, const char *string) + bool + is_valid_hash(const char *hash) + { ++ // Password temporarily locked + hash = strprefix(hash, "!") ?: hash; + + // Passwordless account; discouraged + if (streq(hash, "")) + return true; + ++ // Password permanently locked (and forgotten) + if (streq(hash, "*")) + return true; + +-- +2.52.0 + + +From 6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Fri, 16 Jan 2026 01:52:32 +0100 +Subject: [PATCH 4/4] man/shadow.5.xml: Document "*" + +Signed-off-by: Alejandro Colomar +--- + man/shadow.5.xml | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/man/shadow.5.xml b/man/shadow.5.xml +index dc7fdfde..d3cc0398 100644 +--- a/man/shadow.5.xml ++++ b/man/shadow.5.xml +@@ -82,8 +82,12 @@ + If the password field begins with an exclamation mark !, + the password is locked. + The remaining characters on the +- line represent the password field before the password was +- locked. ++ line represent the password hash. ++ ++ ++ If the password hash consists of a star *, ++ password access is effectively disallowed; ++ this is because no password can produce a hash like this. + + + Refer to crypt +-- +2.52.0 + diff --git a/shadow-4.19.0-usermod-add-optimizations.patch b/shadow-4.19.0-usermod-add-optimizations.patch new file mode 100644 index 0000000..4a883e6 --- /dev/null +++ b/shadow-4.19.0-usermod-add-optimizations.patch @@ -0,0 +1,75 @@ +From 958b4859991e700b61af2f9e07e3aa87ad1d9218 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Sat, 17 Jan 2026 00:56:21 +0100 +Subject: [PATCH] Revert "src/usermod.c: Remove optimizations" + +This wasn't only an optimization; it also skipped some checks that were +now spuriously triggering errors. We may be able to get rid of the +optimizations, but that will need more analysis. For now, let's revert +to a known-good state. + +Fixes: 6a8a25dc7de6 (2025-10-15; "src/usermod.c: Remove optimizations") +Reverts: 6a8a25dc7de6 (2025-10-15; "src/usermod.c: Remove optimizations") +Closes: +Reported-by: Adam Williamson +Signed-off-by: Alejandro Colomar +--- + src/usermod.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/src/usermod.c b/src/usermod.c +index 7400bf84..7cd7a859 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -1391,6 +1391,48 @@ process_flags(int argc, char **argv, struct option_flags *flags) + } + #endif /* WITH_SELINUX */ + ++ if (user_newid == user_id) { ++ uflg = false; ++ oflg = false; ++ } ++ if (user_newgid == user_gid) { ++ gflg = false; ++ } ++ if ( (NULL != user_newshell) ++ && streq(user_newshell, user_shell)) { ++ sflg = false; ++ } ++ if (streq(user_newname, user_name)) { ++ lflg = false; ++ } ++ if (user_newinactive == user_inactive) { ++ fflg = false; ++ } ++ if (user_newexpire == user_expire) { ++ eflg = false; ++ } ++ if ( (NULL != user_newhome) ++ && streq(user_newhome, user_home)) { ++ dflg = false; ++ mflg = false; ++ } ++ if ( (NULL != user_newcomment) ++ && streq(user_newcomment, user_comment)) { ++ cflg = false; ++ } ++ ++ if (!(Uflg || uflg || sflg || pflg || mflg || Lflg || ++ lflg || Gflg || gflg || fflg || eflg || dflg || cflg ++#ifdef ENABLE_SUBIDS ++ || vflg || Vflg || wflg || Wflg ++#endif /* ENABLE_SUBIDS */ ++#ifdef WITH_SELINUX ++ || Zflg ++#endif /* WITH_SELINUX */ ++ )) { ++ exit (E_SUCCESS); ++ } ++ + if (!is_shadow_pwd && (eflg || fflg)) { + fprintf (stderr, + _("%s: shadow passwords required for -e and -f\n"), +-- +2.52.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index f58ceee..82ea3c4 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.19.0 -Release: 4%{?dist} +Release: 5%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -26,6 +26,12 @@ Patch0: shadow-4.15.0-manfix.patch Patch1: shadow-4.19.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 Patch2: shadow-4-19-useradd-support-btrfs.patch +# https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 +Patch3: shadow-4.19.0-chkhash1.patch +# https://github.com/shadow-maint/shadow/commit/9b67543987e3d140c86f1b8e2b5db5c10d8bc3c5 +Patch4: shadow-4.19.0-chkhash2.patch +# https://github.com/shadow-maint/shadow/commit/958b4859991e700b61af2f9e07e3aa87ad1d9218 +Patch5: shadow-4.19.0-usermod-add-optimizations.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -275,6 +281,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Mon Jan 26 2026 Iker Pedrosa - 2:4.19.0-5 +- chkhash.c: fix support for ! and * in hashes +- usermod.c: add back optimizations + * Sat Jan 17 2026 Fedora Release Engineering - 2:4.19.0-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild From dac50e34f899a79c7dc94ef1a0f76a5af6ffcc8d Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Wed, 28 Jan 2026 11:21:11 -0800 Subject: [PATCH 108/118] chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 regexes Signed-off-by: Adam Williamson --- 1520.patch | 40 ++++++++++++++++++++++++++++++++++++++++ shadow-utils.spec | 10 +++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 1520.patch diff --git a/1520.patch b/1520.patch new file mode 100644 index 0000000..069eebb --- /dev/null +++ b/1520.patch @@ -0,0 +1,40 @@ +From b721cdd03daa3416127289da02fe781efb2562df Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Tue, 27 Jan 2026 15:11:07 -0800 +Subject: [PATCH] lib/chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 + regexes + +`\\n` inside square brackets doesn't include or exclude the +newline character. It includes or excludes a literal slash and +the literal character 'n'. + +Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") +Closes: +Signed-off-by: Adam Williamson +--- + lib/chkhash.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/chkhash.c b/lib/chkhash.c +index 101f2004e8..9123038ade 100644 +--- a/lib/chkhash.c ++++ b/lib/chkhash.c +@@ -62,15 +62,15 @@ is_valid_hash(const char *hash) + return true; + + // SHA-512: $6$ + salt + $ + 86-char hash +- if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash)) ++ if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash)) + return true; + + // SHA-256: $5$ + salt + $ + 43-char hash +- if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash)) ++ if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash)) + return true; + + // MD5: $1$ + salt + $ + 22-char hash +- if (match_regex("^\\$1\\$[^$:\\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash)) ++ if (match_regex("^\\$1\\$[^$:\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash)) + return true; + + // DES: exactly 13 characters from [A-Za-z0-9./] diff --git a/shadow-utils.spec b/shadow-utils.spec index 82ea3c4..de8a156 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.19.0 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -32,6 +32,11 @@ Patch3: shadow-4.19.0-chkhash1.patch Patch4: shadow-4.19.0-chkhash2.patch # https://github.com/shadow-maint/shadow/commit/958b4859991e700b61af2f9e07e3aa87ad1d9218 Patch5: shadow-4.19.0-usermod-add-optimizations.patch +# https://github.com/shadow-maint/shadow/pull/1520 +# Approved by upstream for 4.19.3 this weekend: +# https://github.com/shadow-maint/shadow/issues/1521 +# Fixes the hash check to accept hashes with \ or n in the salt +Patch6: 1520.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -281,6 +286,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Tue Jan 27 2026 Adam Williamson - 2:4.19.0-6 +- chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 regexes + * Mon Jan 26 2026 Iker Pedrosa - 2:4.19.0-5 - chkhash.c: fix support for ! and * in hashes - usermod.c: add back optimizations From cf630b1c3cb7762caef5ffa0ce75446e7a5afb75 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Mon, 19 Jan 2026 14:26:44 +0100 Subject: [PATCH 109/118] Remove unused patches There's no need to do a build just for this. Fallout from 799aaaa5088cde64c65f2897d9c335c52e4de0bc https://src.fedoraproject.org/rpms/shadow-utils/pull-request/25 --- ...3-newidmap-support-passing-pid-as-fd.patch | 441 ------------------ shadow-utils-configure-gshadow.patch | 20 - 2 files changed, 461 deletions(-) delete mode 100644 shadow-4.13-newidmap-support-passing-pid-as-fd.patch delete mode 100644 shadow-utils-configure-gshadow.patch diff --git a/shadow-4.13-newidmap-support-passing-pid-as-fd.patch b/shadow-4.13-newidmap-support-passing-pid-as-fd.patch deleted file mode 100644 index 37e0d41..0000000 --- a/shadow-4.13-newidmap-support-passing-pid-as-fd.patch +++ /dev/null @@ -1,441 +0,0 @@ -From 6974df39a708abf8bafbdfa2b7827e0f70f874cb Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Mon, 6 Feb 2023 22:49:42 -0600 -Subject: [PATCH] newuidmap and newgidmap: support passing pid as fd - -Closes #635 - -newuidmap and newgidmap currently take an integner pid as -the first argument, determining the process id on which to -act. Accept also "fd:N", where N must be an open file -descriptor to the /proc/pid directory for the process to -act upon. This way, if you - -exec 10 ---- - lib/get_pid.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ - lib/prototypes.h | 2 ++ - man/newgidmap.1.xml | 11 ++++++++++ - man/newuidmap.1.xml | 11 ++++++++++ - src/newgidmap.c | 41 ++++++++++++++---------------------- - src/newuidmap.c | 40 +++++++++++++---------------------- - 6 files changed, 106 insertions(+), 50 deletions(-) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index 10184bf0..ab91d158 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -10,6 +10,9 @@ - - #include "prototypes.h" - #include "defines.h" -+#include -+#include -+#include - - int get_pid (const char *pidstr, pid_t *pid) - { -@@ -29,3 +32,51 @@ int get_pid (const char *pidstr, pid_t *pid) - return 1; - } - -+/* -+ * If use passed in fd:4 as an argument, then return the -+ * value '4', the fd to use. -+ */ -+int get_pidfd_from_fd(const char *pidfdstr) -+{ -+ long long int val; -+ char *endptr; -+ -+ errno = 0; -+ val = strtoll (pidfdstr, &endptr, 10); -+ if ( ('\0' == *pidfdstr) -+ || ('\0' != *endptr) -+ || (ERANGE == errno) -+ || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { -+ return 0; -+ } -+ -+ return (int)val; -+} -+ -+int open_pidfd(const char *pidstr) -+{ -+ int proc_dir_fd; -+ int written; -+ char proc_dir_name[32]; -+ pid_t target; -+ -+ if (get_pid(pidstr, &target) == 0) -+ return -ENOENT; -+ -+ /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -+ written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -+ target); -+ if ((written <= 0) || ((size_t)written >= sizeof(proc_dir_name))) { -+ fprintf(stderr, "snprintf of proc path failed for %u: %s\n", -+ target, strerror(errno)); -+ return -EINVAL; -+ } -+ -+ proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -+ if (proc_dir_fd < 0) { -+ fprintf(stderr, _("Could not open proc directory for target %u: %s\n"), -+ target, strerror(errno)); -+ return -EINVAL; -+ } -+ return proc_dir_fd; -+} -diff --git a/lib/prototypes.h b/lib/prototypes.h -index 400d5b97..21df6f61 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -160,6 +160,8 @@ extern int getlong (const char *numstr, /*@out@*/long int *result); - - /* get_pid.c */ - extern int get_pid (const char *pidstr, pid_t *pid); -+extern int get_pidfd_from_fd(const char *pidfdstr); -+extern int open_pidfd(const char *pidstr); - - /* getrange */ - extern int getrange (const char *range, -diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml -index e4ebc69e..9b7683eb 100644 ---- a/man/newgidmap.1.xml -+++ b/man/newgidmap.1.xml -@@ -116,6 +116,17 @@ - - Note that newgidmap may be used only once for a given process. - -+ -+ Instead of an integer process id, the first argument may be -+ specified as fd:N, where the integer N -+ is the file descriptor number for the calling process's opened -+ file for /proc/[pid[. In this case, -+ newgidmap will use -+ openat2 -+ to open the gid_map file under that -+ directory, avoiding a TOCTTOU in case the process exits and -+ the pid is immediately reused. -+ - - - -diff --git a/man/newuidmap.1.xml b/man/newuidmap.1.xml -index f5cb5b48..ca917a77 100644 ---- a/man/newuidmap.1.xml -+++ b/man/newuidmap.1.xml -@@ -116,6 +116,17 @@ - - Note that newuidmap may be used only once for a given process. - -+ -+ Instead of an integer process id, the first argument may be -+ specified as fd:N, where the integer N -+ is the file descriptor number for the calling process's opened -+ file for /proc/[pid[. In this case, -+ newuidmap will use -+ openat2 -+ to open the uid_map file under that -+ directory, avoiding a TOCTTOU in case the process exits and -+ the pid is immediately reused. -+ - - - -diff --git a/src/newgidmap.c b/src/newgidmap.c -index 01d0fe90..d6d29725 100644 ---- a/src/newgidmap.c -+++ b/src/newgidmap.c -@@ -69,7 +69,7 @@ static void verify_ranges(struct passwd *pw, int ranges, - - static void usage(void) - { -- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); -+ fprintf(stderr, _("usage: %s [] [ ] ... \n"), Prog); - exit(EXIT_FAILURE); - } - -@@ -143,15 +143,12 @@ out: - */ - int main(int argc, char **argv) - { -- char proc_dir_name[32]; - char *target_str; -- pid_t target; - int proc_dir_fd; - int ranges; - struct map_range *mappings; - struct stat st; - struct passwd *pw; -- int written; - bool allow_setgroups = false; - - Prog = Basename (argv[0]); -@@ -168,25 +165,19 @@ int main(int argc, char **argv) - /* Find the process that needs its user namespace - * gid mapping set. - */ -- target_str = argv[1]; -- if (!get_pid(target_str, &target)) -- usage(); - -- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -- target); -- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { -- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", -- Prog, strerror(errno)); -- } -- -- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -- if (proc_dir_fd < 0) { -- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), -- Prog, target); -- return EXIT_FAILURE; -+ target_str = argv[1]; -+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { -+ /* the user passed in a /proc/pid fd for the process */ -+ target_str = &target_str[3]; -+ proc_dir_fd = get_pidfd_from_fd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); -+ } else { -+ proc_dir_fd = open_pidfd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); - } -- - /* Who am i? */ - pw = get_my_pwent (); - if (NULL == pw) { -@@ -200,8 +191,8 @@ int main(int argc, char **argv) - - /* Get the effective uid and effective gid of the target process */ - if (fstat(proc_dir_fd, &st) < 0) { -- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), -- Prog, target); -+ fprintf(stderr, _("%s: Could not stat directory for process\n"), -+ Prog); - return EXIT_FAILURE; - } - -@@ -213,8 +204,8 @@ int main(int argc, char **argv) - (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || - (pw->pw_uid != st.st_uid) || - (getgid() != st.st_gid)) { -- fprintf(stderr, _( "%s: Target %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -- Prog, target, -+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -+ Prog, - (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, - (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); - return EXIT_FAILURE; -diff --git a/src/newuidmap.c b/src/newuidmap.c -index e8798409..e99655c9 100644 ---- a/src/newuidmap.c -+++ b/src/newuidmap.c -@@ -64,7 +64,7 @@ static void verify_ranges(struct passwd *pw, int ranges, - - static void usage(void) - { -- fprintf(stderr, _("usage: %s [ ] ... \n"), Prog); -+ fprintf(stderr, _("usage: %s [|fd:] [ ] ... \n"), Prog); - exit(EXIT_FAILURE); - } - -@@ -73,15 +73,12 @@ static void usage(void) - */ - int main(int argc, char **argv) - { -- char proc_dir_name[32]; - char *target_str; -- pid_t target; - int proc_dir_fd; - int ranges; - struct map_range *mappings; - struct stat st; - struct passwd *pw; -- int written; - - Prog = Basename (argv[0]); - log_set_progname(Prog); -@@ -94,26 +91,20 @@ int main(int argc, char **argv) - if (argc < 2) - usage(); - -+ target_str = argv[1]; - /* Find the process that needs its user namespace - * uid mapping set. - */ -- target_str = argv[1]; -- if (!get_pid(target_str, &target)) -- usage(); -- -- /* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */ -- written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/", -- target); -- if ((written <= 0) || (written >= sizeof(proc_dir_name))) { -- fprintf(stderr, "%s: snprintf of proc path failed: %s\n", -- Prog, strerror(errno)); -- } -- -- proc_dir_fd = open(proc_dir_name, O_DIRECTORY); -- if (proc_dir_fd < 0) { -- fprintf(stderr, _("%s: Could not open proc directory for target %u\n"), -- Prog, target); -- return EXIT_FAILURE; -+ if (strlen(target_str) > 3 && strncmp(target_str, "fd:", 3) == 0) { -+ /* the user passed in a /proc/pid fd for the process */ -+ target_str = &target_str[3]; -+ proc_dir_fd = get_pidfd_from_fd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); -+ } else { -+ proc_dir_fd = open_pidfd(target_str); -+ if (proc_dir_fd < 0) -+ usage(); - } - - /* Who am i? */ -@@ -129,8 +120,7 @@ int main(int argc, char **argv) - - /* Get the effective uid and effective gid of the target process */ - if (fstat(proc_dir_fd, &st) < 0) { -- fprintf(stderr, _("%s: Could not stat directory for target %u\n"), -- Prog, target); -+ fprintf(stderr, _("%s: Could not stat directory for target process\n"), Prog); - return EXIT_FAILURE; - } - -@@ -142,8 +132,8 @@ int main(int argc, char **argv) - (!getdef_bool("GRANT_AUX_GROUP_SUBIDS") && (getgid() != pw->pw_gid)) || - (pw->pw_uid != st.st_uid) || - (getgid() != st.st_gid)) { -- fprintf(stderr, _( "%s: Target process %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -- Prog, target, -+ fprintf(stderr, _( "%s: Target process is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ), -+ Prog, - (unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid, - (unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid); - return EXIT_FAILURE; --- -2.39.2 - -From 7ff33fae6f9cd79c0e012671c37a172e9a681d0b Mon Sep 17 00:00:00 2001 -From: Serge Hallyn -Date: Fri, 24 Feb 2023 13:52:32 -0600 -Subject: [PATCH] get_pidfd_from_fd: return -1 on error, not 0 - -Fixes: 6974df39a: newuidmap and newgidmap: support passing pid as fd -Signed-off-by: Serge Hallyn ---- - lib/get_pid.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index ab91d158..5b6d9da4 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -35,6 +35,7 @@ int get_pid (const char *pidstr, pid_t *pid) - /* - * If use passed in fd:4 as an argument, then return the - * value '4', the fd to use. -+ * On error, return -1. - */ - int get_pidfd_from_fd(const char *pidfdstr) - { -@@ -47,7 +48,7 @@ int get_pidfd_from_fd(const char *pidfdstr) - || ('\0' != *endptr) - || (ERANGE == errno) - || (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) { -- return 0; -+ return -1; - } - - return (int)val; --- -2.39.2 - -From 05e2adf509ba0e3779dae66a276b86927a8e1e0e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Vin=C3=ADcius=20dos=20Santos=20Oliveira?= - -Date: Fri, 24 Feb 2023 18:06:02 -0300 -Subject: [PATCH] Validate fds created by the user - -write_mapping() will do the following: - -openat(proc_dir_fd, map_file, O_WRONLY); - -An attacker could create a directory containing a symlink named -"uid_map" pointing to any file owned by root, and thus allow him to -overwrite any root-owned file. ---- - lib/get_pid.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/lib/get_pid.c b/lib/get_pid.c -index 5b6d9da4..8e5e6014 100644 ---- a/lib/get_pid.c -+++ b/lib/get_pid.c -@@ -41,6 +41,8 @@ int get_pidfd_from_fd(const char *pidfdstr) - { - long long int val; - char *endptr; -+ struct stat st; -+ dev_t proc_st_dev, proc_st_rdev; - - errno = 0; - val = strtoll (pidfdstr, &endptr, 10); -@@ -51,6 +53,21 @@ int get_pidfd_from_fd(const char *pidfdstr) - return -1; - } - -+ if (stat("/proc/self/uid_map", &st) < 0) { -+ return -1; -+ } -+ -+ proc_st_dev = st.st_dev; -+ proc_st_rdev = st.st_rdev; -+ -+ if (fstat(val, &st) < 0) { -+ return -1; -+ } -+ -+ if (st.st_dev != proc_st_dev || st.st_rdev != proc_st_rdev) { -+ return -1; -+ } -+ - return (int)val; - } - --- -2.39.2 - diff --git a/shadow-utils-configure-gshadow.patch b/shadow-utils-configure-gshadow.patch deleted file mode 100644 index a983ce0..0000000 --- a/shadow-utils-configure-gshadow.patch +++ /dev/null @@ -1,20 +0,0 @@ -The missing #include causes the configure check to fail -spuriously, resulting in HAVE_SHADOWGRP not being defined. - -Submitted upstream: - -diff --git a/configure.ac b/configure.ac -index 924254a0c8171802..6c7d9839979e037d 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -116,6 +116,10 @@ if test "$ac_cv_header_shadow_h" = "yes"; then - ac_cv_libc_shadowgrp, - AC_RUN_IFELSE([AC_LANG_SOURCE([ - #include -+ #ifdef HAVE_GSHADOW_H -+ #include -+ #endif -+ int - main() - { - struct sgrp *sg = sgetsgent("test:x::"); From a85675911953dc0d1a9ecd8c606ea06e73903c22 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Thu, 22 Jan 2026 15:25:57 +0100 Subject: [PATCH 110/118] Silence mixed-use-of-spaces-and-tabs There's no need to do a build just for this. Fallout from 4642a65eb4963253b1abd952aa727fcbb238df53 and fe4f9dc5c0ad3270c280392bb574748f7c49bf81 https://src.fedoraproject.org/rpms/shadow-utils/pull-request/25 --- shadow-utils.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index de8a156..ec8df78 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -126,9 +126,9 @@ cp -a %{SOURCE6} man/login.defs.d/HOME_MODE.xml %build autoreconf %configure \ - --disable-account-tools-setuid \ - --enable-logind=no \ - --enable-man \ + --disable-account-tools-setuid \ + --enable-logind=no \ + --enable-man \ --enable-shadowgrp \ --enable-shared \ --with-audit \ @@ -140,7 +140,7 @@ autoreconf --with-yescrypt \ --without-libbsd \ --without-libcrack \ - --without-nscd \ + --without-nscd \ --without-sssd %make_build From 77fbaa4e9a6b97735947d575ade3f167fad09b59 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Thu, 22 Jan 2026 15:21:36 +0100 Subject: [PATCH 111/118] Rebase to version 4.19.3 Resolves: #2426288 https://src.fedoraproject.org/rpms/shadow-utils/pull-request/27 --- .gitignore | 4 + 1520.patch | 40 --------- shadow-4.19.0-chkhash1.patch | 88 ------------------- shadow-4.19.0-usermod-add-optimizations.patch | 75 ---------------- ...hash2.patch => shadow-4.19.3-chkhash.patch | 65 ++++---------- shadow-utils.spec | 27 +++--- sources | 4 +- 7 files changed, 32 insertions(+), 271 deletions(-) delete mode 100644 1520.patch delete mode 100644 shadow-4.19.0-chkhash1.patch delete mode 100644 shadow-4.19.0-usermod-add-optimizations.patch rename shadow-4.19.0-chkhash2.patch => shadow-4.19.3-chkhash.patch (59%) diff --git a/.gitignore b/.gitignore index 0ceb6c8..7db552e 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,7 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.18.0.tar.xz.asc /shadow-4.19.0.tar.xz /shadow-4.19.0.tar.xz.asc +/shadow-4.19.2.tar.xz +/shadow-4.19.2.tar.xz.asc +/shadow-4.19.3.tar.xz +/shadow-4.19.3.tar.xz.asc diff --git a/1520.patch b/1520.patch deleted file mode 100644 index 069eebb..0000000 --- a/1520.patch +++ /dev/null @@ -1,40 +0,0 @@ -From b721cdd03daa3416127289da02fe781efb2562df Mon Sep 17 00:00:00 2001 -From: Adam Williamson -Date: Tue, 27 Jan 2026 15:11:07 -0800 -Subject: [PATCH] lib/chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 - regexes - -`\\n` inside square brackets doesn't include or exclude the -newline character. It includes or excludes a literal slash and -the literal character 'n'. - -Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") -Closes: -Signed-off-by: Adam Williamson ---- - lib/chkhash.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index 101f2004e8..9123038ade 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -62,15 +62,15 @@ is_valid_hash(const char *hash) - return true; - - // SHA-512: $6$ + salt + $ + 86-char hash -- if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash)) -+ if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash)) - return true; - - // SHA-256: $5$ + salt + $ + 43-char hash -- if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash)) -+ if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash)) - return true; - - // MD5: $1$ + salt + $ + 22-char hash -- if (match_regex("^\\$1\\$[^$:\\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash)) -+ if (match_regex("^\\$1\\$[^$:\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash)) - return true; - - // DES: exactly 13 characters from [A-Za-z0-9./] diff --git a/shadow-4.19.0-chkhash1.patch b/shadow-4.19.0-chkhash1.patch deleted file mode 100644 index 986f10b..0000000 --- a/shadow-4.19.0-chkhash1.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 87ec7a52ab25dd6e91253c274fd651f16844cf2a Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Wed, 7 Jan 2026 23:39:53 +0100 -Subject: [PATCH 1/2] lib/chkhash.c: is_valid_hash(): Accept a leading '!' - -A leading '!' means that the account is locked. - -Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") -Link: -Link: -Reported-by: Chris Hofstaedtler -Reviewed-by: Chris Hofstaedtler -Cc: vinz -Signed-off-by: Alejandro Colomar ---- - lib/chkhash.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index 66870500..cb45f3aa 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -7,6 +7,8 @@ - #include - #include - -+#include "string/strcmp/strprefix.h" -+ - - /* - * match_regex - return true if match, false if not -@@ -37,6 +39,8 @@ match_regex(const char *pattern, const char *string) - bool - is_valid_hash(const char *hash) - { -+ hash = strprefix(hash, "!") ?: hash; -+ - // Minimum hash length - if (strlen(hash) < 13) - return false; --- -2.52.0 - - -From ddc2549f87e3001f663d5179e9b6d7fe2e1f3b3f Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Wed, 7 Jan 2026 23:44:26 +0100 -Subject: [PATCH 2/2] lib/chkhash.c: is_valid_hash(): Accept '*' as the hash - -This is widely accepted as an invalid hash, to remove password access -for an account (that is, no passwords will match the "hash"). - -Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") -Closes: -Closes: -Reported-by: Chris Hofstaedtler -Reviewed-by: Chris Hofstaedtler -Cc: vinz -Signed-off-by: Alejandro Colomar ---- - lib/chkhash.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index cb45f3aa..71e0fb4e 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -7,6 +7,7 @@ - #include - #include - -+#include "string/strcmp/streq.h" - #include "string/strcmp/strprefix.h" - - -@@ -41,6 +42,9 @@ is_valid_hash(const char *hash) - { - hash = strprefix(hash, "!") ?: hash; - -+ if (streq(hash, "*")) -+ return true; -+ - // Minimum hash length - if (strlen(hash) < 13) - return false; --- -2.52.0 - diff --git a/shadow-4.19.0-usermod-add-optimizations.patch b/shadow-4.19.0-usermod-add-optimizations.patch deleted file mode 100644 index 4a883e6..0000000 --- a/shadow-4.19.0-usermod-add-optimizations.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 958b4859991e700b61af2f9e07e3aa87ad1d9218 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Sat, 17 Jan 2026 00:56:21 +0100 -Subject: [PATCH] Revert "src/usermod.c: Remove optimizations" - -This wasn't only an optimization; it also skipped some checks that were -now spuriously triggering errors. We may be able to get rid of the -optimizations, but that will need more analysis. For now, let's revert -to a known-good state. - -Fixes: 6a8a25dc7de6 (2025-10-15; "src/usermod.c: Remove optimizations") -Reverts: 6a8a25dc7de6 (2025-10-15; "src/usermod.c: Remove optimizations") -Closes: -Reported-by: Adam Williamson -Signed-off-by: Alejandro Colomar ---- - src/usermod.c | 42 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - -diff --git a/src/usermod.c b/src/usermod.c -index 7400bf84..7cd7a859 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -1391,6 +1391,48 @@ process_flags(int argc, char **argv, struct option_flags *flags) - } - #endif /* WITH_SELINUX */ - -+ if (user_newid == user_id) { -+ uflg = false; -+ oflg = false; -+ } -+ if (user_newgid == user_gid) { -+ gflg = false; -+ } -+ if ( (NULL != user_newshell) -+ && streq(user_newshell, user_shell)) { -+ sflg = false; -+ } -+ if (streq(user_newname, user_name)) { -+ lflg = false; -+ } -+ if (user_newinactive == user_inactive) { -+ fflg = false; -+ } -+ if (user_newexpire == user_expire) { -+ eflg = false; -+ } -+ if ( (NULL != user_newhome) -+ && streq(user_newhome, user_home)) { -+ dflg = false; -+ mflg = false; -+ } -+ if ( (NULL != user_newcomment) -+ && streq(user_newcomment, user_comment)) { -+ cflg = false; -+ } -+ -+ if (!(Uflg || uflg || sflg || pflg || mflg || Lflg || -+ lflg || Gflg || gflg || fflg || eflg || dflg || cflg -+#ifdef ENABLE_SUBIDS -+ || vflg || Vflg || wflg || Wflg -+#endif /* ENABLE_SUBIDS */ -+#ifdef WITH_SELINUX -+ || Zflg -+#endif /* WITH_SELINUX */ -+ )) { -+ exit (E_SUCCESS); -+ } -+ - if (!is_shadow_pwd && (eflg || fflg)) { - fprintf (stderr, - _("%s: shadow passwords required for -e and -f\n"), --- -2.52.0 - diff --git a/shadow-4.19.0-chkhash2.patch b/shadow-4.19.3-chkhash.patch similarity index 59% rename from shadow-4.19.0-chkhash2.patch rename to shadow-4.19.3-chkhash.patch index 1742544..6dfc159 100644 --- a/shadow-4.19.0-chkhash2.patch +++ b/shadow-4.19.3-chkhash.patch @@ -1,57 +1,20 @@ -From 9b67543987e3d140c86f1b8e2b5db5c10d8bc3c5 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 15 Jan 2026 01:11:52 +0100 -Subject: [PATCH 1/4] lib/chkhash.c: is_valid_hash(): Accept an empty hash - -It represents a passwordless account. -That is discouraged, but accepted. - -Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e") -Link: -Reported-by: Marc 'Zugschlus' Haber -Reported-by: "Serge E. Hallyn" -Reported-by: Adam Williamson -Co-authored-by: "Serge E. Hallyn" -Signed-off-by: Alejandro Colomar ---- - lib/chkhash.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index 71e0fb4e..d0a8dc01 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -42,6 +42,10 @@ is_valid_hash(const char *hash) - { - hash = strprefix(hash, "!") ?: hash; - -+ // Passwordless account; discouraged -+ if (streq(hash, "")) -+ return true; -+ - if (streq(hash, "*")) - return true; - --- -2.52.0 - - -From bce404a7a831de911cf20fc8d4c548957f70bc72 Mon Sep 17 00:00:00 2001 +From 4b2e669441438a6ae91c82a24c796894aa6a53b2 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 15 Jan 2026 01:14:46 +0100 -Subject: [PATCH 2/4] lib/chkhash.c: is_valid_hash(): Update comment +Subject: [PATCH 1/3] lib/chkhash.c: is_valid_hash(): Update comment This checks the entire shadow(5) 2nd field, which is more than just a hash. Reported-by: Tobias Stoeckmann Signed-off-by: Alejandro Colomar +(cherry picked from commit bce404a7a831de911cf20fc8d4c548957f70bc72) --- lib/chkhash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/chkhash.c b/lib/chkhash.c -index d0a8dc01..1723f862 100644 +index 348dfe7478f8..48aaa417e9a9 100644 --- a/lib/chkhash.c +++ b/lib/chkhash.c @@ -31,9 +31,7 @@ match_regex(const char *pattern, const char *string) @@ -66,22 +29,23 @@ index d0a8dc01..1723f862 100644 * regex from: https://man.archlinux.org/man/crypt.5.en */ -- -2.52.0 +2.53.0 -From 9a86c515a1e7caeeb9e60fa63871170a2dfd98f0 Mon Sep 17 00:00:00 2001 +From b72386978e0c994c5efc91d548da68a8d97088ab Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 15 Jan 2026 01:24:10 +0100 -Subject: [PATCH 3/4] lib/chkhash.c: is_valid_hash(): Comment meaning of !hash +Subject: [PATCH 2/3] lib/chkhash.c: is_valid_hash(): Comment meaning of !hash and * Signed-off-by: Alejandro Colomar +(cherry picked from commit 9a86c515a1e7caeeb9e60fa63871170a2dfd98f0) --- lib/chkhash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/chkhash.c b/lib/chkhash.c -index 1723f862..101f2004 100644 +index 48aaa417e9a9..9123038adef0 100644 --- a/lib/chkhash.c +++ b/lib/chkhash.c @@ -38,12 +38,14 @@ match_regex(const char *pattern, const char *string) @@ -100,21 +64,22 @@ index 1723f862..101f2004 100644 return true; -- -2.52.0 +2.53.0 -From 6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c Mon Sep 17 00:00:00 2001 +From 4486e3e0f8b74e6af27b5dcb4114fd776afdd605 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 16 Jan 2026 01:52:32 +0100 -Subject: [PATCH 4/4] man/shadow.5.xml: Document "*" +Subject: [PATCH 3/3] man/shadow.5.xml: Document "*" Signed-off-by: Alejandro Colomar +(cherry picked from commit 6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c) --- man/shadow.5.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/man/shadow.5.xml b/man/shadow.5.xml -index dc7fdfde..d3cc0398 100644 +index dc7fdfde542f..d3cc03982c47 100644 --- a/man/shadow.5.xml +++ b/man/shadow.5.xml @@ -82,8 +82,12 @@ @@ -133,5 +98,5 @@ index dc7fdfde..d3cc0398 100644 Refer to crypt -- -2.52.0 +2.53.0 diff --git a/shadow-utils.spec b/shadow-utils.spec index ec8df78..426f19b 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.19.0 -Release: 6%{?dist} +Version: 4.19.3 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.19.0/shadow-4.19.0.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.19.0/shadow-4.19.0.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.19.3/shadow-4.19.3.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.19.3/shadow-4.19.3.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -26,17 +26,8 @@ Patch0: shadow-4.15.0-manfix.patch Patch1: shadow-4.19.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 Patch2: shadow-4-19-useradd-support-btrfs.patch -# https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 -Patch3: shadow-4.19.0-chkhash1.patch -# https://github.com/shadow-maint/shadow/commit/9b67543987e3d140c86f1b8e2b5db5c10d8bc3c5 -Patch4: shadow-4.19.0-chkhash2.patch -# https://github.com/shadow-maint/shadow/commit/958b4859991e700b61af2f9e07e3aa87ad1d9218 -Patch5: shadow-4.19.0-usermod-add-optimizations.patch -# https://github.com/shadow-maint/shadow/pull/1520 -# Approved by upstream for 4.19.3 this weekend: -# https://github.com/shadow-maint/shadow/issues/1521 -# Fixes the hash check to accept hashes with \ or n in the salt -Patch6: 1520.patch +# https://github.com/shadow-maint/shadow/commit/6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c +Patch3: shadow-4.19.3-chkhash.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -115,7 +106,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.19.0 +%autosetup -p 1 -S git -n shadow-4.19.3 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -286,6 +277,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Feb 11 2026 Debarshi Ray - 2:4.19.3-1 +- Rebase to version 4.19.3 + Resolves: #2426288 + * Tue Jan 27 2026 Adam Williamson - 2:4.19.0-6 - chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 regexes diff --git a/sources b/sources index 22ae907..d12859f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.19.0.tar.xz) = 0846c34f426101213ab6277bbcdc58c28b3a54df2f68d1c1addcc8c5aa79ce3e15d5d8dfcb9cc6dbd1b758e0cd8676c68ca65268f5a037d4c24aa7d358c9a390 -SHA512 (shadow-4.19.0.tar.xz.asc) = 34c1a764d06a5d24533cbb57310de7462eb632c1de904901699d48f44401b1b1f4751db35f2b0e2b9a057cf1a777ccddbae4bc6b19a6db865ebc3e30fde0d060 +SHA512 (shadow-4.19.3.tar.xz) = f2b41f8186681eb98dae0da87ed1a1f03327c5005c9d4bf9500801352e318de6f5954dc5b8f30ab9aece728b1efb74b4ff8fb2720acc4c2aaef701331a4a5a05 +SHA512 (shadow-4.19.3.tar.xz.asc) = 295a6bffefd333a9ea84fa59b368f5c48d0ac5224199624b768087098110b0f0c19bef37f5c474c45277980758dcb6728e8bb17eb7ab1a57603cad41f1dd00ab From 0fba1e26ce07e5cb003b594266f8b34fdb3477f6 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 23 Apr 2026 15:20:03 +0200 Subject: [PATCH 112/118] btrfs: simplify checks improve useradd behavior for non-btrfs Signed-off-by: Iker Pedrosa --- shadow-4.19.3-useradd-fix-btrfs.patch | 492 ++++++++++++++++++++++++++ shadow-utils.spec | 7 +- 2 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 shadow-4.19.3-useradd-fix-btrfs.patch diff --git a/shadow-4.19.3-useradd-fix-btrfs.patch b/shadow-4.19.3-useradd-fix-btrfs.patch new file mode 100644 index 0000000..47671d9 --- /dev/null +++ b/shadow-4.19.3-useradd-fix-btrfs.patch @@ -0,0 +1,492 @@ +From 4079070c4b8ced8df9d86366ad113fc3c2e4e49c Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Wed, 22 Apr 2026 11:02:36 +0200 +Subject: [PATCH 1/5] lib/btrfs.c: btrfs_is_subvolume(): Simplify error check + +Signed-off-by: Alejandro Colomar +--- + lib/btrfs.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/lib/btrfs.c b/lib/btrfs.c +index 85ec7dbc..fe20cf30 100644 +--- a/lib/btrfs.c ++++ b/lib/btrfs.c +@@ -67,8 +67,7 @@ int btrfs_is_subvolume(const char *path) + if (ret <= 0) + return ret; + +- ret = stat(path, &st); +- if (ret == -1) ++ if (stat(path, &st) == -1) + return -1; + + if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) { +-- +2.53.0 + + +From 7a4faaaf46314547cc5e6c8264c3a11753ef9352 Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Wed, 22 Apr 2026 11:14:20 +0200 +Subject: [PATCH 2/5] lib/, src/: Move statfs(2) call out of is_btrfs() + +This simplifies the return value of is_btrfs() into a boolean. + +Signed-off-by: Alejandro Colomar +--- + lib/btrfs.c | 25 +++++++++---------------- + lib/prototypes.h | 3 ++- + src/useradd.c | 11 +++++++++-- + 3 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/lib/btrfs.c b/lib/btrfs.c +index fe20cf30..065c7938 100644 +--- a/lib/btrfs.c ++++ b/lib/btrfs.c +@@ -60,12 +60,13 @@ int btrfs_remove_subvolume(const char *path) + */ + int btrfs_is_subvolume(const char *path) + { +- struct stat st; +- int ret; ++ struct stat st; ++ struct statfs sfs; + +- ret = is_btrfs(path); +- if (ret <= 0) +- return ret; ++ if (statfs(path, &sfs) == -1) ++ return -1; ++ if (!is_btrfs(&sfs)) ++ return 0; + + if (stat(path, &st) == -1) + return -1; +@@ -78,16 +79,8 @@ int btrfs_is_subvolume(const char *path) + } + + +-/* Adapted from btrfsprogs */ +-int is_btrfs(const char *path) ++bool ++is_btrfs(const struct statfs *sfs) + { +- struct statfs sfs; +- int ret; +- +- ret = statfs(path, &sfs); +- if (ret == -1) +- return -1; +- +- return sfs.f_type == BTRFS_SUPER_MAGIC; ++ return sfs->f_type == BTRFS_SUPER_MAGIC; + } +- +diff --git a/lib/prototypes.h b/lib/prototypes.h +index 9a03e312..42aa2923 100644 +--- a/lib/prototypes.h ++++ b/lib/prototypes.h +@@ -23,6 +23,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -54,7 +55,7 @@ extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); + extern int btrfs_create_subvolume(const char *path); + extern int btrfs_remove_subvolume(const char *path); + extern int btrfs_is_subvolume(const char *path); +-extern int is_btrfs(const char *path); ++extern bool is_btrfs(const struct statfs *sfs); + #endif + + /* basename() renamed to Basename() to avoid libc name space confusion */ +diff --git a/src/useradd.c b/src/useradd.c +index df679d28..5ce6cd6a 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2265,6 +2266,7 @@ static void create_home(const struct option_flags *flags) + #if WITH_BTRFS + if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) { + char *btrfs_check = strdup(path); ++ struct statfs sfs; + + if (!btrfs_check) { + fprintf(stderr, +@@ -2273,13 +2275,18 @@ static void create_home(const struct option_flags *flags) + fail_exit(E_HOMEDIR, process_selinux); + } + stpcpy(&btrfs_check[strlen(path) - strlen(cp) - 1], ""); +- if (is_btrfs(btrfs_check) <= 0) { ++ if (statfs(btrfs_check, &sfs) == -1) { ++ fprintf(stderr, "%s: statfs(\"%s\"): %s\n", ++ Prog, btrfs_check, strerrno()); ++ fail_exit(E_HOMEDIR, process_selinux); ++ } ++ free(btrfs_check); ++ if (!is_btrfs(&sfs)) { + fprintf(stderr, + _("%s: home directory \"%s\" must be mounted on BTRFS\n"), + Prog, path); + fail_exit(E_HOMEDIR, process_selinux); + } +- free(btrfs_check); + // make subvolume to mount for user instead of directory + if (btrfs_create_subvolume(path)) { + fprintf(stderr, +-- +2.53.0 + + +From 96460c7240264c0022cebc9ba1774993ee2594cf Mon Sep 17 00:00:00 2001 +From: Alejandro Colomar +Date: Wed, 22 Apr 2026 11:21:14 +0200 +Subject: [PATCH 3/5] lib/, src/: Move btrfs.c prototypes to lib/btrfs.h + +Signed-off-by: Alejandro Colomar +--- + lib/Makefile.am | 2 +- + lib/btrfs.c | 4 ++++ + lib/btrfs.h | 23 +++++++++++++++++++++++ + lib/prototypes.h | 9 --------- + src/useradd.c | 1 + + src/userdel.c | 1 + + src/usermod.c | 1 + + 7 files changed, 31 insertions(+), 10 deletions(-) + create mode 100644 lib/btrfs.h + +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 7c488f82..0664e610 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -290,7 +290,7 @@ libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h + endif + + if WITH_BTRFS +-libshadow_la_SOURCES += btrfs.c ++libshadow_la_SOURCES += btrfs.c btrfs.h + endif + + if ENABLE_LASTLOG +diff --git a/lib/btrfs.c b/lib/btrfs.c +index 065c7938..15b6b315 100644 +--- a/lib/btrfs.c ++++ b/lib/btrfs.c +@@ -1,3 +1,7 @@ ++#include "config.h" ++ ++#include "btrfs.h" ++ + #include + #include + #include +diff --git a/lib/btrfs.h b/lib/btrfs.h +new file mode 100644 +index 00000000..50b70488 +--- /dev/null ++++ b/lib/btrfs.h +@@ -0,0 +1,23 @@ ++// SPDX-FileCopyrightText: 2026, Alejandro Colomar ++// SPDX-License-Identifier: BSD-3-Clause ++ ++ ++#ifndef SHADOW_INCLUDE_LIB_BTRFS_H_ ++#define SHADOW_INCLUDE_LIB_BTRFS_H_ ++ ++ ++#include "config.h" ++ ++#include ++#include ++ ++ ++#ifdef WITH_BTRFS ++int btrfs_create_subvolume(const char *path); ++int btrfs_remove_subvolume(const char *path); ++int btrfs_is_subvolume(const char *path); ++bool is_btrfs(const struct statfs *sfs); ++#endif ++ ++ ++#endif // include guard +diff --git a/lib/prototypes.h b/lib/prototypes.h +index 42aa2923..d22c477a 100644 +--- a/lib/prototypes.h ++++ b/lib/prototypes.h +@@ -23,7 +23,6 @@ + + #include + #include +-#include + #include + #include + #include +@@ -50,14 +49,6 @@ extern int expire (const struct passwd *, /*@null@*/const struct spwd *); + /* isexpired.c */ + extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); + +-/* btrfs.c */ +-#ifdef WITH_BTRFS +-extern int btrfs_create_subvolume(const char *path); +-extern int btrfs_remove_subvolume(const char *path); +-extern int btrfs_is_subvolume(const char *path); +-extern bool is_btrfs(const struct statfs *sfs); +-#endif +- + /* basename() renamed to Basename() to avoid libc name space confusion */ + /* basename.c */ + extern /*@observer@*/const char *Basename (const char *str); +diff --git a/src/useradd.c b/src/useradd.c +index 5ce6cd6a..9bd32b11 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -34,6 +34,7 @@ + #include "alloc/malloc.h" + #include "atoi/a2i.h" + #include "atoi/getnum.h" ++#include "btrfs.h" + #include "chkname.h" + #include "defines.h" + #include "faillog.h" +diff --git a/src/userdel.c b/src/userdel.c +index 9b7d81be..ebd064c0 100644 +--- a/src/userdel.c ++++ b/src/userdel.c +@@ -20,6 +20,7 @@ + #include + #include + ++#include "btrfs.h" + #ifdef ACCT_TOOLS_SETUID + #ifdef USE_PAM + #include "pam_defs.h" +diff --git a/src/usermod.c b/src/usermod.c +index 7c0321a6..3afe19ea 100644 +--- a/src/usermod.c ++++ b/src/usermod.c +@@ -32,6 +32,7 @@ + #include "alloc/malloc.h" + #include "atoi/a2i.h" + #include "atoi/getnum.h" ++#include "btrfs.h" + #include "chkname.h" + #include "defines.h" + #include "faillog.h" +-- +2.53.0 + + +From 7be9a6540f1cad477fd4f4e83d25904a5095bb86 Mon Sep 17 00:00:00 2001 +From: Hadi Chokr +Date: Tue, 21 Apr 2026 09:18:19 +0200 +Subject: [PATCH 4/5] useradd(8): fallback to regular dir for BTRFS home on + non-BTRFS parent + +When the --btrfs-subvolume-home option is used but the parent directory +is not on a BTRFS filesystem, useradd previously failed with an error. +This is too strict; instead, fall back to creating a regular directory +and issue a warning. The subvolume creation is attempted only when the +parent is BTRFS. Otherwise, a regular directory is created and a +syslog(3) warning is logged. + +Fixes: 3e8c105 (2026-01-02; "src/useradd: Support config for creating home dirs as Btrfs subvolumes") +Co-authored-by: Hadi Chokr +Co-authored-by: Alejandro Colomar +Signed-off-by: Alejandro Colomar +--- + man/useradd.8.xml | 27 ++++++++++++++++++++++-- + src/useradd.c | 52 +++++++++++++++++++++++------------------------ + 2 files changed, 51 insertions(+), 28 deletions(-) + +diff --git a/man/useradd.8.xml b/man/useradd.8.xml +index 8a087e13..0bde6683 100644 +--- a/man/useradd.8.xml ++++ b/man/useradd.8.xml +@@ -2,6 +2,7 @@ + + + +- Note: this feature works only if the underlying filesystem supports +- Btrfs subvolumes. ++ If the parent directory of the user's home directory is ++ not on a Btrfs filesystem, ++ useradd will not create a ++ subvolume. ++ Instead, it creates a regular directory, ++ prints a warning to standard error, ++ and logs the event via syslog at level ++ LOG_WARN. ++ The user account is still created successfully. ++ ++ ++ If the filesystem type cannot be determined (e.g., because of ++ insufficient permissions, an I/O error, ++ or a ++ ++ statfs ++ 2 ++ ++ failure), ++ useradd treats this as a fatal error: ++ the home directory is not created, ++ the command exits with a non‑zero status ++ (E_HOMEDIR, 12), ++ and an error message is printed. + + + +diff --git a/src/useradd.c b/src/useradd.c +index 9bd32b11..9210379c 100644 +--- a/src/useradd.c ++++ b/src/useradd.c +@@ -1,11 +1,11 @@ +-/* +- * SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh +- * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz +- * SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko +- * SPDX-FileCopyrightText: 2007 - 2012, Nicolas François +- * +- * SPDX-License-Identifier: BSD-3-Clause +- */ ++// SPDX-FileCopyrightText: 1991-1994, Julianne Frances Haugh ++// SPDX-FileCopyrightText: 1996-2000, Marek Michałkiewicz ++// SPDX-FileCopyrightText: 2000-2006, Tomasz Kłoczko ++// SPDX-FileCopyrightText: 2007-2012, Nicolas François ++// SPDX-FileCopyrightText: 2025-2026, Hadi Chokr ++// SPDX-FileCopyrightText: 2026, Alejandro Colomar ++// SPDX-License-Identifier: BSD-3-Clause ++ + + #include "config.h" + +@@ -2251,6 +2251,8 @@ static void create_home(const struct option_flags *flags) + owner root:root. + */ + for (cp = strtok(bhome, "/"); cp != NULL; cp = strtok(NULL, "/")) { ++ bool dir_created; ++ + /* Avoid turning a relative path into an absolute path. */ + if (strprefix(bhome, "/") || !streq(path, "")) + strcat(path, "/"); +@@ -2260,10 +2262,7 @@ static void create_home(const struct option_flags *flags) + continue; + } + +- /* Check if parent directory is BTRFS, fail if requesting +- subvolume but no BTRFS. The paths could be different by the +- trailing slash +- */ ++ dir_created = false; + #if WITH_BTRFS + if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) { + char *btrfs_check = strdup(path); +@@ -2284,25 +2283,26 @@ static void create_home(const struct option_flags *flags) + free(btrfs_check); + if (!is_btrfs(&sfs)) { + fprintf(stderr, +- _("%s: home directory \"%s\" must be mounted on BTRFS\n"), +- Prog, path); +- fail_exit(E_HOMEDIR, process_selinux); ++ _("%s: warning: \"%s\" is not on BTRFS; creating regular directory instead of subvolume\n"), ++ Prog, prefix_user_home); ++ } else { ++ if (btrfs_create_subvolume(path)) { ++ fprintf(stderr, ++ _("%s: failed to create BTRFS subvolume: %s\n"), ++ Prog, path); ++ fail_exit(E_HOMEDIR, process_selinux); ++ } ++ dir_created = true; + } +- // make subvolume to mount for user instead of directory +- if (btrfs_create_subvolume(path)) { +- fprintf(stderr, +- _("%s: failed to create BTRFS subvolume: %s\n"), ++ } ++#endif ++ if (!dir_created) { ++ if (mkdir(path, 0) != 0) { ++ fprintf(stderr, _("%s: cannot create directory %s\n"), + Prog, path); + fail_exit(E_HOMEDIR, process_selinux); + } + } +- else +-#endif +- if (mkdir(path, 0) != 0) { +- fprintf(stderr, _("%s: cannot create directory %s\n"), +- Prog, path); +- fail_exit(E_HOMEDIR, process_selinux); +- } + if (chown(path, 0, 0) < 0) { + fprintf(stderr, + _("%s: warning: chown on `%s' failed: %m\n"), +-- +2.53.0 + + +From 827f69b864461ab6d7549762bef06ab4495d2587 Mon Sep 17 00:00:00 2001 +From: Hadi Chokr +Date: Mon, 20 Apr 2026 12:27:31 +0200 +Subject: [PATCH 5/5] man/useradd.8.xml: Remove trailing spaces from + useradd.8.xml + +Signed-off-by: Hadi Chokr +Reviewed-by: Alejandro Colomar +--- + man/useradd.8.xml | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/man/useradd.8.xml b/man/useradd.8.xml +index 0bde6683..f85780e2 100644 +--- a/man/useradd.8.xml ++++ b/man/useradd.8.xml +@@ -207,7 +207,7 @@ + user's login directory. The default is to append the + LOGIN name to + BASE_DIR and use that as the +- login directory name. ++ login directory name. + The directory HOME_DIR is not created by + default. However it will be created for non-system users if either the + flag is specifed or +@@ -422,7 +422,7 @@ + + + +- Create the user's home directory if it does not exist. ++ Create the user's home directory if it does not exist. + The files and directories contained in the skeleton directory + (which can be defined with the option) + will be copied to the home directory. +@@ -512,7 +512,7 @@ + password himself. + + +- Note:Avoid this option on the command ++ Note:Avoid this option on the command + line because the password (or encrypted password) will + be visible by users listing the processes. + +-- +2.53.0 + diff --git a/shadow-utils.spec b/shadow-utils.spec index 426f19b..d381c31 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.19.3 -Release: 1%{?dist} +Release: 2%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -28,6 +28,8 @@ Patch1: shadow-4.19.0-account-tools-setuid.patch Patch2: shadow-4-19-useradd-support-btrfs.patch # https://github.com/shadow-maint/shadow/commit/6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c Patch3: shadow-4.19.3-chkhash.patch +# https://github.com/shadow-maint/shadow/commit/827f69b864461ab6d7549762bef06ab4495d2587 +Patch4: shadow-4.19.3-useradd-fix-btrfs.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -277,6 +279,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Thu Apr 23 2026 Iker Pedrosa - 2:4.19.3-2 +- btrfs: simplify checks improve useradd behavior for non-btrfs + * Wed Feb 11 2026 Debarshi Ray - 2:4.19.3-1 - Rebase to version 4.19.3 Resolves: #2426288 From 4a56d06039633e31494bf759e96673dd632925a7 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 14 Apr 2026 16:25:41 +0200 Subject: [PATCH 113/118] Tests: run system tests Tests comprehensive functionality from shadow using the upstream system test suite in testing farm. - Add plans/system-tests.fmf: run upstream shadow system tests via pytest-mh. - Add tests/mhc-fedora-ci.yaml: topology configuration to connect to the test system. - Add .fmf/version: enable testing farm integration. Signed-off-by: Iker Pedrosa --- .fmf/version | 1 + plans/tier0-functional.fmf | 48 ++++++++++++++++++++++++++++++++++++++ tests/mhc-fedora-ci.yaml | 13 +++++++++++ 3 files changed, 62 insertions(+) create mode 100644 .fmf/version create mode 100644 plans/tier0-functional.fmf create mode 100644 tests/mhc-fedora-ci.yaml diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/plans/tier0-functional.fmf b/plans/tier0-functional.fmf new file mode 100644 index 0000000..7fb6f9c --- /dev/null +++ b/plans/tier0-functional.fmf @@ -0,0 +1,48 @@ +summary: Tier 0 functional tests for shadow-utils +description: | + Run comprehensive system tests for shadow-utils. These tests validate user and group + account management functionality by testing actual system operations including user + creation, password management, group operations, and verification of system files + (i.e. /etc/passwd, /etc/shadow). + +provision: + how: virtual + image: fedora + +prepare: + - name: Install general dependencies + how: install + package: + - expect + - git + - python3-pip + + - name: Setup SSH keys for localhost testing + how: shell + script: + - ssh-keygen -t rsa -f /root/.ssh/id_rsa -N "" -q + - cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys + - chmod 600 /root/.ssh/authorized_keys + - ssh-keyscan -H localhost >> /root/.ssh/known_hosts + + - name: Clone shadow repository + how: shell + script: + - git clone https://github.com/shadow-maint/shadow.git /tmp/shadow-test + + - name: Copy test topology for Fedora CI + how: shell + script: + - cp tests/mhc-fedora-ci.yaml /tmp/shadow-test/tests/system + + - name: Install test dependencies + how: shell + script: + - pip3 install -r /tmp/shadow-test/tests/system/requirements.txt + +execute: + how: tmt + duration: 30m + script: | + cd /tmp/shadow-test/tests/system + pytest --mh-config=mhc-fedora-ci.yaml --mh-lazy-ssh -v diff --git a/tests/mhc-fedora-ci.yaml b/tests/mhc-fedora-ci.yaml new file mode 100644 index 0000000..8747e67 --- /dev/null +++ b/tests/mhc-fedora-ci.yaml @@ -0,0 +1,13 @@ +provisioned_topologies: +- shadow +domains: +- id: shadow + hosts: + - hostname: localhost + role: shadow + conn: + type: ssh + host: localhost + user: root + artifacts: + - /var/log/* From 871df3223d7cf041a69d1b19bb9d1fdf4d3220b9 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 27 May 2026 11:40:27 +0200 Subject: [PATCH 114/118] Enable use of PAM for chpasswd and newusers Resolves: #2461179 and #2283963 Signed-off-by: Iker Pedrosa --- shadow-4.19.0-account-tools-setuid.patch | 377 ----------------------- shadow-utils.spec | 14 +- 2 files changed, 9 insertions(+), 382 deletions(-) delete mode 100644 shadow-4.19.0-account-tools-setuid.patch diff --git a/shadow-4.19.0-account-tools-setuid.patch b/shadow-4.19.0-account-tools-setuid.patch deleted file mode 100644 index 9452582..0000000 --- a/shadow-4.19.0-account-tools-setuid.patch +++ /dev/null @@ -1,377 +0,0 @@ -diff -up shadow-4.19.0-rc1/src/chpasswd.c.account-tools-setuid shadow-4.19.0-rc1/src/chpasswd.c ---- shadow-4.19.0-rc1/src/chpasswd.c.account-tools-setuid 2025-12-07 16:56:38.563285789 +0100 -+++ shadow-4.19.0-rc1/src/chpasswd.c 2025-12-09 14:54:29.232282499 +0100 -@@ -466,9 +466,11 @@ int main (int argc, char **argv) - char *newpwd; - const char *salt; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - bool use_pam = true; - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - bool errors = false; - intmax_t line = 0; -@@ -495,19 +497,23 @@ int main (int argc, char **argv) - process_root_flag ("-R", argc, argv); - prefix = process_prefix_flag ("-P", argc, argv); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (md5flg || eflg || cflg || prefix[0]) { - use_pam = false; - } - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - OPENLOG (Prog); - - check_perms (); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - is_shadow_pwd = spw_file_present (); - -@@ -562,6 +568,7 @@ int main (int argc, char **argv) - } - newpwd = cp; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (use_pam) { - if (do_pam_passwd_non_interactive (Prog, name, newpwd) != 0) { -@@ -572,6 +579,7 @@ int main (int argc, char **argv) - } - } else - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - - /* -@@ -706,9 +714,11 @@ int main (int argc, char **argv) - * password database. - */ - if (errors) { -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - fprintf (stderr, - _("%s: error detected, changes ignored\n"), -@@ -717,9 +727,11 @@ int main (int argc, char **argv) - fail_exit (1, process_selinux); - } - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - if (!use_pam) - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - { - /* Save the changes */ - close_files (&flags); -diff -up shadow-4.19.0-rc1/src/groupmems.c.account-tools-setuid shadow-4.19.0-rc1/src/groupmems.c ---- shadow-4.19.0-rc1/src/groupmems.c.account-tools-setuid 2025-12-07 16:56:38.564285805 +0100 -+++ shadow-4.19.0-rc1/src/groupmems.c 2025-12-09 14:57:23.767054141 +0100 -@@ -14,9 +14,11 @@ - #include - #include - #include -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - #include "pam_defs.h" - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - #include - - #include "alloc/malloc.h" -@@ -432,6 +434,7 @@ static void - check_perms(MAYBE_UNUSED bool process_selinux) - { - if (!list) { -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - pam_handle_t *pamh = NULL; - int retval; -@@ -465,7 +468,8 @@ check_perms(MAYBE_UNUSED bool process_se - fail_exit (1, process_selinux); - } - (void) pam_end (pamh, retval); --#endif -+#endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - } - } - -diff -up shadow-4.19.0-rc1/src/newusers.c.account-tools-setuid shadow-4.19.0-rc1/src/newusers.c ---- shadow-4.19.0-rc1/src/newusers.c.account-tools-setuid 2025-12-07 16:56:38.565285821 +0100 -+++ shadow-4.19.0-rc1/src/newusers.c 2025-12-09 15:07:40.115500988 +0100 -@@ -74,6 +74,7 @@ struct option_flags { - static const char Prog[] = "newusers"; - - static bool rflg = false; /* create a system account */ -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - static /*@null@*//*@observer@*/char *crypt_method = NULL; - #define cflg (NULL != crypt_method) -@@ -90,6 +91,7 @@ static long bcrypt_rounds = 13; - static long yescrypt_cost = 5; - #endif /* USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - static bool is_shadow; - #ifdef SHADOWGRP -@@ -112,9 +114,11 @@ NORETURN static void fail_exit (int, boo - static int add_group (const char *, const char *, gid_t *, gid_t); - static int get_user_id (const char *, uid_t *); - static int add_user (const char *, uid_t, gid_t); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - static int update_passwd (struct passwd *, const char *); - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - static int add_passwd (struct passwd *, const char *); - static void process_flags (int argc, char **argv, struct option_flags *flags); - static void check_flags (void); -@@ -136,6 +140,7 @@ static void usage (int status) - "Options:\n"), - Prog); - (void) fputs (_(" -b, --badname allow bad names\n"), usageout); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - (void) fprintf (usageout, - _(" -c, --crypt-method METHOD the crypt method (one of %s)\n"), -@@ -151,9 +156,11 @@ static void usage (int status) - #endif - ); - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); - (void) fputs (_(" -r, --system create system accounts\n"), usageout); - (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA, BCRYPT\n" -@@ -161,6 +168,7 @@ static void usage (int status) - usageout); - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - (void) fputs ("\n", usageout); - - exit (status); -@@ -426,6 +434,7 @@ static int add_user (const char *name, u - return (pw_update (&pwent) == 0) ? -1 : 0; - } - -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - /* - * update_passwd - update the password in the passwd entry -@@ -478,6 +487,7 @@ static int update_passwd (struct passwd - return 0; - } - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - /* - * add_passwd - add or update the encrypted password -@@ -487,10 +497,13 @@ add_passwd(struct passwd *pwd, MAYBE_UNU - { - const struct spwd *sp; - struct spwd spent; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - char *cp; - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - void *crypt_arg = NULL; - if (NULL != crypt_method) { -@@ -528,13 +541,14 @@ add_passwd(struct passwd *pwd, MAYBE_UNU - return update_passwd (pwd, password); - } - #endif /* USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - - /* - * Do the first and easiest shadow file case. The user already - * exists in the shadow password file. - */ - sp = spw_locate (pwd->pw_name); --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - if (NULL != sp) { - spent = *sp; - if ( (NULL != crypt_method) -@@ -571,7 +585,7 @@ add_passwd(struct passwd *pwd, MAYBE_UNU - if (!streq(pwd->pw_passwd, "x")) { - return update_passwd (pwd, password); - } --#else /* USE_PAM */ -+#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ - /* - * If there is already a shadow entry, do not touch it. - * If there is already a passwd entry with a password, do not -@@ -582,14 +596,14 @@ add_passwd(struct passwd *pwd, MAYBE_UNU - || !streq(pwd->pw_passwd, "x")) { - return 0; - } --#endif /* USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID && !USE_PAM */ - - /* - * Now the really hard case - I need to create an entirely new - * shadow password file entry. - */ - spent.sp_namp = pwd->pw_name; --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - if ((crypt_method != NULL) && streq(crypt_method, "NONE")) { - spent.sp_pwdp = (char *)password; - } else { -@@ -647,32 +647,38 @@ add_passwd(struct passwd *pwd, MAYBE_UNU - static void process_flags (int argc, char **argv, struct option_flags *flags) - { - int c; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - int bad_s; - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - static struct option long_options[] = { - {"badname", no_argument, NULL, 'b'}, -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - {"crypt-method", required_argument, NULL, 'c'}, - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - {"help", no_argument, NULL, 'h'}, - {"system", no_argument, NULL, 'r'}, - {"root", required_argument, NULL, 'R'}, -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - {"sha-rounds", required_argument, NULL, 's'}, - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - {NULL, 0, NULL, '\0'} - }; - - while ((c = getopt_long (argc, argv, --#ifndef USE_PAM -+#if !defined(ACCT_TOOLS_SETUID) && !defined(USE_PAM) - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - "c:bhrs:", --#else /* !USE_SHA_CRYPT && !USE_BCRYPT && !USE_YESCRYPT */ -+#else /* !ACCT_TOOLS_SETUID && !USE_PAM */ - "c:bhr", - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #else /* USE_PAM */ -@@ -670,11 +690,13 @@ static void process_flags (int argc, cha - case 'b': - allow_bad_names = true; - break; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - case 'c': - crypt_method = optarg; - break; - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - case 'h': - usage (EXIT_SUCCESS); - break; -@@ -684,6 +706,7 @@ static void process_flags (int argc, cha - case 'R': /* no-op, handled in process_root_flag () */ - flags->chroot = true; - break; -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - case 's': -@@ -723,6 +746,7 @@ static void process_flags (int argc, cha - break; - #endif /* USE_SHA_CRYPT || USE_BCRYPT || USE_YESCRYPT */ - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - default: - usage (EXIT_FAILURE); - break; -@@ -755,6 +779,7 @@ static void process_flags (int argc, cha - */ - static void check_flags (void) - { -+#ifndef ACCT_TOOLS_SETUID - #ifndef USE_PAM - #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_YESCRYPT) - if (sflg && !cflg) { -@@ -787,6 +812,7 @@ static void check_flags (void) - } - } - #endif /* !USE_PAM */ -+#endif /* !ACCT_TOOLS_SETUID */ - } - - /* -@@ -1065,12 +1091,14 @@ int main (int argc, char **argv) - intmax_t line = 0; - uid_t uid; - gid_t gid; -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - intmax_t *lines = NULL; - char **usernames = NULL; - char **passwords = NULL; - size_t nusers = 0; - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - struct option_flags flags = {.chroot = false}; - bool process_selinux; - -@@ -1193,6 +1221,7 @@ int main (int argc, char **argv) - } - newpw = *pw; - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - /* keep the list of user/password for later update by PAM */ - nusers++; -@@ -1207,6 +1236,7 @@ int main (int argc, char **argv) - usernames[nusers-1] = xstrdup(fields[0]); - passwords[nusers-1] = xstrdup(fields[1]); - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - if (!streq(fields[1], "") && add_passwd(&newpw, fields[1]) != 0) { - fprintf (stderr, - _("%s: line %jd: can't update password\n"), -@@ -1321,6 +1351,7 @@ int main (int argc, char **argv) - nscd_flush_cache ("group"); - sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); - -+#ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - /* Now update the passwords using PAM */ - for (size_t i = 0; i < nusers; i++) { -@@ -1334,6 +1365,7 @@ int main (int argc, char **argv) - } - } - #endif /* USE_PAM */ -+#endif /* ACCT_TOOLS_SETUID */ - - exit (EXIT_SUCCESS); - } diff --git a/shadow-utils.spec b/shadow-utils.spec index d381c31..11243dd 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.19.3 -Release: 2%{?dist} +Release: 3%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -22,8 +22,6 @@ Source7: passwd.pamd ### Patches ### # Misc manual page changes - non-upstreamable Patch0: shadow-4.15.0-manfix.patch -# Probably non-upstreamable -Patch1: shadow-4.19.0-account-tools-setuid.patch # https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 Patch2: shadow-4-19-useradd-support-btrfs.patch # https://github.com/shadow-maint/shadow/commit/6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c @@ -146,6 +144,8 @@ install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/default install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/login.defs install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/default/useradd install -d -m 755 $RPM_BUILD_ROOT%{_pam_confdir} +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/chpasswd +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/newusers install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pam_confdir}/passwd @@ -194,11 +194,9 @@ rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* # Remove PAM service files we don't use. rm $RPM_BUILD_ROOT%{_pam_confdir}/chfn -rm $RPM_BUILD_ROOT%{_pam_confdir}/chpasswd rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh rm $RPM_BUILD_ROOT%{_pam_confdir}/groupmems rm $RPM_BUILD_ROOT%{_pam_confdir}/login -rm $RPM_BUILD_ROOT%{_pam_confdir}/newusers rm $RPM_BUILD_ROOT%{_pam_confdir}/su find $RPM_BUILD_ROOT%{_mandir} -depth -type d -empty -delete @@ -225,6 +223,8 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %license gpl-2.0.txt shadow-bsd.txt %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/login.defs %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/default/useradd +%config(noreplace) %{_pam_confdir}/chpasswd +%config(noreplace) %{_pam_confdir}/newusers %config(noreplace) %{_pam_confdir}/passwd %{_bindir}/sg %attr(4755,root,root) %{_bindir}/chage @@ -279,6 +279,10 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed May 27 2026 Iker Pedrosa - 2:4.19.3-3 +- Enable use of PAM for chpasswd and newusers + Resolves: #2461179 and #2283963 + * Thu Apr 23 2026 Iker Pedrosa - 2:4.19.3-2 - btrfs: simplify checks improve useradd behavior for non-btrfs From 8bd71d9f9156a632eb3850c1b2658fc21959f892 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 17 Jul 2026 06:27:57 +0000 Subject: [PATCH 115/118] Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild --- shadow-utils.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shadow-utils.spec b/shadow-utils.spec index 11243dd..4f94261 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.19.3 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow @@ -279,6 +279,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Fri Jul 17 2026 Fedora Release Engineering - 2:4.19.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild + * Wed May 27 2026 Iker Pedrosa - 2:4.19.3-3 - Enable use of PAM for chpasswd and newusers Resolves: #2461179 and #2283963 From 8cb145bd7377a26dae190cc3b7ea46a293ac0a45 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Thu, 2 Jul 2026 16:26:11 +0200 Subject: [PATCH 116/118] Rebase to v4.20.0-rc3 Signed-off-by: Iker Pedrosa --- .gitignore | 4 + shadow-4-19-useradd-support-btrfs.patch | 149 ------- shadow-4.15.0-manfix.patch | 162 -------- shadow-4.19.3-chkhash.patch | 102 ----- shadow-4.19.3-useradd-fix-btrfs.patch | 492 ------------------------ shadow-utils.spec | 28 +- sources | 4 +- 7 files changed, 14 insertions(+), 927 deletions(-) delete mode 100644 shadow-4-19-useradd-support-btrfs.patch delete mode 100644 shadow-4.15.0-manfix.patch delete mode 100644 shadow-4.19.3-chkhash.patch delete mode 100644 shadow-4.19.3-useradd-fix-btrfs.patch diff --git a/.gitignore b/.gitignore index 7db552e..13adb8c 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,7 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.19.2.tar.xz.asc /shadow-4.19.3.tar.xz /shadow-4.19.3.tar.xz.asc +/shadow-4.20.0-rc2.tar.xz +/shadow-4.20.0-rc2.tar.xz.asc +/shadow-4.20.0-rc3.tar.xz +/shadow-4.20.0-rc3.tar.xz.asc diff --git a/shadow-4-19-useradd-support-btrfs.patch b/shadow-4-19-useradd-support-btrfs.patch deleted file mode 100644 index b801289..0000000 --- a/shadow-4-19-useradd-support-btrfs.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 3e8c105f0703264e947d8c034b90419794955d49 Mon Sep 17 00:00:00 2001 -From: Hadi Chokr -Date: Fri, 12 Dec 2025 11:18:06 +0100 -Subject: [PATCH] src/useradd: Support config for creating home dirs as Btrfs - subvolumes - -Closes: #1162 - -Co-authored-by: Neal Gompa -Signed-off-by: Hadi Chokr -Signed-off-by: Neal Gompa -Reviewed-by: Alejandro Colomar ---- - man/useradd.8.xml | 27 +++++++++++++++++++++++++++ - src/useradd.c | 24 ++++++++++++++++++++++++ - 2 files changed, 51 insertions(+) - -diff --git a/man/useradd.8.xml b/man/useradd.8.xml -index e6db7f6d..c745a620 100644 ---- a/man/useradd.8.xml -+++ b/man/useradd.8.xml -@@ -134,6 +134,33 @@ - - - -+ -+ -+ -+ -+ -+ -+ Create the user's home directory as a Btrfs subvolume. -+ -+ -+ If this option is not specified, -+ useradd will follow the default behavior -+ defined by the variable -+ in /etc/default/useradd. -+ If this variable is not set, the default value is no. -+ -+ -+ When the command-line option -+ is specified, -+ a Btrfs subvolume is created -+ regardless of any configuration file settings. -+ -+ -+ Note: this feature works only if the underlying filesystem supports -+ Btrfs subvolumes. -+ -+ -+ - - - ,  COMMENT -diff --git a/src/useradd.c b/src/useradd.c -index 899efe3c..8433ed8a 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -114,6 +114,7 @@ static const char *def_shell = "/bin/bash"; - static const char *def_template = SKEL_DIR; - static const char *def_usrtemplate = USRSKELDIR; - static const char *def_create_mail_spool = "yes"; -+static const char *def_btrfs_subvolume_home = "no"; - static const char *def_log_init = "yes"; - - static long def_inactive = -1; -@@ -222,6 +223,7 @@ static bool home_added = false; - #define DSKEL "SKEL" - #define DUSRSKEL "USRSKEL" - #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL" -+#define DBTRFS_SUBVOLUME_HOME "BTRFS_SUBVOLUME_HOME" - #define DLOG_INIT "LOG_INIT" - - /* local function prototypes */ -@@ -456,6 +458,7 @@ get_defaults(const struct option_flags *flags) - def_usrtemplate = xstrdup(ccp); - } - } -+ - /* - * Create by default user mail spool or not ? - */ -@@ -466,6 +469,15 @@ get_defaults(const struct option_flags *flags) - def_create_mail_spool = xstrdup(ccp); - } - -+ /* -+ * Create home directories as Btrfs subvolumes by default? -+ */ -+ else if (streq(buf, DBTRFS_SUBVOLUME_HOME)) { -+ if (streq(ccp, "")) -+ ccp = "no"; -+ def_btrfs_subvolume_home = xstrdup(ccp); -+ } -+ - /* - * By default do we add the user to the lastlog and faillog databases ? - */ -@@ -500,6 +512,7 @@ static void show_defaults (void) - printf ("SKEL=%s\n", def_template); - printf ("USRSKEL=%s\n", def_usrtemplate); - printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); -+ printf ("BTRFS_SUBVOLUME_HOME=%s\n", def_btrfs_subvolume_home); - printf ("LOG_INIT=%s\n", def_log_init); - } - -@@ -523,6 +536,7 @@ set_defaults(void) - bool out_skel = false; - bool out_usrskel = false; - bool out_create_mail_spool = false; -+ bool out_btrfs_subvolume_home = false; - bool out_log_init = false; - char buf[1024]; - char *new_file = NULL; -@@ -639,6 +653,11 @@ set_defaults(void) - DCREATE_MAIL_SPOOL "=%s\n", - def_create_mail_spool); - out_create_mail_spool = true; -+ } else if (!out_btrfs_subvolume_home && streq(buf, DBTRFS_SUBVOLUME_HOME)) { -+ fprintf(ofp, -+ DBTRFS_SUBVOLUME_HOME "=%s\n", -+ def_btrfs_subvolume_home); -+ out_btrfs_subvolume_home = true; - } else if (!out_log_init && streq(buf, DLOG_INIT)) { - fprintf(ofp, DLOG_INIT "=%s\n", def_log_init); - out_log_init = true; -@@ -673,6 +692,8 @@ set_defaults(void) - - if (!out_create_mail_spool) - fprintf (ofp, DCREATE_MAIL_SPOOL "=%s\n", def_create_mail_spool); -+ if (!out_btrfs_subvolume_home) -+ fprintf (ofp, DBTRFS_SUBVOLUME_HOME "=%s\n", def_btrfs_subvolume_home); - if (!out_log_init) - fprintf (ofp, DLOG_INIT "=%s\n", def_log_init); - /* -@@ -1431,6 +1452,9 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) - } - } - -+ if (!subvolflg && strcaseeq(def_btrfs_subvolume_home, "yes")) -+ subvolflg = true; -+ - if (!gflg && !Nflg && !Uflg) { - /* Get the settings from login.defs */ - Uflg = getdef_bool ("USERGROUPS_ENAB"); --- -2.52.0 - diff --git a/shadow-4.15.0-manfix.patch b/shadow-4.15.0-manfix.patch deleted file mode 100644 index 34e62f9..0000000 --- a/shadow-4.15.0-manfix.patch +++ /dev/null @@ -1,162 +0,0 @@ -diff -up shadow-4.15.0/man/groupmems.8.xml.manfix shadow-4.15.0/man/groupmems.8.xml ---- shadow-4.15.0/man/groupmems.8.xml.manfix 2023-05-26 04:56:11.000000000 +0200 -+++ shadow-4.15.0/man/groupmems.8.xml 2024-02-09 10:42:20.337036378 +0100 -@@ -156,20 +156,10 @@ - - SETUP - -- The groupmems executable should be in mode -- 2710 as user root and in group -- groups. The system administrator can add users to -- group groups to allow or disallow them using the -- groupmems utility to manage their own group -- membership list. -+ In this operating system the groupmems executable -+ is not setuid and regular users cannot use it to manipulate -+ the membership of their own group. - -- -- -- $ groupadd -r groups -- $ chmod 2710 groupmems -- $ chown root:groups groupmems -- $ groupmems -g groups -a gk4 -- - - - -diff -up shadow-4.15.0/man/ja/man5/login.defs.5.manfix shadow-4.15.0/man/ja/man5/login.defs.5 ---- shadow-4.15.0/man/ja/man5/login.defs.5.manfix 2023-03-13 21:58:56.000000000 +0100 -+++ shadow-4.15.0/man/ja/man5/login.defs.5 2024-02-09 10:42:20.337036378 +0100 -@@ -123,10 +123,6 @@ 以下の参照表は、 - shadow パスワード機能のどのプログラムが - どのパラメータを使用するかを示したものである。 - .na --.IP chfn 12 --CHFN_AUTH CHFN_RESTRICT --.IP chsh 12 --CHFN_AUTH - .IP groupadd 12 - GID_MAX GID_MIN - .IP newusers 12 -diff -up shadow-4.15.0/man/login.defs.5.xml.manfix shadow-4.15.0/man/login.defs.5.xml ---- shadow-4.15.0/man/login.defs.5.xml.manfix 2024-01-22 22:36:43.000000000 +0100 -+++ shadow-4.15.0/man/login.defs.5.xml 2024-02-09 10:45:49.014407259 +0100 -@@ -144,6 +144,17 @@ - long numeric parameters is machine-dependent. - - -+ -+ Please note that the parameters in this configuration file control the -+ behavior of the tools from the shadow-utils component. None of these -+ tools uses the PAM mechanism, and the utilities that use PAM (such as the -+ passwd command) should be configured elsewhere. The only values that -+ affect PAM modules are ENCRYPT_METHOD and SHA_CRYPT_MAX_ROUNDS -+ for pam_unix module, FAIL_DELAY for pam_faildelay module, -+ and UMASK for pam_umask module. Refer to -+ pam(8) for more information. -+ -+ - The following configuration items are provided: - - -@@ -240,16 +251,6 @@ - - - -- chfn -- -- -- CHFN_AUTH -- CHFN_RESTRICT -- LOGIN_STRING -- -- -- -- - chgpasswd - - -@@ -276,14 +277,6 @@ - - - -- -- chsh -- -- -- CHSH_AUTH LOGIN_STRING -- -- -- - - - -@@ -352,34 +345,6 @@ - LASTLOG_UID_MAX - - -- -- login -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENV_PATH ENV_SUPATH -- ENV_TZ ENVIRON_FILE -- ERASECHAR FAIL_DELAY -- FAILLOG_ENAB -- FAKE_SHELL -- FTMP_FILE -- HUSHLOGIN_FILE -- ISSUE_FILE -- KILLCHAR -- LASTLOG_ENAB LASTLOG_UID_MAX -- LOGIN_RETRIES -- LOGIN_STRING -- LOGIN_TIMEOUT LOG_OK_LOGINS LOG_UNKFAIL_ENAB -- MAIL_CHECK_ENAB MAIL_DIR MAIL_FILE -- MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB -- QUOTAS_ENAB -- TTYGROUP TTYPERM TTYTYPE_FILE -- ULIMIT UMASK -- USERGROUPS_ENAB -- -- -- - - - newgrp / sg -@@ -451,32 +416,6 @@ - - - -- -- su -- -- -- CONSOLE -- CONSOLE_GROUPS DEFAULT_HOME -- ENV_HZ ENVIRON_FILE -- ENV_PATH ENV_SUPATH -- ENV_TZ LOGIN_STRING MAIL_CHECK_ENAB -- MAIL_DIR MAIL_FILE QUOTAS_ENAB -- SULOG_FILE SU_NAME -- SU_WHEEL_ONLY -- SYSLOG_SU_ENAB -- USERGROUPS_ENAB -- -- -- -- -- sulogin -- -- -- ENV_HZ -- ENV_TZ -- -- -- - - useradd - diff --git a/shadow-4.19.3-chkhash.patch b/shadow-4.19.3-chkhash.patch deleted file mode 100644 index 6dfc159..0000000 --- a/shadow-4.19.3-chkhash.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 4b2e669441438a6ae91c82a24c796894aa6a53b2 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 15 Jan 2026 01:14:46 +0100 -Subject: [PATCH 1/3] lib/chkhash.c: is_valid_hash(): Update comment - -This checks the entire shadow(5) 2nd field, which is more than just -a hash. - -Reported-by: Tobias Stoeckmann -Signed-off-by: Alejandro Colomar -(cherry picked from commit bce404a7a831de911cf20fc8d4c548957f70bc72) ---- - lib/chkhash.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index 348dfe7478f8..48aaa417e9a9 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -31,9 +31,7 @@ match_regex(const char *pattern, const char *string) - - - /* -- * is_valid_hash - check if the given string is a valid password hash -- * -- * Returns true if the string appears to be a valid hash, false otherwise. -+ * is_valid_hash - check if the string is a valid shadow(5) 2nd field. - * - * regex from: https://man.archlinux.org/man/crypt.5.en - */ --- -2.53.0 - - -From b72386978e0c994c5efc91d548da68a8d97088ab Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Thu, 15 Jan 2026 01:24:10 +0100 -Subject: [PATCH 2/3] lib/chkhash.c: is_valid_hash(): Comment meaning of !hash - and * - -Signed-off-by: Alejandro Colomar -(cherry picked from commit 9a86c515a1e7caeeb9e60fa63871170a2dfd98f0) ---- - lib/chkhash.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/lib/chkhash.c b/lib/chkhash.c -index 48aaa417e9a9..9123038adef0 100644 ---- a/lib/chkhash.c -+++ b/lib/chkhash.c -@@ -38,12 +38,14 @@ match_regex(const char *pattern, const char *string) - bool - is_valid_hash(const char *hash) - { -+ // Password temporarily locked - hash = strprefix(hash, "!") ?: hash; - - // Passwordless account; discouraged - if (streq(hash, "")) - return true; - -+ // Password permanently locked (and forgotten) - if (streq(hash, "*")) - return true; - --- -2.53.0 - - -From 4486e3e0f8b74e6af27b5dcb4114fd776afdd605 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Fri, 16 Jan 2026 01:52:32 +0100 -Subject: [PATCH 3/3] man/shadow.5.xml: Document "*" - -Signed-off-by: Alejandro Colomar -(cherry picked from commit 6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c) ---- - man/shadow.5.xml | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/man/shadow.5.xml b/man/shadow.5.xml -index dc7fdfde542f..d3cc03982c47 100644 ---- a/man/shadow.5.xml -+++ b/man/shadow.5.xml -@@ -82,8 +82,12 @@ - If the password field begins with an exclamation mark !, - the password is locked. - The remaining characters on the -- line represent the password field before the password was -- locked. -+ line represent the password hash. -+ -+ -+ If the password hash consists of a star *, -+ password access is effectively disallowed; -+ this is because no password can produce a hash like this. - - - Refer to crypt --- -2.53.0 - diff --git a/shadow-4.19.3-useradd-fix-btrfs.patch b/shadow-4.19.3-useradd-fix-btrfs.patch deleted file mode 100644 index 47671d9..0000000 --- a/shadow-4.19.3-useradd-fix-btrfs.patch +++ /dev/null @@ -1,492 +0,0 @@ -From 4079070c4b8ced8df9d86366ad113fc3c2e4e49c Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Wed, 22 Apr 2026 11:02:36 +0200 -Subject: [PATCH 1/5] lib/btrfs.c: btrfs_is_subvolume(): Simplify error check - -Signed-off-by: Alejandro Colomar ---- - lib/btrfs.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/lib/btrfs.c b/lib/btrfs.c -index 85ec7dbc..fe20cf30 100644 ---- a/lib/btrfs.c -+++ b/lib/btrfs.c -@@ -67,8 +67,7 @@ int btrfs_is_subvolume(const char *path) - if (ret <= 0) - return ret; - -- ret = stat(path, &st); -- if (ret == -1) -+ if (stat(path, &st) == -1) - return -1; - - if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) { --- -2.53.0 - - -From 7a4faaaf46314547cc5e6c8264c3a11753ef9352 Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Wed, 22 Apr 2026 11:14:20 +0200 -Subject: [PATCH 2/5] lib/, src/: Move statfs(2) call out of is_btrfs() - -This simplifies the return value of is_btrfs() into a boolean. - -Signed-off-by: Alejandro Colomar ---- - lib/btrfs.c | 25 +++++++++---------------- - lib/prototypes.h | 3 ++- - src/useradd.c | 11 +++++++++-- - 3 files changed, 20 insertions(+), 19 deletions(-) - -diff --git a/lib/btrfs.c b/lib/btrfs.c -index fe20cf30..065c7938 100644 ---- a/lib/btrfs.c -+++ b/lib/btrfs.c -@@ -60,12 +60,13 @@ int btrfs_remove_subvolume(const char *path) - */ - int btrfs_is_subvolume(const char *path) - { -- struct stat st; -- int ret; -+ struct stat st; -+ struct statfs sfs; - -- ret = is_btrfs(path); -- if (ret <= 0) -- return ret; -+ if (statfs(path, &sfs) == -1) -+ return -1; -+ if (!is_btrfs(&sfs)) -+ return 0; - - if (stat(path, &st) == -1) - return -1; -@@ -78,16 +79,8 @@ int btrfs_is_subvolume(const char *path) - } - - --/* Adapted from btrfsprogs */ --int is_btrfs(const char *path) -+bool -+is_btrfs(const struct statfs *sfs) - { -- struct statfs sfs; -- int ret; -- -- ret = statfs(path, &sfs); -- if (ret == -1) -- return -1; -- -- return sfs.f_type == BTRFS_SUPER_MAGIC; -+ return sfs->f_type == BTRFS_SUPER_MAGIC; - } -- -diff --git a/lib/prototypes.h b/lib/prototypes.h -index 9a03e312..42aa2923 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -23,6 +23,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -54,7 +55,7 @@ extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); - extern int btrfs_create_subvolume(const char *path); - extern int btrfs_remove_subvolume(const char *path); - extern int btrfs_is_subvolume(const char *path); --extern int is_btrfs(const char *path); -+extern bool is_btrfs(const struct statfs *sfs); - #endif - - /* basename() renamed to Basename() to avoid libc name space confusion */ -diff --git a/src/useradd.c b/src/useradd.c -index df679d28..5ce6cd6a 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2265,6 +2266,7 @@ static void create_home(const struct option_flags *flags) - #if WITH_BTRFS - if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) { - char *btrfs_check = strdup(path); -+ struct statfs sfs; - - if (!btrfs_check) { - fprintf(stderr, -@@ -2273,13 +2275,18 @@ static void create_home(const struct option_flags *flags) - fail_exit(E_HOMEDIR, process_selinux); - } - stpcpy(&btrfs_check[strlen(path) - strlen(cp) - 1], ""); -- if (is_btrfs(btrfs_check) <= 0) { -+ if (statfs(btrfs_check, &sfs) == -1) { -+ fprintf(stderr, "%s: statfs(\"%s\"): %s\n", -+ Prog, btrfs_check, strerrno()); -+ fail_exit(E_HOMEDIR, process_selinux); -+ } -+ free(btrfs_check); -+ if (!is_btrfs(&sfs)) { - fprintf(stderr, - _("%s: home directory \"%s\" must be mounted on BTRFS\n"), - Prog, path); - fail_exit(E_HOMEDIR, process_selinux); - } -- free(btrfs_check); - // make subvolume to mount for user instead of directory - if (btrfs_create_subvolume(path)) { - fprintf(stderr, --- -2.53.0 - - -From 96460c7240264c0022cebc9ba1774993ee2594cf Mon Sep 17 00:00:00 2001 -From: Alejandro Colomar -Date: Wed, 22 Apr 2026 11:21:14 +0200 -Subject: [PATCH 3/5] lib/, src/: Move btrfs.c prototypes to lib/btrfs.h - -Signed-off-by: Alejandro Colomar ---- - lib/Makefile.am | 2 +- - lib/btrfs.c | 4 ++++ - lib/btrfs.h | 23 +++++++++++++++++++++++ - lib/prototypes.h | 9 --------- - src/useradd.c | 1 + - src/userdel.c | 1 + - src/usermod.c | 1 + - 7 files changed, 31 insertions(+), 10 deletions(-) - create mode 100644 lib/btrfs.h - -diff --git a/lib/Makefile.am b/lib/Makefile.am -index 7c488f82..0664e610 100644 ---- a/lib/Makefile.am -+++ b/lib/Makefile.am -@@ -290,7 +290,7 @@ libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h - endif - - if WITH_BTRFS --libshadow_la_SOURCES += btrfs.c -+libshadow_la_SOURCES += btrfs.c btrfs.h - endif - - if ENABLE_LASTLOG -diff --git a/lib/btrfs.c b/lib/btrfs.c -index 065c7938..15b6b315 100644 ---- a/lib/btrfs.c -+++ b/lib/btrfs.c -@@ -1,3 +1,7 @@ -+#include "config.h" -+ -+#include "btrfs.h" -+ - #include - #include - #include -diff --git a/lib/btrfs.h b/lib/btrfs.h -new file mode 100644 -index 00000000..50b70488 ---- /dev/null -+++ b/lib/btrfs.h -@@ -0,0 +1,23 @@ -+// SPDX-FileCopyrightText: 2026, Alejandro Colomar -+// SPDX-License-Identifier: BSD-3-Clause -+ -+ -+#ifndef SHADOW_INCLUDE_LIB_BTRFS_H_ -+#define SHADOW_INCLUDE_LIB_BTRFS_H_ -+ -+ -+#include "config.h" -+ -+#include -+#include -+ -+ -+#ifdef WITH_BTRFS -+int btrfs_create_subvolume(const char *path); -+int btrfs_remove_subvolume(const char *path); -+int btrfs_is_subvolume(const char *path); -+bool is_btrfs(const struct statfs *sfs); -+#endif -+ -+ -+#endif // include guard -diff --git a/lib/prototypes.h b/lib/prototypes.h -index 42aa2923..d22c477a 100644 ---- a/lib/prototypes.h -+++ b/lib/prototypes.h -@@ -23,7 +23,6 @@ - - #include - #include --#include - #include - #include - #include -@@ -50,14 +49,6 @@ extern int expire (const struct passwd *, /*@null@*/const struct spwd *); - /* isexpired.c */ - extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *); - --/* btrfs.c */ --#ifdef WITH_BTRFS --extern int btrfs_create_subvolume(const char *path); --extern int btrfs_remove_subvolume(const char *path); --extern int btrfs_is_subvolume(const char *path); --extern bool is_btrfs(const struct statfs *sfs); --#endif -- - /* basename() renamed to Basename() to avoid libc name space confusion */ - /* basename.c */ - extern /*@observer@*/const char *Basename (const char *str); -diff --git a/src/useradd.c b/src/useradd.c -index 5ce6cd6a..9bd32b11 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -34,6 +34,7 @@ - #include "alloc/malloc.h" - #include "atoi/a2i.h" - #include "atoi/getnum.h" -+#include "btrfs.h" - #include "chkname.h" - #include "defines.h" - #include "faillog.h" -diff --git a/src/userdel.c b/src/userdel.c -index 9b7d81be..ebd064c0 100644 ---- a/src/userdel.c -+++ b/src/userdel.c -@@ -20,6 +20,7 @@ - #include - #include - -+#include "btrfs.h" - #ifdef ACCT_TOOLS_SETUID - #ifdef USE_PAM - #include "pam_defs.h" -diff --git a/src/usermod.c b/src/usermod.c -index 7c0321a6..3afe19ea 100644 ---- a/src/usermod.c -+++ b/src/usermod.c -@@ -32,6 +32,7 @@ - #include "alloc/malloc.h" - #include "atoi/a2i.h" - #include "atoi/getnum.h" -+#include "btrfs.h" - #include "chkname.h" - #include "defines.h" - #include "faillog.h" --- -2.53.0 - - -From 7be9a6540f1cad477fd4f4e83d25904a5095bb86 Mon Sep 17 00:00:00 2001 -From: Hadi Chokr -Date: Tue, 21 Apr 2026 09:18:19 +0200 -Subject: [PATCH 4/5] useradd(8): fallback to regular dir for BTRFS home on - non-BTRFS parent - -When the --btrfs-subvolume-home option is used but the parent directory -is not on a BTRFS filesystem, useradd previously failed with an error. -This is too strict; instead, fall back to creating a regular directory -and issue a warning. The subvolume creation is attempted only when the -parent is BTRFS. Otherwise, a regular directory is created and a -syslog(3) warning is logged. - -Fixes: 3e8c105 (2026-01-02; "src/useradd: Support config for creating home dirs as Btrfs subvolumes") -Co-authored-by: Hadi Chokr -Co-authored-by: Alejandro Colomar -Signed-off-by: Alejandro Colomar ---- - man/useradd.8.xml | 27 ++++++++++++++++++++++-- - src/useradd.c | 52 +++++++++++++++++++++++------------------------ - 2 files changed, 51 insertions(+), 28 deletions(-) - -diff --git a/man/useradd.8.xml b/man/useradd.8.xml -index 8a087e13..0bde6683 100644 ---- a/man/useradd.8.xml -+++ b/man/useradd.8.xml -@@ -2,6 +2,7 @@ - - - -- Note: this feature works only if the underlying filesystem supports -- Btrfs subvolumes. -+ If the parent directory of the user's home directory is -+ not on a Btrfs filesystem, -+ useradd will not create a -+ subvolume. -+ Instead, it creates a regular directory, -+ prints a warning to standard error, -+ and logs the event via syslog at level -+ LOG_WARN. -+ The user account is still created successfully. -+ -+ -+ If the filesystem type cannot be determined (e.g., because of -+ insufficient permissions, an I/O error, -+ or a -+ -+ statfs -+ 2 -+ -+ failure), -+ useradd treats this as a fatal error: -+ the home directory is not created, -+ the command exits with a non‑zero status -+ (E_HOMEDIR, 12), -+ and an error message is printed. - - - -diff --git a/src/useradd.c b/src/useradd.c -index 9bd32b11..9210379c 100644 ---- a/src/useradd.c -+++ b/src/useradd.c -@@ -1,11 +1,11 @@ --/* -- * SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh -- * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz -- * SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko -- * SPDX-FileCopyrightText: 2007 - 2012, Nicolas François -- * -- * SPDX-License-Identifier: BSD-3-Clause -- */ -+// SPDX-FileCopyrightText: 1991-1994, Julianne Frances Haugh -+// SPDX-FileCopyrightText: 1996-2000, Marek Michałkiewicz -+// SPDX-FileCopyrightText: 2000-2006, Tomasz Kłoczko -+// SPDX-FileCopyrightText: 2007-2012, Nicolas François -+// SPDX-FileCopyrightText: 2025-2026, Hadi Chokr -+// SPDX-FileCopyrightText: 2026, Alejandro Colomar -+// SPDX-License-Identifier: BSD-3-Clause -+ - - #include "config.h" - -@@ -2251,6 +2251,8 @@ static void create_home(const struct option_flags *flags) - owner root:root. - */ - for (cp = strtok(bhome, "/"); cp != NULL; cp = strtok(NULL, "/")) { -+ bool dir_created; -+ - /* Avoid turning a relative path into an absolute path. */ - if (strprefix(bhome, "/") || !streq(path, "")) - strcat(path, "/"); -@@ -2260,10 +2262,7 @@ static void create_home(const struct option_flags *flags) - continue; - } - -- /* Check if parent directory is BTRFS, fail if requesting -- subvolume but no BTRFS. The paths could be different by the -- trailing slash -- */ -+ dir_created = false; - #if WITH_BTRFS - if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) { - char *btrfs_check = strdup(path); -@@ -2284,25 +2283,26 @@ static void create_home(const struct option_flags *flags) - free(btrfs_check); - if (!is_btrfs(&sfs)) { - fprintf(stderr, -- _("%s: home directory \"%s\" must be mounted on BTRFS\n"), -- Prog, path); -- fail_exit(E_HOMEDIR, process_selinux); -+ _("%s: warning: \"%s\" is not on BTRFS; creating regular directory instead of subvolume\n"), -+ Prog, prefix_user_home); -+ } else { -+ if (btrfs_create_subvolume(path)) { -+ fprintf(stderr, -+ _("%s: failed to create BTRFS subvolume: %s\n"), -+ Prog, path); -+ fail_exit(E_HOMEDIR, process_selinux); -+ } -+ dir_created = true; - } -- // make subvolume to mount for user instead of directory -- if (btrfs_create_subvolume(path)) { -- fprintf(stderr, -- _("%s: failed to create BTRFS subvolume: %s\n"), -+ } -+#endif -+ if (!dir_created) { -+ if (mkdir(path, 0) != 0) { -+ fprintf(stderr, _("%s: cannot create directory %s\n"), - Prog, path); - fail_exit(E_HOMEDIR, process_selinux); - } - } -- else --#endif -- if (mkdir(path, 0) != 0) { -- fprintf(stderr, _("%s: cannot create directory %s\n"), -- Prog, path); -- fail_exit(E_HOMEDIR, process_selinux); -- } - if (chown(path, 0, 0) < 0) { - fprintf(stderr, - _("%s: warning: chown on `%s' failed: %m\n"), --- -2.53.0 - - -From 827f69b864461ab6d7549762bef06ab4495d2587 Mon Sep 17 00:00:00 2001 -From: Hadi Chokr -Date: Mon, 20 Apr 2026 12:27:31 +0200 -Subject: [PATCH 5/5] man/useradd.8.xml: Remove trailing spaces from - useradd.8.xml - -Signed-off-by: Hadi Chokr -Reviewed-by: Alejandro Colomar ---- - man/useradd.8.xml | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/man/useradd.8.xml b/man/useradd.8.xml -index 0bde6683..f85780e2 100644 ---- a/man/useradd.8.xml -+++ b/man/useradd.8.xml -@@ -207,7 +207,7 @@ - user's login directory. The default is to append the - LOGIN name to - BASE_DIR and use that as the -- login directory name. -+ login directory name. - The directory HOME_DIR is not created by - default. However it will be created for non-system users if either the - flag is specifed or -@@ -422,7 +422,7 @@ - - - -- Create the user's home directory if it does not exist. -+ Create the user's home directory if it does not exist. - The files and directories contained in the skeleton directory - (which can be defined with the option) - will be copied to the home directory. -@@ -512,7 +512,7 @@ - password himself. - - -- Note:Avoid this option on the command -+ Note:Avoid this option on the command - line because the password (or encrypted password) will - be visible by users listing the processes. - --- -2.53.0 - diff --git a/shadow-utils.spec b/shadow-utils.spec index 4f94261..a56f0b7 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.19.3 -Release: 4%{?dist} +Version: 4.20.0.rc3 +Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.19.3/shadow-4.19.3.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.19.3/shadow-4.19.3.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.20.0-rc3/shadow-4.20.0-rc3.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.20.0-rc3/shadow-4.20.0-rc3.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -20,14 +20,6 @@ Source7: passwd.pamd %global _ld_strict_symbol_defs 1 ### Patches ### -# Misc manual page changes - non-upstreamable -Patch0: shadow-4.15.0-manfix.patch -# https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49 -Patch2: shadow-4-19-useradd-support-btrfs.patch -# https://github.com/shadow-maint/shadow/commit/6be13b2f84a2c1a0d0f4129b5258b4b443e7f86c -Patch3: shadow-4.19.3-chkhash.patch -# https://github.com/shadow-maint/shadow/commit/827f69b864461ab6d7549762bef06ab4495d2587 -Patch4: shadow-4.19.3-useradd-fix-btrfs.patch ### Dependencies ### Requires: audit-libs >= 1.6.5 @@ -106,7 +98,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.19.3 +%autosetup -p 1 -S git -n shadow-4.20.0-rc3 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -163,26 +155,20 @@ mv -v $RPM_BUILD_ROOT/usr/sbin/* $RPM_BUILD_ROOT%{_bindir}/ # Remove binaries we don't use. rm $RPM_BUILD_ROOT%{_bindir}/chfn rm $RPM_BUILD_ROOT%{_bindir}/chsh -rm $RPM_BUILD_ROOT%{_bindir}/expiry rm $RPM_BUILD_ROOT%{_bindir}/login rm $RPM_BUILD_ROOT%{_bindir}/su rm $RPM_BUILD_ROOT%{_bindir}/faillog -rm $RPM_BUILD_ROOT%{_sbindir}/logoutd rm $RPM_BUILD_ROOT%{_sbindir}/nologin rm $RPM_BUILD_ROOT%{_mandir}/man1/chfn.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chfn.* rm $RPM_BUILD_ROOT%{_mandir}/man1/chsh.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/chsh.* -rm $RPM_BUILD_ROOT%{_mandir}/man1/expiry.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man1/expiry.* rm $RPM_BUILD_ROOT%{_mandir}/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/login.* rm $RPM_BUILD_ROOT%{_mandir}/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/*/man1/su.* rm $RPM_BUILD_ROOT%{_mandir}/man5/passwd.* rm $RPM_BUILD_ROOT%{_mandir}/*/man5/passwd.* -rm $RPM_BUILD_ROOT%{_mandir}/man8/logoutd.* -rm $RPM_BUILD_ROOT%{_mandir}/*/man8/logoutd.* rm $RPM_BUILD_ROOT%{_mandir}/man8/nologin.* rm $RPM_BUILD_ROOT%{_mandir}/*/man8/nologin.* rm $RPM_BUILD_ROOT%{_mandir}/man3/getspnam.* @@ -195,7 +181,6 @@ rm $RPM_BUILD_ROOT%{_mandir}/*/man8/faillog.* # Remove PAM service files we don't use. rm $RPM_BUILD_ROOT%{_pam_confdir}/chfn rm $RPM_BUILD_ROOT%{_pam_confdir}/chsh -rm $RPM_BUILD_ROOT%{_pam_confdir}/groupmems rm $RPM_BUILD_ROOT%{_pam_confdir}/login rm $RPM_BUILD_ROOT%{_pam_confdir}/su @@ -279,6 +264,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Jul 22 2026 Iker Pedrosa - 2:4.20.0-rc3-1 +- Rebase to version 4.20.0-rc3 + * Fri Jul 17 2026 Fedora Release Engineering - 2:4.19.3-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild diff --git a/sources b/sources index d12859f..d0fb76c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.19.3.tar.xz) = f2b41f8186681eb98dae0da87ed1a1f03327c5005c9d4bf9500801352e318de6f5954dc5b8f30ab9aece728b1efb74b4ff8fb2720acc4c2aaef701331a4a5a05 -SHA512 (shadow-4.19.3.tar.xz.asc) = 295a6bffefd333a9ea84fa59b368f5c48d0ac5224199624b768087098110b0f0c19bef37f5c474c45277980758dcb6728e8bb17eb7ab1a57603cad41f1dd00ab +SHA512 (shadow-4.20.0-rc3.tar.xz) = 49a3662d10669c5f34af012b2397324ffe11544c1f09d89a32408a9c8928cd4d313c16ed3afaa6ff8665f8f224de139170dc0d9c5dea127986c2b9350c117d1a +SHA512 (shadow-4.20.0-rc3.tar.xz.asc) = 719b80d1331fe825c0f0279309e7eb56b0a767e61fda845ea051c60128fdbc4abc1b9e9f0569fa6b9073c7a8712ce0b144f33b472cf3eebd32e75668f745cd1c From c8aec6bdba74d16b628a0bd1c440f17ed91bd050 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 22 Jul 2026 16:44:45 +0200 Subject: [PATCH 117/118] Tests: update dependencies System test framework requires gcc, python3-devel and libssh-devel installed before pip tries to compile ansible-pylibssh. Signed-off-by: Iker Pedrosa --- plans/tier0-functional.fmf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plans/tier0-functional.fmf b/plans/tier0-functional.fmf index 7fb6f9c..a9939b5 100644 --- a/plans/tier0-functional.fmf +++ b/plans/tier0-functional.fmf @@ -14,7 +14,10 @@ prepare: how: install package: - expect + - gcc - git + - libssh-devel + - python3-devel - python3-pip - name: Setup SSH keys for localhost testing From 103ee1cc475003e8c32e3f54792aaca0cef33250 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Wed, 29 Jul 2026 15:27:11 +0200 Subject: [PATCH 118/118] Rebase to version 4.20.0 Signed-off-by: Iker Pedrosa --- .gitignore | 2 ++ shadow-utils.spec | 11 +++++++---- sources | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 13adb8c..3023995 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ shadow-4.1.4.2.tar.bz2 /shadow-4.20.0-rc2.tar.xz.asc /shadow-4.20.0-rc3.tar.xz /shadow-4.20.0-rc3.tar.xz.asc +/shadow-4.20.0.tar.xz +/shadow-4.20.0.tar.xz.asc diff --git a/shadow-utils.spec b/shadow-utils.spec index a56f0b7..7bc7e8b 100644 --- a/shadow-utils.spec +++ b/shadow-utils.spec @@ -1,12 +1,12 @@ Summary: Utilities for managing accounts and shadow password files Name: shadow-utils -Version: 4.20.0.rc3 +Version: 4.20.0 Release: 1%{?dist} Epoch: 2 License: BSD-3-Clause AND GPL-2.0-or-later URL: https://github.com/shadow-maint/shadow -Source0: https://github.com/shadow-maint/shadow/releases/download/4.20.0-rc3/shadow-4.20.0-rc3.tar.xz -Source1: https://github.com/shadow-maint/shadow/releases/download/4.20.0-rc3/shadow-4.20.0-rc3.tar.xz.asc +Source0: https://github.com/shadow-maint/shadow/releases/download/4.20.0/shadow-4.20.0.tar.xz +Source1: https://github.com/shadow-maint/shadow/releases/download/4.20.0/shadow-4.20.0.tar.xz.asc Source2: shadow-utils.useradd Source3: shadow-utils.login.defs Source4: shadow-bsd.txt @@ -98,7 +98,7 @@ Requires: shadow-utils-subid = %{epoch}:%{version}-%{release} Development files for shadow-utils-subid. %prep -%autosetup -p 1 -S git -n shadow-4.20.0-rc3 +%autosetup -p 1 -S git -n shadow-4.20.0 iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 cp -f doc/HOWTO.utf8 doc/HOWTO @@ -264,6 +264,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a %{_libdir}/libsubid.so %changelog +* Wed Jul 29 2026 Iker Pedrosa - 2:4.20.0-1 +- Rebase to version 4.20.0 + * Wed Jul 22 2026 Iker Pedrosa - 2:4.20.0-rc3-1 - Rebase to version 4.20.0-rc3 diff --git a/sources b/sources index d0fb76c..7669083 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (shadow-4.20.0-rc3.tar.xz) = 49a3662d10669c5f34af012b2397324ffe11544c1f09d89a32408a9c8928cd4d313c16ed3afaa6ff8665f8f224de139170dc0d9c5dea127986c2b9350c117d1a -SHA512 (shadow-4.20.0-rc3.tar.xz.asc) = 719b80d1331fe825c0f0279309e7eb56b0a767e61fda845ea051c60128fdbc4abc1b9e9f0569fa6b9073c7a8712ce0b144f33b472cf3eebd32e75668f745cd1c +SHA512 (shadow-4.20.0.tar.xz) = 0b8afded372e4d37a78f38cb972c0ab877870ef6356cdd1c45be3c708af3d1496c6f87de6bf6a5b1d217d4d52d7e2d15c28b26530949cc6de0231a4028930406 +SHA512 (shadow-4.20.0.tar.xz.asc) = e4b134543768f323df30a1e450c22086d013020928d62bd3207db7f633beea3587b67802da5b575d5a794e8c2bebd7a0abeba6ed69d44bf08adc37df3bf352ac