Skip to content

Commit

Permalink
Merge tag 'lsm-pr-20250121' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/pcmoore/lsm

Pull lsm updates from Paul Moore:

 - Improved handling of LSM "secctx" strings through lsm_context struct

   The LSM secctx string interface is from an older time when only one
   LSM was supported, migrate over to the lsm_context struct to better
   support the different LSMs we now have and make it easier to support
   new LSMs in the future.

   These changes explain the Rust, VFS, and networking changes in the
   diffstat.

 - Only build lsm_audit.c if CONFIG_SECURITY and CONFIG_AUDIT are
   enabled

   Small tweak to be a bit smarter about when we build the LSM's common
   audit helpers.

 - Check for absurdly large policies from userspace in SafeSetID

   SafeSetID policies rules are fairly small, basically just "UID:UID",
   it easy to impose a limit of KMALLOC_MAX_SIZE on policy writes which
   helps quiet a number of syzbot related issues. While work is being
   done to address the syzbot issues through other mechanisms, this is a
   trivial and relatively safe fix that we can do now.

 - Various minor improvements and cleanups

   A collection of improvements to the kernel selftests, constification
   of some function parameters, removing redundant assignments, and
   local variable renames to improve readability.

* tag 'lsm-pr-20250121' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
  lockdown: initialize local array before use to quiet static analysis
  safesetid: check size of policy writes
  net: corrections for security_secid_to_secctx returns
  lsm: rename variable to avoid shadowing
  lsm: constify function parameters
  security: remove redundant assignment to return variable
  lsm: Only build lsm_audit.c if CONFIG_SECURITY and CONFIG_AUDIT are set
  selftests: refactor the lsm `flags_overset_lsm_set_self_attr` test
  binder: initialize lsm_context structure
  rust: replace lsm context+len with lsm_context
  lsm: secctx provider check on release
  lsm: lsm_context in security_dentry_init_security
  lsm: use lsm_context in security_inode_getsecctx
  lsm: replace context+len with lsm_context
  lsm: ensure the correct LSM context releaser
  • Loading branch information
