aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2007-08-22 16:59:04 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:48:23 -0400
commitcf5cb79f6946063b04be3df16dcaa781e48bdbef (patch)
tree64471b7121109b91a76481a92f6b5c037e66c421 /net/xfrm/xfrm_user.c
parenta7bd9a45c8c8901f800a461a4098ebae2b8a4b78 (diff)
[XFRM] netlink: Establish an attribute policy
Adds a policy defining the minimal payload lengths for all the attributes allowing for most attribute validation checks to be removed from in the middle of the code path. Makes updates more consistent as many format errors are recognised earlier, before any changes have been attempted. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c125
1 files changed, 31 insertions, 94 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 9103af02473c..1371a0ae0606 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -42,19 +42,12 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
42{ 42{
43 struct rtattr *rt = xfrma[type - 1]; 43 struct rtattr *rt = xfrma[type - 1];
44 struct xfrm_algo *algp; 44 struct xfrm_algo *algp;
45 int len;
46 45
47 if (!rt) 46 if (!rt)
48 return 0; 47 return 0;
49 48
50 len = (rt->rta_len - sizeof(*rt)) - sizeof(*algp);
51 if (len < 0)
52 return -EINVAL;
53
54 algp = RTA_DATA(rt); 49 algp = RTA_DATA(rt);
55 50 if (RTA_PAYLOAD(rt) < alg_len(algp))
56 len -= (algp->alg_key_len + 7U) / 8;
57 if (len < 0)
58 return -EINVAL; 51 return -EINVAL;
59 52
60 switch (type) { 53 switch (type) {
@@ -82,55 +75,25 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
82 return 0; 75 return 0;
83} 76}
84 77
85static int verify_encap_tmpl(struct rtattr **xfrma) 78static void verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type,
86{
87 struct rtattr *rt = xfrma[XFRMA_ENCAP - 1];
88 struct xfrm_encap_tmpl *encap;
89
90 if (!rt)
91 return 0;
92
93 if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
94 return -EINVAL;
95
96 return 0;
97}
98
99static int verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type,
100 xfrm_address_t **addrp) 79 xfrm_address_t **addrp)
101{ 80{
102 struct rtattr *rt = xfrma[type - 1]; 81 struct rtattr *rt = xfrma[type - 1];
103 82
104 if (!rt) 83 if (rt && addrp)
105 return 0;
106
107 if ((rt->rta_len - sizeof(*rt)) < sizeof(**addrp))
108 return -EINVAL;
109
110 if (addrp)
111 *addrp = RTA_DATA(rt); 84 *addrp = RTA_DATA(rt);
112
113 return 0;
114} 85}
115 86
116static inline int verify_sec_ctx_len(struct rtattr **xfrma) 87static inline int verify_sec_ctx_len(struct rtattr **xfrma)
117{ 88{
118 struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1]; 89 struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1];
119 struct xfrm_user_sec_ctx *uctx; 90 struct xfrm_user_sec_ctx *uctx;
120 int len = 0;
121 91
122 if (!rt) 92 if (!rt)
123 return 0; 93 return 0;
124 94
125 if (rt->rta_len < sizeof(*uctx))
126 return -EINVAL;
127
128 uctx = RTA_DATA(rt); 95 uctx = RTA_DATA(rt);
129 96 if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
130 len += sizeof(struct xfrm_user_sec_ctx);
131 len += uctx->ctx_len;
132
133 if (uctx->len != len)
134 return -EINVAL; 97 return -EINVAL;
135 98
136 return 0; 99 return 0;
@@ -205,12 +168,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
205 goto out; 168 goto out;
206 if ((err = verify_one_alg(xfrma, XFRMA_ALG_COMP))) 169 if ((err = verify_one_alg(xfrma, XFRMA_ALG_COMP)))
207 goto out; 170 goto out;
208 if ((err = verify_encap_tmpl(xfrma)))
209 goto out;
210 if ((err = verify_sec_ctx_len(xfrma))) 171 if ((err = verify_sec_ctx_len(xfrma)))
211 goto out; 172 goto out;
212 if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL)))
213 goto out;
214 173
215 err = -EINVAL; 174 err = -EINVAL;
216 switch (p->mode) { 175 switch (p->mode) {
@@ -339,9 +298,8 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
339 * somehow made shareable and move it to xfrm_state.c - JHS 298 * somehow made shareable and move it to xfrm_state.c - JHS
340 * 299 *
341*/ 300*/
342static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma) 301static void xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma)
343{ 302{
344 int err = - EINVAL;
345 struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1]; 303 struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1];
346 struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1]; 304 struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1];
347 struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1]; 305 struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1];
@@ -349,8 +307,6 @@ static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma)
349 307
350 if (rp) { 308 if (rp) {
351 struct xfrm_replay_state *replay; 309 struct xfrm_replay_state *replay;
352 if (RTA_PAYLOAD(rp) < sizeof(*replay))
353 goto error;
354 replay = RTA_DATA(rp); 310 replay = RTA_DATA(rp);
355 memcpy(&x->replay, replay, sizeof(*replay)); 311 memcpy(&x->replay, replay, sizeof(*replay));
356 memcpy(&x->preplay, replay, sizeof(*replay)); 312 memcpy(&x->preplay, replay, sizeof(*replay));
@@ -358,8 +314,6 @@ static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma)
358 314
359 if (lt) { 315 if (lt) {
360 struct xfrm_lifetime_cur *ltime; 316 struct xfrm_lifetime_cur *ltime;
361 if (RTA_PAYLOAD(lt) < sizeof(*ltime))
362 goto error;
363 ltime = RTA_DATA(lt); 317 ltime = RTA_DATA(lt);
364 x->curlft.bytes = ltime->bytes; 318 x->curlft.bytes = ltime->bytes;
365 x->curlft.packets = ltime->packets; 319 x->curlft.packets = ltime->packets;
@@ -367,21 +321,11 @@ static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma)
367 x->curlft.use_time = ltime->use_time; 321 x->curlft.use_time = ltime->use_time;
368 } 322 }
369 323
370 if (et) { 324 if (et)
371 if (RTA_PAYLOAD(et) < sizeof(u32))
372 goto error;
373 x->replay_maxage = *(u32*)RTA_DATA(et); 325 x->replay_maxage = *(u32*)RTA_DATA(et);
374 }
375 326
376 if (rt) { 327 if (rt)
377 if (RTA_PAYLOAD(rt) < sizeof(u32))
378 goto error;
379 x->replay_maxdiff = *(u32*)RTA_DATA(rt); 328 x->replay_maxdiff = *(u32*)RTA_DATA(rt);
380 }
381
382 return 0;
383error:
384 return err;
385} 329}
386 330
387static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, 331static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
@@ -429,9 +373,7 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
429 373
430 /* override default values from above */ 374 /* override default values from above */
431 375
432 err = xfrm_update_ae_params(x, (struct rtattr **)xfrma); 376 xfrm_update_ae_params(x, (struct rtattr **)xfrma);
433 if (err < 0)
434 goto error;
435 377
436 return x; 378 return x;
437 379
@@ -497,10 +439,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
497 } else { 439 } else {
498 xfrm_address_t *saddr = NULL; 440 xfrm_address_t *saddr = NULL;
499 441
500 err = verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr); 442 verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr);
501 if (err)
502 goto out;
503
504 if (!saddr) { 443 if (!saddr) {
505 err = -EINVAL; 444 err = -EINVAL;
506 goto out; 445 goto out;
@@ -1072,9 +1011,6 @@ static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma)
1072 int err; 1011 int err;
1073 1012
1074 if (rt) { 1013 if (rt) {
1075 if (rt->rta_len < sizeof(*upt))
1076 return -EINVAL;
1077
1078 upt = RTA_DATA(rt); 1014 upt = RTA_DATA(rt);
1079 type = upt->type; 1015 type = upt->type;
1080 } 1016 }
@@ -1537,10 +1473,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1537 goto out; 1473 goto out;
1538 1474
1539 spin_lock_bh(&x->lock); 1475 spin_lock_bh(&x->lock);
1540 err = xfrm_update_ae_params(x, xfrma); 1476 xfrm_update_ae_params(x, xfrma);
1541 spin_unlock_bh(&x->lock); 1477 spin_unlock_bh(&x->lock);
1542 if (err < 0)
1543 goto out;
1544 1478
1545 c.event = nlh->nlmsg_type; 1479 c.event = nlh->nlmsg_type;
1546 c.seq = nlh->nlmsg_seq; 1480 c.seq = nlh->nlmsg_seq;
@@ -1726,20 +1660,6 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1726} 1660}
1727 1661
1728#ifdef CONFIG_XFRM_MIGRATE 1662#ifdef CONFIG_XFRM_MIGRATE
1729static int verify_user_migrate(struct rtattr **xfrma)
1730{
1731 struct rtattr *rt = xfrma[XFRMA_MIGRATE-1];
1732 struct xfrm_user_migrate *um;
1733
1734 if (!rt)
1735 return -EINVAL;
1736
1737 if ((rt->rta_len - sizeof(*rt)) < sizeof(*um))
1738 return -EINVAL;
1739
1740 return 0;
1741}
1742
1743static int copy_from_user_migrate(struct xfrm_migrate *ma, 1663static int copy_from_user_migrate(struct xfrm_migrate *ma,
1744 struct rtattr **xfrma, int *num) 1664 struct rtattr **xfrma, int *num)
1745{ 1665{
@@ -1780,9 +1700,8 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
1780 int err; 1700 int err;
1781 int n = 0; 1701 int n = 0;
1782 1702
1783 err = verify_user_migrate((struct rtattr **)xfrma); 1703 if (xfrma[XFRMA_MIGRATE-1] == NULL)
1784 if (err) 1704 return -EINVAL;
1785 return err;
1786 1705
1787 err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); 1706 err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
1788 if (err) 1707 if (err)
@@ -1917,6 +1836,23 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
1917 1836
1918#undef XMSGSIZE 1837#undef XMSGSIZE
1919 1838
1839static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
1840 [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) },
1841 [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) },
1842 [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
1843 [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
1844 [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
1845 [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
1846 [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
1847 [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
1848 [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
1849 [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 },
1850 [XFRMA_SRCADDR] = { .len = sizeof(xfrm_address_t) },
1851 [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) },
1852 [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)},
1853 [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
1854};
1855
1920static struct xfrm_link { 1856static struct xfrm_link {
1921 int (*doit)(struct sk_buff *, struct nlmsghdr *, struct rtattr **); 1857 int (*doit)(struct sk_buff *, struct nlmsghdr *, struct rtattr **);
1922 int (*dump)(struct sk_buff *, struct netlink_callback *); 1858 int (*dump)(struct sk_buff *, struct netlink_callback *);
@@ -1972,7 +1908,8 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1972 1908
1973 /* FIXME: Temporary hack, nlmsg_parse() starts at xfrma[1], old code 1909 /* FIXME: Temporary hack, nlmsg_parse() starts at xfrma[1], old code
1974 * expects first attribute at xfrma[0] */ 1910 * expects first attribute at xfrma[0] */
1975 err = nlmsg_parse(nlh, xfrm_msg_min[type], xfrma-1, XFRMA_MAX, NULL); 1911 err = nlmsg_parse(nlh, xfrm_msg_min[type], xfrma-1, XFRMA_MAX,
1912 xfrma_policy);
1976 if (err < 0) 1913 if (err < 0)
1977 return err; 1914 return err;
1978 1915