diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 125 |
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 | ||
85 | static int verify_encap_tmpl(struct rtattr **xfrma) | 78 | static 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 | |||
99 | static 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 | ||
116 | static inline int verify_sec_ctx_len(struct rtattr **xfrma) | 87 | static 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 | */ |
342 | static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma) | 301 | static 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; | ||
383 | error: | ||
384 | return err; | ||
385 | } | 329 | } |
386 | 330 | ||
387 | static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | 331 | static 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 |
1729 | static 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 | |||
1743 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 1663 | static 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 | ||
1839 | static 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 | |||
1920 | static struct xfrm_link { | 1856 | static 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 | ||