diff options
author | 2018-03-30 16:43:49 -0500 | |
---|---|---|
committer | 2018-03-30 16:43:49 -0500 | |
commit | cc6b2008646318c01153d39fef191da3e35a5fc8 (patch) | |
tree | 3d36f07d50f4743b2162ea24a43278efdccea280 | |
parent | 7dedccd196230cb5c9a08a57d8412c75fe6cfe0a (diff) | |
download | pseudo-cc6b2008646318c01153d39fef191da3e35a5fc8.tar.gz pseudo-cc6b2008646318c01153d39fef191da3e35a5fc8.tar.bz2 pseudo-cc6b2008646318c01153d39fef191da3e35a5fc8.zip |
Recently (2015) coreutils cp -Rp changed its behavior such that chmod()
is followed by setxattr(); previously it was the other way around. This
broke pseudo when a copied directory has one of the special
bits (setuid, setgid, sticky) set; the special bit wound up getting
removed.
Root cause is that ACLs never included special bits in the first place,
so we need to merge them back in ourselves.
[YOCTO #12379]
Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
-rw-r--r-- | ports/linux/xattr/pseudo_wrappers.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/ports/linux/xattr/pseudo_wrappers.c b/ports/linux/xattr/pseudo_wrappers.c index d69d53e..1c228a2 100644 --- a/ports/linux/xattr/pseudo_wrappers.c +++ b/ports/linux/xattr/pseudo_wrappers.c @@ -97,6 +97,21 @@ posix_permissions(const acl_header *header, int entries, int *extra, int *mode) return 0; } +static int get_special_bits(const char *path, int fd) { + int rc; + struct stat64 buf; + if (path) { + rc = lstat64(path, &buf); + } else { + rc = fstat64(fd, &buf); + } + if (rc == -1) { + return rc; + } + + return buf.st_mode & (S_ISUID | S_ISGID | S_ISVTX); +} + #define RC_AND_BUF \ int rc; \ PSEUDO_STATBUF buf; \ @@ -172,6 +187,10 @@ static int shared_setxattr(const char *path, int fd, const char *name, const voi int entries = (size - sizeof(acl_header)) / sizeof(acl_entry); int res = posix_permissions(value, entries, &extra, &mode); if (res == 0) { + /* POSIX ACLs don't actually include + * setuid/setgid/sticky bit. We need to add those back + * in ourselves. */ + mode |= get_special_bits(path, fd); pseudo_debug(PDBGF_XATTR, "posix_acl_access translated to mode %04o. Remaining attribute(s): %d.\n", mode, extra); buf.st_mode = mode; |