Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git

This commit is contained in:
Stephen Rothwell 2024-12-20 13:16:33 +11:00
commit f5cf996f5c
25 changed files with 319 additions and 299 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,

View File

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

View File

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

View File

@ -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:

View File

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

View File

@ -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)

View File

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

View File

@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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