Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lsm: ensure the correct LSM context releaser

Add a new lsm_context 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 lsm_context 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.

The BPF security module provides all LSM hooks. While there has yet to
be a known instance of a BPF configuration that uses security contexts,
the possibility is real. In the existing implementation there is
potential for multiple frees in that case.

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>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
[PM: subject tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Casey Schaufler and committed by
Paul Moore
6fba8981 40384c84

+165 -107
+12 -12
drivers/android/binder.c
··· 3017 3017 struct binder_context *context = proc->context; 3018 3018 int t_debug_id = atomic_inc_return(&binder_last_id); 3019 3019 ktime_t t_start_time = ktime_get(); 3020 - char *secctx = NULL; 3021 - u32 secctx_sz = 0; 3020 + struct lsm_context lsmctx; 3022 3021 struct list_head sgc_head; 3023 3022 struct list_head pf_head; 3024 3023 const void __user *user_buffer = (const void __user *) ··· 3296 3297 size_t added_size; 3297 3298 3298 3299 security_cred_getsecid(proc->cred, &secid); 3299 - ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); 3300 + ret = security_secid_to_secctx(secid, &lsmctx.context, 3301 + &lsmctx.len); 3300 3302 if (ret) { 3301 3303 binder_txn_error("%d:%d failed to get security context\n", 3302 3304 thread->pid, proc->pid); ··· 3306 3306 return_error_line = __LINE__; 3307 3307 goto err_get_secctx_failed; 3308 3308 } 3309 - added_size = ALIGN(secctx_sz, sizeof(u64)); 3309 + added_size = ALIGN(lsmctx.len, sizeof(u64)); 3310 3310 extra_buffers_size += added_size; 3311 3311 if (extra_buffers_size < added_size) { 3312 3312 binder_txn_error("%d:%d integer overflow of extra_buffers_size\n", ··· 3340 3340 t->buffer = NULL; 3341 3341 goto err_binder_alloc_buf_failed; 3342 3342 } 3343 - if (secctx) { 3343 + if (lsmctx.context) { 3344 3344 int err; 3345 3345 size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + 3346 3346 ALIGN(tr->offsets_size, sizeof(void *)) + 3347 3347 ALIGN(extra_buffers_size, sizeof(void *)) - 3348 - ALIGN(secctx_sz, sizeof(u64)); 3348 + ALIGN(lsmctx.len, sizeof(u64)); 3349 3349 3350 3350 t->security_ctx = t->buffer->user_data + buf_offset; 3351 3351 err = binder_alloc_copy_to_buffer(&target_proc->alloc, 3352 3352 t->buffer, buf_offset, 3353 - secctx, secctx_sz); 3353 + lsmctx.context, lsmctx.len); 3354 3354 if (err) { 3355 3355 t->security_ctx = 0; 3356 3356 WARN_ON(1); 3357 3357 } 3358 - security_release_secctx(secctx, secctx_sz); 3359 - secctx = NULL; 3358 + security_release_secctx(&lsmctx); 3359 + lsmctx.context = NULL; 3360 3360 } 3361 3361 t->buffer->debug_id = t->debug_id; 3362 3362 t->buffer->transaction = t; ··· 3400 3400 off_end_offset = off_start_offset + tr->offsets_size; 3401 3401 sg_buf_offset = ALIGN(off_end_offset, sizeof(void *)); 3402 3402 sg_buf_end_offset = sg_buf_offset + extra_buffers_size - 3403 - ALIGN(secctx_sz, sizeof(u64)); 3403 + ALIGN(lsmctx.len, sizeof(u64)); 3404 3404 off_min = 0; 3405 3405 for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; 3406 3406 buffer_offset += sizeof(binder_size_t)) { ··· 3779 3779 binder_alloc_free_buf(&target_proc->alloc, t->buffer); 3780 3780 err_binder_alloc_buf_failed: 3781 3781 err_bad_extra_size: 3782 - if (secctx) 3783 - security_release_secctx(secctx, secctx_sz); 3782 + if (lsmctx.context) 3783 + security_release_secctx(&lsmctx); 3784 3784 err_get_secctx_failed: 3785 3785 kfree(tcomplete); 3786 3786 binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
+5 -1
fs/ceph/xattr.c
··· 1446 1446 1447 1447 void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx) 1448 1448 { 1449 + #ifdef CONFIG_CEPH_FS_SECURITY_LABEL 1450 + struct lsm_context scaff; /* scaffolding */ 1451 + #endif 1449 1452 #ifdef CONFIG_CEPH_FS_POSIX_ACL 1450 1453 posix_acl_release(as_ctx->acl); 1451 1454 posix_acl_release(as_ctx->default_acl); 1452 1455 #endif 1453 1456 #ifdef CONFIG_CEPH_FS_SECURITY_LABEL 1454 - security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen); 1457 + lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0); 1458 + security_release_secctx(&scaff); 1455 1459 #endif 1456 1460 #ifdef CONFIG_FS_ENCRYPTION 1457 1461 kfree(as_ctx->fscrypt_auth);
+6 -2
fs/nfs/nfs4proc.c
··· 138 138 static inline void 139 139 nfs4_label_release_security(struct nfs4_label *label) 140 140 { 141 - if (label) 142 - security_release_secctx(label->label, label->len); 141 + struct lsm_context scaff; /* scaffolding */ 142 + 143 + if (label) { 144 + lsmcontext_init(&scaff, label->label, label->len, 0); 145 + security_release_secctx(&scaff); 146 + } 143 147 } 144 148 static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) 145 149 {
+6 -2
fs/nfsd/nfs4xdr.c
··· 3644 3644 3645 3645 out: 3646 3646 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL 3647 - if (args.context) 3648 - security_release_secctx(args.context, args.contextlen); 3647 + if (args.context) { 3648 + struct lsm_context scaff; /* scaffolding */ 3649 + 3650 + lsmcontext_init(&scaff, args.context, args.contextlen, 0); 3651 + security_release_secctx(&scaff); 3652 + } 3649 3653 #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ 3650 3654 kfree(args.acl); 3651 3655 if (tempfh) {
+1 -1
include/linux/lsm_hook_defs.h
··· 300 300 LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop, 301 301 char **secdata, u32 *seclen) 302 302 LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) 303 - LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen) 303 + LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp) 304 304 LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode) 305 305 LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) 306 306 LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen)
+33 -2
include/linux/security.h
··· 226 226 #endif 227 227 228 228 /* 229 + * A "security context" is the text representation of 230 + * the information used by LSMs. 231 + * This structure contains the string, its length, and which LSM 232 + * it is useful for. 233 + */ 234 + struct lsm_context { 235 + char *context; /* Provided by the module */ 236 + u32 len; 237 + int id; /* Identifies the module */ 238 + }; 239 + 240 + /** 241 + * lsmcontext_init - initialize an lsmcontext structure. 242 + * @cp: Pointer to the context to initialize 243 + * @context: Initial context, or NULL 244 + * @size: Size of context, or 0 245 + * @id: Which LSM provided the context 246 + * 247 + * Fill in the lsmcontext from the provided information. 248 + * This is a scaffolding function that will be removed when 249 + * lsm_context integration is complete. 250 + */ 251 + static inline void lsmcontext_init(struct lsm_context *cp, char *context, 252 + u32 size, int id) 253 + { 254 + cp->id = id; 255 + cp->context = context; 256 + cp->len = size; 257 + } 258 + 259 + /* 229 260 * Values used in the task_security_ops calls 230 261 */ 231 262 /* setuid or setgid, id0 == uid or gid */ ··· 587 556 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); 588 557 int security_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, u32 *seclen); 589 558 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); 590 - void security_release_secctx(char *secdata, u32 seclen); 559 + void security_release_secctx(struct lsm_context *cp); 591 560 void security_inode_invalidate_secctx(struct inode *inode); 592 561 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); 593 562 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); ··· 1576 1545 return -EOPNOTSUPP; 1577 1546 } 1578 1547 1579 - static inline void security_release_secctx(char *secdata, u32 seclen) 1548 + static inline void security_release_secctx(struct lsm_context *cp) 1580 1549 { 1581 1550 } 1582 1551
+6 -5
include/net/scm.h
··· 105 105 #ifdef CONFIG_SECURITY_NETWORK 106 106 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 107 107 { 108 - char *secdata; 109 - u32 seclen; 108 + struct lsm_context ctx; 110 109 int err; 111 110 112 111 if (test_bit(SOCK_PASSSEC, &sock->flags)) { 113 - err = security_secid_to_secctx(scm->secid, &secdata, &seclen); 112 + err = security_secid_to_secctx(scm->secid, &ctx.context, 113 + &ctx.len); 114 114 115 115 if (!err) { 116 - put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); 117 - security_release_secctx(secdata, seclen); 116 + put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, ctx.len, 117 + ctx.context); 118 + security_release_secctx(&ctx); 118 119 } 119 120 } 120 121 }
+15 -15
kernel/audit.c
··· 1221 1221 struct audit_buffer *ab; 1222 1222 u16 msg_type = nlh->nlmsg_type; 1223 1223 struct audit_sig_info *sig_data; 1224 - char *ctx = NULL; 1225 - u32 len; 1224 + struct lsm_context lsmctx; 1226 1225 1227 1226 err = audit_netlink_ok(skb, msg_type); 1228 1227 if (err) ··· 1471 1472 break; 1472 1473 } 1473 1474 case AUDIT_SIGNAL_INFO: 1474 - len = 0; 1475 1475 if (lsmprop_is_set(&audit_sig_lsm)) { 1476 - err = security_lsmprop_to_secctx(&audit_sig_lsm, &ctx, 1477 - &len); 1476 + err = security_lsmprop_to_secctx(&audit_sig_lsm, 1477 + &lsmctx.context, 1478 + &lsmctx.len); 1478 1479 if (err) 1479 1480 return err; 1480 1481 } 1481 - sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL); 1482 + sig_data = kmalloc(struct_size(sig_data, ctx, lsmctx.len), 1483 + GFP_KERNEL); 1482 1484 if (!sig_data) { 1483 1485 if (lsmprop_is_set(&audit_sig_lsm)) 1484 - security_release_secctx(ctx, len); 1486 + security_release_secctx(&lsmctx); 1485 1487 return -ENOMEM; 1486 1488 } 1487 1489 sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid); 1488 1490 sig_data->pid = audit_sig_pid; 1489 1491 if (lsmprop_is_set(&audit_sig_lsm)) { 1490 - memcpy(sig_data->ctx, ctx, len); 1491 - security_release_secctx(ctx, len); 1492 + memcpy(sig_data->ctx, lsmctx.context, lsmctx.len); 1493 + security_release_secctx(&lsmctx); 1492 1494 } 1493 1495 audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0, 1494 - sig_data, struct_size(sig_data, ctx, len)); 1496 + sig_data, struct_size(sig_data, ctx, 1497 + lsmctx.len)); 1495 1498 kfree(sig_data); 1496 1499 break; 1497 1500 case AUDIT_TTY_GET: { ··· 2181 2180 int audit_log_task_context(struct audit_buffer *ab) 2182 2181 { 2183 2182 struct lsm_prop prop; 2184 - char *ctx = NULL; 2185 - unsigned len; 2183 + struct lsm_context ctx; 2186 2184 int error; 2187 2185 2188 2186 security_current_getlsmprop_subj(&prop); 2189 2187 if (!lsmprop_is_set(&prop)) 2190 2188 return 0; 2191 2189 2192 - error = security_lsmprop_to_secctx(&prop, &ctx, &len); 2190 + error = security_lsmprop_to_secctx(&prop, &ctx.context, &ctx.len); 2193 2191 if (error) { 2194 2192 if (error != -EINVAL) 2195 2193 goto error_path; 2196 2194 return 0; 2197 2195 } 2198 2196 2199 - audit_log_format(ab, " subj=%s", ctx); 2200 - security_release_secctx(ctx, len); 2197 + audit_log_format(ab, " subj=%s", ctx.context); 2198 + security_release_secctx(&ctx); 2201 2199 return 0; 2202 2200 2203 2201 error_path:
+12 -11
kernel/auditsc.c
··· 1098 1098 char *comm) 1099 1099 { 1100 1100 struct audit_buffer *ab; 1101 - char *ctx = NULL; 1102 - u32 len; 1101 + struct lsm_context ctx; 1103 1102 int rc = 0; 1104 1103 1105 1104 ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); ··· 1109 1110 from_kuid(&init_user_ns, auid), 1110 1111 from_kuid(&init_user_ns, uid), sessionid); 1111 1112 if (lsmprop_is_set(prop)) { 1112 - if (security_lsmprop_to_secctx(prop, &ctx, &len)) { 1113 + if (security_lsmprop_to_secctx(prop, &ctx.context, &ctx.len)) { 1113 1114 audit_log_format(ab, " obj=(none)"); 1114 1115 rc = 1; 1115 1116 } else { 1116 - audit_log_format(ab, " obj=%s", ctx); 1117 - security_release_secctx(ctx, len); 1117 + audit_log_format(ab, " obj=%s", ctx.context); 1118 + security_release_secctx(&ctx); 1118 1119 } 1119 1120 } 1120 1121 audit_log_format(ab, " ocomm="); ··· 1370 1371 1371 1372 static void show_special(struct audit_context *context, int *call_panic) 1372 1373 { 1374 + struct lsm_context lsmcxt; 1373 1375 struct audit_buffer *ab; 1374 1376 int i; 1375 1377 ··· 1401 1401 *call_panic = 1; 1402 1402 } else { 1403 1403 audit_log_format(ab, " obj=%s", ctx); 1404 - security_release_secctx(ctx, len); 1404 + lsmcontext_init(&lsmcxt, ctx, len, 0); 1405 + security_release_secctx(&lsmcxt); 1405 1406 } 1406 1407 } 1407 1408 if (context->ipc.has_perm) { ··· 1561 1560 MAJOR(n->rdev), 1562 1561 MINOR(n->rdev)); 1563 1562 if (lsmprop_is_set(&n->oprop)) { 1564 - char *ctx = NULL; 1565 - u32 len; 1563 + struct lsm_context ctx; 1566 1564 1567 - if (security_lsmprop_to_secctx(&n->oprop, &ctx, &len)) { 1565 + if (security_lsmprop_to_secctx(&n->oprop, &ctx.context, 1566 + &ctx.len)) { 1568 1567 if (call_panic) 1569 1568 *call_panic = 2; 1570 1569 } else { 1571 - audit_log_format(ab, " obj=%s", ctx); 1572 - security_release_secctx(ctx, len); 1570 + audit_log_format(ab, " obj=%s", ctx.context); 1571 + security_release_secctx(&ctx); 1573 1572 } 1574 1573 } 1575 1574
+5 -5
net/ipv4/ip_sockglue.c
··· 128 128 129 129 static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) 130 130 { 131 - char *secdata; 132 - u32 seclen, secid; 131 + struct lsm_context ctx; 132 + u32 secid; 133 133 int err; 134 134 135 135 err = security_socket_getpeersec_dgram(NULL, skb, &secid); 136 136 if (err) 137 137 return; 138 138 139 - err = security_secid_to_secctx(secid, &secdata, &seclen); 139 + err = security_secid_to_secctx(secid, &ctx.context, &ctx.len); 140 140 if (err) 141 141 return; 142 142 143 - put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); 144 - security_release_secctx(secdata, seclen); 143 + put_cmsg(msg, SOL_IP, SCM_SECURITY, ctx.len, ctx.context); 144 + security_release_secctx(&ctx); 145 145 } 146 146 147 147 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
+5 -5
net/netfilter/nf_conntrack_netlink.c
··· 357 357 static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) 358 358 { 359 359 struct nlattr *nest_secctx; 360 - int len, ret; 361 - char *secctx; 360 + struct lsm_context ctx; 361 + int ret; 362 362 363 - ret = security_secid_to_secctx(ct->secmark, &secctx, &len); 363 + ret = security_secid_to_secctx(ct->secmark, &ctx.context, &ctx.len); 364 364 if (ret) 365 365 return 0; 366 366 ··· 369 369 if (!nest_secctx) 370 370 goto nla_put_failure; 371 371 372 - if (nla_put_string(skb, CTA_SECCTX_NAME, secctx)) 372 + if (nla_put_string(skb, CTA_SECCTX_NAME, ctx.context)) 373 373 goto nla_put_failure; 374 374 nla_nest_end(skb, nest_secctx); 375 375 376 376 ret = 0; 377 377 nla_put_failure: 378 - security_release_secctx(secctx, len); 378 + security_release_secctx(&ctx); 379 379 return ret; 380 380 } 381 381 #else
+4 -5
net/netfilter/nf_conntrack_standalone.c
··· 172 172 #ifdef CONFIG_NF_CONNTRACK_SECMARK 173 173 static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct) 174 174 { 175 + struct lsm_context ctx; 175 176 int ret; 176 - u32 len; 177 - char *secctx; 178 177 179 - ret = security_secid_to_secctx(ct->secmark, &secctx, &len); 178 + ret = security_secid_to_secctx(ct->secmark, &ctx.context, &ctx.len); 180 179 if (ret) 181 180 return; 182 181 183 - seq_printf(s, "secctx=%s ", secctx); 182 + seq_printf(s, "secctx=%s ", ctx.context); 184 183 185 - security_release_secctx(secctx, len); 184 + security_release_secctx(&ctx); 186 185 } 187 186 #else 188 187 static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
+18 -22
net/netlabel/netlabel_unlabeled.c
··· 374 374 struct net_device *dev; 375 375 struct netlbl_unlhsh_iface *iface; 376 376 struct audit_buffer *audit_buf = NULL; 377 - char *secctx = NULL; 378 - u32 secctx_len; 377 + struct lsm_context ctx; 379 378 380 379 if (addr_len != sizeof(struct in_addr) && 381 380 addr_len != sizeof(struct in6_addr)) ··· 438 439 rcu_read_unlock(); 439 440 if (audit_buf != NULL) { 440 441 if (security_secid_to_secctx(secid, 441 - &secctx, 442 - &secctx_len) == 0) { 443 - audit_log_format(audit_buf, " sec_obj=%s", secctx); 444 - security_release_secctx(secctx, secctx_len); 442 + &ctx.context, 443 + &ctx.len) == 0) { 444 + audit_log_format(audit_buf, " sec_obj=%s", ctx.context); 445 + security_release_secctx(&ctx); 445 446 } 446 447 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); 447 448 audit_log_end(audit_buf); ··· 472 473 struct netlbl_unlhsh_addr4 *entry; 473 474 struct audit_buffer *audit_buf; 474 475 struct net_device *dev; 475 - char *secctx; 476 - u32 secctx_len; 476 + struct lsm_context ctx; 477 477 478 478 spin_lock(&netlbl_unlhsh_lock); 479 479 list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr, ··· 493 495 dev_put(dev); 494 496 if (entry != NULL && 495 497 security_secid_to_secctx(entry->secid, 496 - &secctx, &secctx_len) == 0) { 497 - audit_log_format(audit_buf, " sec_obj=%s", secctx); 498 - security_release_secctx(secctx, secctx_len); 498 + &ctx.context, &ctx.len) == 0) { 499 + audit_log_format(audit_buf, " sec_obj=%s", ctx.context); 500 + security_release_secctx(&ctx); 499 501 } 500 502 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 501 503 audit_log_end(audit_buf); ··· 532 534 struct netlbl_unlhsh_addr6 *entry; 533 535 struct audit_buffer *audit_buf; 534 536 struct net_device *dev; 535 - char *secctx; 536 - u32 secctx_len; 537 + struct lsm_context ctx; 537 538 538 539 spin_lock(&netlbl_unlhsh_lock); 539 540 list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list); ··· 552 555 dev_put(dev); 553 556 if (entry != NULL && 554 557 security_secid_to_secctx(entry->secid, 555 - &secctx, &secctx_len) == 0) { 556 - audit_log_format(audit_buf, " sec_obj=%s", secctx); 557 - security_release_secctx(secctx, secctx_len); 558 + &ctx.context, &ctx.len) == 0) { 559 + audit_log_format(audit_buf, " sec_obj=%s", ctx.context); 560 + security_release_secctx(&ctx); 558 561 } 559 562 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 560 563 audit_log_end(audit_buf); ··· 1066 1069 int ret_val = -ENOMEM; 1067 1070 struct netlbl_unlhsh_walk_arg *cb_arg = arg; 1068 1071 struct net_device *dev; 1072 + struct lsm_context ctx; 1069 1073 void *data; 1070 1074 u32 secid; 1071 - char *secctx; 1072 - u32 secctx_len; 1073 1075 1074 1076 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, 1075 1077 cb_arg->seq, &netlbl_unlabel_gnl_family, ··· 1123 1127 secid = addr6->secid; 1124 1128 } 1125 1129 1126 - ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len); 1130 + ret_val = security_secid_to_secctx(secid, &ctx.context, &ctx.len); 1127 1131 if (ret_val != 0) 1128 1132 goto list_cb_failure; 1129 1133 ret_val = nla_put(cb_arg->skb, 1130 1134 NLBL_UNLABEL_A_SECCTX, 1131 - secctx_len, 1132 - secctx); 1133 - security_release_secctx(secctx, secctx_len); 1135 + ctx.len, 1136 + ctx.context); 1137 + security_release_secctx(&ctx); 1134 1138 if (ret_val != 0) 1135 1139 goto list_cb_failure; 1136 1140
+5 -6
net/netlabel/netlabel_user.c
··· 84 84 struct netlbl_audit *audit_info) 85 85 { 86 86 struct audit_buffer *audit_buf; 87 - char *secctx; 88 - u32 secctx_len; 87 + struct lsm_context ctx; 89 88 90 89 if (audit_enabled == AUDIT_OFF) 91 90 return NULL; ··· 98 99 audit_info->sessionid); 99 100 100 101 if (lsmprop_is_set(&audit_info->prop) && 101 - security_lsmprop_to_secctx(&audit_info->prop, &secctx, 102 - &secctx_len) == 0) { 103 - audit_log_format(audit_buf, " subj=%s", secctx); 104 - security_release_secctx(secctx, secctx_len); 102 + security_lsmprop_to_secctx(&audit_info->prop, &ctx.context, 103 + &ctx.len) == 0) { 104 + audit_log_format(audit_buf, " subj=%s", ctx.context); 105 + security_release_secctx(&ctx); 105 106 } 106 107 107 108 return audit_buf;
+1 -1
security/apparmor/include/secid.h
··· 29 29 int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, 30 30 u32 *seclen); 31 31 int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); 32 - void apparmor_release_secctx(char *secdata, u32 seclen); 32 + void apparmor_release_secctx(struct lsm_context *cp); 33 33 34 34 35 35 int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
+9 -2
security/apparmor/secid.c
··· 106 106 return 0; 107 107 } 108 108 109 - void apparmor_release_secctx(char *secdata, u32 seclen) 109 + void apparmor_release_secctx(struct lsm_context *cp) 110 110 { 111 - kfree(secdata); 111 + /* 112 + * stacking scaffolding: 113 + * When it is possible for more than one LSM to provide a 114 + * release hook, do this check: 115 + * if (cp->id == LSM_ID_APPARMOR || cp->id == LSM_ID_UNDEF) 116 + */ 117 + 118 + kfree(cp->context); 112 119 } 113 120 114 121 /**
+4 -4
security/security.c
··· 4360 4360 4361 4361 /** 4362 4362 * security_release_secctx() - Free a secctx buffer 4363 - * @secdata: secctx 4364 - * @seclen: length of secctx 4363 + * @cp: the security context 4365 4364 * 4366 4365 * Release the security context. 4367 4366 */ 4368 - void security_release_secctx(char *secdata, u32 seclen) 4367 + void security_release_secctx(struct lsm_context *cp) 4369 4368 { 4370 - call_void_hook(release_secctx, secdata, seclen); 4369 + call_void_hook(release_secctx, cp); 4370 + memset(cp, 0, sizeof(*cp)); 4371 4371 } 4372 4372 EXPORT_SYMBOL(security_release_secctx); 4373 4373
+9 -2
security/selinux/hooks.c
··· 6657 6657 secid, GFP_KERNEL); 6658 6658 } 6659 6659 6660 - static void selinux_release_secctx(char *secdata, u32 seclen) 6660 + static void selinux_release_secctx(struct lsm_context *cp) 6661 6661 { 6662 - kfree(secdata); 6662 + /* 6663 + * stacking scaffolding: 6664 + * When it is possible for more than one LSM to provide a 6665 + * release hook, do this check: 6666 + * if (cp->id == LSM_ID_SELINUX || cp->id == LSM_ID_UNDEF) 6667 + */ 6668 + 6669 + kfree(cp->context); 6663 6670 } 6664 6671 6665 6672 static void selinux_inode_invalidate_secctx(struct inode *inode)