Created attachment 4131 [details] pseudo -x odf log with acl enabled Reproduced with latest pseudo master commit b6b68db896f9963558334 on Arch Linux x86_64 with any version of coreutils (compiled on host Arch Linux) between 8.23 and 8.28 (I did not test earlier than 8.23). I also double checked that both my kernel (stock ArchLinux kernel) and ext4 filesystem have xattr and acl enabled. Compile pseudo natively using: $ git clone <pseudo-url> $ cd pseudo $ mkdir pseudo_install $ ./configure --prefix=./pseudo_install/ $ make $ make install then observe how the sticky bit gets lost on the cp destination: [adi bin]$ cd pseudo_install/bin [adi bin]$ ./pseudo Warning: PSEUDO_PREFIX unset, defaulting to /mnt/hdd_data/workspace/pseudo/pseudo_install. [root bin]$ mkdir baz [root bin]$ chmod 1777 baz [root bin]$ cp -Rp baz baz2 [root bin]$ ls -ld baz baz2 drwxrwxrwt 2 root root 4096 Nov 23 14:06 baz drwxrwxrwx 2 root root 4096 Nov 23 14:06 baz2 A full log of this behaviour under a "./pseudo -x odf" call in attached as pseudo_acl.txt If I configure & compile coreutils' cp with the --disable-acl flag then the sticky big is not lost anymore: $ git clone <coreutils-url> $ cd coreutils $ mkdir coreutils_install $ ./bootstrap $ ./configure --prefix=./coreutils_install/ $ make $ make install $ cp ./coreutils_install/bin/cp <pseudo-git-repo-dir>/pseudo_install/bin/cp_acl_disabled [adi bin]$ ./pseudo Warning: PSEUDO_PREFIX unset, defaulting to /mnt/hdd_data/workspace/pseudo/pseudo_install. [root bin]$ mkdir baz [root bin]$ chmod 1777 baz [root bin]$ ./cp_acl_disabled -Rp baz baz2 [root bin]$ ls -ld baz baz2 drwxrwxrwt 2 root root 4096 Nov 23 16:27 baz drwxrwxrwt 2 root root 4096 Nov 23 16:27 baz2 A full log of the --disable-acl compiled cp pseudo -x odf call is attached as pseudo_no_acl.txt Looking at the difference between the files you can notice get-xattr call failures in the ACL-enabled case, then a remove-xattr: -get-xattr system.posix_acl_access -> /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz (+buf) (041755): (31120) fail -stat /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz (+buf) (041755): (31120) succeed mode 041777 uid 0:0 -get-xattr system.posix_acl_default -> /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz (+buf) (041755): (31120) fail -stat /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz (+buf) (041755): (31120) succeed mode 041777 uid 0:0 chmod /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz2 (+buf) (041777): fuid: 0 -chmod /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz2 (+buf) (040777): fuid: 0 -remove-xattr system.posix_acl_default -> /mnt/hdd_data/workspace/pseudo/pseudo_install/bin/baz2 (+buf) (040755): (31120) succeed I'm assuming it's expected for the get-xattr calls to be missing if ACL is disabled in coreutils' cp, but I don't understand why is the sticky bit carried correctly if ACL is disabled (this only happens under pseudo, outside pseudo it's carried correctly every time). I'm not familiar at all with the pseudo codebase to debug the ACL enabled codepath further, but any help/ideas/pointers in doing so are appreciated.
Created attachment 4132 [details] pseudo -x odf log with acl disabled Adding the second log file mentioned in the bug report
I have a proposed but not confirmed root cause, and a proposed but not written or tested fix. Keep reading. I've bisected this down to the following gnulib commit: commit 2d5ce445d63109b3999402effbc6f8c1db4e8920 Author: Andreas Gruenbacher <andreas.gruenbacher@gmail.com> Date: Sat Apr 11 14:44:30 2015 +0200 qacl: Reimplement qset_acl and qcopy_acl (Bug#20666) Implement get_permissions and set_permissions primitives for getting all the permissions of a file, storing them, and later setting them. (In the minimal case, the permissions consist only of a file mode.) Reimplement qset_acl and qcopy_acl based on these new primitives: this avoids code duplication and makes error handling more consistent. However, that particular commit leaves coreutils unbuildable until the following, about 10 commits later: commit e3704b9c9859ec7b560f118a137668bbb2dd50ff (HEAD) Author: Pádraig Brady <P@draigBrady.com> Date: Mon Jun 1 21:50:13 2015 +0100 gnulib-tool: concatenate lib_SOURCES to a single line * gnulib-tool: Refactor the line merging sed logic, and use that to output a single lib_SOURCES line for each module. gnulib using projects often postprocess this output to prepend subdir paths to each item, and having a single line simplifies this processing allowing better decoupling from the gnulib-tool output. This avoids a new issue with coreutils where it failed to prepend a path on the new {get,set}-permissions.c items (which were on continued lines in modules/acl-permissions). Neither this commit nor the previous ones appear remotely pertinent to this bug, so 2d5ce445 is all we need to worry about. 2d5ce445 change basically rewrites all permission gets/sets for file and directory copies. In the previous implementation, a chmod occurred after acl_set_file if a special bit was set: https://github.com/coreutils/gnulib/commit/2d5ce445d63109b3999402effbc6f8c1db4e8920#diff-2418b5a747cd5170b5f44f2bee8ecbaaL134 But in the new code, the order is reversed. An "early" chmod is now done -- https://github.com/coreutils/gnulib/commit/2d5ce445d63109b3999402effbc6f8c1db4e8920#diff-cd8e3f4d77c9523f0895543fbb893999R781 -- presumably so that the code path for the special bits matches whatever craziness is needed for cygwin. After that comes the acl_set_file. A close study of acl(5) and the relatively unstated assumptions of the above commit unambiguously imply that special bits are **NOT** stored in ACLs. Unfortunately, pseudo appears to be wholly ignorant of this. The predicted result matches the behavior in this bug. The parameters to setxattr() contain no information on special bits, because there's no place to store it. Because this is a system.posix_acl_access xattr, pseudo will attempt to decode the mode itself and wrap_chmod based on that, http://git.yoctoproject.org/cgit/cgit.cgi/pseudo/tree/ports/linux/xattr/pseudo_wrappers.c#n178 . But this decoded mode contains none of the special bits and wrap_chmod will strip them off. If I'm right, then the correct fix is for ports/linux/xattr/pseudo_wrappers.c:shared_setxattr to merge in any existing special bits before calling wrap_chmod.
I think I have a patch, it's out for review to seebs.
Posted patch to oe-core but screwed up the subject so it's not showing up as a patch series in patchwork, and it looks like one of the patches was lost. Patches available in archives at: http://lists.openembedded.org/pipermail/openembedded-core/2017-November/145098.html http://lists.openembedded.org/pipermail/openembedded-core/2017-November/145097.html http://lists.openembedded.org/pipermail/openembedded-core/2017-November/145101.html http://lists.openembedded.org/pipermail/openembedded-core/2017-November/145100.html http://lists.openembedded.org/pipermail/openembedded-core/2017-November/145099.html
Peter, can you please comment? Is this in pseudo master?
I don't think I incorporated that, it seems unfamiliar, but agreed that it should go in.
now merged in master.
http://git.yoctoproject.org/cgit.cgi/poky/commit/?id=5b68f72e590546958a742f64f3501f1abaa22267