From 677e644530f4f5ea7b077f546cc4425c563fc172 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 25 Nov 2023 18:57:53 +0800 Subject: [PATCH 1/2] Revert "nspawn-patch-uid: try fchmodat2() to restore mode of symlink" This reverts commit 30462563b19b92d8c6ed196d30d3cf7de90e8131. fchmodat2(), while accepting AT_SYMLINK_NOFOLLOW as a valid flag, always returns EOPNOTSUPP when operating on a symlink. The Linux kernel simply doesn't support changing the mode of a symlink. Fixes #30157 --- src/nspawn/nspawn-patch-uid.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index 063995dd6b8..66663adc2b9 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -11,7 +11,6 @@ #include "fileio.h" #include "fs-util.h" #include "missing_magic.h" -#include "missing_syscall.h" #include "nspawn-def.h" #include "nspawn-patch-uid.h" #include "stat-util.h" @@ -240,18 +239,14 @@ static int patch_fd(int fd, const char *name, const struct stat *st, uid_t shift /* The Linux kernel alters the mode in some cases of chown(). Let's undo this. */ if (name) { - /* It looks like older glibc (before 2016) did not support AT_SYMLINK_NOFOLLOW. */ if (!S_ISLNK(st->st_mode)) - r = RET_NERRNO(fchmodat(fd, name, st->st_mode, 0)); - else { - r = RET_NERRNO(fchmodat2(fd, name, st->st_mode, AT_SYMLINK_NOFOLLOW)); - if (IN_SET(r, -ENOSYS, -EPERM)) - r = 0; - } + r = fchmodat(fd, name, st->st_mode, 0); + else /* AT_SYMLINK_NOFOLLOW is not available for fchmodat() */ + r = 0; } else - r = RET_NERRNO(fchmod(fd, st->st_mode)); + r = fchmod(fd, st->st_mode); if (r < 0) - return r; + return -errno; changed = true; } From 0cdffada3db60676cd0a837e4dbb42d82b3be994 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 25 Nov 2023 19:10:50 +0800 Subject: [PATCH 2/2] nspawn-patch-uid: clarify that changing mode of symlink is unsupported --- src/nspawn/nspawn-patch-uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index 66663adc2b9..b8918a2315f 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -241,7 +241,7 @@ static int patch_fd(int fd, const char *name, const struct stat *st, uid_t shift if (name) { if (!S_ISLNK(st->st_mode)) r = fchmodat(fd, name, st->st_mode, 0); - else /* AT_SYMLINK_NOFOLLOW is not available for fchmodat() */ + else /* Changing the mode of a symlink is not supported by Linux kernel. Don't bother. */ r = 0; } else r = fchmod(fd, st->st_mode);