From 3698b4cd0ffcbf70d1988509f84cbb0ab1d4df4f Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Fri, 10 Nov 2023 10:38:54 +0200 Subject: [PATCH] Fix sbit removal if fchmodat() doesn't support AT_SYMLINK_NOFOLLOW glibc versions prior to 2020 know about AT_SYMLINK_NOFOLLOW but don't actually implement it for fchmodat() and returns ENOSYS when used. We don't check the return code in removeSBITS() so this silently fails on those older versions. We already verify the thing is not a link in the fstatat() condition because cap_set_fileat() doesn't have any "dont follow" mode at all, so we can just as well drop it from the fchmodat() and make this work on more libc versions. Add a test for the suid bit removal while at it. --- lib/fsm.c | 3 ++- tests/rpme.at | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/fsm.c b/lib/fsm.c index 19e09f48ca..51f439ef3a 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -469,8 +469,9 @@ static void removeSBITS(int dirfd, const char *path) struct stat stb; int flags = AT_SYMLINK_NOFOLLOW; if (fstatat(dirfd, path, &stb, flags) == 0 && S_ISREG(stb.st_mode)) { + /* We now know it's not a link so no need to worry about following */ if ((stb.st_mode & 06000) != 0) { - (void) fchmodat(dirfd, path, stb.st_mode & 0777, flags); + (void) fchmodat(dirfd, path, stb.st_mode & 0777, 0); } #ifdef WITH_CAP if (stb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) { diff --git a/tests/rpme.at b/tests/rpme.at index 3e458a605f..ead757579f 100644 --- a/tests/rpme.at +++ b/tests/rpme.at @@ -25,6 +25,28 @@ missing d /usr/share/doc/hello-2.0/README []) RPMTEST_CLEANUP +AT_SETUP([rpm -e suid hardlink]) +AT_KEYWORDS([install erase]) +RPMDB_INIT + +runroot rpmbuild -bb --quiet \ + /data/SPECS/attrtest.spec +RPMTEST_CHECK([ +# silence "user/group does not exist" messages +runroot rpm -U --nodeps /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm 2> /dev/null +runroot_other ln /i/file /if +runroot_other test -u /if && echo suid +runroot rpm -e attrtest +runroot_other test -f /if && echo exists +runroot_other test -u /if && echo suid +], +[1], +[suid +exists +], +[]) +RPMTEST_CLEANUP + AT_SETUP([rpm reinstall with shared files]) AT_KEYWORDS([install erase update rpmdb]) RPMDB_INIT