diff options
Diffstat (limited to 'testing/linux-grsec/0006-xfrm-Allow-user-space-config-of-SAD-mark.patch')
-rw-r--r-- | testing/linux-grsec/0006-xfrm-Allow-user-space-config-of-SAD-mark.patch | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/testing/linux-grsec/0006-xfrm-Allow-user-space-config-of-SAD-mark.patch b/testing/linux-grsec/0006-xfrm-Allow-user-space-config-of-SAD-mark.patch new file mode 100644 index 0000000000..3afeb97b2e --- /dev/null +++ b/testing/linux-grsec/0006-xfrm-Allow-user-space-config-of-SAD-mark.patch @@ -0,0 +1,284 @@ +From 74ae2962f2250e63494a8c0bcda88609cc016184 Mon Sep 17 00:00:00 2001 +From: Jamal Hadi Salim <hadi@cyberus.ca> +Date: Mon, 22 Feb 2010 11:32:59 +0000 +Subject: [PATCH 6/7] xfrm: Allow user space config of SAD mark + +Add ability for netlink userspace to manipulate the SAD +and manipulate the mark, retrieve it and get events with a defined +mark. +MIGRATE may be added later. + +Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/xfrm/xfrm_user.c | 72 +++++++++++++++++++++++++++++++++++++++---------- + 1 files changed, 57 insertions(+), 15 deletions(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 837bc09..17252b4 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -32,7 +32,6 @@ + #endif + + #define DUMMY_MARK 0 +-static struct xfrm_mark dummy_mark = {0, 0}; + + static inline int aead_len(struct xfrm_algo_aead *alg) + { +@@ -362,6 +361,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, + goto error; + } + ++ xfrm_mark_get(attrs, &x->mark); ++ + err = xfrm_init_state(x); + if (err) + goto error; +@@ -442,11 +443,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, + int *errp) + { + struct xfrm_state *x = NULL; ++ struct xfrm_mark m; + int err; ++ u32 mark = xfrm_mark_get(attrs, &m); + + if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { + err = -ESRCH; +- x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family); ++ x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); + } else { + xfrm_address_t *saddr = NULL; + +@@ -457,7 +460,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, + } + + err = -ESRCH; +- x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr, ++ x = xfrm_state_lookup_byaddr(net, mark, ++ &p->daddr, saddr, + p->proto, p->family); + } + +@@ -576,6 +580,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x, + if (x->encap) + NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); + ++ if (xfrm_mark_put(skb, &x->mark)) ++ goto nla_put_failure; ++ + if (x->security && copy_sec_ctx(x->security, skb) < 0) + goto nla_put_failure; + +@@ -838,6 +845,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + xfrm_address_t *daddr; + int family; + int err; ++ u32 mark; ++ struct xfrm_mark m; + + p = nlmsg_data(nlh); + err = verify_userspi_info(p); +@@ -848,8 +857,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + daddr = &p->info.id.daddr; + + x = NULL; ++ ++ mark = xfrm_mark_get(attrs, &m); + if (p->info.seq) { +- x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq); ++ x = xfrm_find_acq_byseq(net, mark, p->info.seq); + if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { + xfrm_state_put(x); + x = NULL; +@@ -857,7 +868,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + } + + if (!x) +- x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid, ++ x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, + p->info.id.proto, daddr, + &p->info.saddr, 1, + family); +@@ -1362,8 +1373,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, + if (err) + return err; + } +- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, +- &p->sel, ctx, delete, &err); ++ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ++ ctx, delete, &err); + security_xfrm_policy_free(ctx); + } + if (xp == NULL) +@@ -1432,6 +1443,7 @@ static inline size_t xfrm_aevent_msgsize(void) + return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) + + nla_total_size(sizeof(struct xfrm_replay_state)) + + nla_total_size(sizeof(struct xfrm_lifetime_cur)) ++ + nla_total_size(sizeof(struct xfrm_mark)) + + nla_total_size(4) /* XFRM_AE_RTHR */ + + nla_total_size(4); /* XFRM_AE_ETHR */ + } +@@ -1464,6 +1476,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve + NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, + x->replay_maxage * 10 / HZ); + ++ if (xfrm_mark_put(skb, &x->mark)) ++ goto nla_put_failure; ++ + return nlmsg_end(skb, nlh); + + nla_put_failure: +@@ -1479,6 +1494,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, + struct sk_buff *r_skb; + int err; + struct km_event c; ++ u32 mark; ++ struct xfrm_mark m; + struct xfrm_aevent_id *p = nlmsg_data(nlh); + struct xfrm_usersa_id *id = &p->sa_id; + +@@ -1486,7 +1503,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, + if (r_skb == NULL) + return -ENOMEM; + +- x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family); ++ mark = xfrm_mark_get(attrs, &m); ++ ++ x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); + if (x == NULL) { + kfree_skb(r_skb); + return -ESRCH; +@@ -1517,6 +1536,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, + struct xfrm_state *x; + struct km_event c; + int err = - EINVAL; ++ u32 mark = 0; ++ struct xfrm_mark m; + struct xfrm_aevent_id *p = nlmsg_data(nlh); + struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; + struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; +@@ -1528,7 +1549,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, + if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) + return err; + +- x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); ++ mark = xfrm_mark_get(attrs, &m); ++ ++ x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + if (x == NULL) + return -ESRCH; + +@@ -1610,7 +1633,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, + if (err) + return err; + } +- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err); ++ xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, ++ &p->sel, ctx, 0, &err); + security_xfrm_policy_free(ctx); + } + if (xp == NULL) +@@ -1650,8 +1674,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, + int err; + struct xfrm_user_expire *ue = nlmsg_data(nlh); + struct xfrm_usersa_info *p = &ue->state; ++ struct xfrm_mark m; ++ u32 mark = xfrm_mark_get(attrs, &m);; + +- x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family); ++ x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); + + err = -ENOENT; + if (x == NULL) +@@ -1685,6 +1711,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + struct xfrm_user_tmpl *ut; + int i; + struct nlattr *rt = attrs[XFRMA_TMPL]; ++ struct xfrm_mark mark; + + struct xfrm_user_acquire *ua = nlmsg_data(nlh); + struct xfrm_state *x = xfrm_state_alloc(net); +@@ -1693,6 +1720,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + if (!x) + goto nomem; + ++ xfrm_mark_get(attrs, &mark); ++ + err = verify_newpolicy_info(&ua->policy); + if (err) + goto bad_policy; +@@ -1705,7 +1734,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, + memcpy(&x->id, &ua->id, sizeof(ua->id)); + memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); + memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); +- ++ xp->mark.m = x->mark.m = mark.m; ++ xp->mark.v = x->mark.v = mark.v; + ut = nla_data(rt); + /* extract the templates and for each call km_key */ + for (i = 0; i < xp->xfrm_nr; i++, ut++) { +@@ -1961,6 +1991,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { + [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, + [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, + [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, ++ [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, + }; + + static struct xfrm_link { +@@ -2040,7 +2071,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb) + + static inline size_t xfrm_expire_msgsize(void) + { +- return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)); ++ return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) ++ + nla_total_size(sizeof(struct xfrm_mark)); + } + + static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) +@@ -2056,7 +2088,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve + copy_to_user_state(x, &ue->state); + ue->hard = (c->data.hard != 0) ? 1 : 0; + ++ if (xfrm_mark_put(skb, &x->mark)) ++ goto nla_put_failure; ++ + return nlmsg_end(skb, nlh); ++ ++nla_put_failure: ++ return -EMSGSIZE; + } + + static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) +@@ -2068,8 +2106,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) + if (skb == NULL) + return -ENOMEM; + +- if (build_expire(skb, x, c) < 0) +- BUG(); ++ if (build_expire(skb, x, c) < 0) { ++ kfree_skb(skb); ++ return -EMSGSIZE; ++ } + + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); + } +@@ -2154,6 +2194,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) + if (c->event == XFRM_MSG_DELSA) { + len += nla_total_size(headlen); + headlen = sizeof(*id); ++ len += nla_total_size(sizeof(struct xfrm_mark)); + } + len += NLMSG_ALIGN(headlen); + +@@ -2224,6 +2265,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, + { + return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) + + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) ++ + nla_total_size(sizeof(struct xfrm_mark)) + + nla_total_size(xfrm_user_sec_ctx_size(x->security)) + + userpolicy_type_attrsize(); + } +-- +1.6.3.3 + |