]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - security/security.c
UBUNTU: Ubuntu-5.15.0-39.42
[mirror_ubuntu-jammy-kernel.git] / security / security.c
index 293163fb03f7155589ad3c3b4c15677665fb65c8..8ecd012e0bffe0da5e0ccc344978c1de5556f1f6 100644 (file)
@@ -60,6 +60,7 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_DEBUGFS] = "debugfs access",
        [LOCKDOWN_XMON_WR] = "xmon write access",
        [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
+       [LOCKDOWN_KGDB] = "KDB or KGDB access",
        [LOCKDOWN_INTEGRITY_MAX] = "integrity",
        [LOCKDOWN_KCORE] = "/proc/kcore access",
        [LOCKDOWN_KPROBES] = "use of kprobes",
@@ -759,6 +760,57 @@ static void __init lsm_early_task(struct task_struct *task)
                panic("%s: Early task alloc failed.\n", __func__);
 }
 
+/**
+ * append_ctx - append a lsm/context pair to a compound context
+ * @ctx: the existing compound context
+ * @ctxlen: size of the old context, including terminating nul byte
+ * @lsm: new lsm name, nul terminated
+ * @new: new context, possibly nul terminated
+ * @newlen: maximum size of @new
+ *
+ * replace @ctx with a new compound context, appending @newlsm and @new
+ * to @ctx. On exit the new data replaces the old, which is freed.
+ * @ctxlen is set to the new size, which includes a trailing nul byte.
+ *
+ * Returns 0 on success, -ENOMEM if no memory is available.
+ */
+static int append_ctx(char **ctx, int *ctxlen, const char *lsm, char *new,
+                     int newlen)
+{
+       char *final;
+       size_t llen;
+       size_t nlen;
+       size_t flen;
+
+       llen = strlen(lsm) + 1;
+       /*
+        * A security module may or may not provide a trailing nul on
+        * when returning a security context. There is no definition
+        * of which it should be, and there are modules that do it
+        * each way.
+        */
+       nlen = strnlen(new, newlen);
+
+       flen = *ctxlen + llen + nlen + 1;
+       final = kzalloc(flen, GFP_KERNEL);
+
+       if (final == NULL)
+               return -ENOMEM;
+
+       if (*ctxlen)
+               memcpy(final, *ctx, *ctxlen);
+
+       memcpy(final + *ctxlen, lsm, llen);
+       memcpy(final + *ctxlen + llen, new, nlen);
+
+       kfree(*ctx);
+
+       *ctx = final;
+       *ctxlen = flen;
+
+       return 0;
+}
+
 /**
  * lsm_superblock_alloc - allocate a composite superblock blob
  * @sb: the superblock that needs a blob
@@ -833,7 +885,7 @@ static int lsm_superblock_alloc(struct super_block *sb)
 
 /* Security operations */
 
-int security_binder_set_context_mgr(struct task_struct *mgr)
+int security_binder_set_context_mgr(const struct cred *mgr)
 {
        return call_int_hook(binder_set_context_mgr, 0, mgr);
 }
@@ -844,17 +896,17 @@ EXPORT_SYMBOL(security_binder_set_context_mgr);
  * @from: source of the transaction
  * @to: destination of the transaction
  *
- * Verify that the tasks have the same LSM "display", then
+ * Verify that the creds have the same LSM "display", then
  * call the security module hooks.
  *
  * Returns -EINVAL if the displays don't match, or the
  * result of the security module checks.
  */
-int security_binder_transaction(struct task_struct *from,
-                               struct task_struct *to)
+int security_binder_transaction(const struct cred *from,
+                               const struct cred *to)
 {
-       int from_display = lsm_task_display(from);
-       int to_display = lsm_task_display(to);
+       int from_display = lsm_cred_display(from);
+       int to_display = lsm_cred_display(to);
 
        /*
         * If the display is LSMBLOB_INVALID the first module that has
@@ -875,15 +927,15 @@ int security_binder_transaction(struct task_struct *from,
 }
 EXPORT_SYMBOL(security_binder_transaction);
 
-int security_binder_transfer_binder(struct task_struct *from,
-                                   struct task_struct *to)
+int security_binder_transfer_binder(const struct cred *from,
+                                   const struct cred *to)
 {
        return call_int_hook(binder_transfer_binder, 0, from, to);
 }
 EXPORT_SYMBOL(security_binder_transfer_binder);
 
-int security_binder_transfer_file(struct task_struct *from,
-                                 struct task_struct *to, struct file *file)
+int security_binder_transfer_file(const struct cred *from,
+                                 const struct cred *to, struct file *file)
 {
        return call_int_hook(binder_transfer_file, 0, from, to, file);
 }
@@ -1003,9 +1055,22 @@ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
        return call_int_hook(fs_context_dup, 0, fc, src_fc);
 }
 
-int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)
+int security_fs_context_parse_param(struct fs_context *fc,
+                                   struct fs_parameter *param)
 {
-       return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param);
+       struct security_hook_list *hp;
+       int trc;
+       int rc = -ENOPARAM;
+
+       hlist_for_each_entry(hp, &security_hook_heads.fs_context_parse_param,
+                            list) {
+               trc = hp->hook.fs_context_parse_param(fc, param);
+               if (trc == 0)
+                       rc = 0;
+               else if (trc != -ENOPARAM)
+                       return trc;
+       }
+       return rc;
 }
 
 int security_sb_alloc(struct super_block *sb)
@@ -1266,6 +1331,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
                return 0;
        return call_int_hook(path_rmdir, 0, dir, dentry);
 }
+EXPORT_SYMBOL_GPL(security_path_rmdir);
 
 int security_path_unlink(const struct path *dir, struct dentry *dentry)
 {
@@ -1282,6 +1348,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
                return 0;
        return call_int_hook(path_symlink, 0, dir, dentry, old_name);
 }
+EXPORT_SYMBOL_GPL(security_path_symlink);
 
 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
                       struct dentry *new_dentry)
@@ -1290,6 +1357,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
                return 0;
        return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
 }
+EXPORT_SYMBOL_GPL(security_path_link);
 
 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
                         const struct path *new_dir, struct dentry *new_dentry,
@@ -1317,6 +1385,7 @@ int security_path_truncate(const struct path *path)
                return 0;
        return call_int_hook(path_truncate, 0, path);
 }
+EXPORT_SYMBOL_GPL(security_path_truncate);
 
 int security_path_chmod(const struct path *path, umode_t mode)
 {
@@ -1324,6 +1393,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
                return 0;
        return call_int_hook(path_chmod, 0, path, mode);
 }
+EXPORT_SYMBOL_GPL(security_path_chmod);
 
 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
 {
@@ -1331,6 +1401,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
                return 0;
        return call_int_hook(path_chown, 0, path, uid, gid);
 }
+EXPORT_SYMBOL_GPL(security_path_chown);
 
 int security_path_chroot(const struct path *path)
 {
@@ -1431,6 +1502,7 @@ int security_inode_permission(struct inode *inode, int mask)
                return 0;
        return call_int_hook(inode_permission, 0, inode, mask);
 }
+EXPORT_SYMBOL_GPL(security_inode_permission);
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
@@ -1635,6 +1707,7 @@ int security_file_permission(struct file *file, int mask)
 
        return fsnotify_perm(file, mask);
 }
+EXPORT_SYMBOL_GPL(security_file_permission);
 
 int security_file_alloc(struct file *file)
 {
@@ -2216,6 +2289,10 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
                                char **value)
 {
        struct security_hook_list *hp;
+       char *final = NULL;
+       char *cp;
+       int rc = 0;
+       int finallen = 0;
        int display = lsm_task_display(current);
        int slot = 0;
 
@@ -2243,6 +2320,30 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
                return -ENOMEM;
        }
 
+       if (!strcmp(name, "context")) {
+               hlist_for_each_entry(hp, &security_hook_heads.getprocattr,
+                                    list) {
+                       rc = hp->hook.getprocattr(p, "context", &cp);
+                       if (rc == -EINVAL)
+                               continue;
+                       if (rc < 0) {
+                               kfree(final);
+                               return rc;
+                       }
+                       rc = append_ctx(&final, &finallen, hp->lsmid->lsm,
+                                       cp, rc);
+                       kfree(cp);
+                       if (rc < 0) {
+                               kfree(final);
+                               return rc;
+                       }
+               }
+               if (final == NULL)
+                       return -EINVAL;
+               *value = final;
+               return finallen;
+       }
+
        hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
                if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
                        continue;
@@ -2984,6 +3085,12 @@ int security_locked_down(enum lockdown_reason what)
 }
 EXPORT_SYMBOL(security_locked_down);
 
+int security_lock_kernel_down(const char *where, enum lockdown_reason level)
+{
+       return call_int_hook(lock_kernel_down, 0, where, level);
+}
+EXPORT_SYMBOL(security_lock_kernel_down);
+
 #ifdef CONFIG_PERF_EVENTS
 int security_perf_event_open(struct perf_event_attr *attr, int type)
 {