Skip to content

Commit c0a614e

Browse files
committed
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
2 parents 35e886e + eaf0e7a commit c0a614e

File tree

12 files changed

+48
-42
lines changed

12 files changed

+48
-42
lines changed

include/linux/lsm_hook_defs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
280280
LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
281281
struct inode *inode)
282282
LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr,
283-
struct lsm_ctx __user *ctx, size_t *size, u32 flags)
283+
struct lsm_ctx __user *ctx, u32 *size, u32 flags)
284284
LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr,
285-
struct lsm_ctx *ctx, size_t size, u32 flags)
285+
struct lsm_ctx *ctx, u32 size, u32 flags)
286286
LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
287287
char **value)
288288
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)

include/linux/security.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,9 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
491491
unsigned nsops, int alter);
492492
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
493493
int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
494-
size_t __user *size, u32 flags);
494+
u32 __user *size, u32 flags);
495495
int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
496-
size_t size, u32 flags);
496+
u32 size, u32 flags);
497497
int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
498498
char **value);
499499
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
@@ -507,7 +507,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
507507
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
508508
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
509509
int security_locked_down(enum lockdown_reason what);
510-
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
510+
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
511511
void *val, size_t val_len, u64 id, u64 flags);
512512
#else /* CONFIG_SECURITY */
513513

@@ -1478,7 +1478,7 @@ static inline int security_locked_down(enum lockdown_reason what)
14781478
return 0;
14791479
}
14801480
static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx,
1481-
size_t *uctx_len, void *val, size_t val_len,
1481+
u32 *uctx_len, void *val, size_t val_len,
14821482
u64 id, u64 flags)
14831483
{
14841484
return -EOPNOTSUPP;

include/linux/syscalls.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -960,10 +960,10 @@ asmlinkage long sys_cachestat(unsigned int fd,
960960
struct cachestat __user *cstat, unsigned int flags);
961961
asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags);
962962
asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
963-
size_t *size, __u32 flags);
963+
u32 *size, u32 flags);
964964
asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
965-
size_t size, __u32 flags);
966-
asmlinkage long sys_lsm_list_modules(u64 *ids, size_t *size, u32 flags);
965+
u32 size, u32 flags);
966+
asmlinkage long sys_lsm_list_modules(u64 *ids, u32 *size, u32 flags);
967967

968968
/*
969969
* Architecture-specific system calls

security/apparmor/lsm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
779779
}
780780

781781
static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx,
782-
size_t *size, u32 flags)
782+
u32 *size, u32 flags)
783783
{
784784
int error = -ENOENT;
785785
struct aa_task_ctx *ctx = task_ctx(current);
@@ -924,7 +924,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
924924
}
925925

926926
static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
927-
size_t size, u32 flags)
927+
u32 size, u32 flags)
928928
{
929929
int rc;
930930

security/lsm_syscalls.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ u64 lsm_name_to_attr(const char *name)
5353
* value indicating the reason for the error is returned.
5454
*/
5555
SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
56-
ctx, size_t, size, u32, flags)
56+
ctx, u32, size, u32, flags)
5757
{
5858
return security_setselfattr(attr, ctx, size, flags);
5959
}
@@ -75,7 +75,7 @@ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
7575
* a negative value indicating the error is returned.
7676
*/
7777
SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
78-
ctx, size_t __user *, size, u32, flags)
78+
ctx, u32 __user *, size, u32, flags)
7979
{
8080
return security_getselfattr(attr, ctx, size, flags);
8181
}
@@ -93,11 +93,11 @@ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
9393
* required size. In all other cases a negative value indicating the
9494
* error is returned.
9595
*/
96-
SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, size_t __user *, size,
96+
SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, u32 __user *, size,
9797
u32, flags)
9898
{
99-
size_t total_size = lsm_active_cnt * sizeof(*ids);
100-
size_t usize;
99+
u32 total_size = lsm_active_cnt * sizeof(*ids);
100+
u32 usize;
101101
int i;
102102

103103
if (flags)

security/security.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -780,12 +780,14 @@ static int lsm_superblock_alloc(struct super_block *sb)
780780
* @id: LSM id
781781
* @flags: LSM defined flags
782782
*
783-
* Fill all of the fields in a userspace lsm_ctx structure.
783+
* Fill all of the fields in a userspace lsm_ctx structure. If @uctx is NULL
784+
* simply calculate the required size to output via @utc_len and return
785+
* success.
784786
*
785787
* Returns 0 on success, -E2BIG if userspace buffer is not large enough,
786788
* -EFAULT on a copyout error, -ENOMEM if memory can't be allocated.
787789
*/
788-
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
790+
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
789791
void *val, size_t val_len,
790792
u64 id, u64 flags)
791793
{
@@ -799,6 +801,10 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
799801
goto out;
800802
}
801803

