Skip to content

Commit d2ddf62

Browse files
committed
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2018-03-13 1) Refuse to insert 32 bit userspace socket policies on 64 bit systems like we do it for standard policies. We don't have a compat layer, so inserting socket policies from 32 bit userspace will lead to a broken configuration. 2) Make the policy hold queue work without the flowcache. Dummy bundles are not chached anymore, so we need to generate a new one on each lookup as long as the SAs are not yet in place. 3) Fix the validation of the esn replay attribute. The The sanity check in verify_replay() is bypassed if the XFRM_STATE_ESN flag is not set. Fix this by doing the sanity check uncoditionally. From Florian Westphal. 4) After most of the dst_entry garbage collection code is removed, we may leak xfrm_dst entries as they are neither cached nor tracked somewhere. Fix this by reusing the 'uncached_list' to track xfrm_dst entries too. From Xin Long. 5) Fix a rcu_read_lock/rcu_read_unlock imbalance in xfrm_get_tos() From Xin Long. 6) Fix an infinite loop in xfrm_get_dst_nexthop. On transport mode we fetch the child dst_entry after we continue, so this pointer is never updated. Fix this by fetching it before we continue. 7) Fix ESN sequence number gap after IPsec GSO packets. We accidentally increment the sequence number counter on the xfrm_state by one packet too much in the ESN case. Fix this by setting the sequence number to the correct value. 8) Reset the ethernet protocol after decapsulation only if a mac header was set. Otherwise it breaks configurations with TUN devices. From Yossi Kuperman. 9) Fix __this_cpu_read() usage in preemptible code. Use this_cpu_read() instead in ipcomp_alloc_tfms(). From Greg Hackmann. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5a9f8df + 0dcd787 commit d2ddf62

File tree

13 files changed

+56
-33
lines changed

13 files changed

+56
-33
lines changed

include/net/ip6_route.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ void rt6_disable_ip(struct net_device *dev, unsigned long event);
179179
void rt6_sync_down_dev(struct net_device *dev, unsigned long event);
180180
void rt6_multipath_rebalance(struct rt6_info *rt);
181181

