mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-22 07:53:11 -05:00
lsm/stable-6.14 PR 20250121
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmeQFBoUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXPvcA//XCdwMz0bGtWKv58nuyP8vkQx08n6 //olz/O8te3uWK5O3kRiarzFLwH8qsHQ6A7GYalwwix34hatR4ndJE0Y/guVRWa1 +aBmJxJ7Jm/q3fvpAEfqiSgreuE6kBoztlDOWEq+hUQGu4qfnQGm2EnvbvfFrAmN VheOfIQSU2KCL/Scc3FGnF6uru4WrqN0JJ9RbvrEpfdQgmcyTGLnQsZLljutWSIq kDWkteIr7cj3O9J45zpxZsTftvYSgVn/y1iKeXbHI4DBA1eheK12vsHB9AADKI1J GwHxOrnLpZtv+ICUKqcfFTmWTl+NmfJJurAT5KXKdBjL3xM5MoJlBvK1A5qE9CMo LaHVG/TZR2MmBaoM3EN+gvWhDgWlvT02Q/0cYaafTlVLMez3HtfctxN6OnCvTXTB Y8dqYClhhlBm/mHQwYfMoeKw4MftUpzEqBd1Nj7Qe8dbP0f/62Ca3K2B3D6Rf8QV pj3ryMlSWYV9mdTerruLNQexTGoN7l66jPwzdWpTbFeL3WmNtfCako8OZGbXgPIu Iahm3P+jnSVx8ZQro2c9zwdKXI5xiI335pCBbDZ8aX+JAsfj0OofHsFx5Q5diber M7tAEhxDqRisbpz7Ei+/LOAEGg2Z619XKg8ks4z6Y4P5PF7zEgeWTkZJk2iLbxXe 6LLOjmF7LLw+G4M= =fgyr -----END PGP SIGNATURE----- Merge tag 'lsm-pr-20250121' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
commit
f96a974170
31 changed files with 351 additions and 309 deletions
|
@ -3017,8 +3017,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
struct binder_context *context = proc->context;
|
struct binder_context *context = proc->context;
|
||||||
int t_debug_id = atomic_inc_return(&binder_last_id);
|
int t_debug_id = atomic_inc_return(&binder_last_id);
|
||||||
ktime_t t_start_time = ktime_get();
|
ktime_t t_start_time = ktime_get();
|
||||||
char *secctx = NULL;
|
struct lsm_context lsmctx = { };
|
||||||
u32 secctx_sz = 0;
|
|
||||||
struct list_head sgc_head;
|
struct list_head sgc_head;
|
||||||
struct list_head pf_head;
|
struct list_head pf_head;
|
||||||
const void __user *user_buffer = (const void __user *)
|
const void __user *user_buffer = (const void __user *)
|
||||||
|
@ -3297,8 +3296,8 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
size_t added_size;
|
size_t added_size;
|
||||||
|
|
||||||
security_cred_getsecid(proc->cred, &secid);
|
security_cred_getsecid(proc->cred, &secid);
|
||||||
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
|
ret = security_secid_to_secctx(secid, &lsmctx);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
binder_txn_error("%d:%d failed to get security context\n",
|
binder_txn_error("%d:%d failed to get security context\n",
|
||||||
thread->pid, proc->pid);
|
thread->pid, proc->pid);
|
||||||
return_error = BR_FAILED_REPLY;
|
return_error = BR_FAILED_REPLY;
|
||||||
|
@ -3306,7 +3305,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
return_error_line = __LINE__;
|
return_error_line = __LINE__;
|
||||||
goto err_get_secctx_failed;
|
goto err_get_secctx_failed;
|
||||||
}
|
}
|
||||||
added_size = ALIGN(secctx_sz, sizeof(u64));
|
added_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||||
extra_buffers_size += added_size;
|
extra_buffers_size += added_size;
|
||||||
if (extra_buffers_size < added_size) {
|
if (extra_buffers_size < added_size) {
|
||||||
binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
|
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;
|
t->buffer = NULL;
|
||||||
goto err_binder_alloc_buf_failed;
|
goto err_binder_alloc_buf_failed;
|
||||||
}
|
}
|
||||||
if (secctx) {
|
if (lsmctx.context) {
|
||||||
int err;
|
int err;
|
||||||
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
|
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
|
||||||
ALIGN(tr->offsets_size, sizeof(void *)) +
|
ALIGN(tr->offsets_size, sizeof(void *)) +
|
||||||
ALIGN(extra_buffers_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;
|
t->security_ctx = t->buffer->user_data + buf_offset;
|
||||||
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
||||||
t->buffer, buf_offset,
|
t->buffer, buf_offset,
|
||||||
secctx, secctx_sz);
|
lsmctx.context, lsmctx.len);
|
||||||
if (err) {
|
if (err) {
|
||||||
t->security_ctx = 0;
|
t->security_ctx = 0;
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
}
|
}
|
||||||
security_release_secctx(secctx, secctx_sz);
|
security_release_secctx(&lsmctx);
|
||||||
secctx = NULL;
|
lsmctx.context = NULL;
|
||||||
}
|
}
|
||||||
t->buffer->debug_id = t->debug_id;
|
t->buffer->debug_id = t->debug_id;
|
||||||
t->buffer->transaction = t;
|
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;
|
off_end_offset = off_start_offset + tr->offsets_size;
|
||||||
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
|
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
|
||||||
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
|
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
|
||||||
ALIGN(secctx_sz, sizeof(u64));
|
ALIGN(lsmctx.len, sizeof(u64));
|
||||||
off_min = 0;
|
off_min = 0;
|
||||||
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
|
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
|
||||||
buffer_offset += sizeof(binder_size_t)) {
|
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);
|
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
|
||||||
err_binder_alloc_buf_failed:
|
err_binder_alloc_buf_failed:
|
||||||
err_bad_extra_size:
|
err_bad_extra_size:
|
||||||
if (secctx)
|
if (lsmctx.context)
|
||||||
security_release_secctx(secctx, secctx_sz);
|
security_release_secctx(&lsmctx);
|
||||||
err_get_secctx_failed:
|
err_get_secctx_failed:
|
||||||
kfree(tcomplete);
|
kfree(tcomplete);
|
||||||
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
|
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||||
|
|
|
@ -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:
|
||||||
|
@ -1451,7 +1451,7 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
|
||||||
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
|
||||||
security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
|
security_release_secctx(&as_ctx->lsmctx);
|
||||||
#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,18 +129,25 @@ 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 label;
|
|
||||||
|
|
||||||
return NULL;
|
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)
|
||||||
{
|
{
|
||||||
if (label)
|
struct lsm_context shim;
|
||||||
security_release_secctx(label->label, label->len);
|
|
||||||
|
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)
|
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2818,11 +2818,11 @@ static __be32 nfsd4_encode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqst
|
||||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
static inline __be32
|
static inline __be32
|
||||||
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
||||||
void *context, int len)
|
const struct lsm_context *context)
|
||||||
{
|
{
|
||||||
__be32 *p;
|
__be32 *p;
|
||||||
|
|
||||||
p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
|
p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4);
|
||||||
if (!p)
|
if (!p)
|
||||||
return nfserr_resource;
|
return nfserr_resource;
|
||||||
|
|
||||||
|
@ -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); /* lfs */
|
||||||
*p++ = cpu_to_be32(0); /* pi */
|
*p++ = cpu_to_be32(0); /* pi */
|
||||||
p = xdr_encode_opaque(p, context, len);
|
p = xdr_encode_opaque(p, context->context, context->len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline __be32
|
static inline __be32
|
||||||
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
||||||
void *context, int len)
|
struct lsm_context *context)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2920,8 +2920,7 @@ struct nfsd4_fattr_args {
|
||||||
struct kstatfs statfs;
|
struct kstatfs statfs;
|
||||||
struct nfs4_acl *acl;
|
struct nfs4_acl *acl;
|
||||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
void *context;
|
struct lsm_context context;
|
||||||
int contextlen;
|
|
||||||
#endif
|
#endif
|
||||||
u32 rdattr_err;
|
u32 rdattr_err;
|
||||||
bool contextsupport;
|
bool contextsupport;
|
||||||
|
@ -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,
|
static __be32 nfsd4_encode_fattr4_sec_label(struct xdr_stream *xdr,
|
||||||
const struct nfsd4_fattr_args *args)
|
const struct nfsd4_fattr_args *args)
|
||||||
{
|
{
|
||||||
return nfsd4_encode_security_label(xdr, args->rqstp,
|
return nfsd4_encode_security_label(xdr, args->rqstp, &args->context);
|
||||||
args->context, args->contextlen);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3527,7 +3525,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||||
args.ignore_crossmnt = (ignore_crossmnt != 0);
|
args.ignore_crossmnt = (ignore_crossmnt != 0);
|
||||||
args.acl = NULL;
|
args.acl = NULL;
|
||||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
args.context = NULL;
|
args.context.context = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3607,7 +3605,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||||
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
|
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
|
||||||
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
|
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
|
||||||
err = security_inode_getsecctx(d_inode(dentry),
|
err = security_inode_getsecctx(d_inode(dentry),
|
||||||
&args.context, &args.contextlen);
|
&args.context);
|
||||||
else
|
else
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
args.contextsupport = (err == 0);
|
args.contextsupport = (err == 0);
|
||||||
|
@ -3644,8 +3642,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||||
if (args.context)
|
if (args.context.context)
|
||||||
security_release_secctx(args.context, args.contextlen);
|
security_release_secctx(&args.context);
|
||||||
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
|
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
|
||||||
kfree(args.acl);
|
kfree(args.acl);
|
||||||
if (tempfh) {
|
if (tempfh) {
|
||||||
|
|
|
@ -116,14 +116,28 @@ struct common_audit_data {
|
||||||
#define v4info fam.v4
|
#define v4info fam.v4
|
||||||
#define v6info fam.v6
|
#define v6info fam.v6
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
|
||||||
int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
int ipv4_skb_to_auditdata(struct sk_buff *skb,
|
||||||
struct common_audit_data *ad, u8 *proto);
|
struct common_audit_data *ad, u8 *proto);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
||||||
struct common_audit_data *ad, u8 *proto);
|
struct common_audit_data *ad, u8 *proto);
|
||||||
|
#endif /* IS_ENABLED(CONFIG_IPV6) */
|
||||||
|
|
||||||
void common_lsm_audit(struct common_audit_data *a,
|
void common_lsm_audit(struct common_audit_data *a,
|
||||||
void (*pre_audit)(struct audit_buffer *, void *),
|
void (*pre_audit)(struct audit_buffer *, void *),
|
||||||
void (*post_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
|
#endif
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
@ -295,17 +295,16 @@ LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
|
||||||
char **value)
|
char **value)
|
||||||
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
|
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
|
||||||
LSM_HOOK(int, 0, ismaclabel, const char *name)
|
LSM_HOOK(int, 0, ismaclabel, const char *name)
|
||||||
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata,
|
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsm_context *cp)
|
||||||
u32 *seclen)
|
|
||||||
LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop,
|
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(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(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_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen)
|
||||||
LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, 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,
|
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode,
|
||||||
u32 *ctxlen)
|
struct lsm_context *cp)
|
||||||
|
|
||||||
#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
|
#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
|
||||||
LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
|
LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
|
||||||
|
|
|
@ -225,6 +225,18 @@ extern unsigned long dac_mmap_min_addr;
|
||||||
#define dac_mmap_min_addr 0UL
|
#define dac_mmap_min_addr 0UL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A "security context" is the text representation of
|
||||||
|
* the information used by LSMs.
|
||||||
|
* This structure contains the string, its length, and which LSM
|
||||||
|
* it is useful for.
|
||||||
|
*/
|
||||||
|
struct lsm_context {
|
||||||
|
char *context; /* Provided by the module */
|
||||||
|
u32 len;
|
||||||
|
int id; /* Identifies the module */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Values used in the task_security_ops calls
|
* Values used in the task_security_ops calls
|
||||||
*/
|
*/
|
||||||
|
@ -378,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,
|
||||||
|
@ -553,14 +565,14 @@ int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
|
||||||
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
|
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
|
||||||
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
|
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
|
||||||
int security_ismaclabel(const char *name);
|
int security_ismaclabel(const char *name);
|
||||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
int security_secid_to_secctx(u32 secid, struct lsm_context *cp);
|
||||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, u32 *seclen);
|
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp);
|
||||||
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
||||||
void security_release_secctx(char *secdata, u32 seclen);
|
void security_release_secctx(struct lsm_context *cp);
|
||||||
void security_inode_invalidate_secctx(struct inode *inode);
|
void security_inode_invalidate_secctx(struct inode *inode);
|
||||||
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
|
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_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
|
||||||
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
|
int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp);
|
||||||
int security_locked_down(enum lockdown_reason what);
|
int security_locked_down(enum lockdown_reason what);
|
||||||
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *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);
|
void *val, size_t val_len, u64 id, u64 flags);
|
||||||
|
@ -852,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;
|
||||||
}
|
}
|
||||||
|
@ -1526,14 +1537,13 @@ static inline int security_ismaclabel(const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int security_secid_to_secctx(u32 secid, char **secdata,
|
static inline int security_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
u32 *seclen)
|
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int security_lsmprop_to_secctx(struct lsm_prop *prop,
|
static inline int security_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||||
char **secdata, u32 *seclen)
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -1545,7 +1555,7 @@ static inline int security_secctx_to_secid(const char *secdata,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void security_release_secctx(char *secdata, u32 seclen)
|
static inline void security_release_secctx(struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1561,7 +1571,8 @@ static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
|
static inline int security_inode_getsecctx(struct inode *inode,
|
||||||
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,16 +105,16 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
|
||||||
#ifdef CONFIG_SECURITY_NETWORK
|
#ifdef CONFIG_SECURITY_NETWORK
|
||||||
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||||
{
|
{
|
||||||
char *secdata;
|
struct lsm_context ctx;
|
||||||
u32 seclen;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
|
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
|
||||||
err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
|
err = security_secid_to_secctx(scm->secid, &ctx);
|
||||||
|
|
||||||
if (!err) {
|
if (err >= 0) {
|
||||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
|
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
|
||||||
security_release_secctx(secdata, seclen);
|
ctx.context);
|
||||||
|
security_release_secctx(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1221,8 +1221,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
struct audit_buffer *ab;
|
struct audit_buffer *ab;
|
||||||
u16 msg_type = nlh->nlmsg_type;
|
u16 msg_type = nlh->nlmsg_type;
|
||||||
struct audit_sig_info *sig_data;
|
struct audit_sig_info *sig_data;
|
||||||
char *ctx = NULL;
|
struct lsm_context lsmctx;
|
||||||
u32 len;
|
|
||||||
|
|
||||||
err = audit_netlink_ok(skb, msg_type);
|
err = audit_netlink_ok(skb, msg_type);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1472,27 +1471,28 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AUDIT_SIGNAL_INFO:
|
case AUDIT_SIGNAL_INFO:
|
||||||
len = 0;
|
|
||||||
if (lsmprop_is_set(&audit_sig_lsm)) {
|
if (lsmprop_is_set(&audit_sig_lsm)) {
|
||||||
err = security_lsmprop_to_secctx(&audit_sig_lsm, &ctx,
|
err = security_lsmprop_to_secctx(&audit_sig_lsm,
|
||||||
&len);
|
&lsmctx);
|
||||||
if (err)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
|
sig_data = kmalloc(struct_size(sig_data, ctx, lsmctx.len),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!sig_data) {
|
if (!sig_data) {
|
||||||
if (lsmprop_is_set(&audit_sig_lsm))
|
if (lsmprop_is_set(&audit_sig_lsm))
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&lsmctx);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
|
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
|
||||||
sig_data->pid = audit_sig_pid;
|
sig_data->pid = audit_sig_pid;
|
||||||
if (lsmprop_is_set(&audit_sig_lsm)) {
|
if (lsmprop_is_set(&audit_sig_lsm)) {
|
||||||
memcpy(sig_data->ctx, ctx, len);
|
memcpy(sig_data->ctx, lsmctx.context, lsmctx.len);
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&lsmctx);
|
||||||
}
|
}
|
||||||
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
|
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
|
||||||
sig_data, struct_size(sig_data, ctx, len));
|
sig_data, struct_size(sig_data, ctx,
|
||||||
|
lsmctx.len));
|
||||||
kfree(sig_data);
|
kfree(sig_data);
|
||||||
break;
|
break;
|
||||||
case AUDIT_TTY_GET: {
|
case AUDIT_TTY_GET: {
|
||||||
|
@ -2180,23 +2180,22 @@ void audit_log_key(struct audit_buffer *ab, char *key)
|
||||||
int audit_log_task_context(struct audit_buffer *ab)
|
int audit_log_task_context(struct audit_buffer *ab)
|
||||||
{
|
{
|
||||||
struct lsm_prop prop;
|
struct lsm_prop prop;
|
||||||
char *ctx = NULL;
|
struct lsm_context ctx;
|
||||||
unsigned len;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
security_current_getlsmprop_subj(&prop);
|
security_current_getlsmprop_subj(&prop);
|
||||||
if (!lsmprop_is_set(&prop))
|
if (!lsmprop_is_set(&prop))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error = security_lsmprop_to_secctx(&prop, &ctx, &len);
|
error = security_lsmprop_to_secctx(&prop, &ctx);
|
||||||
if (error) {
|
if (error < 0) {
|
||||||
if (error != -EINVAL)
|
if (error != -EINVAL)
|
||||||
goto error_path;
|
goto error_path;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audit_log_format(ab, " subj=%s", ctx);
|
audit_log_format(ab, " subj=%s", ctx.context);
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&ctx);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_path:
|
error_path:
|
||||||
|
|
|
@ -1098,8 +1098,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||||
char *comm)
|
char *comm)
|
||||||
{
|
{
|
||||||
struct audit_buffer *ab;
|
struct audit_buffer *ab;
|
||||||
char *ctx = NULL;
|
struct lsm_context ctx;
|
||||||
u32 len;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
|
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
|
||||||
|
@ -1110,12 +1109,12 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||||
from_kuid(&init_user_ns, auid),
|
from_kuid(&init_user_ns, auid),
|
||||||
from_kuid(&init_user_ns, uid), sessionid);
|
from_kuid(&init_user_ns, uid), sessionid);
|
||||||
if (lsmprop_is_set(prop)) {
|
if (lsmprop_is_set(prop)) {
|
||||||
if (security_lsmprop_to_secctx(prop, &ctx, &len)) {
|
if (security_lsmprop_to_secctx(prop, &ctx) < 0) {
|
||||||
audit_log_format(ab, " obj=(none)");
|
audit_log_format(ab, " obj=(none)");
|
||||||
rc = 1;
|
rc = 1;
|
||||||
} else {
|
} else {
|
||||||
audit_log_format(ab, " obj=%s", ctx);
|
audit_log_format(ab, " obj=%s", ctx.context);
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audit_log_format(ab, " ocomm=");
|
audit_log_format(ab, " ocomm=");
|
||||||
|
@ -1393,15 +1392,14 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||||
from_kgid(&init_user_ns, context->ipc.gid),
|
from_kgid(&init_user_ns, context->ipc.gid),
|
||||||
context->ipc.mode);
|
context->ipc.mode);
|
||||||
if (lsmprop_is_set(&context->ipc.oprop)) {
|
if (lsmprop_is_set(&context->ipc.oprop)) {
|
||||||
char *ctx = NULL;
|
struct lsm_context lsmctx;
|
||||||
u32 len;
|
|
||||||
|
|
||||||
if (security_lsmprop_to_secctx(&context->ipc.oprop,
|
if (security_lsmprop_to_secctx(&context->ipc.oprop,
|
||||||
&ctx, &len)) {
|
&lsmctx) < 0) {
|
||||||
*call_panic = 1;
|
*call_panic = 1;
|
||||||
} else {
|
} else {
|
||||||
audit_log_format(ab, " obj=%s", ctx);
|
audit_log_format(ab, " obj=%s", lsmctx.context);
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&lsmctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (context->ipc.has_perm) {
|
if (context->ipc.has_perm) {
|
||||||
|
@ -1560,15 +1558,14 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
|
||||||
MAJOR(n->rdev),
|
MAJOR(n->rdev),
|
||||||
MINOR(n->rdev));
|
MINOR(n->rdev));
|
||||||
if (lsmprop_is_set(&n->oprop)) {
|
if (lsmprop_is_set(&n->oprop)) {
|
||||||
char *ctx = NULL;
|
struct lsm_context ctx;
|
||||||
u32 len;
|
|
||||||
|
|
||||||
if (security_lsmprop_to_secctx(&n->oprop, &ctx, &len)) {
|
if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
|
||||||
if (call_panic)
|
if (call_panic)
|
||||||
*call_panic = 2;
|
*call_panic = 2;
|
||||||
} else {
|
} else {
|
||||||
audit_log_format(ab, " obj=%s", ctx);
|
audit_log_format(ab, " obj=%s", ctx.context);
|
||||||
security_release_secctx(ctx, len);
|
security_release_secctx(&ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,20 +128,20 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
|
||||||
|
|
||||||
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
|
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
char *secdata;
|
struct lsm_context ctx;
|
||||||
u32 seclen, secid;
|
u32 secid;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = security_socket_getpeersec_dgram(NULL, skb, &secid);
|
err = security_socket_getpeersec_dgram(NULL, skb, &secid);
|
||||||
if (err)
|
if (err)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err = security_secid_to_secctx(secid, &secdata, &seclen);
|
err = security_secid_to_secctx(secid, &ctx);
|
||||||
if (err)
|
if (err < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
|
put_cmsg(msg, SOL_IP, SCM_SECURITY, ctx.len, ctx.context);
|
||||||
security_release_secctx(secdata, seclen);
|
security_release_secctx(&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
|
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
|
||||||
|
|
|
@ -357,11 +357,11 @@ static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct,
|
||||||
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
struct nlattr *nest_secctx;
|
struct nlattr *nest_secctx;
|
||||||
int len, ret;
|
struct lsm_context ctx;
|
||||||
char *secctx;
|
int ret;
|
||||||
|
|
||||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
ret = security_secid_to_secctx(ct->secmark, &ctx);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -369,13 +369,13 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
||||||
if (!nest_secctx)
|
if (!nest_secctx)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (nla_put_string(skb, CTA_SECCTX_NAME, secctx))
|
if (nla_put_string(skb, CTA_SECCTX_NAME, ctx.context))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
nla_nest_end(skb, nest_secctx);
|
nla_nest_end(skb, nest_secctx);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
security_release_secctx(secctx, len);
|
security_release_secctx(&ctx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -663,14 +663,14 @@ static inline size_t ctnetlink_acct_size(const struct nf_conn *ct)
|
||||||
static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
|
static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
||||||
int len, ret;
|
int ret;
|
||||||
|
|
||||||
ret = security_secid_to_secctx(ct->secmark, NULL, &len);
|
ret = security_secid_to_secctx(ct->secmark, NULL);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return nla_total_size(0) /* CTA_SECCTX */
|
return nla_total_size(0) /* CTA_SECCTX */
|
||||||
+ nla_total_size(sizeof(char) * len); /* CTA_SECCTX_NAME */
|
+ nla_total_size(sizeof(char) * ret); /* CTA_SECCTX_NAME */
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -172,17 +172,16 @@ static void ct_seq_stop(struct seq_file *s, void *v)
|
||||||
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
||||||
static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
|
struct lsm_context ctx;
|
||||||
int ret;
|
int ret;
|
||||||
u32 len;
|
|
||||||
char *secctx;
|
|
||||||
|
|
||||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
ret = security_secid_to_secctx(ct->secmark, &ctx);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
seq_printf(s, "secctx=%s ", secctx);
|
seq_printf(s, "secctx=%s ", ctx.context);
|
||||||
|
|
||||||
security_release_secctx(secctx, len);
|
security_release_secctx(&ctx);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
||||||
|
|
|
@ -470,18 +470,18 @@ static int nfqnl_put_sk_classid(struct sk_buff *skb, struct sock *sk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
|
static int nfqnl_get_sk_secctx(struct sk_buff *skb, struct lsm_context *ctx)
|
||||||
{
|
{
|
||||||
u32 seclen = 0;
|
int seclen = 0;
|
||||||
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
|
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
|
||||||
|
|
||||||
if (!skb || !sk_fullsock(skb->sk))
|
if (!skb || !sk_fullsock(skb->sk))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
read_lock_bh(&skb->sk->sk_callback_lock);
|
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||||
|
|
||||||
if (skb->secmark)
|
if (skb->secmark)
|
||||||
security_secid_to_secctx(skb->secmark, secdata, &seclen);
|
seclen = security_secid_to_secctx(skb->secmark, ctx);
|
||||||
|
|
||||||
read_unlock_bh(&skb->sk->sk_callback_lock);
|
read_unlock_bh(&skb->sk->sk_callback_lock);
|
||||||
#endif
|
#endif
|
||||||
return seclen;
|
return seclen;
|
||||||
|
@ -567,8 +567,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||||
enum ip_conntrack_info ctinfo = 0;
|
enum ip_conntrack_info ctinfo = 0;
|
||||||
const struct nfnl_ct_hook *nfnl_ct;
|
const struct nfnl_ct_hook *nfnl_ct;
|
||||||
bool csum_verify;
|
bool csum_verify;
|
||||||
char *secdata = NULL;
|
struct lsm_context ctx;
|
||||||
u32 seclen = 0;
|
int seclen = 0;
|
||||||
ktime_t tstamp;
|
ktime_t tstamp;
|
||||||
|
|
||||||
size = nlmsg_total_size(sizeof(struct nfgenmsg))
|
size = nlmsg_total_size(sizeof(struct nfgenmsg))
|
||||||
|
@ -642,7 +642,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
|
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
|
||||||
seclen = nfqnl_get_sk_secctx(entskb, &secdata);
|
seclen = nfqnl_get_sk_secctx(entskb, &ctx);
|
||||||
|
if (seclen < 0)
|
||||||
|
return NULL;
|
||||||
if (seclen)
|
if (seclen)
|
||||||
size += nla_total_size(seclen);
|
size += nla_total_size(seclen);
|
||||||
}
|
}
|
||||||
|
@ -782,7 +784,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||||
if (nfqnl_put_sk_classid(skb, entskb->sk) < 0)
|
if (nfqnl_put_sk_classid(skb, entskb->sk) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
|
if (seclen > 0 && nla_put(skb, NFQA_SECCTX, ctx.len, ctx.context))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
|
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
|
||||||
|
@ -810,8 +812,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
nlh->nlmsg_len = skb->len;
|
nlh->nlmsg_len = skb->len;
|
||||||
if (seclen)
|
if (seclen >= 0)
|
||||||
security_release_secctx(secdata, seclen);
|
security_release_secctx(&ctx);
|
||||||
return skb;
|
return skb;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
|
@ -819,8 +821,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
net_err_ratelimited("nf_queue: error creating packet message\n");
|
net_err_ratelimited("nf_queue: error creating packet message\n");
|
||||||
nlmsg_failure:
|
nlmsg_failure:
|
||||||
if (seclen)
|
if (seclen >= 0)
|
||||||
security_release_secctx(secdata, seclen);
|
security_release_secctx(&ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,8 +374,7 @@ int netlbl_unlhsh_add(struct net *net,
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct netlbl_unlhsh_iface *iface;
|
struct netlbl_unlhsh_iface *iface;
|
||||||
struct audit_buffer *audit_buf = NULL;
|
struct audit_buffer *audit_buf = NULL;
|
||||||
char *secctx = NULL;
|
struct lsm_context ctx;
|
||||||
u32 secctx_len;
|
|
||||||
|
|
||||||
if (addr_len != sizeof(struct in_addr) &&
|
if (addr_len != sizeof(struct in_addr) &&
|
||||||
addr_len != sizeof(struct in6_addr))
|
addr_len != sizeof(struct in6_addr))
|
||||||
|
@ -438,11 +437,9 @@ int netlbl_unlhsh_add(struct net *net,
|
||||||
unlhsh_add_return:
|
unlhsh_add_return:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if (audit_buf != NULL) {
|
if (audit_buf != NULL) {
|
||||||
if (security_secid_to_secctx(secid,
|
if (security_secid_to_secctx(secid, &ctx) >= 0) {
|
||||||
&secctx,
|
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||||
&secctx_len) == 0) {
|
security_release_secctx(&ctx);
|
||||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
|
||||||
security_release_secctx(secctx, secctx_len);
|
|
||||||
}
|
}
|
||||||
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
|
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
|
||||||
audit_log_end(audit_buf);
|
audit_log_end(audit_buf);
|
||||||
|
@ -473,8 +470,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
|
||||||
struct netlbl_unlhsh_addr4 *entry;
|
struct netlbl_unlhsh_addr4 *entry;
|
||||||
struct audit_buffer *audit_buf;
|
struct audit_buffer *audit_buf;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
char *secctx;
|
struct lsm_context ctx;
|
||||||
u32 secctx_len;
|
|
||||||
|
|
||||||
spin_lock(&netlbl_unlhsh_lock);
|
spin_lock(&netlbl_unlhsh_lock);
|
||||||
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
|
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
|
||||||
|
@ -494,10 +490,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
|
||||||
addr->s_addr, mask->s_addr);
|
addr->s_addr, mask->s_addr);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
if (entry != NULL &&
|
if (entry != NULL &&
|
||||||
security_secid_to_secctx(entry->secid,
|
security_secid_to_secctx(entry->secid, &ctx) >= 0) {
|
||||||
&secctx, &secctx_len) == 0) {
|
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
security_release_secctx(&ctx);
|
||||||
security_release_secctx(secctx, secctx_len);
|
|
||||||
}
|
}
|
||||||
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
||||||
audit_log_end(audit_buf);
|
audit_log_end(audit_buf);
|
||||||
|
@ -534,8 +529,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
|
||||||
struct netlbl_unlhsh_addr6 *entry;
|
struct netlbl_unlhsh_addr6 *entry;
|
||||||
struct audit_buffer *audit_buf;
|
struct audit_buffer *audit_buf;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
char *secctx;
|
struct lsm_context ctx;
|
||||||
u32 secctx_len;
|
|
||||||
|
|
||||||
spin_lock(&netlbl_unlhsh_lock);
|
spin_lock(&netlbl_unlhsh_lock);
|
||||||
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
|
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
|
||||||
|
@ -554,10 +548,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
|
||||||
addr, mask);
|
addr, mask);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
if (entry != NULL &&
|
if (entry != NULL &&
|
||||||
security_secid_to_secctx(entry->secid,
|
security_secid_to_secctx(entry->secid, &ctx) >= 0) {
|
||||||
&secctx, &secctx_len) == 0) {
|
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
security_release_secctx(&ctx);
|
||||||
security_release_secctx(secctx, secctx_len);
|
|
||||||
}
|
}
|
||||||
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
||||||
audit_log_end(audit_buf);
|
audit_log_end(audit_buf);
|
||||||
|
@ -1069,10 +1062,9 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
|
||||||
int ret_val = -ENOMEM;
|
int ret_val = -ENOMEM;
|
||||||
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
|
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
struct lsm_context ctx;
|
||||||
void *data;
|
void *data;
|
||||||
u32 secid;
|
u32 secid;
|
||||||
char *secctx;
|
|
||||||
u32 secctx_len;
|
|
||||||
|
|
||||||
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
|
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
|
||||||
cb_arg->seq, &netlbl_unlabel_gnl_family,
|
cb_arg->seq, &netlbl_unlabel_gnl_family,
|
||||||
|
@ -1127,14 +1119,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
|
||||||
secid = addr6->secid;
|
secid = addr6->secid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
|
ret_val = security_secid_to_secctx(secid, &ctx);
|
||||||
if (ret_val != 0)
|
if (ret_val < 0)
|
||||||
goto list_cb_failure;
|
goto list_cb_failure;
|
||||||
ret_val = nla_put(cb_arg->skb,
|
ret_val = nla_put(cb_arg->skb,
|
||||||
NLBL_UNLABEL_A_SECCTX,
|
NLBL_UNLABEL_A_SECCTX,
|
||||||
secctx_len,
|
ctx.len,
|
||||||
secctx);
|
ctx.context);
|
||||||
security_release_secctx(secctx, secctx_len);
|
security_release_secctx(&ctx);
|
||||||
if (ret_val != 0)
|
if (ret_val != 0)
|
||||||
goto list_cb_failure;
|
goto list_cb_failure;
|
||||||
|
|
||||||
|
|
|
@ -84,8 +84,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||||
struct netlbl_audit *audit_info)
|
struct netlbl_audit *audit_info)
|
||||||
{
|
{
|
||||||
struct audit_buffer *audit_buf;
|
struct audit_buffer *audit_buf;
|
||||||
char *secctx;
|
struct lsm_context ctx;
|
||||||
u32 secctx_len;
|
|
||||||
|
|
||||||
if (audit_enabled == AUDIT_OFF)
|
if (audit_enabled == AUDIT_OFF)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -99,10 +98,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||||
audit_info->sessionid);
|
audit_info->sessionid);
|
||||||
|
|
||||||
if (lsmprop_is_set(&audit_info->prop) &&
|
if (lsmprop_is_set(&audit_info->prop) &&
|
||||||
security_lsmprop_to_secctx(&audit_info->prop, &secctx,
|
security_lsmprop_to_secctx(&audit_info->prop, &ctx) > 0) {
|
||||||
&secctx_len) == 0) {
|
audit_log_format(audit_buf, " subj=%s", ctx.context);
|
||||||
audit_log_format(audit_buf, " subj=%s", secctx);
|
security_release_secctx(&ctx);
|
||||||
security_release_secctx(secctx, secctx_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return audit_buf;
|
return audit_buf;
|
||||||
|
|
|
@ -8,13 +8,13 @@ void rust_helper_security_cred_getsecid(const struct cred *c, u32 *secid)
|
||||||
security_cred_getsecid(c, secid);
|
security_cred_getsecid(c, secid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rust_helper_security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
int rust_helper_security_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return security_secid_to_secctx(secid, secdata, seclen);
|
return security_secid_to_secctx(secid, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rust_helper_security_release_secctx(char *secdata, u32 seclen)
|
void rust_helper_security_release_secctx(struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
security_release_secctx(secdata, seclen);
|
security_release_secctx(cp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,60 +15,56 @@
|
||||||
///
|
///
|
||||||
/// # Invariants
|
/// # Invariants
|
||||||
///
|
///
|
||||||
/// The `secdata` and `seclen` fields correspond to a valid security context as returned by a
|
/// The `ctx` field corresponds to a valid security context as returned by a successful call to
|
||||||
/// successful call to `security_secid_to_secctx`, that has not yet been destroyed by calling
|
/// `security_secid_to_secctx`, that has not yet been destroyed by `security_release_secctx`.
|
||||||
/// `security_release_secctx`.
|
|
||||||
pub struct SecurityCtx {
|
pub struct SecurityCtx {
|
||||||
secdata: *mut crate::ffi::c_char,
|
ctx: bindings::lsm_context,
|
||||||
seclen: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecurityCtx {
|
impl SecurityCtx {
|
||||||
/// Get the security context given its id.
|
/// Get the security context given its id.
|
||||||
pub fn from_secid(secid: u32) -> Result<Self> {
|
pub fn from_secid(secid: u32) -> Result<Self> {
|
||||||
let mut secdata = core::ptr::null_mut();
|
// SAFETY: `struct lsm_context` can be initialized to all zeros.
|
||||||
let mut seclen = 0u32;
|
let mut ctx: bindings::lsm_context = unsafe { core::mem::zeroed() };
|
||||||
// SAFETY: Just a C FFI call. The pointers are valid for writes.
|
|
||||||
to_result(unsafe { bindings::security_secid_to_secctx(secid, &mut secdata, &mut seclen) })?;
|
// SAFETY: Just a C FFI call. The pointer is valid for writes.
|
||||||
|
to_result(unsafe { bindings::security_secid_to_secctx(secid, &mut ctx) })?;
|
||||||
|
|
||||||
// INVARIANT: If the above call did not fail, then we have a valid security context.
|
// INVARIANT: If the above call did not fail, then we have a valid security context.
|
||||||
Ok(Self {
|
Ok(Self { ctx })
|
||||||
secdata,
|
|
||||||
seclen: seclen as usize,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the security context is empty.
|
/// Returns whether the security context is empty.
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.seclen == 0
|
self.ctx.len == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of this security context.
|
/// Returns the length of this security context.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.seclen
|
self.ctx.len as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the bytes for this security context.
|
/// Returns the bytes for this security context.
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
let ptr = self.secdata;
|
let ptr = self.ctx.context;
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
debug_assert_eq!(self.seclen, 0);
|
debug_assert_eq!(self.len(), 0);
|
||||||
// We can't pass a null pointer to `slice::from_raw_parts` even if the length is zero.
|
// We can't pass a null pointer to `slice::from_raw_parts` even if the length is zero.
|
||||||
return &[];
|
return &[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: The call to `security_secid_to_secctx` guarantees that the pointer is valid for
|
// SAFETY: The call to `security_secid_to_secctx` guarantees that the pointer is valid for
|
||||||
// `seclen` bytes. Furthermore, if the length is zero, then we have ensured that the
|
// `self.len()` bytes. Furthermore, if the length is zero, then we have ensured that the
|
||||||
// pointer is not null.
|
// pointer is not null.
|
||||||
unsafe { core::slice::from_raw_parts(ptr.cast(), self.seclen) }
|
unsafe { core::slice::from_raw_parts(ptr.cast(), self.len()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SecurityCtx {
|
impl Drop for SecurityCtx {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// SAFETY: By the invariant of `Self`, this frees a pointer that came from a successful
|
// SAFETY: By the invariant of `Self`, this frees a context that came from a successful
|
||||||
// call to `security_secid_to_secctx` and has not yet been destroyed by
|
// call to `security_secid_to_secctx` and has not yet been destroyed by
|
||||||
// `security_release_secctx`.
|
// `security_release_secctx`.
|
||||||
unsafe { bindings::security_release_secctx(self.secdata, self.seclen as u32) };
|
unsafe { bindings::security_release_secctx(&mut self.ctx) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,11 @@ config SECURITY
|
||||||
|
|
||||||
If you are unsure how to answer this question, answer N.
|
If you are unsure how to answer this question, answer N.
|
||||||
|
|
||||||
|
config HAS_SECURITY_AUDIT
|
||||||
|
def_bool y
|
||||||
|
depends on AUDIT
|
||||||
|
depends on SECURITY
|
||||||
|
|
||||||
config SECURITYFS
|
config SECURITYFS
|
||||||
bool "Enable the securityfs filesystem"
|
bool "Enable the securityfs filesystem"
|
||||||
help
|
help
|
||||||
|
|
|
@ -15,7 +15,7 @@ obj-$(CONFIG_SECURITY) += security.o
|
||||||
obj-$(CONFIG_SECURITYFS) += inode.o
|
obj-$(CONFIG_SECURITYFS) += inode.o
|
||||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
|
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
|
||||||
obj-$(CONFIG_SECURITY_SMACK) += smack/
|
obj-$(CONFIG_SECURITY_SMACK) += smack/
|
||||||
obj-$(CONFIG_SECURITY) += lsm_audit.o
|
obj-$(CONFIG_HAS_SECURITY_AUDIT) += lsm_audit.o
|
||||||
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
|
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
|
||||||
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
|
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
|
||||||
obj-$(CONFIG_SECURITY_YAMA) += yama/
|
obj-$(CONFIG_SECURITY_YAMA) += yama/
|
||||||
|
|
|
@ -25,11 +25,10 @@ struct aa_label;
|
||||||
extern int apparmor_display_secid_mode;
|
extern int apparmor_display_secid_mode;
|
||||||
|
|
||||||
struct aa_label *aa_secid_to_label(u32 secid);
|
struct aa_label *aa_secid_to_label(u32 secid);
|
||||||
int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
int apparmor_secid_to_secctx(u32 secid, struct lsm_context *cp);
|
||||||
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp);
|
||||||
u32 *seclen);
|
|
||||||
int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
||||||
void apparmor_release_secctx(char *secdata, u32 seclen);
|
void apparmor_release_secctx(struct lsm_context *cp);
|
||||||
|
|
||||||
|
|
||||||
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
|
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
|
||||||
|
|
|
@ -47,23 +47,21 @@ struct aa_label *aa_secid_to_label(u32 secid)
|
||||||
return xa_load(&aa_secids, secid);
|
return xa_load(&aa_secids, secid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int apparmor_label_to_secctx(struct aa_label *label, char **secdata,
|
static int apparmor_label_to_secctx(struct aa_label *label,
|
||||||
u32 *seclen)
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
/* TODO: cache secctx and ref count so we don't have to recreate */
|
/* TODO: cache secctx and ref count so we don't have to recreate */
|
||||||
int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT;
|
int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
AA_BUG(!seclen);
|
|
||||||
|
|
||||||
if (!label)
|
if (!label)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (apparmor_display_secid_mode)
|
if (apparmor_display_secid_mode)
|
||||||
flags |= FLAG_SHOW_MODE;
|
flags |= FLAG_SHOW_MODE;
|
||||||
|
|
||||||
if (secdata)
|
if (cp)
|
||||||
len = aa_label_asxprint(secdata, root_ns, label,
|
len = aa_label_asxprint(&cp->context, root_ns, label,
|
||||||
flags, GFP_ATOMIC);
|
flags, GFP_ATOMIC);
|
||||||
else
|
else
|
||||||
len = aa_label_snxprint(NULL, 0, root_ns, label, flags);
|
len = aa_label_snxprint(NULL, 0, root_ns, label, flags);
|
||||||
|
@ -71,26 +69,28 @@ static int apparmor_label_to_secctx(struct aa_label *label, char **secdata,
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*seclen = len;
|
if (cp) {
|
||||||
|
cp->len = len;
|
||||||
return 0;
|
cp->id = LSM_ID_APPARMOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int apparmor_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
struct aa_label *label = aa_secid_to_label(secid);
|
struct aa_label *label = aa_secid_to_label(secid);
|
||||||
|
|
||||||
return apparmor_label_to_secctx(label, secdata, seclen);
|
return apparmor_label_to_secctx(label, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
|
||||||
u32 *seclen)
|
|
||||||
{
|
{
|
||||||
struct aa_label *label;
|
struct aa_label *label;
|
||||||
|
|
||||||
label = prop->apparmor.label;
|
label = prop->apparmor.label;
|
||||||
|
|
||||||
return apparmor_label_to_secctx(label, secdata, seclen);
|
return apparmor_label_to_secctx(label, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||||
|
@ -106,9 +106,13 @@ int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apparmor_release_secctx(char *secdata, u32 seclen)
|
void apparmor_release_secctx(struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
kfree(secdata);
|
if (cp->id == LSM_ID_APPARMOR) {
|
||||||
|
kfree(cp->context);
|
||||||
|
cp->context = NULL;
|
||||||
|
cp->id = LSM_ID_UNDEF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -96,7 +96,7 @@ static int __init lockdown_lsm_init(void)
|
||||||
static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
|
static ssize_t lockdown_read(struct file *filp, char __user *buf, size_t count,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
char temp[80];
|
char temp[80] = "";
|
||||||
int i, offset = 0;
|
int i, offset = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
|
for (i = 0; i < ARRAY_SIZE(lockdown_levels); i++) {
|
||||||
|
|
|
@ -171,7 +171,7 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
||||||
|
|
||||||
static inline void print_ipv6_addr(struct audit_buffer *ab,
|
static inline void print_ipv6_addr(struct audit_buffer *ab,
|
||||||
const struct in6_addr *addr, __be16 port,
|
const struct in6_addr *addr, __be16 port,
|
||||||
char *name1, char *name2)
|
const char *name1, const char *name2)
|
||||||
{
|
{
|
||||||
if (!ipv6_addr_any(addr))
|
if (!ipv6_addr_any(addr))
|
||||||
audit_log_format(ab, " %s=%pI6c", name1, addr);
|
audit_log_format(ab, " %s=%pI6c", name1, addr);
|
||||||
|
@ -180,7 +180,7 @@ static inline void print_ipv6_addr(struct audit_buffer *ab,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
|
static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
|
||||||
__be16 port, char *name1, char *name2)
|
__be16 port, const char *name1, const char *name2)
|
||||||
{
|
{
|
||||||
if (addr)
|
if (addr)
|
||||||
audit_log_format(ab, " %s=%pI4", name1, &addr);
|
audit_log_format(ab, " %s=%pI4", name1, &addr);
|
||||||
|
@ -299,10 +299,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||||
if (tsk) {
|
if (tsk) {
|
||||||
pid_t pid = task_tgid_nr(tsk);
|
pid_t pid = task_tgid_nr(tsk);
|
||||||
if (pid) {
|
if (pid) {
|
||||||
char comm[sizeof(tsk->comm)];
|
char tskcomm[sizeof(tsk->comm)];
|
||||||
audit_log_format(ab, " opid=%d ocomm=", pid);
|
audit_log_format(ab, " opid=%d ocomm=", pid);
|
||||||
audit_log_untrustedstring(ab,
|
audit_log_untrustedstring(ab,
|
||||||
get_task_comm(comm, tsk));
|
get_task_comm(tskcomm, tsk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -143,6 +143,9 @@ static ssize_t handle_policy_update(struct file *file,
|
||||||
char *buf, *p, *end;
|
char *buf, *p, *end;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (len >= KMALLOC_MAX_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
pol = kmalloc(sizeof(struct setid_ruleset), GFP_KERNEL);
|
pol = kmalloc(sizeof(struct setid_ruleset), GFP_KERNEL);
|
||||||
if (!pol)
|
if (!pol)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
@ -4139,10 +4138,8 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
|
||||||
if (base)
|
if (base)
|
||||||
uctx = (struct lsm_ctx __user *)(base + total);
|
uctx = (struct lsm_ctx __user *)(base + total);
|
||||||
rc = scall->hl->hook.getselfattr(attr, uctx, &entrysize, flags);
|
rc = scall->hl->hook.getselfattr(attr, uctx, &entrysize, flags);
|
||||||
if (rc == -EOPNOTSUPP) {
|
if (rc == -EOPNOTSUPP)
|
||||||
rc = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (rc == -E2BIG) {
|
if (rc == -E2BIG) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
left = 0;
|
left = 0;
|
||||||
|
@ -4304,40 +4301,36 @@ EXPORT_SYMBOL(security_ismaclabel);
|
||||||
/**
|
/**
|
||||||
* security_secid_to_secctx() - Convert a secid to a secctx
|
* security_secid_to_secctx() - Convert a secid to a secctx
|
||||||
* @secid: secid
|
* @secid: secid
|
||||||
* @secdata: secctx
|
* @cp: the LSM context
|
||||||
* @seclen: secctx length
|
|
||||||
*
|
*
|
||||||
* Convert secid to security context. If @secdata is NULL the length of the
|
* Convert secid to security context. If @cp is NULL the length of the
|
||||||
* result will be returned in @seclen, but no @secdata will be returned. This
|
* result will be returned, but no data will be returned. This
|
||||||
* does mean that the length could change between calls to check the length and
|
* does mean that the length could change between calls to check the length and
|
||||||
* the next call which actually allocates and returns the @secdata.
|
* the next call which actually allocates and returns the data.
|
||||||
*
|
*
|
||||||
* Return: Return 0 on success, error on failure.
|
* Return: Return length of data on success, error on failure.
|
||||||
*/
|
*/
|
||||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
int security_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return call_int_hook(secid_to_secctx, secid, secdata, seclen);
|
return call_int_hook(secid_to_secctx, secid, cp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_secid_to_secctx);
|
EXPORT_SYMBOL(security_secid_to_secctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx
|
* security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx
|
||||||
* @prop: lsm specific information
|
* @prop: lsm specific information
|
||||||
* @secdata: secctx
|
* @cp: the LSM context
|
||||||
* @seclen: secctx length
|
|
||||||
*
|
*
|
||||||
* Convert a @prop entry to security context. If @secdata is NULL the
|
* Convert a @prop entry to security context. If @cp is NULL the
|
||||||
* length of the result will be returned in @seclen, but no @secdata
|
* length of the result will be returned. This does mean that the
|
||||||
* will be returned. This does mean that the length could change between
|
* length could change between calls to check the length and the
|
||||||
* calls to check the length and the next call which actually allocates
|
* next call which actually allocates and returns the @cp.
|
||||||
* and returns the @secdata.
|
|
||||||
*
|
*
|
||||||
* Return: Return 0 on success, error on failure.
|
* Return: Return length of data on success, error on failure.
|
||||||
*/
|
*/
|
||||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
|
||||||
u32 *seclen)
|
|
||||||
{
|
{
|
||||||
return call_int_hook(lsmprop_to_secctx, prop, secdata, seclen);
|
return call_int_hook(lsmprop_to_secctx, prop, cp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_lsmprop_to_secctx);
|
EXPORT_SYMBOL(security_lsmprop_to_secctx);
|
||||||
|
|
||||||
|
@ -4360,14 +4353,14 @@ EXPORT_SYMBOL(security_secctx_to_secid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* security_release_secctx() - Free a secctx buffer
|
* security_release_secctx() - Free a secctx buffer
|
||||||
* @secdata: secctx
|
* @cp: the security context
|
||||||
* @seclen: length of secctx
|
|
||||||
*
|
*
|
||||||
* Release the security context.
|
* Release the security context.
|
||||||
*/
|
*/
|
||||||
void security_release_secctx(char *secdata, u32 seclen)
|
void security_release_secctx(struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
call_void_hook(release_secctx, secdata, seclen);
|
call_void_hook(release_secctx, cp);
|
||||||
|
memset(cp, 0, sizeof(*cp));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_release_secctx);
|
EXPORT_SYMBOL(security_release_secctx);
|
||||||
|
|
||||||
|
@ -4430,17 +4423,17 @@ EXPORT_SYMBOL(security_inode_setsecctx);
|
||||||
/**
|
/**
|
||||||
* security_inode_getsecctx() - Get the security label of an inode
|
* security_inode_getsecctx() - Get the security label of an inode
|
||||||
* @inode: inode
|
* @inode: inode
|
||||||
* @ctx: secctx
|
* @cp: security context
|
||||||
* @ctxlen: length of secctx
|
|
||||||
*
|
*
|
||||||
* On success, returns 0 and fills out @ctx and @ctxlen with the security
|
* On success, returns 0 and fills out @cp with the security context
|
||||||
* context for the given @inode.
|
* for the given @inode.
|
||||||
*
|
*
|
||||||
* Return: Returns 0 on success, error on failure.
|
* Return: Returns 0 on success, error on failure.
|
||||||
*/
|
*/
|
||||||
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
|
int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return call_int_hook(inode_getsecctx, inode, ctx, ctxlen);
|
memset(cp, 0, sizeof(*cp));
|
||||||
|
return call_int_hook(inode_getsecctx, inode, cp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(security_inode_getsecctx);
|
EXPORT_SYMBOL(security_inode_getsecctx);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -6640,15 +6640,28 @@ static int selinux_ismaclabel(const char *name)
|
||||||
return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
|
return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
static int selinux_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return security_sid_to_context(secid, secdata, seclen);
|
u32 seclen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (cp) {
|
||||||
|
cp->id = LSM_ID_SELINUX;
|
||||||
|
ret = security_sid_to_context(secid, &cp->context, &cp->len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return cp->len;
|
||||||
|
}
|
||||||
|
ret = security_sid_to_context(secid, NULL, &seclen);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return seclen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
static int selinux_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||||
u32 *seclen)
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
return selinux_secid_to_secctx(prop->selinux.secid, secdata, seclen);
|
return selinux_secid_to_secctx(prop->selinux.secid, cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||||
|
@ -6657,9 +6670,13 @@ static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||||
secid, GFP_KERNEL);
|
secid, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void selinux_release_secctx(char *secdata, u32 seclen)
|
static void selinux_release_secctx(struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
kfree(secdata);
|
if (cp->id == LSM_ID_SELINUX) {
|
||||||
|
kfree(cp->context);
|
||||||
|
cp->context = NULL;
|
||||||
|
cp->id = LSM_ID_UNDEF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void selinux_inode_invalidate_secctx(struct inode *inode)
|
static void selinux_inode_invalidate_secctx(struct inode *inode)
|
||||||
|
@ -6691,14 +6708,16 @@ static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
|
||||||
ctx, ctxlen, 0, NULL);
|
ctx, ctxlen, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
|
static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len;
|
||||||
len = selinux_inode_getsecurity(&nop_mnt_idmap, inode,
|
len = selinux_inode_getsecurity(&nop_mnt_idmap, inode,
|
||||||
XATTR_SELINUX_SUFFIX, ctx, true);
|
XATTR_SELINUX_SUFFIX,
|
||||||
|
(void **)&cp->context, true);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return len;
|
return len;
|
||||||
*ctxlen = len;
|
cp->len = len;
|
||||||
|
cp->id = LSM_ID_SELINUX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_KEYS
|
#ifdef CONFIG_KEYS
|
||||||
|
|
|
@ -4801,41 +4801,48 @@ static int smack_ismaclabel(const char *name)
|
||||||
return (strcmp(name, XATTR_SMACK_SUFFIX) == 0);
|
return (strcmp(name, XATTR_SMACK_SUFFIX) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_to_secctx - fill a lsm_context
|
||||||
|
* @skp: Smack label
|
||||||
|
* @cp: destination
|
||||||
|
*
|
||||||
|
* Fill the passed @cp and return the length of the string
|
||||||
|
*/
|
||||||
|
static int smack_to_secctx(struct smack_known *skp, struct lsm_context *cp)
|
||||||
|
{
|
||||||
|
int len = strlen(skp->smk_known);
|
||||||
|
|
||||||
|
if (cp) {
|
||||||
|
cp->context = skp->smk_known;
|
||||||
|
cp->len = len;
|
||||||
|
cp->id = LSM_ID_SMACK;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_secid_to_secctx - return the smack label for a secid
|
* smack_secid_to_secctx - return the smack label for a secid
|
||||||
* @secid: incoming integer
|
* @secid: incoming integer
|
||||||
* @secdata: destination
|
* @cp: destination
|
||||||
* @seclen: how long it is
|
|
||||||
*
|
*
|
||||||
* Exists for networking code.
|
* Exists for networking code.
|
||||||
*/
|
*/
|
||||||
static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
static int smack_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
struct smack_known *skp = smack_from_secid(secid);
|
return smack_to_secctx(smack_from_secid(secid), cp);
|
||||||
|
|
||||||
if (secdata)
|
|
||||||
*secdata = skp->smk_known;
|
|
||||||
*seclen = strlen(skp->smk_known);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_lsmprop_to_secctx - return the smack label
|
* smack_lsmprop_to_secctx - return the smack label
|
||||||
* @prop: includes incoming Smack data
|
* @prop: includes incoming Smack data
|
||||||
* @secdata: destination
|
* @cp: destination
|
||||||
* @seclen: how long it is
|
|
||||||
*
|
*
|
||||||
* Exists for audit code.
|
* Exists for audit code.
|
||||||
*/
|
*/
|
||||||
static int smack_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
static int smack_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||||
u32 *seclen)
|
struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
struct smack_known *skp = prop->smack.skp;
|
return smack_to_secctx(prop->smack.skp, cp);
|
||||||
|
|
||||||
if (secdata)
|
|
||||||
*secdata = skp->smk_known;
|
|
||||||
*seclen = strlen(skp->smk_known);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4875,12 +4882,13 @@ static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
|
||||||
ctx, ctxlen, 0, NULL);
|
ctx, ctxlen, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
|
static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
|
||||||
{
|
{
|
||||||
struct smack_known *skp = smk_of_inode(inode);
|
struct smack_known *skp = smk_of_inode(inode);
|
||||||
|
|
||||||
*ctx = skp->smk_known;
|
cp->context = skp->smk_known;
|
||||||
*ctxlen = strlen(skp->smk_known);
|
cp->len = strlen(skp->smk_known);
|
||||||
|
cp->id = LSM_ID_SMACK;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,16 +56,15 @@ TEST(flags_zero_lsm_set_self_attr)
|
||||||
TEST(flags_overset_lsm_set_self_attr)
|
TEST(flags_overset_lsm_set_self_attr)
|
||||||
{
|
{
|
||||||
const long page_size = sysconf(_SC_PAGESIZE);
|
const long page_size = sysconf(_SC_PAGESIZE);
|
||||||
char *ctx = calloc(page_size, 1);
|
struct lsm_ctx *ctx = calloc(page_size, 1);
|
||||||
__u32 size = page_size;
|
__u32 size = page_size;
|
||||||
struct lsm_ctx *tctx = (struct lsm_ctx *)ctx;
|
|
||||||
|
|
||||||
ASSERT_NE(NULL, ctx);
|
ASSERT_NE(NULL, ctx);
|
||||||
if (attr_lsm_count()) {
|
if (attr_lsm_count()) {
|
||||||
ASSERT_LE(1, lsm_get_self_attr(LSM_ATTR_CURRENT, tctx, &size,
|
ASSERT_LE(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size,
|
||||||
0));
|
0));
|
||||||
}
|
}
|
||||||
ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, tctx,
|
ASSERT_EQ(-1, lsm_set_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, ctx,
|
||||||
size, 0));
|
size, 0));
|
||||||
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
|
Loading…
Reference in a new issue