History

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next

Steffen Klassert says: ==================== 1) Introduce skb_to_sgvec_nomark function to add further data to the sg list without calling sg_unmark_end first. Needed to add extended sequence number informations. From Fan Du. 2) Add IPsec extended sequence numbers support to the Authentication Header protocol for ipv4 and ipv6. From Fan Du. 3) Make the IPsec flowcache namespace aware, from Fan Du. 4) Avoid creating temporary SA for every packet when no key manager is registered. From Horia Geanta. 5) Support filtering of SA dumps to show only the SAs that match a given filter. From Nicolas Dichtel. 6) Remove caching of xfrm_policy_sk_bundles. The cached socket policy bundles are never used, instead we create a new cache entry whenever xfrm_lookup() is called on a socket policy. Most protocols cache the used routes to the socket, so this caching is not needed. 7) Fix a forgotten SADB_X_EXT_FILTER length check in pfkey, from Nicolas Dichtel. 8) Cleanup error handling of xfrm_state_clone. ====================

David S. Miller committed 12 years ago

Commit 1f5a7402 parents 3b5c8ab cc9ab6017 files · +396 −149Browse files

Unified · Split

17 files
  1. MAINTAINERS +1 −0
  2. include/linux/skbuff.h +2 −0
  3. include/net/flow.h +3 −2
  4. include/net/flowcache.h +25 −0
  5. include/net/netns/xfrm.h +11 −1
  6. include/net/xfrm.h +20 −5
  7. include/uapi/linux/pfkeyv2.h +14 −1
  8. include/uapi/linux/xfrm.h +10 −0
  9. net/core/flow.c +57 −70
  10. net/core/skbuff.c +26 −0
  11. net/ipv4/ah4.c +42 −11
  12. net/ipv6/ah6.c +45 −11
  13. net/key/af_key.c +38 −1
  14. net/xfrm/xfrm_policy.c +4 −31
  15. net/xfrm/xfrm_state.c +60 −12
  16. net/xfrm/xfrm_user.c +35 −2
  17. security/selinux/include/xfrm.h +3 −2
