aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeebs <seebs@seebs.net>2018-03-30 16:43:49 -0500
committerSeebs <seebs@seebs.net>2018-03-30 16:43:49 -0500
commitcc6b2008646318c01153d39fef191da3e35a5fc8 (patch)
tree3d36f07d50f4743b2162ea24a43278efdccea280
parent7dedccd196230cb5c9a08a57d8412c75fe6cfe0a (diff)
downloadpseudo-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.c19
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;