Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Landlock LSM - System call implementations and user space interfaces
0004  *
0005  * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
0006  * Copyright © 2018-2020 ANSSI
0007  */
0008 
0009 #include <asm/current.h>
0010 #include <linux/anon_inodes.h>
0011 #include <linux/build_bug.h>
0012 #include <linux/capability.h>
0013 #include <linux/compiler_types.h>
0014 #include <linux/dcache.h>
0015 #include <linux/err.h>
0016 #include <linux/errno.h>
0017 #include <linux/fs.h>
0018 #include <linux/limits.h>
0019 #include <linux/mount.h>
0020 #include <linux/path.h>
0021 #include <linux/sched.h>
0022 #include <linux/security.h>
0023 #include <linux/stddef.h>
0024 #include <linux/syscalls.h>
0025 #include <linux/types.h>
0026 #include <linux/uaccess.h>
0027 #include <uapi/linux/landlock.h>
0028 
0029 #include "cred.h"
0030 #include "fs.h"
0031 #include "limits.h"
0032 #include "ruleset.h"
0033 #include "setup.h"
0034 
0035 /**
0036  * copy_min_struct_from_user - Safe future-proof argument copying
0037  *
0038  * Extend copy_struct_from_user() to check for consistent user buffer.
0039  *
0040  * @dst: Kernel space pointer or NULL.
0041  * @ksize: Actual size of the data pointed to by @dst.
0042  * @ksize_min: Minimal required size to be copied.
0043  * @src: User space pointer or NULL.
0044  * @usize: (Alleged) size of the data pointed to by @src.
0045  */
0046 static __always_inline int
0047 copy_min_struct_from_user(void *const dst, const size_t ksize,
0048               const size_t ksize_min, const void __user *const src,
0049               const size_t usize)
0050 {
0051     /* Checks buffer inconsistencies. */
0052     BUILD_BUG_ON(!dst);
0053     if (!src)
0054         return -EFAULT;
0055 
0056     /* Checks size ranges. */
0057     BUILD_BUG_ON(ksize <= 0);
0058     BUILD_BUG_ON(ksize < ksize_min);
0059     if (usize < ksize_min)
0060         return -EINVAL;
0061     if (usize > PAGE_SIZE)
0062         return -E2BIG;
0063 
0064     /* Copies user buffer and fills with zeros. */
0065     return copy_struct_from_user(dst, ksize, src, usize);
0066 }
0067 
0068 /*
0069  * This function only contains arithmetic operations with constants, leading to
0070  * BUILD_BUG_ON().  The related code is evaluated and checked at build time,
0071  * but it is then ignored thanks to compiler optimizations.
0072  */
0073 static void build_check_abi(void)
0074 {
0075     struct landlock_ruleset_attr ruleset_attr;
0076     struct landlock_path_beneath_attr path_beneath_attr;
0077     size_t ruleset_size, path_beneath_size;
0078 
0079     /*
0080      * For each user space ABI structures, first checks that there is no
0081      * hole in them, then checks that all architectures have the same
0082      * struct size.
0083      */
0084     ruleset_size = sizeof(ruleset_attr.handled_access_fs);
0085     BUILD_BUG_ON(sizeof(ruleset_attr) != ruleset_size);
0086     BUILD_BUG_ON(sizeof(ruleset_attr) != 8);
0087 
0088     path_beneath_size = sizeof(path_beneath_attr.allowed_access);
0089     path_beneath_size += sizeof(path_beneath_attr.parent_fd);
0090     BUILD_BUG_ON(sizeof(path_beneath_attr) != path_beneath_size);
0091     BUILD_BUG_ON(sizeof(path_beneath_attr) != 12);
0092 }
0093 
0094 /* Ruleset handling */
0095 
0096 static int fop_ruleset_release(struct inode *const inode,
0097                    struct file *const filp)
0098 {
0099     struct landlock_ruleset *ruleset = filp->private_data;
0100 
0101     landlock_put_ruleset(ruleset);
0102     return 0;
0103 }
0104 
0105 static ssize_t fop_dummy_read(struct file *const filp, char __user *const buf,
0106                   const size_t size, loff_t *const ppos)
0107 {
0108     /* Dummy handler to enable FMODE_CAN_READ. */
0109     return -EINVAL;
0110 }
0111 
0112 static ssize_t fop_dummy_write(struct file *const filp,
0113                    const char __user *const buf, const size_t size,
0114                    loff_t *const ppos)
0115 {
0116     /* Dummy handler to enable FMODE_CAN_WRITE. */
0117     return -EINVAL;
0118 }
0119 
0120 /*
0121  * A ruleset file descriptor enables to build a ruleset by adding (i.e.
0122  * writing) rule after rule, without relying on the task's context.  This
0123  * reentrant design is also used in a read way to enforce the ruleset on the
0124  * current task.
0125  */
0126 static const struct file_operations ruleset_fops = {
0127     .release = fop_ruleset_release,
0128     .read = fop_dummy_read,
0129     .write = fop_dummy_write,
0130 };
0131 
0132 #define LANDLOCK_ABI_VERSION 2
0133 
0134 /**
0135  * sys_landlock_create_ruleset - Create a new ruleset
0136  *
0137  * @attr: Pointer to a &struct landlock_ruleset_attr identifying the scope of
0138  *        the new ruleset.
0139  * @size: Size of the pointed &struct landlock_ruleset_attr (needed for
0140  *        backward and forward compatibility).
0141  * @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION.
0142  *
0143  * This system call enables to create a new Landlock ruleset, and returns the
0144  * related file descriptor on success.
0145  *
0146  * If @flags is %LANDLOCK_CREATE_RULESET_VERSION and @attr is NULL and @size is
0147  * 0, then the returned value is the highest supported Landlock ABI version
0148  * (starting at 1).
0149  *
0150  * Possible returned errors are:
0151  *
0152  * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
0153  * - EINVAL: unknown @flags, or unknown access, or too small @size;
0154  * - E2BIG or EFAULT: @attr or @size inconsistencies;
0155  * - ENOMSG: empty &landlock_ruleset_attr.handled_access_fs.
0156  */
0157 SYSCALL_DEFINE3(landlock_create_ruleset,
0158         const struct landlock_ruleset_attr __user *const, attr,
0159         const size_t, size, const __u32, flags)
0160 {
0161     struct landlock_ruleset_attr ruleset_attr;
0162     struct landlock_ruleset *ruleset;
0163     int err, ruleset_fd;
0164 
0165     /* Build-time checks. */
0166     build_check_abi();
0167 
0168     if (!landlock_initialized)
0169         return -EOPNOTSUPP;
0170 
0171     if (flags) {
0172         if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr &&
0173             !size)
0174             return LANDLOCK_ABI_VERSION;
0175         return -EINVAL;
0176     }
0177 
0178     /* Copies raw user space buffer. */
0179     err = copy_min_struct_from_user(&ruleset_attr, sizeof(ruleset_attr),
0180                     offsetofend(typeof(ruleset_attr),
0181                             handled_access_fs),
0182                     attr, size);
0183     if (err)
0184         return err;
0185 
0186     /* Checks content (and 32-bits cast). */
0187     if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_ACCESS_FS) !=
0188         LANDLOCK_MASK_ACCESS_FS)
0189         return -EINVAL;
0190 
0191     /* Checks arguments and transforms to kernel struct. */
0192     ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs);
0193     if (IS_ERR(ruleset))
0194         return PTR_ERR(ruleset);
0195 
0196     /* Creates anonymous FD referring to the ruleset. */
0197     ruleset_fd = anon_inode_getfd("[landlock-ruleset]", &ruleset_fops,
0198                       ruleset, O_RDWR | O_CLOEXEC);
0199     if (ruleset_fd < 0)
0200         landlock_put_ruleset(ruleset);
0201     return ruleset_fd;
0202 }
0203 
0204 /*
0205  * Returns an owned ruleset from a FD. It is thus needed to call
0206  * landlock_put_ruleset() on the return value.
0207  */
0208 static struct landlock_ruleset *get_ruleset_from_fd(const int fd,
0209                             const fmode_t mode)
0210 {
0211     struct fd ruleset_f;
0212     struct landlock_ruleset *ruleset;
0213 
0214     ruleset_f = fdget(fd);
0215     if (!ruleset_f.file)
0216         return ERR_PTR(-EBADF);
0217 
0218     /* Checks FD type and access right. */
0219     if (ruleset_f.file->f_op != &ruleset_fops) {
0220         ruleset = ERR_PTR(-EBADFD);
0221         goto out_fdput;
0222     }
0223     if (!(ruleset_f.file->f_mode & mode)) {
0224         ruleset = ERR_PTR(-EPERM);
0225         goto out_fdput;
0226     }
0227     ruleset = ruleset_f.file->private_data;
0228     if (WARN_ON_ONCE(ruleset->num_layers != 1)) {
0229         ruleset = ERR_PTR(-EINVAL);
0230         goto out_fdput;
0231     }
0232     landlock_get_ruleset(ruleset);
0233 
0234 out_fdput:
0235     fdput(ruleset_f);
0236     return ruleset;
0237 }
0238 
0239 /* Path handling */
0240 
0241 /*
0242  * @path: Must call put_path(@path) after the call if it succeeded.
0243  */
0244 static int get_path_from_fd(const s32 fd, struct path *const path)
0245 {
0246     struct fd f;
0247     int err = 0;
0248 
0249     BUILD_BUG_ON(!__same_type(
0250         fd, ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
0251 
0252     /* Handles O_PATH. */
0253     f = fdget_raw(fd);
0254     if (!f.file)
0255         return -EBADF;
0256     /*
0257      * Forbids ruleset FDs, internal filesystems (e.g. nsfs), including
0258      * pseudo filesystems that will never be mountable (e.g. sockfs,
0259      * pipefs).
0260      */
0261     if ((f.file->f_op == &ruleset_fops) ||
0262         (f.file->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
0263         (f.file->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
0264         d_is_negative(f.file->f_path.dentry) ||
0265         IS_PRIVATE(d_backing_inode(f.file->f_path.dentry))) {
0266         err = -EBADFD;
0267         goto out_fdput;
0268     }
0269     *path = f.file->f_path;
0270     path_get(path);
0271 
0272 out_fdput:
0273     fdput(f);
0274     return err;
0275 }
0276 
0277 /**
0278  * sys_landlock_add_rule - Add a new rule to a ruleset
0279  *
0280  * @ruleset_fd: File descriptor tied to the ruleset that should be extended
0281  *      with the new rule.
0282  * @rule_type: Identify the structure type pointed to by @rule_attr (only
0283  *             LANDLOCK_RULE_PATH_BENEATH for now).
0284  * @rule_attr: Pointer to a rule (only of type &struct
0285  *             landlock_path_beneath_attr for now).
0286  * @flags: Must be 0.
0287  *
0288  * This system call enables to define a new rule and add it to an existing
0289  * ruleset.
0290  *
0291  * Possible returned errors are:
0292  *
0293  * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
0294  * - EINVAL: @flags is not 0, or inconsistent access in the rule (i.e.
0295  *   &landlock_path_beneath_attr.allowed_access is not a subset of the
0296  *   ruleset handled accesses);
0297  * - ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access);
0298  * - EBADF: @ruleset_fd is not a file descriptor for the current thread, or a
0299  *   member of @rule_attr is not a file descriptor as expected;
0300  * - EBADFD: @ruleset_fd is not a ruleset file descriptor, or a member of
0301  *   @rule_attr is not the expected file descriptor type;
0302  * - EPERM: @ruleset_fd has no write access to the underlying ruleset;
0303  * - EFAULT: @rule_attr inconsistency.
0304  */
0305 SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
0306         const enum landlock_rule_type, rule_type,
0307         const void __user *const, rule_attr, const __u32, flags)
0308 {
0309     struct landlock_path_beneath_attr path_beneath_attr;
0310     struct path path;
0311     struct landlock_ruleset *ruleset;
0312     int res, err;
0313 
0314     if (!landlock_initialized)
0315         return -EOPNOTSUPP;
0316 
0317     /* No flag for now. */
0318     if (flags)
0319         return -EINVAL;
0320 
0321     /* Gets and checks the ruleset. */
0322     ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_WRITE);
0323     if (IS_ERR(ruleset))
0324         return PTR_ERR(ruleset);
0325 
0326     if (rule_type != LANDLOCK_RULE_PATH_BENEATH) {
0327         err = -EINVAL;
0328         goto out_put_ruleset;
0329     }
0330 
0331     /* Copies raw user space buffer, only one type for now. */
0332     res = copy_from_user(&path_beneath_attr, rule_attr,
0333                  sizeof(path_beneath_attr));
0334     if (res) {
0335         err = -EFAULT;
0336         goto out_put_ruleset;
0337     }
0338 
0339     /*
0340      * Informs about useless rule: empty allowed_access (i.e. deny rules)
0341      * are ignored in path walks.
0342      */
0343     if (!path_beneath_attr.allowed_access) {
0344         err = -ENOMSG;
0345         goto out_put_ruleset;
0346     }
0347     /*
0348      * Checks that allowed_access matches the @ruleset constraints
0349      * (ruleset->fs_access_masks[0] is automatically upgraded to 64-bits).
0350      */
0351     if ((path_beneath_attr.allowed_access | ruleset->fs_access_masks[0]) !=
0352         ruleset->fs_access_masks[0]) {
0353         err = -EINVAL;
0354         goto out_put_ruleset;
0355     }
0356 
0357     /* Gets and checks the new rule. */
0358     err = get_path_from_fd(path_beneath_attr.parent_fd, &path);
0359     if (err)
0360         goto out_put_ruleset;
0361 
0362     /* Imports the new rule. */
0363     err = landlock_append_fs_rule(ruleset, &path,
0364                       path_beneath_attr.allowed_access);
0365     path_put(&path);
0366 
0367 out_put_ruleset:
0368     landlock_put_ruleset(ruleset);
0369     return err;
0370 }
0371 
0372 /* Enforcement */
0373 
0374 /**
0375  * sys_landlock_restrict_self - Enforce a ruleset on the calling thread
0376  *
0377  * @ruleset_fd: File descriptor tied to the ruleset to merge with the target.
0378  * @flags: Must be 0.
0379  *
0380  * This system call enables to enforce a Landlock ruleset on the current
0381  * thread.  Enforcing a ruleset requires that the task has CAP_SYS_ADMIN in its
0382  * namespace or is running with no_new_privs.  This avoids scenarios where
0383  * unprivileged tasks can affect the behavior of privileged children.
0384  *
0385  * Possible returned errors are:
0386  *
0387  * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
0388  * - EINVAL: @flags is not 0.
0389  * - EBADF: @ruleset_fd is not a file descriptor for the current thread;
0390  * - EBADFD: @ruleset_fd is not a ruleset file descriptor;
0391  * - EPERM: @ruleset_fd has no read access to the underlying ruleset, or the
0392  *   current thread is not running with no_new_privs, or it doesn't have
0393  *   CAP_SYS_ADMIN in its namespace.
0394  * - E2BIG: The maximum number of stacked rulesets is reached for the current
0395  *   thread.
0396  */
0397 SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
0398         flags)
0399 {
0400     struct landlock_ruleset *new_dom, *ruleset;
0401     struct cred *new_cred;
0402     struct landlock_cred_security *new_llcred;
0403     int err;
0404 
0405     if (!landlock_initialized)
0406         return -EOPNOTSUPP;
0407 
0408     /*
0409      * Similar checks as for seccomp(2), except that an -EPERM may be
0410      * returned.
0411      */
0412     if (!task_no_new_privs(current) &&
0413         !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
0414         return -EPERM;
0415 
0416     /* No flag for now. */
0417     if (flags)
0418         return -EINVAL;
0419 
0420     /* Gets and checks the ruleset. */
0421     ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_READ);
0422     if (IS_ERR(ruleset))
0423         return PTR_ERR(ruleset);
0424 
0425     /* Prepares new credentials. */
0426     new_cred = prepare_creds();
0427     if (!new_cred) {
0428         err = -ENOMEM;
0429         goto out_put_ruleset;
0430     }
0431     new_llcred = landlock_cred(new_cred);
0432 
0433     /*
0434      * There is no possible race condition while copying and manipulating
0435      * the current credentials because they are dedicated per thread.
0436      */
0437     new_dom = landlock_merge_ruleset(new_llcred->domain, ruleset);
0438     if (IS_ERR(new_dom)) {
0439         err = PTR_ERR(new_dom);
0440         goto out_put_creds;
0441     }
0442 
0443     /* Replaces the old (prepared) domain. */
0444     landlock_put_ruleset(new_llcred->domain);
0445     new_llcred->domain = new_dom;
0446 
0447     landlock_put_ruleset(ruleset);
0448     return commit_creds(new_cred);
0449 
0450 out_put_creds:
0451     abort_creds(new_cred);
0452 
0453 out_put_ruleset:
0454     landlock_put_ruleset(ruleset);
0455     return err;
0456 }