Commit f96a9741 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 678ca9f7 714d87c9
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -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 *)
@@ -3297,8 +3296,8 @@ 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;
@@ -3306,7 +3305,7 @@ static void binder_transaction(struct binder_proc *proc,
			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",
@@ -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;
@@ -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)) {
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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;
+6 −6
Original line number Diff line number Diff line
@@ -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 */
@@ -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;

@@ -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:
@@ -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);
+18 −17
Original line number Diff line number Diff line
@@ -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)
					    &name, &lsmctx);

	/* If no LSM is supporting this security hook ignore error */
	if (err && err != -EOPNOTSUPP)
		goto out_err;
		/* No LSM is supporting this security hook. Ignore error */
		ctxlen = 0;
		ctx = NULL;
	}

	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;
@@ -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;
}

+15 −7
Original line number Diff line number Diff line
@@ -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)
@@ -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;

	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)
{
Loading