On Wed, Mar 31, 2021 at 07:33:50PM +0200, Mickaël Salaün wrote:
+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...
+static int check_access_path(const struct landlock_ruleset *const domain,
const struct path *const path, u32 access_request)+{
- walker_path = *path;
- path_get(&walker_path);
- 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?
+/*
- 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]
+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...