nspawn-patch-uid: try fchmodat2() to restore mode of symlink

Prior to this commit, if the target had been a symlink, we did nothing
with it. Let's try with fchmodat2() and skip gracefully if not supported.

Co-authored-by: Mike Yuan <me@yhndnzj.com>
This commit is contained in:
Arseny Maslennikov
2023-11-02 00:29:09 +08:00
committed by Mike Yuan
co-authored by Mike Yuan
parent adecfb3bc0
commit 30462563b1
+10 -5
View File
@@ -11,6 +11,7 @@
#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"
@@ -239,14 +240,18 @@ 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 = fchmodat(fd, name, st->st_mode, 0);
else /* AT_SYMLINK_NOFOLLOW is not available for fchmodat() */
r = 0;
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;
}
} else
r = fchmod(fd, st->st_mode);
r = RET_NERRNO(fchmod(fd, st->st_mode));
if (r < 0)
return -errno;
return r;
changed = true;
}