Sample Header Ad - 728x90

When (and how) are file permission/access decisions made in kernel space?

4 votes
1 answer
400 views
(I think) I have a relatively good understanding of how Linux permissions work - traditional Unix DAC permissions, and how they're represented, security context in relation to processes (i.e. cred struct, capabilities, etc.), hooks for LSMs, etc., and the link they have to (E)UID/E(GID), etc. What I don't understand, and am having difficulty finding in kernel code, and from using
(via
-cmd
), is when these checks are actually done (presumably) in kernel space, and at *which point* the access decision is actually made. To elaborate: I have a root-owned directory
/dir
chmod-ed to
-x------
(*500*). As an unprivileged user, I run
/bin/ls /dir
and receive a permission denied error, as expected. If I run
-s 10000 /bin/ls /dir
I can see the
syscall, which returns a
-1
back to user space, and sets
to
(i.e. "permission denied"). There's then a subsequent
syscall to print the error message to STDERR, all as expected. At no point here do I ever see
or
syscalls being called. If I run the same test using trace-cmd, as
-cmd record -p function_graph -F /bin/ls
with the same unprivileged user doing
/bin/ls /dir
in a separate terminal tab (where
-cmd
will trigger on the execution of the
binary), I can basically map most of the syscalls I'm seeing, one-to-one, between strace and trace-cmd outputs. However, the discrepancy is that, in the trace-cmd output after the
syscall, rather than seeing the write outputs and it exiting, I can see
calls being made (and the full call tree of iterating over items in the directory, etc.). Because of limitations with ftrace, I guess (and more likely limitations in my understanding), I'm not seeing syscall arguments or returns in the output, so I can't see when, if at all, I'm getting permission errors, but from my limited understanding, the kernel appears to be actually doing the full directory listing, but just not returning the output back to user space. So can anyone explain what's actually happening - why
-cmd
shows the kernel actually doing the
syscalls, while
exits after the open call fails? Most of the forum posts (on here and elsewhere) with questions pertaining to permissions suggest that checks are done on opening the file, but provide little more detail than that, though this aligns with what I can see with
(but not
/
-cmd
). Looking at the kernel source, and following that through manually from the
/
syscalls, I can see functions call sequences such as
-> do_inode_permission -> generic_permission -> acl_permission_check
with the latter actually doing comparisons on the classic Unix permissions, and returning from this. I can also see the hooks elsewhere for the LSMs, like SELinux, Apparmor, SMACK, Tomoyo, etc., which I guess will do their bits. My assumption would be that the directory is attempted to be opened, permission checks would happen, kernel says no, and returns the error back to user space, and it would never get to the point of actually doing the directory listing. However, based on the
-cmd
output appearing to actually show the directory listing happening, I'm not sure any more. Any information - in as much technical depth as possible - would be greatly appreciated. Also, I understand that using Systemtap may be able to offer more information to me, but my knowledge of that is *very* limited! For awareness, my testing has been on Kernel versions 2.6.35 and 6.5.0 on Debian-based distros, with comparatively similar results.
Asked by genericuser99 (119 rep)
Mar 26, 2024, 12:39 PM
Last activity: Mar 26, 2024, 06:23 PM