804+
/* no buffer - return success/0 and set @uctx_len to the req size */
805+
if (!uctx)
806+
goto out;
807+
802808
nctx = kzalloc(nctx_len, GFP_KERNEL);
803809
if (nctx == NULL) {
804810
rc = -ENOMEM;
@@ -3931,14 +3937,14 @@ EXPORT_SYMBOL(security_d_instantiate);
39313937
* If @size is insufficient to contain the data -E2BIG is returned.
39323938
*/
39333939
int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
3934-
size_t __user *size, u32 flags)
3940+
u32 __user *size, u32 flags)
39353941
{
39363942
struct security_hook_list *hp;
39373943
struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, };
39383944
u8 __user *base = (u8 __user *)uctx;
3939-
size_t total = 0;
3940-
size_t entrysize;
3941-
size_t left;
3945+
u32 entrysize;
3946+
u32 total = 0;
3947+
u32 left;
39423948
bool toobig = false;
39433949
bool single = false;
39443950
int count = 0;
@@ -4024,7 +4030,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
40244030
* LSM specific failure.
40254031
*/
40264032
int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
4027-
size_t size, u32 flags)
4033+
u32 size, u32 flags)
40284034
{
40294035
struct security_hook_list *hp;
40304036
struct lsm_ctx *lctx;

security/selinux/hooks.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6559,7 +6559,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
65596559
* There will only ever be one attribute.
65606560
*/
65616561
static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
6562-
size_t *size, u32 flags)
6562+
u32 *size, u32 flags)
65636563
{
65646564
int rc;
65656565
char *val = NULL;
@@ -6574,7 +6574,7 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
65746574
}
65756575

65766576
static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
6577-
size_t size, u32 flags)
6577+
u32 size, u32 flags)
65786578
{
65796579
int rc;
65806580

security/smack/smack_lsm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,7 +3653,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
36533653
* There will only ever be one attribute.
36543654
*/
36553655
static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
3656-
size_t *size, u32 flags)
3656+
u32 *size, u32 flags)
36573657
{
36583658
int rc;
36593659
struct smack_known *skp;
@@ -3774,7 +3774,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
37743774
* Returns 0 on success, an error code otherwise.
37753775
*/
37763776
static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
3777-
size_t size, u32 flags)
3777+
u32 size, u32 flags)
37783778
{
37793779
int rc;
37803780

tools/testing/selftests/lsm/common.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@
77

88
#ifndef lsm_get_self_attr
99
static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
10-
size_t *size, __u32 flags)
10+
__u32 *size, __u32 flags)
1111
{
1212
return syscall(__NR_lsm_get_self_attr, attr, ctx, size, flags);
1313
}
1414
#endif
1515

1616
#ifndef lsm_set_self_attr
1717
static inline int lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
18-
size_t size, __u32 flags)
18+
__u32 size, __u32 flags)
1919
{
2020
return syscall(__NR_lsm_set_self_attr, attr, ctx, size, flags);
2121
}
2222
#endif
2323

2424
#ifndef lsm_list_modules
25-
static inline int lsm_list_modules(__u64 *ids, size_t *size, __u32 flags)
25+
static inline int lsm_list_modules(__u64 *ids, __u32 *size, __u32 flags)
2626
{
2727
return syscall(__NR_lsm_list_modules, ids, size, flags);
2828
}

tools/testing/selftests/lsm/lsm_get_self_attr_test.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ TEST(size_null_lsm_get_self_attr)
4040
TEST(ctx_null_lsm_get_self_attr)
4141
{
4242
const long page_size = sysconf(_SC_PAGESIZE);
43-
size_t size = page_size;
43+
__u32 size = page_size;
4444
int rc;
4545

4646
rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0);
@@ -57,7 +57,7 @@ TEST(size_too_small_lsm_get_self_attr)
5757
{
5858
const long page_size = sysconf(_SC_PAGESIZE);
5959
struct lsm_ctx *ctx = calloc(page_size, 1);
60-
size_t size = 1;
60+
__u32 size = 1;
6161

6262
ASSERT_NE(NULL, ctx);
6363
errno = 0;
@@ -77,7 +77,7 @@ TEST(flags_zero_lsm_get_self_attr)
7777
const long page_size = sysconf(_SC_PAGESIZE);
7878
struct lsm_ctx *ctx = calloc(page_size, 1);
7979
__u64 *syscall_lsms = calloc(page_size, 1);
80-
size_t size;
80+
__u32 size;
8181
int lsmcount;
8282
int i;
8383

@@ -117,7 +117,7 @@ TEST(flags_overset_lsm_get_self_attr)
117117
{
118118
const long page_size = sysconf(_SC_PAGESIZE);
119119
struct lsm_ctx *ctx = calloc(page_size, 1);
120-
size_t size;
120+
__u32 size;
121121

122122
ASSERT_NE(NULL, ctx);
123123

@@ -140,7 +140,7 @@ TEST(flags_overset_lsm_get_self_attr)
140140
TEST(basic_lsm_get_self_attr)
141141
{
142142
const long page_size = sysconf(_SC_PAGESIZE);
143-
size_t size = page_size;
143+
__u32 size = page_size;
144144
struct lsm_ctx *ctx = calloc(page_size, 1);
145145
struct lsm_ctx *tctx = NULL;
146146
__u64 *syscall_lsms = calloc(page_size, 1);

0 commit comments

Comments
 (0)