aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-04-12 22:07:52 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-12 22:07:52 -0400
commit03e1ad7b5d871d4189b1da3125c2f12d1b5f7d0b (patch)
tree1e7f291ac6bd0c1f3a95e8252c32fcce7ff47ea7 /net
parent00447872a643787411c2c0cb1df6169dda8b0c47 (diff)
LSM: Make the Labeled IPsec hooks more stack friendly
The xfrm_get_policy() and xfrm_add_pol_expire() put some rather large structs on the stack to work around the LSM API. This patch attempts to fix that problem by changing the LSM API to require only the relevant "security" pointers instead of the entire SPD entry; we do this for all of the security_xfrm_policy*() functions to keep things consistent. Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/key/af_key.c23
-rw-r--r--net/xfrm/xfrm_policy.c24
-rw-r--r--net/xfrm/xfrm_user.c33
3 files changed, 43 insertions, 37 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 6db58924368a..1fb0fe42a72e 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2292,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2292 goto out; 2292 goto out;
2293 } 2293 }
2294 2294
2295 err = security_xfrm_policy_alloc(xp, uctx); 2295 err = security_xfrm_policy_alloc(&xp->security, uctx);
2296 kfree(uctx); 2296 kfree(uctx);
2297 2297
2298 if (err) 2298 if (err)
@@ -2352,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
2352 int err; 2352 int err;
2353 struct sadb_address *sa; 2353 struct sadb_address *sa;
2354 struct sadb_x_policy *pol; 2354 struct sadb_x_policy *pol;
2355 struct xfrm_policy *xp, tmp; 2355 struct xfrm_policy *xp;
2356 struct xfrm_selector sel; 2356 struct xfrm_selector sel;
2357 struct km_event c; 2357 struct km_event c;
2358 struct sadb_x_sec_ctx *sec_ctx; 2358 struct sadb_x_sec_ctx *sec_ctx;
2359 struct xfrm_sec_ctx *pol_ctx;
2359 2360
2360 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 2361 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
2361 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || 2362 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2385,25 +2386,23 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
2385 sel.dport_mask = htons(0xffff); 2386 sel.dport_mask = htons(0xffff);
2386 2387
2387 sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; 2388 sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
2388 memset(&tmp, 0, sizeof(struct xfrm_policy));
2389
2390 if (sec_ctx != NULL) { 2389 if (sec_ctx != NULL) {
2391 struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 2390 struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
2392 2391
2393 if (!uctx) 2392 if (!uctx)
2394 return -ENOMEM; 2393 return -ENOMEM;
2395 2394
2396 err = security_xfrm_policy_alloc(&tmp, uctx); 2395 err = security_xfrm_policy_alloc(&pol_ctx, uctx);
2397 kfree(uctx); 2396 kfree(uctx);
2398
2399 if (err) 2397 if (err)
2400 return err; 2398 return err;
2401 } 2399 } else
2402 2400 pol_ctx = NULL;
2403 xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
2404 &sel, tmp.security, 1, &err);
2405 security_xfrm_policy_free(&tmp);
2406 2401
2402 xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
2403 pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
2404 1, &err);
2405 security_xfrm_policy_free(pol_ctx);
2407 if (xp == NULL) 2406 if (xp == NULL)
2408 return -ENOENT; 2407 return -ENOENT;
2409 2408
@@ -3298,7 +3297,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
3298 if ((*dir = verify_sec_ctx_len(p))) 3297 if ((*dir = verify_sec_ctx_len(p)))
3299 goto out; 3298 goto out;
3300 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 3299 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
3301 *dir = security_xfrm_policy_alloc(xp, uctx); 3300 *dir = security_xfrm_policy_alloc(&xp->security, uctx);
3302 kfree(uctx); 3301 kfree(uctx);
3303 3302
3304 if (*dir) 3303 if (*dir)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 15d73e47cc2c..ab4d0e598a2c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -263,7 +263,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
263 list_del(&policy->bytype); 263 list_del(&policy->bytype);
264 write_unlock_bh(&xfrm_policy_lock); 264 write_unlock_bh(&xfrm_policy_lock);
265 265
266 security_xfrm_policy_free(policy); 266 security_xfrm_policy_free(policy->security);
267 kfree(policy); 267 kfree(policy);
268} 268}
269EXPORT_SYMBOL(xfrm_policy_destroy); 269EXPORT_SYMBOL(xfrm_policy_destroy);
@@ -676,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
676 xfrm_sec_ctx_match(ctx, pol->security)) { 676 xfrm_sec_ctx_match(ctx, pol->security)) {
677 xfrm_pol_hold(pol); 677 xfrm_pol_hold(pol);
678 if (delete) { 678 if (delete) {
679 *err = security_xfrm_policy_delete(pol); 679 *err = security_xfrm_policy_delete(
680 pol->security);
680 if (*err) { 681 if (*err) {
681 write_unlock_bh(&xfrm_policy_lock); 682 write_unlock_bh(&xfrm_policy_lock);
682 return pol; 683 return pol;
@@ -718,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
718 if (pol->type == type && pol->index == id) { 719 if (pol->type == type && pol->index == id) {
719 xfrm_pol_hold(pol); 720 xfrm_pol_hold(pol);
720 if (delete) { 721 if (delete) {
721 *err = security_xfrm_policy_delete(pol); 722 *err = security_xfrm_policy_delete(
723 pol->security);
722 if (*err) { 724 if (*err) {
723 write_unlock_bh(&xfrm_policy_lock); 725 write_unlock_bh(&xfrm_policy_lock);
724 return pol; 726 return pol;
@@ -756,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
756 &xfrm_policy_inexact[dir], bydst) { 758 &xfrm_policy_inexact[dir], bydst) {
757 if (pol->type != type) 759 if (pol->type != type)
758 continue; 760 continue;
759 err = security_xfrm_policy_delete(pol); 761 err = security_xfrm_policy_delete(pol->security);
760 if (err) { 762 if (err) {
761 xfrm_audit_policy_delete(pol, 0, 763 xfrm_audit_policy_delete(pol, 0,
762 audit_info->loginuid, 764 audit_info->loginuid,
@@ -770,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
770 bydst) { 772 bydst) {
771 if (pol->type != type) 773 if (pol->type != type)
772 continue; 774 continue;
773 err = security_xfrm_policy_delete(pol); 775 err = security_xfrm_policy_delete(
776 pol->security);
774 if (err) { 777 if (err) {
775 xfrm_audit_policy_delete(pol, 0, 778 xfrm_audit_policy_delete(pol, 0,
776 audit_info->loginuid, 779 audit_info->loginuid,
@@ -931,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
931 934
932 match = xfrm_selector_match(sel, fl, family); 935 match = xfrm_selector_match(sel, fl, family);
933 if (match) 936 if (match)
934 ret = security_xfrm_policy_lookup(pol, fl->secid, dir); 937 ret = security_xfrm_policy_lookup(pol->security, fl->secid,
938 dir);
935 939
936 return ret; 940 return ret;
937} 941}
@@ -1048,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
1048 int err = 0; 1052 int err = 0;
1049 1053
1050 if (match) { 1054 if (match) {
1051 err = security_xfrm_policy_lookup(pol, fl->secid, 1055 err = security_xfrm_policy_lookup(pol->security,
1052 policy_to_flow_dir(dir)); 1056 fl->secid,
1057 policy_to_flow_dir(dir));
1053 if (!err) 1058 if (!err)
1054 xfrm_pol_hold(pol); 1059 xfrm_pol_hold(pol);
1055 else if (err == -ESRCH) 1060 else if (err == -ESRCH)
@@ -1138,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
1138 1143
1139 if (newp) { 1144 if (newp) {
1140 newp->selector = old->selector; 1145 newp->selector = old->selector;
1141 if (security_xfrm_policy_clone(old, newp)) { 1146 if (security_xfrm_policy_clone(old->security,
1147 &newp->security)) {
1142 kfree(newp); 1148 kfree(newp);
1143 return NULL; /* ENOMEM */ 1149 return NULL; /* ENOMEM */
1144 } 1150 }
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 5578c909fcf6..ecf9d67daef5 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -959,7 +959,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
959 return 0; 959 return 0;
960 960
961 uctx = nla_data(rt); 961 uctx = nla_data(rt);
962 return security_xfrm_policy_alloc(pol, uctx); 962 return security_xfrm_policy_alloc(&pol->security, uctx);
963} 963}
964 964
965static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, 965static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
@@ -1143,7 +1143,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1143 NETLINK_CB(skb).sid); 1143 NETLINK_CB(skb).sid);
1144 1144
1145 if (err) { 1145 if (err) {
1146 security_xfrm_policy_free(xp); 1146 security_xfrm_policy_free(xp->security);
1147 kfree(xp); 1147 kfree(xp);
1148 return err; 1148 return err;
1149 } 1149 }
@@ -1337,22 +1337,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
1337 xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); 1337 xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
1338 else { 1338 else {
1339 struct nlattr *rt = attrs[XFRMA_SEC_CTX]; 1339 struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1340 struct xfrm_policy tmp; 1340 struct xfrm_sec_ctx *ctx;
1341 1341
1342 err = verify_sec_ctx_len(attrs); 1342 err = verify_sec_ctx_len(attrs);
1343 if (err) 1343 if (err)
1344 return err; 1344 return err;
1345 1345
1346 memset(&tmp, 0, sizeof(struct xfrm_policy));
1347 if (rt) { 1346 if (rt) {
1348 struct xfrm_user_sec_ctx *uctx = nla_data(rt); 1347 struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1349 1348
1350 if ((err = security_xfrm_policy_alloc(&tmp, uctx))) 1349 err = security_xfrm_policy_alloc(&ctx, uctx);
1350 if (err)
1351 return err; 1351 return err;
1352 } 1352 } else
1353 xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 1353 ctx = NULL;
1354 xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
1354 delete, &err); 1355 delete, &err);
1355 security_xfrm_policy_free(&tmp); 1356 security_xfrm_policy_free(ctx);
1356 } 1357 }
1357 if (xp == NULL) 1358 if (xp == NULL)
1358 return -ENOENT; 1359 return -ENOENT;
@@ -1572,26 +1573,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
1572 xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); 1573 xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
1573 else { 1574 else {
1574 struct nlattr *rt = attrs[XFRMA_SEC_CTX]; 1575 struct nlattr *rt = attrs[XFRMA_SEC_CTX];
1575 struct xfrm_policy tmp; 1576 struct xfrm_sec_ctx *ctx;
1576 1577
1577 err = verify_sec_ctx_len(attrs); 1578 err = verify_sec_ctx_len(attrs);
1578 if (err) 1579 if (err)
1579 return err; 1580 return err;
1580 1581
1581 memset(&tmp, 0, sizeof(struct xfrm_policy));
1582 if (rt) { 1582 if (rt) {
1583 struct xfrm_user_sec_ctx *uctx = nla_data(rt); 1583 struct xfrm_user_sec_ctx *uctx = nla_data(rt);
1584 1584
1585 if ((err = security_xfrm_policy_alloc(&tmp, uctx))) 1585 err = security_xfrm_policy_alloc(&ctx, uctx);
1586 if (err)
1586 return err; 1587 return err;
1587 } 1588 } else
1588 xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 1589 ctx = NULL;
1589 0, &err); 1590 xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
1590 security_xfrm_policy_free(&tmp); 1591 security_xfrm_policy_free(ctx);
1591 } 1592 }
1592
1593 if (xp == NULL) 1593 if (xp == NULL)
1594 return -ENOENT; 1594 return -ENOENT;
1595
1595 read_lock(&xp->lock); 1596 read_lock(&xp->lock);
1596 if (xp->dead) { 1597 if (xp->dead) {
1597 read_unlock(&xp->lock); 1598 read_unlock(&xp->lock);