torvalds committed Jan 22, 2025
2 parents 678ca9f + 714d87c commit f96a974
Show file tree
Hide file tree
Showing 31 changed files with 351 additions and 309 deletions.
25 changes: 12 additions & 13 deletions drivers/android/binder.c
Original file line number Diff line number Diff line change
Expand Up @@ -3017,8 +3017,7 @@ static void binder_transaction(struct binder_proc *proc,
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
ktime_t t_start_time = ktime_get();
char *secctx = NULL;
u32 secctx_sz = 0;
struct lsm_context lsmctx = { };
struct list_head sgc_head;
struct list_head pf_head;
const void __user *user_buffer = (const void __user *)
Expand Down Expand Up @@ -3297,16 +3296,16 @@ static void binder_transaction(struct binder_proc *proc,
size_t added_size;

security_cred_getsecid(proc->cred, &secid);
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
if (ret) {
ret = security_secid_to_secctx(secid, &lsmctx);
if (ret < 0) {
binder_txn_error("%d:%d failed to get security context\n",
thread->pid, proc->pid);
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
added_size = ALIGN(secctx_sz, sizeof(u64));
added_size = ALIGN(lsmctx.len, sizeof(u64));
extra_buffers_size += added_size;
if (extra_buffers_size < added_size) {
binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
Expand Down Expand Up @@ -3340,23 +3339,23 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
if (secctx) {
if (lsmctx.context) {
int err;
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
ALIGN(tr->offsets_size, sizeof(void *)) +
ALIGN(extra_buffers_size, sizeof(void *)) -
ALIGN(secctx_sz, sizeof(u64));
ALIGN(lsmctx.len, sizeof(u64));

t->security_ctx = t->buffer->user_data + buf_offset;
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
secctx, secctx_sz);
lsmctx.context, lsmctx.len);
if (err) {
t->security_ctx = 0;
WARN_ON(1);
}
security_release_secctx(secctx, secctx_sz);
secctx = NULL;
security_release_secctx(&lsmctx);
lsmctx.context = NULL;
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
Expand Down Expand Up @@ -3400,7 +3399,7 @@ static void binder_transaction(struct binder_proc *proc,
off_end_offset = off_start_offset + tr->offsets_size;
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
ALIGN(secctx_sz, sizeof(u64));
ALIGN(lsmctx.len, sizeof(u64));
off_min = 0;
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
buffer_offset += sizeof(binder_size_t)) {
Expand Down Expand Up @@ -3779,8 +3778,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
err_bad_extra_size:
if (secctx)
security_release_secctx(secctx, secctx_sz);
if (lsmctx.context)
security_release_secctx(&lsmctx);
err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
Expand Down
3 changes: 1 addition & 2 deletions fs/ceph/super.h
Original file line number Diff line number Diff line change
Expand Up @@ -1132,8 +1132,7 @@ struct ceph_acl_sec_ctx {
void *acl;
#endif
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
void *sec_ctx;
u32 sec_ctxlen;
struct lsm_context lsmctx;
#endif
#ifdef CONFIG_FS_ENCRYPTION
struct ceph_fscrypt_auth *fscrypt_auth;
Expand Down
12 changes: 6 additions & 6 deletions fs/ceph/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1383,8 +1383,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
int err;

err = security_dentry_init_security(dentry, mode, &dentry->d_name,
&name, &as_ctx->sec_ctx,
&as_ctx->sec_ctxlen);
&name, &as_ctx->lsmctx);
if (err < 0) {
WARN_ON_ONCE(err != -EOPNOTSUPP);
err = 0; /* do nothing */
Expand All @@ -1409,7 +1408,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
*/
name_len = strlen(name);
err = ceph_pagelist_reserve(pagelist,
4 * 2 + name_len + as_ctx->sec_ctxlen);
4 * 2 + name_len + as_ctx->lsmctx.len);
if (err)
goto out;

Expand All @@ -1432,8 +1431,9 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
ceph_pagelist_encode_32(pagelist, name_len);
ceph_pagelist_append(pagelist, name, name_len);

ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen);
ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen);
ceph_pagelist_encode_32(pagelist, as_ctx->lsmctx.len);
ceph_pagelist_append(pagelist, as_ctx->lsmctx.context,
as_ctx->lsmctx.len);

err = 0;
out:
Expand All @@ -1451,7 +1451,7 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
posix_acl_release(as_ctx->default_acl);
#endif
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
security_release_secctx(&as_ctx->lsmctx);
#endif
#ifdef CONFIG_FS_ENCRYPTION
kfree(as_ctx->fscrypt_auth);
Expand Down
35 changes: 18 additions & 17 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,29 +467,29 @@ static int get_security_context(struct dentry *entry, umode_t mode,
{
struct fuse_secctx *fctx;
struct fuse_secctx_header *header;
void *ctx = NULL, *ptr;
u32 ctxlen, total_len = sizeof(*header);
struct lsm_context lsmctx = { };
void *ptr;
u32 total_len = sizeof(*header);
int err, nr_ctx = 0;
const char *name;
const char *name = NULL;
size_t namelen;

err = security_dentry_init_security(entry, mode, &entry->d_name,
&name, &ctx, &ctxlen);
if (err) {
if (err != -EOPNOTSUPP)
goto out_err;
/* No LSM is supporting this security hook. Ignore error */
ctxlen = 0;
ctx = NULL;
}
&name, &lsmctx);

/* If no LSM is supporting this security hook ignore error */
if (err && err != -EOPNOTSUPP)
goto out_err;

if (ctxlen) {
if (lsmctx.len) {
nr_ctx = 1;
namelen = strlen(name) + 1;
err = -EIO;
if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX))
if (WARN_ON(namelen > XATTR_NAME_MAX + 1 ||
lsmctx.len > S32_MAX))
goto out_err;
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen +
lsmctx.len);
}

err = -ENOMEM;
Expand All @@ -502,19 +502,20 @@ static int get_security_context(struct dentry *entry, umode_t mode,
ptr += sizeof(*header);
if (nr_ctx) {
fctx = ptr;
fctx->size = ctxlen;
fctx->size = lsmctx.len;
ptr += sizeof(*fctx);

strcpy(ptr, name);
ptr += namelen;

memcpy(ptr, ctx, ctxlen);
memcpy(ptr, lsmctx.context, lsmctx.len);
}
ext->size = total_len;
ext->value = header;
err = 0;
out_err:
kfree(ctx);
if (nr_ctx)
security_release_secctx(&lsmctx);
return err;
}

Expand Down
22 changes: 15 additions & 7 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static inline struct nfs4_label *
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
struct iattr *sattr, struct nfs4_label *label)
{
struct lsm_context shim;
int err;

if (label == NULL)
Expand All @@ -128,18 +129,25 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
label->label = NULL;

err = security_dentry_init_security(dentry, sattr->ia_mode,
&dentry->d_name, NULL,
(void **)&label->label, &label->len);
if (err == 0)
return label;
&dentry->d_name, NULL, &shim);
if (err)
return NULL;

return NULL;
label->label = shim.context;
label->len = shim.len;
return label;
}
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
if (label)
security_release_secctx(label->label, label->len);
struct lsm_context shim;

if (label) {
shim.context = label->label;
shim.len = label->len;
shim.id = LSM_ID_UNDEF;
security_release_secctx(&shim);
}
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
Expand Down
22 changes: 10 additions & 12 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2818,11 +2818,11 @@ static __be32 nfsd4_encode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqst
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
static inline __be32
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
void *context, int len)
const struct lsm_context *context)
{
__be32 *p;

p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4);
if (!p)
return nfserr_resource;

