Re: [PATCH v1 6/8] LSM: lsm_self_attr syscall for LSM self attributes
From: Paul Moore <paul@paul-moore.com>
Date: 2022-11-11 03:16:53
Also in:
linux-api, lkml
Possibly related (same subject, not in this thread)
- 2022-11-23 · [PATCH v1 6/8] LSM: lsm_self_attr syscall for LSM self attributes · Casey Schaufler <casey@schaufler-ca.com>
On Thu, Nov 10, 2022 at 7:36 PM Casey Schaufler [off-list ref] wrote:
On 11/10/2022 3:36 PM, Paul Moore wrote:quoted
On Wed, Nov 9, 2022 at 6:34 PM Paul Moore [off-list ref] wrote:quoted
On Tue, Oct 25, 2022 at 2:48 PM Casey Schaufler [off-list ref] wrote:quoted
Create a system call lsm_self_attr() to provide the security module maintained attributes of the current process. Historically these attributes have been exposed to user space via entries in procfs under /proc/self/attr. Attributes are provided as a collection of lsm_ctx structures which are placed into a user supplied buffer. Each structure identifys the security module providing the attribute, which of the possible attributes is provided, the size of the attribute, and finally the attribute value. The format of the attribute value is defined by the security module, but will always be \0 terminated. The ctx_len value will be larger than strlen(ctx). ------------------------------ | unsigned int id | ------------------------------ | unsigned int flags | ------------------------------ | __kernel_size_t ctx_len | ------------------------------ | unsigned char ctx[ctx_len] | ------------------------------ | unsigned int id | ------------------------------ | unsigned int flags | ------------------------------ | __kernel_size_t ctx_len | ------------------------------ | unsigned char ctx[ctx_len] | ------------------------------ Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/syscalls.h | 2 + include/uapi/linux/lsm.h | 21 ++++++ kernel/sys_ni.c | 3 + security/Makefile | 1 + security/lsm_syscalls.c | 156 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 security/lsm_syscalls.c..quoted
quoted
+/** + * lsm_self_attr - Return current task's security module attributes + * @ctx: the LSM contexts + * @size: size of @ctx, updated on return + * @flags: reserved for future use, must be zero + * + * Returns the calling task's LSM contexts. On success this + * function returns the number of @ctx array elements. This value + * may be zero if there are no LSM contexts assigned. If @size is + * insufficient to contain the return data -E2BIG is returned and + * @size is set to the minimum required size. In all other cases + * a negative value indicating the error is returned. + */ +SYSCALL_DEFINE3(lsm_self_attr, + struct lsm_ctx __user *, ctx, + size_t __user *, size, + int, flags)See my comments above about UAPI types, let's change this to something like this: [NOTE: I'm assuming it is safe to use __XXX types in syscall declarations?] SYSCALL_DEFINE3(lsm_self_attr, struct lsm_ctx __user *, ctx, __kernel_size_t __user *, size, __u32, flags)I wanted to clarify how I originally envisioned this syscall/API, as it looks like it behaves a bit differently than I originally intended.That's why we're having a review cycle.
:)
quoted
My thought was that this syscall would be used to fetch one LSM attribute context at a time, returning an array of lsm_ctx structs, with one, and only one, for each LSM that supports that particular attribute.My thought with the interface I proposed is that we don't want a separate syscall for each attribute: e.g. lsm_get_current(), lsm_get_prev(), and we don't want a separate syscall for each LSM, e.g. lsm_get_selinux().
Agreed. I believe that proposed syscall prototype, leveraging the @flags parameter, supports this.
We can either specify which attribute is desired or which have been returned. In either case we need an attribute identifier.
I never intended the lsm_ctx::flags field to indicate the attribute itself, e.g. LSM_ATTR_CURRENT, that is for future use by the individual LSM which is providing the attribute information in that lsm_ctx array slot. With that in mind, there is no way for the syscall to return *what* attribute is returned, only the attribute value. This is intentional as I wanted to avoid using this syscall to fetch different attributes at the same time (one attribute, with multiple LSMs providing values is the intent). The "why" is explained below ...
quoted
If the LSM does not support that attribute, it must not enter an entry to the array. Requesting more than one attribute context per invocation is not allowed.Why? That seems like an unnecessary and inconvenient restriction for the program that wants to see more than one attribute. A service that wants to check its fscreate, sockcreate and keycreate to see if they're appropriate for the container it's running in, for example.
First off, the currently defined attributes are *very* different in nature so it is unlikely that a chunk of application code would want to manipulate more than one in a given function. That alone is a fairly weak justification, but the idea that attributes aren't related is important when one considers the access controls a LSM may place around the management of these attributes. Combining multiple attribute requests in a single syscall could increase confusion as when one of the requests is blocked but others are allowed. What do you do here, do you fail the entire syscall or supply just the attribute that is allowed? If you do supply just the attribute that is allowed, do you return an error code? How would you be able to distinguish from a LSM which chose not return an attribute and one that is actively blocking access to that attribute? Supporting multiple attributes gets complicated very quickly. Given the syscall prototype where we treat the flag parameter as a bitfield, we do allow ourselves the possibility of supporting this in the future, but let's keep it simple right now. It's also important to note that currently applications cannot request multiple attributes via one action. Even requesting one single attribute requires a minimum of three syscalls, so we're definitely improving things here with this syscall.
quoted
The idea was to closely resemble the familiar open("/proc/self/attr/current")/read()/close() result without relying on procfs and supporting multiple LSMs with an easy(ish) API.rc = lsm_get_self_attr(struct lsm_ctx *ctx, size, attr_id, flags); This looks like what you're asking for. It's what I had proposed but with the attr_id specified in the call rather than returned in the lsm_ctx.
I was thinking that the attr_id would be conveyed as part of the flags
parameter, but I suppose keeping them separate makes life easier (no
worries about flag collisions with the much more generic attribute
ID). I would suggest that we still treat the attribute parameter as a
bitfield to allow for the possibility of multiple attributes in one
request; as well as a reordering of the parameters:
int lsm_get_self_attr(__u32 attr,
struct lsm_ctx *ctx,
__kernel_size_t *size,
__u32 flags);
quoted
Thoughts?I don't have any problem with *what I think* you're suggesting. To make sure, I'll send a new patch. I'll also address lsm_set_self_attr(). Thank you for the feedback. Let's see if we can converge.
Sounds good. Thanks Casey. -- paul-moore.com