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: Casey Schaufler <casey@schaufler-ca.com> [PM: subject tweak] Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
76ecf306ae
commit
b530104f50
8 changed files with 49 additions and 70 deletions
|
@ -1132,8 +1132,7 @@ struct ceph_acl_sec_ctx {
|
||||||
void *acl;
|
void *acl;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||||
void *sec_ctx;
|
struct lsm_context lsmctx;
|
||||||
u32 sec_ctxlen;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
#ifdef CONFIG_FS_ENCRYPTION
|
||||||
struct ceph_fscrypt_auth *fscrypt_auth;
|
struct ceph_fscrypt_auth *fscrypt_auth;
|
||||||
|
|
|
@ -1383,8 +1383,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = security_dentry_init_security(dentry, mode, &dentry->d_name,
|
err = security_dentry_init_security(dentry, mode, &dentry->d_name,
|
||||||
&name, &as_ctx->sec_ctx,
|
&name, &as_ctx->lsmctx);
|
||||||
&as_ctx->sec_ctxlen);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
WARN_ON_ONCE(err != -EOPNOTSUPP);
|
WARN_ON_ONCE(err != -EOPNOTSUPP);
|
||||||
err = 0; /* do nothing */
|
err = 0; /* do nothing */
|
||||||
|
@ -1409,7 +1408,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
|
||||||
*/
|
*/
|
||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
err = ceph_pagelist_reserve(pagelist,
|
err = ceph_pagelist_reserve(pagelist,
|
||||||
4 * 2 + name_len + as_ctx->sec_ctxlen);
|
4 * 2 + name_len + as_ctx->lsmctx.len);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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_encode_32(pagelist, name_len);
|
||||||
ceph_pagelist_append(pagelist, name, name_len);
|
ceph_pagelist_append(pagelist, name, name_len);
|
||||||
|
|
||||||
ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen);
|
ceph_pagelist_encode_32(pagelist, as_ctx->lsmctx.len);
|
||||||
ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen);
|
ceph_pagelist_append(pagelist, as_ctx->lsmctx.context,
|
||||||
|
as_ctx->lsmctx.len);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
out:
|
out:
|
||||||
|
@ -1446,16 +1446,12 @@ out:
|
||||||
|
|
||||||
void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
|
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
|
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||||
posix_acl_release(as_ctx->acl);
|
posix_acl_release(as_ctx->acl);
|
||||||
posix_acl_release(as_ctx->default_acl);
|
posix_acl_release(as_ctx->default_acl);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||||
lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0);
|
security_release_secctx(&as_ctx->lsmctx);
|
||||||
security_release_secctx(&scaff);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FS_ENCRYPTION
|
#ifdef CONFIG_FS_ENCRYPTION
|
||||||
kfree(as_ctx->fscrypt_auth);
|
kfree(as_ctx->fscrypt_auth);
|
||||||
|
|
|
@ -467,29 +467,29 @@ static int get_security_context(struct dentry *entry, umode_t mode,
|
||||||
{
|
{
|
||||||
struct fuse_secctx *fctx;
|
struct fuse_secctx *fctx;
|
||||||
struct fuse_secctx_header *header;
|
struct fuse_secctx_header *header;
|
||||||
void *ctx = NULL, *ptr;
|
struct lsm_context lsmctx = { };
|
||||||
u32 ctxlen, total_len = sizeof(*header);
|
void *ptr;
|
||||||
|
u32 total_len = sizeof(*header);
|
||||||
int err, nr_ctx = 0;
|
int err, nr_ctx = 0;
|
||||||
const char *name;
|
const char *name = NULL;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
err = security_dentry_init_security(entry, mode, &entry->d_name,
|
err = security_dentry_init_security(entry, mode, &entry->d_name,
|
||||||
&name, &ctx, &ctxlen);
|
&name, &lsmctx);
|
||||||
if (err) {
|
|
||||||
if (err != -EOPNOTSUPP)
|
|
||||||
goto out_err;
|
|
||||||
/* No LSM is supporting this security hook. Ignore error */
|
|
||||||
ctxlen = 0;
|
|
||||||
ctx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxlen) {
|
/* If no LSM is supporting this security hook ignore error */
|
||||||
|
if (err && err != -EOPNOTSUPP)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
if (lsmctx.len) {
|
||||||
nr_ctx = 1;
|
nr_ctx = 1;
|
||||||
namelen = strlen(name) + 1;
|
namelen = strlen(name) + 1;
|
||||||
err = -EIO;
|
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;
|
goto out_err;
|
||||||
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
|
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen +
|
||||||
|
lsmctx.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
@ -502,19 +502,20 @@ static int get_security_context(struct dentry *entry, umode_t mode,
|
||||||
ptr += sizeof(*header);
|
ptr += sizeof(*header);
|
||||||
if (nr_ctx) {
|
if (nr_ctx) {
|
||||||
fctx = ptr;
|
fctx = ptr;
|
||||||
fctx->size = ctxlen;
|
fctx->size = lsmctx.len;
|
||||||
ptr += sizeof(*fctx);
|
ptr += sizeof(*fctx);
|
||||||
|
|
||||||
strcpy(ptr, name);
|
strcpy(ptr, name);
|
||||||
ptr += namelen;
|
ptr += namelen;
|
||||||
|
|
||||||
memcpy(ptr, ctx, ctxlen);
|
memcpy(ptr, lsmctx.context, lsmctx.len);
|
||||||
}
|
}
|
||||||
ext->size = total_len;
|
ext->size = total_len;
|
||||||
ext->value = header;
|
ext->value = header;
|
||||||
err = 0;
|
err = 0;
|
||||||
out_err:
|
out_err:
|
||||||
kfree(ctx);
|
if (nr_ctx)
|
||||||
|
security_release_secctx(&lsmctx);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ static inline struct nfs4_label *
|
||||||
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
||||||
struct iattr *sattr, struct nfs4_label *label)
|
struct iattr *sattr, struct nfs4_label *label)
|
||||||
{
|
{
|
||||||
|
struct lsm_context shim;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (label == NULL)
|
if (label == NULL)
|
||||||
|
@ -128,21 +129,24 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
||||||
label->label = NULL;
|
label->label = NULL;
|
||||||
|
|
||||||
err = security_dentry_init_security(dentry, sattr->ia_mode,
|
err = security_dentry_init_security(dentry, sattr->ia_mode,
|
||||||
&dentry->d_name, NULL,
|
&dentry->d_name, NULL, &shim);
|
||||||
(void **)&label->label, &label->len);
|
if (err)
|
||||||
if (err == 0)
|
return NULL;
|
||||||
return label;
|
|
||||||
|
|
||||||
return NULL;
|
label->label = shim.context;
|
||||||
|
label->len = shim.len;
|
||||||
|
return label;
|
||||||
}
|
}
|
||||||
static inline void
|
static inline void
|
||||||
nfs4_label_release_security(struct nfs4_label *label)
|
nfs4_label_release_security(struct nfs4_label *label)
|
||||||
{
|
{
|
||||||
struct lsm_context scaff; /* scaffolding */
|
struct lsm_context shim;
|
||||||
|
|
||||||
if (label) {
|
if (label) {
|
||||||
lsmcontext_init(&scaff, label->label, label->len, 0);
|
shim.context = label->label;
|
||||||
security_release_secctx(&scaff);
|
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)
|
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
|
||||||
|
|
|
@ -83,7 +83,7 @@ LSM_HOOK(int, 0, move_mount, const struct path *from_path,
|
||||||
const struct path *to_path)
|
const struct path *to_path)
|
||||||
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
|
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
|
||||||
int mode, const struct qstr *name, const char **xattr_name,
|
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,
|
LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode,
|
||||||
struct qstr *name, const struct cred *old, struct cred *new)
|
struct qstr *name, const struct cred *old, struct cred *new)
|
||||||
|
|
||||||
|
|
|
@ -237,25 +237,6 @@ struct lsm_context {
|
||||||
int id; /* Identifies the module */
|
int id; /* Identifies the module */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* lsmcontext_init - initialize an lsmcontext structure.
|
|
||||||
* @cp: Pointer to the context to initialize
|
|
||||||
* @context: Initial context, or NULL
|
|
||||||
* @size: Size of context, or 0
|
|
||||||
* @id: Which LSM provided the context
|
|
||||||
*
|
|
||||||
* Fill in the lsmcontext from the provided information.
|
|
||||||
* This is a scaffolding function that will be removed when
|
|
||||||
* lsm_context integration is complete.
|
|
||||||
*/
|
|
||||||
static inline void lsmcontext_init(struct lsm_context *cp, char *context,
|
|
||||||
u32 size, int id)
|
|
||||||
{
|
|
||||||
cp->id = id;
|
|
||||||
cp->context = context;
|
|
||||||
cp->len = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Values used in the task_security_ops calls
|
* Values used in the task_security_ops calls
|
||||||
*/
|
*/
|
||||||
|
@ -409,8 +390,8 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
|
||||||
int security_move_mount(const struct path *from_path, const struct path *to_path);
|
int security_move_mount(const struct path *from_path, const struct path *to_path);
|
||||||
int security_dentry_init_security(struct dentry *dentry, int mode,
|
int security_dentry_init_security(struct dentry *dentry, int mode,
|
||||||
const struct qstr *name,
|
const struct qstr *name,
|
||||||
const char **xattr_name, void **ctx,
|
const char **xattr_name,
|
||||||
u32 *ctxlen);
|
struct lsm_context *lsmcxt);
|
||||||
int security_dentry_create_files_as(struct dentry *dentry, int mode,
|
int security_dentry_create_files_as(struct dentry *dentry, int mode,
|
||||||
struct qstr *name,
|
struct qstr *name,
|
||||||
const struct cred *old,
|
const struct cred *old,
|
||||||
|
@ -883,8 +864,7 @@ static inline int security_dentry_init_security(struct dentry *dentry,
|
||||||
int mode,
|
int mode,
|
||||||
const struct qstr *name,
|
const struct qstr *name,
|
||||||
const char **xattr_name,
|
const char **xattr_name,
|
||||||
void **ctx,
|
struct lsm_context *lsmcxt)
|
||||||
u32 *ctxlen)
|
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1735,8 +1735,7 @@ void security_inode_free(struct inode *inode)
|
||||||
* @mode: mode used to determine resource type
|
* @mode: mode used to determine resource type
|
||||||
* @name: name of the last path component
|
* @name: name of the last path component
|
||||||
* @xattr_name: name of the security/LSM xattr
|
* @xattr_name: name of the security/LSM xattr
|
||||||
* @ctx: pointer to the resulting LSM context
|
* @lsmctx: pointer to the resulting LSM context
|
||||||
* @ctxlen: length of @ctx
|
|
||||||
*
|
*
|
||||||
* Compute a context for a dentry as the inode is not yet available since NFSv4
|
* Compute a context for a dentry as the inode is not yet available since NFSv4
|
||||||
* has no label backed by an EA anyway. It is important to note that
|
* has no label backed by an EA anyway. It is important to note that
|
||||||
|
@ -1746,11 +1745,11 @@ void security_inode_free(struct inode *inode)
|
||||||
*/
|
*/
|
||||||
int security_dentry_init_security(struct dentry *dentry, int mode,
|
int security_dentry_init_security(struct dentry *dentry, int mode,
|
||||||
const struct qstr *name,
|
const struct qstr *name,
|
||||||
const char **xattr_name, void **ctx,
|
const char **xattr_name,
|
||||||
u32 *ctxlen)
|
struct lsm_context *lsmctx)
|
||||||
{
|
{
|
||||||
return call_int_hook(dentry_init_security, dentry, mode, name,
|
return call_int_hook(dentry_init_security, dentry, mode, name,
|
||||||
xattr_name, ctx, ctxlen);
|
xattr_name, lsmctx);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_dentry_init_security);
|
EXPORT_SYMBOL(security_dentry_init_security);
|
||||||
|
|
||||||
|
|
|
@ -2869,8 +2869,8 @@ static void selinux_inode_free_security(struct inode *inode)
|
||||||
|
|
||||||
static int selinux_dentry_init_security(struct dentry *dentry, int mode,
|
static int selinux_dentry_init_security(struct dentry *dentry, int mode,
|
||||||
const struct qstr *name,
|
const struct qstr *name,
|
||||||
const char **xattr_name, void **ctx,
|
const char **xattr_name,
|
||||||
u32 *ctxlen)
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
u32 newsid;
|
u32 newsid;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -2885,8 +2885,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
|
||||||
if (xattr_name)
|
if (xattr_name)
|
||||||
*xattr_name = XATTR_NAME_SELINUX;
|
*xattr_name = XATTR_NAME_SELINUX;
|
||||||
|
|
||||||
return security_sid_to_context(newsid, (char **)ctx,
|
cp->id = LSM_ID_SELINUX;
|
||||||
ctxlen);
|
return security_sid_to_context(newsid, &cp->context, &cp->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
|
static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
|
||||||
|
|
Loading…
Add table
Reference in a new issue