MAINTAINERS+1−0
@@ -6009,6 +6009,7 @@ L: netdev@vger.kernel.org · 6008 unmodified lines
60096009 T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
60106010 T: git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
60116011 S: Maintained
6012+F: net/core/flow.c
60126013 F: net/xfrm/
60136014 F: net/key/
60146015 F: net/ipv4/xfrm*
include/linux/skbuff.h+2−0
@@ -691,6 +691,8 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, · 690 unmodified lines
691691 unsigned int headroom);
692692 struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
693693 int newtailroom, gfp_t priority);
694+int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
695+ int offset, int len);
694696 int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset,
695697 int len);
696698 int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
include/net/flow.h+3−2
@@ -218,9 +218,10 @@ struct flow_cache_object *flow_cache_lookup(struct net *net, · 217 unmodified lines
218218 const struct flowi *key, u16 family,
219219 u8 dir, flow_resolve_t resolver,
220220 void *ctx);
221+int flow_cache_init(struct net *net);
221222
222−void flow_cache_flush(void);
223−void flow_cache_flush_deferred(void);
223+void flow_cache_flush(struct net *net);
224+void flow_cache_flush_deferred(struct net *net);
224225 extern atomic_t flow_cache_genid;
225226
226227 #endif
include/net/flowcache.h+25−0
@@ -0,0 +1,25 @@
1+#ifndef _NET_FLOWCACHE_H
2+#define _NET_FLOWCACHE_H
3+
4+#include <linux/interrupt.h>
5+#include <linux/types.h>
6+#include <linux/timer.h>
7+#include <linux/notifier.h>
8+
9+struct flow_cache_percpu {
10+ struct hlist_head *hash_table;
11+ int hash_count;
12+ u32 hash_rnd;
13+ int hash_rnd_recalc;
14+ struct tasklet_struct flush_tasklet;
15+};
16+
17+struct flow_cache {
18+ u32 hash_shift;
19+ struct flow_cache_percpu __percpu *percpu;
20+ struct notifier_block hotcpu_notifier;
21+ int low_watermark;
22+ int high_watermark;
23+ struct timer_list rnd_timer;
24+};
25+#endif /* _NET_FLOWCACHE_H */
include/net/netns/xfrm.h+11−1
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 #include <linux/workqueue.h>
77 #include <linux/xfrm.h>
88 #include <net/dst_ops.h>
9+#include <net/flowcache.h>
910
1011 struct ctl_table_header;
1112
@@ -58,9 +59,18 @@ struct netns_xfrm { · 46 unmodified lines
5859 struct dst_ops xfrm6_dst_ops;
5960 #endif
6061 spinlock_t xfrm_state_lock;
61− spinlock_t xfrm_policy_sk_bundle_lock;
6262 rwlock_t xfrm_policy_lock;
6363 struct mutex xfrm_cfg_mutex;
64+
65+ /* flow cache part */
66+ struct flow_cache flow_cache_global;
67+ struct kmem_cache *flow_cachep;
68+ atomic_t flow_cache_genid;
69+ struct list_head flow_cache_gc_list;
70+ spinlock_t flow_cache_gc_lock;
71+ struct work_struct flow_cache_gc_work;
72+ struct work_struct flow_cache_flush_work;
73+ struct mutex flow_flush_sem;
6474 };
6575
6676 #endif
include/net/xfrm.h+20−5
@@ -118,11 +118,10 @@ · 117 unmodified lines
118118 struct xfrm_state_walk {
119119 struct list_head all;
120120 u8 state;
121− union {
122− u8 dying;
123− u8 proto;
124− };
121+ u8 dying;
122+ u8 proto;
125123 u32 seq;
124+ struct xfrm_filter *filter;
126125 };
127126
128127 /* Full description of state of transformer. */
@@ -594,6 +593,7 @@ struct xfrm_mgr { · 465 unmodified lines
594593 const struct xfrm_migrate *m,
595594 int num_bundles,
596595 const struct xfrm_kmaddress *k);
596+ bool (*is_alive)(const struct km_event *c);
597597 };
598598
599599 int xfrm_register_km(struct xfrm_mgr *km);
@@ -1405,7 +1405,8 @@ static inline void xfrm_sysctl_fini(struct net *net) · 805 unmodified lines
14051405 }
14061406 #endif
14071407
1408−void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
1408+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
1409+ struct xfrm_filter *filter);
14091410 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
14101411 int (*func)(struct xfrm_state *, int, void*), void *);
14111412 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
@@ -1646,6 +1647,20 @@ static inline int xfrm_aevent_is_on(struct net *net) · 234 unmodified lines
16461647 rcu_read_unlock();
16471648 return ret;
16481649 }
1650+
1651+static inline int xfrm_acquire_is_on(struct net *net)
1652+{
1653+ struct sock *nlsk;
1654+ int ret = 0;
1655+
1656+ rcu_read_lock();
1657+ nlsk = rcu_dereference(net->xfrm.nlsk);
1658+ if (nlsk)
1659+ ret = netlink_has_listeners(nlsk, XFRMNLGRP_ACQUIRE);
1660+ rcu_read_unlock();
1661+
1662+ return ret;
1663+}
16491664 #endif
16501665
16511666 static inline int xfrm_alg_len(const struct xfrm_algo *alg)
include/uapi/linux/pfkeyv2.h+14−1
@@ -235,6 +235,18 @@ struct sadb_x_kmaddress { · 234 unmodified lines
235235 } __attribute__((packed));
236236 /* sizeof(struct sadb_x_kmaddress) == 8 */
237237
238+/* To specify the SA dump filter */
239+struct sadb_x_filter {
240+ __u16 sadb_x_filter_len;
241+ __u16 sadb_x_filter_exttype;
242+ __u32 sadb_x_filter_saddr[4];
243+ __u32 sadb_x_filter_daddr[4];
244+ __u16 sadb_x_filter_family;
245+ __u8 sadb_x_filter_splen;
246+ __u8 sadb_x_filter_dplen;
247+} __attribute__((packed));
248+/* sizeof(struct sadb_x_filter) == 40 */
249+
238250 /* Message types */
239251 #define SADB_RESERVED 0
240252 #define SADB_GETSPI 1
@@ -358,7 +370,8 @@ struct sadb_x_kmaddress { · 117 unmodified lines
358370 #define SADB_X_EXT_SEC_CTX 24
359371 /* Used with MIGRATE to pass @ to IKE for negotiation */
360372 #define SADB_X_EXT_KMADDRESS 25
361−#define SADB_EXT_MAX 25
373+#define SADB_X_EXT_FILTER 26
374+#define SADB_EXT_MAX 26
362375
363376 /* Identity Extension values */
364377 #define SADB_IDENTTYPE_RESERVED 0
include/uapi/linux/xfrm.h+10−0
@@ -298,6 +298,8 @@ enum xfrm_attr_type_t { · 297 unmodified lines
298298 XFRMA_TFCPAD, /* __u32 */
299299 XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */
300300 XFRMA_SA_EXTRA_FLAGS, /* __u32 */
301+ XFRMA_PROTO, /* __u8 */
302+ XFRMA_FILTER, /* struct xfrm_filter */
301303 __XFRMA_MAX
302304
303305 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -474,6 +476,14 @@ struct xfrm_user_mapping { · 170 unmodified lines
474476 __be16 new_sport;
475477 };
476478
479+struct xfrm_filter {
480+ xfrm_address_t saddr;
481+ xfrm_address_t daddr;
482+ __u16 family;
483+ __u8 splen;
484+ __u8 dplen;
485+};
486+
477487 #ifndef __KERNEL__
478488 /* backwards compatibility for userspace */
479489 #define XFRMGRP_ACQUIRE 1
net/core/flow.c+57−70
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424 #include <net/flow.h>
2525 #include <linux/atomic.h>
2626 #include <linux/security.h>
27+#include <net/net_namespace.h>
2728
2829 struct flow_cache_entry {
2930 union {
@@ -38,37 +39,12 @@ struct flow_cache_entry { · 8 unmodified lines
3839 struct flow_cache_object *object;
3940 };
4041
41−struct flow_cache_percpu {
42− struct hlist_head *hash_table;
43− int hash_count;
44− u32 hash_rnd;
45− int hash_rnd_recalc;
46− struct tasklet_struct flush_tasklet;
47−};
48−
4942 struct flow_flush_info {
5043 struct flow_cache *cache;
5144 atomic_t cpuleft;
5245 struct completion completion;
5346 };
5447
55−struct flow_cache {
56− u32 hash_shift;
57− struct flow_cache_percpu __percpu *percpu;
58− struct notifier_block hotcpu_notifier;
59− int low_watermark;
60− int high_watermark;
61− struct timer_list rnd_timer;
62−};
63−
64−atomic_t flow_cache_genid = ATOMIC_INIT(0);
65−EXPORT_SYMBOL(flow_cache_genid);
66−static struct flow_cache flow_cache_global;
67−static struct kmem_cache *flow_cachep __read_mostly;
68−
69−static DEFINE_SPINLOCK(flow_cache_gc_lock);
70−static LIST_HEAD(flow_cache_gc_list);
71−
7248 #define flow_cache_hash_size(cache) (1 << (cache)->hash_shift)
7349 #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ)
7450
@@ -84,46 +60,50 @@ static void flow_cache_new_hashrnd(unsigned long arg) · 9 unmodified lines
8460 add_timer(&fc->rnd_timer);
8561 }
8662
87−static int flow_entry_valid(struct flow_cache_entry *fle)
63+static int flow_entry_valid(struct flow_cache_entry *fle,
64+ struct netns_xfrm *xfrm)
8865 {
89− if (atomic_read(&flow_cache_genid) != fle->genid)
66+ if (atomic_read(&xfrm->flow_cache_genid) != fle->genid)
9067 return 0;
9168 if (fle->object && !fle->object->ops->check(fle->object))
9269 return 0;
9370 return 1;
9471 }
9572
96−static void flow_entry_kill(struct flow_cache_entry *fle)
73+static void flow_entry_kill(struct flow_cache_entry *fle,
74+ struct netns_xfrm *xfrm)
9775 {
9876 if (fle->object)
9977 fle->object->ops->delete(fle->object);
100− kmem_cache_free(flow_cachep, fle);
78+ kmem_cache_free(xfrm->flow_cachep, fle);
10179 }
10280
10381 static void flow_cache_gc_task(struct work_struct *work)
10482 {
10583 struct list_head gc_list;
10684 struct flow_cache_entry *fce, *n;
85+ struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm,
86+ flow_cache_gc_work);
10787
10888 INIT_LIST_HEAD(&gc_list);
109− spin_lock_bh(&flow_cache_gc_lock);
110− list_splice_tail_init(&flow_cache_gc_list, &gc_list);
111− spin_unlock_bh(&flow_cache_gc_lock);
89+ spin_lock_bh(&xfrm->flow_cache_gc_lock);
90+ list_splice_tail_init(&xfrm->flow_cache_gc_list, &gc_list);
91+ spin_unlock_bh(&xfrm->flow_cache_gc_lock);
11292
11393 list_for_each_entry_safe(fce, n, &gc_list, u.gc_list)
114− flow_entry_kill(fce);
94+ flow_entry_kill(fce, xfrm);
11595 }
116−static DECLARE_WORK(flow_cache_gc_work, flow_cache_gc_task);
11796
11897 static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp,
119− int deleted, struct list_head *gc_list)
98+ int deleted, struct list_head *gc_list,
99+ struct netns_xfrm *xfrm)
120100 {
121101 if (deleted) {
122102 fcp->hash_count -= deleted;
123− spin_lock_bh(&flow_cache_gc_lock);
124− list_splice_tail(gc_list, &flow_cache_gc_list);
125− spin_unlock_bh(&flow_cache_gc_lock);
126− schedule_work(&flow_cache_gc_work);
103+ spin_lock_bh(&xfrm->flow_cache_gc_lock);
104+ list_splice_tail(gc_list, &xfrm->flow_cache_gc_list);
105+ spin_unlock_bh(&xfrm->flow_cache_gc_lock);
106+ schedule_work(&xfrm->flow_cache_gc_work);
127107 }
128108 }
129109
@@ -135,6 +115,8 @@ static void __flow_cache_shrink(struct flow_cache *fc, · 5 unmodified lines
135115 struct hlist_node *tmp;
136116 LIST_HEAD(gc_list);
137117 int i, deleted = 0;
118+ struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm,
119+ flow_cache_global);
138120
139121 for (i = 0; i < flow_cache_hash_size(fc); i++) {
140122 int saved = 0;
@@ -142,7 +124,7 @@ static void __flow_cache_shrink(struct flow_cache *fc, · 1 unmodified line
142124 hlist_for_each_entry_safe(fle, tmp,
143125 &fcp->hash_table[i], u.hlist) {
144126 if (saved < shrink_to &&
145− flow_entry_valid(fle)) {
127+ flow_entry_valid(fle, xfrm)) {
146128 saved++;
147129 } else {
148130 deleted++;
@@ -152,7 +134,7 @@ static void __flow_cache_shrink(struct flow_cache *fc, · 3 unmodified lines
152134 }
153135 }
154136
155− flow_cache_queue_garbage(fcp, deleted, &gc_list);
137+ flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm);
156138 }
157139
158140 static void flow_cache_shrink(struct flow_cache *fc,
@@ -208,7 +190,7 @@ struct flow_cache_object * · 49 unmodified lines
208190 flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
209191 flow_resolve_t resolver, void *ctx)
210192 {
211− struct flow_cache *fc = &flow_cache_global;
193+ struct flow_cache *fc = &net->xfrm.flow_cache_global;
212194 struct flow_cache_percpu *fcp;
213195 struct flow_cache_entry *fle, *tfle;
214196 struct flow_cache_object *flo;
@@ -248,7 +230,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, · 33 unmodified lines
248230 if (fcp->hash_count > fc->high_watermark)
249231 flow_cache_shrink(fc, fcp);
250232
251− fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
233+ fle = kmem_cache_alloc(net->xfrm.flow_cachep, GFP_ATOMIC);
252234 if (fle) {
253235 fle->net = net;
254236 fle->family = family;
@@ -258,7 +240,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, · 3 unmodified lines
258240 hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
259241 fcp->hash_count++;
260242 }
261− } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) {
243+ } else if (likely(fle->genid == atomic_read(&net->xfrm.flow_cache_genid))) {
262244 flo = fle->object;
263245 if (!flo)
264246 goto ret_object;
@@ -279,7 +261,7 @@ nocache: · 14 unmodified lines
279261 }
280262 flo = resolver(net, key, family, dir, flo, ctx);
281263 if (fle) {
282− fle->genid = atomic_read(&flow_cache_genid);
264+ fle->genid = atomic_read(&net->xfrm.flow_cache_genid);
283265 if (!IS_ERR(flo))
284266 fle->object = flo;
285267 else
@@ -303,12 +285,14 @@ static void flow_cache_flush_tasklet(unsigned long data) · 17 unmodified lines
303285 struct hlist_node *tmp;
304286 LIST_HEAD(gc_list);
305287 int i, deleted = 0;
288+ struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm,
289+ flow_cache_global);
306290
307291 fcp = this_cpu_ptr(fc->percpu);
308292 for (i = 0; i < flow_cache_hash_size(fc); i++) {
309293 hlist_for_each_entry_safe(fle, tmp,
310294 &fcp->hash_table[i], u.hlist) {
311− if (flow_entry_valid(fle))
295+ if (flow_entry_valid(fle, xfrm))
312296 continue;
313297
314298 deleted++;
@@ -317,7 +301,7 @@ static void flow_cache_flush_tasklet(unsigned long data) · 2 unmodified lines
317301 }
318302 }
319303
320− flow_cache_queue_garbage(fcp, deleted, &gc_list);
304+ flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm);
321305
322306 if (atomic_dec_and_test(&info->cpuleft))
323307 complete(&info->completion);
@@ -351,10 +335,9 @@ static void flow_cache_flush_per_cpu(void *data) · 27 unmodified lines
351335 tasklet_schedule(tasklet);
352336 }
353337
354−void flow_cache_flush(void)
338+void flow_cache_flush(struct net *net)
355339 {
356340 struct flow_flush_info info;
357− static DEFINE_MUTEX(flow_flush_sem);
358341 cpumask_var_t mask;
359342 int i, self;
360343
@@ -365,8 +348,8 @@ void flow_cache_flush(void) · 4 unmodified lines
365348
366349 /* Don't want cpus going down or up during this. */
367350 get_online_cpus();
368− mutex_lock(&flow_flush_sem);
369− info.cache = &flow_cache_global;
351+ mutex_lock(&net->xfrm.flow_flush_sem);
352+ info.cache = &net->xfrm.flow_cache_global;
370353 for_each_online_cpu(i)
371354 if (!flow_cache_percpu_empty(info.cache, i))
372355 cpumask_set_cpu(i, mask);
@@ -386,21 +369,23 @@ void flow_cache_flush(void) · 13 unmodified lines
386369 wait_for_completion(&info.completion);
387370
388371 done:
389− mutex_unlock(&flow_flush_sem);
372+ mutex_unlock(&net->xfrm.flow_flush_sem);
390373 put_online_cpus();
391374 free_cpumask_var(mask);
392375 }
393376
394377 static void flow_cache_flush_task(struct work_struct *work)
395378 {
396− flow_cache_flush();
397−}
379+ struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm,
380+ flow_cache_gc_work);
381+ struct net *net = container_of(xfrm, struct net, xfrm);
398382
399−static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task);
383+ flow_cache_flush(net);
384+}
400385
401−void flow_cache_flush_deferred(void)
386+void flow_cache_flush_deferred(struct net *net)
402387 {
403− schedule_work(&flow_cache_flush_work);
388+ schedule_work(&net->xfrm.flow_cache_flush_work);
404389 }
405390
406391 static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu)
@@ -425,7 +410,8 @@ static int flow_cache_cpu(struct notifier_block *nfb, · 18 unmodified lines
425410 unsigned long action,
426411 void *hcpu)
427412 {
428− struct flow_cache *fc = container_of(nfb, struct flow_cache, hotcpu_notifier);
413+ struct flow_cache *fc = container_of(nfb, struct flow_cache,
414+ hotcpu_notifier);
429415 int res, cpu = (unsigned long) hcpu;
430416 struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu);
431417
@@ -444,9 +430,20 @@ static int flow_cache_cpu(struct notifier_block *nfb, · 12 unmodified lines
444430 return NOTIFY_OK;
445431 }
446432
447−static int __init flow_cache_init(struct flow_cache *fc)
433+int flow_cache_init(struct net *net)
448434 {
449435 int i;
436+ struct flow_cache *fc = &net->xfrm.flow_cache_global;
437+
438+ /* Initialize per-net flow cache global variables here */
439+ net->xfrm.flow_cachep = kmem_cache_create("flow_cache",
440+ sizeof(struct flow_cache_entry),
441+ 0, SLAB_PANIC, NULL);
442+ spin_lock_init(&net->xfrm.flow_cache_gc_lock);
443+ INIT_LIST_HEAD(&net->xfrm.flow_cache_gc_list);
444+ INIT_WORK(&net->xfrm.flow_cache_gc_work, flow_cache_gc_task);
445+ INIT_WORK(&net->xfrm.flow_cache_flush_work, flow_cache_flush_task);
446+ mutex_init(&net->xfrm.flow_flush_sem);
450447
451448 fc->hash_shift = 10;
452449 fc->low_watermark = 2 * flow_cache_hash_size(fc);
@@ -484,14 +481,4 @@ err: · 31 unmodified lines
484481
485482 return -ENOMEM;
486483 }
487−
488−static int __init flow_cache_init_global(void)
489−{
490− flow_cachep = kmem_cache_create("flow_cache",
491− sizeof(struct flow_cache_entry),
492− 0, SLAB_PANIC, NULL);
493−
494− return flow_cache_init(&flow_cache_global);
495−}
496−
497−module_init(flow_cache_init_global);
484+EXPORT_SYMBOL(flow_cache_init);
net/core/skbuff.c+26−0
@@ -3281,6 +3281,32 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) · 3280 unmodified lines
32813281 return elt;
32823282 }
32833283
3284+/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given
3285+ * sglist without mark the sg which contain last skb data as the end.
3286+ * So the caller can mannipulate sg list as will when padding new data after
3287+ * the first call without calling sg_unmark_end to expend sg list.
3288+ *
3289+ * Scenario to use skb_to_sgvec_nomark:
3290+ * 1. sg_init_table
3291+ * 2. skb_to_sgvec_nomark(payload1)
3292+ * 3. skb_to_sgvec_nomark(payload2)
3293+ *
3294+ * This is equivalent to:
3295+ * 1. sg_init_table
3296+ * 2. skb_to_sgvec(payload1)
3297+ * 3. sg_unmark_end
3298+ * 4. skb_to_sgvec(payload2)
3299+ *
3300+ * When mapping mutilple payload conditionally, skb_to_sgvec_nomark
3301+ * is more preferable.
3302+ */
3303+int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
3304+ int offset, int len)
3305+{
3306+ return __skb_to_sgvec(skb, sg, offset, len);
3307+}
3308+EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark);
3309+
32843310 int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
32853311 {
32863312 int nsg = __skb_to_sgvec(skb, sg, offset, len);
net/ipv4/ah4.c+42−11
@@ -155,6 +155,10 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) · 154 unmodified lines
155155 struct iphdr *iph, *top_iph;
156156 struct ip_auth_hdr *ah;
157157 struct ah_data *ahp;
158+ int seqhi_len = 0;
159+ __be32 *seqhi;
160+ int sglists = 0;
161+ struct scatterlist *seqhisg;
158162
159163 ahp = x->data;
160164 ahash = ahp->ahash;
@@ -167,14 +171,19 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) · 6 unmodified lines
167171 ah = ip_auth_hdr(skb);
168172 ihl = ip_hdrlen(skb);
169173
174+ if (x->props.flags & XFRM_STATE_ESN) {
175+ sglists = 1;
176+ seqhi_len = sizeof(*seqhi);
177+ }
170178 err = -ENOMEM;
171− iph = ah_alloc_tmp(ahash, nfrags, ihl);
179+ iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + seqhi_len);
172180 if (!iph)
173181 goto out;
174−
175− icv = ah_tmp_icv(ahash, iph, ihl);
182+ seqhi = (__be32 *)((char *)iph + ihl);
183+ icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
176184 req = ah_tmp_req(ahash, icv);
177185 sg = ah_req_sg(ahash, req);
186+ seqhisg = sg + nfrags;
178187
179188 memset(ah->auth_data, 0, ahp->icv_trunc_len);
180189
@@ -210,10 +219,15 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) · 29 unmodified lines
210219 ah->spi = x->id.spi;
211220 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
212221
213− sg_init_table(sg, nfrags);
214− skb_to_sgvec(skb, sg, 0, skb->len);
222+ sg_init_table(sg, nfrags + sglists);
223+ skb_to_sgvec_nomark(skb, sg, 0, skb->len);
215224
216− ahash_request_set_crypt(req, sg, icv, skb->len);
225+ if (x->props.flags & XFRM_STATE_ESN) {
226+ /* Attach seqhi sg right after packet payload */
227+ *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
228+ sg_set_buf(seqhisg, seqhi, seqhi_len);
229+ }
230+ ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
217231 ahash_request_set_callback(req, 0, ah_output_done, skb);
218232
219233 AH_SKB_CB(skb)->tmp = iph;
@@ -295,6 +309,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) · 75 unmodified lines
295309 struct ip_auth_hdr *ah;
296310 struct ah_data *ahp;
297311 int err = -ENOMEM;
312+ int seqhi_len = 0;
313+ __be32 *seqhi;
314+ int sglists = 0;
315+ struct scatterlist *seqhisg;
298316
299317 if (!pskb_may_pull(skb, sizeof(*ah)))
300318 goto out;
@@ -335,14 +353,22 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) · 34 unmodified lines
335353 iph = ip_hdr(skb);
336354 ihl = ip_hdrlen(skb);
337355
338− work_iph = ah_alloc_tmp(ahash, nfrags, ihl + ahp->icv_trunc_len);
356+ if (x->props.flags & XFRM_STATE_ESN) {
357+ sglists = 1;
358+ seqhi_len = sizeof(*seqhi);
359+ }
360+
361+ work_iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl +
362+ ahp->icv_trunc_len + seqhi_len);
339363 if (!work_iph)
340364 goto out;
341365
342− auth_data = ah_tmp_auth(work_iph, ihl);
366+ seqhi = (__be32 *)((char *)work_iph + ihl);
367+ auth_data = ah_tmp_auth(seqhi, seqhi_len);
343368 icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
344369 req = ah_tmp_req(ahash, icv);
345370 sg = ah_req_sg(ahash, req);
371+ seqhisg = sg + nfrags;
346372
347373 memcpy(work_iph, iph, ihl);
348374 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -361,10 +387,15 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) · 12 unmodified lines
361387
362388 skb_push(skb, ihl);
363389
364− sg_init_table(sg, nfrags);
365− skb_to_sgvec(skb, sg, 0, skb->len);
390+ sg_init_table(sg, nfrags + sglists);
391+ skb_to_sgvec_nomark(skb, sg, 0, skb->len);
366392
367− ahash_request_set_crypt(req, sg, icv, skb->len);
393+ if (x->props.flags & XFRM_STATE_ESN) {
394+ /* Attach seqhi sg right after packet payload */
395+ *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
396+ sg_set_buf(seqhisg, seqhi, seqhi_len);
397+ }
398+ ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
368399 ahash_request_set_callback(req, 0, ah_input_done, skb);
369400
370401 AH_SKB_CB(skb)->tmp = work_iph;
net/ipv6/ah6.c+45−11
@@ -346,6 +346,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) · 345 unmodified lines
346346 struct ip_auth_hdr *ah;
347347 struct ah_data *ahp;
348348 struct tmp_ext *iph_ext;
349+ int seqhi_len = 0;
350+ __be32 *seqhi;
351+ int sglists = 0;
352+ struct scatterlist *seqhisg;
349353
350354 ahp = x->data;
351355 ahash = ahp->ahash;
@@ -359,15 +363,22 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) · 7 unmodified lines
359363 if (extlen)
360364 extlen += sizeof(*iph_ext);
361365
366+ if (x->props.flags & XFRM_STATE_ESN) {
367+ sglists = 1;
368+ seqhi_len = sizeof(*seqhi);
369+ }
362370 err = -ENOMEM;
363− iph_base = ah_alloc_tmp(ahash, nfrags, IPV6HDR_BASELEN + extlen);
371+ iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN +
372+ extlen + seqhi_len);
364373 if (!iph_base)
365374 goto out;
366375
367376 iph_ext = ah_tmp_ext(iph_base);
368− icv = ah_tmp_icv(ahash, iph_ext, extlen);
377+ seqhi = (__be32 *)((char *)iph_ext + extlen);
378+ icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
369379 req = ah_tmp_req(ahash, icv);
370380 sg = ah_req_sg(ahash, req);
381+ seqhisg = sg + nfrags;
371382
372383 ah = ip_auth_hdr(skb);
373384 memset(ah->auth_data, 0, ahp->icv_trunc_len);
@@ -411,10 +422,15 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) · 37 unmodified lines
411422 ah->spi = x->id.spi;
412423 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
413424
414− sg_init_table(sg, nfrags);
415− skb_to_sgvec(skb, sg, 0, skb->len);
425+ sg_init_table(sg, nfrags + sglists);
426+ skb_to_sgvec_nomark(skb, sg, 0, skb->len);
416427
417− ahash_request_set_crypt(req, sg, icv, skb->len);
428+ if (x->props.flags & XFRM_STATE_ESN) {
429+ /* Attach seqhi sg right after packet payload */
430+ *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
431+ sg_set_buf(seqhisg, seqhi, seqhi_len);
432+ }
433+ ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
418434 ahash_request_set_callback(req, 0, ah6_output_done, skb);
419435
420436 AH_SKB_CB(skb)->tmp = iph_base;
@@ -514,6 +530,10 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) · 93 unmodified lines
514530 int nexthdr;
515531 int nfrags;
516532 int err = -ENOMEM;
533+ int seqhi_len = 0;
534+ __be32 *seqhi;
535+ int sglists = 0;
536+ struct scatterlist *seqhisg;
517537
518538 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
519539 goto out;
@@ -550,14 +570,22 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) · 30 unmodified lines
550570
551571 skb_push(skb, hdr_len);
552572
553− work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->icv_trunc_len);
573+ if (x->props.flags & XFRM_STATE_ESN) {
574+ sglists = 1;
575+ seqhi_len = sizeof(*seqhi);
576+ }
577+
578+ work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len +
579+ ahp->icv_trunc_len + seqhi_len);
554580 if (!work_iph)
555581 goto out;
556582
557− auth_data = ah_tmp_auth(work_iph, hdr_len);
558− icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
583+ auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len);
584+ seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len);
585+ icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
559586 req = ah_tmp_req(ahash, icv);
560587 sg = ah_req_sg(ahash, req);
588+ seqhisg = sg + nfrags;
561589
562590 memcpy(work_iph, ip6h, hdr_len);
563591 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -572,10 +600,16 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) · 8 unmodified lines
572600 ip6h->flow_lbl[2] = 0;
573601 ip6h->hop_limit = 0;
574602
575− sg_init_table(sg, nfrags);
576− skb_to_sgvec(skb, sg, 0, skb->len);
603+ sg_init_table(sg, nfrags + sglists);
604+ skb_to_sgvec_nomark(skb, sg, 0, skb->len);
605+
606+ if (x->props.flags & XFRM_STATE_ESN) {
607+ /* Attach seqhi sg right after packet payload */
608+ *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
609+ sg_set_buf(seqhisg, seqhi, seqhi_len);
610+ }
577611
578− ahash_request_set_crypt(req, sg, icv, skb->len);
612+ ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
579613 ahash_request_set_callback(req, 0, ah6_input_done, skb);
580614
581615 AH_SKB_CB(skb)->tmp = work_iph;
net/key/af_key.c+38−1
@@ -365,6 +365,7 @@ static const u8 sadb_ext_min_len[] = { · 364 unmodified lines
365365 [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address),
366366 [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx),
367367 [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress),
368+ [SADB_X_EXT_FILTER] = (u8) sizeof(struct sadb_x_filter),
368369 };
369370
370371 /* Verify sadb_address_{len,prefixlen} against sa_family. */
@@ -1798,6 +1799,7 @@ static void pfkey_dump_sa_done(struct pfkey_sock *pfk) · 1427 unmodified lines
17981799 static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
17991800 {
18001801 u8 proto;
1802+ struct xfrm_filter *filter = NULL;
18011803 struct pfkey_sock *pfk = pfkey_sk(sk);
18021804
18031805 if (pfk->dump.dump != NULL)
@@ -1807,11 +1809,27 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms · 3 unmodified lines
18071809 if (proto == 0)
18081810 return -EINVAL;
18091811
1812+ if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
1813+ struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
1814+
1815+ filter = kmalloc(sizeof(*filter), GFP_KERNEL);
1816+ if (filter == NULL)
1817+ return -ENOMEM;
1818+
1819+ memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr,
1820+ sizeof(xfrm_address_t));
1821+ memcpy(&filter->daddr, &xfilter->sadb_x_filter_daddr,
1822+ sizeof(xfrm_address_t));
1823+ filter->family = xfilter->sadb_x_filter_family;
1824+ filter->splen = xfilter->sadb_x_filter_splen;
1825+ filter->dplen = xfilter->sadb_x_filter_dplen;
1826+ }
1827+
18101828 pfk->dump.msg_version = hdr->sadb_msg_version;
18111829 pfk->dump.msg_portid = hdr->sadb_msg_pid;
18121830 pfk->dump.dump = pfkey_dump_sa;
18131831 pfk->dump.done = pfkey_dump_sa_done;
1814− xfrm_state_walk_init(&pfk->dump.u.state, proto);
1832+ xfrm_state_walk_init(&pfk->dump.u.state, proto, filter);
18151833
18161834 return pfkey_do_dump(pfk);
18171835 }
@@ -3059,6 +3077,24 @@ static u32 get_acqseq(void) · 1241 unmodified lines
30593077 return res;
30603078 }
30613079
3080+static bool pfkey_is_alive(const struct km_event *c)
3081+{
3082+ struct netns_pfkey *net_pfkey = net_generic(c->net, pfkey_net_id);
3083+ struct sock *sk;
3084+ bool is_alive = false;
3085+
3086+ rcu_read_lock();
3087+ sk_for_each_rcu(sk, &net_pfkey->table) {
3088+ if (pfkey_sk(sk)->registered) {
3089+ is_alive = true;
3090+ break;
3091+ }
3092+ }
3093+ rcu_read_unlock();
3094+
3095+ return is_alive;
3096+}
3097+
30623098 static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp)
30633099 {
30643100 struct sk_buff *skb;
@@ -3784,6 +3820,7 @@ static struct xfrm_mgr pfkeyv2_mgr = · 719 unmodified lines
37843820 .new_mapping = pfkey_send_new_mapping,
37853821 .notify_policy = pfkey_send_policy_notify,
37863822 .migrate = pfkey_send_migrate,
3823+ .is_alive = pfkey_is_alive,
37873824 };
37883825
37893826 static int __net_init pfkey_net_init(struct net *net)
net/xfrm/xfrm_policy.c+4−31
@@ -39,8 +39,6 @@ · 38 unmodified lines
3939 #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
4040 #define XFRM_MAX_QUEUE_LEN 100
4141
42−static struct dst_entry *xfrm_policy_sk_bundles;
43−
4442 static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
4543 static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
4644 __read_mostly;
@@ -661,7 +659,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) · 614 unmodified lines
661659 hlist_add_head(&policy->bydst, chain);
662660 xfrm_pol_hold(policy);
663661 net->xfrm.policy_count[dir]++;
664− atomic_inc(&flow_cache_genid);
662+ atomic_inc(&net->xfrm.flow_cache_genid);
665663
666664 /* After previous checking, family can either be AF_INET or AF_INET6 */
667665 if (policy->family == AF_INET)
@@ -2109,13 +2107,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, · 1441 unmodified lines
21092107 goto no_transform;
21102108 }
21112109
2112− dst_hold(&xdst->u.dst);
2113−
2114− spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
2115− xdst->u.dst.next = xfrm_policy_sk_bundles;
2116− xfrm_policy_sk_bundles = &xdst->u.dst;
2117− spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
2118−
21192110 route = xdst->route;
21202111 }
21212112 }
@@ -2549,33 +2540,15 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) · 427 unmodified lines
25492540 return dst;
25502541 }
25512542
2552−static void __xfrm_garbage_collect(struct net *net)
2553−{
2554− struct dst_entry *head, *next;
2555−
2556− spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
2557− head = xfrm_policy_sk_bundles;
2558− xfrm_policy_sk_bundles = NULL;
2559− spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
2560−
2561− while (head) {
2562− next = head->next;
2563− dst_free(head);
2564− head = next;
2565− }
2566−}
2567−
25682543 void xfrm_garbage_collect(struct net *net)
25692544 {
2570− flow_cache_flush();
2571− __xfrm_garbage_collect(net);
2545+ flow_cache_flush(net);
25722546 }
25732547 EXPORT_SYMBOL(xfrm_garbage_collect);
25742548
25752549 static void xfrm_garbage_collect_deferred(struct net *net)
25762550 {
2577− flow_cache_flush_deferred();
2578− __xfrm_garbage_collect(net);
2551+ flow_cache_flush_deferred(net);
25792552 }
25802553
25812554 static void xfrm_init_pmtu(struct dst_entry *dst)
@@ -2944,9 +2917,9 @@ static int __net_init xfrm_net_init(struct net *net) · 362 unmodified lines
29442917 /* Initialize the per-net locks here */
29452918 spin_lock_init(&net->xfrm.xfrm_state_lock);
29462919 rwlock_init(&net->xfrm.xfrm_policy_lock);
2947− spin_lock_init(&net->xfrm.xfrm_policy_sk_bundle_lock);
29482920 mutex_init(&net->xfrm.xfrm_cfg_mutex);
29492921
2922+ flow_cache_init(net);
29502923 return 0;
29512924
29522925 out_sysctl:
net/xfrm/xfrm_state.c+60−12
@@ -161,6 +161,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock); · 160 unmodified lines
161161 int __xfrm_state_delete(struct xfrm_state *x);
162162
163163 int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
164+bool km_is_alive(const struct km_event *c);
164165 void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
165166
166167 static DEFINE_SPINLOCK(xfrm_type_lock);
@@ -788,6 +789,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, · 621 unmodified lines
788789 struct xfrm_state *best = NULL;
789790 u32 mark = pol->mark.v & pol->mark.m;
790791 unsigned short encap_family = tmpl->encap_family;
792+ struct km_event c;
791793
792794 to_put = NULL;
793795
@@ -832,6 +834,17 @@ found: · 38 unmodified lines
832834 error = -EEXIST;
833835 goto out;
834836 }
837+
838+ c.net = net;
839+ /* If the KMs have no listeners (yet...), avoid allocating an SA
840+ * for each and every packet - garbage collection might not
841+ * handle the flood.
842+ */
843+ if (!km_is_alive(&c)) {
844+ error = -ESRCH;
845+ goto out;
846+ }
847+
835848 x = xfrm_state_alloc(net);
836849 if (x == NULL) {
837850 error = -ENOMEM;
@@ -1135,10 +1148,9 @@ out: · 297 unmodified lines
11351148 EXPORT_SYMBOL(xfrm_state_add);
11361149
11371150 #ifdef CONFIG_XFRM_MIGRATE
1138−static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1151+static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
11391152 {
11401153 struct net *net = xs_net(orig);
1141− int err = -ENOMEM;
11421154 struct xfrm_state *x = xfrm_state_alloc(net);
11431155 if (!x)
11441156 goto out;
@@ -1187,15 +1199,13 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) · 42 unmodified lines
11871199 }
11881200
11891201 if (orig->replay_esn) {
1190− err = xfrm_replay_clone(x, orig);
1191− if (err)
1202+ if (xfrm_replay_clone(x, orig))
11921203 goto error;
11931204 }
11941205
11951206 memcpy(&x->mark, &orig->mark, sizeof(x->mark));
11961207
1197− err = xfrm_init_state(x);
1198− if (err)
1208+ if (xfrm_init_state(x) < 0)
11991209 goto error;
12001210
12011211 x->props.flags = orig->props.flags;
@@ -1210,8 +1220,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) · 8 unmodified lines
12101220 error:
12111221 xfrm_state_put(x);
12121222 out:
1213− if (errp)
1214− *errp = err;
12151223 return NULL;
12161224 }
12171225
@@ -1263,9 +1271,8 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, · 45 unmodified lines
12631271 struct xfrm_migrate *m)
12641272 {
12651273 struct xfrm_state *xc;
1266− int err;
12671274
1268− xc = xfrm_state_clone(x, &err);
1275+ xc = xfrm_state_clone(x);
12691276 if (!xc)
12701277 return NULL;
12711278
@@ -1278,7 +1285,7 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, · 6 unmodified lines
12781285 state is to be updated as it is a part of triplet */
12791286 xfrm_state_insert(xc);
12801287 } else {
1281− if ((err = xfrm_state_add(xc)) < 0)
1288+ if (xfrm_state_add(xc) < 0)
12821289 goto error;
12831290 }
12841291
@@ -1590,6 +1597,23 @@ unlock: · 305 unmodified lines
15901597 }
15911598 EXPORT_SYMBOL(xfrm_alloc_spi);
15921599
1600+static bool __xfrm_state_filter_match(struct xfrm_state *x,
1601+ struct xfrm_filter *filter)
1602+{
1603+ if (filter) {
1604+ if ((filter->family == AF_INET ||
1605+ filter->family == AF_INET6) &&
1606+ x->props.family != filter->family)
1607+ return false;
1608+
1609+ return addr_match(&x->props.saddr, &filter->saddr,
1610+ filter->splen) &&
1611+ addr_match(&x->id.daddr, &filter->daddr,
1612+ filter->dplen);
1613+ }
1614+ return true;
1615+}
1616+
15931617 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
15941618 int (*func)(struct xfrm_state *, int, void*),
15951619 void *data)
@@ -1612,6 +1636,8 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, · 16 unmodified lines
16121636 state = container_of(x, struct xfrm_state, km);
16131637 if (!xfrm_id_proto_match(state->id.proto, walk->proto))
16141638 continue;
1639+ if (!__xfrm_state_filter_match(state, walk->filter))
1640+ continue;
16151641 err = func(state, walk->seq, data);
16161642 if (err) {
16171643 list_move_tail(&walk->all, &x->all);
@@ -1630,17 +1656,21 @@ out: · 12 unmodified lines
16301656 }
16311657 EXPORT_SYMBOL(xfrm_state_walk);
16321658
1633−void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
1659+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
1660+ struct xfrm_filter *filter)
16341661 {
16351662 INIT_LIST_HEAD(&walk->all);
16361663 walk->proto = proto;
16371664 walk->state = XFRM_STATE_DEAD;
16381665 walk->seq = 0;
1666+ walk->filter = filter;
16391667 }
16401668 EXPORT_SYMBOL(xfrm_state_walk_init);
16411669
16421670 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net)
16431671 {
1672+ kfree(walk->filter);
1673+
16441674 if (list_empty(&walk->all))
16451675 return;
16461676
@@ -1793,6 +1823,24 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address · 146 unmodified lines
17931823 }
17941824 EXPORT_SYMBOL(km_report);
17951825
1826+bool km_is_alive(const struct km_event *c)
1827+{
1828+ struct xfrm_mgr *km;
1829+ bool is_alive = false;
1830+
1831+ rcu_read_lock();
1832+ list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1833+ if (km->is_alive && km->is_alive(c)) {
1834+ is_alive = true;
1835+ break;
1836+ }
1837+ }
1838+ rcu_read_unlock();
1839+
1840+ return is_alive;
1841+}
1842+EXPORT_SYMBOL(km_is_alive);
1843+
17961844 int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
17971845 {
17981846 int err;
net/xfrm/xfrm_user.c+35−2
@@ -142,7 +142,8 @@ static inline int verify_replay(struct xfrm_usersa_info *p, · 141 unmodified lines
142142 if (!rt)
143143 return 0;
144144
145− if (p->id.proto != IPPROTO_ESP)
145+ /* As only ESP and AH support ESN feature. */
146+ if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH))
146147 return -EINVAL;
147148
148149 if (p->replay_window != 0)
@@ -886,6 +887,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) · 737 unmodified lines
886887 return 0;
887888 }
888889
890+static const struct nla_policy xfrma_policy[XFRMA_MAX+1];
889891 static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
890892 {
891893 struct net *net = sock_net(skb->sk);
@@ -901,8 +903,31 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) · 9 unmodified lines
901903 info.nlmsg_flags = NLM_F_MULTI;
902904
903905 if (!cb->args[0]) {
906+ struct nlattr *attrs[XFRMA_MAX+1];
907+ struct xfrm_filter *filter = NULL;
908+ u8 proto = 0;
909+ int err;
910+
904911 cb->args[0] = 1;
905− xfrm_state_walk_init(walk, 0);
912+
913+ err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX,
914+ xfrma_policy);
915+ if (err < 0)
916+ return err;
917+
918+ if (attrs[XFRMA_FILTER]) {
919+ filter = kmalloc(sizeof(*filter), GFP_KERNEL);
920+ if (filter == NULL)
921+ return -ENOMEM;
922+
923+ memcpy(filter, nla_data(attrs[XFRMA_FILTER]),
924+ sizeof(*filter));
925+ }
926+
927+ if (attrs[XFRMA_PROTO])
928+ proto = nla_get_u8(attrs[XFRMA_PROTO]);
929+
930+ xfrm_state_walk_init(walk, proto, filter);
906931 }
907932
908933 (void) xfrm_state_walk(net, walk, dump_one_state, &info);
@@ -2308,6 +2333,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { · 1399 unmodified lines
23082333 [XFRMA_TFCPAD] = { .type = NLA_U32 },
23092334 [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) },
23102335 [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 },
2336+ [XFRMA_PROTO] = { .type = NLA_U8 },
2337+ [XFRMA_FILTER] = { .len = sizeof(struct xfrm_filter) },
23112338 };
23122339
23132340 static const struct xfrm_link {
@@ -2981,6 +3008,11 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, · 667 unmodified lines
29813008 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
29823009 }
29833010
3011+static bool xfrm_is_alive(const struct km_event *c)
3012+{
3013+ return (bool)xfrm_acquire_is_on(c->net);
3014+}
3015+
29843016 static struct xfrm_mgr netlink_mgr = {
29853017 .id = "netlink",
29863018 .notify = xfrm_send_state_notify,
@@ -2990,6 +3022,7 @@ static struct xfrm_mgr netlink_mgr = { · 3 unmodified lines
29903022 .report = xfrm_send_report,
29913023 .migrate = xfrm_send_migrate,
29923024 .new_mapping = xfrm_send_mapping,
3025+ .is_alive = xfrm_is_alive,
29933026 };
29943027
29953028 static int __net_init xfrm_user_net_init(struct net *net)
security/selinux/include/xfrm.h+3−2
@@ -45,10 +45,11 @@ static inline void selinux_xfrm_notify_policyload(void) · 44 unmodified lines
4545 {
4646 struct net *net;
4747
48− atomic_inc(&flow_cache_genid);
4948 rtnl_lock();
50− for_each_net(net)
49+ for_each_net(net) {
50+ atomic_inc(&net->xfrm.flow_cache_genid);
5151 rt_genid_bump_all(net);
52+ }
5253 rtnl_unlock();
5354 }
5455 #else