Re: [PATCH v31 07/12] landlock: Support filesystem access-control
From: Al Viro <viro@zeniv.linux.org.uk>
Date: 2021-04-01 02:16:02
Also in:
linux-arch, linux-doc, linux-fsdevel, linux-kselftest, linux-security-module, lkml
On Wed, Mar 31, 2021 at 07:33:50PM +0200, Mickaël Salaün wrote:
quoted
+static inline u64 unmask_layers( + const struct landlock_ruleset *const domain, + const struct path *const path, const u32 access_request, + u64 layer_mask) +{ + const struct landlock_rule *rule; + const struct inode *inode; + size_t i; + + if (d_is_negative(path->dentry)) + /* Continues to walk while there is no mapped inode. */
^^^^^ Odd comment, that...
quoted
+static int check_access_path(const struct landlock_ruleset *const domain, + const struct path *const path, u32 access_request) +{
quoted
+ walker_path = *path; + path_get(&walker_path);
quoted
+ while (true) { + struct dentry *parent_dentry; + + layer_mask = unmask_layers(domain, &walker_path, + access_request, layer_mask); + if (layer_mask == 0) { + /* Stops when a rule from each layer grants access. */ + allowed = true; + break; + } + +jump_up: + if (walker_path.dentry == walker_path.mnt->mnt_root) { + if (follow_up(&walker_path)) { + /* Ignores hidden mount points. */ + goto jump_up; + } else { + /* + * Stops at the real root. Denies access + * because not all layers have granted access. + */ + allowed = false; + break; + } + } + if (unlikely(IS_ROOT(walker_path.dentry))) { + /* + * Stops at disconnected root directories. Only allows + * access to internal filesystems (e.g. nsfs, which is + * reachable through /proc/<pid>/ns/<namespace>). + */ + allowed = !!(walker_path.mnt->mnt_flags & MNT_INTERNAL); + break; + } + parent_dentry = dget_parent(walker_path.dentry); + dput(walker_path.dentry); + walker_path.dentry = parent_dentry; + } + path_put(&walker_path); + return allowed ? 0 : -EACCES;
That's a whole lot of grabbing/dropping references... I realize that it's an utterly tactless question, but... how costly it is? IOW, do you have profiling data?
quoted
+/* + * pivot_root(2), like mount(2), changes the current mount namespace. It must + * then be forbidden for a landlocked process.
... and cross-directory rename(2) can change the tree topology. Do you ban that as well? [snip]
quoted
+static int hook_path_rename(const struct path *const old_dir, + struct dentry *const old_dentry, + const struct path *const new_dir, + struct dentry *const new_dentry) +{ + const struct landlock_ruleset *const dom = + landlock_get_current_domain(); + + if (!dom) + return 0; + /* The mount points are the same for old and new paths, cf. EXDEV. */ + if (old_dir->dentry != new_dir->dentry) + /* For now, forbids reparenting. */ + return -EACCES;
You do, apparently, and not in a way that would have the userland fall back to copy+unlink. Lovely... Does e.g. git survive such restriction? Same question for your average package build...