Skip to content

Commit

Permalink
Merge tag 'lsm-pr-20240314' of git:https://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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:https://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
  • Loading branch information
torvalds committed Mar 14, 2024
2 parents 35e886e + eaf0e7a commit c0a614e
Show file tree
Hide file tree
Showing 12 changed files with 48 additions and 42 deletions.
4 changes: 2 additions & 2 deletions include/linux/lsm_hook_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 */

Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions security/apparmor/lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -924,7 +924,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
}

static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
size_t size, u32 flags)
u32 size, u32 flags)
{
int rc;

Expand Down
10 changes: 5 additions & 5 deletions security/lsm_syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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)
Expand Down
20 changes: 13 additions & 7 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -6559,7 +6559,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
* 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;
Expand All @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions security/smack/smack_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
6 changes: 3 additions & 3 deletions tools/testing/selftests/lsm/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@

#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);
}
#endif

#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);
}
Expand Down
10 changes: 5 additions & 5 deletions tools/testing/selftests/lsm/lsm_get_self_attr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions tools/testing/selftests/lsm/lsm_list_modules_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions tools/testing/selftests/lsm/lsm_set_self_attr_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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);
Expand Down

0 comments on commit c0a614e

Please sign in to comment.