[PATCH v38 20/39] LSM: Specify which LSM to display
Mickaël Salaün
mic at digikod.net
Wed Oct 12 21:19:35 UTC 2022
On 27/09/2022 21:54, Casey Schaufler wrote:
> Create two new prctl() options PR_LSM_ATTR_SET and PR_LSM_ATTR_GET
> which change and report the Interface LSM respectively.
>
> The LSM ID number of an active LSM that supplies hooks for
> human readable data may be passed in the arg2 value with the
> PR_LSM_ATTR_SET option. The PR_LSM_ATT_GET option returns the
> LSM ID currently in use. At this point there can only be one LSM
> capable of display active. A helper function lsm_task_ilsm() is
> provided to get the interface lsm slot for a task_struct.
>
> Security modules that wish to restrict this action may provide
> a task_prctl hook to do so. Each such security module is
> responsible for defining its policy.
>
> AppArmor hook initially provided by John Johansen
> <john.johansen at canonical.com>. SELinux hook initially provided by
> Stephen Smalley <stephen.smalley.work at gmail.com>
>
> Signed-off-by: Casey Schaufler <casey at schaufler-ca.com>
> ---
[...]
> diff --git a/security/security.c b/security/security.c
> index 80133d6e982c..43d2431dbda0 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -28,6 +28,7 @@
> #include <linux/backing-dev.h>
> #include <linux/string.h>
> #include <linux/msg.h>
> +#include <linux/prctl.h>
> #include <uapi/linux/lsm.h>
> #include <net/flow.h>
> #include <net/sock.h>
> @@ -81,7 +82,16 @@ static struct kmem_cache *lsm_file_cache;
> static struct kmem_cache *lsm_inode_cache;
>
> char *lsm_names;
> -static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
> +
> +/*
> + * The task blob includes the "interface_lsm" slot used for
> + * chosing which module presents contexts.
> + * Using a long to avoid potential alignment issues with
> + * module assigned task blobs.
> + */
> +static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
> + .lbs_task = sizeof(long),
> +};
>
> /* Boot-time LSM user choice */
> static __initdata const char *chosen_lsm_order;
> @@ -691,6 +701,8 @@ int lsm_inode_alloc(struct inode *inode)
> */
> static int lsm_task_alloc(struct task_struct *task)
> {
> + int *ilsm;
> +
> if (blob_sizes.lbs_task == 0) {
> task->security = NULL;
> return 0;
> @@ -699,6 +711,15 @@ static int lsm_task_alloc(struct task_struct *task)
> task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
> if (task->security == NULL)
> return -ENOMEM;
> +
> + /*
> + * The start of the task blob contains the "interface" LSM slot number.
> + * Start with it set to the invalid slot number, indicating that the
> + * default first registered LSM be displayed.
> + */
> + ilsm = task->security;
> + *ilsm = LSMBLOB_INVALID;
> +
> return 0;
> }
>
> @@ -1765,14 +1786,26 @@ int security_file_open(struct file *file)
>
> int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
> {
> + int *oilsm = current->security;
> + int *nilsm;
> int rc = lsm_task_alloc(task);
>
> - if (rc)
> + if (unlikely(rc))
> return rc;
> +
> rc = call_int_hook(task_alloc, 0, task, clone_flags);
> - if (unlikely(rc))
> + if (unlikely(rc)) {
> security_task_free(task);
> - return rc;
> + return rc;
> + }
> +
> + if (oilsm) {
> + nilsm = task->security;
> + if (nilsm)
> + *nilsm = *oilsm;
> + }
> +
> + return 0;
> }
>
> void security_task_free(struct task_struct *task)
> @@ -2031,10 +2064,15 @@ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info,
> int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
> unsigned long arg4, unsigned long arg5)
> {
> + int *ilsm = current->security;
> int thisrc;
> + int slot;
> int rc = LSM_RET_DEFAULT(task_prctl);
> struct security_hook_list *hp;
>
> + if (lsm_slot == 0)
> + return -EINVAL;
> +
> hlist_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
> thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5);
> if (thisrc != LSM_RET_DEFAULT(task_prctl)) {
> @@ -2043,6 +2081,25 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
> break;
> }
> }
> +
> + switch (option) {
> + case PR_LSM_ATTR_SET:
> + if (rc && rc != LSM_RET_DEFAULT(task_prctl))
> + return rc;
> + for (slot = 0; slot < lsm_slot; slot++)
> + if (lsm_slotlist[slot]->id == arg2) {
This doesn't build if LSMBLOB_ENTRIES == 0
> + *ilsm = lsm_slotlist[slot]->slot;
> + return 0;
> + }
> + return -EINVAL;
> + case PR_LSM_ATTR_GET:
> + if (rc && rc != LSM_RET_DEFAULT(task_prctl))
> + return rc;
> + if (*ilsm != LSMBLOB_INVALID)
> + return lsm_slotlist[*ilsm]->id;
> + return lsm_slotlist[0]->id;
> + }
> +
> return rc;
> }
>
More information about the Linux-security-module-archive
mailing list