summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 16:05:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 16:05:20 -0700
commitc0a614e82ece41d15b7a66f43ee79f4dbdbc925a (patch)
tree2472563bddee5aa4fff1b61957afeda23924eb15 /security
parent35e886e88c803920644c9d3abb45a9ecb7f1e761 (diff)
parenteaf0e7a3d2711018789e9fdb89191d19aa139c47 (diff)
Merge tag 'lsm-pr-20240314' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
Pull lsm fixes from Paul Moore: "Two fixes to address issues with the LSM syscalls that we shipped in Linux v6.8. The first patch might be a bit controversial, but the second is a rather straightforward fix; more on both below. The first fix from Casey addresses a problem that should have been caught during the ~16 month (?) review cycle, but sadly was not. The good news is that Dmitry caught it very quickly once Linux v6.8 was released. The core issue is the use of size_t parameters to pass buffer sizes back and forth in the syscall; while we could have solved this with a compat syscall definition, given the newness of the syscalls I wanted to attempt to just redefine the size_t parameters as u32 types and avoid the work associated with a set of compat syscalls. However, this is technically a change in the syscall's signature/API so I can understand if you're opposed to this, even if the syscalls are less than a week old. [ Fingers crossed nobody even notices - Linus ] The second fix is a rather trivial fix to allow userspace to call into the lsm_get_self_attr() syscall with a NULL buffer to quickly determine a minimum required size for the buffer. We do have kselftests for this very case, I'm not sure why I didn't notice the failure; I'm going to guess stupidity, tired eyes, I dunno. My apologies we didn't catch this earlier" * tag 'lsm-pr-20240314' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: lsm: handle the NULL buffer case in lsm_fill_user_ctx() lsm: use 32-bit compatible data types in LSM syscalls
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/lsm.c4
-rw-r--r--security/lsm_syscalls.c10
-rw-r--r--security/security.c20
-rw-r--r--security/selinux/hooks.c4
-rw-r--r--security/smack/smack_lsm.c4
5 files changed, 24 insertions, 18 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 9a3dcaafb5b1..cef8c466af80 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -779,7 +779,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
}
static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx,
- size_t *size, u32 flags)
+ u32 *size, u32 flags)
{
int error = -ENOENT;
struct aa_task_ctx *ctx = task_ctx(current);
@@ -924,7 +924,7 @@ fail:
}
static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
- size_t size, u32 flags)
+ u32 size, u32 flags)
{
int rc;
diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
index 5d391b1f7e69..8440948a690c 100644
--- a/security/lsm_syscalls.c
+++ b/security/lsm_syscalls.c
@@ -53,7 +53,7 @@ u64 lsm_name_to_attr(const char *name)
* value indicating the reason for the error is returned.
*/
SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
- ctx, size_t, size, u32, flags)
+ ctx, u32, size, u32, flags)
{
return security_setselfattr(attr, ctx, size, flags);
}
@@ -75,7 +75,7 @@ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
* a negative value indicating the error is returned.
*/
SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
- ctx, size_t __user *, size, u32, flags)
+ ctx, u32 __user *, size, u32, flags)
{
return security_getselfattr(attr, ctx, size, flags);
}
@@ -93,11 +93,11 @@ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
* required size. In all other cases a negative value indicating the
* error is returned.
*/
-SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, size_t __user *, size,
+SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, u32 __user *, size,
u32, flags)
{
- size_t total_size = lsm_active_cnt * sizeof(*ids);
- size_t usize;
+ u32 total_size = lsm_active_cnt * sizeof(*ids);
+ u32 usize;
int i;
if (flags)
diff --git a/security/security.c b/security/security.c
index a07f43c58d65..7e118858b545 100644
--- a/security/security.c
+++ b/security/security.c
@@ -780,12 +780,14 @@ static int lsm_superblock_alloc(struct super_block *sb)
* @id: LSM id
* @flags: LSM defined flags
*
- * Fill all of the fields in a userspace lsm_ctx structure.
+ * Fill all of the fields in a userspace lsm_ctx structure. If @uctx is NULL
+ * simply calculate the required size to output via @utc_len and return
+ * success.
*
* Returns 0 on success, -E2BIG if userspace buffer is not large enough,
* -EFAULT on a copyout error, -ENOMEM if memory can't be allocated.
*/
-int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
+int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
void *val, size_t val_len,
u64 id, u64 flags)
{
@@ -799,6 +801,10 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
goto out;
}
+ /* no buffer - return success/0 and set @uctx_len to the req size */
+ if (!uctx)
+ goto out;
+
nctx = kzalloc(nctx_len, GFP_KERNEL);
if (nctx == NULL) {
rc = -ENOMEM;
@@ -3931,14 +3937,14 @@ EXPORT_SYMBOL(security_d_instantiate);
* If @size is insufficient to contain the data -E2BIG is returned.
*/
int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
- size_t __user *size, u32 flags)
+ u32 __user *size, u32 flags)
{
struct security_hook_list *hp;
struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, };
u8 __user *base = (u8 __user *)uctx;
- size_t total = 0;
- size_t entrysize;
- size_t left;
+ u32 entrysize;
+ u32 total = 0;
+ u32 left;
bool toobig = false;
bool single = false;
int count = 0;
@@ -4024,7 +4030,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
* LSM specific failure.
*/
int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
- size_t size, u32 flags)
+ u32 size, u32 flags)
{
struct security_hook_list *hp;
struct lsm_ctx *lctx;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8db4875164ab..3448454c82d0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6559,7 +6559,7 @@ abort_change:
* There will only ever be one attribute.
*/
static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
- size_t *size, u32 flags)
+ u32 *size, u32 flags)
{
int rc;
char *val = NULL;
@@ -6574,7 +6574,7 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
}
static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
- size_t size, u32 flags)
+ u32 size, u32 flags)
{
int rc;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 28be26712396..146667937811 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3653,7 +3653,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* There will only ever be one attribute.
*/
static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
- size_t *size, u32 flags)
+ u32 *size, u32 flags)
{
int rc;
struct smack_known *skp;
@@ -3774,7 +3774,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
* Returns 0 on success, an error code otherwise.
*/
static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
- size_t size, u32 flags)
+ u32 size, u32 flags)
{
int rc;