Skip to content

Commit cf5cb79

Browse files
tgrafDavid S. Miller
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a7bd9a4 commit cf5cb79

File tree

1 file changed

+31
-94
lines changed

1 file changed

+31
-94
lines changed

net/xfrm/xfrm_user.c

Lines changed: 31 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,12 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
4242
{
4343
struct rtattr *rt = xfrma[type - 1];
4444
struct xfrm_algo *algp;
45-
int len;
4645

4746
if (!rt)
4847
return 0;
4948

50-
len = (rt->rta_len - sizeof(*rt)) - sizeof(*algp);
51-
if (len < 0)
52-
return -EINVAL;
53-
5449
algp = RTA_DATA(rt);
55-
56-
len -= (algp->alg_key_len + 7U) / 8;
57-
if (len < 0)
50+
if (RTA_PAYLOAD(rt) < alg_len(algp))
5851
return -EINVAL;
5952

6053
switch (type) {
@@ -82,55 +75,25 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
8275
return 0;
8376
}
8477

85-
static int verify_encap_tmpl(struct rtattr **xfrma)
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,
78+
static void verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type,
10079
xfrm_address_t **addrp)
10180
{
10281
struct rtattr *rt = xfrma[type - 1];
10382

104-
if (!rt)
105-
return 0;
106-
107-
if ((rt->rta_len - sizeof(*rt)) < sizeof(**addrp))
108-
return -EINVAL;
109-
110-
if (addrp)
83+
if (rt && addrp)
11184
*addrp = RTA_DATA(rt);
112-
113-
return 0;
11485
}
11586

11687
static inline int verify_sec_ctx_len(struct rtattr **xfrma)
11788
{
11889
struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1];
11990
struct xfrm_user_sec_ctx *uctx;
120-
int len = 0;
12191

12292
if (!rt)
12393
return 0;
12494

125-
if (rt->rta_len < sizeof(*uctx))
126-
return -EINVAL;
127-
12895
uctx = RTA_DATA(rt);
129-
130-
len += sizeof(struct xfrm_user_sec_ctx);
131-
len += uctx->ctx_len;
132-
133-
if (uctx->len != len)
96+
if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
13497
return -EINVAL;
13598

13699
return 0;
@@ -205,12 +168,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
205168
goto out;
206169
if ((err = verify_one_alg(xfrma, XFRMA_ALG_COMP)))
207170
goto out;
208-
if ((err = verify_encap_tmpl(xfrma)))
209-
goto out;
210171
if ((err = verify_sec_ctx_len(xfrma)))
211172
goto out;
212-
if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL)))
213-
goto out;
214173

215174
err = -EINVAL;
216175
switch (p->mode) {
@@ -339,49 +298,34 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
339298
* somehow made shareable and move it to xfrm_state.c - JHS
340299
*
341300
*/
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)
343302
{
344-
int err = - EINVAL;
345303
struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1];
346304
struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1];
347305
struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1];
348306
struct rtattr *rt = xfrma[XFRMA_REPLAY_THRESH-1];
349307

350308
if (rp) {
351309
struct xfrm_replay_state *replay;
352-
if (RTA_PAYLOAD(rp) < sizeof(*replay))
353-
goto error;
354310
replay = RTA_DATA(rp);
355311
memcpy(&x->replay, replay, sizeof(*replay));
356312
memcpy(&x->preplay, replay, sizeof(*replay));
357313
}
358314

359315
if (lt) {
360316
struct xfrm_lifetime_cur *ltime;
361-
if (RTA_PAYLOAD(lt) < sizeof(*ltime))
362-
goto error;
363317
ltime = RTA_DATA(lt);
364318
x->curlft.bytes = ltime->bytes;
365319
x->curlft.packets = ltime->packets;
366320
x->curlft.add_time = ltime->add_time;
367321
x->curlft.use_time = ltime->use_time;
368322
}
369323

370-
if (et) {
371-
if (RTA_PAYLOAD(et) < sizeof(u32))
372-
goto error;
324+
if (et)
373325
x->replay_maxage = *(u32*)RTA_DATA(et);
374-
}
375326

376-
if (rt) {
377-
if (RTA_PAYLOAD(rt) < sizeof(u32))
378-
goto error;
327+
if (rt)
379328
x->replay_maxdiff = *(u32*)RTA_DATA(rt);
380-
}
381-
382-
return 0;
383-
error:
384-
return err;
385329
}
386330

387331
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,
429373

430374
/* override default values from above */
431375

432-
err = xfrm_update_ae_params(x, (struct rtattr **)xfrma);
433-
if (err < 0)
434-
goto error;
376+
xfrm_update_ae_params(x, (struct rtattr **)xfrma);
435377

436378
return x;
437379

@@ -497,10 +439,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
497439
} else {
498440
xfrm_address_t *saddr = NULL;
499441

500-
err = verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr);
501-
if (err)
502-
goto out;
503-
442+
verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr);
504443
if (!saddr) {
505444
err = -EINVAL;
506445
goto out;
@@ -1072,9 +1011,6 @@ static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma)
10721011
int err;
10731012

10741013
if (rt) {
1075-
if (rt->rta_len < sizeof(*upt))
1076-
return -EINVAL;
1077-
10781014
upt = RTA_DATA(rt);
10791015
type = upt->type;
10801016
}
@@ -1537,10 +1473,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
15371473
goto out;
15381474

15391475
spin_lock_bh(&x->lock);
1540-
err = xfrm_update_ae_params(x, xfrma);
1476+
xfrm_update_ae_params(x, xfrma);
15411477
spin_unlock_bh(&x->lock);
1542-
if (err < 0)
1543-
goto out;
15441478

15451479
c.event = nlh->nlmsg_type;
15461480
c.seq = nlh->nlmsg_seq;
@@ -1726,20 +1660,6 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
17261660
}
17271661

17281662
#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-
17431663
static int copy_from_user_migrate(struct xfrm_migrate *ma,
17441664
struct rtattr **xfrma, int *num)
17451665
{
@@ -1780,9 +1700,8 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
17801700
int err;
17811701
int n = 0;
17821702

1783-
err = verify_user_migrate((struct rtattr **)xfrma);
1784-
if (err)
1785-
return err;
1703+
if (xfrma[XFRMA_MIGRATE-1] == NULL)
1704+
return -EINVAL;
17861705

17871706
err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
17881707
if (err)
@@ -1917,6 +1836,23 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
19171836

19181837
#undef XMSGSIZE
19191838

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+
19201856
static struct xfrm_link {
19211857
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct rtattr **);
19221858
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)
19721908

19731909
/* FIXME: Temporary hack, nlmsg_parse() starts at xfrma[1], old code
19741910
* 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);
19761913
if (err < 0)
19771914
return err;
19781915

0 commit comments

Comments
 (0)