182+
void rt6_uncached_list_add(struct rt6_info *rt);
183+
void rt6_uncached_list_del(struct rt6_info *rt);
184+
182185
static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb)
183186
{
184187
const struct dst_entry *dst = skb_dst(skb);

include/net/route.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ struct in_ifaddr;
227227
void fib_add_ifaddr(struct in_ifaddr *);
228228
void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
229229

230+
void rt_add_uncached_list(struct rtable *rt);
231+
void rt_del_uncached_list(struct rtable *rt);
232+
230233
static inline void ip_rt_put(struct rtable *rt)
231234
{
232235
/* dst_release() accepts a NULL parameter.

net/ipv4/route.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,7 @@ struct uncached_list {
13931393

13941394
static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt_uncached_list);
13951395

1396-
static void rt_add_uncached_list(struct rtable *rt)
1396+
void rt_add_uncached_list(struct rtable *rt)
13971397
{
13981398
struct uncached_list *ul = raw_cpu_ptr(&rt_uncached_list);
13991399

@@ -1404,14 +1404,8 @@ static void rt_add_uncached_list(struct rtable *rt)
14041404
spin_unlock_bh(&ul->lock);
14051405
}
14061406

1407-
static void ipv4_dst_destroy(struct dst_entry *dst)
1407+
void rt_del_uncached_list(struct rtable *rt)
14081408
{
1409-
struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
1410-
struct rtable *rt = (struct rtable *) dst;
1411-
1412-
if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
1413-
kfree(p);
1414-
14151409
if (!list_empty(&rt->rt_uncached)) {
14161410
struct uncached_list *ul = rt->rt_uncached_list;
14171411

@@ -1421,6 +1415,17 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
14211415
}
14221416
}
14231417

1418+
static void ipv4_dst_destroy(struct dst_entry *dst)
1419+
{
1420+
struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
1421+
struct rtable *rt = (struct rtable *)dst;
1422+
1423+
if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt))
1424+
kfree(p);
1425+
1426+
rt_del_uncached_list(rt);
1427+
}
1428+
14241429
void rt_flush_dev(struct net_device *dev)
14251430
{
14261431
struct net *net = dev_net(dev);

net/ipv4/xfrm4_mode_tunnel.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
9292

9393
skb_reset_network_header(skb);
9494
skb_mac_header_rebuild(skb);
95-
eth_hdr(skb)->h_proto = skb->protocol;
95+
if (skb->mac_len)
96+
eth_hdr(skb)->h_proto = skb->protocol;
9697

9798
err = 0;
9899

net/ipv4/xfrm4_policy.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
102102
xdst->u.rt.rt_pmtu = rt->rt_pmtu;
103103
xdst->u.rt.rt_table_id = rt->rt_table_id;
104104
INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
105+
rt_add_uncached_list(&xdst->u.rt);
105106

106107
return 0;
107108
}
@@ -241,7 +242,8 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
241242
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
242243

243244
dst_destroy_metrics_generic(dst);
244-
245+
if (xdst->u.rt.rt_uncached_list)
246+
rt_del_uncached_list(&xdst->u.rt);
245247
xfrm_dst_destroy(xdst);
246248
}
247249

net/ipv6/route.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ struct uncached_list {
128128

129129
static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt6_uncached_list);
130130

131-
static void rt6_uncached_list_add(struct rt6_info *rt)
131+
void rt6_uncached_list_add(struct rt6_info *rt)
132132
{
133133
struct uncached_list *ul = raw_cpu_ptr(&rt6_uncached_list);
134134

@@ -139,7 +139,7 @@ static void rt6_uncached_list_add(struct rt6_info *rt)
139139
spin_unlock_bh(&ul->lock);
140140
}
141141

142-
static void rt6_uncached_list_del(struct rt6_info *rt)
142+
void rt6_uncached_list_del(struct rt6_info *rt)
143143
{
144144
if (!list_empty(&rt->rt6i_uncached)) {
145145
struct uncached_list *ul = rt->rt6i_uncached_list;

net/ipv6/xfrm6_mode_tunnel.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
9292

9393
skb_reset_network_header(skb);
9494
skb_mac_header_rebuild(skb);
95-
eth_hdr(skb)->h_proto = skb->protocol;
95+
if (skb->mac_len)
96+
eth_hdr(skb)->h_proto = skb->protocol;
9697

9798
err = 0;
9899

net/ipv6/xfrm6_policy.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
113113
xdst->u.rt6.rt6i_gateway = rt->rt6i_gateway;
114114
xdst->u.rt6.rt6i_dst = rt->rt6i_dst;
115115
xdst->u.rt6.rt6i_src = rt->rt6i_src;
116+
INIT_LIST_HEAD(&xdst->u.rt6.rt6i_uncached);
117+
rt6_uncached_list_add(&xdst->u.rt6);
118+
atomic_inc(&dev_net(dev)->ipv6.rt6_stats->fib_rt_uncache);
116119

117120
return 0;
118121
}
@@ -244,6 +247,8 @@ static void xfrm6_dst_destroy(struct dst_entry *dst)
244247
if (likely(xdst->u.rt6.rt6i_idev))
245248
in6_dev_put(xdst->u.rt6.rt6i_idev);
246249
dst_destroy_metrics_generic(dst);
250+
if (xdst->u.rt6.rt6i_uncached_list)
251+
rt6_uncached_list_del(&xdst->u.rt6);
247252
xfrm_dst_destroy(xdst);
248253
}
249254

net/xfrm/xfrm_ipcomp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
283283
struct crypto_comp *tfm;
284284

285285
/* This can be any valid CPU ID so we don't need locking. */
286-
tfm = __this_cpu_read(*pos->tfms);
286+
tfm = this_cpu_read(*pos->tfms);
287287

288288
if (!strcmp(crypto_comp_name(tfm), alg_name)) {
289289
pos->users++;

net/xfrm/xfrm_policy.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,10 +1458,13 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, const struct flowi *fl,
14581458
static int xfrm_get_tos(const struct flowi *fl, int family)
14591459
{
14601460
const struct xfrm_policy_afinfo *afinfo;
1461-
int tos = 0;
1461+
int tos;
14621462

14631463
afinfo = xfrm_policy_get_afinfo(family);
1464-
tos = afinfo ? afinfo->get_tos(fl) : 0;
1464+
if (!afinfo)
1465+
return 0;
1466+
1467+
tos = afinfo->get_tos(fl);
14651468

14661469
rcu_read_unlock();
14671470

@@ -1891,7 +1894,7 @@ static void xfrm_policy_queue_process(struct timer_list *t)
18911894
spin_unlock(&pq->hold_queue.lock);
18921895

18931896
dst_hold(xfrm_dst_path(dst));
1894-
dst = xfrm_lookup(net, xfrm_dst_path(dst), &fl, sk, 0);
1897+
dst = xfrm_lookup(net, xfrm_dst_path(dst), &fl, sk, XFRM_LOOKUP_QUEUE);
18951898
if (IS_ERR(dst))
18961899
goto purge_queue;
18971900

@@ -2729,14 +2732,14 @@ static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst,
27292732
while (dst->xfrm) {
27302733
const struct xfrm_state *xfrm = dst->xfrm;
27312734

2735+
dst = xfrm_dst_child(dst);
2736+
27322737
if (xfrm->props.mode == XFRM_MODE_TRANSPORT)
27332738
continue;
27342739
if (xfrm->type->flags & XFRM_TYPE_REMOTE_COADDR)
27352740
daddr = xfrm->coaddr;
27362741
else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR))
27372742
daddr = &xfrm->id.daddr;
2738-
2739-
dst = xfrm_dst_child(dst);
27402743
}
27412744
return daddr;
27422745
}

net/xfrm/xfrm_replay.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff
660660
} else {
661661
XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
662662
XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
663-
xo->seq.low = oseq = oseq + 1;
663+
xo->seq.low = oseq + 1;
664664
xo->seq.hi = oseq_hi;
665665
oseq += skb_shinfo(skb)->gso_segs;
666666
}