Expand All @@ -2832,13 +2832,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
*/
*p++ = cpu_to_be32(0); /* lfs */
*p++ = cpu_to_be32(0); /* pi */
p = xdr_encode_opaque(p, context, len);
p = xdr_encode_opaque(p, context->context, context->len);
return 0;
}
#else
static inline __be32
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
void *context, int len)
struct lsm_context *context)
{ return 0; }
#endif

Expand Down Expand Up @@ -2920,8 +2920,7 @@ struct nfsd4_fattr_args {
struct kstatfs statfs;
struct nfs4_acl *acl;
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
void *context;
int contextlen;
struct lsm_context context;
#endif
u32 rdattr_err;
bool contextsupport;
Expand Down Expand Up @@ -3376,8 +3375,7 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
static __be32 nfsd4_encode_fattr4_sec_label(struct xdr_stream *xdr,
const struct nfsd4_fattr_args *args)
{
return nfsd4_encode_security_label(xdr, args->rqstp,
args->context, args->contextlen);
return nfsd4_encode_security_label(xdr, args->rqstp, &args->context);
}
#endif

Expand Down Expand Up @@ -3527,7 +3525,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
args.ignore_crossmnt = (ignore_crossmnt != 0);
args.acl = NULL;
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
args.context = NULL;
args.context.context = NULL;
#endif

/*
Expand Down Expand Up @@ -3607,7 +3605,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
err = security_inode_getsecctx(d_inode(dentry),
&args.context, &args.contextlen);
&args.context);
else
err = -EOPNOTSUPP;
args.contextsupport = (err == 0);
Expand Down Expand Up @@ -3644,8 +3642,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,

out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
if (args.context)
security_release_secctx(args.context, args.contextlen);
if (args.context.context)
security_release_secctx(&args.context);
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(args.acl);
if (tempfh) {
Expand Down
14 changes: 14 additions & 0 deletions include/linux/lsm_audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,28 @@ struct common_audit_data {
#define v4info fam.v4
#define v6info fam.v6

#ifdef CONFIG_AUDIT

int ipv4_skb_to_auditdata(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto);

#if IS_ENABLED(CONFIG_IPV6)
int ipv6_skb_to_auditdata(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto);
#endif /* IS_ENABLED(CONFIG_IPV6) */

void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *));

#else /* CONFIG_AUDIT */

static inline void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *))
{
}

#endif /* CONFIG_AUDIT */

#endif
13 changes: 6 additions & 7 deletions include/linux/lsm_hook_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ LSM_HOOK(int, 0, move_mount, const struct path *from_path,
const struct path *to_path)
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
int mode, const struct qstr *name, const char **xattr_name,
void **ctx, u32 *ctxlen)
struct lsm_context *cp)
LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode,
struct qstr *name, const struct cred *old, struct cred *new)

Expand Down Expand Up @@ -295,17 +295,16 @@ 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)
LSM_HOOK(int, 0, ismaclabel, const char *name)
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata,
u32 *seclen)
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsm_context *cp)
LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop,
char **secdata, u32 *seclen)
struct lsm_context *cp)
LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid)
LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen)
LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp)
LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode)
LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen)
LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen)
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, void **ctx,
u32 *ctxlen)
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode,
struct lsm_context *cp)

#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
Expand Down
Loading

0 comments on commit f96a974

Please sign in to comment.