On Tue, Oct 18, 2022 at 06:42:04PM -0600, Daniel Xu wrote: > Hi, > > (Going off get_maintainers.pl for fs/namei.c here) > > I'm seeing some weird interactions with file capabilities and S_IRUSR > procfs files. Best I can tell it doesn't occur with real files on my btrfs > home partition. > > Test program: > > #include <fcntl.h> > #include <stdio.h> > > int main() > { > int fd = open("/proc/self/auxv", O_RDONLY); > if (fd < 0) { > perror("open"); > return 1; > } > > printf("ok\n"); > return 0; > } > > Steps to reproduce: > > $ gcc main.c > $ ./a.out > ok > $ sudo setcap "cap_net_admin,cap_sys_admin+p" a.out > $ ./a.out > open: Permission denied > > It's not obvious why this happens, even after spending a few hours > going through the standard documentation and kernel code. It's > intuitively odd b/c you'd think adding capabilities to the permitted > set wouldn't affect functionality. > > Best I could tell the -EACCES error occurs in the fallthrough codepath > inside generic_permission(). > > Sorry if this is something dumb or obvious. Hey Daniel, No, this is neither dumb nor obvious. :) Basically, if you set fscaps then /proc/self/auxv will be owned by root:root. You can verify this: #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> #include <unistd.h> int main() { struct stat st; printf("%d | %d\n", getuid(), geteuid()); if (stat("/proc/self/auxv", &st)) { fprintf(stderr, "stat: %d - %m\n", errno); return 1; } printf("stat: %d | %d\n", st.st_uid, st.st_gid); int fd = open("/proc/self/auxv", O_RDONLY); if (fd < 0) { fprintf(stderr, "open: %d - %m\n", errno); return 1; } printf("ok\n"); return 0; } $ ./a.out 1000 | 1000 stat: 1000 | 1000 ok $ sudo setcap "cap_net_admin,cap_sys_admin+p" a.out $ ./a.out 1000 | 1000 stat: 0 | 0 open: 13 - Permission denied So acl_permission_check() fails and returns -EACCESS which will cause generic_permission() to rely on capable_wrt_inode_uidgid() which checks for CAP_DAC_READ_SEARCH which you don't have as an unprivileged user.