Commit b530104f authored by Casey Schaufler's avatar Casey Schaufler Committed by Paul Moore
Browse files

lsm: lsm_context in security_dentry_init_security



Replace the (secctx,seclen) pointer pair with a single lsm_context
pointer to allow return of the LSM identifier along with the context
and context length. This allows security_release_secctx() to know how
to release the context. Callers have been modified to use or save the
returned data from the new structure.

Cc: ceph-devel@vger.kernel.org
Cc: linux-nfs@vger.kernel.org
Signed-off-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
[PM: subject tweak]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 76ecf306
Loading
Loading
Loading
Loading
+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 −10
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:
@@ -1446,16 +1446,12 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,

void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
{
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
	struct lsm_context scaff; /* scaffolding */
#endif
#ifdef CONFIG_CEPH_FS_POSIX_ACL
	posix_acl_release(as_ctx->acl);
	posix_acl_release(as_ctx->default_acl);
#endif
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
	lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0);
	security_release_secctx(&scaff);
	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;
}

+12 −8
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,21 +129,24 @@ 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)
{
	struct lsm_context scaff; /* scaffolding */
	struct lsm_context shim;

	if (label) {
		lsmcontext_init(&scaff, label->label, label->len, 0);
		security_release_secctx(&scaff);
		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)
+1 −1
Original line number Diff line number Diff line
@@ -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)

Loading