net/xfrm/xfrm_state.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,11 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
20562056
struct xfrm_mgr *km;
20572057
struct xfrm_policy *pol = NULL;
20582058

2059+
#ifdef CONFIG_COMPAT
2060+
if (in_compat_syscall())
2061+
return -EOPNOTSUPP;
2062+
#endif
2063+
20592064
if (!optval && !optlen) {
20602065
xfrm_sk_policy_insert(sk, XFRM_POLICY_IN, NULL);
20612066
xfrm_sk_policy_insert(sk, XFRM_POLICY_OUT, NULL);

net/xfrm/xfrm_user.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,17 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
121121
struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
122122
struct xfrm_replay_state_esn *rs;
123123

124-
if (p->flags & XFRM_STATE_ESN) {
125-
if (!rt)
126-
return -EINVAL;
124+
if (!rt)
125+
return (p->flags & XFRM_STATE_ESN) ? -EINVAL : 0;
127126

128-
rs = nla_data(rt);
127+
rs = nla_data(rt);
129128

130-
if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
131-
return -EINVAL;
132-
133-
if (nla_len(rt) < (int)xfrm_replay_state_esn_len(rs) &&
134-
nla_len(rt) != sizeof(*rs))
135-
return -EINVAL;
136-
}
129+
if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
130+
return -EINVAL;
137131

138-
if (!rt)
139-
return 0;
132+
if (nla_len(rt) < (int)xfrm_replay_state_esn_len(rs) &&
133+
nla_len(rt) != sizeof(*rs))
134+
return -EINVAL;
140135

141136
/* As only ESP and AH support ESN feature. */
142137
if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH))

0 commit comments

Comments
 (0)