lsm/stable-6.9 PR 20240314
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmXzVowUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXNHJw/+LJLFacgvuNv6erCQNJoKpIoUVfwl HMEWJv3MICSvG7BvqpWMS29tqms1XWP7IzblmMOJ3PF86h8oOf8hg2KbEBvarSW4 WT0gVkHa+IBn9aaakUM5wDxgRnQyw5Iq+2P3LRC1rDkGgcgC2ETjcgYqnq3fD7SJ K1NpyhodaNEJ6ViW4CTjka/XX4mNpPilGJ2jqlBsNONBlHETafxE19njHxDaB4Xc AXPlc0atYW9RZXCnJ3Ot89vUdsNLZomDxLbay71O4PTUY6UpwFJHqrjnqhcKP5bQ gieX1Z6qdfi2Rb6recPCyWxOelYhvLsnTHD9bxXZfNHi8XnmQzW8rhCbVoD+nEOE xSkSk/pgiVhYcPCnKS8Skhr2p/AB/TSLhcnTAcCAD+w5yawFsVn96O54ntg8ljWW YVdtUS69AzqqtImedu2iPHBfVpi2DG2NIWI75Febf6NZeTnQemt2m6cY7eH92Noi kZgZBFkqRhBMzXKxQoeHVlbGbHGPQ+f7UUDxjzI24KXoDHHiMW5ecoGSomkLzvdS PxFVTfvSlvzdqAfKmbfGPpRNPgtGd7CV1glg7MYaKVt4ln1X1L/0jREiD5I/7uGY d60bFdFJcYNvod99YwDrlVdX9yCd1AHjy6PDydC//dfOKOChHzIVNFW9NcNPVNBy 5H7VjBJO5TQpvWY= =ugzm -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c0a614e82e
|
@ -280,9 +280,9 @@ LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
|
|||
LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr,
|
||||
struct lsm_ctx __user *ctx, size_t *size, u32 flags)
|
||||
struct lsm_ctx __user *ctx, u32 *size, u32 flags)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr,
|
||||
struct lsm_ctx *ctx, size_t size, u32 flags)
|
||||
struct lsm_ctx *ctx, u32 size, u32 flags)
|
||||
LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
|
||||
char **value)
|
||||
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
|
||||
|
|
|
@ -491,9 +491,9 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
|
|||
unsigned nsops, int alter);
|
||||
void security_d_instantiate(struct dentry *dentry, struct inode *inode);
|
||||
int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
|
||||
size_t __user *size, u32 flags);
|
||||
u32 __user *size, u32 flags);
|
||||
int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
|
||||
size_t size, u32 flags);
|
||||
u32 size, u32 flags);
|
||||
int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
|
||||
char **value);
|
||||
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);
|
|||
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
|
||||
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
|
||||
int security_locked_down(enum lockdown_reason what);
|
||||
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);
|
||||
#else /* CONFIG_SECURITY */
|
||||
|
||||
|
@ -1478,7 +1478,7 @@ static inline int security_locked_down(enum lockdown_reason what)
|
|||
return 0;
|
||||
}
|
||||
static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx,
|
||||
size_t *uctx_len, void *val, size_t val_len,
|
||||
u32 *uctx_len, void *val, size_t val_len,
|
||||
u64 id, u64 flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
|
|
@ -960,10 +960,10 @@ asmlinkage long sys_cachestat(unsigned int fd,
|
|||
struct cachestat __user *cstat, unsigned int flags);
|
||||
asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags);
|
||||
asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
|
||||
size_t *size, __u32 flags);
|
||||
u32 *size, u32 flags);
|
||||
asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
|
||||
size_t size, __u32 flags);
|
||||
asmlinkage long sys_lsm_list_modules(u64 *ids, size_t *size, u32 flags);
|
||||
u32 size, u32 flags);
|
||||
asmlinkage long sys_lsm_list_modules(u64 *ids, u32 *size, u32 flags);
|
||||
|
||||
/*
|
||||
* Architecture-specific system calls
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#ifndef lsm_get_self_attr
|
||||
static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
|
||||
size_t *size, __u32 flags)
|
||||
__u32 *size, __u32 flags)
|
||||
{
|
||||
return syscall(__NR_lsm_get_self_attr, attr, ctx, size, flags);
|
||||
}
|
||||
|
@ -15,14 +15,14 @@ static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
|
|||
|
||||
#ifndef lsm_set_self_attr
|
||||
static inline int lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
|
||||
size_t size, __u32 flags)
|
||||
__u32 size, __u32 flags)
|
||||
{
|
||||
return syscall(__NR_lsm_set_self_attr, attr, ctx, size, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef lsm_list_modules
|
||||
static inline int lsm_list_modules(__u64 *ids, size_t *size, __u32 flags)
|
||||
static inline int lsm_list_modules(__u64 *ids, __u32 *size, __u32 flags)
|
||||
{
|
||||
return syscall(__NR_lsm_list_modules, ids, size, flags);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ TEST(size_null_lsm_get_self_attr)
|
|||
TEST(ctx_null_lsm_get_self_attr)
|
||||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
int rc;
|
||||
|
||||
rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0);
|
||||
|
@ -57,7 +57,7 @@ TEST(size_too_small_lsm_get_self_attr)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
size_t size = 1;
|
||||
__u32 size = 1;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
errno = 0;
|
||||
|
@ -77,7 +77,7 @@ TEST(flags_zero_lsm_get_self_attr)
|
|||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
__u64 *syscall_lsms = calloc(page_size, 1);
|
||||
size_t size;
|
||||
__u32 size;
|
||||
int lsmcount;
|
||||
int i;
|
||||
|
||||
|
@ -117,7 +117,7 @@ TEST(flags_overset_lsm_get_self_attr)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
size_t size;
|
||||
__u32 size;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
|
||||
|
@ -140,7 +140,7 @@ TEST(flags_overset_lsm_get_self_attr)
|
|||
TEST(basic_lsm_get_self_attr)
|
||||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
struct lsm_ctx *tctx = NULL;
|
||||
__u64 *syscall_lsms = calloc(page_size, 1);
|
||||
|
|
|
@ -31,7 +31,7 @@ TEST(size_null_lsm_list_modules)
|
|||
TEST(ids_null_lsm_list_modules)
|
||||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
|
||||
errno = 0;
|
||||
ASSERT_EQ(-1, lsm_list_modules(NULL, &size, 0));
|
||||
|
@ -43,7 +43,7 @@ TEST(size_too_small_lsm_list_modules)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
__u64 *syscall_lsms = calloc(page_size, 1);
|
||||
size_t size = 1;
|
||||
__u32 size = 1;
|
||||
|
||||
ASSERT_NE(NULL, syscall_lsms);
|
||||
errno = 0;
|
||||
|
@ -58,7 +58,7 @@ TEST(flags_set_lsm_list_modules)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
__u64 *syscall_lsms = calloc(page_size, 1);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
|
||||
ASSERT_NE(NULL, syscall_lsms);
|
||||
errno = 0;
|
||||
|
@ -72,7 +72,7 @@ TEST(flags_set_lsm_list_modules)
|
|||
TEST(correct_lsm_list_modules)
|
||||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
__u64 *syscall_lsms = calloc(page_size, 1);
|
||||
char *sysfs_lsms = calloc(page_size, 1);
|
||||
char *name;
|
||||
|
|
|
@ -25,7 +25,7 @@ TEST(size_too_small_lsm_set_self_attr)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
if (attr_lsm_count()) {
|
||||
|
@ -41,7 +41,7 @@ TEST(flags_zero_lsm_set_self_attr)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
if (attr_lsm_count()) {
|
||||
|
@ -57,7 +57,7 @@ TEST(flags_overset_lsm_set_self_attr)
|
|||
{
|
||||
const long page_size = sysconf(_SC_PAGESIZE);
|
||||
char *ctx = calloc(page_size, 1);
|
||||
size_t size = page_size;
|
||||
__u32 size = page_size;
|
||||
struct lsm_ctx *tctx = (struct lsm_ctx *)ctx;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
|
|
Loading…
Reference in New Issue