UBUNTU: SAUCE: apparmor4.0.0 [16/90]: LSM stacking v39: LSM: Ensure the correct LSM context releaser
BugLink: http://bugs.launchpad.net/bugs/2028253 Add a new lsmcontext data structure to hold all the information about a "security context", including the string, its size and which LSM allocated the string. The allocation information is necessary because LSMs have different policies regarding the lifecycle of these strings. SELinux allocates and destroys them on each use, whereas Smack provides a pointer to an entry in a list that never goes away. Update security_release_secctx() to use the lsmcontext instead of a (char *, len) pair. Change its callers to do likewise. The LSMs supporting this hook have had comments added to remind the developer that there is more work to be done. Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: John Johansen <john.johansen@canonical.com> Acked-by: Paul Moore <paul@paul-moore.com> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com> Acked-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Cc: linux-integrity@vger.kernel.org Cc: netdev@vger.kernel.org Cc: audit@vger.kernel.org Cc: netfilter-devel@vger.kernel.org To: Pablo Neira Ayuso <pablo@netfilter.org> Cc: linux-nfs@vger.kernel.org Cc: Todd Kjos <tkjos@google.com> (cherry picked from commit ff955dc9c08dfa96a404f52269ea8c0ec192be6d https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next) Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
This commit is contained in:
committed by
Paolo Pisati
parent
75ce10a9ac
commit
21aab7be69
+12
-12
@@ -2930,8 +2930,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 lsmcontext lsmctx;
|
||||
struct list_head sgc_head;
|
||||
struct list_head pf_head;
|
||||
const void __user *user_buffer = (const void __user *)
|
||||
@@ -3210,7 +3209,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);
|
||||
ret = security_secid_to_secctx(secid, &lsmctx.context,
|
||||
&lsmctx.len);
|
||||
if (ret) {
|
||||
binder_txn_error("%d:%d failed to get security context\n",
|
||||
thread->pid, proc->pid);
|
||||
@@ -3219,7 +3219,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",
|
||||
@@ -3253,23 +3253,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;
|
||||
@@ -3313,7 +3313,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)) {
|
||||
@@ -3691,8 +3691,8 @@ err_copy_data_failed:
|
||||
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);
|
||||
|
||||
+5
-1
@@ -1446,12 +1446,16 @@ out:
|
||||
|
||||
void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
|
||||
{
|
||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||
struct lsmcontext scaff; /* scaffolding */
|
||||
#endif
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
posix_acl_release(as_ctx->acl);
|
||||
posix_acl_release(as_ctx->default_acl);
|
||||
#endif
|
||||
#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
|
||||
security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
|
||||
lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0);
|
||||
security_release_secctx(&scaff);
|
||||
#endif
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
kfree(as_ctx->fscrypt_auth);
|
||||
|
||||
+6
-2
@@ -138,8 +138,12 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
|
||||
static inline void
|
||||
nfs4_label_release_security(struct nfs4_label *label)
|
||||
{
|
||||
if (label)
|
||||
security_release_secctx(label->label, label->len);
|
||||
struct lsmcontext scaff; /* scaffolding */
|
||||
|
||||
if (label) {
|
||||
lsmcontext_init(&scaff, label->label, label->len, 0);
|
||||
security_release_secctx(&scaff);
|
||||
}
|
||||
}
|
||||
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
|
||||
{
|
||||
|
||||
+6
-2
@@ -3625,8 +3625,12 @@ 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) {
|
||||
struct lsmcontext scaff; /* scaffolding */
|
||||
|
||||
lsmcontext_init(&scaff, args.context, args.contextlen, 0);
|
||||
security_release_secctx(&scaff);
|
||||
}
|
||||
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
|
||||
kfree(args.acl);
|
||||
if (tempfh) {
|
||||
|
||||
@@ -280,7 +280,7 @@ LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata,
|
||||
LSM_HOOK(int, -EOPNOTSUPP, lsmblob_to_secctx, struct lsmblob *blob,
|
||||
char **secdata, u32 *seclen)
|
||||
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 lsmcontext *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)
|
||||
|
||||
@@ -148,6 +148,37 @@ struct lsmblob_scaffold {
|
||||
u32 secid;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 lsmcontext {
|
||||
char *context; /* Provided by the module */
|
||||
u32 len;
|
||||
int id; /* Identifies the module */
|
||||
};
|
||||
|
||||
/**
|
||||
* lsmcontext_init - initialize an lsmcontext structure.
|
||||
* @cp: Pointer to the context to initialize
|
||||
* @context: Initial context, or NULL
|
||||
* @size: Size of context, or 0
|
||||
* @id: Which LSM provided the context
|
||||
*
|
||||
* Fill in the lsmcontext from the provided information.
|
||||
* This is a scaffolding function that will be removed when
|
||||
* lsmcontext integration is complete.
|
||||
*/
|
||||
static inline void lsmcontext_init(struct lsmcontext *cp, char *context,
|
||||
u32 size, int id)
|
||||
{
|
||||
cp->id = id;
|
||||
cp->context = context;
|
||||
cp->len = size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data exported by the security modules
|
||||
*/
|
||||
@@ -537,7 +568,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
int security_lsmblob_to_secctx(struct lsmblob *blob, char **secdata,
|
||||
u32 *seclen);
|
||||
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 lsmcontext *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);
|
||||
@@ -1485,7 +1516,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 lsmcontext *cp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -94,16 +94,17 @@ 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 lsmcontext 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.context,
|
||||
&ctx.len);
|
||||
|
||||
if (!err) {
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
|
||||
security_release_secctx(secdata, seclen);
|
||||
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len,
|
||||
ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-16
@@ -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 lsmcontext lsmctx;
|
||||
|
||||
err = audit_netlink_ok(skb, msg_type);
|
||||
if (err)
|
||||
@@ -1471,30 +1470,34 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
kfree(new);
|
||||
break;
|
||||
}
|
||||
case AUDIT_SIGNAL_INFO:
|
||||
len = 0;
|
||||
case AUDIT_SIGNAL_INFO: {
|
||||
size_t sig_data_size;
|
||||
|
||||
if (lsmblob_is_set(&audit_sig_lsm)) {
|
||||
err = security_lsmblob_to_secctx(&audit_sig_lsm, &ctx,
|
||||
&len);
|
||||
err = security_lsmblob_to_secctx(&audit_sig_lsm,
|
||||
&lsmctx.context,
|
||||
&lsmctx.len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
|
||||
sig_data_size = struct_size(sig_data, ctx, lsmctx.len);
|
||||
sig_data = kmalloc(sig_data_size, GFP_KERNEL);
|
||||
if (!sig_data) {
|
||||
if (lsmblob_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 (lsmblob_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, sig_data_size);
|
||||
kfree(sig_data);
|
||||
break;
|
||||
}
|
||||
case AUDIT_TTY_GET: {
|
||||
struct audit_tty_status s;
|
||||
unsigned int t;
|
||||
@@ -2181,24 +2184,23 @@ void audit_log_key(struct audit_buffer *ab, char *key)
|
||||
|
||||
int audit_log_task_context(struct audit_buffer *ab)
|
||||
{
|
||||
struct lsmcontext ctx;
|
||||
struct lsmblob blob;
|
||||
char *ctx = NULL;
|
||||
unsigned len;
|
||||
int error;
|
||||
|
||||
security_current_getlsmblob_subj(&blob);
|
||||
if (!lsmblob_is_set(&blob))
|
||||
return 0;
|
||||
|
||||
error = security_lsmblob_to_secctx(&blob, &ctx, &len);
|
||||
error = security_lsmblob_to_secctx(&blob, &ctx.context, &ctx.len);
|
||||
if (error) {
|
||||
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:
|
||||
|
||||
+12
-11
@@ -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 lsmcontext 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 (lsmblob_is_set(blob)) {
|
||||
if (security_lsmblob_to_secctx(blob, &ctx, &len)) {
|
||||
if (security_lsmblob_to_secctx(blob, &ctx.context, &ctx.len)) {
|
||||
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=");
|
||||
@@ -1371,6 +1370,7 @@ static void audit_log_time(struct audit_context *context, struct audit_buffer **
|
||||
|
||||
static void show_special(struct audit_context *context, int *call_panic)
|
||||
{
|
||||
struct lsmcontext lsmcxt;
|
||||
struct audit_buffer *ab;
|
||||
int i;
|
||||
|
||||
@@ -1401,7 +1401,8 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
*call_panic = 1;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
lsmcontext_init(&lsmcxt, ctx, len, 0);
|
||||
security_release_secctx(&lsmcxt);
|
||||
}
|
||||
}
|
||||
if (context->ipc.has_perm) {
|
||||
@@ -1560,15 +1561,15 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
|
||||
MAJOR(n->rdev),
|
||||
MINOR(n->rdev));
|
||||
if (lsmblob_is_set(&n->oblob)) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
struct lsmcontext ctx;
|
||||
|
||||
if (security_lsmblob_to_secctx(&n->oblob, &ctx, &len)) {
|
||||
if (security_lsmblob_to_secctx(&n->oblob, &ctx.context,
|
||||
&ctx.len)) {
|
||||
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 lsmcontext ctx;
|
||||
u32 secid;
|
||||
int err;
|
||||
|
||||
err = security_socket_getpeersec_dgram(NULL, skb, &secid);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
err = security_secid_to_secctx(secid, &secdata, &seclen);
|
||||
err = security_secid_to_secctx(secid, &ctx.context, &ctx.len);
|
||||
if (err)
|
||||
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,10 +357,10 @@ nla_put_failure:
|
||||
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
||||
{
|
||||
struct nlattr *nest_secctx;
|
||||
int len, ret;
|
||||
char *secctx;
|
||||
struct lsmcontext ctx;
|
||||
int ret;
|
||||
|
||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
||||
ret = security_secid_to_secctx(ct->secmark, &ctx.context, &ctx.len);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -175,17 +175,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 lsmcontext ctx;
|
||||
int ret;
|
||||
u32 len;
|
||||
char *secctx;
|
||||
|
||||
ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
|
||||
ret = security_secid_to_secctx(ct->secmark, &ctx.context, &ctx.len);
|
||||
if (ret)
|
||||
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)
|
||||
|
||||
@@ -415,6 +415,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;
|
||||
struct lsmcontext scaff; /* scaffolding */
|
||||
char *secdata = NULL;
|
||||
u32 seclen = 0;
|
||||
ktime_t tstamp;
|
||||
@@ -658,8 +659,10 @@ 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) {
|
||||
lsmcontext_init(&scaff, secdata, seclen, 0);
|
||||
security_release_secctx(&scaff);
|
||||
}
|
||||
return skb;
|
||||
|
||||
nla_put_failure:
|
||||
@@ -667,8 +670,10 @@ nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
net_err_ratelimited("nf_queue: error creating packet message\n");
|
||||
nlmsg_failure:
|
||||
if (seclen)
|
||||
security_release_secctx(secdata, seclen);
|
||||
if (seclen) {
|
||||
lsmcontext_init(&scaff, secdata, seclen, 0);
|
||||
security_release_secctx(&scaff);
|
||||
}
|
||||
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 lsmcontext ctx;
|
||||
|
||||
if (addr_len != sizeof(struct in_addr) &&
|
||||
addr_len != sizeof(struct in6_addr))
|
||||
@@ -438,11 +437,10 @@ 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.context,
|
||||
&ctx.len) == 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 +471,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 lsmcontext ctx;
|
||||
|
||||
spin_lock(&netlbl_unlhsh_lock);
|
||||
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
|
||||
@@ -494,10 +491,10 @@ 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.context,
|
||||
&ctx.len) == 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 +531,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 lsmcontext ctx;
|
||||
|
||||
spin_lock(&netlbl_unlhsh_lock);
|
||||
list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
|
||||
@@ -554,10 +550,10 @@ 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.context,
|
||||
&ctx.len) == 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 +1065,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 lsmcontext 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 +1122,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
|
||||
secid = addr6->secid;
|
||||
}
|
||||
|
||||
ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
|
||||
ret_val = security_secid_to_secctx(secid, &ctx.context, &ctx.len);
|
||||
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 lsmcontext ctx;
|
||||
|
||||
if (audit_enabled == AUDIT_OFF)
|
||||
return NULL;
|
||||
@@ -99,10 +98,10 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||
audit_info->sessionid);
|
||||
|
||||
if (lsmblob_is_set(&audit_info->blob) &&
|
||||
security_lsmblob_to_secctx(&audit_info->blob, &secctx,
|
||||
&secctx_len) == 0) {
|
||||
audit_log_format(audit_buf, " subj=%s", secctx);
|
||||
security_release_secctx(secctx, secctx_len);
|
||||
security_lsmblob_to_secctx(&audit_info->blob, &ctx.context,
|
||||
&ctx.len) == 0) {
|
||||
audit_log_format(audit_buf, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
|
||||
return audit_buf;
|
||||
|
||||
@@ -29,7 +29,7 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata,
|
||||
u32 *seclen);
|
||||
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 lsmcontext *cp);
|
||||
|
||||
|
||||
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
|
||||
|
||||
@@ -139,9 +139,16 @@ 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 lsmcontext *cp)
|
||||
{
|
||||
kfree(secdata);
|
||||
/*
|
||||
* stacking scaffolding:
|
||||
* When it is possible for more than one LSM to provide a
|
||||
* release hook, do this check:
|
||||
* if (cp->id == LSM_ID_APPARMOR || cp->id == LSM_ID_UNDEF)
|
||||
*/
|
||||
|
||||
kfree(cp->context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -4269,14 +4269,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 lsmcontext *cp)
|
||||
{
|
||||
call_void_hook(release_secctx, secdata, seclen);
|
||||
call_void_hook(release_secctx, cp);
|
||||
memset(cp, 0, sizeof(*cp));
|
||||
}
|
||||
EXPORT_SYMBOL(security_release_secctx);
|
||||
|
||||
|
||||
@@ -6644,9 +6644,16 @@ 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 lsmcontext *cp)
|
||||
{
|
||||
kfree(secdata);
|
||||
/*
|
||||
* stacking scaffolding:
|
||||
* When it is possible for more than one LSM to provide a
|
||||
* release hook, do this check:
|
||||
* if (cp->id == LSM_ID_SELINUX || cp->id == LSM_ID_UNDEF)
|
||||
*/
|
||||
|
||||
kfree(cp->context);
|
||||
}
|
||||
|
||||
static void selinux_inode_invalidate_secctx(struct inode *inode)
|
||||
|
||||
Reference in New Issue
Block a user