mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-26 07:44:27 +08:00
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
|
#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)
|
static inline int xfrm_alg_len(const struct xfrm_algo *alg)
|
||||||
{
|
{
|
||||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
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;
|
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)
|
static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
|
||||||
{
|
{
|
||||||
return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
|
return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
|
||||||
|
@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
|
|||||||
config IPV6_VTI
|
config IPV6_VTI
|
||||||
tristate "Virtual (secure) IPv6: tunneling"
|
tristate "Virtual (secure) IPv6: tunneling"
|
||||||
select IPV6_TUNNEL
|
select IPV6_TUNNEL
|
||||||
|
select NET_IP_TUNNEL
|
||||||
depends on INET6_XFRM_MODE_TUNNEL
|
depends on INET6_XFRM_MODE_TUNNEL
|
||||||
---help---
|
---help---
|
||||||
Tunneling means encapsulating data of one protocol type within
|
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))
|
if (hlist_unhashed(&pol->bydst))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
hlist_del(&pol->bydst);
|
hlist_del_init(&pol->bydst);
|
||||||
hlist_del(&pol->byidx);
|
hlist_del(&pol->byidx);
|
||||||
list_del(&pol->walk.all);
|
list_del(&pol->walk.all);
|
||||||
net->xfrm.policy_count[dir]--;
|
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;
|
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) {
|
if (orig->ealg) {
|
||||||
x->ealg = xfrm_algo_clone(orig->ealg);
|
x->ealg = xfrm_algo_clone(orig->ealg);
|
||||||
if (!x->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.flags = orig->props.flags;
|
||||||
x->props.extra_flags = orig->props.extra_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->curlft.add_time = orig->curlft.add_time;
|
||||||
x->km.state = orig->km.state;
|
x->km.state = orig->km.state;
|
||||||
x->km.seq = orig->km.seq;
|
x->km.seq = orig->km.seq;
|
||||||
@ -1215,11 +1223,12 @@ out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* net->xfrm.xfrm_state_lock is held */
|
|
||||||
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
|
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
|
||||||
{
|
{
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
struct xfrm_state *x;
|
struct xfrm_state *x = NULL;
|
||||||
|
|
||||||
|
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||||
|
|
||||||
if (m->reqid) {
|
if (m->reqid) {
|
||||||
h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
|
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))
|
m->old_family))
|
||||||
continue;
|
continue;
|
||||||
xfrm_state_hold(x);
|
xfrm_state_hold(x);
|
||||||
return x;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
|
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))
|
m->old_family))
|
||||||
continue;
|
continue;
|
||||||
xfrm_state_hold(x);
|
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);
|
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;
|
int err = 0;
|
||||||
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
|
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
|
||||||
struct net *net = xs_net(*dst);
|
struct net *net = xs_net(*src);
|
||||||
|
|
||||||
if (!afinfo)
|
if (!afinfo)
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
|
@ -32,11 +32,6 @@
|
|||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
#endif
|
#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)
|
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
|
||||||
{
|
{
|
||||||
struct nlattr *rt = attrs[type];
|
struct nlattr *rt = attrs[type];
|
||||||
|
Loading…
Reference in New Issue
Block a user