aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-21 15:39:35 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-21 15:39:35 -0400
commitf5caadbb3d8fc0b71533e880c684b2230bdb76ac (patch)
tree7a23a2b44f6e043d9cb6ad4245b78da4bd2e14b0
parent0ca87f05ba8bdc6791c14878464efc901ad71e99 (diff)
parent0f598f0b4c3b2259366cfa8adc01bd8e714c82d0 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
-rw-r--r--include/linux/audit.h7
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h108
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h1
-rw-r--r--kernel/audit.c29
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c40
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c6
-rw-r--r--net/netfilter/nfnetlink.c40
-rw-r--r--net/netfilter/nfnetlink_queue.c170
-rw-r--r--net/netfilter/xt_AUDIT.c5
15 files changed, 327 insertions, 112 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9d339eb2788..0c8006129fb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -613,6 +613,12 @@ extern void audit_log_d_path(struct audit_buffer *ab,
613extern void audit_log_key(struct audit_buffer *ab, 613extern void audit_log_key(struct audit_buffer *ab,
614 char *key); 614 char *key);
615extern void audit_log_lost(const char *message); 615extern void audit_log_lost(const char *message);
616#ifdef CONFIG_SECURITY
617extern void audit_log_secctx(struct audit_buffer *ab, u32 secid);
618#else
619#define audit_log_secctx(b,s) do { ; } while (0)
620#endif
621
616extern int audit_update_lsm_rules(void); 622extern int audit_update_lsm_rules(void);
617 623
618 /* Private API (for audit.c only) */ 624 /* Private API (for audit.c only) */
@@ -635,6 +641,7 @@ extern int audit_enabled;
635#define audit_log_untrustedstring(a,s) do { ; } while (0) 641#define audit_log_untrustedstring(a,s) do { ; } while (0)
636#define audit_log_d_path(b, p, d) do { ; } while (0) 642#define audit_log_d_path(b, p, d) do { ; } while (0)
637#define audit_log_key(b, k) do { ; } while (0) 643#define audit_log_key(b, k) do { ; } while (0)
644#define audit_log_secctx(b,s) do { ; } while (0)
638#define audit_enabled 0 645#define audit_enabled 0
639#endif 646#endif
640#endif 647#endif
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index c5b06aaa205..b89fb79cb44 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -28,7 +28,32 @@
28/* Number of elements to store in an initial array block */ 28/* Number of elements to store in an initial array block */
29#define AHASH_INIT_SIZE 4 29#define AHASH_INIT_SIZE 4
30/* Max number of elements to store in an array block */ 30/* Max number of elements to store in an array block */
31#define AHASH_MAX_SIZE (3*4) 31#define AHASH_MAX_SIZE (3*AHASH_INIT_SIZE)
32
33/* Max number of elements can be tuned */
34#ifdef IP_SET_HASH_WITH_MULTI
35#define AHASH_MAX(h) ((h)->ahash_max)
36
37static inline u8
38tune_ahash_max(u8 curr, u32 multi)
39{
40 u32 n;
41
42 if (multi < curr)
43 return curr;
44
45 n = curr + AHASH_INIT_SIZE;
46 /* Currently, at listing one hash bucket must fit into a message.
47 * Therefore we have a hard limit here.
48 */
49 return n > curr && n <= 64 ? n : curr;
50}
51#define TUNE_AHASH_MAX(h, multi) \
52 ((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
53#else
54#define AHASH_MAX(h) AHASH_MAX_SIZE
55#define TUNE_AHASH_MAX(h, multi)
56#endif
32 57
33/* A hash bucket */ 58/* A hash bucket */
34struct hbucket { 59struct hbucket {
@@ -60,6 +85,9 @@ struct ip_set_hash {
60 u32 timeout; /* timeout value, if enabled */ 85 u32 timeout; /* timeout value, if enabled */
61 struct timer_list gc; /* garbage collection when timeout enabled */ 86 struct timer_list gc; /* garbage collection when timeout enabled */
62 struct type_pf_next next; /* temporary storage for uadd */ 87 struct type_pf_next next; /* temporary storage for uadd */
88#ifdef IP_SET_HASH_WITH_MULTI
89 u8 ahash_max; /* max elements in an array block */
90#endif
63#ifdef IP_SET_HASH_WITH_NETMASK 91#ifdef IP_SET_HASH_WITH_NETMASK
64 u8 netmask; /* netmask value for subnets to store */ 92 u8 netmask; /* netmask value for subnets to store */
65#endif 93#endif
@@ -211,12 +239,16 @@ ip_set_hash_destroy(struct ip_set *set)
211 set->data = NULL; 239 set->data = NULL;
212} 240}
213 241
214#define HKEY(data, initval, htable_bits) \
215(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
216 & jhash_mask(htable_bits))
217
218#endif /* _IP_SET_AHASH_H */ 242#endif /* _IP_SET_AHASH_H */
219 243
244#ifndef HKEY_DATALEN
245#define HKEY_DATALEN sizeof(struct type_pf_elem)
246#endif
247
248#define HKEY(data, initval, htable_bits) \
249(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \
250 & jhash_mask(htable_bits))
251
220#define CONCAT(a, b, c) a##b##c 252#define CONCAT(a, b, c) a##b##c
221#define TOKEN(a, b, c) CONCAT(a, b, c) 253#define TOKEN(a, b, c) CONCAT(a, b, c)
222 254
@@ -275,12 +307,13 @@ ip_set_hash_destroy(struct ip_set *set)
275/* Add an element to the hash table when resizing the set: 307/* Add an element to the hash table when resizing the set:
276 * we spare the maintenance of the internal counters. */ 308 * we spare the maintenance of the internal counters. */
277static int 309static int
278type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value) 310type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value,
311 u8 ahash_max)
279{ 312{
280 if (n->pos >= n->size) { 313 if (n->pos >= n->size) {
281 void *tmp; 314 void *tmp;
282 315
283 if (n->size >= AHASH_MAX_SIZE) 316 if (n->size >= ahash_max)
284 /* Trigger rehashing */ 317 /* Trigger rehashing */
285 return -EAGAIN; 318 return -EAGAIN;
286 319
@@ -335,7 +368,7 @@ retry:
335 for (j = 0; j < n->pos; j++) { 368 for (j = 0; j < n->pos; j++) {
336 data = ahash_data(n, j); 369 data = ahash_data(n, j);
337 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 370 m = hbucket(t, HKEY(data, h->initval, htable_bits));
338 ret = type_pf_elem_add(m, data); 371 ret = type_pf_elem_add(m, data, AHASH_MAX(h));
339 if (ret < 0) { 372 if (ret < 0) {
340 read_unlock_bh(&set->lock); 373 read_unlock_bh(&set->lock);
341 ahash_destroy(t); 374 ahash_destroy(t);
@@ -359,7 +392,7 @@ retry:
359 return 0; 392 return 0;
360} 393}
361 394
362static void 395static inline void
363type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d); 396type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
364 397
365/* Add an element to a hash and update the internal counters when succeeded, 398/* Add an element to a hash and update the internal counters when succeeded,
@@ -372,7 +405,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
372 const struct type_pf_elem *d = value; 405 const struct type_pf_elem *d = value;
373 struct hbucket *n; 406 struct hbucket *n;
374 int i, ret = 0; 407 int i, ret = 0;
375 u32 key; 408 u32 key, multi = 0;
376 409
377 if (h->elements >= h->maxelem) 410 if (h->elements >= h->maxelem)
378 return -IPSET_ERR_HASH_FULL; 411 return -IPSET_ERR_HASH_FULL;
@@ -382,12 +415,12 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
382 key = HKEY(value, h->initval, t->htable_bits); 415 key = HKEY(value, h->initval, t->htable_bits);
383 n = hbucket(t, key); 416 n = hbucket(t, key);
384 for (i = 0; i < n->pos; i++) 417 for (i = 0; i < n->pos; i++)
385 if (type_pf_data_equal(ahash_data(n, i), d)) { 418 if (type_pf_data_equal(ahash_data(n, i), d, &multi)) {
386 ret = -IPSET_ERR_EXIST; 419 ret = -IPSET_ERR_EXIST;
387 goto out; 420 goto out;
388 } 421 }
389 422 TUNE_AHASH_MAX(h, multi);
390 ret = type_pf_elem_add(n, value); 423 ret = type_pf_elem_add(n, value, AHASH_MAX(h));
391 if (ret != 0) { 424 if (ret != 0) {
392 if (ret == -EAGAIN) 425 if (ret == -EAGAIN)
393 type_pf_data_next(h, d); 426 type_pf_data_next(h, d);
@@ -415,13 +448,13 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
415 struct hbucket *n; 448 struct hbucket *n;
416 int i; 449 int i;
417 struct type_pf_elem *data; 450 struct type_pf_elem *data;
418 u32 key; 451 u32 key, multi = 0;
419 452
420 key = HKEY(value, h->initval, t->htable_bits); 453 key = HKEY(value, h->initval, t->htable_bits);
421 n = hbucket(t, key); 454 n = hbucket(t, key);
422 for (i = 0; i < n->pos; i++) { 455 for (i = 0; i < n->pos; i++) {
423 data = ahash_data(n, i); 456 data = ahash_data(n, i);
424 if (!type_pf_data_equal(data, d)) 457 if (!type_pf_data_equal(data, d, &multi))
425 continue; 458 continue;
426 if (i != n->pos - 1) 459 if (i != n->pos - 1)
427 /* Not last one */ 460 /* Not last one */
@@ -462,17 +495,17 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
462 struct hbucket *n; 495 struct hbucket *n;
463 const struct type_pf_elem *data; 496 const struct type_pf_elem *data;
464 int i, j = 0; 497 int i, j = 0;
465 u32 key; 498 u32 key, multi = 0;
466 u8 host_mask = SET_HOST_MASK(set->family); 499 u8 host_mask = SET_HOST_MASK(set->family);
467 500
468 pr_debug("test by nets\n"); 501 pr_debug("test by nets\n");
469 for (; j < host_mask && h->nets[j].cidr; j++) { 502 for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
470 type_pf_data_netmask(d, h->nets[j].cidr); 503 type_pf_data_netmask(d, h->nets[j].cidr);
471 key = HKEY(d, h->initval, t->htable_bits); 504 key = HKEY(d, h->initval, t->htable_bits);
472 n = hbucket(t, key); 505 n = hbucket(t, key);
473 for (i = 0; i < n->pos; i++) { 506 for (i = 0; i < n->pos; i++) {
474 data = ahash_data(n, i); 507 data = ahash_data(n, i);
475 if (type_pf_data_equal(data, d)) 508 if (type_pf_data_equal(data, d, &multi))
476 return 1; 509 return 1;
477 } 510 }
478 } 511 }
@@ -490,7 +523,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
490 struct hbucket *n; 523 struct hbucket *n;
491 const struct type_pf_elem *data; 524 const struct type_pf_elem *data;
492 int i; 525 int i;
493 u32 key; 526 u32 key, multi = 0;
494 527
495#ifdef IP_SET_HASH_WITH_NETS 528#ifdef IP_SET_HASH_WITH_NETS
496 /* If we test an IP address and not a network address, 529 /* If we test an IP address and not a network address,
@@ -503,7 +536,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
503 n = hbucket(t, key); 536 n = hbucket(t, key);
504 for (i = 0; i < n->pos; i++) { 537 for (i = 0; i < n->pos; i++) {
505 data = ahash_data(n, i); 538 data = ahash_data(n, i);
506 if (type_pf_data_equal(data, d)) 539 if (type_pf_data_equal(data, d, &multi))
507 return 1; 540 return 1;
508 } 541 }
509 return 0; 542 return 0;
@@ -660,14 +693,14 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
660 693
661static int 694static int
662type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, 695type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
663 u32 timeout) 696 u8 ahash_max, u32 timeout)
664{ 697{
665 struct type_pf_elem *data; 698 struct type_pf_elem *data;
666 699
667 if (n->pos >= n->size) { 700 if (n->pos >= n->size) {
668 void *tmp; 701 void *tmp;
669 702
670 if (n->size >= AHASH_MAX_SIZE) 703 if (n->size >= ahash_max)
671 /* Trigger rehashing */ 704 /* Trigger rehashing */
672 return -EAGAIN; 705 return -EAGAIN;
673 706
@@ -772,7 +805,7 @@ retry:
772 for (j = 0; j < n->pos; j++) { 805 for (j = 0; j < n->pos; j++) {
773 data = ahash_tdata(n, j); 806 data = ahash_tdata(n, j);
774 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 807 m = hbucket(t, HKEY(data, h->initval, htable_bits));
775 ret = type_pf_elem_tadd(m, data, 808 ret = type_pf_elem_tadd(m, data, AHASH_MAX(h),
776 type_pf_data_timeout(data)); 809 type_pf_data_timeout(data));
777 if (ret < 0) { 810 if (ret < 0) {
778 read_unlock_bh(&set->lock); 811 read_unlock_bh(&set->lock);
@@ -803,9 +836,9 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
803 const struct type_pf_elem *d = value; 836 const struct type_pf_elem *d = value;
804 struct hbucket *n; 837 struct hbucket *n;
805 struct type_pf_elem *data; 838 struct type_pf_elem *data;
806 int ret = 0, i, j = AHASH_MAX_SIZE + 1; 839 int ret = 0, i, j = AHASH_MAX(h) + 1;
807 bool flag_exist = flags & IPSET_FLAG_EXIST; 840 bool flag_exist = flags & IPSET_FLAG_EXIST;
808 u32 key; 841 u32 key, multi = 0;
809 842
810 if (h->elements >= h->maxelem) 843 if (h->elements >= h->maxelem)
811 /* FIXME: when set is full, we slow down here */ 844 /* FIXME: when set is full, we slow down here */
@@ -819,18 +852,18 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
819 n = hbucket(t, key); 852 n = hbucket(t, key);
820 for (i = 0; i < n->pos; i++) { 853 for (i = 0; i < n->pos; i++) {
821 data = ahash_tdata(n, i); 854 data = ahash_tdata(n, i);
822 if (type_pf_data_equal(data, d)) { 855 if (type_pf_data_equal(data, d, &multi)) {
823 if (type_pf_data_expired(data) || flag_exist) 856 if (type_pf_data_expired(data) || flag_exist)
824 j = i; 857 j = i;
825 else { 858 else {
826 ret = -IPSET_ERR_EXIST; 859 ret = -IPSET_ERR_EXIST;
827 goto out; 860 goto out;
828 } 861 }
829 } else if (j == AHASH_MAX_SIZE + 1 && 862 } else if (j == AHASH_MAX(h) + 1 &&
830 type_pf_data_expired(data)) 863 type_pf_data_expired(data))
831 j = i; 864 j = i;
832 } 865 }
833 if (j != AHASH_MAX_SIZE + 1) { 866 if (j != AHASH_MAX(h) + 1) {
834 data = ahash_tdata(n, j); 867 data = ahash_tdata(n, j);
835#ifdef IP_SET_HASH_WITH_NETS 868#ifdef IP_SET_HASH_WITH_NETS
836 del_cidr(h, data->cidr, HOST_MASK); 869 del_cidr(h, data->cidr, HOST_MASK);
@@ -840,7 +873,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
840 type_pf_data_timeout_set(data, timeout); 873 type_pf_data_timeout_set(data, timeout);
841 goto out; 874 goto out;
842 } 875 }
843 ret = type_pf_elem_tadd(n, d, timeout); 876 TUNE_AHASH_MAX(h, multi);
877 ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout);
844 if (ret != 0) { 878 if (ret != 0) {
845 if (ret == -EAGAIN) 879 if (ret == -EAGAIN)
846 type_pf_data_next(h, d); 880 type_pf_data_next(h, d);
@@ -865,13 +899,13 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
865 struct hbucket *n; 899 struct hbucket *n;
866 int i; 900 int i;
867 struct type_pf_elem *data; 901 struct type_pf_elem *data;
868 u32 key; 902 u32 key, multi = 0;
869 903
870 key = HKEY(value, h->initval, t->htable_bits); 904 key = HKEY(value, h->initval, t->htable_bits);
871 n = hbucket(t, key); 905 n = hbucket(t, key);
872 for (i = 0; i < n->pos; i++) { 906 for (i = 0; i < n->pos; i++) {
873 data = ahash_tdata(n, i); 907 data = ahash_tdata(n, i);
874 if (!type_pf_data_equal(data, d)) 908 if (!type_pf_data_equal(data, d, &multi))
875 continue; 909 continue;
876 if (type_pf_data_expired(data)) 910 if (type_pf_data_expired(data))
877 return -IPSET_ERR_EXIST; 911 return -IPSET_ERR_EXIST;
@@ -911,16 +945,16 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
911 struct type_pf_elem *data; 945 struct type_pf_elem *data;
912 struct hbucket *n; 946 struct hbucket *n;
913 int i, j = 0; 947 int i, j = 0;
914 u32 key; 948 u32 key, multi = 0;
915 u8 host_mask = SET_HOST_MASK(set->family); 949 u8 host_mask = SET_HOST_MASK(set->family);
916 950
917 for (; j < host_mask && h->nets[j].cidr; j++) { 951 for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
918 type_pf_data_netmask(d, h->nets[j].cidr); 952 type_pf_data_netmask(d, h->nets[j].cidr);
919 key = HKEY(d, h->initval, t->htable_bits); 953 key = HKEY(d, h->initval, t->htable_bits);
920 n = hbucket(t, key); 954 n = hbucket(t, key);
921 for (i = 0; i < n->pos; i++) { 955 for (i = 0; i < n->pos; i++) {
922 data = ahash_tdata(n, i); 956 data = ahash_tdata(n, i);
923 if (type_pf_data_equal(data, d)) 957 if (type_pf_data_equal(data, d, &multi))
924 return !type_pf_data_expired(data); 958 return !type_pf_data_expired(data);
925 } 959 }
926 } 960 }
@@ -936,7 +970,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
936 struct type_pf_elem *data, *d = value; 970 struct type_pf_elem *data, *d = value;
937 struct hbucket *n; 971 struct hbucket *n;
938 int i; 972 int i;
939 u32 key; 973 u32 key, multi = 0;
940 974
941#ifdef IP_SET_HASH_WITH_NETS 975#ifdef IP_SET_HASH_WITH_NETS
942 if (d->cidr == SET_HOST_MASK(set->family)) 976 if (d->cidr == SET_HOST_MASK(set->family))
@@ -946,7 +980,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
946 n = hbucket(t, key); 980 n = hbucket(t, key);
947 for (i = 0; i < n->pos; i++) { 981 for (i = 0; i < n->pos; i++) {
948 data = ahash_tdata(n, i); 982 data = ahash_tdata(n, i);
949 if (type_pf_data_equal(data, d)) 983 if (type_pf_data_equal(data, d, &multi))
950 return !type_pf_data_expired(data); 984 return !type_pf_data_expired(data);
951 } 985 }
952 return 0; 986 return 0;
@@ -1054,6 +1088,8 @@ type_pf_gc_init(struct ip_set *set)
1054 IPSET_GC_PERIOD(h->timeout)); 1088 IPSET_GC_PERIOD(h->timeout));
1055} 1089}
1056 1090
1091#undef HKEY_DATALEN
1092#undef HKEY
1057#undef type_pf_data_equal 1093#undef type_pf_data_equal
1058#undef type_pf_data_isnull 1094#undef type_pf_data_isnull
1059#undef type_pf_data_copy 1095#undef type_pf_data_copy
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 2b11fc1a86b..74d33861473 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -60,6 +60,9 @@ struct nfnl_callback {
60 int (*call)(struct sock *nl, struct sk_buff *skb, 60 int (*call)(struct sock *nl, struct sk_buff *skb,
61 const struct nlmsghdr *nlh, 61 const struct nlmsghdr *nlh,
62 const struct nlattr * const cda[]); 62 const struct nlattr * const cda[]);
63 int (*call_rcu)(struct sock *nl, struct sk_buff *skb,
64 const struct nlmsghdr *nlh,
65 const struct nlattr * const cda[]);
63 const struct nla_policy *policy; /* netlink attribute policy */ 66 const struct nla_policy *policy; /* netlink attribute policy */
64 const u_int16_t attr_count; /* number of nlattr's */ 67 const u_int16_t attr_count; /* number of nlattr's */
65}; 68};
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index af94e0014eb..24b32e6c009 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -8,6 +8,7 @@ enum nfqnl_msg_types {
8 NFQNL_MSG_PACKET, /* packet from kernel to userspace */ 8 NFQNL_MSG_PACKET, /* packet from kernel to userspace */
9 NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ 9 NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
10 NFQNL_MSG_CONFIG, /* connect to a particular queue */ 10 NFQNL_MSG_CONFIG, /* connect to a particular queue */
11 NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */
11 12
12 NFQNL_MSG_MAX 13 NFQNL_MSG_MAX
13}; 14};
diff --git a/kernel/audit.c b/kernel/audit.c
index 93950031706..52501b5d490 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -55,6 +55,9 @@
55#include <net/sock.h> 55#include <net/sock.h>
56#include <net/netlink.h> 56#include <net/netlink.h>
57#include <linux/skbuff.h> 57#include <linux/skbuff.h>
58#ifdef CONFIG_SECURITY
59#include <linux/security.h>
60#endif
58#include <linux/netlink.h> 61#include <linux/netlink.h>
59#include <linux/freezer.h> 62#include <linux/freezer.h>
60#include <linux/tty.h> 63#include <linux/tty.h>
@@ -1502,6 +1505,32 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
1502 } 1505 }
1503} 1506}
1504 1507
1508#ifdef CONFIG_SECURITY
1509/**
1510 * audit_log_secctx - Converts and logs SELinux context
1511 * @ab: audit_buffer
1512 * @secid: security number
1513 *
1514 * This is a helper function that calls security_secid_to_secctx to convert
1515 * secid to secctx and then adds the (converted) SELinux context to the audit
1516 * log by calling audit_log_format, thus also preventing leak of internal secid
1517 * to userspace. If secid cannot be converted audit_panic is called.
1518 */
1519void audit_log_secctx(struct audit_buffer *ab, u32 secid)
1520{
1521 u32 len;
1522 char *secctx;
1523
1524 if (security_secid_to_secctx(secid, &secctx, &len)) {
1525 audit_panic("Cannot convert secid to context");
1526 } else {
1527 audit_log_format(ab, " obj=%s", secctx);
1528 security_release_secctx(secctx, len);
1529 }
1530}
1531EXPORT_SYMBOL(audit_log_secctx);
1532#endif
1533
1505EXPORT_SYMBOL(audit_log_start); 1534EXPORT_SYMBOL(audit_log_start);
1506EXPORT_SYMBOL(audit_log_end); 1535EXPORT_SYMBOL(audit_log_end);
1507EXPORT_SYMBOL(audit_log_format); 1536EXPORT_SYMBOL(audit_log_format);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index fa80bb9b9c8..f2d576e6b76 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -53,7 +53,8 @@ struct hash_ip4_telem {
53 53
54static inline bool 54static inline bool
55hash_ip4_data_equal(const struct hash_ip4_elem *ip1, 55hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
56 const struct hash_ip4_elem *ip2) 56 const struct hash_ip4_elem *ip2,
57 u32 *multi)
57{ 58{
58 return ip1->ip == ip2->ip; 59 return ip1->ip == ip2->ip;
59} 60}
@@ -225,7 +226,8 @@ struct hash_ip6_telem {
225 226
226static inline bool 227static inline bool
227hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 228hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
228 const struct hash_ip6_elem *ip2) 229 const struct hash_ip6_elem *ip2,
230 u32 *multi)
229{ 231{
230 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0; 232 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
231} 233}
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index bbf51b67b17..6ee10f5d59b 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
60 60
61static inline bool 61static inline bool
62hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, 62hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
63 const struct hash_ipport4_elem *ip2) 63 const struct hash_ipport4_elem *ip2,
64 u32 *multi)
64{ 65{
65 return ip1->ip == ip2->ip && 66 return ip1->ip == ip2->ip &&
66 ip1->port == ip2->port && 67 ip1->port == ip2->port &&
@@ -276,7 +277,8 @@ struct hash_ipport6_telem {
276 277
277static inline bool 278static inline bool
278hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 279hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
279 const struct hash_ipport6_elem *ip2) 280 const struct hash_ipport6_elem *ip2,
281 u32 *multi)
280{ 282{
281 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 283 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
282 ip1->port == ip2->port && 284 ip1->port == ip2->port &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 96525f529a5..fb90e344e90 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
62 62
63static inline bool 63static inline bool
64hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, 64hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
65 const struct hash_ipportip4_elem *ip2) 65 const struct hash_ipportip4_elem *ip2,
66 u32 *multi)
66{ 67{
67 return ip1->ip == ip2->ip && 68 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 && 69 ip1->ip2 == ip2->ip2 &&
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
286 287
287static inline bool 288static inline bool
288hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 289hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
289 const struct hash_ipportip6_elem *ip2) 290 const struct hash_ipportip6_elem *ip2,
291 u32 *multi)
290{ 292{
291 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 293 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
292 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 294 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index d2d6ab89f08..deb3e3dfa5f 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
62 62
63static inline bool 63static inline bool
64hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 64hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
65 const struct hash_ipportnet4_elem *ip2) 65 const struct hash_ipportnet4_elem *ip2,
66 u32 *multi)
66{ 67{
67 return ip1->ip == ip2->ip && 68 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 && 69 ip1->ip2 == ip2->ip2 &&
@@ -335,7 +336,8 @@ struct hash_ipportnet6_telem {
335 336
336static inline bool 337static inline bool
337hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 338hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
338 const struct hash_ipportnet6_elem *ip2) 339 const struct hash_ipportnet6_elem *ip2,
340 u32 *multi)
339{ 341{
340 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 342 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
341 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 343 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 2d4b1f48e8c..60d016541c5 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -58,7 +58,8 @@ struct hash_net4_telem {
58 58
59static inline bool 59static inline bool
60hash_net4_data_equal(const struct hash_net4_elem *ip1, 60hash_net4_data_equal(const struct hash_net4_elem *ip1,
61 const struct hash_net4_elem *ip2) 61 const struct hash_net4_elem *ip2,
62 u32 *multi)
62{ 63{
63 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; 64 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
64} 65}
@@ -249,7 +250,8 @@ struct hash_net6_telem {
249 250
250static inline bool 251static inline bool
251hash_net6_data_equal(const struct hash_net6_elem *ip1, 252hash_net6_data_equal(const struct hash_net6_elem *ip1,
252 const struct hash_net6_elem *ip2) 253 const struct hash_net6_elem *ip2,
254 u32 *multi)
253{ 255{
254 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 256 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
255 ip1->cidr == ip2->cidr; 257 ip1->cidr == ip2->cidr;
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 3d6c53b6211..e13095deb50 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -99,7 +99,7 @@ iface_test(struct rb_root *root, const char **iface)
99 99
100 while (n) { 100 while (n) {
101 const char *d = iface_data(n); 101 const char *d = iface_data(n);
102 int res = ifname_compare(*iface, d); 102 long res = ifname_compare(*iface, d);
103 103
104 if (res < 0) 104 if (res < 0)
105 n = n->rb_left; 105 n = n->rb_left;
@@ -121,7 +121,7 @@ iface_add(struct rb_root *root, const char **iface)
121 121
122 while (*n) { 122 while (*n) {
123 char *ifname = iface_data(*n); 123 char *ifname = iface_data(*n);
124 int res = ifname_compare(*iface, ifname); 124 long res = ifname_compare(*iface, ifname);
125 125
126 p = *n; 126 p = *n;
127 if (res < 0) 127 if (res < 0)
@@ -159,31 +159,42 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
159 159
160/* The type variant functions: IPv4 */ 160/* The type variant functions: IPv4 */
161 161
162struct hash_netiface4_elem_hashed {
163 __be32 ip;
164 u8 physdev;
165 u8 cidr;
166 u16 padding;
167};
168
169#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
170
162/* Member elements without timeout */ 171/* Member elements without timeout */
163struct hash_netiface4_elem { 172struct hash_netiface4_elem {
164 __be32 ip; 173 __be32 ip;
165 const char *iface;
166 u8 physdev; 174 u8 physdev;
167 u8 cidr; 175 u8 cidr;
168 u16 padding; 176 u16 padding;
177 const char *iface;
169}; 178};
170 179
171/* Member elements with timeout support */ 180/* Member elements with timeout support */
172struct hash_netiface4_telem { 181struct hash_netiface4_telem {
173 __be32 ip; 182 __be32 ip;
174 const char *iface;
175 u8 physdev; 183 u8 physdev;
176 u8 cidr; 184 u8 cidr;
177 u16 padding; 185 u16 padding;
186 const char *iface;
178 unsigned long timeout; 187 unsigned long timeout;
179}; 188};
180 189
181static inline bool 190static inline bool
182hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, 191hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
183 const struct hash_netiface4_elem *ip2) 192 const struct hash_netiface4_elem *ip2,
193 u32 *multi)
184{ 194{
185 return ip1->ip == ip2->ip && 195 return ip1->ip == ip2->ip &&
186 ip1->cidr == ip2->cidr && 196 ip1->cidr == ip2->cidr &&
197 (++*multi) &&
187 ip1->physdev == ip2->physdev && 198 ip1->physdev == ip2->physdev &&
188 ip1->iface == ip2->iface; 199 ip1->iface == ip2->iface;
189} 200}
@@ -257,6 +268,7 @@ nla_put_failure:
257 268
258#define IP_SET_HASH_WITH_NETS 269#define IP_SET_HASH_WITH_NETS
259#define IP_SET_HASH_WITH_RBTREE 270#define IP_SET_HASH_WITH_RBTREE
271#define IP_SET_HASH_WITH_MULTI
260 272
261#define PF 4 273#define PF 4
262#define HOST_MASK 32 274#define HOST_MASK 32
@@ -424,29 +436,40 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
424 436
425/* The type variant functions: IPv6 */ 437/* The type variant functions: IPv6 */
426 438
439struct hash_netiface6_elem_hashed {
440 union nf_inet_addr ip;
441 u8 physdev;
442 u8 cidr;
443 u16 padding;
444};
445
446#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
447
427struct hash_netiface6_elem { 448struct hash_netiface6_elem {
428 union nf_inet_addr ip; 449 union nf_inet_addr ip;
429 const char *iface;
430 u8 physdev; 450 u8 physdev;
431 u8 cidr; 451 u8 cidr;
432 u16 padding; 452 u16 padding;
453 const char *iface;
433}; 454};
434 455
435struct hash_netiface6_telem { 456struct hash_netiface6_telem {
436 union nf_inet_addr ip; 457 union nf_inet_addr ip;
437 const char *iface;
438 u8 physdev; 458 u8 physdev;
439 u8 cidr; 459 u8 cidr;
440 u16 padding; 460 u16 padding;
461 const char *iface;
441 unsigned long timeout; 462 unsigned long timeout;
442}; 463};
443 464
444static inline bool 465static inline bool
445hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 466hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
446 const struct hash_netiface6_elem *ip2) 467 const struct hash_netiface6_elem *ip2,
468 u32 *multi)
447{ 469{
448 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 470 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
449 ip1->cidr == ip2->cidr && 471 ip1->cidr == ip2->cidr &&
472 (++*multi) &&
450 ip1->physdev == ip2->physdev && 473 ip1->physdev == ip2->physdev &&
451 ip1->iface == ip2->iface; 474 ip1->iface == ip2->iface;
452} 475}
@@ -681,6 +704,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
681 h->maxelem = maxelem; 704 h->maxelem = maxelem;
682 get_random_bytes(&h->initval, sizeof(h->initval)); 705 get_random_bytes(&h->initval, sizeof(h->initval));
683 h->timeout = IPSET_NO_TIMEOUT; 706 h->timeout = IPSET_NO_TIMEOUT;
707 h->ahash_max = AHASH_MAX_SIZE;
684 708
685 hbits = htable_bits(hashsize); 709 hbits = htable_bits(hashsize);
686 h->table = ip_set_alloc( 710 h->table = ip_set_alloc(
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index fe203d12f56..8f9de7207ec 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -59,7 +59,8 @@ struct hash_netport4_telem {
59 59
60static inline bool 60static inline bool
61hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 61hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
62 const struct hash_netport4_elem *ip2) 62 const struct hash_netport4_elem *ip2,
63 u32 *multi)
63{ 64{
64 return ip1->ip == ip2->ip && 65 return ip1->ip == ip2->ip &&
65 ip1->port == ip2->port && 66 ip1->port == ip2->port &&
@@ -300,7 +301,8 @@ struct hash_netport6_telem {
300 301
301static inline bool 302static inline bool
302hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 303hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
303 const struct hash_netport6_elem *ip2) 304 const struct hash_netport6_elem *ip2,
305 u32 *multi)
304{ 306{
305 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 307 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
306 ip1->port == ip2->port && 308 ip1->port == ip2->port &&
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index b4a4532823e..1905976b513 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -37,7 +37,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
37 37
38static char __initdata nfversion[] = "0.30"; 38static char __initdata nfversion[] = "0.30";
39 39
40static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; 40static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT];
41static DEFINE_MUTEX(nfnl_mutex); 41static DEFINE_MUTEX(nfnl_mutex);
42 42
43void nfnl_lock(void) 43void nfnl_lock(void)
@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
59 nfnl_unlock(); 59 nfnl_unlock();
60 return -EBUSY; 60 return -EBUSY;
61 } 61 }
62 subsys_table[n->subsys_id] = n; 62 rcu_assign_pointer(subsys_table[n->subsys_id], n);
63 nfnl_unlock(); 63 nfnl_unlock();
64 64
65 return 0; 65 return 0;
@@ -71,7 +71,7 @@ int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
71 nfnl_lock(); 71 nfnl_lock();
72 subsys_table[n->subsys_id] = NULL; 72 subsys_table[n->subsys_id] = NULL;
73 nfnl_unlock(); 73 nfnl_unlock();
74 74 synchronize_rcu();
75 return 0; 75 return 0;
76} 76}
77EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); 77EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
@@ -83,7 +83,7 @@ static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t t
83 if (subsys_id >= NFNL_SUBSYS_COUNT) 83 if (subsys_id >= NFNL_SUBSYS_COUNT)
84 return NULL; 84 return NULL;
85 85
86 return subsys_table[subsys_id]; 86 return rcu_dereference(subsys_table[subsys_id]);
87} 87}
88 88
89static inline const struct nfnl_callback * 89static inline const struct nfnl_callback *
@@ -139,21 +139,27 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
139 139
140 type = nlh->nlmsg_type; 140 type = nlh->nlmsg_type;
141replay: 141replay:
142 rcu_read_lock();
142 ss = nfnetlink_get_subsys(type); 143 ss = nfnetlink_get_subsys(type);
143 if (!ss) { 144 if (!ss) {
144#ifdef CONFIG_MODULES 145#ifdef CONFIG_MODULES
145 nfnl_unlock(); 146 rcu_read_unlock();
146 request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); 147 request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
147 nfnl_lock(); 148 rcu_read_lock();
148 ss = nfnetlink_get_subsys(type); 149 ss = nfnetlink_get_subsys(type);
149 if (!ss) 150 if (!ss)
150#endif 151#endif
152 {
153 rcu_read_unlock();
151 return -EINVAL; 154 return -EINVAL;
155 }
152 } 156 }
153 157
154 nc = nfnetlink_find_client(type, ss); 158 nc = nfnetlink_find_client(type, ss);
155 if (!nc) 159 if (!nc) {
160 rcu_read_unlock();
156 return -EINVAL; 161 return -EINVAL;
162 }
157 163
158 { 164 {
159 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 165 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
@@ -167,7 +173,23 @@ replay:
167 if (err < 0) 173 if (err < 0)
168 return err; 174 return err;
169 175
170 err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda); 176 if (nc->call_rcu) {
177 err = nc->call_rcu(net->nfnl, skb, nlh,
178 (const struct nlattr **)cda);
179 rcu_read_unlock();
180 } else {
181 rcu_read_unlock();
182 nfnl_lock();
183 if (rcu_dereference_protected(
184 subsys_table[NFNL_SUBSYS_ID(type)],
185 lockdep_is_held(&nfnl_mutex)) != ss ||
186 nfnetlink_find_client(type, ss) != nc)
187 err = -EAGAIN;
188 else
189 err = nc->call(net->nfnl, skb, nlh,
190 (const struct nlattr **)cda);
191 nfnl_unlock();
192 }
171 if (err == -EAGAIN) 193 if (err == -EAGAIN)
172 goto replay; 194 goto replay;
173 return err; 195 return err;
@@ -176,9 +198,7 @@ replay:
176 198
177static void nfnetlink_rcv(struct sk_buff *skb) 199static void nfnetlink_rcv(struct sk_buff *skb)
178{ 200{
179 nfnl_lock();
180 netlink_rcv_skb(skb, &nfnetlink_rcv_msg); 201 netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
181 nfnl_unlock();
182} 202}
183 203
184static int __net_init nfnetlink_net_init(struct net *net) 204static int __net_init nfnetlink_net_init(struct net *net)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index fdd2fafe0a1..49132bddd73 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -58,7 +58,7 @@ struct nfqnl_instance {
58 */ 58 */
59 spinlock_t lock; 59 spinlock_t lock;
60 unsigned int queue_total; 60 unsigned int queue_total;
61 atomic_t id_sequence; /* 'sequence' of pkt ids */ 61 unsigned int id_sequence; /* 'sequence' of pkt ids */
62 struct list_head queue_list; /* packets in queue */ 62 struct list_head queue_list; /* packets in queue */
63}; 63};
64 64
@@ -171,6 +171,13 @@ __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
171 queue->queue_total++; 171 queue->queue_total++;
172} 172}
173 173
174static void
175__dequeue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
176{
177 list_del(&entry->list);
178 queue->queue_total--;
179}
180
174static struct nf_queue_entry * 181static struct nf_queue_entry *
175find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) 182find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
176{ 183{
@@ -185,10 +192,8 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
185 } 192 }
186 } 193 }
187 194
188 if (entry) { 195 if (entry)
189 list_del(&entry->list); 196 __dequeue_entry(queue, entry);
190 queue->queue_total--;
191 }
192 197
193 spin_unlock_bh(&queue->lock); 198 spin_unlock_bh(&queue->lock);
194 199
@@ -213,13 +218,15 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
213 218
214static struct sk_buff * 219static struct sk_buff *
215nfqnl_build_packet_message(struct nfqnl_instance *queue, 220nfqnl_build_packet_message(struct nfqnl_instance *queue,
216 struct nf_queue_entry *entry) 221 struct nf_queue_entry *entry,
222 __be32 **packet_id_ptr)
217{ 223{
218 sk_buff_data_t old_tail; 224 sk_buff_data_t old_tail;
219 size_t size; 225 size_t size;
220 size_t data_len = 0; 226 size_t data_len = 0;
221 struct sk_buff *skb; 227 struct sk_buff *skb;
222 struct nfqnl_msg_packet_hdr pmsg; 228 struct nlattr *nla;
229 struct nfqnl_msg_packet_hdr *pmsg;
223 struct nlmsghdr *nlh; 230 struct nlmsghdr *nlh;
224 struct nfgenmsg *nfmsg; 231 struct nfgenmsg *nfmsg;
225 struct sk_buff *entskb = entry->skb; 232 struct sk_buff *entskb = entry->skb;
@@ -272,12 +279,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
272 nfmsg->version = NFNETLINK_V0; 279 nfmsg->version = NFNETLINK_V0;
273 nfmsg->res_id = htons(queue->queue_num); 280 nfmsg->res_id = htons(queue->queue_num);
274 281
275 entry->id = atomic_inc_return(&queue->id_sequence); 282 nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
276 pmsg.packet_id = htonl(entry->id); 283 pmsg = nla_data(nla);
277 pmsg.hw_protocol = entskb->protocol; 284 pmsg->hw_protocol = entskb->protocol;
278 pmsg.hook = entry->hook; 285 pmsg->hook = entry->hook;
279 286 *packet_id_ptr = &pmsg->packet_id;
280 NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
281 287
282 indev = entry->indev; 288 indev = entry->indev;
283 if (indev) { 289 if (indev) {
@@ -389,6 +395,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
389 struct sk_buff *nskb; 395 struct sk_buff *nskb;
390 struct nfqnl_instance *queue; 396 struct nfqnl_instance *queue;
391 int err = -ENOBUFS; 397 int err = -ENOBUFS;
398 __be32 *packet_id_ptr;
392 399
393 /* rcu_read_lock()ed by nf_hook_slow() */ 400 /* rcu_read_lock()ed by nf_hook_slow() */
394 queue = instance_lookup(queuenum); 401 queue = instance_lookup(queuenum);
@@ -402,7 +409,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
402 goto err_out; 409 goto err_out;
403 } 410 }
404 411
405 nskb = nfqnl_build_packet_message(queue, entry); 412 nskb = nfqnl_build_packet_message(queue, entry, &packet_id_ptr);
406 if (nskb == NULL) { 413 if (nskb == NULL) {
407 err = -ENOMEM; 414 err = -ENOMEM;
408 goto err_out; 415 goto err_out;
@@ -421,6 +428,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
421 queue->queue_total); 428 queue->queue_total);
422 goto err_out_free_nskb; 429 goto err_out_free_nskb;
423 } 430 }
431 entry->id = ++queue->id_sequence;
432 *packet_id_ptr = htonl(entry->id);
424 433
425 /* nfnetlink_unicast will either free the nskb or add it to a socket */ 434 /* nfnetlink_unicast will either free the nskb or add it to a socket */
426 err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); 435 err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
@@ -608,6 +617,92 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
608 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC }, 617 [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
609}; 618};
610 619
620static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
621 [NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
622 [NFQA_MARK] = { .type = NLA_U32 },
623};
624
625static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
626{
627 struct nfqnl_instance *queue;
628
629 queue = instance_lookup(queue_num);
630 if (!queue)
631 return ERR_PTR(-ENODEV);
632
633 if (queue->peer_pid != nlpid)
634 return ERR_PTR(-EPERM);
635
636 return queue;
637}
638
639static struct nfqnl_msg_verdict_hdr*
640verdicthdr_get(const struct nlattr * const nfqa[])
641{
642 struct nfqnl_msg_verdict_hdr *vhdr;
643 unsigned int verdict;
644
645 if (!nfqa[NFQA_VERDICT_HDR])
646 return NULL;
647
648 vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
649 verdict = ntohl(vhdr->verdict);
650 if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
651 return NULL;
652 return vhdr;
653}
654
655static int nfq_id_after(unsigned int id, unsigned int max)
656{
657 return (int)(id - max) > 0;
658}
659
660static int
661nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
662 const struct nlmsghdr *nlh,
663 const struct nlattr * const nfqa[])
664{
665 struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
666 struct nf_queue_entry *entry, *tmp;
667 unsigned int verdict, maxid;
668 struct nfqnl_msg_verdict_hdr *vhdr;
669 struct nfqnl_instance *queue;
670 LIST_HEAD(batch_list);
671 u16 queue_num = ntohs(nfmsg->res_id);
672
673 queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
674 if (IS_ERR(queue))
675 return PTR_ERR(queue);
676
677 vhdr = verdicthdr_get(nfqa);
678 if (!vhdr)
679 return -EINVAL;
680
681 verdict = ntohl(vhdr->verdict);
682 maxid = ntohl(vhdr->id);
683
684 spin_lock_bh(&queue->lock);
685
686 list_for_each_entry_safe(entry, tmp, &queue->queue_list, list) {
687 if (nfq_id_after(entry->id, maxid))
688 break;
689 __dequeue_entry(queue, entry);
690 list_add_tail(&entry->list, &batch_list);
691 }
692
693 spin_unlock_bh(&queue->lock);
694
695 if (list_empty(&batch_list))
696 return -ENOENT;
697
698 list_for_each_entry_safe(entry, tmp, &batch_list, list) {
699 if (nfqa[NFQA_MARK])
700 entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
701 nf_reinject(entry, verdict);
702 }
703 return 0;
704}
705
611static int 706static int
612nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, 707nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
613 const struct nlmsghdr *nlh, 708 const struct nlmsghdr *nlh,
@@ -620,39 +715,23 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
620 struct nfqnl_instance *queue; 715 struct nfqnl_instance *queue;
621 unsigned int verdict; 716 unsigned int verdict;
622 struct nf_queue_entry *entry; 717 struct nf_queue_entry *entry;
623 int err;
624 718
625 rcu_read_lock();
626 queue = instance_lookup(queue_num); 719 queue = instance_lookup(queue_num);
627 if (!queue) { 720 if (!queue)
628 err = -ENODEV;
629 goto err_out_unlock;
630 }
631 721
632 if (queue->peer_pid != NETLINK_CB(skb).pid) { 722 queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
633 err = -EPERM; 723 if (IS_ERR(queue))
634 goto err_out_unlock; 724 return PTR_ERR(queue);
635 }
636 725
637 if (!nfqa[NFQA_VERDICT_HDR]) { 726 vhdr = verdicthdr_get(nfqa);
638 err = -EINVAL; 727 if (!vhdr)
639 goto err_out_unlock; 728 return -EINVAL;
640 }
641 729
642 vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
643 verdict = ntohl(vhdr->verdict); 730 verdict = ntohl(vhdr->verdict);
644 731
645 if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
646 err = -EINVAL;
647 goto err_out_unlock;
648 }
649
650 entry = find_dequeue_entry(queue, ntohl(vhdr->id)); 732 entry = find_dequeue_entry(queue, ntohl(vhdr->id));
651 if (entry == NULL) { 733 if (entry == NULL)
652 err = -ENOENT; 734 return -ENOENT;
653 goto err_out_unlock;
654 }
655 rcu_read_unlock();
656 735
657 if (nfqa[NFQA_PAYLOAD]) { 736 if (nfqa[NFQA_PAYLOAD]) {
658 if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]), 737 if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
@@ -665,10 +744,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
665 744
666 nf_reinject(entry, verdict); 745 nf_reinject(entry, verdict);
667 return 0; 746 return 0;
668
669err_out_unlock:
670 rcu_read_unlock();
671 return err;
672} 747}
673 748
674static int 749static int
@@ -781,14 +856,17 @@ err_out_unlock:
781} 856}
782 857
783static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { 858static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
784 [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, 859 [NFQNL_MSG_PACKET] = { .call_rcu = nfqnl_recv_unsupp,
785 .attr_count = NFQA_MAX, }, 860 .attr_count = NFQA_MAX, },
786 [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, 861 [NFQNL_MSG_VERDICT] = { .call_rcu = nfqnl_recv_verdict,
787 .attr_count = NFQA_MAX, 862 .attr_count = NFQA_MAX,
788 .policy = nfqa_verdict_policy }, 863 .policy = nfqa_verdict_policy },
789 [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, 864 [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
790 .attr_count = NFQA_CFG_MAX, 865 .attr_count = NFQA_CFG_MAX,
791 .policy = nfqa_cfg_policy }, 866 .policy = nfqa_cfg_policy },
867 [NFQNL_MSG_VERDICT_BATCH]={ .call_rcu = nfqnl_recv_verdict_batch,
868 .attr_count = NFQA_MAX,
869 .policy = nfqa_verdict_batch_policy },
792}; 870};
793 871
794static const struct nfnetlink_subsystem nfqnl_subsys = { 872static const struct nfnetlink_subsystem nfqnl_subsys = {
@@ -870,7 +948,7 @@ static int seq_show(struct seq_file *s, void *v)
870 inst->peer_pid, inst->queue_total, 948 inst->peer_pid, inst->queue_total,
871 inst->copy_mode, inst->copy_range, 949 inst->copy_mode, inst->copy_range,
872 inst->queue_dropped, inst->queue_user_dropped, 950 inst->queue_dropped, inst->queue_user_dropped,
873 atomic_read(&inst->id_sequence), 1); 951 inst->id_sequence, 1);
874} 952}
875 953
876static const struct seq_operations nfqnl_seq_ops = { 954static const struct seq_operations nfqnl_seq_ops = {
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 363a99ec063..4bca15a0c38 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -163,6 +163,11 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
163 break; 163 break;
164 } 164 }
165 165
166#ifdef CONFIG_NETWORK_SECMARK
167 if (skb->secmark)
168 audit_log_secctx(ab, skb->secmark);
169#endif
170
166 audit_log_end(ab); 171 audit_log_end(ab);
167 172
168errout: 173errout: