Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

capabilities are lost when send/receive #85

Closed
freswa opened this issue Jan 20, 2018 · 13 comments
Closed

capabilities are lost when send/receive #85

freswa opened this issue Jan 20, 2018 · 13 comments
Labels

Comments

@freswa
Copy link

freswa commented Jan 20, 2018

This bug is probably a regression: https://bugzilla.kernel.org/show_bug.cgi?id=68891

btrfs-progs: 4.14
kernel 4.14.14 (on Archlinux)

For the original fs and a readonly snapshot, I get:

# find /usr/bin -type f | xargs getcap                                           
/usr/bin/rsh = cap_net_bind_service+ep
/usr/bin/rcp = cap_net_bind_service+ep
/usr/bin/rlogin = cap_net_bind_service+ep
/usr/bin/ping = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_bind_service,cap_net_raw+ep
/usr/bin/sway = cap_sys_ptrace+eip
/usr/bin/dumpcap = cap_dac_override,cap_net_admin,cap_net_raw+eip

After send/receive:

# find /usr/bin -type f | xargs getcap
<nothing>
@adam900710
Copy link
Collaborator

It seems that the XATTR_ITEM is lost.

Would you please dump the metadata of the send stream by:

btrfs receive --dump -i <stream>

@kdave kdave added the bug label Jan 22, 2018
@freswa
Copy link
Author

freswa commented Jan 22, 2018

Here we go:

root@kvasir /mnt/tempmount # btrfs subvolume create testvol
Create subvolume './testvol'
root@kvasir /mnt/tempmount # cp -a /usr/bin/ping testvol/testping
root@kvasir /mnt/tempmount # getcap testvol/testping 
testvol/testping = cap_net_raw+ep
root@kvasir /mnt/tempmount # btrfs subvolume snapshot  -r testvol testsnap
Create a readonly snapshot of 'testvol' in './testsnap'
root@kvasir /mnt/tempmount # btrfs send testsnap | btrfs receive --dump  
At subvol testsnap
subvol          ./testsnap                      uuid=cb230e20-1874-1c48-88f8-9b201ba6b24b transid=26777
chown           ./testsnap/                     gid=0 uid=0
chmod           ./testsnap/                     mode=775
utimes          ./testsnap/                     atime=2018-01-22T14:05:33+0100 mtime=2018-01-22T14:05:19+0100 ctime=2018-01-22T14:05:19+0100
mkfile          ./testsnap/o257-26776-0
rename          ./testsnap/o257-26776-0         dest=./testsnap/testping
utimes          ./testsnap/                     atime=2018-01-22T14:05:33+0100 mtime=2018-01-22T14:05:19+0100 ctime=2018-01-22T14:05:19+0100
set_xattr       ./testsnap/testping             name=security.capability data=� len=20
write           ./testsnap/testping             offset=0 len=49152
write           ./testsnap/testping             offset=49152 len=12016
truncate        ./testsnap/testping             size=61168
chown           ./testsnap/testping             gid=0 uid=0
chmod           ./testsnap/testping             mode=755
utimes          ./testsnap/testping             atime=2018-01-22T13:53:30+0100 mtime=2017-02-11T13:06:45+0100 ctime=2018-01-22T14:05:19+0100
truncate        ./testsnap/testping             size=61168
chown           ./testsnap/testping             gid=0 uid=0
chmod           ./testsnap/testping             mode=755
utimes          ./testsnap/testping             atime=2018-01-22T13:53:30+0100 mtime=2017-02-11T13:06:45+0100 ctime=2018-01-22T14:05:19+0100
truncate        ./testsnap/testping             size=61168
chown           ./testsnap/testping             gid=0 uid=0
chmod           ./testsnap/testping             mode=755
utimes          ./testsnap/testping             atime=2018-01-22T13:53:30+0100 mtime=2017-02-11T13:06:45+0100 ctime=2018-01-22T14:05:19+0100
truncate        ./testsnap/testping             size=61168
chown           ./testsnap/testping             gid=0 uid=0
chmod           ./testsnap/testping             mode=755
utimes          ./testsnap/testping             atime=2018-01-22T13:53:30+0100 mtime=2017-02-11T13:06:45+0100 ctime=2018-01-22T14:05:19+0100
root@kvasir /mnt/tempmount # btrfs subvolume create testreceived         
Create subvolume './testreceived'
root@kvasir /mnt/tempmount # btrfs send testsnap | btrfs receive testreceived 
At subvol testsnap
At subvol testsnap
root@kvasir /mnt/tempmount # getcap testreceived/testsnap/testping 
root@kvasir /mnt/tempmount # 
Linux version 4.14.13-1-ARCH (builduser@heftig-32336) (gcc version 7.2.1 20171224 (GCC)) #1 SMP PREEMPT Wed Jan 10 11:14:50 UTC 2018
root@kvasir /mnt/tempmount # btrfs --version
btrfs-progs v4.14

@freswa
Copy link
Author

freswa commented Jan 22, 2018

I guess the problem once again is, that we set_xattr before we chown, so chown wipes all xattr of.

@kdave
Copy link
Owner

kdave commented Jan 22, 2018

If you increase verobosity, the capability vs chown will be logged. Once the xattr is detected (https://github.com/kdave/btrfs-progs/blob/master/cmds-receive.c#L856), the contents is saved and applied after chown so it does not get lost. There was no change in that code so I wonder what went wrong.

@freswa
Copy link
Author

freswa commented Jan 22, 2018

btrfs -v --dump does not print anything helpful (two more lines).
But I also ran a strace where the xattr are set before chown (correct me if I am wrong):
Edit: I see that the mechanism is "working" because there is a second lsetxattr after one of the chowns. The problem might be that there are way too many chowns...

root@kvasir /mnt/tempmount # btrfs send testsnap | strace btrfs receive  testreceived 
At subvol testsnap
execve("/usr/bin/btrfs", ["btrfs", "receive", "testreceived"], 0x7fff6648f950 /* 54 vars */) = 0
brk(NULL)                               = 0x55c202349000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=210657, ...}) = 0
mmap(NULL, 210657, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb5d700b000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libuuid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\24\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=26552, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb5d7009000
mmap(NULL, 2121752, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d6c14000
mprotect(0x7fb5d6c1a000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d6e19000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7fb5d6e19000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libblkid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\224\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=314168, ...}) = 0
mmap(NULL, 2414400, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d69c6000
mprotect(0x7fb5d6a0d000, 2097152, PROT_NONE) = 0
mmap(0x7fb5d6c0d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x47000) = 0x7fb5d6c0d000
mmap(0x7fb5d6c13000, 1856, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb5d6c13000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360!\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=92056, ...}) = 0
mmap(NULL, 2187280, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d67af000
mprotect(0x7fb5d67c5000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d69c4000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7fb5d69c4000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/liblzo2.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20'\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=137432, ...}) = 0
mmap(NULL, 2232528, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d658d000
mprotect(0x7fb5d65ae000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d67ad000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x20000) = 0x7fb5d67ad000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libzstd.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240@\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=505536, ...}) = 0
mmap(NULL, 2601008, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d6311000
mprotect(0x7fb5d638c000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d658b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7a000) = 0x7fb5d658b000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0]\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=145336, ...}) = 0
mmap(NULL, 2216400, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d60f3000
mprotect(0x7fb5d610c000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d630b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7fb5d630b000
mmap(0x7fb5d630d000, 12752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb5d630d000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\20\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2065784, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb5d7007000
mmap(NULL, 3893488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5d5d3c000
mprotect(0x7fb5d5eea000, 2093056, PROT_NONE) = 0
mmap(0x7fb5d60e9000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ad000) = 0x7fb5d60e9000
mmap(0x7fb5d60ef000, 14576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb5d60ef000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb5d7004000
arch_prctl(ARCH_SET_FS, 0x7fb5d70048c0) = 0
mprotect(0x7fb5d60e9000, 16384, PROT_READ) = 0
mprotect(0x7fb5d630b000, 4096, PROT_READ) = 0
mprotect(0x7fb5d658b000, 4096, PROT_READ) = 0
mprotect(0x7fb5d67ad000, 4096, PROT_READ) = 0
mprotect(0x7fb5d69c4000, 4096, PROT_READ) = 0
mprotect(0x7fb5d6e19000, 4096, PROT_READ) = 0
mprotect(0x7fb5d6c0d000, 20480, PROT_READ) = 0
mprotect(0x55c2014c8000, 20480, PROT_READ) = 0
mprotect(0x7fb5d703f000, 4096, PROT_READ) = 0
munmap(0x7fb5d700b000, 210657)          = 0
set_tid_address(0x7fb5d7004b90)         = 15528
set_robust_list(0x7fb5d7004ba0, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7fb5d60f8770, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7fb5d6104db0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7fb5d60f8810, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7fb5d6104db0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
brk(NULL)                               = 0x55c202349000
brk(0x55c20236a000)                     = 0x55c20236a000
getcwd("/mnt/tempmount", 4096)          = 15
lstat("/mnt/tempmount/testreceived", {st_mode=S_IFDIR|0775, st_size=0, ...}) = 0
openat(AT_FDCWD, "/mnt/tempmount/testreceived", O_RDONLY|O_NOATIME) = 3
openat(AT_FDCWD, "/mnt/tempmount/testreceived", O_RDONLY|O_NOATIME) = 4
close(4)                                = 0
open("/proc/self/mounts", O_RDONLY|O_CLOEXEC) = 4
futex(0x7fb5d60effc8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(4, "proc /proc proc rw,nosuid,nodev,"..., 1024) = 1024
read(4, "/fs/cgroup/rdma cgroup rw,nosuid"..., 1024) = 1024
read(4, "uid,nodev 0 0\nconfigfs /sys/kern"..., 1024) = 576
read(4, "", 1024)                       = 0
close(4)                                = 0
openat(AT_FDCWD, "/", O_RDONLY|O_NOATIME) = 4
ioctl(4, BTRFS_IOC_INO_LOOKUP, {treeid=0, objectid=256 /* BTRFS_FIRST_FREE_OBJECTID */} => {treeid=350, name=""}) = 0
ioctl(4, BTRFS_IOC_TREE_SEARCH, {key={tree_id=1 /* BTRFS_ROOT_TREE_OBJECTID */, min_objectid=350, max_objectid=350, max_offset=18446744073709551615 /* UINT64_MAX */, max_transid=18446744073709551615 /* UINT64_MAX */, min_type=144 /* BTRFS_ROOT_BACKREF_KEY */, max_type=144 /* BTRFS_ROOT_BACKREF_KEY */, nr_items=1}} => {key={nr_items=1}, buf=...}) = 0
ioctl(4, BTRFS_IOC_INO_LOOKUP, {treeid=5 /* BTRFS_FS_TREE_OBJECTID */, objectid=257} => {name="orig/"}) = 0
ioctl(4, BTRFS_IOC_TREE_SEARCH, {key={tree_id=1 /* BTRFS_ROOT_TREE_OBJECTID */, min_objectid=9 /* BTRFS_UUID_TREE_OBJECTID */, max_objectid=9 /* BTRFS_UUID_TREE_OBJECTID */, max_offset=18446744073709551615 /* UINT64_MAX */, max_transid=18446744073709551615 /* UINT64_MAX */, min_type=132 /* BTRFS_ROOT_ITEM_KEY */, max_type=132 /* BTRFS_ROOT_ITEM_KEY */, nr_items=1}} => {key={nr_items=1}, buf=...}) = 0
read(0, "btrfs-stream\0\1\0\0\0", 17)   = 17
read(0, ",\0\0\0\1\0d\276\264$", 10)    = 10
read(0, "\17\0\10\0testsnap\1\0\20\0\313#\16 \30t\34H\210\370\233 \33\246\262K"..., 44) = 44
write(2, "At subvol testsnap\n", 19At subvol testsnap
)    = 19
ioctl(3, BTRFS_IOC_SUBVOL_CREATE, {fd=0, name="testsnap"}) = 0
read(0, "\34\0\0\0\23\0\0027-\214", 10) = 10
read(0, "\17\0\0\0\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0\0\0\0\0", 28) = 28
lchown("/mnt/tempmount/testreceived/testsnap/", 0, 0) = 0
read(0, "\20\0\0\0\22\0\355\\\3\261", 10) = 10
read(0, "\17\0\0\0\5\0\10\0\375\1\0\0\0\0\0\0", 16) = 16
chmod("/mnt/tempmount/testreceived/testsnap/", 0775) = 0
read(0, "4\0\0\0\24\0\220\271\r\341", 10) = 10
read(0, "\17\0\0\0\v\0\f\0\235\341eZ\0\0\0\0\231)\215\36\n\0\f\0\217\341eZ\0\0\0\0"..., 52) = 52
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/", [{tv_sec=1516626333, tv_nsec=512567705} /* 2018-01-22T14:05:33.512567705+0100 */, {tv_sec=1516626319, tv_nsec=475723957} /* 2018-01-22T14:05:19.475723957+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\34\0\0\0\3\0\345\34\7e", 10)  = 10
read(0, "\17\0\f\0o257-26776-0\3\0\10\0\1\1\0\0\0\0\0\0", 28) = 28
creat("/mnt/tempmount/testreceived/testsnap/o257-26776-0", 0600) = 5
close(5)                                = 0
read(0, "\34\0\0\0\t\0\346\250\335\341", 10) = 10
read(0, "\17\0\f\0o257-26776-0\20\0\10\0testping", 28) = 28
rename("/mnt/tempmount/testreceived/testsnap/o257-26776-0", "/mnt/tempmount/testreceived/testsnap/testping") = 0
read(0, "4\0\0\0\24\0\220\271\r\341", 10) = 10
read(0, "\17\0\0\0\v\0\f\0\235\341eZ\0\0\0\0\231)\215\36\n\0\f\0\217\341eZ\0\0\0\0"..., 52) = 52
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/", [{tv_sec=1516626333, tv_nsec=512567705} /* 2018-01-22T14:05:33.512567705+0100 */, {tv_sec=1516626319, tv_nsec=475723957} /* 2018-01-22T14:05:19.475723957+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, ";\0\0\0\r\0000\312\10\270", 10) = 10
read(0, "\17\0\10\0testping\r\0\23\0security.capabil"..., 59) = 59
lsetxattr("/mnt/tempmount/testreceived/testsnap/testping", "security.capability", "\1\0\0\2\0 \0\0\0\0\0\0\0\0\0\0\0\0\0", 20, 0) = 0
read(0, "\34\300\0\0\17\0v+\1\365", 10) = 10
read(0, "\17\0\10\0testping\22\0\10\0\0\0\0\0\0\0\0\0\23\0\0\300\177ELF"..., 49180) = 49180
openat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/testping", O_RDWR) = 5
pwrite64(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0 .@\0\0\0\0\0"..., 49152, 0) = 49152
read(0, "\f/\0\0\17\0\3267\317D", 10)   = 10
read(0, "\17\0\10\0testping\22\0\10\0\0\300\0\0\0\0\0\0\23\0\360.at %"..., 12044) = 12044
pwrite64(5, "at %u\0Echo request\0Echo reply\0ML"..., 12016, 49152) = 12016
read(0, "\30\0\0\0\21\0r\f\177\303", 10) = 10
read(0, "\17\0\10\0testping\4\0\10\0\360\356\0\0\0\0\0\0", 24) = 24
truncate("/mnt/tempmount/testreceived/testsnap/testping", 61168) = 0
read(0, "$\0\0\0\23\0B\324\265\207", 10) = 10
read(0, "\17\0\10\0testping\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0"..., 36) = 36
lchown("/mnt/tempmount/testreceived/testsnap/testping", 0, 0) = 0
lsetxattr("/mnt/tempmount/testreceived/testsnap/testping", "security.capability", "\1\0\0\2\0 \0\0\0\0\0\0\0\0\0\0\0\0\0", 20, 0) = 0
read(0, "\30\0\0\0\22\0\224.\345\203", 10) = 10
read(0, "\17\0\10\0testping\5\0\10\0\355\1\0\0\0\0\0\0", 24) = 24
chmod("/mnt/tempmount/testreceived/testsnap/testping", 0755) = 0
read(0, "<\0\0\0\24\0\2561\37\10", 10)  = 10
read(0, "\17\0\10\0testping\v\0\f\0\312\336eZ\0\0\0\0@\351!#\n\0\f\0"..., 60) = 60
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/testping", [{tv_sec=1516625610, tv_nsec=589424960} /* 2018-01-22T13:53:30.589424960+0100 */, {tv_sec=1486814805, tv_nsec=0} /* 2017-02-11T13:06:45+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\30\0\0\0\21\0r\f\177\303", 10) = 10
read(0, "\17\0\10\0testping\4\0\10\0\360\356\0\0\0\0\0\0", 24) = 24
truncate("/mnt/tempmount/testreceived/testsnap/testping", 61168) = 0
read(0, "$\0\0\0\23\0B\324\265\207", 10) = 10
read(0, "\17\0\10\0testping\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0"..., 36) = 36
lchown("/mnt/tempmount/testreceived/testsnap/testping", 0, 0) = 0
read(0, "\30\0\0\0\22\0\224.\345\203", 10) = 10
read(0, "\17\0\10\0testping\5\0\10\0\355\1\0\0\0\0\0\0", 24) = 24
chmod("/mnt/tempmount/testreceived/testsnap/testping", 0755) = 0
read(0, "<\0\0\0\24\0\2561\37\10", 10)  = 10
read(0, "\17\0\10\0testping\v\0\f\0\312\336eZ\0\0\0\0@\351!#\n\0\f\0"..., 60) = 60
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/testping", [{tv_sec=1516625610, tv_nsec=589424960} /* 2018-01-22T13:53:30.589424960+0100 */, {tv_sec=1486814805, tv_nsec=0} /* 2017-02-11T13:06:45+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\30\0\0\0\21\0r\f\177\303", 10) = 10
read(0, "\17\0\10\0testping\4\0\10\0\360\356\0\0\0\0\0\0", 24) = 24
truncate("/mnt/tempmount/testreceived/testsnap/testping", 61168) = 0
read(0, "$\0\0\0\23\0B\324\265\207", 10) = 10
read(0, "\17\0\10\0testping\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0"..., 36) = 36
lchown("/mnt/tempmount/testreceived/testsnap/testping", 0, 0) = 0
read(0, "\30\0\0\0\22\0\224.\345\203", 10) = 10
read(0, "\17\0\10\0testping\5\0\10\0\355\1\0\0\0\0\0\0", 24) = 24
chmod("/mnt/tempmount/testreceived/testsnap/testping", 0755) = 0
read(0, "<\0\0\0\24\0\2561\37\10", 10)  = 10
read(0, "\17\0\10\0testping\v\0\f\0\312\336eZ\0\0\0\0@\351!#\n\0\f\0"..., 60) = 60
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/testping", [{tv_sec=1516625610, tv_nsec=589424960} /* 2018-01-22T13:53:30.589424960+0100 */, {tv_sec=1486814805, tv_nsec=0} /* 2017-02-11T13:06:45+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\30\0\0\0\21\0r\f\177\303", 10) = 10
read(0, "\17\0\10\0testping\4\0\10\0\360\356\0\0\0\0\0\0", 24) = 24
truncate("/mnt/tempmount/testreceived/testsnap/testping", 61168) = 0
read(0, "$\0\0\0\23\0B\324\265\207", 10) = 10
read(0, "\17\0\10\0testping\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0"..., 36) = 36
lchown("/mnt/tempmount/testreceived/testsnap/testping", 0, 0) = 0
read(0, "\30\0\0\0\22\0\224.\345\203", 10) = 10
read(0, "\17\0\10\0testping\5\0\10\0\355\1\0\0\0\0\0\0", 24) = 24
chmod("/mnt/tempmount/testreceived/testsnap/testping", 0755) = 0
read(0, "<\0\0\0\24\0\2561\37\10", 10)  = 10
read(0, "\17\0\10\0testping\v\0\f\0\312\336eZ\0\0\0\0@\351!#\n\0\f\0"..., 60) = 60
utimensat(AT_FDCWD, "/mnt/tempmount/testreceived/testsnap/testping", [{tv_sec=1516625610, tv_nsec=589424960} /* 2018-01-22T13:53:30.589424960+0100 */, {tv_sec=1486814805, tv_nsec=0} /* 2017-02-11T13:06:45+0100 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\0\0\0\0\25\0Pl\311\235", 10)  = 10
close(5)                                = 0
openat(4, "mnt/tempmount/testreceived/testsnap", O_RDONLY|O_NOATIME) = 5
ioctl(5, BTRFS_IOC_SET_RECEIVED_SUBVOL, {uuid=cb230e20-1874-1c48-88f8-9b201ba6b24b, stransid=26777, stime=0.0, flags=0} => {rtransid=27033, rtime=1516634939.806456409}) = 0
ioctl(5, BTRFS_IOC_SUBVOL_GETFLAGS, 0)  = 0
ioctl(5, BTRFS_IOC_SUBVOL_SETFLAGS, BTRFS_SUBVOL_RDONLY) = 0
close(5)                                = 0
read(0, "", 17)                         = 0
close(4)                                = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

@adam900710
Copy link
Collaborator

btrfs -v --dump does not print anything helpful (two more lines).

I think David means add the -v option for real receive other than dump.

But at least, the stream is good so only btrfs-progs is involved.

@lorddoskias
Copy link
Contributor


root@ubuntu-virtual:~# mkfs.btrfs -f /dev/vdc 
btrfs-progs v4.15.1
See http://btrfs.wiki.kernel.org for more information.

Label:              (null)
UUID:               4563bbc2-629c-497b-9795-ee308632378f
Node size:          16384
Sector size:        4096
Filesystem size:    14.65GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP               1.00GiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1    14.65GiB  /dev/vdc

root@ubuntu-virtual:~# mount /dev/vdc /media/scratch/
root@ubuntu-virtual:~# btrfs subvol create /media/scratch/subvol1
Create subvolume '/media/scratch/subvol1'
root@ubuntu-virtual:~# touch /media/scratch/subvol1/foobar  
root@ubuntu-virtual:~# setcap cap_sys_admin+ep /media/scratch/subvol1/foobar 
root@ubuntu-virtual:~# getcap /media/scratch/subvol1/foobar 
/media/scratch/subvol1/foobar = cap_sys_admin+ep

root@ubuntu-virtual:~# btrfs subvol snapshot -r /media/scratch/subvol1/ /media/scratch/testsnap
Create a readonly snapshot of '/media/scratch/subvol1/' in '/media/scratch/testsnap'

root@ubuntu-virtual:~# mkdir /media/scratch/received-vol
btrfs send /media/scratch/testsnap/ | btrfs receive /media/scratch/received-vol/
At subvol /media/scratch/testsnap/
At subvol testsnap

getcap /media/scratch/received-vol/testsnap/foobar 
/media/scratch/received-vol/testsnap/foobar = cap_sys_admin+ep

Everything seems to work.

@freswa
Copy link
Author

freswa commented Apr 2, 2018

I just tried kernel 4.15.15 with btrfs progs 4.15.1 and the capabilities from my example are still not transferred.

@lorddoskias
Copy link
Contributor

Is your example identical to the commands which I've executed, if yes, then it seems the problem is specific to you.

@freswa
Copy link
Author

freswa commented Apr 2, 2018

Just tried your example on a machine of a colleague. Caps are still missing.

@freswa
Copy link
Author

freswa commented Apr 2, 2018

Well, I didn't use a seperate device for the test. I tried again using a flash drive, did a mkfs.btrfs on it and the caps work there (on both machines).
stream:

# btrfs send /media/scratch/testsnap/ | btrfs receive --dump 
At subvol /media/scratch/testsnap/
subvol          ./testsnap                      uuid=daaaa373-719f-4947-8924-70876fe70b39 transid=8
chown           ./testsnap/                     gid=0 uid=0
chmod           ./testsnap/                     mode=755
utimes          ./testsnap/                     atime=2018-04-02T18:49:43+0200 mtime=2018-04-02T18:49:47+0200 ctime=2018-04-02T18:49:47+0200
mkfile          ./testsnap/o257-8-0
rename          ./testsnap/o257-8-0             dest=./testsnap/foobar
utimes          ./testsnap/                     atime=2018-04-02T18:49:43+0200 mtime=2018-04-02T18:49:47+0200 ctime=2018-04-02T18:49:47+0200
set_xattr       ./testsnap/foobar               name=security.capability data=� len=20
truncate        ./testsnap/foobar               size=0
chown           ./testsnap/foobar               gid=0 uid=0
chmod           ./testsnap/foobar               mode=644
utimes          ./testsnap/foobar               atime=2018-04-02T18:49:47+0200 mtime=2018-04-02T18:49:47+0200 ctime=2018-04-02T18:49:50+0200

strace:

# btrfs send /media/scratch/testsnap/ | strace btrfs receive /media/scratch/received-vol/
At subvol /media/scratch/testsnap/
execve("/usr/bin/btrfs", ["btrfs", "receive", "/media/scratch/received-vol/"], 0x7d61047fe350 /* 30 vars */) = 0
brk(NULL)                               = 0x26a65692a28
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=283910, ...}) = 0
mmap(NULL, 283910, PROT_READ, MAP_PRIVATE, 3, 0) = 0x65778bdde000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libuuid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\24\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=26552, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x65778bddc000
mmap(NULL, 2121752, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778b9fe000
mprotect(0x65778ba04000, 2093056, PROT_NONE) = 0
mmap(0x65778bc03000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x65778bc03000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libblkid.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\231\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=322392, ...}) = 0
mmap(NULL, 2422624, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778b7ae000
mprotect(0x65778b7f7000, 2097152, PROT_NONE) = 0
mmap(0x65778b9f7000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x49000) = 0x65778b9f7000
mmap(0x65778b9fd000, 1888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x65778b9fd000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360!\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=92056, ...}) = 0
mmap(NULL, 2187280, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778b597000
mprotect(0x65778b5ad000, 2093056, PROT_NONE) = 0
mmap(0x65778b7ac000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x65778b7ac000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/liblzo2.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20'\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=137432, ...}) = 0
mmap(NULL, 2232528, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778b375000
mprotect(0x65778b396000, 2093056, PROT_NONE) = 0
mmap(0x65778b595000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x20000) = 0x65778b595000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libzstd.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240@\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=505536, ...}) = 0
mmap(NULL, 2601008, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778b0f9000
mprotect(0x65778b174000, 2093056, PROT_NONE) = 0
mmap(0x65778b373000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7a000) = 0x65778b373000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0]\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=145336, ...}) = 0
mmap(NULL, 2216400, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778aedb000
mprotect(0x65778aef4000, 2093056, PROT_NONE) = 0
mmap(0x65778b0f3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x65778b0f3000
mmap(0x65778b0f5000, 12752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x65778b0f5000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\20\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2065784, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x65778bdda000
mmap(NULL, 3893488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x65778ab24000
mprotect(0x65778acd2000, 2093056, PROT_NONE) = 0
mmap(0x65778aed1000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ad000) = 0x65778aed1000
mmap(0x65778aed7000, 14576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x65778aed7000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x65778bdd7000
arch_prctl(ARCH_SET_FS, 0x65778bdd78c0) = 0
mprotect(0x65778aed1000, 16384, PROT_READ) = 0
mprotect(0x65778b0f3000, 4096, PROT_READ) = 0
mprotect(0x65778b373000, 4096, PROT_READ) = 0
mprotect(0x65778b595000, 4096, PROT_READ) = 0
mprotect(0x65778b7ac000, 4096, PROT_READ) = 0
mprotect(0x65778bc03000, 4096, PROT_READ) = 0
mprotect(0x65778b9f7000, 20480, PROT_READ) = 0
mprotect(0x26a53c8c000, 20480, PROT_READ) = 0
mprotect(0x65778be29000, 4096, PROT_READ) = 0
munmap(0x65778bdde000, 283910)          = 0
set_tid_address(0x65778bdd7b90)         = 7958
set_robust_list(0x65778bdd7ba0, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x65778aee0770, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x65778aeecdd0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x65778aee0810, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x65778aeecdd0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
brk(NULL)                               = 0x26a65692a28
brk(0x26a656b3a28)                      = 0x26a656b3a28
brk(0x26a656b4000)                      = 0x26a656b4000
lstat("/media", {st_mode=S_IFDIR|0755, st_size=14, ...}) = 0
lstat("/media/scratch", {st_mode=S_IFDIR|0755, st_size=54, ...}) = 0
lstat("/media/scratch/received-vol", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
openat(AT_FDCWD, "/media/scratch/received-vol", O_RDONLY|O_NOATIME) = 3
openat(AT_FDCWD, "/media/scratch/received-vol", O_RDONLY|O_NOATIME) = 4
close(4)                                = 0
open("/proc/self/mounts", O_RDONLY|O_CLOEXEC) = 4
futex(0x65778aed7fc8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(4, "proc /proc proc rw,nosuid,nodev,"..., 1024) = 1024
read(4, "oup rw,nosuid,nodev,noexec,relat"..., 1024) = 1024
read(4, "nproto=5,maxproto=5,direct 0 0\nh"..., 1024) = 1024
read(4, "ode=700,uid=1000,gid=1000 0 0\ngv"..., 1024) = 211
read(4, "", 1024)                       = 0
close(4)                                = 0
lstat("/media", {st_mode=S_IFDIR|0755, st_size=14, ...}) = 0
lstat("/media/scratch", {st_mode=S_IFDIR|0755, st_size=54, ...}) = 0
openat(AT_FDCWD, "/media/scratch", O_RDONLY|O_NOATIME) = 4
ioctl(4, BTRFS_IOC_INO_LOOKUP, {treeid=0, objectid=256 /* BTRFS_FIRST_FREE_OBJECTID */} => {treeid=5 /* BTRFS_FS_TREE_OBJECTID */, name=""}) = 0
ioctl(4, BTRFS_IOC_TREE_SEARCH, {key={tree_id=1 /* BTRFS_ROOT_TREE_OBJECTID */, min_objectid=9 /* BTRFS_UUID_TREE_OBJECTID */, max_objectid=9 /* BTRFS_UUID_TREE_OBJECTID */, max_offset=18446744073709551615 /* UINT64_MAX */, max_transid=18446744073709551615 /* UINT64_MAX */, min_type=132 /* BTRFS_ROOT_ITEM_KEY */, max_type=132 /* BTRFS_ROOT_ITEM_KEY */, nr_items=1}} => {key={nr_items=1}, buf=...}) = 0
read(0, "btrfs-stream\0\1\0\0\0", 17)   = 17
read(0, ",\0\0\0\1\0}!\321>", 10)       = 10
read(0, "\17\0\10\0testsnap\1\0\20\0\332\252\243sq\237IG\211$p\207o\347\v9"..., 44) = 44
write(2, "At subvol testsnap\n", 19At subvol testsnap
)    = 19
ioctl(3, BTRFS_IOC_SUBVOL_CREATE, {fd=0, name="testsnap"}) = 0
read(0, "\34\0\0\0\23\0\0027-\214", 10) = 10
read(0, "\17\0\0\0\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0\0\0\0\0", 28) = 28
lchown("/media/scratch/received-vol/testsnap/", 0, 0) = 0
read(0, "\20\0\0\0\22\0YUu5", 10)       = 10
read(0, "\17\0\0\0\5\0\10\0\355\1\0\0\0\0\0\0", 16) = 16
chmod("/media/scratch/received-vol/testsnap/", 0755) = 0
read(0, "4\0\0\0\24\0\6Rs\210", 10)     = 10
read(0, "\17\0\0\0\v\0\f\0'_\302Z\0\0\0\0\316>e\37\n\0\f\0+_\302Z\0\0\0\0"..., 52) = 52
utimensat(AT_FDCWD, "/media/scratch/received-vol/testsnap/", [{tv_sec=1522687783, tv_nsec=526728910} /* 2018-04-02T18:49:43.526728910+0200 */, {tv_sec=1522687787, tv_nsec=60699566} /* 2018-04-02T18:49:47.060699566+0200 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\30\0\0\0\3\0\201\230\334\2", 10) = 10
read(0, "\17\0\10\0o257-8-0\3\0\10\0\1\1\0\0\0\0\0\0", 24) = 24
creat("/media/scratch/received-vol/testsnap/o257-8-0", 0600) = 5
close(5)                                = 0
read(0, "\26\0\0\0\t\0\260`\257\v", 10) = 10
read(0, "\17\0\10\0o257-8-0\20\0\6\0foobar", 22) = 22
rename("/media/scratch/received-vol/testsnap/o257-8-0", "/media/scratch/received-vol/testsnap/foobar") = 0
read(0, "4\0\0\0\24\0\6Rs\210", 10)     = 10
read(0, "\17\0\0\0\v\0\f\0'_\302Z\0\0\0\0\316>e\37\n\0\f\0+_\302Z\0\0\0\0"..., 52) = 52
utimensat(AT_FDCWD, "/media/scratch/received-vol/testsnap/", [{tv_sec=1522687783, tv_nsec=526728910} /* 2018-04-02T18:49:43.526728910+0200 */, {tv_sec=1522687787, tv_nsec=60699566} /* 2018-04-02T18:49:47.060699566+0200 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "9\0\0\0\r\0\"\202\32\344", 10) = 10
read(0, "\17\0\6\0foobar\r\0\23\0security.capabilit"..., 57) = 57
lsetxattr("/media/scratch/received-vol/testsnap/foobar", "security.capability", "\1\0\0\2\0\0 \0\0\0\0\0\0\0\0\0\0\0\0", 20, 0) = 0
read(0, "\26\0\0\0\21\0\372\3717\312", 10) = 10
read(0, "\17\0\6\0foobar\4\0\10\0\0\0\0\0\0\0\0\0", 22) = 22
truncate("/media/scratch/received-vol/testsnap/foobar", 0) = 0
read(0, "\"\0\0\0\23\0\306\340\253Y", 10) = 10
read(0, "\17\0\6\0foobar\6\0\10\0\0\0\0\0\0\0\0\0\7\0\10\0\0\0\0\0\0\0"..., 34) = 34
lchown("/media/scratch/received-vol/testsnap/foobar", 0, 0) = 0
lsetxattr("/media/scratch/received-vol/testsnap/foobar", "security.capability", "\1\0\0\2\0\0 \0\0\0\0\0\0\0\0\0\0\0\0", 20, 0) = 0
read(0, "\26\0\0\0\22\0?\233\213h", 10) = 10
read(0, "\17\0\6\0foobar\5\0\10\0\244\1\0\0\0\0\0\0", 22) = 22
chmod("/media/scratch/received-vol/testsnap/foobar", 0644) = 0
read(0, ":\0\0\0\24\0Y\303\201\307", 10) = 10
read(0, "\17\0\6\0foobar\v\0\f\0+_\302Z\0\0\0\0\2563\236\3\n\0\f\0+_"..., 58) = 58
utimensat(AT_FDCWD, "/media/scratch/received-vol/testsnap/foobar", [{tv_sec=1522687787, tv_nsec=60699566} /* 2018-04-02T18:49:47.060699566+0200 */, {tv_sec=1522687787, tv_nsec=60699566} /* 2018-04-02T18:49:47.060699566+0200 */], AT_SYMLINK_NOFOLLOW) = 0
read(0, "\0\0\0\0\25\0Pl\311\235", 10)  = 10
openat(4, "received-vol/testsnap", O_RDONLY|O_NOATIME) = 5
ioctl(5, BTRFS_IOC_SET_RECEIVED_SUBVOL, {uuid=daaaa373-719f-4947-8924-70876fe70b39, stransid=8, stime=0.0, flags=0} => {rtransid=13, rtime=1522688059.123074793}) = 0
ioctl(5, BTRFS_IOC_SUBVOL_GETFLAGS, 0)  = 0
ioctl(5, BTRFS_IOC_SUBVOL_SETFLAGS, BTRFS_SUBVOL_RDONLY) = 0
close(5)                                = 0
read(0, "", 17)                         = 0
close(4)                                = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

@marcosps
Copy link
Contributor

marcosps commented Apr 8, 2020

This seems to be the same issue reported in #202. Can we close this one, and keep track of this issue in that bug? What do you think? Also, I'm currently working to fix this problem.

@kdave
Copy link
Owner

kdave commented Apr 8, 2020

Ok, let's use #202 for future discussions of the bug.

@kdave kdave closed this as completed Apr 8, 2020
kdave pushed a commit that referenced this issue Feb 11, 2021
We had a few bugs on the kernel side of send/receive where capabilities
ended up being lost after receiving a send stream. They all stem from the
fact that the kernel used to send all xattrs before issuing the chown
command, and the later clears any existing capabilities in a file or
directory.

Initially a workaround was added to btrfs-progs' receive command, in commit
123a2a0 ("btrfs-progs: receive: restore capabilities after chown"),
and that fixed some instances of the problem. More recently, other instances
of the problem were found, a proper fix for the kernel was made, which fixes
the root problem by making send always emit the setxattr command for setting
capabilities after issuing a chown command. This was done in kernel commit
89efda52e6b693 ("btrfs: send: emit file capabilities after chown"), which
landed in kernel 5.8.

However, the workaround on the receive command now causes us to incorrectly
set a capability on a file that should not have it, because it assumes all
setxattr commands for a file always comes before a chown.

Example reproducer:

  $ cat send-caps.sh
  #!/bin/bash

  DEV1=/dev/sdh
  DEV2=/dev/sdi

  MNT1=/mnt/sdh
  MNT2=/mnt/sdi

  mkfs.btrfs -f $DEV1 > /dev/null
  mkfs.btrfs -f $DEV2 > /dev/null

  mount $DEV1 $MNT1
  mount $DEV2 $MNT2

  touch $MNT1/foo
  touch $MNT1/bar
  setcap cap_net_raw=p $MNT1/foo

  btrfs subvolume snapshot -r $MNT1 $MNT1/snap1

  btrfs send $MNT1/snap1 | btrfs receive $MNT2

  echo
  echo "capabilities on destination filesystem:"
  echo
  getcap $MNT2/snap1/foo
  getcap $MNT2/snap1/bar

  umount $MNT1
  umount $MNT2

When running the test script, we can see that both files foo and bar get
the capability set, when only file foo should have it:

  $ ./send-caps.sh
  Create a readonly snapshot of '/mnt/sdh' in '/mnt/sdh/snap1'
  At subvol /mnt/sdh/snap1
  At subvol snap1

  capabilities on destination filesystem:

  /mnt/sdi/snap1/foo cap_net_raw=p
  /mnt/sdi/snap1/bar cap_net_raw=p

Since the kernel fix was backported to all currently supported stable
releases (5.10.x, 5.4.x, 4.19.x, 4.14.x, 4.9.x and 4.4.x), remove the
workaround from receive. Having such a workaround relying on the order
of commands in a send stream is always troublesome and doomed to break
one day.

A test case for fstests will come soon.

Issue: #85
Issue: #202
Issue: #292
Reported-by: Richard Brown <rbrown@suse.de>
Reviewed-by: Su Yue <l@damenly.su>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
kdave pushed a commit that referenced this issue Feb 19, 2021
We had a few bugs on the kernel side of send/receive where capabilities
ended up being lost after receiving a send stream. They all stem from the
fact that the kernel used to send all xattrs before issuing the chown
command, and the later clears any existing capabilities in a file or
directory.

Initially a workaround was added to btrfs-progs' receive command, in commit
123a2a0 ("btrfs-progs: receive: restore capabilities after chown"),
and that fixed some instances of the problem. More recently, other instances
of the problem were found, a proper fix for the kernel was made, which fixes
the root problem by making send always emit the setxattr command for setting
capabilities after issuing a chown command. This was done in kernel commit
89efda52e6b693 ("btrfs: send: emit file capabilities after chown"), which
landed in kernel 5.8.

However, the workaround on the receive command now causes us to incorrectly
set a capability on a file that should not have it, because it assumes all
setxattr commands for a file always comes before a chown.

Example reproducer:

  $ cat send-caps.sh
  #!/bin/bash

  DEV1=/dev/sdh
  DEV2=/dev/sdi

  MNT1=/mnt/sdh
  MNT2=/mnt/sdi

  mkfs.btrfs -f $DEV1 > /dev/null
  mkfs.btrfs -f $DEV2 > /dev/null

  mount $DEV1 $MNT1
  mount $DEV2 $MNT2

  touch $MNT1/foo
  touch $MNT1/bar
  setcap cap_net_raw=p $MNT1/foo

  btrfs subvolume snapshot -r $MNT1 $MNT1/snap1

  btrfs send $MNT1/snap1 | btrfs receive $MNT2

  echo
  echo "capabilities on destination filesystem:"
  echo
  getcap $MNT2/snap1/foo
  getcap $MNT2/snap1/bar

  umount $MNT1
  umount $MNT2

When running the test script, we can see that both files foo and bar get
the capability set, when only file foo should have it:

  $ ./send-caps.sh
  Create a readonly snapshot of '/mnt/sdh' in '/mnt/sdh/snap1'
  At subvol /mnt/sdh/snap1
  At subvol snap1

  capabilities on destination filesystem:

  /mnt/sdi/snap1/foo cap_net_raw=p
  /mnt/sdi/snap1/bar cap_net_raw=p

Since the kernel fix was backported to all currently supported stable
releases (5.10.x, 5.4.x, 4.19.x, 4.14.x, 4.9.x and 4.4.x), remove the
workaround from receive. Having such a workaround relying on the order
of commands in a send stream is always troublesome and doomed to break
one day.

A test case for fstests will come soon.

Issue: #85
Issue: #202
Issue: #292
Reported-by: Richard Brown <rbrown@suse.de>
Reviewed-by: Su Yue <l@damenly.su>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
kdave pushed a commit that referenced this issue Feb 22, 2021
We had a few bugs on the kernel side of send/receive where capabilities
ended up being lost after receiving a send stream. They all stem from the
fact that the kernel used to send all xattrs before issuing the chown
command, and the later clears any existing capabilities in a file or
directory.

Initially a workaround was added to btrfs-progs' receive command, in commit
123a2a0 ("btrfs-progs: receive: restore capabilities after chown"),
and that fixed some instances of the problem. More recently, other instances
of the problem were found, a proper fix for the kernel was made, which fixes
the root problem by making send always emit the setxattr command for setting
capabilities after issuing a chown command. This was done in kernel commit
89efda52e6b693 ("btrfs: send: emit file capabilities after chown"), which
landed in kernel 5.8.

However, the workaround on the receive command now causes us to incorrectly
set a capability on a file that should not have it, because it assumes all
setxattr commands for a file always comes before a chown.

Example reproducer:

  $ cat send-caps.sh
  #!/bin/bash

  DEV1=/dev/sdh
  DEV2=/dev/sdi

  MNT1=/mnt/sdh
  MNT2=/mnt/sdi

  mkfs.btrfs -f $DEV1 > /dev/null
  mkfs.btrfs -f $DEV2 > /dev/null

  mount $DEV1 $MNT1
  mount $DEV2 $MNT2

  touch $MNT1/foo
  touch $MNT1/bar
  setcap cap_net_raw=p $MNT1/foo

  btrfs subvolume snapshot -r $MNT1 $MNT1/snap1

  btrfs send $MNT1/snap1 | btrfs receive $MNT2

  echo
  echo "capabilities on destination filesystem:"
  echo
  getcap $MNT2/snap1/foo
  getcap $MNT2/snap1/bar

  umount $MNT1
  umount $MNT2

When running the test script, we can see that both files foo and bar get
the capability set, when only file foo should have it:

  $ ./send-caps.sh
  Create a readonly snapshot of '/mnt/sdh' in '/mnt/sdh/snap1'
  At subvol /mnt/sdh/snap1
  At subvol snap1

  capabilities on destination filesystem:

  /mnt/sdi/snap1/foo cap_net_raw=p
  /mnt/sdi/snap1/bar cap_net_raw=p

Since the kernel fix was backported to all currently supported stable
releases (5.10.x, 5.4.x, 4.19.x, 4.14.x, 4.9.x and 4.4.x), remove the
workaround from receive. Having such a workaround relying on the order
of commands in a send stream is always troublesome and doomed to break
one day.

A test case for fstests will come soon.

Issue: #85
Issue: #202
Issue: #292
Reported-by: Richard Brown <rbrown@suse.de>
Reviewed-by: Su Yue <l@damenly.su>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants