diff options
40 files changed, 699 insertions, 532 deletions
diff --git a/Documentation/networking/nf_conntrack-sysctl.txt b/Documentation/networking/nf_conntrack-sysctl.txt index f55599c62c9d..4fb51d32fccc 100644 --- a/Documentation/networking/nf_conntrack-sysctl.txt +++ b/Documentation/networking/nf_conntrack-sysctl.txt | |||
| @@ -7,12 +7,13 @@ nf_conntrack_acct - BOOLEAN | |||
| 7 | Enable connection tracking flow accounting. 64-bit byte and packet | 7 | Enable connection tracking flow accounting. 64-bit byte and packet |
| 8 | counters per flow are added. | 8 | counters per flow are added. |
| 9 | 9 | ||
| 10 | nf_conntrack_buckets - INTEGER (read-only) | 10 | nf_conntrack_buckets - INTEGER |
| 11 | Size of hash table. If not specified as parameter during module | 11 | Size of hash table. If not specified as parameter during module |
| 12 | loading, the default size is calculated by dividing total memory | 12 | loading, the default size is calculated by dividing total memory |
| 13 | by 16384 to determine the number of buckets but the hash table will | 13 | by 16384 to determine the number of buckets but the hash table will |
| 14 | never have fewer than 32 and limited to 16384 buckets. For systems | 14 | never have fewer than 32 and limited to 16384 buckets. For systems |
| 15 | with more than 4GB of memory it will be 65536 buckets. | 15 | with more than 4GB of memory it will be 65536 buckets. |
| 16 | This sysctl is only writeable in the initial net namespace. | ||
| 16 | 17 | ||
| 17 | nf_conntrack_checksum - BOOLEAN | 18 | nf_conntrack_checksum - BOOLEAN |
| 18 | 0 - disabled | 19 | 0 - disabled |
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 37ff4a6faa9a..6fec9e81bd70 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h | |||
| @@ -374,6 +374,29 @@ static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2) | |||
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | /** | 376 | /** |
| 377 | * ether_addr_equal_masked - Compare two Ethernet addresses with a mask | ||
| 378 | * @addr1: Pointer to a six-byte array containing the 1st Ethernet address | ||
| 379 | * @addr2: Pointer to a six-byte array containing the 2nd Ethernet address | ||
| 380 | * @mask: Pointer to a six-byte array containing the Ethernet address bitmask | ||
| 381 | * | ||
| 382 | * Compare two Ethernet addresses with a mask, returns true if for every bit | ||
| 383 | * set in the bitmask the equivalent bits in the ethernet addresses are equal. | ||
| 384 | * Using a mask with all bits set is a slower ether_addr_equal. | ||
| 385 | */ | ||
| 386 | static inline bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2, | ||
| 387 | const u8 *mask) | ||
| 388 | { | ||
| 389 | int i; | ||
| 390 | |||
| 391 | for (i = 0; i < ETH_ALEN; i++) { | ||
| 392 | if ((addr1[i] ^ addr2[i]) & mask[i]) | ||
| 393 | return false; | ||
| 394 | } | ||
| 395 | |||
| 396 | return true; | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 377 | * is_etherdev_addr - Tell if given Ethernet address belongs to the device. | 400 | * is_etherdev_addr - Tell if given Ethernet address belongs to the device. |
| 378 | * @dev: Pointer to a device structure | 401 | * @dev: Pointer to a device structure |
| 379 | * @addr: Pointer to a six-byte array containing the Ethernet address | 402 | * @addr: Pointer to a six-byte array containing the Ethernet address |
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index dc4f58a3cdcc..e94e81ab2b58 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | #include <linux/static_key.h> | 6 | #include <linux/static_key.h> |
| 7 | #include <uapi/linux/netfilter/x_tables.h> | 7 | #include <uapi/linux/netfilter/x_tables.h> |
| 8 | 8 | ||
| 9 | /* Test a struct->invflags and a boolean for inequality */ | ||
| 10 | #define NF_INVF(ptr, flag, boolean) \ | ||
| 11 | ((boolean) ^ !!((ptr)->invflags & (flag))) | ||
| 12 | |||
| 9 | /** | 13 | /** |
| 10 | * struct xt_action_param - parameters for matches/targets | 14 | * struct xt_action_param - parameters for matches/targets |
| 11 | * | 15 | * |
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 2ea517c7c6b9..984b2112c77b 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h | |||
| @@ -115,8 +115,6 @@ extern unsigned int ebt_do_table(struct sk_buff *skb, | |||
| 115 | const struct nf_hook_state *state, | 115 | const struct nf_hook_state *state, |
| 116 | struct ebt_table *table); | 116 | struct ebt_table *table); |
| 117 | 117 | ||
| 118 | /* Used in the kernel match() functions */ | ||
| 119 | #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) | ||
| 120 | /* True if the hook mask denotes that the rule is in a base chain, | 118 | /* True if the hook mask denotes that the rule is in a base chain, |
| 121 | * used in the check() functions */ | 119 | * used in the check() functions */ |
| 122 | #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS)) | 120 | #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS)) |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index dd78bea227c8..5d3397f34583 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
| @@ -85,6 +85,9 @@ struct nf_conn { | |||
| 85 | spinlock_t lock; | 85 | spinlock_t lock; |
| 86 | u16 cpu; | 86 | u16 cpu; |
| 87 | 87 | ||
| 88 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 89 | struct nf_conntrack_zone zone; | ||
| 90 | #endif | ||
| 88 | /* XXX should I move this to the tail ? - Y.K */ | 91 | /* XXX should I move this to the tail ? - Y.K */ |
| 89 | /* These are my tuples; original and reply */ | 92 | /* These are my tuples; original and reply */ |
| 90 | struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; | 93 | struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; |
| @@ -287,6 +290,7 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) | |||
| 287 | struct kernel_param; | 290 | struct kernel_param; |
| 288 | 291 | ||
| 289 | int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); | 292 | int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); |
| 293 | int nf_conntrack_hash_resize(unsigned int hashsize); | ||
| 290 | extern unsigned int nf_conntrack_htable_size; | 294 | extern unsigned int nf_conntrack_htable_size; |
| 291 | extern unsigned int nf_conntrack_max; | 295 | extern unsigned int nf_conntrack_max; |
| 292 | 296 | ||
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 55d15049ab2f..b925395fa5ed 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h | |||
| @@ -15,9 +15,6 @@ enum nf_ct_ext_id { | |||
| 15 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 15 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
| 16 | NF_CT_EXT_ECACHE, | 16 | NF_CT_EXT_ECACHE, |
| 17 | #endif | 17 | #endif |
| 18 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 19 | NF_CT_EXT_ZONE, | ||
| 20 | #endif | ||
| 21 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | 18 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP |
| 22 | NF_CT_EXT_TSTAMP, | 19 | NF_CT_EXT_TSTAMP, |
| 23 | #endif | 20 | #endif |
| @@ -38,7 +35,6 @@ enum nf_ct_ext_id { | |||
| 38 | #define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj | 35 | #define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj |
| 39 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct | 36 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct |
| 40 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache | 37 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache |
| 41 | #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone | ||
| 42 | #define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp | 38 | #define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp |
| 43 | #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout | 39 | #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout |
| 44 | #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels | 40 | #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels |
diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h index 4e32512cef32..64a718b60839 100644 --- a/include/net/netfilter/nf_conntrack_zones.h +++ b/include/net/netfilter/nf_conntrack_zones.h | |||
| @@ -9,12 +9,11 @@ | |||
| 9 | static inline const struct nf_conntrack_zone * | 9 | static inline const struct nf_conntrack_zone * |
| 10 | nf_ct_zone(const struct nf_conn *ct) | 10 | nf_ct_zone(const struct nf_conn *ct) |
| 11 | { | 11 | { |
| 12 | const struct nf_conntrack_zone *nf_ct_zone = NULL; | ||
| 13 | |||
| 14 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 12 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 15 | nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE); | 13 | return &ct->zone; |
| 14 | #else | ||
| 15 | return &nf_ct_zone_dflt; | ||
| 16 | #endif | 16 | #endif |
| 17 | return nf_ct_zone ? nf_ct_zone : &nf_ct_zone_dflt; | ||
| 18 | } | 17 | } |
| 19 | 18 | ||
| 20 | static inline const struct nf_conntrack_zone * | 19 | static inline const struct nf_conntrack_zone * |
| @@ -31,32 +30,22 @@ static inline const struct nf_conntrack_zone * | |||
| 31 | nf_ct_zone_tmpl(const struct nf_conn *tmpl, const struct sk_buff *skb, | 30 | nf_ct_zone_tmpl(const struct nf_conn *tmpl, const struct sk_buff *skb, |
| 32 | struct nf_conntrack_zone *tmp) | 31 | struct nf_conntrack_zone *tmp) |
| 33 | { | 32 | { |
| 34 | const struct nf_conntrack_zone *zone; | 33 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 35 | |||
| 36 | if (!tmpl) | 34 | if (!tmpl) |
| 37 | return &nf_ct_zone_dflt; | 35 | return &nf_ct_zone_dflt; |
| 38 | 36 | ||
| 39 | zone = nf_ct_zone(tmpl); | 37 | if (tmpl->zone.flags & NF_CT_FLAG_MARK) |
| 40 | if (zone->flags & NF_CT_FLAG_MARK) | 38 | return nf_ct_zone_init(tmp, skb->mark, tmpl->zone.dir, 0); |
| 41 | zone = nf_ct_zone_init(tmp, skb->mark, zone->dir, 0); | 39 | #endif |
| 42 | 40 | return nf_ct_zone(tmpl); | |
| 43 | return zone; | ||
| 44 | } | 41 | } |
| 45 | 42 | ||
| 46 | static inline int nf_ct_zone_add(struct nf_conn *ct, gfp_t flags, | 43 | static inline void nf_ct_zone_add(struct nf_conn *ct, |
| 47 | const struct nf_conntrack_zone *info) | 44 | const struct nf_conntrack_zone *zone) |
| 48 | { | 45 | { |
| 49 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 46 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 50 | struct nf_conntrack_zone *nf_ct_zone; | 47 | ct->zone = *zone; |
| 51 | |||
| 52 | nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, flags); | ||
| 53 | if (!nf_ct_zone) | ||
| 54 | return -ENOMEM; | ||
| 55 | |||
| 56 | nf_ct_zone_init(nf_ct_zone, info->id, info->dir, | ||
| 57 | info->flags); | ||
| 58 | #endif | 48 | #endif |
| 59 | return 0; | ||
| 60 | } | 49 | } |
| 61 | 50 | ||
| 62 | static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone, | 51 | static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone, |
| @@ -68,22 +57,34 @@ static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone, | |||
| 68 | static inline u16 nf_ct_zone_id(const struct nf_conntrack_zone *zone, | 57 | static inline u16 nf_ct_zone_id(const struct nf_conntrack_zone *zone, |
| 69 | enum ip_conntrack_dir dir) | 58 | enum ip_conntrack_dir dir) |
| 70 | { | 59 | { |
| 60 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 71 | return nf_ct_zone_matches_dir(zone, dir) ? | 61 | return nf_ct_zone_matches_dir(zone, dir) ? |
| 72 | zone->id : NF_CT_DEFAULT_ZONE_ID; | 62 | zone->id : NF_CT_DEFAULT_ZONE_ID; |
| 63 | #else | ||
| 64 | return NF_CT_DEFAULT_ZONE_ID; | ||
| 65 | #endif | ||
| 73 | } | 66 | } |
| 74 | 67 | ||
| 75 | static inline bool nf_ct_zone_equal(const struct nf_conn *a, | 68 | static inline bool nf_ct_zone_equal(const struct nf_conn *a, |
| 76 | const struct nf_conntrack_zone *b, | 69 | const struct nf_conntrack_zone *b, |
| 77 | enum ip_conntrack_dir dir) | 70 | enum ip_conntrack_dir dir) |
| 78 | { | 71 | { |
| 72 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 79 | return nf_ct_zone_id(nf_ct_zone(a), dir) == | 73 | return nf_ct_zone_id(nf_ct_zone(a), dir) == |
| 80 | nf_ct_zone_id(b, dir); | 74 | nf_ct_zone_id(b, dir); |
| 75 | #else | ||
| 76 | return true; | ||
| 77 | #endif | ||
| 81 | } | 78 | } |
| 82 | 79 | ||
| 83 | static inline bool nf_ct_zone_equal_any(const struct nf_conn *a, | 80 | static inline bool nf_ct_zone_equal_any(const struct nf_conn *a, |
| 84 | const struct nf_conntrack_zone *b) | 81 | const struct nf_conntrack_zone *b) |
| 85 | { | 82 | { |
| 83 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 86 | return nf_ct_zone(a)->id == b->id; | 84 | return nf_ct_zone(a)->id == b->id; |
| 85 | #else | ||
| 86 | return true; | ||
| 87 | #endif | ||
| 87 | } | 88 | } |
| 88 | #endif /* IS_ENABLED(CONFIG_NF_CONNTRACK) */ | 89 | #endif /* IS_ENABLED(CONFIG_NF_CONNTRACK) */ |
| 89 | #endif /* _NF_CONNTRACK_ZONES_H */ | 90 | #endif /* _NF_CONNTRACK_ZONES_H */ |
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index 57639fca223a..83d855ba6af1 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h | |||
| @@ -12,6 +12,9 @@ | |||
| 12 | #define NF_LOG_UID 0x08 /* Log UID owning local socket */ | 12 | #define NF_LOG_UID 0x08 /* Log UID owning local socket */ |
| 13 | #define NF_LOG_MASK 0x0f | 13 | #define NF_LOG_MASK 0x0f |
| 14 | 14 | ||
| 15 | /* This flag indicates that copy_len field in nf_loginfo is set */ | ||
| 16 | #define NF_LOG_F_COPY_LEN 0x1 | ||
| 17 | |||
| 15 | enum nf_log_type { | 18 | enum nf_log_type { |
| 16 | NF_LOG_TYPE_LOG = 0, | 19 | NF_LOG_TYPE_LOG = 0, |
| 17 | NF_LOG_TYPE_ULOG, | 20 | NF_LOG_TYPE_ULOG, |
| @@ -22,9 +25,13 @@ struct nf_loginfo { | |||
| 22 | u_int8_t type; | 25 | u_int8_t type; |
| 23 | union { | 26 | union { |
| 24 | struct { | 27 | struct { |
| 28 | /* copy_len will be used iff you set | ||
| 29 | * NF_LOG_F_COPY_LEN in flags | ||
| 30 | */ | ||
| 25 | u_int32_t copy_len; | 31 | u_int32_t copy_len; |
| 26 | u_int16_t group; | 32 | u_int16_t group; |
| 27 | u_int16_t qthreshold; | 33 | u_int16_t qthreshold; |
| 34 | u_int16_t flags; | ||
| 28 | } ulog; | 35 | } ulog; |
| 29 | struct { | 36 | struct { |
| 30 | u_int8_t level; | 37 | u_int8_t level; |
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index f7c291ff4074..30c1d9489ae2 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
| @@ -297,6 +297,7 @@ void nft_unregister_set(struct nft_set_ops *ops); | |||
| 297 | * @ops: set ops | 297 | * @ops: set ops |
| 298 | * @pnet: network namespace | 298 | * @pnet: network namespace |
| 299 | * @flags: set flags | 299 | * @flags: set flags |
| 300 | * @genmask: generation mask | ||
| 300 | * @klen: key length | 301 | * @klen: key length |
| 301 | * @dlen: data length | 302 | * @dlen: data length |
| 302 | * @data: private set data | 303 | * @data: private set data |
| @@ -318,7 +319,8 @@ struct nft_set { | |||
| 318 | /* runtime data below here */ | 319 | /* runtime data below here */ |
| 319 | const struct nft_set_ops *ops ____cacheline_aligned; | 320 | const struct nft_set_ops *ops ____cacheline_aligned; |
| 320 | possible_net_t pnet; | 321 | possible_net_t pnet; |
| 321 | u16 flags; | 322 | u16 flags:14, |
| 323 | genmask:2; | ||
| 322 | u8 klen; | 324 | u8 klen; |
| 323 | u8 dlen; | 325 | u8 dlen; |
| 324 | unsigned char data[] | 326 | unsigned char data[] |
| @@ -336,9 +338,9 @@ static inline struct nft_set *nft_set_container_of(const void *priv) | |||
| 336 | } | 338 | } |
| 337 | 339 | ||
| 338 | struct nft_set *nf_tables_set_lookup(const struct nft_table *table, | 340 | struct nft_set *nf_tables_set_lookup(const struct nft_table *table, |
| 339 | const struct nlattr *nla); | 341 | const struct nlattr *nla, u8 genmask); |
| 340 | struct nft_set *nf_tables_set_lookup_byid(const struct net *net, | 342 | struct nft_set *nf_tables_set_lookup_byid(const struct net *net, |
| 341 | const struct nlattr *nla); | 343 | const struct nlattr *nla, u8 genmask); |
| 342 | 344 | ||
| 343 | static inline unsigned long nft_set_gc_interval(const struct nft_set *set) | 345 | static inline unsigned long nft_set_gc_interval(const struct nft_set *set) |
| 344 | { | 346 | { |
| @@ -733,7 +735,6 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule) | |||
| 733 | 735 | ||
| 734 | enum nft_chain_flags { | 736 | enum nft_chain_flags { |
| 735 | NFT_BASE_CHAIN = 0x1, | 737 | NFT_BASE_CHAIN = 0x1, |
| 736 | NFT_CHAIN_INACTIVE = 0x2, | ||
| 737 | }; | 738 | }; |
| 738 | 739 | ||
| 739 | /** | 740 | /** |
| @@ -755,7 +756,8 @@ struct nft_chain { | |||
| 755 | u64 handle; | 756 | u64 handle; |
| 756 | u32 use; | 757 | u32 use; |
| 757 | u16 level; | 758 | u16 level; |
| 758 | u8 flags; | 759 | u8 flags:6, |
| 760 | genmask:2; | ||
| 759 | char name[NFT_CHAIN_MAXNAMELEN]; | 761 | char name[NFT_CHAIN_MAXNAMELEN]; |
| 760 | }; | 762 | }; |
| 761 | 763 | ||
| @@ -797,7 +799,6 @@ struct nft_stats { | |||
| 797 | }; | 799 | }; |
| 798 | 800 | ||
| 799 | #define NFT_HOOK_OPS_MAX 2 | 801 | #define NFT_HOOK_OPS_MAX 2 |
| 800 | #define NFT_BASECHAIN_DISABLED (1 << 0) | ||
| 801 | 802 | ||
| 802 | /** | 803 | /** |
| 803 | * struct nft_base_chain - nf_tables base chain | 804 | * struct nft_base_chain - nf_tables base chain |
| @@ -839,6 +840,7 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv); | |||
| 839 | * @hgenerator: handle generator state | 840 | * @hgenerator: handle generator state |
| 840 | * @use: number of chain references to this table | 841 | * @use: number of chain references to this table |
| 841 | * @flags: table flag (see enum nft_table_flags) | 842 | * @flags: table flag (see enum nft_table_flags) |
| 843 | * @genmask: generation mask | ||
| 842 | * @name: name of the table | 844 | * @name: name of the table |
| 843 | */ | 845 | */ |
| 844 | struct nft_table { | 846 | struct nft_table { |
| @@ -847,7 +849,8 @@ struct nft_table { | |||
| 847 | struct list_head sets; | 849 | struct list_head sets; |
| 848 | u64 hgenerator; | 850 | u64 hgenerator; |
| 849 | u32 use; | 851 | u32 use; |
| 850 | u16 flags; | 852 | u16 flags:14, |
| 853 | genmask:2; | ||
| 851 | char name[NFT_TABLE_MAXNAMELEN]; | 854 | char name[NFT_TABLE_MAXNAMELEN]; |
| 852 | }; | 855 | }; |
| 853 | 856 | ||
| @@ -971,6 +974,32 @@ static inline u8 nft_genmask_cur(const struct net *net) | |||
| 971 | #define NFT_GENMASK_ANY ((1 << 0) | (1 << 1)) | 974 | #define NFT_GENMASK_ANY ((1 << 0) | (1 << 1)) |
| 972 | 975 | ||
| 973 | /* | 976 | /* |
| 977 | * Generic transaction helpers | ||
| 978 | */ | ||
| 979 | |||
| 980 | /* Check if this object is currently active. */ | ||
| 981 | #define nft_is_active(__net, __obj) \ | ||
| 982 | (((__obj)->genmask & nft_genmask_cur(__net)) == 0) | ||
| 983 | |||
| 984 | /* Check if this object is active in the next generation. */ | ||
| 985 | #define nft_is_active_next(__net, __obj) \ | ||
| 986 | (((__obj)->genmask & nft_genmask_next(__net)) == 0) | ||
| 987 | |||
| 988 | /* This object becomes active in the next generation. */ | ||
| 989 | #define nft_activate_next(__net, __obj) \ | ||
| 990 | (__obj)->genmask = nft_genmask_cur(__net) | ||
| 991 | |||
| 992 | /* This object becomes inactive in the next generation. */ | ||
| 993 | #define nft_deactivate_next(__net, __obj) \ | ||
| 994 | (__obj)->genmask = nft_genmask_next(__net) | ||
| 995 | |||
| 996 | /* After committing the ruleset, clear the stale generation bit. */ | ||
| 997 | #define nft_clear(__net, __obj) \ | ||
| 998 | (__obj)->genmask &= ~nft_genmask_next(__net) | ||
| 999 | #define nft_active_genmask(__obj, __genmask) \ | ||
| 1000 | !((__obj)->genmask & __genmask) | ||
| 1001 | |||
| 1002 | /* | ||
| 974 | * Set element transaction helpers | 1003 | * Set element transaction helpers |
| 975 | */ | 1004 | */ |
| 976 | 1005 | ||
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 6a4dbe04f09e..01751faccaf8 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h | |||
| @@ -546,6 +546,10 @@ enum nft_cmp_attributes { | |||
| 546 | }; | 546 | }; |
| 547 | #define NFTA_CMP_MAX (__NFTA_CMP_MAX - 1) | 547 | #define NFTA_CMP_MAX (__NFTA_CMP_MAX - 1) |
| 548 | 548 | ||
| 549 | enum nft_lookup_flags { | ||
| 550 | NFT_LOOKUP_F_INV = (1 << 0), | ||
| 551 | }; | ||
| 552 | |||
| 549 | /** | 553 | /** |
| 550 | * enum nft_lookup_attributes - nf_tables set lookup expression netlink attributes | 554 | * enum nft_lookup_attributes - nf_tables set lookup expression netlink attributes |
| 551 | * | 555 | * |
| @@ -553,6 +557,7 @@ enum nft_cmp_attributes { | |||
| 553 | * @NFTA_LOOKUP_SREG: source register of the data to look for (NLA_U32: nft_registers) | 557 | * @NFTA_LOOKUP_SREG: source register of the data to look for (NLA_U32: nft_registers) |
| 554 | * @NFTA_LOOKUP_DREG: destination register (NLA_U32: nft_registers) | 558 | * @NFTA_LOOKUP_DREG: destination register (NLA_U32: nft_registers) |
| 555 | * @NFTA_LOOKUP_SET_ID: uniquely identifies a set in a transaction (NLA_U32) | 559 | * @NFTA_LOOKUP_SET_ID: uniquely identifies a set in a transaction (NLA_U32) |
| 560 | * @NFTA_LOOKUP_FLAGS: flags (NLA_U32: enum nft_lookup_flags) | ||
| 556 | */ | 561 | */ |
| 557 | enum nft_lookup_attributes { | 562 | enum nft_lookup_attributes { |
| 558 | NFTA_LOOKUP_UNSPEC, | 563 | NFTA_LOOKUP_UNSPEC, |
| @@ -560,6 +565,7 @@ enum nft_lookup_attributes { | |||
| 560 | NFTA_LOOKUP_SREG, | 565 | NFTA_LOOKUP_SREG, |
| 561 | NFTA_LOOKUP_DREG, | 566 | NFTA_LOOKUP_DREG, |
| 562 | NFTA_LOOKUP_SET_ID, | 567 | NFTA_LOOKUP_SET_ID, |
| 568 | NFTA_LOOKUP_FLAGS, | ||
| 563 | __NFTA_LOOKUP_MAX | 569 | __NFTA_LOOKUP_MAX |
| 564 | }; | 570 | }; |
| 565 | #define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1) | 571 | #define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1) |
diff --git a/include/uapi/linux/netfilter/xt_NFLOG.h b/include/uapi/linux/netfilter/xt_NFLOG.h index 87b58311ce6b..f33070730fc8 100644 --- a/include/uapi/linux/netfilter/xt_NFLOG.h +++ b/include/uapi/linux/netfilter/xt_NFLOG.h | |||
| @@ -6,9 +6,13 @@ | |||
| 6 | #define XT_NFLOG_DEFAULT_GROUP 0x1 | 6 | #define XT_NFLOG_DEFAULT_GROUP 0x1 |
| 7 | #define XT_NFLOG_DEFAULT_THRESHOLD 0 | 7 | #define XT_NFLOG_DEFAULT_THRESHOLD 0 |
| 8 | 8 | ||
| 9 | #define XT_NFLOG_MASK 0x0 | 9 | #define XT_NFLOG_MASK 0x1 |
| 10 | |||
| 11 | /* This flag indicates that 'len' field in xt_nflog_info is set*/ | ||
| 12 | #define XT_NFLOG_F_COPY_LEN 0x1 | ||
| 10 | 13 | ||
| 11 | struct xt_nflog_info { | 14 | struct xt_nflog_info { |
| 15 | /* 'len' will be used iff you set XT_NFLOG_F_COPY_LEN in flags */ | ||
| 12 | __u32 len; | 16 | __u32 len; |
| 13 | __u16 group; | 17 | __u16 group; |
| 14 | __u16 threshold; | 18 | __u16 threshold; |
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c index 2a449b7ab8fa..5fc4affd9fdb 100644 --- a/net/bridge/netfilter/ebt_802_3.c +++ b/net/bridge/netfilter/ebt_802_3.c | |||
| @@ -20,16 +20,16 @@ ebt_802_3_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 20 | __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; | 20 | __be16 type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type; |
| 21 | 21 | ||
| 22 | if (info->bitmask & EBT_802_3_SAP) { | 22 | if (info->bitmask & EBT_802_3_SAP) { |
| 23 | if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP)) | 23 | if (NF_INVF(info, EBT_802_3_SAP, info->sap != hdr->llc.ui.ssap)) |
| 24 | return false; | 24 | return false; |
| 25 | if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP)) | 25 | if (NF_INVF(info, EBT_802_3_SAP, info->sap != hdr->llc.ui.dsap)) |
| 26 | return false; | 26 | return false; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | if (info->bitmask & EBT_802_3_TYPE) { | 29 | if (info->bitmask & EBT_802_3_TYPE) { |
| 30 | if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE)) | 30 | if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE)) |
| 31 | return false; | 31 | return false; |
| 32 | if (FWINV(info->type != type, EBT_802_3_TYPE)) | 32 | if (NF_INVF(info, EBT_802_3_TYPE, info->type != type)) |
| 33 | return false; | 33 | return false; |
| 34 | } | 34 | } |
| 35 | 35 | ||
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index cd457b891b27..227142282b45 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c | |||
| @@ -25,14 +25,14 @@ ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 25 | ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); | 25 | ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); |
| 26 | if (ah == NULL) | 26 | if (ah == NULL) |
| 27 | return false; | 27 | return false; |
| 28 | if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode != | 28 | if ((info->bitmask & EBT_ARP_OPCODE) && |
| 29 | ah->ar_op, EBT_ARP_OPCODE)) | 29 | NF_INVF(info, EBT_ARP_OPCODE, info->opcode != ah->ar_op)) |
| 30 | return false; | 30 | return false; |
| 31 | if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype != | 31 | if ((info->bitmask & EBT_ARP_HTYPE) && |
| 32 | ah->ar_hrd, EBT_ARP_HTYPE)) | 32 | NF_INVF(info, EBT_ARP_HTYPE, info->htype != ah->ar_hrd)) |
| 33 | return false; | 33 | return false; |
| 34 | if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype != | 34 | if ((info->bitmask & EBT_ARP_PTYPE) && |
| 35 | ah->ar_pro, EBT_ARP_PTYPE)) | 35 | NF_INVF(info, EBT_ARP_PTYPE, info->ptype != ah->ar_pro)) |
| 36 | return false; | 36 | return false; |
| 37 | 37 | ||
| 38 | if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { | 38 | if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { |
| @@ -51,21 +51,22 @@ ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 51 | sizeof(daddr), &daddr); | 51 | sizeof(daddr), &daddr); |
| 52 | if (dap == NULL) | 52 | if (dap == NULL) |
| 53 | return false; | 53 | return false; |
| 54 | if (info->bitmask & EBT_ARP_SRC_IP && | 54 | if ((info->bitmask & EBT_ARP_SRC_IP) && |
| 55 | FWINV(info->saddr != (*sap & info->smsk), EBT_ARP_SRC_IP)) | 55 | NF_INVF(info, EBT_ARP_SRC_IP, |
| 56 | info->saddr != (*sap & info->smsk))) | ||
| 56 | return false; | 57 | return false; |
| 57 | if (info->bitmask & EBT_ARP_DST_IP && | 58 | if ((info->bitmask & EBT_ARP_DST_IP) && |
| 58 | FWINV(info->daddr != (*dap & info->dmsk), EBT_ARP_DST_IP)) | 59 | NF_INVF(info, EBT_ARP_DST_IP, |
| 60 | info->daddr != (*dap & info->dmsk))) | ||
| 59 | return false; | 61 | return false; |
| 60 | if (info->bitmask & EBT_ARP_GRAT && | 62 | if ((info->bitmask & EBT_ARP_GRAT) && |
| 61 | FWINV(*dap != *sap, EBT_ARP_GRAT)) | 63 | NF_INVF(info, EBT_ARP_GRAT, *dap != *sap)) |
| 62 | return false; | 64 | return false; |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { | 67 | if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) { |
| 66 | const unsigned char *mp; | 68 | const unsigned char *mp; |
| 67 | unsigned char _mac[ETH_ALEN]; | 69 | unsigned char _mac[ETH_ALEN]; |
| 68 | uint8_t verdict, i; | ||
| 69 | 70 | ||
| 70 | if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) | 71 | if (ah->ar_hln != ETH_ALEN || ah->ar_hrd != htons(ARPHRD_ETHER)) |
| 71 | return false; | 72 | return false; |
| @@ -74,11 +75,9 @@ ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 74 | sizeof(_mac), &_mac); | 75 | sizeof(_mac), &_mac); |
| 75 | if (mp == NULL) | 76 | if (mp == NULL) |
| 76 | return false; | 77 | return false; |
| 77 | verdict = 0; | 78 | if (NF_INVF(info, EBT_ARP_SRC_MAC, |
| 78 | for (i = 0; i < 6; i++) | 79 | !ether_addr_equal_masked(mp, info->smaddr, |
| 79 | verdict |= (mp[i] ^ info->smaddr[i]) & | 80 | info->smmsk))) |
| 80 | info->smmsk[i]; | ||
| 81 | if (FWINV(verdict != 0, EBT_ARP_SRC_MAC)) | ||
| 82 | return false; | 81 | return false; |
| 83 | } | 82 | } |
| 84 | 83 | ||
| @@ -88,11 +87,9 @@ ebt_arp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 88 | sizeof(_mac), &_mac); | 87 | sizeof(_mac), &_mac); |
| 89 | if (mp == NULL) | 88 | if (mp == NULL) |
| 90 | return false; | 89 | return false; |
| 91 | verdict = 0; | 90 | if (NF_INVF(info, EBT_ARP_DST_MAC, |
| 92 | for (i = 0; i < 6; i++) | 91 | !ether_addr_equal_masked(mp, info->dmaddr, |
| 93 | verdict |= (mp[i] ^ info->dmaddr[i]) & | 92 | info->dmmsk))) |
| 94 | info->dmmsk[i]; | ||
| 95 | if (FWINV(verdict != 0, EBT_ARP_DST_MAC)) | ||
| 96 | return false; | 93 | return false; |
| 97 | } | 94 | } |
| 98 | } | 95 | } |
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index 23bca62d58d2..d06968bdf5ec 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c | |||
| @@ -36,19 +36,19 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 36 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); | 36 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); |
| 37 | if (ih == NULL) | 37 | if (ih == NULL) |
| 38 | return false; | 38 | return false; |
| 39 | if (info->bitmask & EBT_IP_TOS && | 39 | if ((info->bitmask & EBT_IP_TOS) && |
| 40 | FWINV(info->tos != ih->tos, EBT_IP_TOS)) | 40 | NF_INVF(info, EBT_IP_TOS, info->tos != ih->tos)) |
| 41 | return false; | 41 | return false; |
| 42 | if (info->bitmask & EBT_IP_SOURCE && | 42 | if ((info->bitmask & EBT_IP_SOURCE) && |
| 43 | FWINV((ih->saddr & info->smsk) != | 43 | NF_INVF(info, EBT_IP_SOURCE, |
| 44 | info->saddr, EBT_IP_SOURCE)) | 44 | (ih->saddr & info->smsk) != info->saddr)) |
| 45 | return false; | 45 | return false; |
| 46 | if ((info->bitmask & EBT_IP_DEST) && | 46 | if ((info->bitmask & EBT_IP_DEST) && |
| 47 | FWINV((ih->daddr & info->dmsk) != | 47 | NF_INVF(info, EBT_IP_DEST, |
| 48 | info->daddr, EBT_IP_DEST)) | 48 | (ih->daddr & info->dmsk) != info->daddr)) |
| 49 | return false; | 49 | return false; |
| 50 | if (info->bitmask & EBT_IP_PROTO) { | 50 | if (info->bitmask & EBT_IP_PROTO) { |
| 51 | if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) | 51 | if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol)) |
| 52 | return false; | 52 | return false; |
| 53 | if (!(info->bitmask & EBT_IP_DPORT) && | 53 | if (!(info->bitmask & EBT_IP_DPORT) && |
| 54 | !(info->bitmask & EBT_IP_SPORT)) | 54 | !(info->bitmask & EBT_IP_SPORT)) |
| @@ -61,16 +61,16 @@ ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 61 | return false; | 61 | return false; |
| 62 | if (info->bitmask & EBT_IP_DPORT) { | 62 | if (info->bitmask & EBT_IP_DPORT) { |
| 63 | u32 dst = ntohs(pptr->dst); | 63 | u32 dst = ntohs(pptr->dst); |
| 64 | if (FWINV(dst < info->dport[0] || | 64 | if (NF_INVF(info, EBT_IP_DPORT, |
| 65 | dst > info->dport[1], | 65 | dst < info->dport[0] || |
| 66 | EBT_IP_DPORT)) | 66 | dst > info->dport[1])) |
| 67 | return false; | 67 | return false; |
| 68 | } | 68 | } |
| 69 | if (info->bitmask & EBT_IP_SPORT) { | 69 | if (info->bitmask & EBT_IP_SPORT) { |
| 70 | u32 src = ntohs(pptr->src); | 70 | u32 src = ntohs(pptr->src); |
| 71 | if (FWINV(src < info->sport[0] || | 71 | if (NF_INVF(info, EBT_IP_SPORT, |
| 72 | src > info->sport[1], | 72 | src < info->sport[0] || |
| 73 | EBT_IP_SPORT)) | 73 | src > info->sport[1])) |
| 74 | return false; | 74 | return false; |
| 75 | } | 75 | } |
| 76 | } | 76 | } |
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index 98de6e7fd86d..4617491be41e 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c | |||
| @@ -45,15 +45,18 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 45 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); | 45 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); |
| 46 | if (ih6 == NULL) | 46 | if (ih6 == NULL) |
| 47 | return false; | 47 | return false; |
| 48 | if (info->bitmask & EBT_IP6_TCLASS && | 48 | if ((info->bitmask & EBT_IP6_TCLASS) && |
| 49 | FWINV(info->tclass != ipv6_get_dsfield(ih6), EBT_IP6_TCLASS)) | 49 | NF_INVF(info, EBT_IP6_TCLASS, |
| 50 | info->tclass != ipv6_get_dsfield(ih6))) | ||
| 50 | return false; | 51 | return false; |
| 51 | if ((info->bitmask & EBT_IP6_SOURCE && | 52 | if (((info->bitmask & EBT_IP6_SOURCE) && |
| 52 | FWINV(ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk, | 53 | NF_INVF(info, EBT_IP6_SOURCE, |
| 53 | &info->saddr), EBT_IP6_SOURCE)) || | 54 | ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk, |
| 54 | (info->bitmask & EBT_IP6_DEST && | 55 | &info->saddr))) || |
| 55 | FWINV(ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, | 56 | ((info->bitmask & EBT_IP6_DEST) && |
| 56 | &info->daddr), EBT_IP6_DEST))) | 57 | NF_INVF(info, EBT_IP6_DEST, |
| 58 | ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, | ||
| 59 | &info->daddr)))) | ||
| 57 | return false; | 60 | return false; |
| 58 | if (info->bitmask & EBT_IP6_PROTO) { | 61 | if (info->bitmask & EBT_IP6_PROTO) { |
| 59 | uint8_t nexthdr = ih6->nexthdr; | 62 | uint8_t nexthdr = ih6->nexthdr; |
| @@ -63,7 +66,7 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 63 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off); | 66 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off); |
| 64 | if (offset_ph == -1) | 67 | if (offset_ph == -1) |
| 65 | return false; | 68 | return false; |
| 66 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) | 69 | if (NF_INVF(info, EBT_IP6_PROTO, info->protocol != nexthdr)) |
| 67 | return false; | 70 | return false; |
| 68 | if (!(info->bitmask & (EBT_IP6_DPORT | | 71 | if (!(info->bitmask & (EBT_IP6_DPORT | |
| 69 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) | 72 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) |
| @@ -76,22 +79,24 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 76 | return false; | 79 | return false; |
| 77 | if (info->bitmask & EBT_IP6_DPORT) { | 80 | if (info->bitmask & EBT_IP6_DPORT) { |
| 78 | u16 dst = ntohs(pptr->tcpudphdr.dst); | 81 | u16 dst = ntohs(pptr->tcpudphdr.dst); |
| 79 | if (FWINV(dst < info->dport[0] || | 82 | if (NF_INVF(info, EBT_IP6_DPORT, |
| 80 | dst > info->dport[1], EBT_IP6_DPORT)) | 83 | dst < info->dport[0] || |
| 84 | dst > info->dport[1])) | ||
| 81 | return false; | 85 | return false; |
| 82 | } | 86 | } |
| 83 | if (info->bitmask & EBT_IP6_SPORT) { | 87 | if (info->bitmask & EBT_IP6_SPORT) { |
| 84 | u16 src = ntohs(pptr->tcpudphdr.src); | 88 | u16 src = ntohs(pptr->tcpudphdr.src); |
| 85 | if (FWINV(src < info->sport[0] || | 89 | if (NF_INVF(info, EBT_IP6_SPORT, |
| 86 | src > info->sport[1], EBT_IP6_SPORT)) | 90 | src < info->sport[0] || |
| 91 | src > info->sport[1])) | ||
| 87 | return false; | 92 | return false; |
| 88 | } | 93 | } |
| 89 | if ((info->bitmask & EBT_IP6_ICMP6) && | 94 | if ((info->bitmask & EBT_IP6_ICMP6) && |
| 90 | FWINV(pptr->icmphdr.type < info->icmpv6_type[0] || | 95 | NF_INVF(info, EBT_IP6_ICMP6, |
| 91 | pptr->icmphdr.type > info->icmpv6_type[1] || | 96 | pptr->icmphdr.type < info->icmpv6_type[0] || |
| 92 | pptr->icmphdr.code < info->icmpv6_code[0] || | 97 | pptr->icmphdr.type > info->icmpv6_type[1] || |
| 93 | pptr->icmphdr.code > info->icmpv6_code[1], | 98 | pptr->icmphdr.code < info->icmpv6_code[0] || |
| 94 | EBT_IP6_ICMP6)) | 99 | pptr->icmphdr.code > info->icmpv6_code[1])) |
| 95 | return false; | 100 | return false; |
| 96 | } | 101 | } |
| 97 | return true; | 102 | return true; |
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 6b731e12ecfa..3140eb912d7e 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c | |||
| @@ -17,24 +17,24 @@ | |||
| 17 | #define BPDU_TYPE_TCN 0x80 | 17 | #define BPDU_TYPE_TCN 0x80 |
| 18 | 18 | ||
| 19 | struct stp_header { | 19 | struct stp_header { |
| 20 | uint8_t dsap; | 20 | u8 dsap; |
| 21 | uint8_t ssap; | 21 | u8 ssap; |
| 22 | uint8_t ctrl; | 22 | u8 ctrl; |
| 23 | uint8_t pid; | 23 | u8 pid; |
| 24 | uint8_t vers; | 24 | u8 vers; |
| 25 | uint8_t type; | 25 | u8 type; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | struct stp_config_pdu { | 28 | struct stp_config_pdu { |
| 29 | uint8_t flags; | 29 | u8 flags; |
| 30 | uint8_t root[8]; | 30 | u8 root[8]; |
| 31 | uint8_t root_cost[4]; | 31 | u8 root_cost[4]; |
| 32 | uint8_t sender[8]; | 32 | u8 sender[8]; |
| 33 | uint8_t port[2]; | 33 | u8 port[2]; |
| 34 | uint8_t msg_age[2]; | 34 | u8 msg_age[2]; |
| 35 | uint8_t max_age[2]; | 35 | u8 max_age[2]; |
| 36 | uint8_t hello_time[2]; | 36 | u8 hello_time[2]; |
| 37 | uint8_t forward_delay[2]; | 37 | u8 forward_delay[2]; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | #define NR16(p) (p[0] << 8 | p[1]) | 40 | #define NR16(p) (p[0] << 8 | p[1]) |
| @@ -44,76 +44,73 @@ static bool ebt_filter_config(const struct ebt_stp_info *info, | |||
| 44 | const struct stp_config_pdu *stpc) | 44 | const struct stp_config_pdu *stpc) |
| 45 | { | 45 | { |
| 46 | const struct ebt_stp_config_info *c; | 46 | const struct ebt_stp_config_info *c; |
| 47 | uint16_t v16; | 47 | u16 v16; |
| 48 | uint32_t v32; | 48 | u32 v32; |
| 49 | int verdict, i; | ||
| 50 | 49 | ||
| 51 | c = &info->config; | 50 | c = &info->config; |
| 52 | if ((info->bitmask & EBT_STP_FLAGS) && | 51 | if ((info->bitmask & EBT_STP_FLAGS) && |
| 53 | FWINV(c->flags != stpc->flags, EBT_STP_FLAGS)) | 52 | NF_INVF(info, EBT_STP_FLAGS, c->flags != stpc->flags)) |
| 54 | return false; | 53 | return false; |
| 55 | if (info->bitmask & EBT_STP_ROOTPRIO) { | 54 | if (info->bitmask & EBT_STP_ROOTPRIO) { |
| 56 | v16 = NR16(stpc->root); | 55 | v16 = NR16(stpc->root); |
| 57 | if (FWINV(v16 < c->root_priol || | 56 | if (NF_INVF(info, EBT_STP_ROOTPRIO, |
| 58 | v16 > c->root_priou, EBT_STP_ROOTPRIO)) | 57 | v16 < c->root_priol || v16 > c->root_priou)) |
| 59 | return false; | 58 | return false; |
| 60 | } | 59 | } |
| 61 | if (info->bitmask & EBT_STP_ROOTADDR) { | 60 | if (info->bitmask & EBT_STP_ROOTADDR) { |
| 62 | verdict = 0; | 61 | if (NF_INVF(info, EBT_STP_ROOTADDR, |
| 63 | for (i = 0; i < 6; i++) | 62 | !ether_addr_equal_masked(&stpc->root[2], |
| 64 | verdict |= (stpc->root[2+i] ^ c->root_addr[i]) & | 63 | c->root_addr, |
| 65 | c->root_addrmsk[i]; | 64 | c->root_addrmsk))) |
| 66 | if (FWINV(verdict != 0, EBT_STP_ROOTADDR)) | ||
| 67 | return false; | 65 | return false; |
| 68 | } | 66 | } |
| 69 | if (info->bitmask & EBT_STP_ROOTCOST) { | 67 | if (info->bitmask & EBT_STP_ROOTCOST) { |
| 70 | v32 = NR32(stpc->root_cost); | 68 | v32 = NR32(stpc->root_cost); |
| 71 | if (FWINV(v32 < c->root_costl || | 69 | if (NF_INVF(info, EBT_STP_ROOTCOST, |
| 72 | v32 > c->root_costu, EBT_STP_ROOTCOST)) | 70 | v32 < c->root_costl || v32 > c->root_costu)) |
| 73 | return false; | 71 | return false; |
| 74 | } | 72 | } |
| 75 | if (info->bitmask & EBT_STP_SENDERPRIO) { | 73 | if (info->bitmask & EBT_STP_SENDERPRIO) { |
| 76 | v16 = NR16(stpc->sender); | 74 | v16 = NR16(stpc->sender); |
| 77 | if (FWINV(v16 < c->sender_priol || | 75 | if (NF_INVF(info, EBT_STP_SENDERPRIO, |
| 78 | v16 > c->sender_priou, EBT_STP_SENDERPRIO)) | 76 | v16 < c->sender_priol || v16 > c->sender_priou)) |
| 79 | return false; | 77 | return false; |
| 80 | } | 78 | } |
| 81 | if (info->bitmask & EBT_STP_SENDERADDR) { | 79 | if (info->bitmask & EBT_STP_SENDERADDR) { |
| 82 | verdict = 0; | 80 | if (NF_INVF(info, EBT_STP_SENDERADDR, |
| 83 | for (i = 0; i < 6; i++) | 81 | !ether_addr_equal_masked(&stpc->sender[2], |
| 84 | verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) & | 82 | c->sender_addr, |
| 85 | c->sender_addrmsk[i]; | 83 | c->sender_addrmsk))) |
| 86 | if (FWINV(verdict != 0, EBT_STP_SENDERADDR)) | ||
| 87 | return false; | 84 | return false; |
| 88 | } | 85 | } |
| 89 | if (info->bitmask & EBT_STP_PORT) { | 86 | if (info->bitmask & EBT_STP_PORT) { |
| 90 | v16 = NR16(stpc->port); | 87 | v16 = NR16(stpc->port); |
| 91 | if (FWINV(v16 < c->portl || | 88 | if (NF_INVF(info, EBT_STP_PORT, |
| 92 | v16 > c->portu, EBT_STP_PORT)) | 89 | v16 < c->portl || v16 > c->portu)) |
| 93 | return false; | 90 | return false; |
| 94 | } | 91 | } |
| 95 | if (info->bitmask & EBT_STP_MSGAGE) { | 92 | if (info->bitmask & EBT_STP_MSGAGE) { |
| 96 | v16 = NR16(stpc->msg_age); | 93 | v16 = NR16(stpc->msg_age); |
| 97 | if (FWINV(v16 < c->msg_agel || | 94 | if (NF_INVF(info, EBT_STP_MSGAGE, |
| 98 | v16 > c->msg_ageu, EBT_STP_MSGAGE)) | 95 | v16 < c->msg_agel || v16 > c->msg_ageu)) |
| 99 | return false; | 96 | return false; |
| 100 | } | 97 | } |
| 101 | if (info->bitmask & EBT_STP_MAXAGE) { | 98 | if (info->bitmask & EBT_STP_MAXAGE) { |
| 102 | v16 = NR16(stpc->max_age); | 99 | v16 = NR16(stpc->max_age); |
| 103 | if (FWINV(v16 < c->max_agel || | 100 | if (NF_INVF(info, EBT_STP_MAXAGE, |
| 104 | v16 > c->max_ageu, EBT_STP_MAXAGE)) | 101 | v16 < c->max_agel || v16 > c->max_ageu)) |
| 105 | return false; | 102 | return false; |
| 106 | } | 103 | } |
| 107 | if (info->bitmask & EBT_STP_HELLOTIME) { | 104 | if (info->bitmask & EBT_STP_HELLOTIME) { |
| 108 | v16 = NR16(stpc->hello_time); | 105 | v16 = NR16(stpc->hello_time); |
| 109 | if (FWINV(v16 < c->hello_timel || | 106 | if (NF_INVF(info, EBT_STP_HELLOTIME, |
| 110 | v16 > c->hello_timeu, EBT_STP_HELLOTIME)) | 107 | v16 < c->hello_timel || v16 > c->hello_timeu)) |
| 111 | return false; | 108 | return false; |
| 112 | } | 109 | } |
| 113 | if (info->bitmask & EBT_STP_FWDD) { | 110 | if (info->bitmask & EBT_STP_FWDD) { |
| 114 | v16 = NR16(stpc->forward_delay); | 111 | v16 = NR16(stpc->forward_delay); |
| 115 | if (FWINV(v16 < c->forward_delayl || | 112 | if (NF_INVF(info, EBT_STP_FWDD, |
| 116 | v16 > c->forward_delayu, EBT_STP_FWDD)) | 113 | v16 < c->forward_delayl || v16 > c->forward_delayu)) |
| 117 | return false; | 114 | return false; |
| 118 | } | 115 | } |
| 119 | return true; | 116 | return true; |
| @@ -125,7 +122,7 @@ ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 125 | const struct ebt_stp_info *info = par->matchinfo; | 122 | const struct ebt_stp_info *info = par->matchinfo; |
| 126 | const struct stp_header *sp; | 123 | const struct stp_header *sp; |
| 127 | struct stp_header _stph; | 124 | struct stp_header _stph; |
| 128 | const uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; | 125 | const u8 header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; |
| 129 | 126 | ||
| 130 | sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph); | 127 | sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph); |
| 131 | if (sp == NULL) | 128 | if (sp == NULL) |
| @@ -135,8 +132,8 @@ ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 135 | if (memcmp(sp, header, sizeof(header))) | 132 | if (memcmp(sp, header, sizeof(header))) |
| 136 | return false; | 133 | return false; |
| 137 | 134 | ||
| 138 | if (info->bitmask & EBT_STP_TYPE && | 135 | if ((info->bitmask & EBT_STP_TYPE) && |
| 139 | FWINV(info->type != sp->type, EBT_STP_TYPE)) | 136 | NF_INVF(info, EBT_STP_TYPE, info->type != sp->type)) |
| 140 | return false; | 137 | return false; |
| 141 | 138 | ||
| 142 | if (sp->type == BPDU_TYPE_CONFIG && | 139 | if (sp->type == BPDU_TYPE_CONFIG && |
| @@ -156,8 +153,8 @@ ebt_stp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 156 | static int ebt_stp_mt_check(const struct xt_mtchk_param *par) | 153 | static int ebt_stp_mt_check(const struct xt_mtchk_param *par) |
| 157 | { | 154 | { |
| 158 | const struct ebt_stp_info *info = par->matchinfo; | 155 | const struct ebt_stp_info *info = par->matchinfo; |
| 159 | const uint8_t bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; | 156 | const u8 bridge_ula[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; |
| 160 | const uint8_t msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 157 | const u8 msk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| 161 | const struct ebt_entry *e = par->entryinfo; | 158 | const struct ebt_entry *e = par->entryinfo; |
| 162 | 159 | ||
| 163 | if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || | 160 | if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK || |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 5a61f35412a0..cceac5bb658f 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -121,7 +121,6 @@ ebt_dev_check(const char *entry, const struct net_device *device) | |||
| 121 | return devname[i] != entry[i] && entry[i] != 1; | 121 | return devname[i] != entry[i] && entry[i] != 1; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | #define FWINV2(bool, invflg) ((bool) ^ !!(e->invflags & invflg)) | ||
| 125 | /* process standard matches */ | 124 | /* process standard matches */ |
| 126 | static inline int | 125 | static inline int |
| 127 | ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | 126 | ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, |
| @@ -130,7 +129,6 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | |||
| 130 | const struct ethhdr *h = eth_hdr(skb); | 129 | const struct ethhdr *h = eth_hdr(skb); |
| 131 | const struct net_bridge_port *p; | 130 | const struct net_bridge_port *p; |
| 132 | __be16 ethproto; | 131 | __be16 ethproto; |
| 133 | int verdict, i; | ||
| 134 | 132 | ||
| 135 | if (skb_vlan_tag_present(skb)) | 133 | if (skb_vlan_tag_present(skb)) |
| 136 | ethproto = htons(ETH_P_8021Q); | 134 | ethproto = htons(ETH_P_8021Q); |
| @@ -138,38 +136,36 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, | |||
| 138 | ethproto = h->h_proto; | 136 | ethproto = h->h_proto; |
| 139 | 137 | ||
| 140 | if (e->bitmask & EBT_802_3) { | 138 | if (e->bitmask & EBT_802_3) { |
| 141 | if (FWINV2(eth_proto_is_802_3(ethproto), EBT_IPROTO)) | 139 | if (NF_INVF(e, EBT_IPROTO, eth_proto_is_802_3(ethproto))) |
| 142 | return 1; | 140 | return 1; |
| 143 | } else if (!(e->bitmask & EBT_NOPROTO) && | 141 | } else if (!(e->bitmask & EBT_NOPROTO) && |
| 144 | FWINV2(e->ethproto != ethproto, EBT_IPROTO)) | 142 | NF_INVF(e, EBT_IPROTO, e->ethproto != ethproto)) |
| 145 | return 1; | 143 | return 1; |
| 146 | 144 | ||
| 147 | if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN)) | 145 | if (NF_INVF(e, EBT_IIN, ebt_dev_check(e->in, in))) |
| 148 | return 1; | 146 | return 1; |
| 149 | if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) | 147 | if (NF_INVF(e, EBT_IOUT, ebt_dev_check(e->out, out))) |
| 150 | return 1; | 148 | return 1; |
| 151 | /* rcu_read_lock()ed by nf_hook_slow */ | 149 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 152 | if (in && (p = br_port_get_rcu(in)) != NULL && | 150 | if (in && (p = br_port_get_rcu(in)) != NULL && |
| 153 | FWINV2(ebt_dev_check(e->logical_in, p->br->dev), EBT_ILOGICALIN)) | 151 | NF_INVF(e, EBT_ILOGICALIN, |
| 152 | ebt_dev_check(e->logical_in, p->br->dev))) | ||
| 154 | return 1; | 153 | return 1; |
| 155 | if (out && (p = br_port_get_rcu(out)) != NULL && | 154 | if (out && (p = br_port_get_rcu(out)) != NULL && |
| 156 | FWINV2(ebt_dev_check(e->logical_out, p->br->dev), EBT_ILOGICALOUT)) | 155 | NF_INVF(e, EBT_ILOGICALOUT, |
| 156 | ebt_dev_check(e->logical_out, p->br->dev))) | ||
| 157 | return 1; | 157 | return 1; |
| 158 | 158 | ||
| 159 | if (e->bitmask & EBT_SOURCEMAC) { | 159 | if (e->bitmask & EBT_SOURCEMAC) { |
| 160 | verdict = 0; | 160 | if (NF_INVF(e, EBT_ISOURCE, |
| 161 | for (i = 0; i < 6; i++) | 161 | !ether_addr_equal_masked(h->h_source, e->sourcemac, |
| 162 | verdict |= (h->h_source[i] ^ e->sourcemac[i]) & | 162 | e->sourcemsk))) |
| 163 | e->sourcemsk[i]; | ||
| 164 | if (FWINV2(verdict != 0, EBT_ISOURCE)) | ||
| 165 | return 1; | 163 | return 1; |
| 166 | } | 164 | } |
| 167 | if (e->bitmask & EBT_DESTMAC) { | 165 | if (e->bitmask & EBT_DESTMAC) { |
| 168 | verdict = 0; | 166 | if (NF_INVF(e, EBT_IDEST, |
| 169 | for (i = 0; i < 6; i++) | 167 | !ether_addr_equal_masked(h->h_dest, e->destmac, |
| 170 | verdict |= (h->h_dest[i] ^ e->destmac[i]) & | 168 | e->destmsk))) |
| 171 | e->destmsk[i]; | ||
| 172 | if (FWINV2(verdict != 0, EBT_IDEST)) | ||
| 173 | return 1; | 169 | return 1; |
| 174 | } | 170 | } |
| 175 | return 0; | 171 | return 0; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 2033f929aa66..c8dd9e26b185 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -89,22 +89,20 @@ static inline int arp_packet_match(const struct arphdr *arphdr, | |||
| 89 | __be32 src_ipaddr, tgt_ipaddr; | 89 | __be32 src_ipaddr, tgt_ipaddr; |
| 90 | long ret; | 90 | long ret; |
| 91 | 91 | ||
| 92 | #define FWINV(bool, invflg) ((bool) ^ !!(arpinfo->invflags & (invflg))) | 92 | if (NF_INVF(arpinfo, ARPT_INV_ARPOP, |
| 93 | 93 | (arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop)) | |
| 94 | if (FWINV((arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop, | ||
| 95 | ARPT_INV_ARPOP)) | ||
| 96 | return 0; | 94 | return 0; |
| 97 | 95 | ||
| 98 | if (FWINV((arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd, | 96 | if (NF_INVF(arpinfo, ARPT_INV_ARPHRD, |
| 99 | ARPT_INV_ARPHRD)) | 97 | (arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd)) |
| 100 | return 0; | 98 | return 0; |
| 101 | 99 | ||
| 102 | if (FWINV((arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro, | 100 | if (NF_INVF(arpinfo, ARPT_INV_ARPPRO, |
| 103 | ARPT_INV_ARPPRO)) | 101 | (arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro)) |
| 104 | return 0; | 102 | return 0; |
| 105 | 103 | ||
| 106 | if (FWINV((arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln, | 104 | if (NF_INVF(arpinfo, ARPT_INV_ARPHLN, |
| 107 | ARPT_INV_ARPHLN)) | 105 | (arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln)) |
| 108 | return 0; | 106 | return 0; |
| 109 | 107 | ||
| 110 | src_devaddr = arpptr; | 108 | src_devaddr = arpptr; |
| @@ -115,31 +113,32 @@ static inline int arp_packet_match(const struct arphdr *arphdr, | |||
| 115 | arpptr += dev->addr_len; | 113 | arpptr += dev->addr_len; |
| 116 | memcpy(&tgt_ipaddr, arpptr, sizeof(u32)); | 114 | memcpy(&tgt_ipaddr, arpptr, sizeof(u32)); |
| 117 | 115 | ||
| 118 | if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len), | 116 | if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR, |
| 119 | ARPT_INV_SRCDEVADDR) || | 117 | arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, |
| 120 | FWINV(arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr, dev->addr_len), | 118 | dev->addr_len)) || |
| 121 | ARPT_INV_TGTDEVADDR)) | 119 | NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR, |
| 120 | arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr, | ||
| 121 | dev->addr_len))) | ||
| 122 | return 0; | 122 | return 0; |
| 123 | 123 | ||
| 124 | if (FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr, | 124 | if (NF_INVF(arpinfo, ARPT_INV_SRCIP, |
| 125 | ARPT_INV_SRCIP) || | 125 | (src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr) || |
| 126 | FWINV(((tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr), | 126 | NF_INVF(arpinfo, ARPT_INV_TGTIP, |
| 127 | ARPT_INV_TGTIP)) | 127 | (tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr)) |
| 128 | return 0; | 128 | return 0; |
| 129 | 129 | ||
| 130 | /* Look for ifname matches. */ | 130 | /* Look for ifname matches. */ |
| 131 | ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask); | 131 | ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask); |
| 132 | 132 | ||
| 133 | if (FWINV(ret != 0, ARPT_INV_VIA_IN)) | 133 | if (NF_INVF(arpinfo, ARPT_INV_VIA_IN, ret != 0)) |
| 134 | return 0; | 134 | return 0; |
| 135 | 135 | ||
| 136 | ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask); | 136 | ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask); |
| 137 | 137 | ||
| 138 | if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) | 138 | if (NF_INVF(arpinfo, ARPT_INV_VIA_OUT, ret != 0)) |
| 139 | return 0; | 139 | return 0; |
| 140 | 140 | ||
| 141 | return 1; | 141 | return 1; |
| 142 | #undef FWINV | ||
| 143 | } | 142 | } |
| 144 | 143 | ||
| 145 | static inline int arp_checkentry(const struct arpt_arp *arp) | 144 | static inline int arp_checkentry(const struct arpt_arp *arp) |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 54906e0e8e0c..f0df66f54ce6 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -58,32 +58,31 @@ ip_packet_match(const struct iphdr *ip, | |||
| 58 | { | 58 | { |
| 59 | unsigned long ret; | 59 | unsigned long ret; |
| 60 | 60 | ||
| 61 | #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) | 61 | if (NF_INVF(ipinfo, IPT_INV_SRCIP, |
| 62 | 62 | (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || | |
| 63 | if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, | 63 | NF_INVF(ipinfo, IPT_INV_DSTIP, |
| 64 | IPT_INV_SRCIP) || | 64 | (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) |
| 65 | FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, | ||
| 66 | IPT_INV_DSTIP)) | ||
| 67 | return false; | 65 | return false; |
| 68 | 66 | ||
| 69 | ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); | 67 | ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); |
| 70 | 68 | ||
| 71 | if (FWINV(ret != 0, IPT_INV_VIA_IN)) | 69 | if (NF_INVF(ipinfo, IPT_INV_VIA_IN, ret != 0)) |
| 72 | return false; | 70 | return false; |
| 73 | 71 | ||
| 74 | ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); | 72 | ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); |
| 75 | 73 | ||
| 76 | if (FWINV(ret != 0, IPT_INV_VIA_OUT)) | 74 | if (NF_INVF(ipinfo, IPT_INV_VIA_OUT, ret != 0)) |
| 77 | return false; | 75 | return false; |
| 78 | 76 | ||
| 79 | /* Check specific protocol */ | 77 | /* Check specific protocol */ |
| 80 | if (ipinfo->proto && | 78 | if (ipinfo->proto && |
| 81 | FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) | 79 | NF_INVF(ipinfo, IPT_INV_PROTO, ip->protocol != ipinfo->proto)) |
| 82 | return false; | 80 | return false; |
| 83 | 81 | ||
| 84 | /* If we have a fragment rule but the packet is not a fragment | 82 | /* If we have a fragment rule but the packet is not a fragment |
| 85 | * then we return zero */ | 83 | * then we return zero */ |
| 86 | if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) | 84 | if (NF_INVF(ipinfo, IPT_INV_FRAG, |
| 85 | (ipinfo->flags & IPT_F_FRAG) && !isfrag)) | ||
| 87 | return false; | 86 | return false; |
| 88 | 87 | ||
| 89 | return true; | 88 | return true; |
| @@ -122,7 +121,6 @@ static inline bool unconditional(const struct ipt_entry *e) | |||
| 122 | 121 | ||
| 123 | return e->target_offset == sizeof(struct ipt_entry) && | 122 | return e->target_offset == sizeof(struct ipt_entry) && |
| 124 | memcmp(&e->ip, &uncond, sizeof(uncond)) == 0; | 123 | memcmp(&e->ip, &uncond, sizeof(uncond)) == 0; |
| 125 | #undef FWINV | ||
| 126 | } | 124 | } |
| 127 | 125 | ||
| 128 | /* for const-correctness */ | 126 | /* for const-correctness */ |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 57fc97cdac70..aebdb337fd7e 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
| @@ -87,10 +87,6 @@ iptable_mangle_hook(void *priv, | |||
| 87 | { | 87 | { |
| 88 | if (state->hook == NF_INET_LOCAL_OUT) | 88 | if (state->hook == NF_INET_LOCAL_OUT) |
| 89 | return ipt_mangle_out(skb, state); | 89 | return ipt_mangle_out(skb, state); |
| 90 | if (state->hook == NF_INET_POST_ROUTING) | ||
| 91 | return ipt_do_table(skb, state, | ||
| 92 | state->net->ipv4.iptable_mangle); | ||
| 93 | /* PREROUTING/INPUT/FORWARD: */ | ||
| 94 | return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); | 90 | return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle); |
| 95 | } | 91 | } |
| 96 | 92 | ||
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index b6ea57ec5e14..fd8220213afc 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
| @@ -24,6 +24,9 @@ const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, | |||
| 24 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | 24 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) |
| 25 | return NULL; | 25 | return NULL; |
| 26 | 26 | ||
| 27 | if (ip_hdr(oldskb)->protocol != IPPROTO_TCP) | ||
| 28 | return NULL; | ||
| 29 | |||
| 27 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), | 30 | oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb), |
| 28 | sizeof(struct tcphdr), _oth); | 31 | sizeof(struct tcphdr), _oth); |
| 29 | if (oth == NULL) | 32 | if (oth == NULL) |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 63e06c3dd319..61ed95054efa 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -73,22 +73,22 @@ ip6_packet_match(const struct sk_buff *skb, | |||
| 73 | unsigned long ret; | 73 | unsigned long ret; |
| 74 | const struct ipv6hdr *ipv6 = ipv6_hdr(skb); | 74 | const struct ipv6hdr *ipv6 = ipv6_hdr(skb); |
| 75 | 75 | ||
| 76 | #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg))) | 76 | if (NF_INVF(ip6info, IP6T_INV_SRCIP, |
| 77 | 77 | ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, | |
| 78 | if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, | 78 | &ip6info->src)) || |
| 79 | &ip6info->src), IP6T_INV_SRCIP) || | 79 | NF_INVF(ip6info, IP6T_INV_DSTIP, |
| 80 | FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, | 80 | ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, |
| 81 | &ip6info->dst), IP6T_INV_DSTIP)) | 81 | &ip6info->dst))) |
| 82 | return false; | 82 | return false; |
| 83 | 83 | ||
| 84 | ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); | 84 | ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); |
| 85 | 85 | ||
| 86 | if (FWINV(ret != 0, IP6T_INV_VIA_IN)) | 86 | if (NF_INVF(ip6info, IP6T_INV_VIA_IN, ret != 0)) |
| 87 | return false; | 87 | return false; |
| 88 | 88 | ||
| 89 | ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); | 89 | ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); |
| 90 | 90 | ||
| 91 | if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) | 91 | if (NF_INVF(ip6info, IP6T_INV_VIA_OUT, ret != 0)) |
| 92 | return false; | 92 | return false; |
| 93 | 93 | ||
| 94 | /* ... might want to do something with class and flowlabel here ... */ | 94 | /* ... might want to do something with class and flowlabel here ... */ |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index cb2b28883252..2b1a9dcdbcb3 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
| @@ -83,10 +83,6 @@ ip6table_mangle_hook(void *priv, struct sk_buff *skb, | |||
| 83 | { | 83 | { |
| 84 | if (state->hook == NF_INET_LOCAL_OUT) | 84 | if (state->hook == NF_INET_LOCAL_OUT) |
| 85 | return ip6t_mangle_out(skb, state); | 85 | return ip6t_mangle_out(skb, state); |
| 86 | if (state->hook == NF_INET_POST_ROUTING) | ||
| 87 | return ip6t_do_table(skb, state, | ||
| 88 | state->net->ipv6.ip6table_mangle); | ||
| 89 | /* INPUT/FORWARD */ | ||
| 90 | return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); | 86 | return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); |
| 91 | } | 87 | } |
| 92 | 88 | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 95e757c377f9..9266ceebd112 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -609,9 +609,8 @@ config NETFILTER_XT_MARK | |||
| 609 | The target allows you to create rules in the "mangle" table which alter | 609 | The target allows you to create rules in the "mangle" table which alter |
| 610 | the netfilter mark (nfmark) field associated with the packet. | 610 | the netfilter mark (nfmark) field associated with the packet. |
| 611 | 611 | ||
| 612 | Prior to routing, the nfmark can influence the routing method (see | 612 | Prior to routing, the nfmark can influence the routing method and can |
| 613 | "Use netfilter MARK value as routing key") and can also be used by | 613 | also be used by other subsystems to change their behavior. |
| 614 | other subsystems to change their behavior. | ||
| 615 | 614 | ||
| 616 | config NETFILTER_XT_CONNMARK | 615 | config NETFILTER_XT_CONNMARK |
| 617 | tristate 'ctmark target and match support' | 616 | tristate 'ctmark target and match support' |
| @@ -753,9 +752,8 @@ config NETFILTER_XT_TARGET_HMARK | |||
| 753 | 752 | ||
| 754 | The target allows you to create rules in the "raw" and "mangle" tables | 753 | The target allows you to create rules in the "raw" and "mangle" tables |
| 755 | which set the skbuff mark by means of hash calculation within a given | 754 | which set the skbuff mark by means of hash calculation within a given |
| 756 | range. The nfmark can influence the routing method (see "Use netfilter | 755 | range. The nfmark can influence the routing method and can also be used |
| 757 | MARK value as routing key") and can also be used by other subsystems to | 756 | by other subsystems to change their behaviour. |
| 758 | change their behaviour. | ||
| 759 | 757 | ||
| 760 | To compile it as a module, choose M here. If unsure, say N. | 758 | To compile it as a module, choose M here. If unsure, say N. |
| 761 | 759 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index f204274a9b6b..153e33ffeeaa 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -327,16 +327,10 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, | |||
| 327 | 327 | ||
| 328 | tmpl->status = IPS_TEMPLATE; | 328 | tmpl->status = IPS_TEMPLATE; |
| 329 | write_pnet(&tmpl->ct_net, net); | 329 | write_pnet(&tmpl->ct_net, net); |
| 330 | 330 | nf_ct_zone_add(tmpl, zone); | |
| 331 | if (nf_ct_zone_add(tmpl, flags, zone) < 0) | ||
| 332 | goto out_free; | ||
| 333 | |||
| 334 | atomic_set(&tmpl->ct_general.use, 0); | 331 | atomic_set(&tmpl->ct_general.use, 0); |
| 335 | 332 | ||
| 336 | return tmpl; | 333 | return tmpl; |
| 337 | out_free: | ||
| 338 | kfree(tmpl); | ||
| 339 | return NULL; | ||
| 340 | } | 334 | } |
| 341 | EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); | 335 | EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); |
| 342 | 336 | ||
| @@ -929,16 +923,13 @@ __nf_conntrack_alloc(struct net *net, | |||
| 929 | offsetof(struct nf_conn, proto) - | 923 | offsetof(struct nf_conn, proto) - |
| 930 | offsetof(struct nf_conn, __nfct_init_offset[0])); | 924 | offsetof(struct nf_conn, __nfct_init_offset[0])); |
| 931 | 925 | ||
| 932 | if (zone && nf_ct_zone_add(ct, GFP_ATOMIC, zone) < 0) | 926 | nf_ct_zone_add(ct, zone); |
| 933 | goto out_free; | ||
| 934 | 927 | ||
| 935 | /* Because we use RCU lookups, we set ct_general.use to zero before | 928 | /* Because we use RCU lookups, we set ct_general.use to zero before |
| 936 | * this is inserted in any list. | 929 | * this is inserted in any list. |
| 937 | */ | 930 | */ |
| 938 | atomic_set(&ct->ct_general.use, 0); | 931 | atomic_set(&ct->ct_general.use, 0); |
| 939 | return ct; | 932 | return ct; |
| 940 | out_free: | ||
| 941 | kmem_cache_free(nf_conntrack_cachep, ct); | ||
| 942 | out: | 933 | out: |
| 943 | atomic_dec(&net->ct.count); | 934 | atomic_dec(&net->ct.count); |
| 944 | return ERR_PTR(-ENOMEM); | 935 | return ERR_PTR(-ENOMEM); |
| @@ -1342,14 +1333,6 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, | |||
| 1342 | } | 1333 | } |
| 1343 | EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); | 1334 | EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); |
| 1344 | 1335 | ||
| 1345 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1346 | static struct nf_ct_ext_type nf_ct_zone_extend __read_mostly = { | ||
| 1347 | .len = sizeof(struct nf_conntrack_zone), | ||
| 1348 | .align = __alignof__(struct nf_conntrack_zone), | ||
| 1349 | .id = NF_CT_EXT_ZONE, | ||
| 1350 | }; | ||
| 1351 | #endif | ||
| 1352 | |||
| 1353 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | 1336 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
| 1354 | 1337 | ||
| 1355 | #include <linux/netfilter/nfnetlink.h> | 1338 | #include <linux/netfilter/nfnetlink.h> |
| @@ -1532,9 +1515,6 @@ void nf_conntrack_cleanup_end(void) | |||
| 1532 | 1515 | ||
| 1533 | nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); | 1516 | nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size); |
| 1534 | 1517 | ||
| 1535 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1536 | nf_ct_extend_unregister(&nf_ct_zone_extend); | ||
| 1537 | #endif | ||
| 1538 | nf_conntrack_proto_fini(); | 1518 | nf_conntrack_proto_fini(); |
| 1539 | nf_conntrack_seqadj_fini(); | 1519 | nf_conntrack_seqadj_fini(); |
| 1540 | nf_conntrack_labels_fini(); | 1520 | nf_conntrack_labels_fini(); |
| @@ -1617,24 +1597,14 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) | |||
| 1617 | } | 1597 | } |
| 1618 | EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable); | 1598 | EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable); |
| 1619 | 1599 | ||
| 1620 | int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | 1600 | int nf_conntrack_hash_resize(unsigned int hashsize) |
| 1621 | { | 1601 | { |
| 1622 | int i, bucket, rc; | 1602 | int i, bucket; |
| 1623 | unsigned int hashsize, old_size; | 1603 | unsigned int old_size; |
| 1624 | struct hlist_nulls_head *hash, *old_hash; | 1604 | struct hlist_nulls_head *hash, *old_hash; |
| 1625 | struct nf_conntrack_tuple_hash *h; | 1605 | struct nf_conntrack_tuple_hash *h; |
| 1626 | struct nf_conn *ct; | 1606 | struct nf_conn *ct; |
| 1627 | 1607 | ||
| 1628 | if (current->nsproxy->net_ns != &init_net) | ||
| 1629 | return -EOPNOTSUPP; | ||
| 1630 | |||
| 1631 | /* On boot, we can set this without any fancy locking. */ | ||
| 1632 | if (!nf_conntrack_htable_size) | ||
| 1633 | return param_set_uint(val, kp); | ||
| 1634 | |||
| 1635 | rc = kstrtouint(val, 0, &hashsize); | ||
| 1636 | if (rc) | ||
| 1637 | return rc; | ||
| 1638 | if (!hashsize) | 1608 | if (!hashsize) |
| 1639 | return -EINVAL; | 1609 | return -EINVAL; |
| 1640 | 1610 | ||
| @@ -1642,6 +1612,12 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1642 | if (!hash) | 1612 | if (!hash) |
| 1643 | return -ENOMEM; | 1613 | return -ENOMEM; |
| 1644 | 1614 | ||
| 1615 | old_size = nf_conntrack_htable_size; | ||
| 1616 | if (old_size == hashsize) { | ||
| 1617 | nf_ct_free_hashtable(hash, hashsize); | ||
| 1618 | return 0; | ||
| 1619 | } | ||
| 1620 | |||
| 1645 | local_bh_disable(); | 1621 | local_bh_disable(); |
| 1646 | nf_conntrack_all_lock(); | 1622 | nf_conntrack_all_lock(); |
| 1647 | write_seqcount_begin(&nf_conntrack_generation); | 1623 | write_seqcount_begin(&nf_conntrack_generation); |
| @@ -1677,6 +1653,25 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1677 | nf_ct_free_hashtable(old_hash, old_size); | 1653 | nf_ct_free_hashtable(old_hash, old_size); |
| 1678 | return 0; | 1654 | return 0; |
| 1679 | } | 1655 | } |
| 1656 | |||
| 1657 | int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | ||
| 1658 | { | ||
| 1659 | unsigned int hashsize; | ||
| 1660 | int rc; | ||
| 1661 | |||
| 1662 | if (current->nsproxy->net_ns != &init_net) | ||
| 1663 | return -EOPNOTSUPP; | ||
| 1664 | |||
| 1665 | /* On boot, we can set this without any fancy locking. */ | ||
| 1666 | if (!nf_conntrack_htable_size) | ||
| 1667 | return param_set_uint(val, kp); | ||
| 1668 | |||
| 1669 | rc = kstrtouint(val, 0, &hashsize); | ||
| 1670 | if (rc) | ||
| 1671 | return rc; | ||
| 1672 | |||
| 1673 | return nf_conntrack_hash_resize(hashsize); | ||
| 1674 | } | ||
| 1680 | EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize); | 1675 | EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize); |
| 1681 | 1676 | ||
| 1682 | module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, | 1677 | module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, |
| @@ -1733,7 +1728,7 @@ int nf_conntrack_init_start(void) | |||
| 1733 | 1728 | ||
| 1734 | nf_conntrack_cachep = kmem_cache_create("nf_conntrack", | 1729 | nf_conntrack_cachep = kmem_cache_create("nf_conntrack", |
| 1735 | sizeof(struct nf_conn), 0, | 1730 | sizeof(struct nf_conn), 0, |
| 1736 | SLAB_DESTROY_BY_RCU, NULL); | 1731 | SLAB_DESTROY_BY_RCU | SLAB_HWCACHE_ALIGN, NULL); |
| 1737 | if (!nf_conntrack_cachep) | 1732 | if (!nf_conntrack_cachep) |
| 1738 | goto err_cachep; | 1733 | goto err_cachep; |
| 1739 | 1734 | ||
| @@ -1773,11 +1768,6 @@ int nf_conntrack_init_start(void) | |||
| 1773 | if (ret < 0) | 1768 | if (ret < 0) |
| 1774 | goto err_seqadj; | 1769 | goto err_seqadj; |
| 1775 | 1770 | ||
| 1776 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1777 | ret = nf_ct_extend_register(&nf_ct_zone_extend); | ||
| 1778 | if (ret < 0) | ||
| 1779 | goto err_extend; | ||
| 1780 | #endif | ||
| 1781 | ret = nf_conntrack_proto_init(); | 1771 | ret = nf_conntrack_proto_init(); |
| 1782 | if (ret < 0) | 1772 | if (ret < 0) |
| 1783 | goto err_proto; | 1773 | goto err_proto; |
| @@ -1793,10 +1783,6 @@ int nf_conntrack_init_start(void) | |||
| 1793 | return 0; | 1783 | return 0; |
| 1794 | 1784 | ||
| 1795 | err_proto: | 1785 | err_proto: |
| 1796 | #ifdef CONFIG_NF_CONNTRACK_ZONES | ||
| 1797 | nf_ct_extend_unregister(&nf_ct_zone_extend); | ||
| 1798 | err_extend: | ||
| 1799 | #endif | ||
| 1800 | nf_conntrack_seqadj_fini(); | 1786 | nf_conntrack_seqadj_fini(); |
| 1801 | err_seqadj: | 1787 | err_seqadj: |
| 1802 | nf_conntrack_labels_fini(); | 1788 | nf_conntrack_labels_fini(); |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 196cb39649e1..3a1a88b9bafa 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
| @@ -389,11 +389,38 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
| 389 | struct net *net) | 389 | struct net *net) |
| 390 | { | 390 | { |
| 391 | struct nf_conntrack_tuple_hash *h; | 391 | struct nf_conntrack_tuple_hash *h; |
| 392 | const struct hlist_nulls_node *nn; | ||
| 393 | int cpu; | ||
| 394 | |||
| 395 | /* Get rid of expecteds, set helpers to NULL. */ | ||
| 396 | for_each_possible_cpu(cpu) { | ||
| 397 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); | ||
| 398 | |||
| 399 | spin_lock_bh(&pcpu->lock); | ||
| 400 | hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode) | ||
| 401 | unhelp(h, me); | ||
| 402 | spin_unlock_bh(&pcpu->lock); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | ||
| 407 | { | ||
| 408 | struct nf_conntrack_tuple_hash *h; | ||
| 392 | struct nf_conntrack_expect *exp; | 409 | struct nf_conntrack_expect *exp; |
| 393 | const struct hlist_node *next; | 410 | const struct hlist_node *next; |
| 394 | const struct hlist_nulls_node *nn; | 411 | const struct hlist_nulls_node *nn; |
| 412 | struct net *net; | ||
| 395 | unsigned int i; | 413 | unsigned int i; |
| 396 | int cpu; | 414 | |
| 415 | mutex_lock(&nf_ct_helper_mutex); | ||
| 416 | hlist_del_rcu(&me->hnode); | ||
| 417 | nf_ct_helper_count--; | ||
| 418 | mutex_unlock(&nf_ct_helper_mutex); | ||
| 419 | |||
| 420 | /* Make sure every nothing is still using the helper unless its a | ||
| 421 | * connection in the hash. | ||
| 422 | */ | ||
| 423 | synchronize_rcu(); | ||
| 397 | 424 | ||
| 398 | /* Get rid of expectations */ | 425 | /* Get rid of expectations */ |
| 399 | spin_lock_bh(&nf_conntrack_expect_lock); | 426 | spin_lock_bh(&nf_conntrack_expect_lock); |
| @@ -413,15 +440,11 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
| 413 | } | 440 | } |
| 414 | spin_unlock_bh(&nf_conntrack_expect_lock); | 441 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 415 | 442 | ||
| 416 | /* Get rid of expecteds, set helpers to NULL. */ | 443 | rtnl_lock(); |
| 417 | for_each_possible_cpu(cpu) { | 444 | for_each_net(net) |
| 418 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); | 445 | __nf_conntrack_helper_unregister(me, net); |
| 446 | rtnl_unlock(); | ||
| 419 | 447 | ||
| 420 | spin_lock_bh(&pcpu->lock); | ||
| 421 | hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode) | ||
| 422 | unhelp(h, me); | ||
| 423 | spin_unlock_bh(&pcpu->lock); | ||
| 424 | } | ||
| 425 | local_bh_disable(); | 448 | local_bh_disable(); |
| 426 | for (i = 0; i < nf_conntrack_htable_size; i++) { | 449 | for (i = 0; i < nf_conntrack_htable_size; i++) { |
| 427 | nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | 450 | nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); |
| @@ -433,26 +456,6 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
| 433 | } | 456 | } |
| 434 | local_bh_enable(); | 457 | local_bh_enable(); |
| 435 | } | 458 | } |
| 436 | |||
| 437 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | ||
| 438 | { | ||
| 439 | struct net *net; | ||
| 440 | |||
| 441 | mutex_lock(&nf_ct_helper_mutex); | ||
| 442 | hlist_del_rcu(&me->hnode); | ||
| 443 | nf_ct_helper_count--; | ||
| 444 | mutex_unlock(&nf_ct_helper_mutex); | ||
| 445 | |||
| 446 | /* Make sure every nothing is still using the helper unless its a | ||
| 447 | * connection in the hash. | ||
| 448 | */ | ||
| 449 | synchronize_rcu(); | ||
| 450 | |||
| 451 | rtnl_lock(); | ||
| 452 | for_each_net(net) | ||
| 453 | __nf_conntrack_helper_unregister(me, net); | ||
| 454 | rtnl_unlock(); | ||
| 455 | } | ||
| 456 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); | 459 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); |
| 457 | 460 | ||
| 458 | static struct nf_ct_ext_type helper_extend __read_mostly = { | 461 | static struct nf_ct_ext_type helper_extend __read_mostly = { |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index c026c472ea80..2aaa188ee961 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
| @@ -434,8 +434,29 @@ static void nf_conntrack_standalone_fini_proc(struct net *net) | |||
| 434 | 434 | ||
| 435 | #ifdef CONFIG_SYSCTL | 435 | #ifdef CONFIG_SYSCTL |
| 436 | /* Log invalid packets of a given protocol */ | 436 | /* Log invalid packets of a given protocol */ |
| 437 | static int log_invalid_proto_min = 0; | 437 | static int log_invalid_proto_min __read_mostly; |
| 438 | static int log_invalid_proto_max = 255; | 438 | static int log_invalid_proto_max __read_mostly = 255; |
| 439 | |||
| 440 | /* size the user *wants to set */ | ||
| 441 | static unsigned int nf_conntrack_htable_size_user __read_mostly; | ||
| 442 | |||
| 443 | static int | ||
| 444 | nf_conntrack_hash_sysctl(struct ctl_table *table, int write, | ||
| 445 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
| 446 | { | ||
| 447 | int ret; | ||
| 448 | |||
| 449 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | ||
| 450 | if (ret < 0 || !write) | ||
| 451 | return ret; | ||
| 452 | |||
| 453 | /* update ret, we might not be able to satisfy request */ | ||
| 454 | ret = nf_conntrack_hash_resize(nf_conntrack_htable_size_user); | ||
| 455 | |||
| 456 | /* update it to the actual value used by conntrack */ | ||
| 457 | nf_conntrack_htable_size_user = nf_conntrack_htable_size; | ||
| 458 | return ret; | ||
| 459 | } | ||
| 439 | 460 | ||
| 440 | static struct ctl_table_header *nf_ct_netfilter_header; | 461 | static struct ctl_table_header *nf_ct_netfilter_header; |
| 441 | 462 | ||
| @@ -456,10 +477,10 @@ static struct ctl_table nf_ct_sysctl_table[] = { | |||
| 456 | }, | 477 | }, |
| 457 | { | 478 | { |
| 458 | .procname = "nf_conntrack_buckets", | 479 | .procname = "nf_conntrack_buckets", |
| 459 | .data = &nf_conntrack_htable_size, | 480 | .data = &nf_conntrack_htable_size_user, |
| 460 | .maxlen = sizeof(unsigned int), | 481 | .maxlen = sizeof(unsigned int), |
| 461 | .mode = 0444, | 482 | .mode = 0644, |
| 462 | .proc_handler = proc_dointvec, | 483 | .proc_handler = nf_conntrack_hash_sysctl, |
| 463 | }, | 484 | }, |
| 464 | { | 485 | { |
| 465 | .procname = "nf_conntrack_checksum", | 486 | .procname = "nf_conntrack_checksum", |
| @@ -515,6 +536,9 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) | |||
| 515 | if (net->user_ns != &init_user_ns) | 536 | if (net->user_ns != &init_user_ns) |
| 516 | table[0].procname = NULL; | 537 | table[0].procname = NULL; |
| 517 | 538 | ||
| 539 | if (!net_eq(&init_net, net)) | ||
| 540 | table[2].mode = 0444; | ||
| 541 | |||
| 518 | net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table); | 542 | net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table); |
| 519 | if (!net->ct.sysctl_header) | 543 | if (!net->ct.sysctl_header) |
| 520 | goto out_unregister_netfilter; | 544 | goto out_unregister_netfilter; |
| @@ -604,6 +628,8 @@ static int __init nf_conntrack_standalone_init(void) | |||
| 604 | ret = -ENOMEM; | 628 | ret = -ENOMEM; |
| 605 | goto out_sysctl; | 629 | goto out_sysctl; |
| 606 | } | 630 | } |
| 631 | |||
| 632 | nf_conntrack_htable_size_user = nf_conntrack_htable_size; | ||
| 607 | #endif | 633 | #endif |
| 608 | 634 | ||
| 609 | ret = register_pernet_subsys(&nf_conntrack_net_ops); | 635 | ret = register_pernet_subsys(&nf_conntrack_net_ops); |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index a5d41dfa9f05..aa5847a16713 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
| @@ -159,6 +159,20 @@ int nf_logger_find_get(int pf, enum nf_log_type type) | |||
| 159 | struct nf_logger *logger; | 159 | struct nf_logger *logger; |
| 160 | int ret = -ENOENT; | 160 | int ret = -ENOENT; |
| 161 | 161 | ||
| 162 | if (pf == NFPROTO_INET) { | ||
| 163 | ret = nf_logger_find_get(NFPROTO_IPV4, type); | ||
| 164 | if (ret < 0) | ||
| 165 | return ret; | ||
| 166 | |||
| 167 | ret = nf_logger_find_get(NFPROTO_IPV6, type); | ||
| 168 | if (ret < 0) { | ||
| 169 | nf_logger_put(NFPROTO_IPV4, type); | ||
| 170 | return ret; | ||
| 171 | } | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 162 | if (rcu_access_pointer(loggers[pf][type]) == NULL) | 176 | if (rcu_access_pointer(loggers[pf][type]) == NULL) |
| 163 | request_module("nf-logger-%u-%u", pf, type); | 177 | request_module("nf-logger-%u-%u", pf, type); |
| 164 | 178 | ||
| @@ -167,7 +181,7 @@ int nf_logger_find_get(int pf, enum nf_log_type type) | |||
| 167 | if (logger == NULL) | 181 | if (logger == NULL) |
| 168 | goto out; | 182 | goto out; |
| 169 | 183 | ||
| 170 | if (logger && try_module_get(logger->me)) | 184 | if (try_module_get(logger->me)) |
| 171 | ret = 0; | 185 | ret = 0; |
| 172 | out: | 186 | out: |
| 173 | rcu_read_unlock(); | 187 | rcu_read_unlock(); |
| @@ -179,6 +193,12 @@ void nf_logger_put(int pf, enum nf_log_type type) | |||
| 179 | { | 193 | { |
| 180 | struct nf_logger *logger; | 194 | struct nf_logger *logger; |
| 181 | 195 | ||
| 196 | if (pf == NFPROTO_INET) { | ||
| 197 | nf_logger_put(NFPROTO_IPV4, type); | ||
| 198 | nf_logger_put(NFPROTO_IPV6, type); | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | |||
| 182 | BUG_ON(loggers[pf][type] == NULL); | 202 | BUG_ON(loggers[pf][type] == NULL); |
| 183 | 203 | ||
| 184 | rcu_read_lock(); | 204 | rcu_read_lock(); |
| @@ -398,16 +418,17 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, | |||
| 398 | { | 418 | { |
| 399 | const struct nf_logger *logger; | 419 | const struct nf_logger *logger; |
| 400 | char buf[NFLOGGER_NAME_LEN]; | 420 | char buf[NFLOGGER_NAME_LEN]; |
| 401 | size_t size = *lenp; | ||
| 402 | int r = 0; | 421 | int r = 0; |
| 403 | int tindex = (unsigned long)table->extra1; | 422 | int tindex = (unsigned long)table->extra1; |
| 404 | struct net *net = current->nsproxy->net_ns; | 423 | struct net *net = current->nsproxy->net_ns; |
| 405 | 424 | ||
| 406 | if (write) { | 425 | if (write) { |
| 407 | if (size > sizeof(buf)) | 426 | struct ctl_table tmp = *table; |
| 408 | size = sizeof(buf); | 427 | |
| 409 | if (copy_from_user(buf, buffer, size)) | 428 | tmp.data = buf; |
| 410 | return -EFAULT; | 429 | r = proc_dostring(&tmp, write, buffer, lenp, ppos); |
| 430 | if (r) | ||
| 431 | return r; | ||
| 411 | 432 | ||
| 412 | if (!strcmp(buf, "NONE")) { | 433 | if (!strcmp(buf, "NONE")) { |
| 413 | nf_log_unbind_pf(net, tindex); | 434 | nf_log_unbind_pf(net, tindex); |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2c881871db38..18b7f8578ee0 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -131,29 +131,8 @@ static void nft_trans_destroy(struct nft_trans *trans) | |||
| 131 | kfree(trans); | 131 | kfree(trans); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static int nft_register_basechain(struct nft_base_chain *basechain, | 134 | static int nf_tables_register_hooks(struct net *net, |
| 135 | unsigned int hook_nops) | 135 | const struct nft_table *table, |
| 136 | { | ||
| 137 | struct net *net = read_pnet(&basechain->pnet); | ||
| 138 | |||
| 139 | if (basechain->flags & NFT_BASECHAIN_DISABLED) | ||
| 140 | return 0; | ||
| 141 | |||
| 142 | return nf_register_net_hooks(net, basechain->ops, hook_nops); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void nft_unregister_basechain(struct nft_base_chain *basechain, | ||
| 146 | unsigned int hook_nops) | ||
| 147 | { | ||
| 148 | struct net *net = read_pnet(&basechain->pnet); | ||
| 149 | |||
| 150 | if (basechain->flags & NFT_BASECHAIN_DISABLED) | ||
| 151 | return; | ||
| 152 | |||
| 153 | nf_unregister_net_hooks(net, basechain->ops, hook_nops); | ||
| 154 | } | ||
| 155 | |||
| 156 | static int nf_tables_register_hooks(const struct nft_table *table, | ||
| 157 | struct nft_chain *chain, | 136 | struct nft_chain *chain, |
| 158 | unsigned int hook_nops) | 137 | unsigned int hook_nops) |
| 159 | { | 138 | { |
| @@ -161,10 +140,12 @@ static int nf_tables_register_hooks(const struct nft_table *table, | |||
| 161 | !(chain->flags & NFT_BASE_CHAIN)) | 140 | !(chain->flags & NFT_BASE_CHAIN)) |
| 162 | return 0; | 141 | return 0; |
| 163 | 142 | ||
| 164 | return nft_register_basechain(nft_base_chain(chain), hook_nops); | 143 | return nf_register_net_hooks(net, nft_base_chain(chain)->ops, |
| 144 | hook_nops); | ||
| 165 | } | 145 | } |
| 166 | 146 | ||
| 167 | static void nf_tables_unregister_hooks(const struct nft_table *table, | 147 | static void nf_tables_unregister_hooks(struct net *net, |
| 148 | const struct nft_table *table, | ||
| 168 | struct nft_chain *chain, | 149 | struct nft_chain *chain, |
| 169 | unsigned int hook_nops) | 150 | unsigned int hook_nops) |
| 170 | { | 151 | { |
| @@ -172,12 +153,9 @@ static void nf_tables_unregister_hooks(const struct nft_table *table, | |||
| 172 | !(chain->flags & NFT_BASE_CHAIN)) | 153 | !(chain->flags & NFT_BASE_CHAIN)) |
| 173 | return; | 154 | return; |
| 174 | 155 | ||
| 175 | nft_unregister_basechain(nft_base_chain(chain), hook_nops); | 156 | nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops); |
| 176 | } | 157 | } |
| 177 | 158 | ||
| 178 | /* Internal table flags */ | ||
| 179 | #define NFT_TABLE_INACTIVE (1 << 15) | ||
| 180 | |||
| 181 | static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) | 159 | static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) |
| 182 | { | 160 | { |
| 183 | struct nft_trans *trans; | 161 | struct nft_trans *trans; |
| @@ -187,7 +165,7 @@ static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) | |||
| 187 | return -ENOMEM; | 165 | return -ENOMEM; |
| 188 | 166 | ||
| 189 | if (msg_type == NFT_MSG_NEWTABLE) | 167 | if (msg_type == NFT_MSG_NEWTABLE) |
| 190 | ctx->table->flags |= NFT_TABLE_INACTIVE; | 168 | nft_activate_next(ctx->net, ctx->table); |
| 191 | 169 | ||
| 192 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 170 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
| 193 | return 0; | 171 | return 0; |
| @@ -201,7 +179,7 @@ static int nft_deltable(struct nft_ctx *ctx) | |||
| 201 | if (err < 0) | 179 | if (err < 0) |
| 202 | return err; | 180 | return err; |
| 203 | 181 | ||
| 204 | list_del_rcu(&ctx->table->list); | 182 | nft_deactivate_next(ctx->net, ctx->table); |
| 205 | return err; | 183 | return err; |
| 206 | } | 184 | } |
| 207 | 185 | ||
| @@ -214,7 +192,7 @@ static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) | |||
| 214 | return -ENOMEM; | 192 | return -ENOMEM; |
| 215 | 193 | ||
| 216 | if (msg_type == NFT_MSG_NEWCHAIN) | 194 | if (msg_type == NFT_MSG_NEWCHAIN) |
| 217 | ctx->chain->flags |= NFT_CHAIN_INACTIVE; | 195 | nft_activate_next(ctx->net, ctx->chain); |
| 218 | 196 | ||
| 219 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 197 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
| 220 | return 0; | 198 | return 0; |
| @@ -229,47 +207,17 @@ static int nft_delchain(struct nft_ctx *ctx) | |||
| 229 | return err; | 207 | return err; |
| 230 | 208 | ||
| 231 | ctx->table->use--; | 209 | ctx->table->use--; |
| 232 | list_del_rcu(&ctx->chain->list); | 210 | nft_deactivate_next(ctx->net, ctx->chain); |
| 233 | 211 | ||
| 234 | return err; | 212 | return err; |
| 235 | } | 213 | } |
| 236 | 214 | ||
| 237 | static inline bool | ||
| 238 | nft_rule_is_active(struct net *net, const struct nft_rule *rule) | ||
| 239 | { | ||
| 240 | return (rule->genmask & nft_genmask_cur(net)) == 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static inline int | ||
| 244 | nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) | ||
| 245 | { | ||
| 246 | return (rule->genmask & nft_genmask_next(net)) == 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static inline void | ||
| 250 | nft_rule_activate_next(struct net *net, struct nft_rule *rule) | ||
| 251 | { | ||
| 252 | /* Now inactive, will be active in the future */ | ||
| 253 | rule->genmask = nft_genmask_cur(net); | ||
| 254 | } | ||
| 255 | |||
| 256 | static inline void | ||
| 257 | nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) | ||
| 258 | { | ||
| 259 | rule->genmask = nft_genmask_next(net); | ||
| 260 | } | ||
| 261 | |||
| 262 | static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) | ||
| 263 | { | ||
| 264 | rule->genmask &= ~nft_genmask_next(net); | ||
| 265 | } | ||
| 266 | |||
| 267 | static int | 215 | static int |
| 268 | nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) | 216 | nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) |
| 269 | { | 217 | { |
| 270 | /* You cannot delete the same rule twice */ | 218 | /* You cannot delete the same rule twice */ |
| 271 | if (nft_rule_is_active_next(ctx->net, rule)) { | 219 | if (nft_is_active_next(ctx->net, rule)) { |
| 272 | nft_rule_deactivate_next(ctx->net, rule); | 220 | nft_deactivate_next(ctx->net, rule); |
| 273 | ctx->chain->use--; | 221 | ctx->chain->use--; |
| 274 | return 0; | 222 | return 0; |
| 275 | } | 223 | } |
| @@ -322,9 +270,6 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx) | |||
| 322 | return 0; | 270 | return 0; |
| 323 | } | 271 | } |
| 324 | 272 | ||
| 325 | /* Internal set flag */ | ||
| 326 | #define NFT_SET_INACTIVE (1 << 15) | ||
| 327 | |||
| 328 | static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type, | 273 | static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type, |
| 329 | struct nft_set *set) | 274 | struct nft_set *set) |
| 330 | { | 275 | { |
| @@ -337,7 +282,7 @@ static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type, | |||
| 337 | if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) { | 282 | if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) { |
| 338 | nft_trans_set_id(trans) = | 283 | nft_trans_set_id(trans) = |
| 339 | ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID])); | 284 | ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID])); |
| 340 | set->flags |= NFT_SET_INACTIVE; | 285 | nft_activate_next(ctx->net, set); |
| 341 | } | 286 | } |
| 342 | nft_trans_set(trans) = set; | 287 | nft_trans_set(trans) = set; |
| 343 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 288 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
| @@ -353,7 +298,7 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set) | |||
| 353 | if (err < 0) | 298 | if (err < 0) |
| 354 | return err; | 299 | return err; |
| 355 | 300 | ||
| 356 | list_del_rcu(&set->list); | 301 | nft_deactivate_next(ctx->net, set); |
| 357 | ctx->table->use--; | 302 | ctx->table->use--; |
| 358 | 303 | ||
| 359 | return err; | 304 | return err; |
| @@ -364,26 +309,29 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set) | |||
| 364 | */ | 309 | */ |
| 365 | 310 | ||
| 366 | static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, | 311 | static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, |
| 367 | const struct nlattr *nla) | 312 | const struct nlattr *nla, |
| 313 | u8 genmask) | ||
| 368 | { | 314 | { |
| 369 | struct nft_table *table; | 315 | struct nft_table *table; |
| 370 | 316 | ||
| 371 | list_for_each_entry(table, &afi->tables, list) { | 317 | list_for_each_entry(table, &afi->tables, list) { |
| 372 | if (!nla_strcmp(nla, table->name)) | 318 | if (!nla_strcmp(nla, table->name) && |
| 319 | nft_active_genmask(table, genmask)) | ||
| 373 | return table; | 320 | return table; |
| 374 | } | 321 | } |
| 375 | return NULL; | 322 | return NULL; |
| 376 | } | 323 | } |
| 377 | 324 | ||
| 378 | static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, | 325 | static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, |
| 379 | const struct nlattr *nla) | 326 | const struct nlattr *nla, |
| 327 | u8 genmask) | ||
| 380 | { | 328 | { |
| 381 | struct nft_table *table; | 329 | struct nft_table *table; |
| 382 | 330 | ||
| 383 | if (nla == NULL) | 331 | if (nla == NULL) |
| 384 | return ERR_PTR(-EINVAL); | 332 | return ERR_PTR(-EINVAL); |
| 385 | 333 | ||
| 386 | table = nft_table_lookup(afi, nla); | 334 | table = nft_table_lookup(afi, nla, genmask); |
| 387 | if (table != NULL) | 335 | if (table != NULL) |
| 388 | return table; | 336 | return table; |
| 389 | 337 | ||
| @@ -524,6 +472,8 @@ static int nf_tables_dump_tables(struct sk_buff *skb, | |||
| 524 | if (idx > s_idx) | 472 | if (idx > s_idx) |
| 525 | memset(&cb->args[1], 0, | 473 | memset(&cb->args[1], 0, |
| 526 | sizeof(cb->args) - sizeof(cb->args[0])); | 474 | sizeof(cb->args) - sizeof(cb->args[0])); |
| 475 | if (!nft_is_active(net, table)) | ||
| 476 | continue; | ||
| 527 | if (nf_tables_fill_table_info(skb, net, | 477 | if (nf_tables_fill_table_info(skb, net, |
| 528 | NETLINK_CB(cb->skb).portid, | 478 | NETLINK_CB(cb->skb).portid, |
| 529 | cb->nlh->nlmsg_seq, | 479 | cb->nlh->nlmsg_seq, |
| @@ -548,6 +498,7 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk, | |||
| 548 | const struct nlattr * const nla[]) | 498 | const struct nlattr * const nla[]) |
| 549 | { | 499 | { |
| 550 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 500 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 501 | u8 genmask = nft_genmask_cur(net); | ||
| 551 | const struct nft_af_info *afi; | 502 | const struct nft_af_info *afi; |
| 552 | const struct nft_table *table; | 503 | const struct nft_table *table; |
| 553 | struct sk_buff *skb2; | 504 | struct sk_buff *skb2; |
| @@ -565,11 +516,9 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk, | |||
| 565 | if (IS_ERR(afi)) | 516 | if (IS_ERR(afi)) |
| 566 | return PTR_ERR(afi); | 517 | return PTR_ERR(afi); |
| 567 | 518 | ||
| 568 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]); | 519 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); |
| 569 | if (IS_ERR(table)) | 520 | if (IS_ERR(table)) |
| 570 | return PTR_ERR(table); | 521 | return PTR_ERR(table); |
| 571 | if (table->flags & NFT_TABLE_INACTIVE) | ||
| 572 | return -ENOENT; | ||
| 573 | 522 | ||
| 574 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 523 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 575 | if (!skb2) | 524 | if (!skb2) |
| @@ -588,17 +537,21 @@ err: | |||
| 588 | return err; | 537 | return err; |
| 589 | } | 538 | } |
| 590 | 539 | ||
| 591 | static int nf_tables_table_enable(const struct nft_af_info *afi, | 540 | static int nf_tables_table_enable(struct net *net, |
| 541 | const struct nft_af_info *afi, | ||
| 592 | struct nft_table *table) | 542 | struct nft_table *table) |
| 593 | { | 543 | { |
| 594 | struct nft_chain *chain; | 544 | struct nft_chain *chain; |
| 595 | int err, i = 0; | 545 | int err, i = 0; |
| 596 | 546 | ||
| 597 | list_for_each_entry(chain, &table->chains, list) { | 547 | list_for_each_entry(chain, &table->chains, list) { |
| 548 | if (!nft_is_active_next(net, chain)) | ||
| 549 | continue; | ||
| 598 | if (!(chain->flags & NFT_BASE_CHAIN)) | 550 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| 599 | continue; | 551 | continue; |
| 600 | 552 | ||
| 601 | err = nft_register_basechain(nft_base_chain(chain), afi->nops); | 553 | err = nf_register_net_hooks(net, nft_base_chain(chain)->ops, |
| 554 | afi->nops); | ||
| 602 | if (err < 0) | 555 | if (err < 0) |
| 603 | goto err; | 556 | goto err; |
| 604 | 557 | ||
| @@ -607,26 +560,34 @@ static int nf_tables_table_enable(const struct nft_af_info *afi, | |||
| 607 | return 0; | 560 | return 0; |
| 608 | err: | 561 | err: |
| 609 | list_for_each_entry(chain, &table->chains, list) { | 562 | list_for_each_entry(chain, &table->chains, list) { |
| 563 | if (!nft_is_active_next(net, chain)) | ||
| 564 | continue; | ||
| 610 | if (!(chain->flags & NFT_BASE_CHAIN)) | 565 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| 611 | continue; | 566 | continue; |
| 612 | 567 | ||
| 613 | if (i-- <= 0) | 568 | if (i-- <= 0) |
| 614 | break; | 569 | break; |
| 615 | 570 | ||
| 616 | nft_unregister_basechain(nft_base_chain(chain), afi->nops); | 571 | nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, |
| 572 | afi->nops); | ||
| 617 | } | 573 | } |
| 618 | return err; | 574 | return err; |
| 619 | } | 575 | } |
| 620 | 576 | ||
| 621 | static void nf_tables_table_disable(const struct nft_af_info *afi, | 577 | static void nf_tables_table_disable(struct net *net, |
| 578 | const struct nft_af_info *afi, | ||
| 622 | struct nft_table *table) | 579 | struct nft_table *table) |
| 623 | { | 580 | { |
| 624 | struct nft_chain *chain; | 581 | struct nft_chain *chain; |
| 625 | 582 | ||
| 626 | list_for_each_entry(chain, &table->chains, list) { | 583 | list_for_each_entry(chain, &table->chains, list) { |
| 627 | if (chain->flags & NFT_BASE_CHAIN) | 584 | if (!nft_is_active_next(net, chain)) |
| 628 | nft_unregister_basechain(nft_base_chain(chain), | 585 | continue; |
| 629 | afi->nops); | 586 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| 587 | continue; | ||
| 588 | |||
| 589 | nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, | ||
| 590 | afi->nops); | ||
| 630 | } | 591 | } |
| 631 | } | 592 | } |
| 632 | 593 | ||
| @@ -656,7 +617,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx) | |||
| 656 | nft_trans_table_enable(trans) = false; | 617 | nft_trans_table_enable(trans) = false; |
| 657 | } else if (!(flags & NFT_TABLE_F_DORMANT) && | 618 | } else if (!(flags & NFT_TABLE_F_DORMANT) && |
| 658 | ctx->table->flags & NFT_TABLE_F_DORMANT) { | 619 | ctx->table->flags & NFT_TABLE_F_DORMANT) { |
| 659 | ret = nf_tables_table_enable(ctx->afi, ctx->table); | 620 | ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table); |
| 660 | if (ret >= 0) { | 621 | if (ret >= 0) { |
| 661 | ctx->table->flags &= ~NFT_TABLE_F_DORMANT; | 622 | ctx->table->flags &= ~NFT_TABLE_F_DORMANT; |
| 662 | nft_trans_table_enable(trans) = true; | 623 | nft_trans_table_enable(trans) = true; |
| @@ -678,6 +639,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, | |||
| 678 | const struct nlattr * const nla[]) | 639 | const struct nlattr * const nla[]) |
| 679 | { | 640 | { |
| 680 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 641 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 642 | u8 genmask = nft_genmask_next(net); | ||
| 681 | const struct nlattr *name; | 643 | const struct nlattr *name; |
| 682 | struct nft_af_info *afi; | 644 | struct nft_af_info *afi; |
| 683 | struct nft_table *table; | 645 | struct nft_table *table; |
| @@ -691,7 +653,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, | |||
| 691 | return PTR_ERR(afi); | 653 | return PTR_ERR(afi); |
| 692 | 654 | ||
| 693 | name = nla[NFTA_TABLE_NAME]; | 655 | name = nla[NFTA_TABLE_NAME]; |
| 694 | table = nf_tables_table_lookup(afi, name); | 656 | table = nf_tables_table_lookup(afi, name, genmask); |
| 695 | if (IS_ERR(table)) { | 657 | if (IS_ERR(table)) { |
| 696 | if (PTR_ERR(table) != -ENOENT) | 658 | if (PTR_ERR(table) != -ENOENT) |
| 697 | return PTR_ERR(table); | 659 | return PTR_ERR(table); |
| @@ -699,8 +661,6 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, | |||
| 699 | } | 661 | } |
| 700 | 662 | ||
| 701 | if (table != NULL) { | 663 | if (table != NULL) { |
| 702 | if (table->flags & NFT_TABLE_INACTIVE) | ||
| 703 | return -ENOENT; | ||
| 704 | if (nlh->nlmsg_flags & NLM_F_EXCL) | 664 | if (nlh->nlmsg_flags & NLM_F_EXCL) |
| 705 | return -EEXIST; | 665 | return -EEXIST; |
| 706 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | 666 | if (nlh->nlmsg_flags & NLM_F_REPLACE) |
| @@ -752,6 +712,9 @@ static int nft_flush_table(struct nft_ctx *ctx) | |||
| 752 | struct nft_set *set, *ns; | 712 | struct nft_set *set, *ns; |
| 753 | 713 | ||
| 754 | list_for_each_entry(chain, &ctx->table->chains, list) { | 714 | list_for_each_entry(chain, &ctx->table->chains, list) { |
| 715 | if (!nft_is_active_next(ctx->net, chain)) | ||
| 716 | continue; | ||
| 717 | |||
| 755 | ctx->chain = chain; | 718 | ctx->chain = chain; |
| 756 | 719 | ||
| 757 | err = nft_delrule_by_chain(ctx); | 720 | err = nft_delrule_by_chain(ctx); |
| @@ -760,6 +723,9 @@ static int nft_flush_table(struct nft_ctx *ctx) | |||
| 760 | } | 723 | } |
| 761 | 724 | ||
| 762 | list_for_each_entry_safe(set, ns, &ctx->table->sets, list) { | 725 | list_for_each_entry_safe(set, ns, &ctx->table->sets, list) { |
| 726 | if (!nft_is_active_next(ctx->net, set)) | ||
| 727 | continue; | ||
| 728 | |||
| 763 | if (set->flags & NFT_SET_ANONYMOUS && | 729 | if (set->flags & NFT_SET_ANONYMOUS && |
| 764 | !list_empty(&set->bindings)) | 730 | !list_empty(&set->bindings)) |
| 765 | continue; | 731 | continue; |
| @@ -770,6 +736,9 @@ static int nft_flush_table(struct nft_ctx *ctx) | |||
| 770 | } | 736 | } |
| 771 | 737 | ||
| 772 | list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) { | 738 | list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) { |
| 739 | if (!nft_is_active_next(ctx->net, chain)) | ||
| 740 | continue; | ||
| 741 | |||
| 773 | ctx->chain = chain; | 742 | ctx->chain = chain; |
| 774 | 743 | ||
| 775 | err = nft_delchain(ctx); | 744 | err = nft_delchain(ctx); |
| @@ -795,6 +764,9 @@ static int nft_flush(struct nft_ctx *ctx, int family) | |||
| 795 | 764 | ||
| 796 | ctx->afi = afi; | 765 | ctx->afi = afi; |
| 797 | list_for_each_entry_safe(table, nt, &afi->tables, list) { | 766 | list_for_each_entry_safe(table, nt, &afi->tables, list) { |
| 767 | if (!nft_is_active_next(ctx->net, table)) | ||
| 768 | continue; | ||
| 769 | |||
| 798 | if (nla[NFTA_TABLE_NAME] && | 770 | if (nla[NFTA_TABLE_NAME] && |
| 799 | nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) | 771 | nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) |
| 800 | continue; | 772 | continue; |
| @@ -815,6 +787,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, | |||
| 815 | const struct nlattr * const nla[]) | 787 | const struct nlattr * const nla[]) |
| 816 | { | 788 | { |
| 817 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 789 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 790 | u8 genmask = nft_genmask_next(net); | ||
| 818 | struct nft_af_info *afi; | 791 | struct nft_af_info *afi; |
| 819 | struct nft_table *table; | 792 | struct nft_table *table; |
| 820 | int family = nfmsg->nfgen_family; | 793 | int family = nfmsg->nfgen_family; |
| @@ -828,7 +801,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, | |||
| 828 | if (IS_ERR(afi)) | 801 | if (IS_ERR(afi)) |
| 829 | return PTR_ERR(afi); | 802 | return PTR_ERR(afi); |
| 830 | 803 | ||
| 831 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]); | 804 | table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); |
| 832 | if (IS_ERR(table)) | 805 | if (IS_ERR(table)) |
| 833 | return PTR_ERR(table); | 806 | return PTR_ERR(table); |
| 834 | 807 | ||
| @@ -875,12 +848,14 @@ EXPORT_SYMBOL_GPL(nft_unregister_chain_type); | |||
| 875 | */ | 848 | */ |
| 876 | 849 | ||
| 877 | static struct nft_chain * | 850 | static struct nft_chain * |
| 878 | nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle) | 851 | nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle, |
| 852 | u8 genmask) | ||
| 879 | { | 853 | { |
| 880 | struct nft_chain *chain; | 854 | struct nft_chain *chain; |
| 881 | 855 | ||
| 882 | list_for_each_entry(chain, &table->chains, list) { | 856 | list_for_each_entry(chain, &table->chains, list) { |
| 883 | if (chain->handle == handle) | 857 | if (chain->handle == handle && |
| 858 | nft_active_genmask(chain, genmask)) | ||
| 884 | return chain; | 859 | return chain; |
| 885 | } | 860 | } |
| 886 | 861 | ||
| @@ -888,7 +863,8 @@ nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle) | |||
| 888 | } | 863 | } |
| 889 | 864 | ||
| 890 | static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table, | 865 | static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table, |
| 891 | const struct nlattr *nla) | 866 | const struct nlattr *nla, |
| 867 | u8 genmask) | ||
| 892 | { | 868 | { |
| 893 | struct nft_chain *chain; | 869 | struct nft_chain *chain; |
| 894 | 870 | ||
| @@ -896,7 +872,8 @@ static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table, | |||
| 896 | return ERR_PTR(-EINVAL); | 872 | return ERR_PTR(-EINVAL); |
| 897 | 873 | ||
| 898 | list_for_each_entry(chain, &table->chains, list) { | 874 | list_for_each_entry(chain, &table->chains, list) { |
| 899 | if (!nla_strcmp(nla, chain->name)) | 875 | if (!nla_strcmp(nla, chain->name) && |
| 876 | nft_active_genmask(chain, genmask)) | ||
| 900 | return chain; | 877 | return chain; |
| 901 | } | 878 | } |
| 902 | 879 | ||
| @@ -1079,6 +1056,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb, | |||
| 1079 | if (idx > s_idx) | 1056 | if (idx > s_idx) |
| 1080 | memset(&cb->args[1], 0, | 1057 | memset(&cb->args[1], 0, |
| 1081 | sizeof(cb->args) - sizeof(cb->args[0])); | 1058 | sizeof(cb->args) - sizeof(cb->args[0])); |
| 1059 | if (!nft_is_active(net, chain)) | ||
| 1060 | continue; | ||
| 1082 | if (nf_tables_fill_chain_info(skb, net, | 1061 | if (nf_tables_fill_chain_info(skb, net, |
| 1083 | NETLINK_CB(cb->skb).portid, | 1062 | NETLINK_CB(cb->skb).portid, |
| 1084 | cb->nlh->nlmsg_seq, | 1063 | cb->nlh->nlmsg_seq, |
| @@ -1104,6 +1083,7 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk, | |||
| 1104 | const struct nlattr * const nla[]) | 1083 | const struct nlattr * const nla[]) |
| 1105 | { | 1084 | { |
| 1106 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1085 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 1086 | u8 genmask = nft_genmask_cur(net); | ||
| 1107 | const struct nft_af_info *afi; | 1087 | const struct nft_af_info *afi; |
| 1108 | const struct nft_table *table; | 1088 | const struct nft_table *table; |
| 1109 | const struct nft_chain *chain; | 1089 | const struct nft_chain *chain; |
| @@ -1122,17 +1102,13 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk, | |||
| 1122 | if (IS_ERR(afi)) | 1102 | if (IS_ERR(afi)) |
| 1123 | return PTR_ERR(afi); | 1103 | return PTR_ERR(afi); |
| 1124 | 1104 | ||
| 1125 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]); | 1105 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); |
| 1126 | if (IS_ERR(table)) | 1106 | if (IS_ERR(table)) |
| 1127 | return PTR_ERR(table); | 1107 | return PTR_ERR(table); |
| 1128 | if (table->flags & NFT_TABLE_INACTIVE) | ||
| 1129 | return -ENOENT; | ||
| 1130 | 1108 | ||
| 1131 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]); | 1109 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
| 1132 | if (IS_ERR(chain)) | 1110 | if (IS_ERR(chain)) |
| 1133 | return PTR_ERR(chain); | 1111 | return PTR_ERR(chain); |
| 1134 | if (chain->flags & NFT_CHAIN_INACTIVE) | ||
| 1135 | return -ENOENT; | ||
| 1136 | 1112 | ||
| 1137 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 1113 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 1138 | if (!skb2) | 1114 | if (!skb2) |
| @@ -1231,6 +1207,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1231 | struct nft_chain *chain; | 1207 | struct nft_chain *chain; |
| 1232 | struct nft_base_chain *basechain = NULL; | 1208 | struct nft_base_chain *basechain = NULL; |
| 1233 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; | 1209 | struct nlattr *ha[NFTA_HOOK_MAX + 1]; |
| 1210 | u8 genmask = nft_genmask_next(net); | ||
| 1234 | int family = nfmsg->nfgen_family; | 1211 | int family = nfmsg->nfgen_family; |
| 1235 | struct net_device *dev = NULL; | 1212 | struct net_device *dev = NULL; |
| 1236 | u8 policy = NF_ACCEPT; | 1213 | u8 policy = NF_ACCEPT; |
| @@ -1247,7 +1224,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1247 | if (IS_ERR(afi)) | 1224 | if (IS_ERR(afi)) |
| 1248 | return PTR_ERR(afi); | 1225 | return PTR_ERR(afi); |
| 1249 | 1226 | ||
| 1250 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]); | 1227 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); |
| 1251 | if (IS_ERR(table)) | 1228 | if (IS_ERR(table)) |
| 1252 | return PTR_ERR(table); | 1229 | return PTR_ERR(table); |
| 1253 | 1230 | ||
| @@ -1256,11 +1233,11 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1256 | 1233 | ||
| 1257 | if (nla[NFTA_CHAIN_HANDLE]) { | 1234 | if (nla[NFTA_CHAIN_HANDLE]) { |
| 1258 | handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); | 1235 | handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); |
| 1259 | chain = nf_tables_chain_lookup_byhandle(table, handle); | 1236 | chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); |
| 1260 | if (IS_ERR(chain)) | 1237 | if (IS_ERR(chain)) |
| 1261 | return PTR_ERR(chain); | 1238 | return PTR_ERR(chain); |
| 1262 | } else { | 1239 | } else { |
| 1263 | chain = nf_tables_chain_lookup(table, name); | 1240 | chain = nf_tables_chain_lookup(table, name, genmask); |
| 1264 | if (IS_ERR(chain)) { | 1241 | if (IS_ERR(chain)) { |
| 1265 | if (PTR_ERR(chain) != -ENOENT) | 1242 | if (PTR_ERR(chain) != -ENOENT) |
| 1266 | return PTR_ERR(chain); | 1243 | return PTR_ERR(chain); |
| @@ -1291,16 +1268,20 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1291 | struct nft_stats *stats = NULL; | 1268 | struct nft_stats *stats = NULL; |
| 1292 | struct nft_trans *trans; | 1269 | struct nft_trans *trans; |
| 1293 | 1270 | ||
| 1294 | if (chain->flags & NFT_CHAIN_INACTIVE) | ||
| 1295 | return -ENOENT; | ||
| 1296 | if (nlh->nlmsg_flags & NLM_F_EXCL) | 1271 | if (nlh->nlmsg_flags & NLM_F_EXCL) |
| 1297 | return -EEXIST; | 1272 | return -EEXIST; |
| 1298 | if (nlh->nlmsg_flags & NLM_F_REPLACE) | 1273 | if (nlh->nlmsg_flags & NLM_F_REPLACE) |
| 1299 | return -EOPNOTSUPP; | 1274 | return -EOPNOTSUPP; |
| 1300 | 1275 | ||
| 1301 | if (nla[NFTA_CHAIN_HANDLE] && name && | 1276 | if (nla[NFTA_CHAIN_HANDLE] && name) { |
| 1302 | !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]))) | 1277 | struct nft_chain *chain2; |
| 1303 | return -EEXIST; | 1278 | |
| 1279 | chain2 = nf_tables_chain_lookup(table, | ||
| 1280 | nla[NFTA_CHAIN_NAME], | ||
| 1281 | genmask); | ||
| 1282 | if (IS_ERR(chain2)) | ||
| 1283 | return PTR_ERR(chain2); | ||
| 1284 | } | ||
| 1304 | 1285 | ||
| 1305 | if (nla[NFTA_CHAIN_COUNTERS]) { | 1286 | if (nla[NFTA_CHAIN_COUNTERS]) { |
| 1306 | if (!(chain->flags & NFT_BASE_CHAIN)) | 1287 | if (!(chain->flags & NFT_BASE_CHAIN)) |
| @@ -1455,7 +1436,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1455 | chain->table = table; | 1436 | chain->table = table; |
| 1456 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); | 1437 | nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN); |
| 1457 | 1438 | ||
| 1458 | err = nf_tables_register_hooks(table, chain, afi->nops); | 1439 | err = nf_tables_register_hooks(net, table, chain, afi->nops); |
| 1459 | if (err < 0) | 1440 | if (err < 0) |
| 1460 | goto err1; | 1441 | goto err1; |
| 1461 | 1442 | ||
| @@ -1468,7 +1449,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, | |||
| 1468 | list_add_tail_rcu(&chain->list, &table->chains); | 1449 | list_add_tail_rcu(&chain->list, &table->chains); |
| 1469 | return 0; | 1450 | return 0; |
| 1470 | err2: | 1451 | err2: |
| 1471 | nf_tables_unregister_hooks(table, chain, afi->nops); | 1452 | nf_tables_unregister_hooks(net, table, chain, afi->nops); |
| 1472 | err1: | 1453 | err1: |
| 1473 | nf_tables_chain_destroy(chain); | 1454 | nf_tables_chain_destroy(chain); |
| 1474 | return err; | 1455 | return err; |
| @@ -1479,6 +1460,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, | |||
| 1479 | const struct nlattr * const nla[]) | 1460 | const struct nlattr * const nla[]) |
| 1480 | { | 1461 | { |
| 1481 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1462 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 1463 | u8 genmask = nft_genmask_next(net); | ||
| 1482 | struct nft_af_info *afi; | 1464 | struct nft_af_info *afi; |
| 1483 | struct nft_table *table; | 1465 | struct nft_table *table; |
| 1484 | struct nft_chain *chain; | 1466 | struct nft_chain *chain; |
| @@ -1489,11 +1471,11 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, | |||
| 1489 | if (IS_ERR(afi)) | 1471 | if (IS_ERR(afi)) |
| 1490 | return PTR_ERR(afi); | 1472 | return PTR_ERR(afi); |
| 1491 | 1473 | ||
| 1492 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]); | 1474 | table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); |
| 1493 | if (IS_ERR(table)) | 1475 | if (IS_ERR(table)) |
| 1494 | return PTR_ERR(table); | 1476 | return PTR_ERR(table); |
| 1495 | 1477 | ||
| 1496 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]); | 1478 | chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
| 1497 | if (IS_ERR(chain)) | 1479 | if (IS_ERR(chain)) |
| 1498 | return PTR_ERR(chain); | 1480 | return PTR_ERR(chain); |
| 1499 | if (chain->use > 0) | 1481 | if (chain->use > 0) |
| @@ -1898,7 +1880,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb, | |||
| 1898 | list_for_each_entry_rcu(table, &afi->tables, list) { | 1880 | list_for_each_entry_rcu(table, &afi->tables, list) { |
| 1899 | list_for_each_entry_rcu(chain, &table->chains, list) { | 1881 | list_for_each_entry_rcu(chain, &table->chains, list) { |
| 1900 | list_for_each_entry_rcu(rule, &chain->rules, list) { | 1882 | list_for_each_entry_rcu(rule, &chain->rules, list) { |
| 1901 | if (!nft_rule_is_active(net, rule)) | 1883 | if (!nft_is_active(net, rule)) |
| 1902 | goto cont; | 1884 | goto cont; |
| 1903 | if (idx < s_idx) | 1885 | if (idx < s_idx) |
| 1904 | goto cont; | 1886 | goto cont; |
| @@ -1931,6 +1913,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, | |||
| 1931 | const struct nlattr * const nla[]) | 1913 | const struct nlattr * const nla[]) |
| 1932 | { | 1914 | { |
| 1933 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1915 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 1916 | u8 genmask = nft_genmask_cur(net); | ||
| 1934 | const struct nft_af_info *afi; | 1917 | const struct nft_af_info *afi; |
| 1935 | const struct nft_table *table; | 1918 | const struct nft_table *table; |
| 1936 | const struct nft_chain *chain; | 1919 | const struct nft_chain *chain; |
| @@ -1950,17 +1933,13 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk, | |||
| 1950 | if (IS_ERR(afi)) | 1933 | if (IS_ERR(afi)) |
| 1951 | return PTR_ERR(afi); | 1934 | return PTR_ERR(afi); |
| 1952 | 1935 | ||
| 1953 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]); | 1936 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); |
| 1954 | if (IS_ERR(table)) | 1937 | if (IS_ERR(table)) |
| 1955 | return PTR_ERR(table); | 1938 | return PTR_ERR(table); |
| 1956 | if (table->flags & NFT_TABLE_INACTIVE) | ||
| 1957 | return -ENOENT; | ||
| 1958 | 1939 | ||
| 1959 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); | 1940 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask); |
| 1960 | if (IS_ERR(chain)) | 1941 | if (IS_ERR(chain)) |
| 1961 | return PTR_ERR(chain); | 1942 | return PTR_ERR(chain); |
| 1962 | if (chain->flags & NFT_CHAIN_INACTIVE) | ||
| 1963 | return -ENOENT; | ||
| 1964 | 1943 | ||
| 1965 | rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); | 1944 | rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]); |
| 1966 | if (IS_ERR(rule)) | 1945 | if (IS_ERR(rule)) |
| @@ -2009,6 +1988,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, | |||
| 2009 | const struct nlattr * const nla[]) | 1988 | const struct nlattr * const nla[]) |
| 2010 | { | 1989 | { |
| 2011 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1990 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 1991 | u8 genmask = nft_genmask_next(net); | ||
| 2012 | struct nft_af_info *afi; | 1992 | struct nft_af_info *afi; |
| 2013 | struct nft_table *table; | 1993 | struct nft_table *table; |
| 2014 | struct nft_chain *chain; | 1994 | struct nft_chain *chain; |
| @@ -2029,11 +2009,11 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, | |||
| 2029 | if (IS_ERR(afi)) | 2009 | if (IS_ERR(afi)) |
| 2030 | return PTR_ERR(afi); | 2010 | return PTR_ERR(afi); |
| 2031 | 2011 | ||
| 2032 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]); | 2012 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); |
| 2033 | if (IS_ERR(table)) | 2013 | if (IS_ERR(table)) |
| 2034 | return PTR_ERR(table); | 2014 | return PTR_ERR(table); |
| 2035 | 2015 | ||
| 2036 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); | 2016 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask); |
| 2037 | if (IS_ERR(chain)) | 2017 | if (IS_ERR(chain)) |
| 2038 | return PTR_ERR(chain); | 2018 | return PTR_ERR(chain); |
| 2039 | 2019 | ||
| @@ -2102,7 +2082,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, | |||
| 2102 | if (rule == NULL) | 2082 | if (rule == NULL) |
| 2103 | goto err1; | 2083 | goto err1; |
| 2104 | 2084 | ||
| 2105 | nft_rule_activate_next(net, rule); | 2085 | nft_activate_next(net, rule); |
| 2106 | 2086 | ||
| 2107 | rule->handle = handle; | 2087 | rule->handle = handle; |
| 2108 | rule->dlen = size; | 2088 | rule->dlen = size; |
| @@ -2124,14 +2104,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, | |||
| 2124 | } | 2104 | } |
| 2125 | 2105 | ||
| 2126 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | 2106 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { |
| 2127 | if (nft_rule_is_active_next(net, old_rule)) { | 2107 | if (nft_is_active_next(net, old_rule)) { |
| 2128 | trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE, | 2108 | trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE, |
| 2129 | old_rule); | 2109 | old_rule); |
| 2130 | if (trans == NULL) { | 2110 | if (trans == NULL) { |
| 2131 | err = -ENOMEM; | 2111 | err = -ENOMEM; |
| 2132 | goto err2; | 2112 | goto err2; |
| 2133 | } | 2113 | } |
| 2134 | nft_rule_deactivate_next(net, old_rule); | 2114 | nft_deactivate_next(net, old_rule); |
| 2135 | chain->use--; | 2115 | chain->use--; |
| 2136 | list_add_tail_rcu(&rule->list, &old_rule->list); | 2116 | list_add_tail_rcu(&rule->list, &old_rule->list); |
| 2137 | } else { | 2117 | } else { |
| @@ -2174,6 +2154,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, | |||
| 2174 | const struct nlattr * const nla[]) | 2154 | const struct nlattr * const nla[]) |
| 2175 | { | 2155 | { |
| 2176 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2156 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 2157 | u8 genmask = nft_genmask_next(net); | ||
| 2177 | struct nft_af_info *afi; | 2158 | struct nft_af_info *afi; |
| 2178 | struct nft_table *table; | 2159 | struct nft_table *table; |
| 2179 | struct nft_chain *chain = NULL; | 2160 | struct nft_chain *chain = NULL; |
| @@ -2185,12 +2166,13 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, | |||
| 2185 | if (IS_ERR(afi)) | 2166 | if (IS_ERR(afi)) |
| 2186 | return PTR_ERR(afi); | 2167 | return PTR_ERR(afi); |
| 2187 | 2168 | ||
| 2188 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]); | 2169 | table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); |
| 2189 | if (IS_ERR(table)) | 2170 | if (IS_ERR(table)) |
| 2190 | return PTR_ERR(table); | 2171 | return PTR_ERR(table); |
| 2191 | 2172 | ||
| 2192 | if (nla[NFTA_RULE_CHAIN]) { | 2173 | if (nla[NFTA_RULE_CHAIN]) { |
| 2193 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]); | 2174 | chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], |
| 2175 | genmask); | ||
| 2194 | if (IS_ERR(chain)) | 2176 | if (IS_ERR(chain)) |
| 2195 | return PTR_ERR(chain); | 2177 | return PTR_ERR(chain); |
| 2196 | } | 2178 | } |
| @@ -2210,6 +2192,9 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk, | |||
| 2210 | } | 2192 | } |
| 2211 | } else { | 2193 | } else { |
| 2212 | list_for_each_entry(chain, &table->chains, list) { | 2194 | list_for_each_entry(chain, &table->chains, list) { |
| 2195 | if (!nft_is_active_next(net, chain)) | ||
| 2196 | continue; | ||
| 2197 | |||
| 2213 | ctx.chain = chain; | 2198 | ctx.chain = chain; |
| 2214 | err = nft_delrule_by_chain(&ctx); | 2199 | err = nft_delrule_by_chain(&ctx); |
| 2215 | if (err < 0) | 2200 | if (err < 0) |
| @@ -2339,7 +2324,8 @@ static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { | |||
| 2339 | static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, | 2324 | static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, |
| 2340 | const struct sk_buff *skb, | 2325 | const struct sk_buff *skb, |
| 2341 | const struct nlmsghdr *nlh, | 2326 | const struct nlmsghdr *nlh, |
| 2342 | const struct nlattr * const nla[]) | 2327 | const struct nlattr * const nla[], |
| 2328 | u8 genmask) | ||
| 2343 | { | 2329 | { |
| 2344 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2330 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 2345 | struct nft_af_info *afi = NULL; | 2331 | struct nft_af_info *afi = NULL; |
| @@ -2355,7 +2341,8 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, | |||
| 2355 | if (afi == NULL) | 2341 | if (afi == NULL) |
| 2356 | return -EAFNOSUPPORT; | 2342 | return -EAFNOSUPPORT; |
| 2357 | 2343 | ||
| 2358 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 2344 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], |
| 2345 | genmask); | ||
| 2359 | if (IS_ERR(table)) | 2346 | if (IS_ERR(table)) |
| 2360 | return PTR_ERR(table); | 2347 | return PTR_ERR(table); |
| 2361 | } | 2348 | } |
| @@ -2365,7 +2352,7 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net, | |||
| 2365 | } | 2352 | } |
| 2366 | 2353 | ||
| 2367 | struct nft_set *nf_tables_set_lookup(const struct nft_table *table, | 2354 | struct nft_set *nf_tables_set_lookup(const struct nft_table *table, |
| 2368 | const struct nlattr *nla) | 2355 | const struct nlattr *nla, u8 genmask) |
| 2369 | { | 2356 | { |
| 2370 | struct nft_set *set; | 2357 | struct nft_set *set; |
| 2371 | 2358 | ||
| @@ -2373,22 +2360,27 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table, | |||
| 2373 | return ERR_PTR(-EINVAL); | 2360 | return ERR_PTR(-EINVAL); |
| 2374 | 2361 | ||
| 2375 | list_for_each_entry(set, &table->sets, list) { | 2362 | list_for_each_entry(set, &table->sets, list) { |
| 2376 | if (!nla_strcmp(nla, set->name)) | 2363 | if (!nla_strcmp(nla, set->name) && |
| 2364 | nft_active_genmask(set, genmask)) | ||
| 2377 | return set; | 2365 | return set; |
| 2378 | } | 2366 | } |
| 2379 | return ERR_PTR(-ENOENT); | 2367 | return ERR_PTR(-ENOENT); |
| 2380 | } | 2368 | } |
| 2381 | 2369 | ||
| 2382 | struct nft_set *nf_tables_set_lookup_byid(const struct net *net, | 2370 | struct nft_set *nf_tables_set_lookup_byid(const struct net *net, |
| 2383 | const struct nlattr *nla) | 2371 | const struct nlattr *nla, |
| 2372 | u8 genmask) | ||
| 2384 | { | 2373 | { |
| 2385 | struct nft_trans *trans; | 2374 | struct nft_trans *trans; |
| 2386 | u32 id = ntohl(nla_get_be32(nla)); | 2375 | u32 id = ntohl(nla_get_be32(nla)); |
| 2387 | 2376 | ||
| 2388 | list_for_each_entry(trans, &net->nft.commit_list, list) { | 2377 | list_for_each_entry(trans, &net->nft.commit_list, list) { |
| 2378 | struct nft_set *set = nft_trans_set(trans); | ||
| 2379 | |||
| 2389 | if (trans->msg_type == NFT_MSG_NEWSET && | 2380 | if (trans->msg_type == NFT_MSG_NEWSET && |
| 2390 | id == nft_trans_set_id(trans)) | 2381 | id == nft_trans_set_id(trans) && |
| 2391 | return nft_trans_set(trans); | 2382 | nft_active_genmask(set, genmask)) |
| 2383 | return set; | ||
| 2392 | } | 2384 | } |
| 2393 | return ERR_PTR(-ENOENT); | 2385 | return ERR_PTR(-ENOENT); |
| 2394 | } | 2386 | } |
| @@ -2413,6 +2405,8 @@ cont: | |||
| 2413 | list_for_each_entry(i, &ctx->table->sets, list) { | 2405 | list_for_each_entry(i, &ctx->table->sets, list) { |
| 2414 | int tmp; | 2406 | int tmp; |
| 2415 | 2407 | ||
| 2408 | if (!nft_is_active_next(ctx->net, set)) | ||
| 2409 | continue; | ||
| 2416 | if (!sscanf(i->name, name, &tmp)) | 2410 | if (!sscanf(i->name, name, &tmp)) |
| 2417 | continue; | 2411 | continue; |
| 2418 | if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE) | 2412 | if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE) |
| @@ -2432,6 +2426,8 @@ cont: | |||
| 2432 | 2426 | ||
| 2433 | snprintf(set->name, sizeof(set->name), name, min + n); | 2427 | snprintf(set->name, sizeof(set->name), name, min + n); |
| 2434 | list_for_each_entry(i, &ctx->table->sets, list) { | 2428 | list_for_each_entry(i, &ctx->table->sets, list) { |
| 2429 | if (!nft_is_active_next(ctx->net, i)) | ||
| 2430 | continue; | ||
| 2435 | if (!strcmp(set->name, i->name)) | 2431 | if (!strcmp(set->name, i->name)) |
| 2436 | return -ENFILE; | 2432 | return -ENFILE; |
| 2437 | } | 2433 | } |
| @@ -2580,6 +2576,8 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2580 | list_for_each_entry_rcu(set, &table->sets, list) { | 2576 | list_for_each_entry_rcu(set, &table->sets, list) { |
| 2581 | if (idx < s_idx) | 2577 | if (idx < s_idx) |
| 2582 | goto cont; | 2578 | goto cont; |
| 2579 | if (!nft_is_active(net, set)) | ||
| 2580 | goto cont; | ||
| 2583 | 2581 | ||
| 2584 | ctx_set = *ctx; | 2582 | ctx_set = *ctx; |
| 2585 | ctx_set.table = table; | 2583 | ctx_set.table = table; |
| @@ -2616,6 +2614,7 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk, | |||
| 2616 | struct sk_buff *skb, const struct nlmsghdr *nlh, | 2614 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
| 2617 | const struct nlattr * const nla[]) | 2615 | const struct nlattr * const nla[]) |
| 2618 | { | 2616 | { |
| 2617 | u8 genmask = nft_genmask_cur(net); | ||
| 2619 | const struct nft_set *set; | 2618 | const struct nft_set *set; |
| 2620 | struct nft_ctx ctx; | 2619 | struct nft_ctx ctx; |
| 2621 | struct sk_buff *skb2; | 2620 | struct sk_buff *skb2; |
| @@ -2623,7 +2622,7 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk, | |||
| 2623 | int err; | 2622 | int err; |
| 2624 | 2623 | ||
| 2625 | /* Verify existence before starting dump */ | 2624 | /* Verify existence before starting dump */ |
| 2626 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla); | 2625 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask); |
| 2627 | if (err < 0) | 2626 | if (err < 0) |
| 2628 | return err; | 2627 | return err; |
| 2629 | 2628 | ||
| @@ -2650,11 +2649,9 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk, | |||
| 2650 | if (!nla[NFTA_SET_TABLE]) | 2649 | if (!nla[NFTA_SET_TABLE]) |
| 2651 | return -EINVAL; | 2650 | return -EINVAL; |
| 2652 | 2651 | ||
| 2653 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2652 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
| 2654 | if (IS_ERR(set)) | 2653 | if (IS_ERR(set)) |
| 2655 | return PTR_ERR(set); | 2654 | return PTR_ERR(set); |
| 2656 | if (set->flags & NFT_SET_INACTIVE) | ||
| 2657 | return -ENOENT; | ||
| 2658 | 2655 | ||
| 2659 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 2656 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 2660 | if (skb2 == NULL) | 2657 | if (skb2 == NULL) |
| @@ -2693,6 +2690,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, | |||
| 2693 | const struct nlattr * const nla[]) | 2690 | const struct nlattr * const nla[]) |
| 2694 | { | 2691 | { |
| 2695 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2692 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 2693 | u8 genmask = nft_genmask_next(net); | ||
| 2696 | const struct nft_set_ops *ops; | 2694 | const struct nft_set_ops *ops; |
| 2697 | struct nft_af_info *afi; | 2695 | struct nft_af_info *afi; |
| 2698 | struct nft_table *table; | 2696 | struct nft_table *table; |
| @@ -2790,13 +2788,13 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, | |||
| 2790 | if (IS_ERR(afi)) | 2788 | if (IS_ERR(afi)) |
| 2791 | return PTR_ERR(afi); | 2789 | return PTR_ERR(afi); |
| 2792 | 2790 | ||
| 2793 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 2791 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask); |
| 2794 | if (IS_ERR(table)) | 2792 | if (IS_ERR(table)) |
| 2795 | return PTR_ERR(table); | 2793 | return PTR_ERR(table); |
| 2796 | 2794 | ||
| 2797 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); | 2795 | nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); |
| 2798 | 2796 | ||
| 2799 | set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]); | 2797 | set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); |
| 2800 | if (IS_ERR(set)) { | 2798 | if (IS_ERR(set)) { |
| 2801 | if (PTR_ERR(set) != -ENOENT) | 2799 | if (PTR_ERR(set) != -ENOENT) |
| 2802 | return PTR_ERR(set); | 2800 | return PTR_ERR(set); |
| @@ -2895,6 +2893,7 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, | |||
| 2895 | const struct nlattr * const nla[]) | 2893 | const struct nlattr * const nla[]) |
| 2896 | { | 2894 | { |
| 2897 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 2895 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 2896 | u8 genmask = nft_genmask_next(net); | ||
| 2898 | struct nft_set *set; | 2897 | struct nft_set *set; |
| 2899 | struct nft_ctx ctx; | 2898 | struct nft_ctx ctx; |
| 2900 | int err; | 2899 | int err; |
| @@ -2904,11 +2903,11 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, | |||
| 2904 | if (nla[NFTA_SET_TABLE] == NULL) | 2903 | if (nla[NFTA_SET_TABLE] == NULL) |
| 2905 | return -EINVAL; | 2904 | return -EINVAL; |
| 2906 | 2905 | ||
| 2907 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla); | 2906 | err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask); |
| 2908 | if (err < 0) | 2907 | if (err < 0) |
| 2909 | return err; | 2908 | return err; |
| 2910 | 2909 | ||
| 2911 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2910 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
| 2912 | if (IS_ERR(set)) | 2911 | if (IS_ERR(set)) |
| 2913 | return PTR_ERR(set); | 2912 | return PTR_ERR(set); |
| 2914 | if (!list_empty(&set->bindings)) | 2913 | if (!list_empty(&set->bindings)) |
| @@ -2973,7 +2972,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, | |||
| 2973 | list_del_rcu(&binding->list); | 2972 | list_del_rcu(&binding->list); |
| 2974 | 2973 | ||
| 2975 | if (list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS && | 2974 | if (list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS && |
| 2976 | !(set->flags & NFT_SET_INACTIVE)) | 2975 | nft_is_active(ctx->net, set)) |
| 2977 | nf_tables_set_destroy(ctx, set); | 2976 | nf_tables_set_destroy(ctx, set); |
| 2978 | } | 2977 | } |
| 2979 | 2978 | ||
| @@ -3029,7 +3028,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + | |||
| 3029 | static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, | 3028 | static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, |
| 3030 | const struct sk_buff *skb, | 3029 | const struct sk_buff *skb, |
| 3031 | const struct nlmsghdr *nlh, | 3030 | const struct nlmsghdr *nlh, |
| 3032 | const struct nlattr * const nla[]) | 3031 | const struct nlattr * const nla[], |
| 3032 | u8 genmask) | ||
| 3033 | { | 3033 | { |
| 3034 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 3034 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 3035 | struct nft_af_info *afi; | 3035 | struct nft_af_info *afi; |
| @@ -3039,7 +3039,8 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net, | |||
| 3039 | if (IS_ERR(afi)) | 3039 | if (IS_ERR(afi)) |
| 3040 | return PTR_ERR(afi); | 3040 | return PTR_ERR(afi); |
| 3041 | 3041 | ||
| 3042 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]); | 3042 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE], |
| 3043 | genmask); | ||
| 3043 | if (IS_ERR(table)) | 3044 | if (IS_ERR(table)) |
| 3044 | return PTR_ERR(table); | 3045 | return PTR_ERR(table); |
| 3045 | 3046 | ||
| @@ -3136,6 +3137,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx, | |||
| 3136 | static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) | 3137 | static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) |
| 3137 | { | 3138 | { |
| 3138 | struct net *net = sock_net(skb->sk); | 3139 | struct net *net = sock_net(skb->sk); |
| 3140 | u8 genmask = nft_genmask_cur(net); | ||
| 3139 | const struct nft_set *set; | 3141 | const struct nft_set *set; |
| 3140 | struct nft_set_dump_args args; | 3142 | struct nft_set_dump_args args; |
| 3141 | struct nft_ctx ctx; | 3143 | struct nft_ctx ctx; |
| @@ -3152,17 +3154,14 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 3152 | return err; | 3154 | return err; |
| 3153 | 3155 | ||
| 3154 | err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh, | 3156 | err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh, |
| 3155 | (void *)nla); | 3157 | (void *)nla, genmask); |
| 3156 | if (err < 0) | 3158 | if (err < 0) |
| 3157 | return err; | 3159 | return err; |
| 3158 | if (ctx.table->flags & NFT_TABLE_INACTIVE) | ||
| 3159 | return -ENOENT; | ||
| 3160 | 3160 | ||
| 3161 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3161 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], |
| 3162 | genmask); | ||
| 3162 | if (IS_ERR(set)) | 3163 | if (IS_ERR(set)) |
| 3163 | return PTR_ERR(set); | 3164 | return PTR_ERR(set); |
| 3164 | if (set->flags & NFT_SET_INACTIVE) | ||
| 3165 | return -ENOENT; | ||
| 3166 | 3165 | ||
| 3167 | event = NFT_MSG_NEWSETELEM; | 3166 | event = NFT_MSG_NEWSETELEM; |
| 3168 | event |= NFNL_SUBSYS_NFTABLES << 8; | 3167 | event |= NFNL_SUBSYS_NFTABLES << 8; |
| @@ -3216,21 +3215,19 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, | |||
| 3216 | struct sk_buff *skb, const struct nlmsghdr *nlh, | 3215 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
| 3217 | const struct nlattr * const nla[]) | 3216 | const struct nlattr * const nla[]) |
| 3218 | { | 3217 | { |
| 3218 | u8 genmask = nft_genmask_cur(net); | ||
| 3219 | const struct nft_set *set; | 3219 | const struct nft_set *set; |
| 3220 | struct nft_ctx ctx; | 3220 | struct nft_ctx ctx; |
| 3221 | int err; | 3221 | int err; |
| 3222 | 3222 | ||
| 3223 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); | 3223 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); |
| 3224 | if (err < 0) | 3224 | if (err < 0) |
| 3225 | return err; | 3225 | return err; |
| 3226 | if (ctx.table->flags & NFT_TABLE_INACTIVE) | ||
| 3227 | return -ENOENT; | ||
| 3228 | 3226 | ||
| 3229 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3227 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], |
| 3228 | genmask); | ||
| 3230 | if (IS_ERR(set)) | 3229 | if (IS_ERR(set)) |
| 3231 | return PTR_ERR(set); | 3230 | return PTR_ERR(set); |
| 3232 | if (set->flags & NFT_SET_INACTIVE) | ||
| 3233 | return -ENOENT; | ||
| 3234 | 3231 | ||
| 3235 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 3232 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
| 3236 | struct netlink_dump_control c = { | 3233 | struct netlink_dump_control c = { |
| @@ -3548,6 +3545,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, | |||
| 3548 | struct sk_buff *skb, const struct nlmsghdr *nlh, | 3545 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
| 3549 | const struct nlattr * const nla[]) | 3546 | const struct nlattr * const nla[]) |
| 3550 | { | 3547 | { |
| 3548 | u8 genmask = nft_genmask_next(net); | ||
| 3551 | const struct nlattr *attr; | 3549 | const struct nlattr *attr; |
| 3552 | struct nft_set *set; | 3550 | struct nft_set *set; |
| 3553 | struct nft_ctx ctx; | 3551 | struct nft_ctx ctx; |
| @@ -3556,15 +3554,17 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, | |||
| 3556 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | 3554 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) |
| 3557 | return -EINVAL; | 3555 | return -EINVAL; |
| 3558 | 3556 | ||
| 3559 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); | 3557 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); |
| 3560 | if (err < 0) | 3558 | if (err < 0) |
| 3561 | return err; | 3559 | return err; |
| 3562 | 3560 | ||
| 3563 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3561 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], |
| 3562 | genmask); | ||
| 3564 | if (IS_ERR(set)) { | 3563 | if (IS_ERR(set)) { |
| 3565 | if (nla[NFTA_SET_ELEM_LIST_SET_ID]) { | 3564 | if (nla[NFTA_SET_ELEM_LIST_SET_ID]) { |
| 3566 | set = nf_tables_set_lookup_byid(net, | 3565 | set = nf_tables_set_lookup_byid(net, |
| 3567 | nla[NFTA_SET_ELEM_LIST_SET_ID]); | 3566 | nla[NFTA_SET_ELEM_LIST_SET_ID], |
| 3567 | genmask); | ||
| 3568 | } | 3568 | } |
| 3569 | if (IS_ERR(set)) | 3569 | if (IS_ERR(set)) |
| 3570 | return PTR_ERR(set); | 3570 | return PTR_ERR(set); |
| @@ -3670,6 +3670,7 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, | |||
| 3670 | struct sk_buff *skb, const struct nlmsghdr *nlh, | 3670 | struct sk_buff *skb, const struct nlmsghdr *nlh, |
| 3671 | const struct nlattr * const nla[]) | 3671 | const struct nlattr * const nla[]) |
| 3672 | { | 3672 | { |
| 3673 | u8 genmask = nft_genmask_next(net); | ||
| 3673 | const struct nlattr *attr; | 3674 | const struct nlattr *attr; |
| 3674 | struct nft_set *set; | 3675 | struct nft_set *set; |
| 3675 | struct nft_ctx ctx; | 3676 | struct nft_ctx ctx; |
| @@ -3678,11 +3679,12 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, | |||
| 3678 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | 3679 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) |
| 3679 | return -EINVAL; | 3680 | return -EINVAL; |
| 3680 | 3681 | ||
| 3681 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla); | 3682 | err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); |
| 3682 | if (err < 0) | 3683 | if (err < 0) |
| 3683 | return err; | 3684 | return err; |
| 3684 | 3685 | ||
| 3685 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]); | 3686 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], |
| 3687 | genmask); | ||
| 3686 | if (IS_ERR(set)) | 3688 | if (IS_ERR(set)) |
| 3687 | return PTR_ERR(set); | 3689 | return PTR_ERR(set); |
| 3688 | if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT) | 3690 | if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT) |
| @@ -3950,36 +3952,40 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) | |||
| 3950 | case NFT_MSG_NEWTABLE: | 3952 | case NFT_MSG_NEWTABLE: |
| 3951 | if (nft_trans_table_update(trans)) { | 3953 | if (nft_trans_table_update(trans)) { |
| 3952 | if (!nft_trans_table_enable(trans)) { | 3954 | if (!nft_trans_table_enable(trans)) { |
| 3953 | nf_tables_table_disable(trans->ctx.afi, | 3955 | nf_tables_table_disable(net, |
| 3956 | trans->ctx.afi, | ||
| 3954 | trans->ctx.table); | 3957 | trans->ctx.table); |
| 3955 | trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; | 3958 | trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; |
| 3956 | } | 3959 | } |
| 3957 | } else { | 3960 | } else { |
| 3958 | trans->ctx.table->flags &= ~NFT_TABLE_INACTIVE; | 3961 | nft_clear(net, trans->ctx.table); |
| 3959 | } | 3962 | } |
| 3960 | nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE); | 3963 | nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE); |
| 3961 | nft_trans_destroy(trans); | 3964 | nft_trans_destroy(trans); |
| 3962 | break; | 3965 | break; |
| 3963 | case NFT_MSG_DELTABLE: | 3966 | case NFT_MSG_DELTABLE: |
| 3967 | list_del_rcu(&trans->ctx.table->list); | ||
| 3964 | nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE); | 3968 | nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE); |
| 3965 | break; | 3969 | break; |
| 3966 | case NFT_MSG_NEWCHAIN: | 3970 | case NFT_MSG_NEWCHAIN: |
| 3967 | if (nft_trans_chain_update(trans)) | 3971 | if (nft_trans_chain_update(trans)) |
| 3968 | nft_chain_commit_update(trans); | 3972 | nft_chain_commit_update(trans); |
| 3969 | else | 3973 | else |
| 3970 | trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE; | 3974 | nft_clear(net, trans->ctx.chain); |
| 3971 | 3975 | ||
| 3972 | nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN); | 3976 | nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN); |
| 3973 | nft_trans_destroy(trans); | 3977 | nft_trans_destroy(trans); |
| 3974 | break; | 3978 | break; |
| 3975 | case NFT_MSG_DELCHAIN: | 3979 | case NFT_MSG_DELCHAIN: |
| 3980 | list_del_rcu(&trans->ctx.chain->list); | ||
| 3976 | nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); | 3981 | nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); |
| 3977 | nf_tables_unregister_hooks(trans->ctx.table, | 3982 | nf_tables_unregister_hooks(trans->ctx.net, |
| 3983 | trans->ctx.table, | ||
| 3978 | trans->ctx.chain, | 3984 | trans->ctx.chain, |
| 3979 | trans->ctx.afi->nops); | 3985 | trans->ctx.afi->nops); |
| 3980 | break; | 3986 | break; |
| 3981 | case NFT_MSG_NEWRULE: | 3987 | case NFT_MSG_NEWRULE: |
| 3982 | nft_rule_clear(trans->ctx.net, nft_trans_rule(trans)); | 3988 | nft_clear(trans->ctx.net, nft_trans_rule(trans)); |
| 3983 | nf_tables_rule_notify(&trans->ctx, | 3989 | nf_tables_rule_notify(&trans->ctx, |
| 3984 | nft_trans_rule(trans), | 3990 | nft_trans_rule(trans), |
| 3985 | NFT_MSG_NEWRULE); | 3991 | NFT_MSG_NEWRULE); |
| @@ -3992,7 +3998,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) | |||
| 3992 | NFT_MSG_DELRULE); | 3998 | NFT_MSG_DELRULE); |
| 3993 | break; | 3999 | break; |
| 3994 | case NFT_MSG_NEWSET: | 4000 | case NFT_MSG_NEWSET: |
| 3995 | nft_trans_set(trans)->flags &= ~NFT_SET_INACTIVE; | 4001 | nft_clear(net, nft_trans_set(trans)); |
| 3996 | /* This avoids hitting -EBUSY when deleting the table | 4002 | /* This avoids hitting -EBUSY when deleting the table |
| 3997 | * from the transaction. | 4003 | * from the transaction. |
| 3998 | */ | 4004 | */ |
| @@ -4005,6 +4011,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) | |||
| 4005 | nft_trans_destroy(trans); | 4011 | nft_trans_destroy(trans); |
| 4006 | break; | 4012 | break; |
| 4007 | case NFT_MSG_DELSET: | 4013 | case NFT_MSG_DELSET: |
| 4014 | list_del_rcu(&nft_trans_set(trans)->list); | ||
| 4008 | nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), | 4015 | nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), |
| 4009 | NFT_MSG_DELSET, GFP_KERNEL); | 4016 | NFT_MSG_DELSET, GFP_KERNEL); |
| 4010 | break; | 4017 | break; |
| @@ -4076,7 +4083,8 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |||
| 4076 | case NFT_MSG_NEWTABLE: | 4083 | case NFT_MSG_NEWTABLE: |
| 4077 | if (nft_trans_table_update(trans)) { | 4084 | if (nft_trans_table_update(trans)) { |
| 4078 | if (nft_trans_table_enable(trans)) { | 4085 | if (nft_trans_table_enable(trans)) { |
| 4079 | nf_tables_table_disable(trans->ctx.afi, | 4086 | nf_tables_table_disable(net, |
| 4087 | trans->ctx.afi, | ||
| 4080 | trans->ctx.table); | 4088 | trans->ctx.table); |
| 4081 | trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; | 4089 | trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; |
| 4082 | } | 4090 | } |
| @@ -4086,8 +4094,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |||
| 4086 | } | 4094 | } |
| 4087 | break; | 4095 | break; |
| 4088 | case NFT_MSG_DELTABLE: | 4096 | case NFT_MSG_DELTABLE: |
| 4089 | list_add_tail_rcu(&trans->ctx.table->list, | 4097 | nft_clear(trans->ctx.net, trans->ctx.table); |
| 4090 | &trans->ctx.afi->tables); | ||
| 4091 | nft_trans_destroy(trans); | 4098 | nft_trans_destroy(trans); |
| 4092 | break; | 4099 | break; |
| 4093 | case NFT_MSG_NEWCHAIN: | 4100 | case NFT_MSG_NEWCHAIN: |
| @@ -4098,15 +4105,15 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |||
| 4098 | } else { | 4105 | } else { |
| 4099 | trans->ctx.table->use--; | 4106 | trans->ctx.table->use--; |
| 4100 | list_del_rcu(&trans->ctx.chain->list); | 4107 | list_del_rcu(&trans->ctx.chain->list); |
| 4101 | nf_tables_unregister_hooks(trans->ctx.table, | 4108 | nf_tables_unregister_hooks(trans->ctx.net, |
| 4109 | trans->ctx.table, | ||
| 4102 | trans->ctx.chain, | 4110 | trans->ctx.chain, |
| 4103 | trans->ctx.afi->nops); | 4111 | trans->ctx.afi->nops); |
| 4104 | } | 4112 | } |
| 4105 | break; | 4113 | break; |
| 4106 | case NFT_MSG_DELCHAIN: | 4114 | case NFT_MSG_DELCHAIN: |
| 4107 | trans->ctx.table->use++; | 4115 | trans->ctx.table->use++; |
| 4108 | list_add_tail_rcu(&trans->ctx.chain->list, | 4116 | nft_clear(trans->ctx.net, trans->ctx.chain); |
| 4109 | &trans->ctx.table->chains); | ||
| 4110 | nft_trans_destroy(trans); | 4117 | nft_trans_destroy(trans); |
| 4111 | break; | 4118 | break; |
| 4112 | case NFT_MSG_NEWRULE: | 4119 | case NFT_MSG_NEWRULE: |
| @@ -4115,7 +4122,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |||
| 4115 | break; | 4122 | break; |
| 4116 | case NFT_MSG_DELRULE: | 4123 | case NFT_MSG_DELRULE: |
| 4117 | trans->ctx.chain->use++; | 4124 | trans->ctx.chain->use++; |
| 4118 | nft_rule_clear(trans->ctx.net, nft_trans_rule(trans)); | 4125 | nft_clear(trans->ctx.net, nft_trans_rule(trans)); |
| 4119 | nft_trans_destroy(trans); | 4126 | nft_trans_destroy(trans); |
| 4120 | break; | 4127 | break; |
| 4121 | case NFT_MSG_NEWSET: | 4128 | case NFT_MSG_NEWSET: |
| @@ -4124,8 +4131,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) | |||
| 4124 | break; | 4131 | break; |
| 4125 | case NFT_MSG_DELSET: | 4132 | case NFT_MSG_DELSET: |
| 4126 | trans->ctx.table->use++; | 4133 | trans->ctx.table->use++; |
| 4127 | list_add_tail_rcu(&nft_trans_set(trans)->list, | 4134 | nft_clear(trans->ctx.net, nft_trans_set(trans)); |
| 4128 | &trans->ctx.table->sets); | ||
| 4129 | nft_trans_destroy(trans); | 4135 | nft_trans_destroy(trans); |
| 4130 | break; | 4136 | break; |
| 4131 | case NFT_MSG_NEWSETELEM: | 4137 | case NFT_MSG_NEWSETELEM: |
| @@ -4272,6 +4278,8 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, | |||
| 4272 | } | 4278 | } |
| 4273 | 4279 | ||
| 4274 | list_for_each_entry(set, &ctx->table->sets, list) { | 4280 | list_for_each_entry(set, &ctx->table->sets, list) { |
| 4281 | if (!nft_is_active_next(ctx->net, set)) | ||
| 4282 | continue; | ||
| 4275 | if (!(set->flags & NFT_SET_MAP) || | 4283 | if (!(set->flags & NFT_SET_MAP) || |
| 4276 | set->dtype != NFT_DATA_VERDICT) | 4284 | set->dtype != NFT_DATA_VERDICT) |
| 4277 | continue; | 4285 | continue; |
| @@ -4430,6 +4438,7 @@ static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { | |||
| 4430 | static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | 4438 | static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, |
| 4431 | struct nft_data_desc *desc, const struct nlattr *nla) | 4439 | struct nft_data_desc *desc, const struct nlattr *nla) |
| 4432 | { | 4440 | { |
| 4441 | u8 genmask = nft_genmask_next(ctx->net); | ||
| 4433 | struct nlattr *tb[NFTA_VERDICT_MAX + 1]; | 4442 | struct nlattr *tb[NFTA_VERDICT_MAX + 1]; |
| 4434 | struct nft_chain *chain; | 4443 | struct nft_chain *chain; |
| 4435 | int err; | 4444 | int err; |
| @@ -4462,7 +4471,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
| 4462 | if (!tb[NFTA_VERDICT_CHAIN]) | 4471 | if (!tb[NFTA_VERDICT_CHAIN]) |
| 4463 | return -EINVAL; | 4472 | return -EINVAL; |
| 4464 | chain = nf_tables_chain_lookup(ctx->table, | 4473 | chain = nf_tables_chain_lookup(ctx->table, |
| 4465 | tb[NFTA_VERDICT_CHAIN]); | 4474 | tb[NFTA_VERDICT_CHAIN], genmask); |
| 4466 | if (IS_ERR(chain)) | 4475 | if (IS_ERR(chain)) |
| 4467 | return PTR_ERR(chain); | 4476 | return PTR_ERR(chain); |
| 4468 | if (chain->flags & NFT_BASE_CHAIN) | 4477 | if (chain->flags & NFT_BASE_CHAIN) |
| @@ -4640,7 +4649,7 @@ int __nft_release_basechain(struct nft_ctx *ctx) | |||
| 4640 | 4649 | ||
| 4641 | BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN)); | 4650 | BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN)); |
| 4642 | 4651 | ||
| 4643 | nf_tables_unregister_hooks(ctx->chain->table, ctx->chain, | 4652 | nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain, |
| 4644 | ctx->afi->nops); | 4653 | ctx->afi->nops); |
| 4645 | list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { | 4654 | list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { |
| 4646 | list_del(&rule->list); | 4655 | list_del(&rule->list); |
| @@ -4669,7 +4678,8 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) | |||
| 4669 | 4678 | ||
| 4670 | list_for_each_entry_safe(table, nt, &afi->tables, list) { | 4679 | list_for_each_entry_safe(table, nt, &afi->tables, list) { |
| 4671 | list_for_each_entry(chain, &table->chains, list) | 4680 | list_for_each_entry(chain, &table->chains, list) |
| 4672 | nf_tables_unregister_hooks(table, chain, afi->nops); | 4681 | nf_tables_unregister_hooks(net, table, chain, |
| 4682 | afi->nops); | ||
| 4673 | /* No packets are walking on these chains anymore. */ | 4683 | /* No packets are walking on these chains anymore. */ |
| 4674 | ctx.table = table; | 4684 | ctx.table = table; |
| 4675 | list_for_each_entry(chain, &table->chains, list) { | 4685 | list_for_each_entry(chain, &table->chains, list) { |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 11f81c8385fc..cbcfdfb586a6 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -700,10 +700,13 @@ nfulnl_log_packet(struct net *net, | |||
| 700 | break; | 700 | break; |
| 701 | 701 | ||
| 702 | case NFULNL_COPY_PACKET: | 702 | case NFULNL_COPY_PACKET: |
| 703 | if (inst->copy_range > skb->len) | 703 | data_len = inst->copy_range; |
| 704 | if ((li->u.ulog.flags & NF_LOG_F_COPY_LEN) && | ||
| 705 | (li->u.ulog.copy_len < data_len)) | ||
| 706 | data_len = li->u.ulog.copy_len; | ||
| 707 | |||
| 708 | if (data_len > skb->len) | ||
| 704 | data_len = skb->len; | 709 | data_len = skb->len; |
| 705 | else | ||
| 706 | data_len = inst->copy_range; | ||
| 707 | 710 | ||
| 708 | size += nla_total_size(data_len); | 711 | size += nla_total_size(data_len); |
| 709 | break; | 712 | break; |
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 78d4914fb39c..0af26699bf04 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c | |||
| @@ -103,6 +103,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
| 103 | const struct nlattr * const tb[]) | 103 | const struct nlattr * const tb[]) |
| 104 | { | 104 | { |
| 105 | struct nft_dynset *priv = nft_expr_priv(expr); | 105 | struct nft_dynset *priv = nft_expr_priv(expr); |
| 106 | u8 genmask = nft_genmask_next(ctx->net); | ||
| 106 | struct nft_set *set; | 107 | struct nft_set *set; |
| 107 | u64 timeout; | 108 | u64 timeout; |
| 108 | int err; | 109 | int err; |
| @@ -112,11 +113,13 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
| 112 | tb[NFTA_DYNSET_SREG_KEY] == NULL) | 113 | tb[NFTA_DYNSET_SREG_KEY] == NULL) |
| 113 | return -EINVAL; | 114 | return -EINVAL; |
| 114 | 115 | ||
| 115 | set = nf_tables_set_lookup(ctx->table, tb[NFTA_DYNSET_SET_NAME]); | 116 | set = nf_tables_set_lookup(ctx->table, tb[NFTA_DYNSET_SET_NAME], |
| 117 | genmask); | ||
| 116 | if (IS_ERR(set)) { | 118 | if (IS_ERR(set)) { |
| 117 | if (tb[NFTA_DYNSET_SET_ID]) | 119 | if (tb[NFTA_DYNSET_SET_ID]) |
| 118 | set = nf_tables_set_lookup_byid(ctx->net, | 120 | set = nf_tables_set_lookup_byid(ctx->net, |
| 119 | tb[NFTA_DYNSET_SET_ID]); | 121 | tb[NFTA_DYNSET_SET_ID], |
| 122 | genmask); | ||
| 120 | if (IS_ERR(set)) | 123 | if (IS_ERR(set)) |
| 121 | return PTR_ERR(set); | 124 | return PTR_ERR(set); |
| 122 | } | 125 | } |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index f39c53a159eb..ea924816b7b8 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
| @@ -153,9 +153,10 @@ static void *nft_hash_deactivate(const struct nft_set *set, | |||
| 153 | const struct nft_set_elem *elem) | 153 | const struct nft_set_elem *elem) |
| 154 | { | 154 | { |
| 155 | struct nft_hash *priv = nft_set_priv(set); | 155 | struct nft_hash *priv = nft_set_priv(set); |
| 156 | struct net *net = read_pnet(&set->pnet); | ||
| 156 | struct nft_hash_elem *he; | 157 | struct nft_hash_elem *he; |
| 157 | struct nft_hash_cmp_arg arg = { | 158 | struct nft_hash_cmp_arg arg = { |
| 158 | .genmask = nft_genmask_next(read_pnet(&set->pnet)), | 159 | .genmask = nft_genmask_next(net), |
| 159 | .set = set, | 160 | .set = set, |
| 160 | .key = elem->key.val.data, | 161 | .key = elem->key.val.data, |
| 161 | }; | 162 | }; |
| @@ -163,7 +164,8 @@ static void *nft_hash_deactivate(const struct nft_set *set, | |||
| 163 | rcu_read_lock(); | 164 | rcu_read_lock(); |
| 164 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); | 165 | he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); |
| 165 | if (he != NULL) { | 166 | if (he != NULL) { |
| 166 | if (!nft_set_elem_mark_busy(&he->ext)) | 167 | if (!nft_set_elem_mark_busy(&he->ext) || |
| 168 | !nft_is_active(net, &he->ext)) | ||
| 167 | nft_set_elem_change_active(set, &he->ext); | 169 | nft_set_elem_change_active(set, &he->ext); |
| 168 | else | 170 | else |
| 169 | he = NULL; | 171 | he = NULL; |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 319c22b4bca2..713d66837705 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
| @@ -52,7 +52,6 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
| 52 | struct nft_log *priv = nft_expr_priv(expr); | 52 | struct nft_log *priv = nft_expr_priv(expr); |
| 53 | struct nf_loginfo *li = &priv->loginfo; | 53 | struct nf_loginfo *li = &priv->loginfo; |
| 54 | const struct nlattr *nla; | 54 | const struct nlattr *nla; |
| 55 | int ret; | ||
| 56 | 55 | ||
| 57 | nla = tb[NFTA_LOG_PREFIX]; | 56 | nla = tb[NFTA_LOG_PREFIX]; |
| 58 | if (nla != NULL) { | 57 | if (nla != NULL) { |
| @@ -97,19 +96,6 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
| 97 | break; | 96 | break; |
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | if (ctx->afi->family == NFPROTO_INET) { | ||
| 101 | ret = nf_logger_find_get(NFPROTO_IPV4, li->type); | ||
| 102 | if (ret < 0) | ||
| 103 | return ret; | ||
| 104 | |||
| 105 | ret = nf_logger_find_get(NFPROTO_IPV6, li->type); | ||
| 106 | if (ret < 0) { | ||
| 107 | nf_logger_put(NFPROTO_IPV4, li->type); | ||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | return nf_logger_find_get(ctx->afi->family, li->type); | 99 | return nf_logger_find_get(ctx->afi->family, li->type); |
| 114 | } | 100 | } |
| 115 | 101 | ||
| @@ -122,12 +108,7 @@ static void nft_log_destroy(const struct nft_ctx *ctx, | |||
| 122 | if (priv->prefix != nft_log_null_prefix) | 108 | if (priv->prefix != nft_log_null_prefix) |
| 123 | kfree(priv->prefix); | 109 | kfree(priv->prefix); |
| 124 | 110 | ||
| 125 | if (ctx->afi->family == NFPROTO_INET) { | 111 | nf_logger_put(ctx->afi->family, li->type); |
| 126 | nf_logger_put(NFPROTO_IPV4, li->type); | ||
| 127 | nf_logger_put(NFPROTO_IPV6, li->type); | ||
| 128 | } else { | ||
| 129 | nf_logger_put(ctx->afi->family, li->type); | ||
| 130 | } | ||
| 131 | } | 112 | } |
| 132 | 113 | ||
| 133 | static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) | 114 | static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) |
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index b3c31ef8015d..b8d18f598569 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
| @@ -22,6 +22,7 @@ struct nft_lookup { | |||
| 22 | struct nft_set *set; | 22 | struct nft_set *set; |
| 23 | enum nft_registers sreg:8; | 23 | enum nft_registers sreg:8; |
| 24 | enum nft_registers dreg:8; | 24 | enum nft_registers dreg:8; |
| 25 | bool invert; | ||
| 25 | struct nft_set_binding binding; | 26 | struct nft_set_binding binding; |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| @@ -32,14 +33,20 @@ static void nft_lookup_eval(const struct nft_expr *expr, | |||
| 32 | const struct nft_lookup *priv = nft_expr_priv(expr); | 33 | const struct nft_lookup *priv = nft_expr_priv(expr); |
| 33 | const struct nft_set *set = priv->set; | 34 | const struct nft_set *set = priv->set; |
| 34 | const struct nft_set_ext *ext; | 35 | const struct nft_set_ext *ext; |
| 36 | bool found; | ||
| 35 | 37 | ||
| 36 | if (set->ops->lookup(set, ®s->data[priv->sreg], &ext)) { | 38 | found = set->ops->lookup(set, ®s->data[priv->sreg], &ext) ^ |
| 37 | if (set->flags & NFT_SET_MAP) | 39 | priv->invert; |
| 38 | nft_data_copy(®s->data[priv->dreg], | 40 | |
| 39 | nft_set_ext_data(ext), set->dlen); | 41 | if (!found) { |
| 42 | regs->verdict.code = NFT_BREAK; | ||
| 40 | return; | 43 | return; |
| 41 | } | 44 | } |
| 42 | regs->verdict.code = NFT_BREAK; | 45 | |
| 46 | if (found && set->flags & NFT_SET_MAP) | ||
| 47 | nft_data_copy(®s->data[priv->dreg], | ||
| 48 | nft_set_ext_data(ext), set->dlen); | ||
| 49 | |||
| 43 | } | 50 | } |
| 44 | 51 | ||
| 45 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { | 52 | static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { |
| @@ -47,6 +54,7 @@ static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { | |||
| 47 | [NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 }, | 54 | [NFTA_LOOKUP_SET_ID] = { .type = NLA_U32 }, |
| 48 | [NFTA_LOOKUP_SREG] = { .type = NLA_U32 }, | 55 | [NFTA_LOOKUP_SREG] = { .type = NLA_U32 }, |
| 49 | [NFTA_LOOKUP_DREG] = { .type = NLA_U32 }, | 56 | [NFTA_LOOKUP_DREG] = { .type = NLA_U32 }, |
| 57 | [NFTA_LOOKUP_FLAGS] = { .type = NLA_U32 }, | ||
| 50 | }; | 58 | }; |
| 51 | 59 | ||
| 52 | static int nft_lookup_init(const struct nft_ctx *ctx, | 60 | static int nft_lookup_init(const struct nft_ctx *ctx, |
| @@ -54,18 +62,21 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
| 54 | const struct nlattr * const tb[]) | 62 | const struct nlattr * const tb[]) |
| 55 | { | 63 | { |
| 56 | struct nft_lookup *priv = nft_expr_priv(expr); | 64 | struct nft_lookup *priv = nft_expr_priv(expr); |
| 65 | u8 genmask = nft_genmask_next(ctx->net); | ||
| 57 | struct nft_set *set; | 66 | struct nft_set *set; |
| 67 | u32 flags; | ||
| 58 | int err; | 68 | int err; |
| 59 | 69 | ||
| 60 | if (tb[NFTA_LOOKUP_SET] == NULL || | 70 | if (tb[NFTA_LOOKUP_SET] == NULL || |
| 61 | tb[NFTA_LOOKUP_SREG] == NULL) | 71 | tb[NFTA_LOOKUP_SREG] == NULL) |
| 62 | return -EINVAL; | 72 | return -EINVAL; |
| 63 | 73 | ||
| 64 | set = nf_tables_set_lookup(ctx->table, tb[NFTA_LOOKUP_SET]); | 74 | set = nf_tables_set_lookup(ctx->table, tb[NFTA_LOOKUP_SET], genmask); |
| 65 | if (IS_ERR(set)) { | 75 | if (IS_ERR(set)) { |
| 66 | if (tb[NFTA_LOOKUP_SET_ID]) { | 76 | if (tb[NFTA_LOOKUP_SET_ID]) { |
| 67 | set = nf_tables_set_lookup_byid(ctx->net, | 77 | set = nf_tables_set_lookup_byid(ctx->net, |
| 68 | tb[NFTA_LOOKUP_SET_ID]); | 78 | tb[NFTA_LOOKUP_SET_ID], |
| 79 | genmask); | ||
| 69 | } | 80 | } |
| 70 | if (IS_ERR(set)) | 81 | if (IS_ERR(set)) |
| 71 | return PTR_ERR(set); | 82 | return PTR_ERR(set); |
| @@ -79,7 +90,22 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
| 79 | if (err < 0) | 90 | if (err < 0) |
| 80 | return err; | 91 | return err; |
| 81 | 92 | ||
| 93 | if (tb[NFTA_LOOKUP_FLAGS]) { | ||
| 94 | flags = ntohl(nla_get_be32(tb[NFTA_LOOKUP_FLAGS])); | ||
| 95 | |||
| 96 | if (flags & ~NFT_LOOKUP_F_INV) | ||
| 97 | return -EINVAL; | ||
| 98 | |||
| 99 | if (flags & NFT_LOOKUP_F_INV) { | ||
| 100 | if (set->flags & NFT_SET_MAP) | ||
| 101 | return -EINVAL; | ||
| 102 | priv->invert = true; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 82 | if (tb[NFTA_LOOKUP_DREG] != NULL) { | 106 | if (tb[NFTA_LOOKUP_DREG] != NULL) { |
| 107 | if (priv->invert) | ||
| 108 | return -EINVAL; | ||
| 83 | if (!(set->flags & NFT_SET_MAP)) | 109 | if (!(set->flags & NFT_SET_MAP)) |
| 84 | return -EINVAL; | 110 | return -EINVAL; |
| 85 | 111 | ||
| @@ -112,6 +138,7 @@ static void nft_lookup_destroy(const struct nft_ctx *ctx, | |||
| 112 | static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) | 138 | static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) |
| 113 | { | 139 | { |
| 114 | const struct nft_lookup *priv = nft_expr_priv(expr); | 140 | const struct nft_lookup *priv = nft_expr_priv(expr); |
| 141 | u32 flags = priv->invert ? NFT_LOOKUP_F_INV : 0; | ||
| 115 | 142 | ||
| 116 | if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) | 143 | if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) |
| 117 | goto nla_put_failure; | 144 | goto nla_put_failure; |
| @@ -120,6 +147,8 @@ static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
| 120 | if (priv->set->flags & NFT_SET_MAP) | 147 | if (priv->set->flags & NFT_SET_MAP) |
| 121 | if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg)) | 148 | if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg)) |
| 122 | goto nla_put_failure; | 149 | goto nla_put_failure; |
| 150 | if (nla_put_be32(skb, NFTA_LOOKUP_FLAGS, htonl(flags))) | ||
| 151 | goto nla_put_failure; | ||
| 123 | return 0; | 152 | return 0; |
| 124 | 153 | ||
| 125 | nla_put_failure: | 154 | nla_put_failure: |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index 7201d57b5a93..c0f638745adc 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
| @@ -170,7 +170,7 @@ static void *nft_rbtree_deactivate(const struct nft_set *set, | |||
| 170 | const struct nft_rbtree *priv = nft_set_priv(set); | 170 | const struct nft_rbtree *priv = nft_set_priv(set); |
| 171 | const struct rb_node *parent = priv->root.rb_node; | 171 | const struct rb_node *parent = priv->root.rb_node; |
| 172 | struct nft_rbtree_elem *rbe, *this = elem->priv; | 172 | struct nft_rbtree_elem *rbe, *this = elem->priv; |
| 173 | u8 genmask = nft_genmask_cur(read_pnet(&set->pnet)); | 173 | u8 genmask = nft_genmask_next(read_pnet(&set->pnet)); |
| 174 | int d; | 174 | int d; |
| 175 | 175 | ||
| 176 | while (parent != NULL) { | 176 | while (parent != NULL) { |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 2675d580c490..fe0e2db632c7 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
| @@ -1460,6 +1460,9 @@ xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn) | |||
| 1460 | uint8_t hooknum; | 1460 | uint8_t hooknum; |
| 1461 | struct nf_hook_ops *ops; | 1461 | struct nf_hook_ops *ops; |
| 1462 | 1462 | ||
| 1463 | if (!num_hooks) | ||
| 1464 | return ERR_PTR(-EINVAL); | ||
| 1465 | |||
| 1463 | ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); | 1466 | ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); |
| 1464 | if (ops == NULL) | 1467 | if (ops == NULL) |
| 1465 | return ERR_PTR(-ENOMEM); | 1468 | return ERR_PTR(-ENOMEM); |
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index a1fa2c800cb9..018eed7e1ff1 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
| @@ -33,6 +33,9 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 33 | li.u.ulog.group = info->group; | 33 | li.u.ulog.group = info->group; |
| 34 | li.u.ulog.qthreshold = info->threshold; | 34 | li.u.ulog.qthreshold = info->threshold; |
| 35 | 35 | ||
| 36 | if (info->flags & XT_NFLOG_F_COPY_LEN) | ||
| 37 | li.u.ulog.flags |= NF_LOG_F_COPY_LEN; | ||
| 38 | |||
| 36 | nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in, | 39 | nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in, |
| 37 | par->out, &li, info->prefix); | 40 | par->out, &li, info->prefix); |
| 38 | return XT_CONTINUE; | 41 | return XT_CONTINUE; |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c index df48967af382..858d189a1303 100644 --- a/net/netfilter/xt_TRACE.c +++ b/net/netfilter/xt_TRACE.c | |||
| @@ -4,12 +4,23 @@ | |||
| 4 | #include <linux/skbuff.h> | 4 | #include <linux/skbuff.h> |
| 5 | 5 | ||
| 6 | #include <linux/netfilter/x_tables.h> | 6 | #include <linux/netfilter/x_tables.h> |
| 7 | #include <net/netfilter/nf_log.h> | ||
| 7 | 8 | ||
| 8 | MODULE_DESCRIPTION("Xtables: packet flow tracing"); | 9 | MODULE_DESCRIPTION("Xtables: packet flow tracing"); |
| 9 | MODULE_LICENSE("GPL"); | 10 | MODULE_LICENSE("GPL"); |
| 10 | MODULE_ALIAS("ipt_TRACE"); | 11 | MODULE_ALIAS("ipt_TRACE"); |
| 11 | MODULE_ALIAS("ip6t_TRACE"); | 12 | MODULE_ALIAS("ip6t_TRACE"); |
| 12 | 13 | ||
| 14 | static int trace_tg_check(const struct xt_tgchk_param *par) | ||
| 15 | { | ||
| 16 | return nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); | ||
| 17 | } | ||
| 18 | |||
| 19 | static void trace_tg_destroy(const struct xt_tgdtor_param *par) | ||
| 20 | { | ||
| 21 | nf_logger_put(par->family, NF_LOG_TYPE_LOG); | ||
| 22 | } | ||
| 23 | |||
| 13 | static unsigned int | 24 | static unsigned int |
| 14 | trace_tg(struct sk_buff *skb, const struct xt_action_param *par) | 25 | trace_tg(struct sk_buff *skb, const struct xt_action_param *par) |
| 15 | { | 26 | { |
| @@ -18,12 +29,14 @@ trace_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 18 | } | 29 | } |
| 19 | 30 | ||
| 20 | static struct xt_target trace_tg_reg __read_mostly = { | 31 | static struct xt_target trace_tg_reg __read_mostly = { |
| 21 | .name = "TRACE", | 32 | .name = "TRACE", |
| 22 | .revision = 0, | 33 | .revision = 0, |
| 23 | .family = NFPROTO_UNSPEC, | 34 | .family = NFPROTO_UNSPEC, |
| 24 | .table = "raw", | 35 | .table = "raw", |
| 25 | .target = trace_tg, | 36 | .target = trace_tg, |
| 26 | .me = THIS_MODULE, | 37 | .checkentry = trace_tg_check, |
| 38 | .destroy = trace_tg_destroy, | ||
| 39 | .me = THIS_MODULE, | ||
| 27 | }; | 40 | }; |
| 28 | 41 | ||
| 29 | static int __init trace_tg_init(void) | 42 | static int __init trace_tg_init(void) |
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index 1302b475abcb..a20e731b5b6c 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c | |||
| @@ -21,11 +21,39 @@ | |||
| 21 | static int owner_check(const struct xt_mtchk_param *par) | 21 | static int owner_check(const struct xt_mtchk_param *par) |
| 22 | { | 22 | { |
| 23 | struct xt_owner_match_info *info = par->matchinfo; | 23 | struct xt_owner_match_info *info = par->matchinfo; |
| 24 | struct net *net = par->net; | ||
| 24 | 25 | ||
| 25 | /* For now only allow adding matches from the initial user namespace */ | 26 | /* Only allow the common case where the userns of the writer |
| 27 | * matches the userns of the network namespace. | ||
| 28 | */ | ||
| 26 | if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) && | 29 | if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) && |
| 27 | (current_user_ns() != &init_user_ns)) | 30 | (current_user_ns() != net->user_ns)) |
| 28 | return -EINVAL; | 31 | return -EINVAL; |
| 32 | |||
| 33 | /* Ensure the uids are valid */ | ||
| 34 | if (info->match & XT_OWNER_UID) { | ||
| 35 | kuid_t uid_min = make_kuid(net->user_ns, info->uid_min); | ||
| 36 | kuid_t uid_max = make_kuid(net->user_ns, info->uid_max); | ||
| 37 | |||
| 38 | if (!uid_valid(uid_min) || !uid_valid(uid_max) || | ||
| 39 | (info->uid_max < info->uid_min) || | ||
| 40 | uid_lt(uid_max, uid_min)) { | ||
| 41 | return -EINVAL; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | /* Ensure the gids are valid */ | ||
| 46 | if (info->match & XT_OWNER_GID) { | ||
| 47 | kgid_t gid_min = make_kgid(net->user_ns, info->gid_min); | ||
| 48 | kgid_t gid_max = make_kgid(net->user_ns, info->gid_max); | ||
| 49 | |||
| 50 | if (!gid_valid(gid_min) || !gid_valid(gid_max) || | ||
| 51 | (info->gid_max < info->gid_min) || | ||
| 52 | gid_lt(gid_max, gid_min)) { | ||
| 53 | return -EINVAL; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 29 | return 0; | 57 | return 0; |
| 30 | } | 58 | } |
| 31 | 59 | ||
| @@ -35,6 +63,7 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 35 | const struct xt_owner_match_info *info = par->matchinfo; | 63 | const struct xt_owner_match_info *info = par->matchinfo; |
| 36 | const struct file *filp; | 64 | const struct file *filp; |
| 37 | struct sock *sk = skb_to_full_sk(skb); | 65 | struct sock *sk = skb_to_full_sk(skb); |
| 66 | struct net *net = par->net; | ||
| 38 | 67 | ||
| 39 | if (sk == NULL || sk->sk_socket == NULL) | 68 | if (sk == NULL || sk->sk_socket == NULL) |
| 40 | return (info->match ^ info->invert) == 0; | 69 | return (info->match ^ info->invert) == 0; |
| @@ -51,8 +80,8 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 51 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; | 80 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; |
| 52 | 81 | ||
| 53 | if (info->match & XT_OWNER_UID) { | 82 | if (info->match & XT_OWNER_UID) { |
| 54 | kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min); | 83 | kuid_t uid_min = make_kuid(net->user_ns, info->uid_min); |
| 55 | kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max); | 84 | kuid_t uid_max = make_kuid(net->user_ns, info->uid_max); |
| 56 | if ((uid_gte(filp->f_cred->fsuid, uid_min) && | 85 | if ((uid_gte(filp->f_cred->fsuid, uid_min) && |
| 57 | uid_lte(filp->f_cred->fsuid, uid_max)) ^ | 86 | uid_lte(filp->f_cred->fsuid, uid_max)) ^ |
| 58 | !(info->invert & XT_OWNER_UID)) | 87 | !(info->invert & XT_OWNER_UID)) |
| @@ -60,8 +89,8 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 60 | } | 89 | } |
| 61 | 90 | ||
| 62 | if (info->match & XT_OWNER_GID) { | 91 | if (info->match & XT_OWNER_GID) { |
| 63 | kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min); | 92 | kgid_t gid_min = make_kgid(net->user_ns, info->gid_min); |
| 64 | kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max); | 93 | kgid_t gid_max = make_kgid(net->user_ns, info->gid_max); |
| 65 | if ((gid_gte(filp->f_cred->fsgid, gid_min) && | 94 | if ((gid_gte(filp->f_cred->fsgid, gid_min) && |
| 66 | gid_lte(filp->f_cred->fsgid, gid_max)) ^ | 95 | gid_lte(filp->f_cred->fsgid, gid_max)) ^ |
| 67 | !(info->invert & XT_OWNER_GID)) | 96 | !(info->invert & XT_OWNER_GID)) |
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c index c14d4645daa3..ade024c90f4f 100644 --- a/net/netfilter/xt_tcpudp.c +++ b/net/netfilter/xt_tcpudp.c | |||
| @@ -83,8 +83,6 @@ static bool tcp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 83 | return false; | 83 | return false; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | #define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg))) | ||
| 87 | |||
| 88 | th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); | 86 | th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); |
| 89 | if (th == NULL) { | 87 | if (th == NULL) { |
| 90 | /* We've been asked to examine this packet, and we | 88 | /* We've been asked to examine this packet, and we |
| @@ -102,9 +100,8 @@ static bool tcp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 102 | ntohs(th->dest), | 100 | ntohs(th->dest), |
| 103 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) | 101 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) |
| 104 | return false; | 102 | return false; |
| 105 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | 103 | if (!NF_INVF(tcpinfo, XT_TCP_INV_FLAGS, |
| 106 | == tcpinfo->flg_cmp, | 104 | (((unsigned char *)th)[13] & tcpinfo->flg_mask) == tcpinfo->flg_cmp)) |
| 107 | XT_TCP_INV_FLAGS)) | ||
| 108 | return false; | 105 | return false; |
| 109 | if (tcpinfo->option) { | 106 | if (tcpinfo->option) { |
| 110 | if (th->doff * 4 < sizeof(_tcph)) { | 107 | if (th->doff * 4 < sizeof(_tcph)) { |
