Learning objective: Follow the outline of the open syscall
Thoughts?
Get a handle to an inode
Create entry in the file descriptor table
Invoke underlying filesystem-specific code
openat(2) is preferred
force_o_largefile()Do we have ARCH_32_BIT_OFF_T
strace ./hello_world
SYSCALL_CANCEL() used for thread semanticsstruct open_howint flags and umode_t modedo_sys_open()flagsFollow symlinks in each component of patch
By default, follow for last component, unless O_NOFOLLOW
O_PATH: another exception, open path without followingRESOLVE_BENEATH: all resolutions in subtreeRESOLVE_NO_ROOT: can’t cross into another mount namespaceRESOLVE_NO_SYMLINKS: Like O_NOFOLLOW for whole path resolution processopenat2 would -EINVAL with bad flagsread, write, exec for user, group, and other
struct open_how => struct open_flags
getname called => getname_flags
copy_from_user() for filenamesWhat the heck is “omirr”
Important enough for fundamental changes to pathname lookup
kernel_clone() calls copy_process()
copy_process() calls copy_files()
path_openat()do_open()
vfs_open()struct dentry in struct pathsudo bpftrace -e 'k:do_dentry_open /comm=="kdlp_hello"/ { printf("%s\n", kstack); }'
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <linux/openat2.h>
#include <err.h>
int main(void)
{
struct open_how how = {
.flags = O_RDONLY,
.mode = 0,
.resolve = 0,
};
int fd = syscall(SYS_openat2, AT_FDCWD, "hello.txt", &how, sizeof how);
if (fd < 0)
err(1, "openat2 failed");
close(fd);
return 0;
}
Open resolves a path into an inode
An open file descriptor refers to a struct file in the current->files structure
The newer openat2 provides useful symlink resolution options
Everything is a file descriptor in Linux, and open is the first step