Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== 1) Build fix for ip_vti when NET_IP_TUNNEL is not set. We need this set to have ip_tunnel_get_stats64() available. 2) Fix a NULL pointer dereference on sub policy usage. We try to access a xfrm_state from the wrong array. 3) Take xfrm_state_lock in xfrm_migrate_state_find(), we need it to traverse through the state lists. 4) Clone states properly on migration, otherwise we crash when we migrate a state with aead algorithm attached. 5) Fix unlink race when between thread context and timer when policies are deleted. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
23187212e7
|
@ -1648,6 +1648,11 @@ static inline int xfrm_aevent_is_on(struct net *net)
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline int aead_len(struct xfrm_algo_aead *alg)
|
||||
{
|
||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
||||
}
|
||||
|
||||
static inline int xfrm_alg_len(const struct xfrm_algo *alg)
|
||||
{
|
||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
||||
|
@ -1686,6 +1691,12 @@ static inline int xfrm_replay_clone(struct xfrm_state *x,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline struct xfrm_algo_aead *xfrm_algo_aead_clone(struct xfrm_algo_aead *orig)
|
||||
{
|
||||
return kmemdup(orig, aead_len(orig), GFP_KERNEL);
|
||||
}
|
||||
|
||||
|
||||
static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
|
||||
{
|
||||
return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
|
||||
|
|
|
@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
|
|||
config IPV6_VTI
|
||||
tristate "Virtual (secure) IPv6: tunneling"
|
||||
select IPV6_TUNNEL
|
||||
select NET_IP_TUNNEL
|
||||
depends on INET6_XFRM_MODE_TUNNEL
|
||||
---help---
|
||||
Tunneling means encapsulating data of one protocol type within
|
||||
|
|
|
@ -1158,7 +1158,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
|
|||
if (hlist_unhashed(&pol->bydst))
|
||||
return NULL;
|
||||
|
||||
hlist_del(&pol->bydst);
|
||||
hlist_del_init(&pol->bydst);
|
||||
hlist_del(&pol->byidx);
|
||||
list_del(&pol->walk.all);
|
||||
net->xfrm.policy_count[dir]--;
|
||||
|
|
|
@ -1159,6 +1159,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
|
|||
}
|
||||
x->props.aalgo = orig->props.aalgo;
|
||||
|
||||
if (orig->aead) {
|
||||
x->aead = xfrm_algo_aead_clone(orig->aead);
|
||||
if (!x->aead)
|
||||
goto error;
|
||||
}
|
||||
if (orig->ealg) {
|
||||
x->ealg = xfrm_algo_clone(orig->ealg);
|
||||
if (!x->ealg)
|
||||
|
@ -1201,6 +1206,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
|
|||
x->props.flags = orig->props.flags;
|
||||
x->props.extra_flags = orig->props.extra_flags;
|
||||
|
||||
x->tfcpad = orig->tfcpad;
|
||||
x->replay_maxdiff = orig->replay_maxdiff;
|
||||
x->replay_maxage = orig->replay_maxage;
|
||||
x->curlft.add_time = orig->curlft.add_time;
|
||||
x->km.state = orig->km.state;
|
||||
x->km.seq = orig->km.seq;
|
||||
|
@ -1215,11 +1223,12 @@ out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* net->xfrm.xfrm_state_lock is held */
|
||||
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
|
||||
{
|
||||
unsigned int h;
|
||||
struct xfrm_state *x;
|
||||
struct xfrm_state *x = NULL;
|
||||
|
||||
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||
|
||||
if (m->reqid) {
|
||||
h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
|
||||
|
@ -1236,7 +1245,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
|
|||
m->old_family))
|
||||
continue;
|
||||
xfrm_state_hold(x);
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
|
||||
|
@ -1251,11 +1260,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
|
|||
m->old_family))
|
||||
continue;
|
||||
xfrm_state_hold(x);
|
||||
return x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
|
||||
|
||||
return x;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_migrate_state_find);
|
||||
|
||||
|
@ -1451,7 +1462,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
|
|||
{
|
||||
int err = 0;
|
||||
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
|
||||
struct net *net = xs_net(*dst);
|
||||
struct net *net = xs_net(*src);
|
||||
|
||||
if (!afinfo)
|
||||
return -EAFNOSUPPORT;
|
||||
|
|
|
@ -32,11 +32,6 @@
|
|||
#include <linux/in6.h>
|
||||
#endif
|
||||
|
||||
static inline int aead_len(struct xfrm_algo_aead *alg)
|
||||
{
|
||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
||||
}
|
||||
|
||||
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
|
||||
{
|
||||
struct nlattr *rt = attrs[type];
|
||||
|
|
Loading…
Reference in a new issue