summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-04-12 19:07:52 -0700
committerDavid S. Miller <davem@davemloft.net>2008-04-12 19:07:52 -0700
commit03e1ad7b5d871d4189b1da3125c2f12d1b5f7d0b (patch)
tree1e7f291ac6bd0c1f3a95e8252c32fcce7ff47ea7 /net
parent00447872a643787411c2c0cb1df6169dda8b0c47 (diff)
downloadlinux-03e1ad7b5d871d4189b1da3125c2f12d1b5f7d0b.tar.bz2
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
goto out;
}
- err = security_xfrm_policy_alloc(xp, uctx);
+ err = security_xfrm_policy_alloc(&xp->security, uctx);
kfree(uctx);
if (err)
@@ -2352,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
int err;
struct sadb_address *sa;
struct sadb_x_policy *pol;
- struct xfrm_policy *xp, tmp;
+ struct xfrm_policy *xp;
struct xfrm_selector sel;
struct km_event c;
struct sadb_x_sec_ctx *sec_ctx;
+ struct xfrm_sec_ctx *pol_ctx;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
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
sel.dport_mask = htons(0xffff);
sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
- memset(&tmp, 0, sizeof(struct xfrm_policy));
-
if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
if (!uctx)
return -ENOMEM;
- err = security_xfrm_policy_alloc(&tmp, uctx);
+ err = security_xfrm_policy_alloc(&pol_ctx, uctx);
kfree(uctx);
-
if (err)
return err;
- }
-
- xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
- &sel, tmp.security, 1, &err);
- security_xfrm_policy_free(&tmp);
+ } else
+ pol_ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
+ pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
+ 1, &err);
+ security_xfrm_policy_free(pol_ctx);
if (xp == NULL)
return -ENOENT;
@@ -3298,7 +3297,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
if ((*dir = verify_sec_ctx_len(p)))
goto out;
uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
- *dir = security_xfrm_policy_alloc(xp, uctx);
+ *dir = security_xfrm_policy_alloc(&xp->security, uctx);
kfree(uctx);
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)
list_del(&policy->bytype);
write_unlock_bh(&xfrm_policy_lock);
- security_xfrm_policy_free(policy);
+ security_xfrm_policy_free(policy->security);
kfree(policy);
}
EXPORT_SYMBOL(xfrm_policy_destroy);
@@ -676,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
xfrm_sec_ctx_match(ctx, pol->security)) {
xfrm_pol_hold(pol);
if (delete) {
- *err = security_xfrm_policy_delete(pol);
+ *err = security_xfrm_policy_delete(
+ pol->security);
if (*err) {
write_unlock_bh(&xfrm_policy_lock);
return pol;
@@ -718,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
if (pol->type == type && pol->index == id) {
xfrm_pol_hold(pol);
if (delete) {
- *err = security_xfrm_policy_delete(pol);
+ *err = security_xfrm_policy_delete(
+ pol->security);
if (*err) {
write_unlock_bh(&xfrm_policy_lock);
return pol;
@@ -756,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
&xfrm_policy_inexact[dir], bydst) {
if (pol->type != type)
continue;
- err = security_xfrm_policy_delete(pol);
+ err = security_xfrm_policy_delete(pol->security);
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
@@ -770,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
bydst) {
if (pol->type != type)
continue;
- err = security_xfrm_policy_delete(pol);
+ err = security_xfrm_policy_delete(
+ pol->security);
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
@@ -931,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
match = xfrm_selector_match(sel, fl, family);
if (match)
- ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
+ ret = security_xfrm_policy_lookup(pol->security, fl->secid,
+ dir);
return ret;
}
@@ -1048,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
int err = 0;
if (match) {
- err = security_xfrm_policy_lookup(pol, fl->secid,
- policy_to_flow_dir(dir));
+ err = security_xfrm_policy_lookup(pol->security,
+ fl->secid,
+ policy_to_flow_dir(dir));
if (!err)
xfrm_pol_hold(pol);
else if (err == -ESRCH)
@@ -1138,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
if (newp) {
newp->selector = old->selector;
- if (security_xfrm_policy_clone(old, newp)) {
+ if (security_xfrm_policy_clone(old->security,
+ &newp->security)) {
kfree(newp);
return NULL; /* ENOMEM */
}
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
return 0;
uctx = nla_data(rt);
- return security_xfrm_policy_alloc(pol, uctx);
+ return security_xfrm_policy_alloc(&pol->security, uctx);
}
static 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,
NETLINK_CB(skb).sid);
if (err) {
- security_xfrm_policy_free(xp);
+ security_xfrm_policy_free(xp->security);
kfree(xp);
return err;
}
@@ -1337,22 +1337,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
- struct xfrm_policy tmp;
+ struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs);
if (err)
return err;
- memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(rt);
- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
+ err = security_xfrm_policy_alloc(&ctx, uctx);
+ if (err)
return err;
- }
- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+ } else
+ ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
delete, &err);
- security_xfrm_policy_free(&tmp);
+ security_xfrm_policy_free(ctx);
}
if (xp == NULL)
return -ENOENT;
@@ -1572,26 +1573,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
- struct xfrm_policy tmp;
+ struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs);
if (err)
return err;
- memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(rt);
- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
+ err = security_xfrm_policy_alloc(&ctx, uctx);
+ if (err)
return err;
- }
- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
- 0, &err);
- security_xfrm_policy_free(&tmp);
+ } else
+ ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
+ security_xfrm_policy_free(ctx);
}
-
if (xp == NULL)
return -ENOENT;
+
read_lock(&xp->lock);
if (xp->dead) {
read_unlock(&xp->lock);