Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6

+331 -116
+7
include/linux/audit.h
··· 613 613 extern void audit_log_key(struct audit_buffer *ab, 614 614 char *key); 615 615 extern void audit_log_lost(const char *message); 616 + #ifdef CONFIG_SECURITY 617 + extern 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 + 616 622 extern int audit_update_lsm_rules(void); 617 623 618 624 /* Private API (for audit.c only) */ ··· 641 635 #define audit_log_untrustedstring(a,s) do { ; } while (0) 642 636 #define audit_log_d_path(b, p, d) do { ; } while (0) 643 637 #define audit_log_key(b, k) do { ; } while (0) 638 + #define audit_log_secctx(b,s) do { ; } while (0) 644 639 #define audit_enabled 0 645 640 #endif 646 641 #endif
+72 -36
include/linux/netfilter/ipset/ip_set_ahash.h
··· 28 28 /* Number of elements to store in an initial array block */ 29 29 #define AHASH_INIT_SIZE 4 30 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 + 37 + static inline u8 38 + tune_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 58 /* A hash bucket */ 34 59 struct hbucket { ··· 85 60 u32 timeout; /* timeout value, if enabled */ 86 61 struct timer_list gc; /* garbage collection when timeout enabled */ 87 62 struct type_pf_next next; /* temporary storage for uadd */ 63 + #ifdef IP_SET_HASH_WITH_MULTI 64 + u8 ahash_max; /* max elements in an array block */ 65 + #endif 88 66 #ifdef IP_SET_HASH_WITH_NETMASK 89 67 u8 netmask; /* netmask value for subnets to store */ 90 68 #endif ··· 239 211 set->data = NULL; 240 212 } 241 213 242 - #define HKEY(data, initval, htable_bits) \ 243 - (jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \ 244 - & jhash_mask(htable_bits)) 245 - 246 214 #endif /* _IP_SET_AHASH_H */ 215 + 216 + #ifndef HKEY_DATALEN 217 + #define HKEY_DATALEN sizeof(struct type_pf_elem) 218 + #endif 219 + 220 + #define HKEY(data, initval, htable_bits) \ 221 + (jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \ 222 + & jhash_mask(htable_bits)) 247 223 248 224 #define CONCAT(a, b, c) a##b##c 249 225 #define TOKEN(a, b, c) CONCAT(a, b, c) ··· 307 275 /* Add an element to the hash table when resizing the set: 308 276 * we spare the maintenance of the internal counters. */ 309 277 static int 310 - type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value) 278 + type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value, 279 + u8 ahash_max) 311 280 { 312 281 if (n->pos >= n->size) { 313 282 void *tmp; 314 283 315 - if (n->size >= AHASH_MAX_SIZE) 284 + if (n->size >= ahash_max) 316 285 /* Trigger rehashing */ 317 286 return -EAGAIN; 318 287 ··· 368 335 for (j = 0; j < n->pos; j++) { 369 336 data = ahash_data(n, j); 370 337 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 371 - ret = type_pf_elem_add(m, data); 338 + ret = type_pf_elem_add(m, data, AHASH_MAX(h)); 372 339 if (ret < 0) { 373 340 read_unlock_bh(&set->lock); 374 341 ahash_destroy(t); ··· 392 359 return 0; 393 360 } 394 361 395 - static void 362 + static inline void 396 363 type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d); 397 364 398 365 /* Add an element to a hash and update the internal counters when succeeded, ··· 405 372 const struct type_pf_elem *d = value; 406 373 struct hbucket *n; 407 374 int i, ret = 0; 408 - u32 key; 375 + u32 key, multi = 0; 409 376 410 377 if (h->elements >= h->maxelem) 411 378 return -IPSET_ERR_HASH_FULL; ··· 415 382 key = HKEY(value, h->initval, t->htable_bits); 416 383 n = hbucket(t, key); 417 384 for (i = 0; i < n->pos; i++) 418 - if (type_pf_data_equal(ahash_data(n, i), d)) { 385 + if (type_pf_data_equal(ahash_data(n, i), d, &multi)) { 419 386 ret = -IPSET_ERR_EXIST; 420 387 goto out; 421 388 } 422 - 423 - ret = type_pf_elem_add(n, value); 389 + TUNE_AHASH_MAX(h, multi); 390 + ret = type_pf_elem_add(n, value, AHASH_MAX(h)); 424 391 if (ret != 0) { 425 392 if (ret == -EAGAIN) 426 393 type_pf_data_next(h, d); ··· 448 415 struct hbucket *n; 449 416 int i; 450 417 struct type_pf_elem *data; 451 - u32 key; 418 + u32 key, multi = 0; 452 419 453 420 key = HKEY(value, h->initval, t->htable_bits); 454 421 n = hbucket(t, key); 455 422 for (i = 0; i < n->pos; i++) { 456 423 data = ahash_data(n, i); 457 - if (!type_pf_data_equal(data, d)) 424 + if (!type_pf_data_equal(data, d, &multi)) 458 425 continue; 459 426 if (i != n->pos - 1) 460 427 /* Not last one */ ··· 495 462 struct hbucket *n; 496 463 const struct type_pf_elem *data; 497 464 int i, j = 0; 498 - u32 key; 465 + u32 key, multi = 0; 499 466 u8 host_mask = SET_HOST_MASK(set->family); 500 467 501 468 pr_debug("test by nets\n"); 502 - for (; j < host_mask && h->nets[j].cidr; j++) { 469 + for (; j < host_mask && h->nets[j].cidr && !multi; j++) { 503 470 type_pf_data_netmask(d, h->nets[j].cidr); 504 471 key = HKEY(d, h->initval, t->htable_bits); 505 472 n = hbucket(t, key); 506 473 for (i = 0; i < n->pos; i++) { 507 474 data = ahash_data(n, i); 508 - if (type_pf_data_equal(data, d)) 475 + if (type_pf_data_equal(data, d, &multi)) 509 476 return 1; 510 477 } 511 478 } ··· 523 490 struct hbucket *n; 524 491 const struct type_pf_elem *data; 525 492 int i; 526 - u32 key; 493 + u32 key, multi = 0; 527 494 528 495 #ifdef IP_SET_HASH_WITH_NETS 529 496 /* If we test an IP address and not a network address, ··· 536 503 n = hbucket(t, key); 537 504 for (i = 0; i < n->pos; i++) { 538 505 data = ahash_data(n, i); 539 - if (type_pf_data_equal(data, d)) 506 + if (type_pf_data_equal(data, d, &multi)) 540 507 return 1; 541 508 } 542 509 return 0; ··· 693 660 694 661 static int 695 662 type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, 696 - u32 timeout) 663 + u8 ahash_max, u32 timeout) 697 664 { 698 665 struct type_pf_elem *data; 699 666 700 667 if (n->pos >= n->size) { 701 668 void *tmp; 702 669 703 - if (n->size >= AHASH_MAX_SIZE) 670 + if (n->size >= ahash_max) 704 671 /* Trigger rehashing */ 705 672 return -EAGAIN; 706 673 ··· 805 772 for (j = 0; j < n->pos; j++) { 806 773 data = ahash_tdata(n, j); 807 774 m = hbucket(t, HKEY(data, h->initval, htable_bits)); 808 - ret = type_pf_elem_tadd(m, data, 775 + ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 809 776 type_pf_data_timeout(data)); 810 777 if (ret < 0) { 811 778 read_unlock_bh(&set->lock); ··· 836 803 const struct type_pf_elem *d = value; 837 804 struct hbucket *n; 838 805 struct type_pf_elem *data; 839 - int ret = 0, i, j = AHASH_MAX_SIZE + 1; 806 + int ret = 0, i, j = AHASH_MAX(h) + 1; 840 807 bool flag_exist = flags & IPSET_FLAG_EXIST; 841 - u32 key; 808 + u32 key, multi = 0; 842 809 843 810 if (h->elements >= h->maxelem) 844 811 /* FIXME: when set is full, we slow down here */ ··· 852 819 n = hbucket(t, key); 853 820 for (i = 0; i < n->pos; i++) { 854 821 data = ahash_tdata(n, i); 855 - if (type_pf_data_equal(data, d)) { 822 + if (type_pf_data_equal(data, d, &multi)) { 856 823 if (type_pf_data_expired(data) || flag_exist) 857 824 j = i; 858 825 else { 859 826 ret = -IPSET_ERR_EXIST; 860 827 goto out; 861 828 } 862 - } else if (j == AHASH_MAX_SIZE + 1 && 829 + } else if (j == AHASH_MAX(h) + 1 && 863 830 type_pf_data_expired(data)) 864 831 j = i; 865 832 } 866 - if (j != AHASH_MAX_SIZE + 1) { 833 + if (j != AHASH_MAX(h) + 1) { 867 834 data = ahash_tdata(n, j); 868 835 #ifdef IP_SET_HASH_WITH_NETS 869 836 del_cidr(h, data->cidr, HOST_MASK); ··· 873 840 type_pf_data_timeout_set(data, timeout); 874 841 goto out; 875 842 } 876 - ret = type_pf_elem_tadd(n, d, timeout); 843 + TUNE_AHASH_MAX(h, multi); 844 + ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout); 877 845 if (ret != 0) { 878 846 if (ret == -EAGAIN) 879 847 type_pf_data_next(h, d); ··· 899 865 struct hbucket *n; 900 866 int i; 901 867 struct type_pf_elem *data; 902 - u32 key; 868 + u32 key, multi = 0; 903 869 904 870 key = HKEY(value, h->initval, t->htable_bits); 905 871 n = hbucket(t, key); 906 872 for (i = 0; i < n->pos; i++) { 907 873 data = ahash_tdata(n, i); 908 - if (!type_pf_data_equal(data, d)) 874 + if (!type_pf_data_equal(data, d, &multi)) 909 875 continue; 910 876 if (type_pf_data_expired(data)) 911 877 return -IPSET_ERR_EXIST; ··· 945 911 struct type_pf_elem *data; 946 912 struct hbucket *n; 947 913 int i, j = 0; 948 - u32 key; 914 + u32 key, multi = 0; 949 915 u8 host_mask = SET_HOST_MASK(set->family); 950 916 951 - for (; j < host_mask && h->nets[j].cidr; j++) { 917 + for (; j < host_mask && h->nets[j].cidr && !multi; j++) { 952 918 type_pf_data_netmask(d, h->nets[j].cidr); 953 919 key = HKEY(d, h->initval, t->htable_bits); 954 920 n = hbucket(t, key); 955 921 for (i = 0; i < n->pos; i++) { 956 922 data = ahash_tdata(n, i); 957 - if (type_pf_data_equal(data, d)) 923 + if (type_pf_data_equal(data, d, &multi)) 958 924 return !type_pf_data_expired(data); 959 925 } 960 926 } ··· 970 936 struct type_pf_elem *data, *d = value; 971 937 struct hbucket *n; 972 938 int i; 973 - u32 key; 939 + u32 key, multi = 0; 974 940 975 941 #ifdef IP_SET_HASH_WITH_NETS 976 942 if (d->cidr == SET_HOST_MASK(set->family)) ··· 980 946 n = hbucket(t, key); 981 947 for (i = 0; i < n->pos; i++) { 982 948 data = ahash_tdata(n, i); 983 - if (type_pf_data_equal(data, d)) 949 + if (type_pf_data_equal(data, d, &multi)) 984 950 return !type_pf_data_expired(data); 985 951 } 986 952 return 0; ··· 1088 1054 IPSET_GC_PERIOD(h->timeout)); 1089 1055 } 1090 1056 1057 + #undef HKEY_DATALEN 1058 + #undef HKEY 1091 1059 #undef type_pf_data_equal 1092 1060 #undef type_pf_data_isnull 1093 1061 #undef type_pf_data_copy
+3
include/linux/netfilter/nfnetlink.h
··· 60 60 int (*call)(struct sock *nl, struct sk_buff *skb, 61 61 const struct nlmsghdr *nlh, 62 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 66 const struct nla_policy *policy; /* netlink attribute policy */ 64 67 const u_int16_t attr_count; /* number of nlattr's */ 65 68 };
+29
kernel/audit.c
··· 55 55 #include <net/sock.h> 56 56 #include <net/netlink.h> 57 57 #include <linux/skbuff.h> 58 + #ifdef CONFIG_SECURITY 59 + #include <linux/security.h> 60 + #endif 58 61 #include <linux/netlink.h> 59 62 #include <linux/freezer.h> 60 63 #include <linux/tty.h> ··· 1504 1501 audit_log_end(ab); 1505 1502 } 1506 1503 } 1504 + 1505 + #ifdef CONFIG_SECURITY 1506 + /** 1507 + * audit_log_secctx - Converts and logs SELinux context 1508 + * @ab: audit_buffer 1509 + * @secid: security number 1510 + * 1511 + * This is a helper function that calls security_secid_to_secctx to convert 1512 + * secid to secctx and then adds the (converted) SELinux context to the audit 1513 + * log by calling audit_log_format, thus also preventing leak of internal secid 1514 + * to userspace. If secid cannot be converted audit_panic is called. 1515 + */ 1516 + void audit_log_secctx(struct audit_buffer *ab, u32 secid) 1517 + { 1518 + u32 len; 1519 + char *secctx; 1520 + 1521 + if (security_secid_to_secctx(secid, &secctx, &len)) { 1522 + audit_panic("Cannot convert secid to context"); 1523 + } else { 1524 + audit_log_format(ab, " obj=%s", secctx); 1525 + security_release_secctx(secctx, len); 1526 + } 1527 + } 1528 + EXPORT_SYMBOL(audit_log_secctx); 1529 + #endif 1507 1530 1508 1531 EXPORT_SYMBOL(audit_log_start); 1509 1532 EXPORT_SYMBOL(audit_log_end);
+4 -2
net/netfilter/ipset/ip_set_hash_ip.c
··· 53 53 54 54 static inline bool 55 55 hash_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 59 return ip1->ip == ip2->ip; 59 60 } ··· 226 225 227 226 static inline bool 228 227 hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 229 - const struct hash_ip6_elem *ip2) 228 + const struct hash_ip6_elem *ip2, 229 + u32 *multi) 230 230 { 231 231 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0; 232 232 }
+4 -2
net/netfilter/ipset/ip_set_hash_ipport.c
··· 60 60 61 61 static inline bool 62 62 hash_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 66 return ip1->ip == ip2->ip && 66 67 ip1->port == ip2->port && ··· 277 276 278 277 static inline bool 279 278 hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 280 - const struct hash_ipport6_elem *ip2) 279 + const struct hash_ipport6_elem *ip2, 280 + u32 *multi) 281 281 { 282 282 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 283 283 ip1->port == ip2->port &&
+4 -2
net/netfilter/ipset/ip_set_hash_ipportip.c
··· 62 62 63 63 static inline bool 64 64 hash_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 68 return ip1->ip == ip2->ip && 68 69 ip1->ip2 == ip2->ip2 && ··· 287 286 288 287 static inline bool 289 288 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 290 - const struct hash_ipportip6_elem *ip2) 289 + const struct hash_ipportip6_elem *ip2, 290 + u32 *multi) 291 291 { 292 292 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 293 293 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
+4 -2
net/netfilter/ipset/ip_set_hash_ipportnet.c
··· 62 62 63 63 static inline bool 64 64 hash_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 68 return ip1->ip == ip2->ip && 68 69 ip1->ip2 == ip2->ip2 && ··· 336 335 337 336 static inline bool 338 337 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 339 - const struct hash_ipportnet6_elem *ip2) 338 + const struct hash_ipportnet6_elem *ip2, 339 + u32 *multi) 340 340 { 341 341 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 342 342 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
+4 -2
net/netfilter/ipset/ip_set_hash_net.c
··· 58 58 59 59 static inline bool 60 60 hash_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 64 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; 64 65 } ··· 250 249 251 250 static inline bool 252 251 hash_net6_data_equal(const struct hash_net6_elem *ip1, 253 - const struct hash_net6_elem *ip2) 252 + const struct hash_net6_elem *ip2, 253 + u32 *multi) 254 254 { 255 255 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 256 256 ip1->cidr == ip2->cidr;
+36 -12
net/netfilter/ipset/ip_set_hash_netiface.c
··· 99 99 100 100 while (n) { 101 101 const char *d = iface_data(n); 102 - int res = ifname_compare(*iface, d); 102 + long res = ifname_compare(*iface, d); 103 103 104 104 if (res < 0) 105 105 n = n->rb_left; ··· 121 121 122 122 while (*n) { 123 123 char *ifname = iface_data(*n); 124 - int res = ifname_compare(*iface, ifname); 124 + long res = ifname_compare(*iface, ifname); 125 125 126 126 p = *n; 127 127 if (res < 0) ··· 159 159 160 160 /* The type variant functions: IPv4 */ 161 161 162 - /* Member elements without timeout */ 163 - struct hash_netiface4_elem { 162 + struct hash_netiface4_elem_hashed { 164 163 __be32 ip; 165 - const char *iface; 166 164 u8 physdev; 167 165 u8 cidr; 168 166 u16 padding; 167 + }; 168 + 169 + #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) 170 + 171 + /* Member elements without timeout */ 172 + struct hash_netiface4_elem { 173 + __be32 ip; 174 + u8 physdev; 175 + u8 cidr; 176 + u16 padding; 177 + const char *iface; 169 178 }; 170 179 171 180 /* Member elements with timeout support */ 172 181 struct hash_netiface4_telem { 173 182 __be32 ip; 174 - const char *iface; 175 183 u8 physdev; 176 184 u8 cidr; 177 185 u16 padding; 186 + const char *iface; 178 187 unsigned long timeout; 179 188 }; 180 189 181 190 static inline bool 182 191 hash_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 195 return ip1->ip == ip2->ip && 186 196 ip1->cidr == ip2->cidr && 197 + (++*multi) && 187 198 ip1->physdev == ip2->physdev && 188 199 ip1->iface == ip2->iface; 189 200 } ··· 268 257 269 258 #define IP_SET_HASH_WITH_NETS 270 259 #define IP_SET_HASH_WITH_RBTREE 260 + #define IP_SET_HASH_WITH_MULTI 271 261 272 262 #define PF 4 273 263 #define HOST_MASK 32 ··· 436 424 437 425 /* The type variant functions: IPv6 */ 438 426 439 - struct hash_netiface6_elem { 427 + struct hash_netiface6_elem_hashed { 440 428 union nf_inet_addr ip; 441 - const char *iface; 442 429 u8 physdev; 443 430 u8 cidr; 444 431 u16 padding; 445 432 }; 446 433 447 - struct hash_netiface6_telem { 434 + #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) 435 + 436 + struct hash_netiface6_elem { 448 437 union nf_inet_addr ip; 449 - const char *iface; 450 438 u8 physdev; 451 439 u8 cidr; 452 440 u16 padding; 441 + const char *iface; 442 + }; 443 + 444 + struct hash_netiface6_telem { 445 + union nf_inet_addr ip; 446 + u8 physdev; 447 + u8 cidr; 448 + u16 padding; 449 + const char *iface; 453 450 unsigned long timeout; 454 451 }; 455 452 456 453 static inline bool 457 454 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 458 - const struct hash_netiface6_elem *ip2) 455 + const struct hash_netiface6_elem *ip2, 456 + u32 *multi) 459 457 { 460 458 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 461 459 ip1->cidr == ip2->cidr && 460 + (++*multi) && 462 461 ip1->physdev == ip2->physdev && 463 462 ip1->iface == ip2->iface; 464 463 } ··· 704 681 h->maxelem = maxelem; 705 682 get_random_bytes(&h->initval, sizeof(h->initval)); 706 683 h->timeout = IPSET_NO_TIMEOUT; 684 + h->ahash_max = AHASH_MAX_SIZE; 707 685 708 686 hbits = htable_bits(hashsize); 709 687 h->table = ip_set_alloc(
+4 -2
net/netfilter/ipset/ip_set_hash_netport.c
··· 59 59 60 60 static inline bool 61 61 hash_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 65 return ip1->ip == ip2->ip && 65 66 ip1->port == ip2->port && ··· 301 300 302 301 static inline bool 303 302 hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 304 - const struct hash_netport6_elem *ip2) 303 + const struct hash_netport6_elem *ip2, 304 + u32 *multi) 305 305 { 306 306 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 307 307 ip1->port == ip2->port &&
+30 -10
net/netfilter/nfnetlink.c
··· 37 37 38 38 static char __initdata nfversion[] = "0.30"; 39 39 40 - static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; 40 + static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT]; 41 41 static DEFINE_MUTEX(nfnl_mutex); 42 42 43 43 void nfnl_lock(void) ··· 59 59 nfnl_unlock(); 60 60 return -EBUSY; 61 61 } 62 - subsys_table[n->subsys_id] = n; 62 + rcu_assign_pointer(subsys_table[n->subsys_id], n); 63 63 nfnl_unlock(); 64 64 65 65 return 0; ··· 71 71 nfnl_lock(); 72 72 subsys_table[n->subsys_id] = NULL; 73 73 nfnl_unlock(); 74 - 74 + synchronize_rcu(); 75 75 return 0; 76 76 } 77 77 EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); ··· 83 83 if (subsys_id >= NFNL_SUBSYS_COUNT) 84 84 return NULL; 85 85 86 - return subsys_table[subsys_id]; 86 + return rcu_dereference(subsys_table[subsys_id]); 87 87 } 88 88 89 89 static inline const struct nfnl_callback * ··· 139 139 140 140 type = nlh->nlmsg_type; 141 141 replay: 142 + rcu_read_lock(); 142 143 ss = nfnetlink_get_subsys(type); 143 144 if (!ss) { 144 145 #ifdef CONFIG_MODULES 145 - nfnl_unlock(); 146 + rcu_read_unlock(); 146 147 request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); 147 - nfnl_lock(); 148 + rcu_read_lock(); 148 149 ss = nfnetlink_get_subsys(type); 149 150 if (!ss) 150 151 #endif 152 + { 153 + rcu_read_unlock(); 151 154 return -EINVAL; 155 + } 152 156 } 153 157 154 158 nc = nfnetlink_find_client(type, ss); 155 - if (!nc) 159 + if (!nc) { 160 + rcu_read_unlock(); 156 161 return -EINVAL; 162 + } 157 163 158 164 { 159 165 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); ··· 173 167 if (err < 0) 174 168 return err; 175 169 176 - err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda); 170 + if (nc->call_rcu) { 171 + err = nc->call_rcu(net->nfnl, skb, nlh, 172 + (const struct nlattr **)cda); 173 + rcu_read_unlock(); 174 + } else { 175 + rcu_read_unlock(); 176 + nfnl_lock(); 177 + if (rcu_dereference_protected( 178 + subsys_table[NFNL_SUBSYS_ID(type)], 179 + lockdep_is_held(&nfnl_mutex)) != ss || 180 + nfnetlink_find_client(type, ss) != nc) 181 + err = -EAGAIN; 182 + else 183 + err = nc->call(net->nfnl, skb, nlh, 184 + (const struct nlattr **)cda); 185 + nfnl_unlock(); 186 + } 177 187 if (err == -EAGAIN) 178 188 goto replay; 179 189 return err; ··· 198 176 199 177 static void nfnetlink_rcv(struct sk_buff *skb) 200 178 { 201 - nfnl_lock(); 202 179 netlink_rcv_skb(skb, &nfnetlink_rcv_msg); 203 - nfnl_unlock(); 204 180 } 205 181 206 182 static int __net_init nfnetlink_net_init(struct net *net)
+5
net/netfilter/xt_AUDIT.c
··· 163 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 171 audit_log_end(ab); 167 172 168 173 errout: