Re: [PATCH v7 07/11] LSM: Helpers for attribute names and filling an lsm_ctx
From: Casey Schaufler
Date: Fri Mar 31 2023 - 16:22:24 EST
On 3/31/2023 12:24 PM, Paul Moore wrote:
> On Fri, Mar 31, 2023 at 12:56 PM Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote:
>> On 3/30/2023 4:28 PM, Paul Moore wrote:
>>> On Thu, Mar 30, 2023 at 4:42 PM Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote:
>>>> On 3/29/2023 6:13 PM, Paul Moore wrote:
>>>>> On Wed, Mar 15, 2023 at 6:50 PM Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote:
>>>>>> Add lsm_name_to_attr(), which translates a text string to a
>>>>>> LSM_ATTR value if one is available.
>>>>>>
>>>>>> Add lsm_fill_user_ctx(), which fills a struct lsm_ctx, including
>>>>>> the trailing attribute value.
>>>>>>
>>>>>> All are used in module specific components of LSM system calls.
>>>>>>
>>>>>> Signed-off-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx>
>>>>>> ---
>>>>>> include/linux/security.h | 13 ++++++++++
>>>>>> security/lsm_syscalls.c | 51 ++++++++++++++++++++++++++++++++++++++++
>>>>>> security/security.c | 31 ++++++++++++++++++++++++
>>>>>> 3 files changed, 95 insertions(+)
>>>>> ..
>>>>>
>>>>>> diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
>>>>>> index 6efbe244d304..55d849ad5d6e 100644
>>>>>> --- a/security/lsm_syscalls.c
>>>>>> +++ b/security/lsm_syscalls.c
>>>>>> @@ -17,6 +17,57 @@
>>>>>> #include <linux/lsm_hooks.h>
>>>>>> #include <uapi/linux/lsm.h>
>>>>>>
>>>>>> +struct attr_map {
>>>>>> + char *name;
>>>>>> + u64 attr;
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attr_map lsm_attr_names[] = {
>>>>>> + {
>>>>>> + .name = "current",
>>>>>> + .attr = LSM_ATTR_CURRENT,
>>>>>> + },
>>>>>> + {
>>>>>> + .name = "exec",
>>>>>> + .attr = LSM_ATTR_EXEC,
>>>>>> + },
>>>>>> + {
>>>>>> + .name = "fscreate",
>>>>>> + .attr = LSM_ATTR_FSCREATE,
>>>>>> + },
>>>>>> + {
>>>>>> + .name = "keycreate",
>>>>>> + .attr = LSM_ATTR_KEYCREATE,
>>>>>> + },
>>>>>> + {
>>>>>> + .name = "prev",
>>>>>> + .attr = LSM_ATTR_PREV,
>>>>>> + },
>>>>>> + {
>>>>>> + .name = "sockcreate",
>>>>>> + .attr = LSM_ATTR_SOCKCREATE,
>>>>>> + },
>>>>>> +};
>>>>>> +
>>>>>> +/**
>>>>>> + * lsm_name_to_attr - map an LSM attribute name to its ID
>>>>>> + * @name: name of the attribute
>>>>>> + *
>>>>>> + * Look the given @name up in the table of know attribute names.
>>>>>> + *
>>>>>> + * Returns the LSM attribute value associated with @name, or 0 if
>>>>>> + * there is no mapping.
>>>>>> + */
>>>>>> +u64 lsm_name_to_attr(const char *name)
>>>>>> +{
>>>>>> + int i;
>>>>>> +
>>>>>> + for (i = 0; i < ARRAY_SIZE(lsm_attr_names); i++)
>>>>>> + if (!strcmp(name, lsm_attr_names[i].name))
>>>>>> + return lsm_attr_names[i].attr;
>>>>> I'm pretty sure this is the only place where @lsm_attr_names is used,
>>>>> right? If true, when coupled with the idea that these syscalls are
>>>>> going to close the door on new LSM attributes in procfs I think we can
>>>>> just put the mapping directly in this function via a series of
>>>>> if-statements.
>>>> Ick. You're not wrong, but the hard coded if-statement approach goes
>>>> against all sorts of coding principles. I'll do it, but I can't say I
>>>> like it.
>>> If it helps any, I understand and am sympathetic. I guess I've gotten
>>> to that point where in addition to "code elegance", I'm also very
>>> concerned about defending against "code abuse", and something like an
>>> nicely defined mapping array is ripe for someone to come along and use
>>> that to justify further use of the attribute string names in some
>>> other function/API.
>>>
>>> If you want to stick with the array - I have no problem with that -
>>> make it local to lsm_name_to_attr().
>>>
>>>>>> +/**
>>>>>> + * lsm_fill_user_ctx - Fill a user space lsm_ctx structure
>>>>>> + * @ctx: an LSM context to be filled
>>>>>> + * @context: the new context value
>>>>>> + * @context_size: the size of the new context value
>>>>>> + * @id: LSM id
>>>>>> + * @flags: LSM defined flags
>>>>>> + *
>>>>>> + * Fill all of the fields in a user space lsm_ctx structure.
>>>>>> + * Caller is assumed to have verified that @ctx has enough space
>>>>>> + * for @context.
>>>>>> + * Returns 0 on success, -EFAULT on a copyout error.
>>>>>> + */
>>>>>> +int lsm_fill_user_ctx(struct lsm_ctx __user *ctx, void *context,
>>>>>> + size_t context_size, u64 id, u64 flags)
>>>>>> +{
>>>>>> + struct lsm_ctx local;
>>>>>> + void __user *vc = ctx;
>>>>>> +
>>>>>> + local.id = id;
>>>>>> + local.flags = flags;
>>>>>> + local.ctx_len = context_size;
>>>>>> + local.len = context_size + sizeof(local);
>>>>>> + vc += sizeof(local);
>>>>> See my prior comments about void pointer math.
>>>>>
>>>>>> + if (copy_to_user(ctx, &local, sizeof(local)))
>>>>>> + return -EFAULT;
>>>>>> + if (context_size > 0 && copy_to_user(vc, context, context_size))
>>>>>> + return -EFAULT;
>>>>> Should we handle the padding in this function?
>>>> This function fills in a lsm_ctx. The padding, if any, is in addition to
>>>> the lsm_ctx, not part of it.
>>> Okay, so where is the padding managed? I may have missed it, but I
>>> don't recall seeing it anywhere in this patchset ...
>> Padding isn't being managed. There has been talk about using padding to
>> expand the API, but there is no use for it now. Or is there?
> I think two separate ideas are getting conflated, likely because the
> 'len' field is involved in both.
>
> THe first issue is padding at the end of the lsm_ctx struct to ensure
> that the next array element is aligned. The second issue is the
> potential for extending the lsm_ctx struct on a per-LSM basis through
> creative use of the 'flags' and 'len' fields; in this case additional
> information could be stashed at the end of the lsm_ctx struct after
> the 'ctx' field. The latter issue (extending the lsm_ctx) isn't
> something we want to jump into, but it is something the syscall/struct
> API would allow, and I don't want to exclude it as a possible future
> solution to a yet unknown future problem. The former issue (padding
> array elements) isn't a strict requirement as the syscall/struct API
> works either way, but it seems like a good thing to do.
Reasonable. Thanks for the clarification.