diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:15 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:59 -0400 |
| commit | 07f9479a40cc778bc1462ada11f95b01360ae4ff (patch) | |
| tree | 0676cf38df3844004bb3ebfd99dfa67a4a8998f5 /net/xfrm | |
| parent | 9d5e6bdb3013acfb311ab407eeca0b6a6a3dedbf (diff) | |
| parent | cd2e49e90f1cae7726c9a2c54488d881d7f1cd1c (diff) | |
Merge branch 'master' into for-next
Fast-forwarded to current state of Linus' tree as there are patches to be
applied for files that didn't exist on the old branch.
Diffstat (limited to 'net/xfrm')
| -rw-r--r-- | net/xfrm/xfrm_input.c | 4 | ||||
| -rw-r--r-- | net/xfrm/xfrm_output.c | 4 | ||||
| -rw-r--r-- | net/xfrm/xfrm_replay.c | 17 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 21 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 32 |
5 files changed, 69 insertions, 9 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 872065ca7f8c..a026b0ef2443 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
| @@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 173 | goto drop_unlock; | 173 | goto drop_unlock; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | if (x->props.replay_window && x->repl->check(x, skb, seq)) { | 176 | if (x->repl->check(x, skb, seq)) { |
| 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); | 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
| 178 | goto drop_unlock; | 178 | goto drop_unlock; |
| 179 | } | 179 | } |
| @@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; | 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; |
| 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; | 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
| 192 | 192 | ||
| 193 | skb_dst_force(skb); | ||
| 194 | |||
| 193 | nexthdr = x->type->input(x, skb); | 195 | nexthdr = x->type->input(x, skb); |
| 194 | 196 | ||
| 195 | if (nexthdr == -EINPROGRESS) | 197 | if (nexthdr == -EINPROGRESS) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 1aba03f449cc..47bacd8c0250 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
| 78 | 78 | ||
| 79 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
| 80 | 80 | ||
| 81 | skb_dst_force(skb); | ||
| 82 | |||
| 81 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
| 82 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
| 83 | goto out_exit; | 85 | goto out_exit; |
| @@ -94,7 +96,7 @@ resume: | |||
| 94 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
| 95 | goto error_nolock; | 97 | goto error_nolock; |
| 96 | } | 98 | } |
| 97 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
| 98 | x = dst->xfrm; | 100 | x = dst->xfrm; |
| 99 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
| 100 | 102 | ||
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f5be5b15740..f218385950ca 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
| 118 | u32 diff; | 118 | u32 diff; |
| 119 | u32 seq = ntohl(net_seq); | 119 | u32 seq = ntohl(net_seq); |
| 120 | 120 | ||
| 121 | if (!x->props.replay_window) | ||
| 122 | return 0; | ||
| 123 | |||
| 121 | if (unlikely(seq == 0)) | 124 | if (unlikely(seq == 0)) |
| 122 | goto err; | 125 | goto err; |
| 123 | 126 | ||
| @@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, | |||
| 193 | { | 196 | { |
| 194 | unsigned int bitnr, nr; | 197 | unsigned int bitnr, nr; |
| 195 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 198 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 199 | u32 pos; | ||
| 196 | u32 seq = ntohl(net_seq); | 200 | u32 seq = ntohl(net_seq); |
| 197 | u32 diff = replay_esn->seq - seq; | 201 | u32 diff = replay_esn->seq - seq; |
| 198 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | 202 | |
| 203 | if (!replay_esn->replay_window) | ||
| 204 | return 0; | ||
| 205 | |||
| 206 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 199 | 207 | ||
| 200 | if (unlikely(seq == 0)) | 208 | if (unlikely(seq == 0)) |
| 201 | goto err; | 209 | goto err; |
| @@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, | |||
| 373 | unsigned int bitnr, nr; | 381 | unsigned int bitnr, nr; |
| 374 | u32 diff; | 382 | u32 diff; |
| 375 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 383 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 384 | u32 pos; | ||
| 376 | u32 seq = ntohl(net_seq); | 385 | u32 seq = ntohl(net_seq); |
| 377 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 378 | u32 wsize = replay_esn->replay_window; | 386 | u32 wsize = replay_esn->replay_window; |
| 379 | u32 top = replay_esn->seq; | 387 | u32 top = replay_esn->seq; |
| 380 | u32 bottom = top - wsize + 1; | 388 | u32 bottom = top - wsize + 1; |
| 381 | 389 | ||
| 390 | if (!wsize) | ||
| 391 | return 0; | ||
| 392 | |||
| 393 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 394 | |||
| 382 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && | 395 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && |
| 383 | (replay_esn->seq < replay_esn->replay_window - 1))) | 396 | (replay_esn->seq < replay_esn->replay_window - 1))) |
| 384 | goto err; | 397 | goto err; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d575f0534868..dd78536d40de 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1181 | goto error; | 1181 | goto error; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | if (orig->replay_esn) { | ||
| 1185 | err = xfrm_replay_clone(x, orig); | ||
| 1186 | if (err) | ||
| 1187 | goto error; | ||
| 1188 | } | ||
| 1189 | |||
| 1184 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1190 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
| 1185 | 1191 | ||
| 1186 | err = xfrm_init_state(x); | 1192 | err = xfrm_init_state(x); |
| @@ -1907,7 +1913,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
| 1907 | return res; | 1913 | return res; |
| 1908 | } | 1914 | } |
| 1909 | 1915 | ||
| 1910 | int xfrm_init_state(struct xfrm_state *x) | 1916 | int __xfrm_init_state(struct xfrm_state *x, bool init_replay) |
| 1911 | { | 1917 | { |
| 1912 | struct xfrm_state_afinfo *afinfo; | 1918 | struct xfrm_state_afinfo *afinfo; |
| 1913 | struct xfrm_mode *inner_mode; | 1919 | struct xfrm_mode *inner_mode; |
| @@ -1980,12 +1986,25 @@ int xfrm_init_state(struct xfrm_state *x) | |||
| 1980 | if (x->outer_mode == NULL) | 1986 | if (x->outer_mode == NULL) |
| 1981 | goto error; | 1987 | goto error; |
| 1982 | 1988 | ||
| 1989 | if (init_replay) { | ||
| 1990 | err = xfrm_init_replay(x); | ||
| 1991 | if (err) | ||
| 1992 | goto error; | ||
| 1993 | } | ||
| 1994 | |||
| 1983 | x->km.state = XFRM_STATE_VALID; | 1995 | x->km.state = XFRM_STATE_VALID; |
| 1984 | 1996 | ||
| 1985 | error: | 1997 | error: |
| 1986 | return err; | 1998 | return err; |
| 1987 | } | 1999 | } |
| 1988 | 2000 | ||
| 2001 | EXPORT_SYMBOL(__xfrm_init_state); | ||
| 2002 | |||
| 2003 | int xfrm_init_state(struct xfrm_state *x) | ||
| 2004 | { | ||
| 2005 | return __xfrm_init_state(x, true); | ||
| 2006 | } | ||
| 2007 | |||
| 1989 | EXPORT_SYMBOL(xfrm_init_state); | 2008 | EXPORT_SYMBOL(xfrm_init_state); |
| 1990 | 2009 | ||
| 1991 | int __net_init xfrm_state_init(struct net *net) | 2010 | int __net_init xfrm_state_init(struct net *net) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 706385ae3e4b..5d1d60d3ca83 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
| 127 | if (!rt) | 127 | if (!rt) |
| 128 | return 0; | 128 | return 0; |
| 129 | 129 | ||
| 130 | if (p->id.proto != IPPROTO_ESP) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 130 | if (p->replay_window != 0) | 133 | if (p->replay_window != 0) |
| 131 | return -EINVAL; | 134 | return -EINVAL; |
| 132 | 135 | ||
| @@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
| 360 | return 0; | 363 | return 0; |
| 361 | } | 364 | } |
| 362 | 365 | ||
| 366 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
| 367 | struct nlattr *rp) | ||
| 368 | { | ||
| 369 | struct xfrm_replay_state_esn *up; | ||
| 370 | |||
| 371 | if (!replay_esn || !rp) | ||
| 372 | return 0; | ||
| 373 | |||
| 374 | up = nla_data(rp); | ||
| 375 | |||
| 376 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
| 377 | xfrm_replay_state_esn_len(up)) | ||
| 378 | return -EINVAL; | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 363 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 383 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
| 364 | struct xfrm_replay_state_esn **preplay_esn, | 384 | struct xfrm_replay_state_esn **preplay_esn, |
| 365 | struct nlattr *rta) | 385 | struct nlattr *rta) |
| @@ -511,7 +531,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
| 511 | 531 | ||
| 512 | xfrm_mark_get(attrs, &x->mark); | 532 | xfrm_mark_get(attrs, &x->mark); |
| 513 | 533 | ||
| 514 | err = xfrm_init_state(x); | 534 | err = __xfrm_init_state(x, false); |
| 515 | if (err) | 535 | if (err) |
| 516 | goto error; | 536 | goto error; |
| 517 | 537 | ||
| @@ -874,7 +894,7 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
| 874 | u32 *f; | 894 | u32 *f; |
| 875 | 895 | ||
| 876 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 896 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
| 877 | if (nlh == NULL) /* shouldnt really happen ... */ | 897 | if (nlh == NULL) /* shouldn't really happen ... */ |
| 878 | return -EMSGSIZE; | 898 | return -EMSGSIZE; |
| 879 | 899 | ||
| 880 | f = nlmsg_data(nlh); | 900 | f = nlmsg_data(nlh); |
| @@ -934,7 +954,7 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, | |||
| 934 | u32 *f; | 954 | u32 *f; |
| 935 | 955 | ||
| 936 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | 956 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
| 937 | if (nlh == NULL) /* shouldnt really happen ... */ | 957 | if (nlh == NULL) /* shouldn't really happen ... */ |
| 938 | return -EMSGSIZE; | 958 | return -EMSGSIZE; |
| 939 | 959 | ||
| 940 | f = nlmsg_data(nlh); | 960 | f = nlmsg_data(nlh); |
| @@ -1341,7 +1361,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1341 | if (!xp) | 1361 | if (!xp) |
| 1342 | return err; | 1362 | return err; |
| 1343 | 1363 | ||
| 1344 | /* shouldnt excl be based on nlh flags?? | 1364 | /* shouldn't excl be based on nlh flags?? |
| 1345 | * Aha! this is anti-netlink really i.e more pfkey derived | 1365 | * Aha! this is anti-netlink really i.e more pfkey derived |
| 1346 | * in netlink excl is a flag and you wouldnt need | 1366 | * in netlink excl is a flag and you wouldnt need |
| 1347 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1367 | * a type XFRM_MSG_UPDPOLICY - JHS */ |
| @@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1766 | if (x->km.state != XFRM_STATE_VALID) | 1786 | if (x->km.state != XFRM_STATE_VALID) |
| 1767 | goto out; | 1787 | goto out; |
| 1768 | 1788 | ||
| 1789 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
| 1790 | if (err) | ||
| 1791 | goto out; | ||
| 1792 | |||
| 1769 | spin_lock_bh(&x->lock); | 1793 | spin_lock_bh(&x->lock); |
| 1770 | xfrm_update_ae_params(x, attrs); | 1794 | xfrm_update_ae_params(x, attrs); |
| 1771 | spin_unlock_bh(&x->lock); | 1795 | spin_unlock_bh(&x->lock); |
