mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 00:32:00 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
This commit is contained in:
commit
f5cf996f5c
@ -3017,8 +3017,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
struct binder_context *context = proc->context;
|
||||
int t_debug_id = atomic_inc_return(&binder_last_id);
|
||||
ktime_t t_start_time = ktime_get();
|
||||
char *secctx = NULL;
|
||||
u32 secctx_sz = 0;
|
||||
struct lsm_context lsmctx = { };
|
||||
struct list_head sgc_head;
|
||||
struct list_head pf_head;
|
||||
const void __user *user_buffer = (const void __user *)
|
||||
@ -3297,8 +3296,8 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
size_t added_size;
|
||||
|
||||
security_cred_getsecid(proc->cred, &secid);
|
||||
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
|
||||
if (ret) {
|
||||
ret = security_secid_to_secctx(secid, &lsmctx);
|
||||
if (ret < 0) {
|
||||
binder_txn_error("%d:%d failed to get security context\n",
|
||||
thread->pid, proc->pid);
|
||||
return_error = BR_FAILED_REPLY;
|
||||
@ -3306,7 +3305,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_get_secctx_failed;
|
||||
}
|
||||
added_size = ALIGN(secctx_sz, sizeof(u64));
|
||||
added_size = ALIGN(lsmctx.len, sizeof(u64));
|
||||
extra_buffers_size += added_size;
|
||||
if (extra_buffers_size < added_size) {
|
||||
binder_txn_error("%d:%d integer overflow of extra_buffers_size\n",
|
||||
@ -3340,23 +3339,23 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
t->buffer = NULL;
|
||||
goto err_binder_alloc_buf_failed;
|
||||
}
|
||||
if (secctx) {
|
||||
if (lsmctx.context) {
|
||||
int err;
|
||||
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
|
||||
ALIGN(tr->offsets_size, sizeof(void *)) +
|
||||
ALIGN(extra_buffers_size, sizeof(void *)) -
|
||||
ALIGN(secctx_sz, sizeof(u64));
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
|
||||
t->security_ctx = t->buffer->user_data + buf_offset;
|
||||
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
|
||||
t->buffer, buf_offset,
|
||||
secctx, secctx_sz);
|
||||
lsmctx.context, lsmctx.len);
|
||||
if (err) {
|
||||
t->security_ctx = 0;
|
||||
WARN_ON(1);
|
||||
}
|
||||
security_release_secctx(secctx, secctx_sz);
|
||||
secctx = NULL;
|
||||
security_release_secctx(&lsmctx);
|
||||
lsmctx.context = NULL;
|
||||
}
|
||||
t->buffer->debug_id = t->debug_id;
|
||||
t->buffer->transaction = t;
|
||||
@ -3400,7 +3399,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
off_end_offset = off_start_offset + tr->offsets_size;
|
||||
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
|
||||
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
|
||||
ALIGN(secctx_sz, sizeof(u64));
|
||||
ALIGN(lsmctx.len, sizeof(u64));
|
||||
off_min = 0;
|
||||
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
|
||||
buffer_offset += sizeof(binder_size_t)) {
|
||||
@ -3779,8 +3778,8 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
|
||||
err_binder_alloc_buf_failed:
|
||||
err_bad_extra_size:
|
||||
if (secctx)
|
||||
security_release_secctx(secctx, secctx_sz);
|
||||
if (lsmctx.context)
|
||||
security_release_secctx(&lsmctx);
|
||||
err_get_secctx_failed:
|
||||
kfree(tcomplete);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||
|
@ -1132,8 +1132,7 @@ struct ceph_acl_sec_ctx {
|
||||
void *acl;
|
||||
#endif
|
||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||
void *sec_ctx;
|
||||
u32 sec_ctxlen;
|
||||
struct lsm_context lsmctx;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
struct ceph_fscrypt_auth *fscrypt_auth;
|
||||
|
@ -1383,8 +1383,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
|
||||
int err;
|
||||
|
||||
err = security_dentry_init_security(dentry, mode, &dentry->d_name,
|
||||
&name, &as_ctx->sec_ctx,
|
||||
&as_ctx->sec_ctxlen);
|
||||
&name, &as_ctx->lsmctx);
|
||||
if (err < 0) {
|
||||
WARN_ON_ONCE(err != -EOPNOTSUPP);
|
||||
err = 0; /* do nothing */
|
||||
@ -1409,7 +1408,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
|
||||
*/
|
||||
name_len = strlen(name);
|
||||
err = ceph_pagelist_reserve(pagelist,
|
||||
4 * 2 + name_len + as_ctx->sec_ctxlen);
|
||||
4 * 2 + name_len + as_ctx->lsmctx.len);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -1432,8 +1431,9 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
|
||||
ceph_pagelist_encode_32(pagelist, name_len);
|
||||
ceph_pagelist_append(pagelist, name, name_len);
|
||||
|
||||
ceph_pagelist_encode_32(pagelist, as_ctx->sec_ctxlen);
|
||||
ceph_pagelist_append(pagelist, as_ctx->sec_ctx, as_ctx->sec_ctxlen);
|
||||
ceph_pagelist_encode_32(pagelist, as_ctx->lsmctx.len);
|
||||
ceph_pagelist_append(pagelist, as_ctx->lsmctx.context,
|
||||
as_ctx->lsmctx.len);
|
||||
|
||||
err = 0;
|
||||
out:
|
||||
@ -1451,7 +1451,7 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
|
||||
posix_acl_release(as_ctx->default_acl);
|
||||
#endif
|
||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||
security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
|
||||
security_release_secctx(&as_ctx->lsmctx);
|
||||
#endif
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
kfree(as_ctx->fscrypt_auth);
|
||||
|
@ -467,29 +467,29 @@ static int get_security_context(struct dentry *entry, umode_t mode,
|
||||
{
|
||||
struct fuse_secctx *fctx;
|
||||
struct fuse_secctx_header *header;
|
||||
void *ctx = NULL, *ptr;
|
||||
u32 ctxlen, total_len = sizeof(*header);
|
||||
struct lsm_context lsmctx = { };
|
||||
void *ptr;
|
||||
u32 total_len = sizeof(*header);
|
||||
int err, nr_ctx = 0;
|
||||
const char *name;
|
||||
const char *name = NULL;
|
||||
size_t namelen;
|
||||
|
||||
err = security_dentry_init_security(entry, mode, &entry->d_name,
|
||||
&name, &ctx, &ctxlen);
|
||||
if (err) {
|
||||
if (err != -EOPNOTSUPP)
|
||||
goto out_err;
|
||||
/* No LSM is supporting this security hook. Ignore error */
|
||||
ctxlen = 0;
|
||||
ctx = NULL;
|
||||
}
|
||||
&name, &lsmctx);
|
||||
|
||||
if (ctxlen) {
|
||||
/* If no LSM is supporting this security hook ignore error */
|
||||
if (err && err != -EOPNOTSUPP)
|
||||
goto out_err;
|
||||
|
||||
if (lsmctx.len) {
|
||||
nr_ctx = 1;
|
||||
namelen = strlen(name) + 1;
|
||||
err = -EIO;
|
||||
if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX))
|
||||
if (WARN_ON(namelen > XATTR_NAME_MAX + 1 ||
|
||||
lsmctx.len > S32_MAX))
|
||||
goto out_err;
|
||||
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
|
||||
total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen +
|
||||
lsmctx.len);
|
||||
}
|
||||
|
||||
err = -ENOMEM;
|
||||
@ -502,19 +502,20 @@ static int get_security_context(struct dentry *entry, umode_t mode,
|
||||
ptr += sizeof(*header);
|
||||
if (nr_ctx) {
|
||||
fctx = ptr;
|
||||
fctx->size = ctxlen;
|
||||
fctx->size = lsmctx.len;
|
||||
ptr += sizeof(*fctx);
|
||||
|
||||
strcpy(ptr, name);
|
||||
ptr += namelen;
|
||||
|
||||
memcpy(ptr, ctx, ctxlen);
|
||||
memcpy(ptr, lsmctx.context, lsmctx.len);
|
||||
}
|
||||
ext->size = total_len;
|
||||
ext->value = header;
|
||||
err = 0;
|
||||
out_err:
|
||||
kfree(ctx);
|
||||
if (nr_ctx)
|
||||
security_release_secctx(&lsmctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,7 @@ static inline struct nfs4_label *
|
||||
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
||||
struct iattr *sattr, struct nfs4_label *label)
|
||||
{
|
||||
struct lsm_context shim;
|
||||
int err;
|
||||
|
||||
if (label == NULL)
|
||||
@ -128,18 +129,25 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
||||
label->label = NULL;
|
||||
|
||||
err = security_dentry_init_security(dentry, sattr->ia_mode,
|
||||
&dentry->d_name, NULL,
|
||||
(void **)&label->label, &label->len);
|
||||
if (err == 0)
|
||||
return label;
|
||||
&dentry->d_name, NULL, &shim);
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
label->label = shim.context;
|
||||
label->len = shim.len;
|
||||
return label;
|
||||
}
|
||||
static inline void
|
||||
nfs4_label_release_security(struct nfs4_label *label)
|
||||
{
|
||||
if (label)
|
||||
security_release_secctx(label->label, label->len);
|
||||
struct lsm_context shim;
|
||||
|
||||
if (label) {
|
||||
shim.context = label->label;
|
||||
shim.len = label->len;
|
||||
shim.id = LSM_ID_UNDEF;
|
||||
security_release_secctx(&shim);
|
||||
}
|
||||
}
|
||||
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
|
||||
{
|
||||
|
@ -2818,11 +2818,11 @@ static __be32 nfsd4_encode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqst
|
||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||
static inline __be32
|
||||
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
||||
void *context, int len)
|
||||
const struct lsm_context *context)
|
||||
{
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
|
||||
p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4);
|
||||
if (!p)
|
||||
return nfserr_resource;
|
||||
|
||||
@ -2832,13 +2832,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
||||
*/
|
||||
*p++ = cpu_to_be32(0); /* lfs */
|
||||
*p++ = cpu_to_be32(0); /* pi */
|
||||
p = xdr_encode_opaque(p, context, len);
|
||||
p = xdr_encode_opaque(p, context->context, context->len);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline __be32
|
||||
nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
|
||||
void *context, int len)
|
||||
struct lsm_context *context)
|
||||
{ return 0; }
|
||||
#endif
|
||||
|
||||
@ -2920,8 +2920,7 @@ struct nfsd4_fattr_args {
|
||||
struct kstatfs statfs;
|
||||
struct nfs4_acl *acl;
|
||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||
void *context;
|
||||
int contextlen;
|
||||
struct lsm_context context;
|
||||
#endif
|
||||
u32 rdattr_err;
|
||||
bool contextsupport;
|
||||
@ -3376,8 +3375,7 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
|
||||
static __be32 nfsd4_encode_fattr4_sec_label(struct xdr_stream *xdr,
|
||||
const struct nfsd4_fattr_args *args)
|
||||
{
|
||||
return nfsd4_encode_security_label(xdr, args->rqstp,
|
||||
args->context, args->contextlen);
|
||||
return nfsd4_encode_security_label(xdr, args->rqstp, &args->context);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3527,7 +3525,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||
args.ignore_crossmnt = (ignore_crossmnt != 0);
|
||||
args.acl = NULL;
|
||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||
args.context = NULL;
|
||||
args.context.context = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -3607,7 +3605,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||
attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
|
||||
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
|
||||
err = security_inode_getsecctx(d_inode(dentry),
|
||||
&args.context, &args.contextlen);
|
||||
&args.context);
|
||||
else
|
||||
err = -EOPNOTSUPP;
|
||||
args.contextsupport = (err == 0);
|
||||
@ -3644,8 +3642,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
|
||||
|
||||
out:
|
||||
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
|
||||
if (args.context)
|
||||
security_release_secctx(args.context, args.contextlen);
|
||||
if (args.context.context)
|
||||
security_release_secctx(&args.context);
|
||||
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
|
||||
kfree(args.acl);
|
||||
if (tempfh) {
|
||||
|
@ -83,7 +83,7 @@ LSM_HOOK(int, 0, move_mount, const struct path *from_path,
|
||||
const struct path *to_path)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
|
||||
int mode, const struct qstr *name, const char **xattr_name,
|
||||
void **ctx, u32 *ctxlen)
|
||||
struct lsm_context *cp)
|
||||
LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode,
|
||||
struct qstr *name, const struct cred *old, struct cred *new)
|
||||
|
||||
@ -295,17 +295,16 @@ LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
|
||||
char **value)
|
||||
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
|
||||
LSM_HOOK(int, 0, ismaclabel, const char *name)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata,
|
||||
u32 *seclen)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsm_context *cp)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop,
|
||||
char **secdata, u32 *seclen)
|
||||
struct lsm_context *cp)
|
||||
LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid)
|
||||
LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen)
|
||||
LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp)
|
||||
LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode)
|
||||
LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen)
|
||||
LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, void **ctx,
|
||||
u32 *ctxlen)
|
||||
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode,
|
||||
struct lsm_context *cp)
|
||||
|
||||
#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
|
||||
LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
|
||||
|
@ -225,6 +225,18 @@ extern unsigned long dac_mmap_min_addr;
|
||||
#define dac_mmap_min_addr 0UL
|
||||
#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
|
||||
*/
|
||||
@ -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_dentry_init_security(struct dentry *dentry, int mode,
|
||||
const struct qstr *name,
|
||||
const char **xattr_name, void **ctx,
|
||||
u32 *ctxlen);
|
||||
const char **xattr_name,
|
||||
struct lsm_context *lsmcxt);
|
||||
int security_dentry_create_files_as(struct dentry *dentry, int mode,
|
||||
struct qstr *name,
|
||||
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_netlink_send(struct sock *sk, struct sk_buff *skb);
|
||||
int security_ismaclabel(const char *name);
|
||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, u32 *seclen);
|
||||
int security_secid_to_secctx(u32 secid, struct lsm_context *cp);
|
||||
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);
|
||||
void security_release_secctx(char *secdata, u32 seclen);
|
||||
void security_release_secctx(struct lsm_context *cp);
|
||||
void security_inode_invalidate_secctx(struct inode *inode);
|
||||
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_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 lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
|
||||
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,
|
||||
const struct qstr *name,
|
||||
const char **xattr_name,
|
||||
void **ctx,
|
||||
u32 *ctxlen)
|
||||
struct lsm_context *lsmcxt)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -1526,14 +1537,13 @@ static inline int security_ismaclabel(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_secid_to_secctx(u32 secid, char **secdata,
|
||||
u32 *seclen)
|
||||
static inline int security_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int security_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||
char **secdata, u32 *seclen)
|
||||
struct lsm_context *cp)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -1545,7 +1555,7 @@ static inline int security_secctx_to_secid(const char *secdata,
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -105,16 +105,16 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
|
||||
{
|
||||
char *secdata;
|
||||
u32 seclen;
|
||||
struct lsm_context ctx;
|
||||
int err;
|
||||
|
||||
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) {
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
|
||||
security_release_secctx(secdata, seclen);
|
||||
if (err >= 0) {
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
|
||||
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;
|
||||
u16 msg_type = nlh->nlmsg_type;
|
||||
struct audit_sig_info *sig_data;
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
struct lsm_context lsmctx;
|
||||
|
||||
err = audit_netlink_ok(skb, msg_type);
|
||||
if (err)
|
||||
@ -1472,27 +1471,28 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
break;
|
||||
}
|
||||
case AUDIT_SIGNAL_INFO:
|
||||
len = 0;
|
||||
if (lsmprop_is_set(&audit_sig_lsm)) {
|
||||
err = security_lsmprop_to_secctx(&audit_sig_lsm, &ctx,
|
||||
&len);
|
||||
if (err)
|
||||
err = security_lsmprop_to_secctx(&audit_sig_lsm,
|
||||
&lsmctx);
|
||||
if (err < 0)
|
||||
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 (lsmprop_is_set(&audit_sig_lsm))
|
||||
security_release_secctx(ctx, len);
|
||||
security_release_secctx(&lsmctx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
|
||||
sig_data->pid = audit_sig_pid;
|
||||
if (lsmprop_is_set(&audit_sig_lsm)) {
|
||||
memcpy(sig_data->ctx, ctx, len);
|
||||
security_release_secctx(ctx, len);
|
||||
memcpy(sig_data->ctx, lsmctx.context, lsmctx.len);
|
||||
security_release_secctx(&lsmctx);
|
||||
}
|
||||
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);
|
||||
break;
|
||||
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)
|
||||
{
|
||||
struct lsm_prop prop;
|
||||
char *ctx = NULL;
|
||||
unsigned len;
|
||||
struct lsm_context ctx;
|
||||
int error;
|
||||
|
||||
security_current_getlsmprop_subj(&prop);
|
||||
if (!lsmprop_is_set(&prop))
|
||||
return 0;
|
||||
|
||||
error = security_lsmprop_to_secctx(&prop, &ctx, &len);
|
||||
if (error) {
|
||||
error = security_lsmprop_to_secctx(&prop, &ctx);
|
||||
if (error < 0) {
|
||||
if (error != -EINVAL)
|
||||
goto error_path;
|
||||
return 0;
|
||||
}
|
||||
|
||||
audit_log_format(ab, " subj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
audit_log_format(ab, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
return 0;
|
||||
|
||||
error_path:
|
||||
|
@ -1098,8 +1098,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||
char *comm)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
struct lsm_context ctx;
|
||||
int rc = 0;
|
||||
|
||||
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, uid), sessionid);
|
||||
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)");
|
||||
rc = 1;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
audit_log_format(ab, " obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
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),
|
||||
context->ipc.mode);
|
||||
if (lsmprop_is_set(&context->ipc.oprop)) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
struct lsm_context lsmctx;
|
||||
|
||||
if (security_lsmprop_to_secctx(&context->ipc.oprop,
|
||||
&ctx, &len)) {
|
||||
&lsmctx) < 0) {
|
||||
*call_panic = 1;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
audit_log_format(ab, " obj=%s", lsmctx.context);
|
||||
security_release_secctx(&lsmctx);
|
||||
}
|
||||
}
|
||||
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),
|
||||
MINOR(n->rdev));
|
||||
if (lsmprop_is_set(&n->oprop)) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (security_lsmprop_to_secctx(&n->oprop, &ctx, &len)) {
|
||||
if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
|
||||
if (call_panic)
|
||||
*call_panic = 2;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
audit_log_format(ab, " obj=%s", ctx.context);
|
||||
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)
|
||||
{
|
||||
char *secdata;
|
||||
u32 seclen, secid;
|
||||
struct lsm_context ctx;
|
||||
u32 secid;
|
||||
int err;
|
||||
|
||||
err = security_socket_getpeersec_dgram(NULL, skb, &secid);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
err = security_secid_to_secctx(secid, &secdata, &seclen);
|
||||
if (err)
|
||||
err = security_secid_to_secctx(secid, &ctx);
|
||||
if (err < 0)
|
||||
return;
|
||||
|
||||
put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
|
||||
security_release_secctx(secdata, seclen);
|
||||
put_cmsg(msg, SOL_IP, SCM_SECURITY, ctx.len, ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct nlattr *nest_secctx;
|
||||
int len, ret;
|
||||
char *secctx;
|
||||
struct lsm_context ctx;
|
||||
int ret;
|
||||
|
||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
||||
if (ret)
|
||||
ret = security_secid_to_secctx(ct->secmark, &ctx);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
ret = -1;
|
||||
@ -369,13 +369,13 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
||||
if (!nest_secctx)
|
||||
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;
|
||||
nla_nest_end(skb, nest_secctx);
|
||||
|
||||
ret = 0;
|
||||
nla_put_failure:
|
||||
security_release_secctx(secctx, len);
|
||||
security_release_secctx(&ctx);
|
||||
return ret;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
||||
int len, ret;
|
||||
int ret;
|
||||
|
||||
ret = security_secid_to_secctx(ct->secmark, NULL, &len);
|
||||
if (ret)
|
||||
ret = security_secid_to_secctx(ct->secmark, NULL);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
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
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -172,17 +172,16 @@ static void ct_seq_stop(struct seq_file *s, void *v)
|
||||
#ifdef CONFIG_NF_CONNTRACK_SECMARK
|
||||
static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
||||
{
|
||||
struct lsm_context ctx;
|
||||
int ret;
|
||||
u32 len;
|
||||
char *secctx;
|
||||
|
||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
||||
if (ret)
|
||||
ret = security_secid_to_secctx(ct->secmark, &ctx);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
seq_printf(s, "secctx=%s ", secctx);
|
||||
seq_printf(s, "secctx=%s ", ctx.context);
|
||||
|
||||
security_release_secctx(secctx, len);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
#else
|
||||
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;
|
||||
}
|
||||
|
||||
static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
|
||||
static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, struct lsm_context *ctx)
|
||||
{
|
||||
u32 seclen = 0;
|
||||
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
|
||||
|
||||
if (!skb || !sk_fullsock(skb->sk))
|
||||
return 0;
|
||||
|
||||
read_lock_bh(&skb->sk->sk_callback_lock);
|
||||
|
||||
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);
|
||||
#endif
|
||||
return seclen;
|
||||
@ -567,7 +567,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
enum ip_conntrack_info ctinfo = 0;
|
||||
const struct nfnl_ct_hook *nfnl_ct;
|
||||
bool csum_verify;
|
||||
char *secdata = NULL;
|
||||
struct lsm_context ctx;
|
||||
u32 seclen = 0;
|
||||
ktime_t tstamp;
|
||||
|
||||
@ -642,8 +642,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
}
|
||||
|
||||
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
|
||||
seclen = nfqnl_get_sk_secctx(entskb, &secdata);
|
||||
if (seclen)
|
||||
seclen = nfqnl_get_sk_secctx(entskb, &ctx);
|
||||
if (seclen >= 0)
|
||||
size += nla_total_size(seclen);
|
||||
}
|
||||
|
||||
@ -782,7 +782,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
if (nfqnl_put_sk_classid(skb, entskb->sk) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
|
||||
if (seclen && nla_put(skb, NFQA_SECCTX, ctx.len, ctx.context))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
|
||||
@ -810,8 +810,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
}
|
||||
|
||||
nlh->nlmsg_len = skb->len;
|
||||
if (seclen)
|
||||
security_release_secctx(secdata, seclen);
|
||||
if (seclen >= 0)
|
||||
security_release_secctx(&ctx);
|
||||
return skb;
|
||||
|
||||
nla_put_failure:
|
||||
@ -819,8 +819,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
kfree_skb(skb);
|
||||
net_err_ratelimited("nf_queue: error creating packet message\n");
|
||||
nlmsg_failure:
|
||||
if (seclen)
|
||||
security_release_secctx(secdata, seclen);
|
||||
if (seclen >= 0)
|
||||
security_release_secctx(&ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -374,8 +374,7 @@ int netlbl_unlhsh_add(struct net *net,
|
||||
struct net_device *dev;
|
||||
struct netlbl_unlhsh_iface *iface;
|
||||
struct audit_buffer *audit_buf = NULL;
|
||||
char *secctx = NULL;
|
||||
u32 secctx_len;
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (addr_len != sizeof(struct in_addr) &&
|
||||
addr_len != sizeof(struct in6_addr))
|
||||
@ -438,11 +437,9 @@ int netlbl_unlhsh_add(struct net *net,
|
||||
unlhsh_add_return:
|
||||
rcu_read_unlock();
|
||||
if (audit_buf != NULL) {
|
||||
if (security_secid_to_secctx(secid,
|
||||
&secctx,
|
||||
&secctx_len) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
if (security_secid_to_secctx(secid, &ctx) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
|
||||
audit_log_end(audit_buf);
|
||||
@ -473,8 +470,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
|
||||
struct netlbl_unlhsh_addr4 *entry;
|
||||
struct audit_buffer *audit_buf;
|
||||
struct net_device *dev;
|
||||
char *secctx;
|
||||
u32 secctx_len;
|
||||
struct lsm_context ctx;
|
||||
|
||||
spin_lock(&netlbl_unlhsh_lock);
|
||||
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);
|
||||
dev_put(dev);
|
||||
if (entry != NULL &&
|
||||
security_secid_to_secctx(entry->secid,
|
||||
&secctx, &secctx_len) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
security_secid_to_secctx(entry->secid, &ctx) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
||||
audit_log_end(audit_buf);
|
||||
@ -534,8 +529,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
|
||||
struct netlbl_unlhsh_addr6 *entry;
|
||||
struct audit_buffer *audit_buf;
|
||||
struct net_device *dev;
|
||||
char *secctx;
|
||||
u32 secctx_len;
|
||||
struct lsm_context ctx;
|
||||
|
||||
spin_lock(&netlbl_unlhsh_lock);
|
||||
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);
|
||||
dev_put(dev);
|
||||
if (entry != NULL &&
|
||||
security_secid_to_secctx(entry->secid,
|
||||
&secctx, &secctx_len) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
security_secid_to_secctx(entry->secid, &ctx) == 0) {
|
||||
audit_log_format(audit_buf, " sec_obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
|
||||
audit_log_end(audit_buf);
|
||||
@ -1069,10 +1062,9 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
|
||||
int ret_val = -ENOMEM;
|
||||
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
|
||||
struct net_device *dev;
|
||||
struct lsm_context ctx;
|
||||
void *data;
|
||||
u32 secid;
|
||||
char *secctx;
|
||||
u32 secctx_len;
|
||||
|
||||
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
|
||||
cb_arg->seq, &netlbl_unlabel_gnl_family,
|
||||
@ -1127,14 +1119,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
|
||||
secid = addr6->secid;
|
||||
}
|
||||
|
||||
ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
|
||||
if (ret_val != 0)
|
||||
ret_val = security_secid_to_secctx(secid, &ctx);
|
||||
if (ret_val < 0)
|
||||
goto list_cb_failure;
|
||||
ret_val = nla_put(cb_arg->skb,
|
||||
NLBL_UNLABEL_A_SECCTX,
|
||||
secctx_len,
|
||||
secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
ctx.len,
|
||||
ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
if (ret_val != 0)
|
||||
goto list_cb_failure;
|
||||
|
||||
|
@ -84,8 +84,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||
struct netlbl_audit *audit_info)
|
||||
{
|
||||
struct audit_buffer *audit_buf;
|
||||
char *secctx;
|
||||
u32 secctx_len;
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (audit_enabled == AUDIT_OFF)
|
||||
return NULL;
|
||||
@ -99,10 +98,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||
audit_info->sessionid);
|
||||
|
||||
if (lsmprop_is_set(&audit_info->prop) &&
|
||||
security_lsmprop_to_secctx(&audit_info->prop, &secctx,
|
||||
&secctx_len) == 0) {
|
||||
audit_log_format(audit_buf, " subj=%s", secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
security_lsmprop_to_secctx(&audit_info->prop, &ctx) > 0) {
|
||||
audit_log_format(audit_buf, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
|
||||
return audit_buf;
|
||||
|
@ -8,13 +8,13 @@ void rust_helper_security_cred_getsecid(const struct cred *c, u32 *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
|
||||
|
@ -15,60 +15,56 @@
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// The `secdata` and `seclen` fields correspond to a valid security context as returned by a
|
||||
/// successful call to `security_secid_to_secctx`, that has not yet been destroyed by calling
|
||||
/// `security_release_secctx`.
|
||||
/// The `ctx` field corresponds to a valid security context as returned by a successful call to
|
||||
/// `security_secid_to_secctx`, that has not yet been destroyed by `security_release_secctx`.
|
||||
pub struct SecurityCtx {
|
||||
secdata: *mut core::ffi::c_char,
|
||||
seclen: usize,
|
||||
ctx: bindings::lsm_context,
|
||||
}
|
||||
|
||||
impl SecurityCtx {
|
||||
/// Get the security context given its id.
|
||||
pub fn from_secid(secid: u32) -> Result<Self> {
|
||||
let mut secdata = core::ptr::null_mut();
|
||||
let mut seclen = 0u32;
|
||||
// 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: `struct lsm_context` can be initialized to all zeros.
|
||||
let mut ctx: bindings::lsm_context = unsafe { core::mem::zeroed() };
|
||||
|
||||
// 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.
|
||||
Ok(Self {
|
||||
secdata,
|
||||
seclen: seclen as usize,
|
||||
})
|
||||
Ok(Self { ctx })
|
||||
}
|
||||
|
||||
/// Returns whether the security context is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.seclen == 0
|
||||
self.ctx.len == 0
|
||||
}
|
||||
|
||||
/// Returns the length of this security context.
|
||||
pub fn len(&self) -> usize {
|
||||
self.seclen
|
||||
self.ctx.len as usize
|
||||
}
|
||||
|
||||
/// Returns the bytes for this security context.
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
let ptr = self.secdata;
|
||||
let ptr = self.ctx.context;
|
||||
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.
|
||||
return &[];
|
||||
}
|
||||
|
||||
// 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.
|
||||
unsafe { core::slice::from_raw_parts(ptr.cast(), self.seclen) }
|
||||
unsafe { core::slice::from_raw_parts(ptr.cast(), self.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SecurityCtx {
|
||||
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
|
||||
// `security_release_secctx`.
|
||||
unsafe { bindings::security_release_secctx(self.secdata, self.seclen as u32) };
|
||||
unsafe { bindings::security_release_secctx(&mut self.ctx) };
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,10 @@ struct aa_label;
|
||||
extern int apparmor_display_secid_mode;
|
||||
|
||||
struct aa_label *aa_secid_to_label(u32 secid);
|
||||
int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
||||
u32 *seclen);
|
||||
int apparmor_secid_to_secctx(u32 secid, struct lsm_context *cp);
|
||||
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp);
|
||||
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);
|
||||
|
@ -47,23 +47,21 @@ struct aa_label *aa_secid_to_label(u32 secid)
|
||||
return xa_load(&aa_secids, secid);
|
||||
}
|
||||
|
||||
static int apparmor_label_to_secctx(struct aa_label *label, char **secdata,
|
||||
u32 *seclen)
|
||||
static int apparmor_label_to_secctx(struct aa_label *label,
|
||||
struct lsm_context *cp)
|
||||
{
|
||||
/* 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 len;
|
||||
|
||||
AA_BUG(!seclen);
|
||||
|
||||
if (!label)
|
||||
return -EINVAL;
|
||||
|
||||
if (apparmor_display_secid_mode)
|
||||
flags |= FLAG_SHOW_MODE;
|
||||
|
||||
if (secdata)
|
||||
len = aa_label_asxprint(secdata, root_ns, label,
|
||||
if (cp)
|
||||
len = aa_label_asxprint(&cp->context, root_ns, label,
|
||||
flags, GFP_ATOMIC);
|
||||
else
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
*seclen = len;
|
||||
if (cp) {
|
||||
cp->len = len;
|
||||
cp->id = LSM_ID_APPARMOR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
||||
int apparmor_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||
{
|
||||
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,
|
||||
u32 *seclen)
|
||||
int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
|
||||
{
|
||||
struct aa_label *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)
|
||||
@ -106,9 +106,13 @@ int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1735,8 +1735,7 @@ void security_inode_free(struct inode *inode)
|
||||
* @mode: mode used to determine resource type
|
||||
* @name: name of the last path component
|
||||
* @xattr_name: name of the security/LSM xattr
|
||||
* @ctx: pointer to the resulting LSM context
|
||||
* @ctxlen: length of @ctx
|
||||
* @lsmctx: pointer to the resulting LSM context
|
||||
*
|
||||
* 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
|
||||
@ -1746,11 +1745,11 @@ void security_inode_free(struct inode *inode)
|
||||
*/
|
||||
int security_dentry_init_security(struct dentry *dentry, int mode,
|
||||
const struct qstr *name,
|
||||
const char **xattr_name, void **ctx,
|
||||
u32 *ctxlen)
|
||||
const char **xattr_name,
|
||||
struct lsm_context *lsmctx)
|
||||
{
|
||||
return call_int_hook(dentry_init_security, dentry, mode, name,
|
||||
xattr_name, ctx, ctxlen);
|
||||
xattr_name, lsmctx);
|
||||
}
|
||||
EXPORT_SYMBOL(security_dentry_init_security);
|
||||
|
||||
@ -4304,40 +4303,36 @@ EXPORT_SYMBOL(security_ismaclabel);
|
||||
/**
|
||||
* security_secid_to_secctx() - Convert a secid to a secctx
|
||||
* @secid: secid
|
||||
* @secdata: secctx
|
||||
* @seclen: secctx length
|
||||
* @cp: the LSM context
|
||||
*
|
||||
* Convert secid to security context. If @secdata is NULL the length of the
|
||||
* result will be returned in @seclen, but no @secdata will be returned. This
|
||||
* Convert secid to security context. If @cp is NULL the length of the
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx
|
||||
* @prop: lsm specific information
|
||||
* @secdata: secctx
|
||||
* @seclen: secctx length
|
||||
* @cp: the LSM context
|
||||
*
|
||||
* Convert a @prop entry to security context. If @secdata is NULL the
|
||||
* length of the result will be returned in @seclen, but no @secdata
|
||||
* will be returned. This does mean that the length could change between
|
||||
* calls to check the length and the next call which actually allocates
|
||||
* and returns the @secdata.
|
||||
* Convert a @prop entry to security context. If @cp is NULL the
|
||||
* length of the result will be returned. This does mean that the
|
||||
* length could change between calls to check the length and the
|
||||
* next call which actually allocates and returns the @cp.
|
||||
*
|
||||
* 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,
|
||||
u32 *seclen)
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -4360,14 +4355,14 @@ EXPORT_SYMBOL(security_secctx_to_secid);
|
||||
|
||||
/**
|
||||
* security_release_secctx() - Free a secctx buffer
|
||||
* @secdata: secctx
|
||||
* @seclen: length of secctx
|
||||
* @cp: 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);
|
||||
|
||||
@ -4430,17 +4425,17 @@ EXPORT_SYMBOL(security_inode_setsecctx);
|
||||
/**
|
||||
* security_inode_getsecctx() - Get the security label of an inode
|
||||
* @inode: inode
|
||||
* @ctx: secctx
|
||||
* @ctxlen: length of secctx
|
||||
* @cp: security context
|
||||
*
|
||||
* On success, returns 0 and fills out @ctx and @ctxlen with the security
|
||||
* context for the given @inode.
|
||||
* On success, returns 0 and fills out @cp with the security context
|
||||
* for the given @inode.
|
||||
*
|
||||
* 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);
|
||||
|
||||
|
@ -2869,8 +2869,8 @@ static void selinux_inode_free_security(struct inode *inode)
|
||||
|
||||
static int selinux_dentry_init_security(struct dentry *dentry, int mode,
|
||||
const struct qstr *name,
|
||||
const char **xattr_name, void **ctx,
|
||||
u32 *ctxlen)
|
||||
const char **xattr_name,
|
||||
struct lsm_context *cp)
|
||||
{
|
||||
u32 newsid;
|
||||
int rc;
|
||||
@ -2885,8 +2885,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
|
||||
if (xattr_name)
|
||||
*xattr_name = XATTR_NAME_SELINUX;
|
||||
|
||||
return security_sid_to_context(newsid, (char **)ctx,
|
||||
ctxlen);
|
||||
cp->id = LSM_ID_SELINUX;
|
||||
return security_sid_to_context(newsid, &cp->context, &cp->len);
|
||||
}
|
||||
|
||||
static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
|
||||
@ -6641,15 +6641,28 @@ static int selinux_ismaclabel(const char *name)
|
||||
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,
|
||||
u32 *seclen)
|
||||
static int selinux_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||
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)
|
||||
@ -6658,9 +6671,13 @@ static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
|
||||
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)
|
||||
@ -6692,14 +6709,16 @@ static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
|
||||
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,
|
||||
XATTR_SELINUX_SUFFIX, ctx, true);
|
||||
XATTR_SELINUX_SUFFIX,
|
||||
(void **)&cp->context, true);
|
||||
if (len < 0)
|
||||
return len;
|
||||
*ctxlen = len;
|
||||
cp->len = len;
|
||||
cp->id = LSM_ID_SELINUX;
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_KEYS
|
||||
|
@ -4817,41 +4817,48 @@ static int smack_ismaclabel(const char *name)
|
||||
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
|
||||
* @secid: incoming integer
|
||||
* @secdata: destination
|
||||
* @seclen: how long it is
|
||||
* @cp: destination
|
||||
*
|
||||
* 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);
|
||||
|
||||
if (secdata)
|
||||
*secdata = skp->smk_known;
|
||||
*seclen = strlen(skp->smk_known);
|
||||
return 0;
|
||||
return smack_to_secctx(smack_from_secid(secid), cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_lsmprop_to_secctx - return the smack label
|
||||
* @prop: includes incoming Smack data
|
||||
* @secdata: destination
|
||||
* @seclen: how long it is
|
||||
* @cp: destination
|
||||
*
|
||||
* Exists for audit code.
|
||||
*/
|
||||
static int smack_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata,
|
||||
u32 *seclen)
|
||||
static int smack_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||
struct lsm_context *cp)
|
||||
{
|
||||
struct smack_known *skp = prop->smack.skp;
|
||||
|
||||
if (secdata)
|
||||
*secdata = skp->smk_known;
|
||||
*seclen = strlen(skp->smk_known);
|
||||
return 0;
|
||||
return smack_to_secctx(prop->smack.skp, cp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4891,12 +4898,13 @@ static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
|
||||
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);
|
||||
|
||||
*ctx = skp->smk_known;
|
||||
*ctxlen = strlen(skp->smk_known);
|
||||
cp->context = skp->smk_known;
|
||||
cp->len = strlen(skp->smk_known);
|
||||
cp->id = LSM_ID_SMACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -56,16 +56,15 @@ TEST(flags_zero_lsm_set_self_attr)
|
||||
TEST(flags_overset_lsm_set_self_attr)
|
||||
{
|
||||
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;
|
||||
struct lsm_ctx *tctx = (struct lsm_ctx *)ctx;
|
||||
|
||||
ASSERT_NE(NULL, ctx);
|
||||
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));
|
||||
}
|
||||
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));
|
||||
|
||||
free(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user