[PATCH v7 07/11] LSM: Helpers for attribute names and filling an lsm_ctx
Paul Moore
paul at paul-moore.com
Fri Mar 31 19:24:54 UTC 2023
On Fri, Mar 31, 2023 at 12:56 PM Casey Schaufler <casey at schaufler-ca.com> wrote:
> On 3/30/2023 4:28 PM, Paul Moore wrote:
> > On Thu, Mar 30, 2023 at 4:42 PM Casey Schaufler <casey at schaufler-ca.com> wrote:
> >> On 3/29/2023 6:13 PM, Paul Moore wrote:
> >>> On Wed, Mar 15, 2023 at 6:50 PM Casey Schaufler <casey at schaufler-ca.com> 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 at schaufler-ca.com>
> >>>> ---
> >>>> 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.
--
paul-moore.com
More information about the Linux-security-module-archive
mailing list