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. -- paul-moore.com