Commit 9da82b20 authored by Mickaël Salaün's avatar Mickaël Salaün

landlock: Move filesystem helpers and add a new one

Move the SB_NOUSER and IS_PRIVATE dentry check to a standalone
is_nouser_or_private() helper.  This will be useful for a following
commit.

Move get_mode_access() and maybe_remove() to make them usable by new
code provided by a following commit.
Reviewed-by: default avatarPaul Moore <paul@paul-moore.com>
Signed-off-by: default avatarMickaël Salaün <mic@digikod.net>
Link: https://lore.kernel.org/r/20220506161102.525323-6-mic@digikod.net
parent 8ba0005f
...@@ -261,6 +261,18 @@ unmask_layers(const struct landlock_rule *const rule, ...@@ -261,6 +261,18 @@ unmask_layers(const struct landlock_rule *const rule,
return false; return false;
} }
/*
* Allows access to pseudo filesystems that will never be mountable (e.g.
* sockfs, pipefs), but can still be reachable through
* /proc/<pid>/fd/<file-descriptor>
*/
static inline bool is_nouser_or_private(const struct dentry *dentry)
{
return (dentry->d_sb->s_flags & SB_NOUSER) ||
(d_is_positive(dentry) &&
unlikely(IS_PRIVATE(d_backing_inode(dentry))));
}
static int check_access_path(const struct landlock_ruleset *const domain, static int check_access_path(const struct landlock_ruleset *const domain,
const struct path *const path, const struct path *const path,
const access_mask_t access_request) const access_mask_t access_request)
...@@ -274,14 +286,7 @@ static int check_access_path(const struct landlock_ruleset *const domain, ...@@ -274,14 +286,7 @@ static int check_access_path(const struct landlock_ruleset *const domain,
return 0; return 0;
if (WARN_ON_ONCE(!domain || !path)) if (WARN_ON_ONCE(!domain || !path))
return 0; return 0;
/* if (is_nouser_or_private(path->dentry))
* Allows access to pseudo filesystems that will never be mountable
* (e.g. sockfs, pipefs), but can still be reachable through
* /proc/<pid>/fd/<file-descriptor> .
*/
if ((path->dentry->d_sb->s_flags & SB_NOUSER) ||
(d_is_positive(path->dentry) &&
unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))))
return 0; return 0;
if (WARN_ON_ONCE(domain->num_layers < 1)) if (WARN_ON_ONCE(domain->num_layers < 1))
return -EACCES; return -EACCES;
...@@ -360,6 +365,39 @@ static inline int current_check_access_path(const struct path *const path, ...@@ -360,6 +365,39 @@ static inline int current_check_access_path(const struct path *const path,
return check_access_path(dom, path, access_request); return check_access_path(dom, path, access_request);
} }
static inline access_mask_t get_mode_access(const umode_t mode)
{
switch (mode & S_IFMT) {
case S_IFLNK:
return LANDLOCK_ACCESS_FS_MAKE_SYM;
case 0:
/* A zero mode translates to S_IFREG. */
case S_IFREG:
return LANDLOCK_ACCESS_FS_MAKE_REG;
case S_IFDIR:
return LANDLOCK_ACCESS_FS_MAKE_DIR;
case S_IFCHR:
return LANDLOCK_ACCESS_FS_MAKE_CHAR;
case S_IFBLK:
return LANDLOCK_ACCESS_FS_MAKE_BLOCK;
case S_IFIFO:
return LANDLOCK_ACCESS_FS_MAKE_FIFO;
case S_IFSOCK:
return LANDLOCK_ACCESS_FS_MAKE_SOCK;
default:
WARN_ON_ONCE(1);
return 0;
}
}
static inline access_mask_t maybe_remove(const struct dentry *const dentry)
{
if (d_is_negative(dentry))
return 0;
return d_is_dir(dentry) ? LANDLOCK_ACCESS_FS_REMOVE_DIR :
LANDLOCK_ACCESS_FS_REMOVE_FILE;
}
/* Inode hooks */ /* Inode hooks */
static void hook_inode_free_security(struct inode *const inode) static void hook_inode_free_security(struct inode *const inode)
...@@ -553,31 +591,6 @@ static int hook_sb_pivotroot(const struct path *const old_path, ...@@ -553,31 +591,6 @@ static int hook_sb_pivotroot(const struct path *const old_path,
/* Path hooks */ /* Path hooks */
static inline access_mask_t get_mode_access(const umode_t mode)
{
switch (mode & S_IFMT) {
case S_IFLNK:
return LANDLOCK_ACCESS_FS_MAKE_SYM;
case 0:
/* A zero mode translates to S_IFREG. */
case S_IFREG:
return LANDLOCK_ACCESS_FS_MAKE_REG;
case S_IFDIR:
return LANDLOCK_ACCESS_FS_MAKE_DIR;
case S_IFCHR:
return LANDLOCK_ACCESS_FS_MAKE_CHAR;
case S_IFBLK:
return LANDLOCK_ACCESS_FS_MAKE_BLOCK;
case S_IFIFO:
return LANDLOCK_ACCESS_FS_MAKE_FIFO;
case S_IFSOCK:
return LANDLOCK_ACCESS_FS_MAKE_SOCK;
default:
WARN_ON_ONCE(1);
return 0;
}
}
/* /*
* Creating multiple links or renaming may lead to privilege escalations if not * Creating multiple links or renaming may lead to privilege escalations if not
* handled properly. Indeed, we must be sure that the source doesn't gain more * handled properly. Indeed, we must be sure that the source doesn't gain more
...@@ -606,14 +619,6 @@ static int hook_path_link(struct dentry *const old_dentry, ...@@ -606,14 +619,6 @@ static int hook_path_link(struct dentry *const old_dentry,
get_mode_access(d_backing_inode(old_dentry)->i_mode)); get_mode_access(d_backing_inode(old_dentry)->i_mode));
} }
static inline access_mask_t maybe_remove(const struct dentry *const dentry)
{
if (d_is_negative(dentry))
return 0;
return d_is_dir(dentry) ? LANDLOCK_ACCESS_FS_REMOVE_DIR :
LANDLOCK_ACCESS_FS_REMOVE_FILE;
}
static int hook_path_rename(const struct path *const old_dir, static int hook_path_rename(const struct path *const old_dir,
struct dentry *const old_dentry, struct dentry *const old_dentry,
const struct path *const new_dir, const struct path *const new_dir,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment