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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

A final pull request, I know it's very late but this time I think it's worth a
bit of rush.

The following patchset contains Netfilter/nf_tables updates for net-next, more
specifically concatenation support and dynamic stateful expression
instantiation.

This also comes with a couple of small patches. One to fix the ebtables.h
userspace header and another to get rid of an obsolete example file in tree
that describes a nf_tables expression.

This time, I decided to paste the original descriptions. This will result in a
rather large commit description, but I think these bytes to keep.

Patrick McHardy says:

====================
netfilter: nf_tables: concatenation support

The following patches add support for concatenations, which allow multi
dimensional exact matches in O(1).

The basic idea is to split the data registers, currently consisting of
4 registers of 16 bytes each, into smaller units, 16 registers of 4
bytes each, and making sure each register store always leaves the
full 32 bit in a well defined state, meaning smaller stores will
zero the remaining bits.

Based on that, we can load multiple adjacent registers with different
values, thereby building a concatenated bigger value, and use that
value for set lookups.

Sets are changed to use variable sized extensions for their key and
data values, removing the fixed limit of 16 bytes while saving memory
if less space is needed.

As a side effect, these patches will allow some nice optimizations in
the future, like using jhash2 in nft_hash, removing the masking in
nft_cmp_fast, optimized data comparison using 32 bit word size etc.
These are not done so far however.

The patches are split up as follows:

* the first five patches add length validation to register loads and
stores to make sure we stay within bounds and prepare the validation
functions for the new addressing mode

* the next patches prepare for changing to 32 bit addressing by
introducing a struct nft_regs, which holds the verdict register as
well as the data registers. The verdict members are moved to a new
struct nft_verdict to allow to pull struct nft_data out of the stack.

* the next patches contain preparatory conversions of expressions and
sets to use 32 bit addressing

* the next patch introduces so far unused register conversion helpers
for parsing and dumping register numbers over netlink

* following is the real conversion to 32 bit addressing, consisting of
replacing struct nft_data in struct nft_regs by an array of u32s and
actually translating and validating the new register numbers.

* the final two patches add support for variable sized data items and
variable sized keys / data in set elements

The patches have been verified to work correctly with nft binaries using
both old and new addressing.
====================

Patrick McHardy says:

====================
netfilter: nf_tables: dynamic stateful expression instantiation

The following patches are the grand finale of my nf_tables set work,
using all the building blocks put in place by the previous patches
to support something like iptables hashlimit, but a lot more powerful.

Sets are extended to allow attaching expressions to set elements.
The dynset expression dynamically instantiates these expressions
based on a template when creating new set elements and evaluates
them for all new or updated set members.

In combination with concatenations this effectively creates state
tables for arbitrary combinations of keys, using the existing
expression types to maintain that state. Regular set GC takes care
of purging expired states.

We currently support two different stateful expressions, counter
and limit. Using limit as a template we can express the functionality
of hashlimit, but completely unrestricted in the combination of keys.
Using counter we can perform accounting for arbitrary flows.

The following examples from patch 5/5 show some possibilities.
Userspace syntax is still WIP, especially the listing of state
tables will most likely be seperated from normal set listings
and use a more structured format:

1. Limit the rate of new SSH connections per host, similar to iptables
hashlimit:

flow ip saddr timeout 60s \
limit 10/second \
accept

2. Account network traffic between each set of /24 networks:

flow ip saddr & 255.255.255.0 . ip daddr & 255.255.255.0 \
counter

3. Account traffic to each host per user:

flow skuid . ip daddr \
counter

4. Account traffic for each combination of source address and TCP flags:

flow ip saddr . tcp flags \
counter

The resulting set content after a Xmas-scan look like this:

{
192.168.122.1 . fin | psh | urg : counter packets 1001 bytes 40040,
192.168.122.1 . ack : counter packets 74 bytes 3848,
192.168.122.1 . psh | ack : counter packets 35 bytes 3144
}

In the future the "expressions attached to elements" will be extended
to also support user created non-stateful expressions to allow to
efficiently select beween a set of parameter sets, f.i. a set of log
statements with different prefixes based on the interface, which currently
require one rule each. This will most likely have to wait until the next
kernel version though.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+745 -585
+2 -1
include/linux/netfilter_bridge/ebtables.h
··· 12 12 #ifndef __LINUX_BRIDGE_EFF_H 13 13 #define __LINUX_BRIDGE_EFF_H 14 14 15 + #include <linux/if.h> 16 + #include <linux/if_ether.h> 15 17 #include <uapi/linux/netfilter_bridge/ebtables.h> 16 - 17 18 18 19 /* return values for match() functions */ 19 20 #define EBT_MATCH 0
+73 -30
include/net/netfilter/nf_tables.h
··· 1 1 #ifndef _NET_NF_TABLES_H 2 2 #define _NET_NF_TABLES_H 3 3 4 + #include <linux/module.h> 4 5 #include <linux/list.h> 5 6 #include <linux/netfilter.h> 6 7 #include <linux/netfilter/nfnetlink.h> ··· 37 36 pkt->xt.family = ops->pf; 38 37 } 39 38 39 + /** 40 + * struct nft_verdict - nf_tables verdict 41 + * 42 + * @code: nf_tables/netfilter verdict code 43 + * @chain: destination chain for NFT_JUMP/NFT_GOTO 44 + */ 45 + struct nft_verdict { 46 + u32 code; 47 + struct nft_chain *chain; 48 + }; 49 + 40 50 struct nft_data { 41 51 union { 42 - u32 data[4]; 43 - struct { 44 - u32 verdict; 45 - struct nft_chain *chain; 46 - }; 52 + u32 data[4]; 53 + struct nft_verdict verdict; 47 54 }; 48 55 } __attribute__((aligned(__alignof__(u64)))); 49 56 50 - static inline int nft_data_cmp(const struct nft_data *d1, 51 - const struct nft_data *d2, 52 - unsigned int len) 53 - { 54 - return memcmp(d1->data, d2->data, len); 55 - } 57 + /** 58 + * struct nft_regs - nf_tables register set 59 + * 60 + * @data: data registers 61 + * @verdict: verdict register 62 + * 63 + * The first four data registers alias to the verdict register. 64 + */ 65 + struct nft_regs { 66 + union { 67 + u32 data[20]; 68 + struct nft_verdict verdict; 69 + }; 70 + }; 56 71 57 - static inline void nft_data_copy(struct nft_data *dst, 58 - const struct nft_data *src) 72 + static inline void nft_data_copy(u32 *dst, const struct nft_data *src, 73 + unsigned int len) 59 74 { 60 - BUILD_BUG_ON(__alignof__(*dst) != __alignof__(u64)); 61 - *(u64 *)&dst->data[0] = *(u64 *)&src->data[0]; 62 - *(u64 *)&dst->data[2] = *(u64 *)&src->data[2]; 75 + memcpy(dst, src, len); 63 76 } 64 77 65 78 static inline void nft_data_debug(const struct nft_data *data) ··· 111 96 unsigned int len; 112 97 }; 113 98 114 - int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, 99 + int nft_data_init(const struct nft_ctx *ctx, 100 + struct nft_data *data, unsigned int size, 115 101 struct nft_data_desc *desc, const struct nlattr *nla); 116 102 void nft_data_uninit(const struct nft_data *data, enum nft_data_types type); 117 103 int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, ··· 128 112 return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1; 129 113 } 130 114 131 - int nft_validate_input_register(enum nft_registers reg); 132 - int nft_validate_output_register(enum nft_registers reg); 133 - int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, 134 - const struct nft_data *data, 135 - enum nft_data_types type); 115 + unsigned int nft_parse_register(const struct nlattr *attr); 116 + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); 136 117 118 + int nft_validate_register_load(enum nft_registers reg, unsigned int len); 119 + int nft_validate_register_store(const struct nft_ctx *ctx, 120 + enum nft_registers reg, 121 + const struct nft_data *data, 122 + enum nft_data_types type, unsigned int len); 137 123 138 124 /** 139 125 * struct nft_userdata - user defined data associated with an object ··· 159 141 * @priv: element private data and extensions 160 142 */ 161 143 struct nft_set_elem { 162 - struct nft_data key; 144 + union { 145 + u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; 146 + struct nft_data val; 147 + } key; 163 148 void *priv; 164 149 }; 165 150 ··· 237 216 */ 238 217 struct nft_set_ops { 239 218 bool (*lookup)(const struct nft_set *set, 240 - const struct nft_data *key, 219 + const u32 *key, 241 220 const struct nft_set_ext **ext); 242 221 bool (*update)(struct nft_set *set, 243 - const struct nft_data *key, 222 + const u32 *key, 244 223 void *(*new)(struct nft_set *, 245 224 const struct nft_expr *, 246 - struct nft_data []), 225 + struct nft_regs *), 247 226 const struct nft_expr *expr, 248 - struct nft_data data[], 227 + struct nft_regs *regs, 249 228 const struct nft_set_ext **ext); 250 229 251 230 int (*insert)(const struct nft_set *set, ··· 371 350 * @NFT_SET_EXT_TIMEOUT: element timeout 372 351 * @NFT_SET_EXT_EXPIRATION: element expiration time 373 352 * @NFT_SET_EXT_USERDATA: user data associated with the element 353 + * @NFT_SET_EXT_EXPR: expression assiociated with the element 374 354 * @NFT_SET_EXT_NUM: number of extension types 375 355 */ 376 356 enum nft_set_extensions { ··· 381 359 NFT_SET_EXT_TIMEOUT, 382 360 NFT_SET_EXT_EXPIRATION, 383 361 NFT_SET_EXT_USERDATA, 362 + NFT_SET_EXT_EXPR, 384 363 NFT_SET_EXT_NUM 385 364 }; 386 365 ··· 493 470 return nft_set_ext(ext, NFT_SET_EXT_USERDATA); 494 471 } 495 472 473 + static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext) 474 + { 475 + return nft_set_ext(ext, NFT_SET_EXT_EXPR); 476 + } 477 + 496 478 static inline bool nft_set_elem_expired(const struct nft_set_ext *ext) 497 479 { 498 480 return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) && ··· 512 484 513 485 void *nft_set_elem_init(const struct nft_set *set, 514 486 const struct nft_set_ext_tmpl *tmpl, 515 - const struct nft_data *key, 516 - const struct nft_data *data, 487 + const u32 *key, const u32 *data, 517 488 u64 timeout, gfp_t gfp); 518 489 void nft_set_elem_destroy(const struct nft_set *set, void *elem); 519 490 ··· 583 556 * @policy: netlink attribute policy 584 557 * @maxattr: highest netlink attribute number 585 558 * @family: address family for AF-specific types 559 + * @flags: expression type flags 586 560 */ 587 561 struct nft_expr_type { 588 562 const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *, ··· 595 567 const struct nla_policy *policy; 596 568 unsigned int maxattr; 597 569 u8 family; 570 + u8 flags; 598 571 }; 572 + 573 + #define NFT_EXPR_STATEFUL 0x1 599 574 600 575 /** 601 576 * struct nft_expr_ops - nf_tables expression operations ··· 615 584 struct nft_expr; 616 585 struct nft_expr_ops { 617 586 void (*eval)(const struct nft_expr *expr, 618 - struct nft_data data[NFT_REG_MAX + 1], 587 + struct nft_regs *regs, 619 588 const struct nft_pktinfo *pkt); 620 589 unsigned int size; 621 590 ··· 651 620 static inline void *nft_expr_priv(const struct nft_expr *expr) 652 621 { 653 622 return (void *)expr->data; 623 + } 624 + 625 + struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, 626 + const struct nlattr *nla); 627 + void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr); 628 + int nft_expr_dump(struct sk_buff *skb, unsigned int attr, 629 + const struct nft_expr *expr); 630 + 631 + static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src) 632 + { 633 + __module_get(src->ops->type->owner); 634 + memcpy(dst, src, src->ops->size); 654 635 } 655 636 656 637 /**
+2 -2
include/net/netfilter/nft_meta.h
··· 26 26 const struct nft_expr *expr); 27 27 28 28 void nft_meta_get_eval(const struct nft_expr *expr, 29 - struct nft_data data[NFT_REG_MAX + 1], 29 + struct nft_regs *regs, 30 30 const struct nft_pktinfo *pkt); 31 31 32 32 void nft_meta_set_eval(const struct nft_expr *expr, 33 - struct nft_data data[NFT_REG_MAX + 1], 33 + struct nft_regs *regs, 34 34 const struct nft_pktinfo *pkt); 35 35 36 36 #endif
+39 -1
include/uapi/linux/netfilter/nf_tables.h
··· 5 5 #define NFT_CHAIN_MAXNAMELEN 32 6 6 #define NFT_USERDATA_MAXLEN 256 7 7 8 + /** 9 + * enum nft_registers - nf_tables registers 10 + * 11 + * nf_tables used to have five registers: a verdict register and four data 12 + * registers of size 16. The data registers have been changed to 16 registers 13 + * of size 4. For compatibility reasons, the NFT_REG_[1-4] registers still 14 + * map to areas of size 16, the 4 byte registers are addressed using 15 + * NFT_REG32_00 - NFT_REG32_15. 16 + */ 8 17 enum nft_registers { 9 18 NFT_REG_VERDICT, 10 19 NFT_REG_1, 11 20 NFT_REG_2, 12 21 NFT_REG_3, 13 22 NFT_REG_4, 14 - __NFT_REG_MAX 23 + __NFT_REG_MAX, 24 + 25 + NFT_REG32_00 = 8, 26 + MFT_REG32_01, 27 + NFT_REG32_02, 28 + NFT_REG32_03, 29 + NFT_REG32_04, 30 + NFT_REG32_05, 31 + NFT_REG32_06, 32 + NFT_REG32_07, 33 + NFT_REG32_08, 34 + NFT_REG32_09, 35 + NFT_REG32_10, 36 + NFT_REG32_11, 37 + NFT_REG32_12, 38 + NFT_REG32_13, 39 + NFT_REG32_14, 40 + NFT_REG32_15, 15 41 }; 16 42 #define NFT_REG_MAX (__NFT_REG_MAX - 1) 43 + 44 + #define NFT_REG_SIZE 16 45 + #define NFT_REG32_SIZE 4 17 46 18 47 /** 19 48 * enum nft_verdicts - nf_tables internal verdicts ··· 238 209 * @NFT_SET_INTERVAL: set contains intervals 239 210 * @NFT_SET_MAP: set is used as a dictionary 240 211 * @NFT_SET_TIMEOUT: set uses timeouts 212 + * @NFT_SET_EVAL: set contains expressions for evaluation 241 213 */ 242 214 enum nft_set_flags { 243 215 NFT_SET_ANONYMOUS = 0x1, ··· 246 216 NFT_SET_INTERVAL = 0x4, 247 217 NFT_SET_MAP = 0x8, 248 218 NFT_SET_TIMEOUT = 0x10, 219 + NFT_SET_EVAL = 0x20, 249 220 }; 250 221 251 222 /** ··· 324 293 * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64) 325 294 * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64) 326 295 * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) 296 + * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) 327 297 */ 328 298 enum nft_set_elem_attributes { 329 299 NFTA_SET_ELEM_UNSPEC, ··· 334 302 NFTA_SET_ELEM_TIMEOUT, 335 303 NFTA_SET_ELEM_EXPIRATION, 336 304 NFTA_SET_ELEM_USERDATA, 305 + NFTA_SET_ELEM_EXPR, 337 306 __NFTA_SET_ELEM_MAX 338 307 }; 339 308 #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) ··· 391 358 __NFTA_DATA_MAX 392 359 }; 393 360 #define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1) 361 + 362 + /* Maximum length of a value */ 363 + #define NFT_DATA_VALUE_MAXLEN 64 394 364 395 365 /** 396 366 * enum nft_verdict_attributes - nf_tables verdict netlink attributes ··· 567 531 * @NFTA_DYNSET_SREG_KEY: source register of the key (NLA_U32) 568 532 * @NFTA_DYNSET_SREG_DATA: source register of the data (NLA_U32) 569 533 * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64) 534 + * @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes) 570 535 */ 571 536 enum nft_dynset_attributes { 572 537 NFTA_DYNSET_UNSPEC, ··· 577 540 NFTA_DYNSET_SREG_KEY, 578 541 NFTA_DYNSET_SREG_DATA, 579 542 NFTA_DYNSET_TIMEOUT, 543 + NFTA_DYNSET_EXPR, 580 544 __NFTA_DYNSET_MAX, 581 545 }; 582 546 #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1)
-2
include/uapi/linux/netfilter_bridge/ebtables.h
··· 12 12 13 13 #ifndef _UAPI__LINUX_BRIDGE_EFF_H 14 14 #define _UAPI__LINUX_BRIDGE_EFF_H 15 - #include <linux/if.h> 16 15 #include <linux/netfilter_bridge.h> 17 - #include <linux/if_ether.h> 18 16 19 17 #define EBT_TABLE_MAXNAMELEN 32 20 18 #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN
+10 -16
net/bridge/netfilter/nft_meta_bridge.c
··· 19 19 #include "../br_private.h" 20 20 21 21 static void nft_meta_bridge_get_eval(const struct nft_expr *expr, 22 - struct nft_data data[NFT_REG_MAX + 1], 22 + struct nft_regs *regs, 23 23 const struct nft_pktinfo *pkt) 24 24 { 25 25 const struct nft_meta *priv = nft_expr_priv(expr); 26 26 const struct net_device *in = pkt->in, *out = pkt->out; 27 - struct nft_data *dest = &data[priv->dreg]; 27 + u32 *dest = &regs->data[priv->dreg]; 28 28 const struct net_bridge_port *p; 29 29 30 30 switch (priv->key) { ··· 40 40 goto out; 41 41 } 42 42 43 - strncpy((char *)dest->data, p->br->dev->name, sizeof(dest->data)); 43 + strncpy((char *)dest, p->br->dev->name, IFNAMSIZ); 44 44 return; 45 45 out: 46 - return nft_meta_get_eval(expr, data, pkt); 46 + return nft_meta_get_eval(expr, regs, pkt); 47 47 err: 48 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 48 + regs->verdict.code = NFT_BREAK; 49 49 } 50 50 51 51 static int nft_meta_bridge_get_init(const struct nft_ctx *ctx, ··· 53 53 const struct nlattr * const tb[]) 54 54 { 55 55 struct nft_meta *priv = nft_expr_priv(expr); 56 - int err; 56 + unsigned int len; 57 57 58 58 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 59 59 switch (priv->key) { 60 60 case NFT_META_BRI_IIFNAME: 61 61 case NFT_META_BRI_OIFNAME: 62 + len = IFNAMSIZ; 62 63 break; 63 64 default: 64 65 return nft_meta_get_init(ctx, expr, tb); 65 66 } 66 67 67 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG])); 68 - err = nft_validate_output_register(priv->dreg); 69 - if (err < 0) 70 - return err; 71 - 72 - err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 73 - if (err < 0) 74 - return err; 75 - 76 - return 0; 68 + priv->dreg = nft_parse_register(tb[NFTA_META_DREG]); 69 + return nft_validate_register_store(ctx, priv->dreg, NULL, 70 + NFT_DATA_VALUE, len); 77 71 } 78 72 79 73 static struct nft_expr_type nft_meta_bridge_type;
+3 -3
net/bridge/netfilter/nft_reject_bridge.c
··· 257 257 } 258 258 259 259 static void nft_reject_bridge_eval(const struct nft_expr *expr, 260 - struct nft_data data[NFT_REG_MAX + 1], 261 - const struct nft_pktinfo *pkt) 260 + struct nft_regs *regs, 261 + const struct nft_pktinfo *pkt) 262 262 { 263 263 struct nft_reject *priv = nft_expr_priv(expr); 264 264 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); ··· 310 310 break; 311 311 } 312 312 out: 313 - data[NFT_REG_VERDICT].verdict = NF_DROP; 313 + regs->verdict.code = NF_DROP; 314 314 } 315 315 316 316 static int nft_reject_bridge_validate(const struct nft_ctx *ctx,
+3 -6
net/ipv4/netfilter/nft_masq_ipv4.c
··· 17 17 #include <net/netfilter/ipv4/nf_nat_masquerade.h> 18 18 19 19 static void nft_masq_ipv4_eval(const struct nft_expr *expr, 20 - struct nft_data data[NFT_REG_MAX + 1], 20 + struct nft_regs *regs, 21 21 const struct nft_pktinfo *pkt) 22 22 { 23 23 struct nft_masq *priv = nft_expr_priv(expr); 24 24 struct nf_nat_range range; 25 - unsigned int verdict; 26 25 27 26 memset(&range, 0, sizeof(range)); 28 27 range.flags = priv->flags; 29 28 30 - verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, 31 - &range, pkt->out); 32 - 33 - data[NFT_REG_VERDICT].verdict = verdict; 29 + regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum, 30 + &range, pkt->out); 34 31 } 35 32 36 33 static struct nft_expr_type nft_masq_ipv4_type;
+5 -6
net/ipv4/netfilter/nft_redir_ipv4.c
··· 18 18 #include <net/netfilter/nft_redir.h> 19 19 20 20 static void nft_redir_ipv4_eval(const struct nft_expr *expr, 21 - struct nft_data data[NFT_REG_MAX + 1], 21 + struct nft_regs *regs, 22 22 const struct nft_pktinfo *pkt) 23 23 { 24 24 struct nft_redir *priv = nft_expr_priv(expr); 25 25 struct nf_nat_ipv4_multi_range_compat mr; 26 - unsigned int verdict; 27 26 28 27 memset(&mr, 0, sizeof(mr)); 29 28 if (priv->sreg_proto_min) { 30 29 mr.range[0].min.all = 31 - *(__be16 *)&data[priv->sreg_proto_min].data[0]; 30 + *(__be16 *)&regs->data[priv->sreg_proto_min]; 32 31 mr.range[0].max.all = 33 - *(__be16 *)&data[priv->sreg_proto_max].data[0]; 32 + *(__be16 *)&regs->data[priv->sreg_proto_max]; 34 33 mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 35 34 } 36 35 37 36 mr.range[0].flags |= priv->flags; 38 37 39 - verdict = nf_nat_redirect_ipv4(pkt->skb, &mr, pkt->ops->hooknum); 40 - data[NFT_REG_VERDICT].verdict = verdict; 38 + regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, 39 + pkt->ops->hooknum); 41 40 } 42 41 43 42 static struct nft_expr_type nft_redir_ipv4_type;
+2 -2
net/ipv4/netfilter/nft_reject_ipv4.c
··· 20 20 #include <net/netfilter/nft_reject.h> 21 21 22 22 static void nft_reject_ipv4_eval(const struct nft_expr *expr, 23 - struct nft_data data[NFT_REG_MAX + 1], 23 + struct nft_regs *regs, 24 24 const struct nft_pktinfo *pkt) 25 25 { 26 26 struct nft_reject *priv = nft_expr_priv(expr); ··· 37 37 break; 38 38 } 39 39 40 - data[NFT_REG_VERDICT].verdict = NF_DROP; 40 + regs->verdict.code = NF_DROP; 41 41 } 42 42 43 43 static struct nft_expr_type nft_reject_ipv4_type;
+2 -5
net/ipv6/netfilter/nft_masq_ipv6.c
··· 18 18 #include <net/netfilter/ipv6/nf_nat_masquerade.h> 19 19 20 20 static void nft_masq_ipv6_eval(const struct nft_expr *expr, 21 - struct nft_data data[NFT_REG_MAX + 1], 21 + struct nft_regs *regs, 22 22 const struct nft_pktinfo *pkt) 23 23 { 24 24 struct nft_masq *priv = nft_expr_priv(expr); 25 25 struct nf_nat_range range; 26 - unsigned int verdict; 27 26 28 27 memset(&range, 0, sizeof(range)); 29 28 range.flags = priv->flags; 30 29 31 - verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); 32 - 33 - data[NFT_REG_VERDICT].verdict = verdict; 30 + regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); 34 31 } 35 32 36 33 static struct nft_expr_type nft_masq_ipv6_type;
+5 -6
net/ipv6/netfilter/nft_redir_ipv6.c
··· 18 18 #include <net/netfilter/nf_nat_redirect.h> 19 19 20 20 static void nft_redir_ipv6_eval(const struct nft_expr *expr, 21 - struct nft_data data[NFT_REG_MAX + 1], 21 + struct nft_regs *regs, 22 22 const struct nft_pktinfo *pkt) 23 23 { 24 24 struct nft_redir *priv = nft_expr_priv(expr); 25 25 struct nf_nat_range range; 26 - unsigned int verdict; 27 26 28 27 memset(&range, 0, sizeof(range)); 29 28 if (priv->sreg_proto_min) { 30 29 range.min_proto.all = 31 - *(__be16 *)&data[priv->sreg_proto_min].data[0]; 30 + *(__be16 *)&regs->data[priv->sreg_proto_min], 32 31 range.max_proto.all = 33 - *(__be16 *)&data[priv->sreg_proto_max].data[0]; 32 + *(__be16 *)&regs->data[priv->sreg_proto_max], 34 33 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 35 34 } 36 35 37 36 range.flags |= priv->flags; 38 37 39 - verdict = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->ops->hooknum); 40 - data[NFT_REG_VERDICT].verdict = verdict; 38 + regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, 39 + pkt->ops->hooknum); 41 40 } 42 41 43 42 static struct nft_expr_type nft_redir_ipv6_type;
+2 -2
net/ipv6/netfilter/nft_reject_ipv6.c
··· 20 20 #include <net/netfilter/ipv6/nf_reject.h> 21 21 22 22 static void nft_reject_ipv6_eval(const struct nft_expr *expr, 23 - struct nft_data data[NFT_REG_MAX + 1], 23 + struct nft_regs *regs, 24 24 const struct nft_pktinfo *pkt) 25 25 { 26 26 struct nft_reject *priv = nft_expr_priv(expr); ··· 38 38 break; 39 39 } 40 40 41 - data[NFT_REG_VERDICT].verdict = NF_DROP; 41 + regs->verdict.code = NF_DROP; 42 42 } 43 43 44 44 static struct nft_expr_type nft_reject_ipv6_type;
+196 -87
net/netfilter/nf_tables_api.c
··· 1545 1545 return -1; 1546 1546 }; 1547 1547 1548 + int nft_expr_dump(struct sk_buff *skb, unsigned int attr, 1549 + const struct nft_expr *expr) 1550 + { 1551 + struct nlattr *nest; 1552 + 1553 + nest = nla_nest_start(skb, attr); 1554 + if (!nest) 1555 + goto nla_put_failure; 1556 + if (nf_tables_fill_expr_info(skb, expr) < 0) 1557 + goto nla_put_failure; 1558 + nla_nest_end(skb, nest); 1559 + return 0; 1560 + 1561 + nla_put_failure: 1562 + return -1; 1563 + } 1564 + 1548 1565 struct nft_expr_info { 1549 1566 const struct nft_expr_ops *ops; 1550 1567 struct nlattr *tb[NFT_EXPR_MAXATTR + 1]; ··· 1637 1620 if (expr->ops->destroy) 1638 1621 expr->ops->destroy(ctx, expr); 1639 1622 module_put(expr->ops->type->owner); 1623 + } 1624 + 1625 + struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, 1626 + const struct nlattr *nla) 1627 + { 1628 + struct nft_expr_info info; 1629 + struct nft_expr *expr; 1630 + int err; 1631 + 1632 + err = nf_tables_expr_parse(ctx, nla, &info); 1633 + if (err < 0) 1634 + goto err1; 1635 + 1636 + err = -ENOMEM; 1637 + expr = kzalloc(info.ops->size, GFP_KERNEL); 1638 + if (expr == NULL) 1639 + goto err2; 1640 + 1641 + err = nf_tables_newexpr(ctx, &info, expr); 1642 + if (err < 0) 1643 + goto err2; 1644 + 1645 + return expr; 1646 + err2: 1647 + module_put(info.ops->type->owner); 1648 + err1: 1649 + return ERR_PTR(err); 1650 + } 1651 + 1652 + void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr) 1653 + { 1654 + nf_tables_expr_destroy(ctx, expr); 1655 + kfree(expr); 1640 1656 } 1641 1657 1642 1658 /* ··· 1753 1703 if (list == NULL) 1754 1704 goto nla_put_failure; 1755 1705 nft_rule_for_each_expr(expr, next, rule) { 1756 - struct nlattr *elem = nla_nest_start(skb, NFTA_LIST_ELEM); 1757 - if (elem == NULL) 1706 + if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0) 1758 1707 goto nla_put_failure; 1759 - if (nf_tables_fill_expr_info(skb, expr) < 0) 1760 - goto nla_put_failure; 1761 - nla_nest_end(skb, elem); 1762 1708 } 1763 1709 nla_nest_end(skb, list); 1764 1710 ··· 2654 2608 } 2655 2609 2656 2610 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); 2657 - if (desc.klen == 0 || desc.klen > FIELD_SIZEOF(struct nft_data, data)) 2611 + if (desc.klen == 0 || desc.klen > NFT_DATA_VALUE_MAXLEN) 2658 2612 return -EINVAL; 2659 2613 2660 2614 flags = 0; 2661 2615 if (nla[NFTA_SET_FLAGS] != NULL) { 2662 2616 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2663 2617 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | 2664 - NFT_SET_INTERVAL | NFT_SET_MAP | 2665 - NFT_SET_TIMEOUT)) 2618 + NFT_SET_INTERVAL | NFT_SET_TIMEOUT | 2619 + NFT_SET_MAP | NFT_SET_EVAL)) 2666 2620 return -EINVAL; 2621 + /* Only one of both operations is supported */ 2622 + if ((flags & (NFT_SET_MAP | NFT_SET_EVAL)) == 2623 + (NFT_SET_MAP | NFT_SET_EVAL)) 2624 + return -EOPNOTSUPP; 2667 2625 } 2668 2626 2669 2627 dtype = 0; ··· 2684 2634 if (nla[NFTA_SET_DATA_LEN] == NULL) 2685 2635 return -EINVAL; 2686 2636 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN])); 2687 - if (desc.dlen == 0 || 2688 - desc.dlen > FIELD_SIZEOF(struct nft_data, data)) 2637 + if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN) 2689 2638 return -EINVAL; 2690 2639 } else 2691 - desc.dlen = sizeof(struct nft_data); 2640 + desc.dlen = sizeof(struct nft_verdict); 2692 2641 } else if (flags & NFT_SET_MAP) 2693 2642 return -EINVAL; 2694 2643 ··· 2846 2797 enum nft_registers dreg; 2847 2798 2848 2799 dreg = nft_type_to_reg(set->dtype); 2849 - return nft_validate_data_load(ctx, dreg, nft_set_ext_data(ext), 2850 - set->dtype == NFT_DATA_VERDICT ? 2851 - NFT_DATA_VERDICT : NFT_DATA_VALUE); 2800 + return nft_validate_register_store(ctx, dreg, nft_set_ext_data(ext), 2801 + set->dtype == NFT_DATA_VERDICT ? 2802 + NFT_DATA_VERDICT : NFT_DATA_VALUE, 2803 + set->dlen); 2852 2804 } 2853 2805 2854 2806 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, ··· 2903 2853 2904 2854 const struct nft_set_ext_type nft_set_ext_types[] = { 2905 2855 [NFT_SET_EXT_KEY] = { 2906 - .len = sizeof(struct nft_data), 2907 - .align = __alignof__(struct nft_data), 2856 + .align = __alignof__(u32), 2908 2857 }, 2909 2858 [NFT_SET_EXT_DATA] = { 2910 - .len = sizeof(struct nft_data), 2911 - .align = __alignof__(struct nft_data), 2859 + .align = __alignof__(u32), 2860 + }, 2861 + [NFT_SET_EXT_EXPR] = { 2862 + .align = __alignof__(struct nft_expr), 2912 2863 }, 2913 2864 [NFT_SET_EXT_FLAGS] = { 2914 2865 .len = sizeof(u8), ··· 2995 2944 nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext), 2996 2945 set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE, 2997 2946 set->dlen) < 0) 2947 + goto nla_put_failure; 2948 + 2949 + if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR) && 2950 + nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0) 2998 2951 goto nla_put_failure; 2999 2952 3000 2953 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && ··· 3255 3200 3256 3201 void *nft_set_elem_init(const struct nft_set *set, 3257 3202 const struct nft_set_ext_tmpl *tmpl, 3258 - const struct nft_data *key, 3259 - const struct nft_data *data, 3203 + const u32 *key, const u32 *data, 3260 3204 u64 timeout, gfp_t gfp) 3261 3205 { 3262 3206 struct nft_set_ext *ext; ··· 3287 3233 nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE); 3288 3234 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) 3289 3235 nft_data_uninit(nft_set_ext_data(ext), set->dtype); 3236 + if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 3237 + nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); 3290 3238 3291 3239 kfree(elem); 3292 3240 } ··· 3355 3299 timeout = set->timeout; 3356 3300 } 3357 3301 3358 - err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]); 3302 + err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1, 3303 + nla[NFTA_SET_ELEM_KEY]); 3359 3304 if (err < 0) 3360 3305 goto err1; 3361 3306 err = -EINVAL; 3362 3307 if (d1.type != NFT_DATA_VALUE || d1.len != set->klen) 3363 3308 goto err2; 3364 3309 3365 - nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY); 3310 + nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len); 3366 3311 if (timeout > 0) { 3367 3312 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION); 3368 3313 if (timeout != set->timeout) ··· 3371 3314 } 3372 3315 3373 3316 if (nla[NFTA_SET_ELEM_DATA] != NULL) { 3374 - err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]); 3317 + err = nft_data_init(ctx, &data, sizeof(data), &d2, 3318 + nla[NFTA_SET_ELEM_DATA]); 3375 3319 if (err < 0) 3376 3320 goto err2; 3377 3321 ··· 3391 3333 if (!(binding->flags & NFT_SET_MAP)) 3392 3334 continue; 3393 3335 3394 - err = nft_validate_data_load(&bind_ctx, dreg, 3395 - &data, d2.type); 3336 + err = nft_validate_register_store(&bind_ctx, dreg, 3337 + &data, 3338 + d2.type, d2.len); 3396 3339 if (err < 0) 3397 3340 goto err3; 3398 3341 } 3399 3342 3400 - nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA); 3343 + nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len); 3401 3344 } 3402 3345 3403 3346 /* The full maximum length of userdata can exceed the maximum ··· 3414 3355 } 3415 3356 3416 3357 err = -ENOMEM; 3417 - elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data, 3358 + elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data, 3418 3359 timeout, GFP_KERNEL); 3419 3360 if (elem.priv == NULL) 3420 3361 goto err3; ··· 3449 3390 if (nla[NFTA_SET_ELEM_DATA] != NULL) 3450 3391 nft_data_uninit(&data, d2.type); 3451 3392 err2: 3452 - nft_data_uninit(&elem.key, d1.type); 3393 + nft_data_uninit(&elem.key.val, d1.type); 3453 3394 err1: 3454 3395 return err; 3455 3396 } ··· 3516 3457 if (nla[NFTA_SET_ELEM_KEY] == NULL) 3517 3458 goto err1; 3518 3459 3519 - err = nft_data_init(ctx, &elem.key, &desc, nla[NFTA_SET_ELEM_KEY]); 3460 + err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc, 3461 + nla[NFTA_SET_ELEM_KEY]); 3520 3462 if (err < 0) 3521 3463 goto err1; 3522 3464 ··· 3544 3484 err3: 3545 3485 kfree(trans); 3546 3486 err2: 3547 - nft_data_uninit(&elem.key, desc.type); 3487 + nft_data_uninit(&elem.key.val, desc.type); 3548 3488 err1: 3549 3489 return err; 3550 3490 } ··· 4107 4047 return 0; 4108 4048 4109 4049 data = nft_set_ext_data(ext); 4110 - switch (data->verdict) { 4050 + switch (data->verdict.code) { 4111 4051 case NFT_JUMP: 4112 4052 case NFT_GOTO: 4113 - return nf_tables_check_loops(ctx, data->chain); 4053 + return nf_tables_check_loops(ctx, data->verdict.chain); 4114 4054 default: 4115 4055 return 0; 4116 4056 } ··· 4143 4083 if (data == NULL) 4144 4084 continue; 4145 4085 4146 - switch (data->verdict) { 4086 + switch (data->verdict.code) { 4147 4087 case NFT_JUMP: 4148 4088 case NFT_GOTO: 4149 - err = nf_tables_check_loops(ctx, data->chain); 4089 + err = nf_tables_check_loops(ctx, 4090 + data->verdict.chain); 4150 4091 if (err < 0) 4151 4092 return err; 4152 4093 default: ··· 4181 4120 } 4182 4121 4183 4122 /** 4184 - * nft_validate_input_register - validate an expressions' input register 4123 + * nft_parse_register - parse a register value from a netlink attribute 4124 + * 4125 + * @attr: netlink attribute 4126 + * 4127 + * Parse and translate a register value from a netlink attribute. 4128 + * Registers used to be 128 bit wide, these register numbers will be 4129 + * mapped to the corresponding 32 bit register numbers. 4130 + */ 4131 + unsigned int nft_parse_register(const struct nlattr *attr) 4132 + { 4133 + unsigned int reg; 4134 + 4135 + reg = ntohl(nla_get_be32(attr)); 4136 + switch (reg) { 4137 + case NFT_REG_VERDICT...NFT_REG_4: 4138 + return reg * NFT_REG_SIZE / NFT_REG32_SIZE; 4139 + default: 4140 + return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00; 4141 + } 4142 + } 4143 + EXPORT_SYMBOL_GPL(nft_parse_register); 4144 + 4145 + /** 4146 + * nft_dump_register - dump a register value to a netlink attribute 4147 + * 4148 + * @skb: socket buffer 4149 + * @attr: attribute number 4150 + * @reg: register number 4151 + * 4152 + * Construct a netlink attribute containing the register number. For 4153 + * compatibility reasons, register numbers being a multiple of 4 are 4154 + * translated to the corresponding 128 bit register numbers. 4155 + */ 4156 + int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg) 4157 + { 4158 + if (reg % (NFT_REG_SIZE / NFT_REG32_SIZE) == 0) 4159 + reg = reg / (NFT_REG_SIZE / NFT_REG32_SIZE); 4160 + else 4161 + reg = reg - NFT_REG_SIZE / NFT_REG32_SIZE + NFT_REG32_00; 4162 + 4163 + return nla_put_be32(skb, attr, htonl(reg)); 4164 + } 4165 + EXPORT_SYMBOL_GPL(nft_dump_register); 4166 + 4167 + /** 4168 + * nft_validate_register_load - validate a load from a register 4185 4169 * 4186 4170 * @reg: the register number 4171 + * @len: the length of the data 4187 4172 * 4188 4173 * Validate that the input register is one of the general purpose 4189 - * registers. 4174 + * registers and that the length of the load is within the bounds. 4190 4175 */ 4191 - int nft_validate_input_register(enum nft_registers reg) 4176 + int nft_validate_register_load(enum nft_registers reg, unsigned int len) 4192 4177 { 4193 - if (reg <= NFT_REG_VERDICT) 4178 + if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) 4194 4179 return -EINVAL; 4195 - if (reg > NFT_REG_MAX) 4180 + if (len == 0) 4181 + return -EINVAL; 4182 + if (reg * NFT_REG32_SIZE + len > FIELD_SIZEOF(struct nft_regs, data)) 4196 4183 return -ERANGE; 4184 + 4197 4185 return 0; 4198 4186 } 4199 - EXPORT_SYMBOL_GPL(nft_validate_input_register); 4187 + EXPORT_SYMBOL_GPL(nft_validate_register_load); 4200 4188 4201 4189 /** 4202 - * nft_validate_output_register - validate an expressions' output register 4203 - * 4204 - * @reg: the register number 4205 - * 4206 - * Validate that the output register is one of the general purpose 4207 - * registers or the verdict register. 4208 - */ 4209 - int nft_validate_output_register(enum nft_registers reg) 4210 - { 4211 - if (reg < NFT_REG_VERDICT) 4212 - return -EINVAL; 4213 - if (reg > NFT_REG_MAX) 4214 - return -ERANGE; 4215 - return 0; 4216 - } 4217 - EXPORT_SYMBOL_GPL(nft_validate_output_register); 4218 - 4219 - /** 4220 - * nft_validate_data_load - validate an expressions' data load 4190 + * nft_validate_register_store - validate an expressions' register store 4221 4191 * 4222 4192 * @ctx: context of the expression performing the load 4223 4193 * @reg: the destination register number 4224 4194 * @data: the data to load 4225 4195 * @type: the data type 4196 + * @len: the length of the data 4226 4197 * 4227 4198 * Validate that a data load uses the appropriate data type for 4228 - * the destination register. A value of NULL for the data means 4229 - * that its runtime gathered data, which is always of type 4230 - * NFT_DATA_VALUE. 4199 + * the destination register and the length is within the bounds. 4200 + * A value of NULL for the data means that its runtime gathered 4201 + * data. 4231 4202 */ 4232 - int nft_validate_data_load(const struct nft_ctx *ctx, enum nft_registers reg, 4233 - const struct nft_data *data, 4234 - enum nft_data_types type) 4203 + int nft_validate_register_store(const struct nft_ctx *ctx, 4204 + enum nft_registers reg, 4205 + const struct nft_data *data, 4206 + enum nft_data_types type, unsigned int len) 4235 4207 { 4236 4208 int err; 4237 4209 4238 4210 switch (reg) { 4239 4211 case NFT_REG_VERDICT: 4240 - if (data == NULL || type != NFT_DATA_VERDICT) 4212 + if (type != NFT_DATA_VERDICT) 4241 4213 return -EINVAL; 4242 4214 4243 - if (data->verdict == NFT_GOTO || data->verdict == NFT_JUMP) { 4244 - err = nf_tables_check_loops(ctx, data->chain); 4215 + if (data != NULL && 4216 + (data->verdict.code == NFT_GOTO || 4217 + data->verdict.code == NFT_JUMP)) { 4218 + err = nf_tables_check_loops(ctx, data->verdict.chain); 4245 4219 if (err < 0) 4246 4220 return err; 4247 4221 4248 - if (ctx->chain->level + 1 > data->chain->level) { 4222 + if (ctx->chain->level + 1 > 4223 + data->verdict.chain->level) { 4249 4224 if (ctx->chain->level + 1 == NFT_JUMP_STACK_SIZE) 4250 4225 return -EMLINK; 4251 - data->chain->level = ctx->chain->level + 1; 4226 + data->verdict.chain->level = ctx->chain->level + 1; 4252 4227 } 4253 4228 } 4254 4229 4255 4230 return 0; 4256 4231 default: 4232 + if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) 4233 + return -EINVAL; 4234 + if (len == 0) 4235 + return -EINVAL; 4236 + if (reg * NFT_REG32_SIZE + len > 4237 + FIELD_SIZEOF(struct nft_regs, data)) 4238 + return -ERANGE; 4239 + 4257 4240 if (data != NULL && type != NFT_DATA_VALUE) 4258 4241 return -EINVAL; 4259 4242 return 0; 4260 4243 } 4261 4244 } 4262 - EXPORT_SYMBOL_GPL(nft_validate_data_load); 4245 + EXPORT_SYMBOL_GPL(nft_validate_register_store); 4263 4246 4264 4247 static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = { 4265 4248 [NFTA_VERDICT_CODE] = { .type = NLA_U32 }, ··· 4324 4219 4325 4220 if (!tb[NFTA_VERDICT_CODE]) 4326 4221 return -EINVAL; 4327 - data->verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); 4222 + data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); 4328 4223 4329 - switch (data->verdict) { 4224 + switch (data->verdict.code) { 4330 4225 default: 4331 - switch (data->verdict & NF_VERDICT_MASK) { 4226 + switch (data->verdict.code & NF_VERDICT_MASK) { 4332 4227 case NF_ACCEPT: 4333 4228 case NF_DROP: 4334 4229 case NF_QUEUE: ··· 4354 4249 return -EOPNOTSUPP; 4355 4250 4356 4251 chain->use++; 4357 - data->chain = chain; 4252 + data->verdict.chain = chain; 4358 4253 desc->len = sizeof(data); 4359 4254 break; 4360 4255 } ··· 4365 4260 4366 4261 static void nft_verdict_uninit(const struct nft_data *data) 4367 4262 { 4368 - switch (data->verdict) { 4263 + switch (data->verdict.code) { 4369 4264 case NFT_JUMP: 4370 4265 case NFT_GOTO: 4371 - data->chain->use--; 4266 + data->verdict.chain->use--; 4372 4267 break; 4373 4268 } 4374 4269 } ··· 4381 4276 if (!nest) 4382 4277 goto nla_put_failure; 4383 4278 4384 - if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict))) 4279 + if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(data->verdict.code))) 4385 4280 goto nla_put_failure; 4386 4281 4387 - switch (data->verdict) { 4282 + switch (data->verdict.code) { 4388 4283 case NFT_JUMP: 4389 4284 case NFT_GOTO: 4390 - if (nla_put_string(skb, NFTA_VERDICT_CHAIN, data->chain->name)) 4285 + if (nla_put_string(skb, NFTA_VERDICT_CHAIN, 4286 + data->verdict.chain->name)) 4391 4287 goto nla_put_failure; 4392 4288 } 4393 4289 nla_nest_end(skb, nest); ··· 4398 4292 return -1; 4399 4293 } 4400 4294 4401 - static int nft_value_init(const struct nft_ctx *ctx, struct nft_data *data, 4295 + static int nft_value_init(const struct nft_ctx *ctx, 4296 + struct nft_data *data, unsigned int size, 4402 4297 struct nft_data_desc *desc, const struct nlattr *nla) 4403 4298 { 4404 4299 unsigned int len; ··· 4407 4300 len = nla_len(nla); 4408 4301 if (len == 0) 4409 4302 return -EINVAL; 4410 - if (len > sizeof(data->data)) 4303 + if (len > size) 4411 4304 return -EOVERFLOW; 4412 4305 4413 - nla_memcpy(data->data, nla, sizeof(data->data)); 4306 + nla_memcpy(data->data, nla, len); 4414 4307 desc->type = NFT_DATA_VALUE; 4415 4308 desc->len = len; 4416 4309 return 0; ··· 4423 4316 } 4424 4317 4425 4318 static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = { 4426 - [NFTA_DATA_VALUE] = { .type = NLA_BINARY, 4427 - .len = FIELD_SIZEOF(struct nft_data, data) }, 4319 + [NFTA_DATA_VALUE] = { .type = NLA_BINARY }, 4428 4320 [NFTA_DATA_VERDICT] = { .type = NLA_NESTED }, 4429 4321 }; 4430 4322 ··· 4432 4326 * 4433 4327 * @ctx: context of the expression using the data 4434 4328 * @data: destination struct nft_data 4329 + * @size: maximum data length 4435 4330 * @desc: data description 4436 4331 * @nla: netlink attribute containing data 4437 4332 * ··· 4442 4335 * The caller can indicate that it only wants to accept data of type 4443 4336 * NFT_DATA_VALUE by passing NULL for the ctx argument. 4444 4337 */ 4445 - int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data, 4338 + int nft_data_init(const struct nft_ctx *ctx, 4339 + struct nft_data *data, unsigned int size, 4446 4340 struct nft_data_desc *desc, const struct nlattr *nla) 4447 4341 { 4448 4342 struct nlattr *tb[NFTA_DATA_MAX + 1]; ··· 4454 4346 return err; 4455 4347 4456 4348 if (tb[NFTA_DATA_VALUE]) 4457 - return nft_value_init(ctx, data, desc, tb[NFTA_DATA_VALUE]); 4349 + return nft_value_init(ctx, data, size, desc, 4350 + tb[NFTA_DATA_VALUE]); 4458 4351 if (tb[NFTA_DATA_VERDICT] && ctx != NULL) 4459 4352 return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]); 4460 4353 return -EINVAL;
+21 -20
net/netfilter/nf_tables_core.c
··· 65 65 } 66 66 67 67 static void nft_cmp_fast_eval(const struct nft_expr *expr, 68 - struct nft_data data[NFT_REG_MAX + 1]) 68 + struct nft_regs *regs) 69 69 { 70 70 const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); 71 71 u32 mask = nft_cmp_fast_mask(priv->len); 72 72 73 - if ((data[priv->sreg].data[0] & mask) == priv->data) 73 + if ((regs->data[priv->sreg] & mask) == priv->data) 74 74 return; 75 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 75 + regs->verdict.code = NFT_BREAK; 76 76 } 77 77 78 78 static bool nft_payload_fast_eval(const struct nft_expr *expr, 79 - struct nft_data data[NFT_REG_MAX + 1], 79 + struct nft_regs *regs, 80 80 const struct nft_pktinfo *pkt) 81 81 { 82 82 const struct nft_payload *priv = nft_expr_priv(expr); 83 83 const struct sk_buff *skb = pkt->skb; 84 - struct nft_data *dest = &data[priv->dreg]; 84 + u32 *dest = &regs->data[priv->dreg]; 85 85 unsigned char *ptr; 86 86 87 87 if (priv->base == NFT_PAYLOAD_NETWORK_HEADER) ··· 94 94 if (unlikely(ptr + priv->len >= skb_tail_pointer(skb))) 95 95 return false; 96 96 97 + *dest = 0; 97 98 if (priv->len == 2) 98 - *(u16 *)dest->data = *(u16 *)ptr; 99 + *(u16 *)dest = *(u16 *)ptr; 99 100 else if (priv->len == 4) 100 - *(u32 *)dest->data = *(u32 *)ptr; 101 + *(u32 *)dest = *(u32 *)ptr; 101 102 else 102 - *(u8 *)dest->data = *(u8 *)ptr; 103 + *(u8 *)dest = *(u8 *)ptr; 103 104 return true; 104 105 } 105 106 ··· 117 116 const struct net *net = read_pnet(&nft_base_chain(basechain)->pnet); 118 117 const struct nft_rule *rule; 119 118 const struct nft_expr *expr, *last; 120 - struct nft_data data[NFT_REG_MAX + 1]; 119 + struct nft_regs regs; 121 120 unsigned int stackptr = 0; 122 121 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; 123 122 struct nft_stats *stats; ··· 128 127 rulenum = 0; 129 128 rule = list_entry(&chain->rules, struct nft_rule, list); 130 129 next_rule: 131 - data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 130 + regs.verdict.code = NFT_CONTINUE; 132 131 list_for_each_entry_continue_rcu(rule, &chain->rules, list) { 133 132 134 133 /* This rule is not active, skip. */ ··· 139 138 140 139 nft_rule_for_each_expr(expr, last, rule) { 141 140 if (expr->ops == &nft_cmp_fast_ops) 142 - nft_cmp_fast_eval(expr, data); 141 + nft_cmp_fast_eval(expr, &regs); 143 142 else if (expr->ops != &nft_payload_fast_ops || 144 - !nft_payload_fast_eval(expr, data, pkt)) 145 - expr->ops->eval(expr, data, pkt); 143 + !nft_payload_fast_eval(expr, &regs, pkt)) 144 + expr->ops->eval(expr, &regs, pkt); 146 145 147 - if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE) 146 + if (regs.verdict.code != NFT_CONTINUE) 148 147 break; 149 148 } 150 149 151 - switch (data[NFT_REG_VERDICT].verdict) { 150 + switch (regs.verdict.code) { 152 151 case NFT_BREAK: 153 - data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 152 + regs.verdict.code = NFT_CONTINUE; 154 153 continue; 155 154 case NFT_CONTINUE: 156 155 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); ··· 159 158 break; 160 159 } 161 160 162 - switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) { 161 + switch (regs.verdict.code & NF_VERDICT_MASK) { 163 162 case NF_ACCEPT: 164 163 case NF_DROP: 165 164 case NF_QUEUE: 166 165 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); 167 - return data[NFT_REG_VERDICT].verdict; 166 + return regs.verdict.code; 168 167 } 169 168 170 - switch (data[NFT_REG_VERDICT].verdict) { 169 + switch (regs.verdict.code) { 171 170 case NFT_JUMP: 172 171 BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); 173 172 jumpstack[stackptr].chain = chain; ··· 178 177 case NFT_GOTO: 179 178 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); 180 179 181 - chain = data[NFT_REG_VERDICT].chain; 180 + chain = regs.verdict.chain; 182 181 goto do_chain; 183 182 case NFT_CONTINUE: 184 183 rulenum++;
+17 -20
net/netfilter/nft_bitwise.c
··· 26 26 }; 27 27 28 28 static void nft_bitwise_eval(const struct nft_expr *expr, 29 - struct nft_data data[NFT_REG_MAX + 1], 29 + struct nft_regs *regs, 30 30 const struct nft_pktinfo *pkt) 31 31 { 32 32 const struct nft_bitwise *priv = nft_expr_priv(expr); 33 - const struct nft_data *src = &data[priv->sreg]; 34 - struct nft_data *dst = &data[priv->dreg]; 33 + const u32 *src = &regs->data[priv->sreg]; 34 + u32 *dst = &regs->data[priv->dreg]; 35 35 unsigned int i; 36 36 37 - for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) { 38 - dst->data[i] = (src->data[i] & priv->mask.data[i]) ^ 39 - priv->xor.data[i]; 40 - } 37 + for (i = 0; i < DIV_ROUND_UP(priv->len, 4); i++) 38 + dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i]; 41 39 } 42 40 43 41 static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = { ··· 61 63 tb[NFTA_BITWISE_XOR] == NULL) 62 64 return -EINVAL; 63 65 64 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_SREG])); 65 - err = nft_validate_input_register(priv->sreg); 66 + priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN])); 67 + priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]); 68 + err = nft_validate_register_load(priv->sreg, priv->len); 66 69 if (err < 0) 67 70 return err; 68 71 69 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_BITWISE_DREG])); 70 - err = nft_validate_output_register(priv->dreg); 71 - if (err < 0) 72 - return err; 73 - err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 72 + priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]); 73 + err = nft_validate_register_store(ctx, priv->dreg, NULL, 74 + NFT_DATA_VALUE, priv->len); 74 75 if (err < 0) 75 76 return err; 76 77 77 - priv->len = ntohl(nla_get_be32(tb[NFTA_BITWISE_LEN])); 78 - 79 - err = nft_data_init(NULL, &priv->mask, &d1, tb[NFTA_BITWISE_MASK]); 78 + err = nft_data_init(NULL, &priv->mask, sizeof(priv->mask), &d1, 79 + tb[NFTA_BITWISE_MASK]); 80 80 if (err < 0) 81 81 return err; 82 82 if (d1.len != priv->len) 83 83 return -EINVAL; 84 84 85 - err = nft_data_init(NULL, &priv->xor, &d2, tb[NFTA_BITWISE_XOR]); 85 + err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, 86 + tb[NFTA_BITWISE_XOR]); 86 87 if (err < 0) 87 88 return err; 88 89 if (d2.len != priv->len) ··· 94 97 { 95 98 const struct nft_bitwise *priv = nft_expr_priv(expr); 96 99 97 - if (nla_put_be32(skb, NFTA_BITWISE_SREG, htonl(priv->sreg))) 100 + if (nft_dump_register(skb, NFTA_BITWISE_SREG, priv->sreg)) 98 101 goto nla_put_failure; 99 - if (nla_put_be32(skb, NFTA_BITWISE_DREG, htonl(priv->dreg))) 102 + if (nft_dump_register(skb, NFTA_BITWISE_DREG, priv->dreg)) 100 103 goto nla_put_failure; 101 104 if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(priv->len))) 102 105 goto nla_put_failure;
+16 -24
net/netfilter/nft_byteorder.c
··· 26 26 }; 27 27 28 28 static void nft_byteorder_eval(const struct nft_expr *expr, 29 - struct nft_data data[NFT_REG_MAX + 1], 29 + struct nft_regs *regs, 30 30 const struct nft_pktinfo *pkt) 31 31 { 32 32 const struct nft_byteorder *priv = nft_expr_priv(expr); 33 - struct nft_data *src = &data[priv->sreg], *dst = &data[priv->dreg]; 33 + u32 *src = &regs->data[priv->sreg]; 34 + u32 *dst = &regs->data[priv->dreg]; 34 35 union { u32 u32; u16 u16; } *s, *d; 35 36 unsigned int i; 36 37 37 - s = (void *)src->data; 38 - d = (void *)dst->data; 38 + s = (void *)src; 39 + d = (void *)dst; 39 40 40 41 switch (priv->size) { 41 42 case 4: ··· 88 87 tb[NFTA_BYTEORDER_OP] == NULL) 89 88 return -EINVAL; 90 89 91 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SREG])); 92 - err = nft_validate_input_register(priv->sreg); 93 - if (err < 0) 94 - return err; 95 - 96 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_DREG])); 97 - err = nft_validate_output_register(priv->dreg); 98 - if (err < 0) 99 - return err; 100 - err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 101 - if (err < 0) 102 - return err; 103 - 104 90 priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP])); 105 91 switch (priv->op) { 106 92 case NFT_BYTEORDER_NTOH: ··· 96 108 default: 97 109 return -EINVAL; 98 110 } 99 - 100 - priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN])); 101 - if (priv->len == 0 || priv->len > FIELD_SIZEOF(struct nft_data, data)) 102 - return -EINVAL; 103 111 104 112 priv->size = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_SIZE])); 105 113 switch (priv->size) { ··· 106 122 return -EINVAL; 107 123 } 108 124 109 - return 0; 125 + priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]); 126 + priv->len = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_LEN])); 127 + err = nft_validate_register_load(priv->sreg, priv->len); 128 + if (err < 0) 129 + return err; 130 + 131 + priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]); 132 + return nft_validate_register_store(ctx, priv->dreg, NULL, 133 + NFT_DATA_VALUE, priv->len); 110 134 } 111 135 112 136 static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr) 113 137 { 114 138 const struct nft_byteorder *priv = nft_expr_priv(expr); 115 139 116 - if (nla_put_be32(skb, NFTA_BYTEORDER_SREG, htonl(priv->sreg))) 140 + if (nft_dump_register(skb, NFTA_BYTEORDER_SREG, priv->sreg)) 117 141 goto nla_put_failure; 118 - if (nla_put_be32(skb, NFTA_BYTEORDER_DREG, htonl(priv->dreg))) 142 + if (nft_dump_register(skb, NFTA_BYTEORDER_DREG, priv->dreg)) 119 143 goto nla_put_failure; 120 144 if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op))) 121 145 goto nla_put_failure;
+24 -20
net/netfilter/nft_cmp.c
··· 25 25 }; 26 26 27 27 static void nft_cmp_eval(const struct nft_expr *expr, 28 - struct nft_data data[NFT_REG_MAX + 1], 28 + struct nft_regs *regs, 29 29 const struct nft_pktinfo *pkt) 30 30 { 31 31 const struct nft_cmp_expr *priv = nft_expr_priv(expr); 32 32 int d; 33 33 34 - d = nft_data_cmp(&data[priv->sreg], &priv->data, priv->len); 34 + d = memcmp(&regs->data[priv->sreg], &priv->data, priv->len); 35 35 switch (priv->op) { 36 36 case NFT_CMP_EQ: 37 37 if (d != 0) ··· 59 59 return; 60 60 61 61 mismatch: 62 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 62 + regs->verdict.code = NFT_BREAK; 63 63 } 64 64 65 65 static const struct nla_policy nft_cmp_policy[NFTA_CMP_MAX + 1] = { ··· 75 75 struct nft_data_desc desc; 76 76 int err; 77 77 78 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); 79 - priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); 80 - 81 - err = nft_data_init(NULL, &priv->data, &desc, tb[NFTA_CMP_DATA]); 78 + err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &desc, 79 + tb[NFTA_CMP_DATA]); 82 80 BUG_ON(err < 0); 83 81 82 + priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); 83 + err = nft_validate_register_load(priv->sreg, desc.len); 84 + if (err < 0) 85 + return err; 86 + 87 + priv->op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); 84 88 priv->len = desc.len; 85 89 return 0; 86 90 } ··· 93 89 { 94 90 const struct nft_cmp_expr *priv = nft_expr_priv(expr); 95 91 96 - if (nla_put_be32(skb, NFTA_CMP_SREG, htonl(priv->sreg))) 92 + if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) 97 93 goto nla_put_failure; 98 94 if (nla_put_be32(skb, NFTA_CMP_OP, htonl(priv->op))) 99 95 goto nla_put_failure; ··· 126 122 u32 mask; 127 123 int err; 128 124 129 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); 130 - 131 - err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); 125 + err = nft_data_init(NULL, &data, sizeof(data), &desc, 126 + tb[NFTA_CMP_DATA]); 132 127 BUG_ON(err < 0); 133 - desc.len *= BITS_PER_BYTE; 134 128 129 + priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]); 130 + err = nft_validate_register_load(priv->sreg, desc.len); 131 + if (err < 0) 132 + return err; 133 + 134 + desc.len *= BITS_PER_BYTE; 135 135 mask = nft_cmp_fast_mask(desc.len); 136 + 136 137 priv->data = data.data[0] & mask; 137 138 priv->len = desc.len; 138 139 return 0; ··· 148 139 const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); 149 140 struct nft_data data; 150 141 151 - if (nla_put_be32(skb, NFTA_CMP_SREG, htonl(priv->sreg))) 142 + if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg)) 152 143 goto nla_put_failure; 153 144 if (nla_put_be32(skb, NFTA_CMP_OP, htonl(NFT_CMP_EQ))) 154 145 goto nla_put_failure; ··· 176 167 { 177 168 struct nft_data_desc desc; 178 169 struct nft_data data; 179 - enum nft_registers sreg; 180 170 enum nft_cmp_ops op; 181 171 int err; 182 172 ··· 183 175 tb[NFTA_CMP_OP] == NULL || 184 176 tb[NFTA_CMP_DATA] == NULL) 185 177 return ERR_PTR(-EINVAL); 186 - 187 - sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG])); 188 - err = nft_validate_input_register(sreg); 189 - if (err < 0) 190 - return ERR_PTR(err); 191 178 192 179 op = ntohl(nla_get_be32(tb[NFTA_CMP_OP])); 193 180 switch (op) { ··· 197 194 return ERR_PTR(-EINVAL); 198 195 } 199 196 200 - err = nft_data_init(NULL, &data, &desc, tb[NFTA_CMP_DATA]); 197 + err = nft_data_init(NULL, &data, sizeof(data), &desc, 198 + tb[NFTA_CMP_DATA]); 201 199 if (err < 0) 202 200 return ERR_PTR(err); 203 201
+13 -13
net/netfilter/nft_compat.c
··· 55 55 } 56 56 57 57 static void nft_target_eval_xt(const struct nft_expr *expr, 58 - struct nft_data data[NFT_REG_MAX + 1], 58 + struct nft_regs *regs, 59 59 const struct nft_pktinfo *pkt) 60 60 { 61 61 void *info = nft_expr_priv(expr); ··· 72 72 73 73 switch (ret) { 74 74 case XT_CONTINUE: 75 - data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 75 + regs->verdict.code = NFT_CONTINUE; 76 76 break; 77 77 default: 78 - data[NFT_REG_VERDICT].verdict = ret; 78 + regs->verdict.code = ret; 79 79 break; 80 80 } 81 81 } 82 82 83 83 static void nft_target_eval_bridge(const struct nft_expr *expr, 84 - struct nft_data data[NFT_REG_MAX + 1], 84 + struct nft_regs *regs, 85 85 const struct nft_pktinfo *pkt) 86 86 { 87 87 void *info = nft_expr_priv(expr); ··· 98 98 99 99 switch (ret) { 100 100 case EBT_ACCEPT: 101 - data[NFT_REG_VERDICT].verdict = NF_ACCEPT; 101 + regs->verdict.code = NF_ACCEPT; 102 102 break; 103 103 case EBT_DROP: 104 - data[NFT_REG_VERDICT].verdict = NF_DROP; 104 + regs->verdict.code = NF_DROP; 105 105 break; 106 106 case EBT_CONTINUE: 107 - data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 107 + regs->verdict.code = NFT_CONTINUE; 108 108 break; 109 109 case EBT_RETURN: 110 - data[NFT_REG_VERDICT].verdict = NFT_RETURN; 110 + regs->verdict.code = NFT_RETURN; 111 111 break; 112 112 default: 113 - data[NFT_REG_VERDICT].verdict = ret; 113 + regs->verdict.code = ret; 114 114 break; 115 115 } 116 116 } ··· 304 304 } 305 305 306 306 static void nft_match_eval(const struct nft_expr *expr, 307 - struct nft_data data[NFT_REG_MAX + 1], 307 + struct nft_regs *regs, 308 308 const struct nft_pktinfo *pkt) 309 309 { 310 310 void *info = nft_expr_priv(expr); ··· 317 317 ret = match->match(skb, (struct xt_action_param *)&pkt->xt); 318 318 319 319 if (pkt->xt.hotdrop) { 320 - data[NFT_REG_VERDICT].verdict = NF_DROP; 320 + regs->verdict.code = NF_DROP; 321 321 return; 322 322 } 323 323 324 324 switch (ret ? 1 : 0) { 325 325 case 1: 326 - data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 326 + regs->verdict.code = NFT_CONTINUE; 327 327 break; 328 328 case 0: 329 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 329 + regs->verdict.code = NFT_BREAK; 330 330 break; 331 331 } 332 332 }
+2 -1
net/netfilter/nft_counter.c
··· 24 24 }; 25 25 26 26 static void nft_counter_eval(const struct nft_expr *expr, 27 - struct nft_data data[NFT_REG_MAX + 1], 27 + struct nft_regs *regs, 28 28 const struct nft_pktinfo *pkt) 29 29 { 30 30 struct nft_counter *priv = nft_expr_priv(expr); ··· 92 92 .ops = &nft_counter_ops, 93 93 .policy = nft_counter_policy, 94 94 .maxattr = NFTA_COUNTER_MAX, 95 + .flags = NFT_EXPR_STATEFUL, 95 96 .owner = THIS_MODULE, 96 97 }; 97 98
+71 -39
net/netfilter/nft_ct.c
··· 31 31 }; 32 32 33 33 static void nft_ct_get_eval(const struct nft_expr *expr, 34 - struct nft_data data[NFT_REG_MAX + 1], 34 + struct nft_regs *regs, 35 35 const struct nft_pktinfo *pkt) 36 36 { 37 37 const struct nft_ct *priv = nft_expr_priv(expr); 38 - struct nft_data *dest = &data[priv->dreg]; 38 + u32 *dest = &regs->data[priv->dreg]; 39 39 enum ip_conntrack_info ctinfo; 40 40 const struct nf_conn *ct; 41 41 const struct nf_conn_help *help; ··· 54 54 state = NF_CT_STATE_UNTRACKED_BIT; 55 55 else 56 56 state = NF_CT_STATE_BIT(ctinfo); 57 - dest->data[0] = state; 57 + *dest = state; 58 58 return; 59 59 default: 60 60 break; ··· 65 65 66 66 switch (priv->key) { 67 67 case NFT_CT_DIRECTION: 68 - dest->data[0] = CTINFO2DIR(ctinfo); 68 + *dest = CTINFO2DIR(ctinfo); 69 69 return; 70 70 case NFT_CT_STATUS: 71 - dest->data[0] = ct->status; 71 + *dest = ct->status; 72 72 return; 73 73 #ifdef CONFIG_NF_CONNTRACK_MARK 74 74 case NFT_CT_MARK: 75 - dest->data[0] = ct->mark; 75 + *dest = ct->mark; 76 76 return; 77 77 #endif 78 78 #ifdef CONFIG_NF_CONNTRACK_SECMARK 79 79 case NFT_CT_SECMARK: 80 - dest->data[0] = ct->secmark; 80 + *dest = ct->secmark; 81 81 return; 82 82 #endif 83 83 case NFT_CT_EXPIRATION: 84 84 diff = (long)jiffies - (long)ct->timeout.expires; 85 85 if (diff < 0) 86 86 diff = 0; 87 - dest->data[0] = jiffies_to_msecs(diff); 87 + *dest = jiffies_to_msecs(diff); 88 88 return; 89 89 case NFT_CT_HELPER: 90 90 if (ct->master == NULL) ··· 95 95 helper = rcu_dereference(help->helper); 96 96 if (helper == NULL) 97 97 goto err; 98 - if (strlen(helper->name) >= sizeof(dest->data)) 99 - goto err; 100 - strncpy((char *)dest->data, helper->name, sizeof(dest->data)); 98 + strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN); 101 99 return; 102 100 #ifdef CONFIG_NF_CONNTRACK_LABELS 103 101 case NFT_CT_LABELS: { ··· 103 105 unsigned int size; 104 106 105 107 if (!labels) { 106 - memset(dest->data, 0, sizeof(dest->data)); 108 + memset(dest, 0, NF_CT_LABELS_MAX_SIZE); 107 109 return; 108 110 } 109 111 110 - BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > sizeof(dest->data)); 111 112 size = labels->words * sizeof(long); 112 - 113 - memcpy(dest->data, labels->bits, size); 114 - if (size < sizeof(dest->data)) 115 - memset(((char *) dest->data) + size, 0, 116 - sizeof(dest->data) - size); 113 + memcpy(dest, labels->bits, size); 114 + if (size < NF_CT_LABELS_MAX_SIZE) 115 + memset(((char *) dest) + size, 0, 116 + NF_CT_LABELS_MAX_SIZE - size); 117 117 return; 118 118 } 119 119 #endif ··· 122 126 tuple = &ct->tuplehash[priv->dir].tuple; 123 127 switch (priv->key) { 124 128 case NFT_CT_L3PROTOCOL: 125 - dest->data[0] = nf_ct_l3num(ct); 129 + *dest = nf_ct_l3num(ct); 126 130 return; 127 131 case NFT_CT_SRC: 128 - memcpy(dest->data, tuple->src.u3.all, 132 + memcpy(dest, tuple->src.u3.all, 129 133 nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); 130 134 return; 131 135 case NFT_CT_DST: 132 - memcpy(dest->data, tuple->dst.u3.all, 136 + memcpy(dest, tuple->dst.u3.all, 133 137 nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16); 134 138 return; 135 139 case NFT_CT_PROTOCOL: 136 - dest->data[0] = nf_ct_protonum(ct); 140 + *dest = nf_ct_protonum(ct); 137 141 return; 138 142 case NFT_CT_PROTO_SRC: 139 - dest->data[0] = (__force __u16)tuple->src.u.all; 143 + *dest = (__force __u16)tuple->src.u.all; 140 144 return; 141 145 case NFT_CT_PROTO_DST: 142 - dest->data[0] = (__force __u16)tuple->dst.u.all; 146 + *dest = (__force __u16)tuple->dst.u.all; 143 147 return; 144 148 default: 145 149 break; 146 150 } 147 151 return; 148 152 err: 149 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 153 + regs->verdict.code = NFT_BREAK; 150 154 } 151 155 152 156 static void nft_ct_set_eval(const struct nft_expr *expr, 153 - struct nft_data data[NFT_REG_MAX + 1], 157 + struct nft_regs *regs, 154 158 const struct nft_pktinfo *pkt) 155 159 { 156 160 const struct nft_ct *priv = nft_expr_priv(expr); 157 161 struct sk_buff *skb = pkt->skb; 158 162 #ifdef CONFIG_NF_CONNTRACK_MARK 159 - u32 value = data[priv->sreg].data[0]; 163 + u32 value = regs->data[priv->sreg]; 160 164 #endif 161 165 enum ip_conntrack_info ctinfo; 162 166 struct nf_conn *ct; ··· 224 228 const struct nlattr * const tb[]) 225 229 { 226 230 struct nft_ct *priv = nft_expr_priv(expr); 231 + unsigned int len; 227 232 int err; 228 233 229 234 priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); 230 235 switch (priv->key) { 231 - case NFT_CT_STATE: 232 236 case NFT_CT_DIRECTION: 237 + if (tb[NFTA_CT_DIRECTION] != NULL) 238 + return -EINVAL; 239 + len = sizeof(u8); 240 + break; 241 + case NFT_CT_STATE: 233 242 case NFT_CT_STATUS: 234 243 #ifdef CONFIG_NF_CONNTRACK_MARK 235 244 case NFT_CT_MARK: ··· 242 241 #ifdef CONFIG_NF_CONNTRACK_SECMARK 243 242 case NFT_CT_SECMARK: 244 243 #endif 244 + case NFT_CT_EXPIRATION: 245 + if (tb[NFTA_CT_DIRECTION] != NULL) 246 + return -EINVAL; 247 + len = sizeof(u32); 248 + break; 245 249 #ifdef CONFIG_NF_CONNTRACK_LABELS 246 250 case NFT_CT_LABELS: 251 + if (tb[NFTA_CT_DIRECTION] != NULL) 252 + return -EINVAL; 253 + len = NF_CT_LABELS_MAX_SIZE; 254 + break; 247 255 #endif 248 - case NFT_CT_EXPIRATION: 249 256 case NFT_CT_HELPER: 250 257 if (tb[NFTA_CT_DIRECTION] != NULL) 251 258 return -EINVAL; 259 + len = NF_CT_HELPER_NAME_LEN; 252 260 break; 261 + 253 262 case NFT_CT_L3PROTOCOL: 254 263 case NFT_CT_PROTOCOL: 264 + if (tb[NFTA_CT_DIRECTION] == NULL) 265 + return -EINVAL; 266 + len = sizeof(u8); 267 + break; 255 268 case NFT_CT_SRC: 256 269 case NFT_CT_DST: 270 + if (tb[NFTA_CT_DIRECTION] == NULL) 271 + return -EINVAL; 272 + 273 + switch (ctx->afi->family) { 274 + case NFPROTO_IPV4: 275 + len = FIELD_SIZEOF(struct nf_conntrack_tuple, 276 + src.u3.ip); 277 + break; 278 + case NFPROTO_IPV6: 279 + case NFPROTO_INET: 280 + len = FIELD_SIZEOF(struct nf_conntrack_tuple, 281 + src.u3.ip6); 282 + break; 283 + default: 284 + return -EAFNOSUPPORT; 285 + } 286 + break; 257 287 case NFT_CT_PROTO_SRC: 258 288 case NFT_CT_PROTO_DST: 259 289 if (tb[NFTA_CT_DIRECTION] == NULL) 260 290 return -EINVAL; 291 + len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all); 261 292 break; 262 293 default: 263 294 return -EOPNOTSUPP; ··· 306 273 } 307 274 } 308 275 309 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG])); 310 - err = nft_validate_output_register(priv->dreg); 311 - if (err < 0) 312 - return err; 313 - 314 - err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 276 + priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]); 277 + err = nft_validate_register_store(ctx, priv->dreg, NULL, 278 + NFT_DATA_VALUE, len); 315 279 if (err < 0) 316 280 return err; 317 281 ··· 324 294 const struct nlattr * const tb[]) 325 295 { 326 296 struct nft_ct *priv = nft_expr_priv(expr); 297 + unsigned int len; 327 298 int err; 328 299 329 300 priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); 330 301 switch (priv->key) { 331 302 #ifdef CONFIG_NF_CONNTRACK_MARK 332 303 case NFT_CT_MARK: 304 + len = FIELD_SIZEOF(struct nf_conn, mark); 333 305 break; 334 306 #endif 335 307 default: 336 308 return -EOPNOTSUPP; 337 309 } 338 310 339 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_CT_SREG])); 340 - err = nft_validate_input_register(priv->sreg); 311 + priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]); 312 + err = nft_validate_register_load(priv->sreg, len); 341 313 if (err < 0) 342 314 return err; 343 315 ··· 360 328 { 361 329 const struct nft_ct *priv = nft_expr_priv(expr); 362 330 363 - if (nla_put_be32(skb, NFTA_CT_DREG, htonl(priv->dreg))) 331 + if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg)) 364 332 goto nla_put_failure; 365 333 if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) 366 334 goto nla_put_failure; ··· 387 355 { 388 356 const struct nft_ct *priv = nft_expr_priv(expr); 389 357 390 - if (nla_put_be32(skb, NFTA_CT_SREG, htonl(priv->sreg))) 358 + if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg)) 391 359 goto nla_put_failure; 392 360 if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key))) 393 361 goto nla_put_failure;
+63 -16
net/netfilter/nft_dynset.c
··· 23 23 enum nft_registers sreg_key:8; 24 24 enum nft_registers sreg_data:8; 25 25 u64 timeout; 26 + struct nft_expr *expr; 26 27 struct nft_set_binding binding; 27 28 }; 28 29 29 30 static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, 30 - struct nft_data data[NFT_REG_MAX + 1]) 31 + struct nft_regs *regs) 31 32 { 32 33 const struct nft_dynset *priv = nft_expr_priv(expr); 34 + struct nft_set_ext *ext; 33 35 u64 timeout; 34 36 void *elem; 35 37 ··· 40 38 41 39 timeout = priv->timeout ? : set->timeout; 42 40 elem = nft_set_elem_init(set, &priv->tmpl, 43 - &data[priv->sreg_key], &data[priv->sreg_data], 41 + &regs->data[priv->sreg_key], 42 + &regs->data[priv->sreg_data], 44 43 timeout, GFP_ATOMIC); 45 44 if (elem == NULL) { 46 45 if (set->size) 47 46 atomic_dec(&set->nelems); 47 + return NULL; 48 48 } 49 + 50 + ext = nft_set_elem_ext(set, elem); 51 + if (priv->expr != NULL) 52 + nft_expr_clone(nft_set_ext_expr(ext), priv->expr); 53 + 49 54 return elem; 50 55 } 51 56 52 57 static void nft_dynset_eval(const struct nft_expr *expr, 53 - struct nft_data data[NFT_REG_MAX + 1], 58 + struct nft_regs *regs, 54 59 const struct nft_pktinfo *pkt) 55 60 { 56 61 const struct nft_dynset *priv = nft_expr_priv(expr); 57 62 struct nft_set *set = priv->set; 58 63 const struct nft_set_ext *ext; 64 + const struct nft_expr *sexpr; 59 65 u64 timeout; 60 66 61 - if (set->ops->update(set, &data[priv->sreg_key], nft_dynset_new, 62 - expr, data, &ext)) { 67 + if (set->ops->update(set, &regs->data[priv->sreg_key], nft_dynset_new, 68 + expr, regs, &ext)) { 69 + sexpr = NULL; 70 + if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 71 + sexpr = nft_set_ext_expr(ext); 72 + 63 73 if (priv->op == NFT_DYNSET_OP_UPDATE && 64 74 nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) { 65 75 timeout = priv->timeout ? : set->timeout; 66 76 *nft_set_ext_expiration(ext) = jiffies + timeout; 67 - return; 68 - } 69 - } 77 + } else if (sexpr == NULL) 78 + goto out; 70 79 71 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 80 + if (sexpr != NULL) 81 + sexpr->ops->eval(sexpr, regs, pkt); 82 + return; 83 + } 84 + out: 85 + regs->verdict.code = NFT_BREAK; 72 86 } 73 87 74 88 static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = { ··· 94 76 [NFTA_DYNSET_SREG_KEY] = { .type = NLA_U32 }, 95 77 [NFTA_DYNSET_SREG_DATA] = { .type = NLA_U32 }, 96 78 [NFTA_DYNSET_TIMEOUT] = { .type = NLA_U64 }, 79 + [NFTA_DYNSET_EXPR] = { .type = NLA_NESTED }, 97 80 }; 98 81 99 82 static int nft_dynset_init(const struct nft_ctx *ctx, ··· 142 123 timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT])); 143 124 } 144 125 145 - priv->sreg_key = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_KEY])); 146 - err = nft_validate_input_register(priv->sreg_key); 126 + priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]); 127 + err = nft_validate_register_load(priv->sreg_key, set->klen);; 147 128 if (err < 0) 148 129 return err; 149 130 ··· 153 134 if (set->dtype == NFT_DATA_VERDICT) 154 135 return -EOPNOTSUPP; 155 136 156 - priv->sreg_data = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_DATA])); 157 - err = nft_validate_input_register(priv->sreg_data); 137 + priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]); 138 + err = nft_validate_register_load(priv->sreg_data, set->dlen); 158 139 if (err < 0) 159 140 return err; 160 141 } else if (set->flags & NFT_SET_MAP) 142 + return -EINVAL; 143 + 144 + if (tb[NFTA_DYNSET_EXPR] != NULL) { 145 + if (!(set->flags & NFT_SET_EVAL)) 146 + return -EINVAL; 147 + if (!(set->flags & NFT_SET_ANONYMOUS)) 148 + return -EOPNOTSUPP; 149 + 150 + priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]); 151 + if (IS_ERR(priv->expr)) 152 + return PTR_ERR(priv->expr); 153 + 154 + err = -EOPNOTSUPP; 155 + if (!(priv->expr->ops->type->flags & NFT_EXPR_STATEFUL)) 156 + goto err1; 157 + } else if (set->flags & NFT_SET_EVAL) 161 158 return -EINVAL; 162 159 163 160 nft_set_ext_prepare(&priv->tmpl); 164 161 nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen); 165 162 if (set->flags & NFT_SET_MAP) 166 163 nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_DATA, set->dlen); 164 + if (priv->expr != NULL) 165 + nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_EXPR, 166 + priv->expr->ops->size); 167 167 if (set->flags & NFT_SET_TIMEOUT) { 168 168 if (timeout || set->timeout) 169 169 nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION); ··· 192 154 193 155 err = nf_tables_bind_set(ctx, set, &priv->binding); 194 156 if (err < 0) 195 - return err; 157 + goto err1; 196 158 197 159 priv->set = set; 198 160 return 0; 161 + 162 + err1: 163 + if (priv->expr != NULL) 164 + nft_expr_destroy(ctx, priv->expr); 165 + return err; 199 166 } 200 167 201 168 static void nft_dynset_destroy(const struct nft_ctx *ctx, ··· 209 166 struct nft_dynset *priv = nft_expr_priv(expr); 210 167 211 168 nf_tables_unbind_set(ctx, priv->set, &priv->binding); 169 + if (priv->expr != NULL) 170 + nft_expr_destroy(ctx, priv->expr); 212 171 } 213 172 214 173 static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr) 215 174 { 216 175 const struct nft_dynset *priv = nft_expr_priv(expr); 217 176 218 - if (nla_put_be32(skb, NFTA_DYNSET_SREG_KEY, htonl(priv->sreg_key))) 177 + if (nft_dump_register(skb, NFTA_DYNSET_SREG_KEY, priv->sreg_key)) 219 178 goto nla_put_failure; 220 179 if (priv->set->flags & NFT_SET_MAP && 221 - nla_put_be32(skb, NFTA_DYNSET_SREG_DATA, htonl(priv->sreg_data))) 180 + nft_dump_register(skb, NFTA_DYNSET_SREG_DATA, priv->sreg_data)) 222 181 goto nla_put_failure; 223 182 if (nla_put_be32(skb, NFTA_DYNSET_OP, htonl(priv->op))) 224 183 goto nla_put_failure; 225 184 if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name)) 226 185 goto nla_put_failure; 227 186 if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout))) 187 + goto nla_put_failure; 188 + if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr)) 228 189 goto nla_put_failure; 229 190 return 0; 230 191
-94
net/netfilter/nft_expr_template.c
··· 1 - /* 2 - * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - * 8 - * Development of this code funded by Astaro AG (http://www.astaro.com/) 9 - */ 10 - 11 - #include <linux/kernel.h> 12 - #include <linux/init.h> 13 - #include <linux/netlink.h> 14 - #include <linux/netfilter.h> 15 - #include <linux/netfilter/nf_tables.h> 16 - #include <net/netfilter/nf_tables.h> 17 - 18 - struct nft_template { 19 - 20 - }; 21 - 22 - static void nft_template_eval(const struct nft_expr *expr, 23 - struct nft_data data[NFT_REG_MAX + 1], 24 - const struct nft_pktinfo *pkt) 25 - { 26 - struct nft_template *priv = nft_expr_priv(expr); 27 - 28 - } 29 - 30 - static const struct nla_policy nft_template_policy[NFTA_TEMPLATE_MAX + 1] = { 31 - [NFTA_TEMPLATE_ATTR] = { .type = NLA_U32 }, 32 - }; 33 - 34 - static int nft_template_init(const struct nft_ctx *ctx, 35 - const struct nft_expr *expr, 36 - const struct nlattr * const tb[]) 37 - { 38 - struct nft_template *priv = nft_expr_priv(expr); 39 - 40 - return 0; 41 - } 42 - 43 - static void nft_template_destroy(const struct nft_ctx *ctx, 44 - const struct nft_expr *expr) 45 - { 46 - struct nft_template *priv = nft_expr_priv(expr); 47 - 48 - } 49 - 50 - static int nft_template_dump(struct sk_buff *skb, const struct nft_expr *expr) 51 - { 52 - const struct nft_template *priv = nft_expr_priv(expr); 53 - 54 - NLA_PUT_BE32(skb, NFTA_TEMPLATE_ATTR, priv->field); 55 - return 0; 56 - 57 - nla_put_failure: 58 - return -1; 59 - } 60 - 61 - static struct nft_expr_type nft_template_type; 62 - static const struct nft_expr_ops nft_template_ops = { 63 - .type = &nft_template_type, 64 - .size = NFT_EXPR_SIZE(sizeof(struct nft_template)), 65 - .eval = nft_template_eval, 66 - .init = nft_template_init, 67 - .destroy = nft_template_destroy, 68 - .dump = nft_template_dump, 69 - }; 70 - 71 - static struct nft_expr_type nft_template_type __read_mostly = { 72 - .name = "template", 73 - .ops = &nft_template_ops, 74 - .policy = nft_template_policy, 75 - .maxattr = NFTA_TEMPLATE_MAX, 76 - .owner = THIS_MODULE, 77 - }; 78 - 79 - static int __init nft_template_module_init(void) 80 - { 81 - return nft_register_expr(&nft_template_type); 82 - } 83 - 84 - static void __exit nft_template_module_exit(void) 85 - { 86 - nft_unregister_expr(&nft_template_type); 87 - } 88 - 89 - module_init(nft_template_module_init); 90 - module_exit(nft_template_module_exit); 91 - 92 - MODULE_LICENSE("GPL"); 93 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 94 - MODULE_ALIAS_NFT_EXPR("template");
+9 -14
net/netfilter/nft_exthdr.c
··· 26 26 }; 27 27 28 28 static void nft_exthdr_eval(const struct nft_expr *expr, 29 - struct nft_data data[NFT_REG_MAX + 1], 29 + struct nft_regs *regs, 30 30 const struct nft_pktinfo *pkt) 31 31 { 32 32 struct nft_exthdr *priv = nft_expr_priv(expr); 33 - struct nft_data *dest = &data[priv->dreg]; 33 + u32 *dest = &regs->data[priv->dreg]; 34 34 unsigned int offset = 0; 35 35 int err; 36 36 ··· 39 39 goto err; 40 40 offset += priv->offset; 41 41 42 - if (skb_copy_bits(pkt->skb, offset, dest->data, priv->len) < 0) 42 + dest[priv->len / NFT_REG32_SIZE] = 0; 43 + if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0) 43 44 goto err; 44 45 return; 45 46 err: 46 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 47 + regs->verdict.code = NFT_BREAK; 47 48 } 48 49 49 50 static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = { ··· 59 58 const struct nlattr * const tb[]) 60 59 { 61 60 struct nft_exthdr *priv = nft_expr_priv(expr); 62 - int err; 63 61 64 62 if (tb[NFTA_EXTHDR_DREG] == NULL || 65 63 tb[NFTA_EXTHDR_TYPE] == NULL || ··· 69 69 priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]); 70 70 priv->offset = ntohl(nla_get_be32(tb[NFTA_EXTHDR_OFFSET])); 71 71 priv->len = ntohl(nla_get_be32(tb[NFTA_EXTHDR_LEN])); 72 - if (priv->len == 0 || 73 - priv->len > FIELD_SIZEOF(struct nft_data, data)) 74 - return -EINVAL; 72 + priv->dreg = nft_parse_register(tb[NFTA_EXTHDR_DREG]); 75 73 76 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_EXTHDR_DREG])); 77 - err = nft_validate_output_register(priv->dreg); 78 - if (err < 0) 79 - return err; 80 - return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 74 + return nft_validate_register_store(ctx, priv->dreg, NULL, 75 + NFT_DATA_VALUE, priv->len); 81 76 } 82 77 83 78 static int nft_exthdr_dump(struct sk_buff *skb, const struct nft_expr *expr) 84 79 { 85 80 const struct nft_exthdr *priv = nft_expr_priv(expr); 86 81 87 - if (nla_put_be32(skb, NFTA_EXTHDR_DREG, htonl(priv->dreg))) 82 + if (nft_dump_register(skb, NFTA_EXTHDR_DREG, priv->dreg)) 88 83 goto nla_put_failure; 89 84 if (nla_put_u8(skb, NFTA_EXTHDR_TYPE, priv->type)) 90 85 goto nla_put_failure;
+9 -10
net/netfilter/nft_hash.c
··· 36 36 37 37 struct nft_hash_cmp_arg { 38 38 const struct nft_set *set; 39 - const struct nft_data *key; 39 + const u32 *key; 40 40 u8 genmask; 41 41 }; 42 42 ··· 62 62 const struct nft_hash_cmp_arg *x = arg->key; 63 63 const struct nft_hash_elem *he = ptr; 64 64 65 - if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) 65 + if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) 66 66 return 1; 67 67 if (nft_set_elem_expired(&he->ext)) 68 68 return 1; ··· 71 71 return 0; 72 72 } 73 73 74 - static bool nft_hash_lookup(const struct nft_set *set, 75 - const struct nft_data *key, 74 + static bool nft_hash_lookup(const struct nft_set *set, const u32 *key, 76 75 const struct nft_set_ext **ext) 77 76 { 78 77 struct nft_hash *priv = nft_set_priv(set); ··· 89 90 return !!he; 90 91 } 91 92 92 - static bool nft_hash_update(struct nft_set *set, const struct nft_data *key, 93 + static bool nft_hash_update(struct nft_set *set, const u32 *key, 93 94 void *(*new)(struct nft_set *, 94 95 const struct nft_expr *, 95 - struct nft_data []), 96 + struct nft_regs *regs), 96 97 const struct nft_expr *expr, 97 - struct nft_data data[], 98 + struct nft_regs *regs, 98 99 const struct nft_set_ext **ext) 99 100 { 100 101 struct nft_hash *priv = nft_set_priv(set); ··· 109 110 if (he != NULL) 110 111 goto out; 111 112 112 - he = new(set, expr, data); 113 + he = new(set, expr, regs); 113 114 if (he == NULL) 114 115 goto err1; 115 116 if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, ··· 133 134 struct nft_hash_cmp_arg arg = { 134 135 .genmask = nft_genmask_next(read_pnet(&set->pnet)), 135 136 .set = set, 136 - .key = &elem->key, 137 + .key = elem->key.val.data, 137 138 }; 138 139 139 140 return rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, ··· 157 158 struct nft_hash_cmp_arg arg = { 158 159 .genmask = nft_genmask_next(read_pnet(&set->pnet)), 159 160 .set = set, 160 - .key = &elem->key, 161 + .key = elem->key.val.data, 161 162 }; 162 163 163 164 rcu_read_lock();
+8 -10
net/netfilter/nft_immediate.c
··· 24 24 }; 25 25 26 26 static void nft_immediate_eval(const struct nft_expr *expr, 27 - struct nft_data data[NFT_REG_MAX + 1], 27 + struct nft_regs *regs, 28 28 const struct nft_pktinfo *pkt) 29 29 { 30 30 const struct nft_immediate_expr *priv = nft_expr_priv(expr); 31 31 32 - nft_data_copy(&data[priv->dreg], &priv->data); 32 + nft_data_copy(&regs->data[priv->dreg], &priv->data, priv->dlen); 33 33 } 34 34 35 35 static const struct nla_policy nft_immediate_policy[NFTA_IMMEDIATE_MAX + 1] = { ··· 49 49 tb[NFTA_IMMEDIATE_DATA] == NULL) 50 50 return -EINVAL; 51 51 52 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_IMMEDIATE_DREG])); 53 - err = nft_validate_output_register(priv->dreg); 54 - if (err < 0) 55 - return err; 56 - 57 - err = nft_data_init(ctx, &priv->data, &desc, tb[NFTA_IMMEDIATE_DATA]); 52 + err = nft_data_init(ctx, &priv->data, sizeof(priv->data), &desc, 53 + tb[NFTA_IMMEDIATE_DATA]); 58 54 if (err < 0) 59 55 return err; 60 56 priv->dlen = desc.len; 61 57 62 - err = nft_validate_data_load(ctx, priv->dreg, &priv->data, desc.type); 58 + priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]); 59 + err = nft_validate_register_store(ctx, priv->dreg, &priv->data, 60 + desc.type, desc.len); 63 61 if (err < 0) 64 62 goto err1; 65 63 ··· 79 81 { 80 82 const struct nft_immediate_expr *priv = nft_expr_priv(expr); 81 83 82 - if (nla_put_be32(skb, NFTA_IMMEDIATE_DREG, htonl(priv->dreg))) 84 + if (nft_dump_register(skb, NFTA_IMMEDIATE_DREG, priv->dreg)) 83 85 goto nla_put_failure; 84 86 85 87 return nft_data_dump(skb, NFTA_IMMEDIATE_DATA, &priv->data,
+3 -2
net/netfilter/nft_limit.c
··· 27 27 }; 28 28 29 29 static void nft_limit_eval(const struct nft_expr *expr, 30 - struct nft_data data[NFT_REG_MAX + 1], 30 + struct nft_regs *regs, 31 31 const struct nft_pktinfo *pkt) 32 32 { 33 33 struct nft_limit *priv = nft_expr_priv(expr); ··· 45 45 } 46 46 spin_unlock_bh(&limit_lock); 47 47 48 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 48 + regs->verdict.code = NFT_BREAK; 49 49 } 50 50 51 51 static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = { ··· 98 98 .ops = &nft_limit_ops, 99 99 .policy = nft_limit_policy, 100 100 .maxattr = NFTA_LIMIT_MAX, 101 + .flags = NFT_EXPR_STATEFUL, 101 102 .owner = THIS_MODULE, 102 103 }; 103 104
+1 -1
net/netfilter/nft_log.c
··· 27 27 }; 28 28 29 29 static void nft_log_eval(const struct nft_expr *expr, 30 - struct nft_data data[NFT_REG_MAX + 1], 30 + struct nft_regs *regs, 31 31 const struct nft_pktinfo *pkt) 32 32 { 33 33 const struct nft_log *priv = nft_expr_priv(expr);
+15 -16
net/netfilter/nft_lookup.c
··· 26 26 }; 27 27 28 28 static void nft_lookup_eval(const struct nft_expr *expr, 29 - struct nft_data data[NFT_REG_MAX + 1], 29 + struct nft_regs *regs, 30 30 const struct nft_pktinfo *pkt) 31 31 { 32 32 const struct nft_lookup *priv = nft_expr_priv(expr); 33 33 const struct nft_set *set = priv->set; 34 34 const struct nft_set_ext *ext; 35 35 36 - if (set->ops->lookup(set, &data[priv->sreg], &ext)) { 36 + if (set->ops->lookup(set, &regs->data[priv->sreg], &ext)) { 37 37 if (set->flags & NFT_SET_MAP) 38 - nft_data_copy(&data[priv->dreg], nft_set_ext_data(ext)); 38 + nft_data_copy(&regs->data[priv->dreg], 39 + nft_set_ext_data(ext), set->dlen); 39 40 return; 40 41 } 41 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 42 + regs->verdict.code = NFT_BREAK; 42 43 } 43 44 44 45 static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { ··· 71 70 return PTR_ERR(set); 72 71 } 73 72 74 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_SREG])); 75 - err = nft_validate_input_register(priv->sreg); 73 + if (set->flags & NFT_SET_EVAL) 74 + return -EOPNOTSUPP; 75 + 76 + priv->sreg = nft_parse_register(tb[NFTA_LOOKUP_SREG]); 77 + err = nft_validate_register_load(priv->sreg, set->klen); 76 78 if (err < 0) 77 79 return err; 78 80 ··· 83 79 if (!(set->flags & NFT_SET_MAP)) 84 80 return -EINVAL; 85 81 86 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_LOOKUP_DREG])); 87 - err = nft_validate_output_register(priv->dreg); 82 + priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]); 83 + err = nft_validate_register_store(ctx, priv->dreg, NULL, 84 + set->dtype, set->dlen); 88 85 if (err < 0) 89 86 return err; 90 - 91 - if (priv->dreg == NFT_REG_VERDICT) { 92 - if (set->dtype != NFT_DATA_VERDICT) 93 - return -EINVAL; 94 - } else if (set->dtype == NFT_DATA_VERDICT) 95 - return -EINVAL; 96 87 } else if (set->flags & NFT_SET_MAP) 97 88 return -EINVAL; 98 89 ··· 115 116 116 117 if (nla_put_string(skb, NFTA_LOOKUP_SET, priv->set->name)) 117 118 goto nla_put_failure; 118 - if (nla_put_be32(skb, NFTA_LOOKUP_SREG, htonl(priv->sreg))) 119 + if (nft_dump_register(skb, NFTA_LOOKUP_SREG, priv->sreg)) 119 120 goto nla_put_failure; 120 121 if (priv->set->flags & NFT_SET_MAP) 121 - if (nla_put_be32(skb, NFTA_LOOKUP_DREG, htonl(priv->dreg))) 122 + if (nft_dump_register(skb, NFTA_LOOKUP_DREG, priv->dreg)) 122 123 goto nla_put_failure; 123 124 return 0; 124 125
+55 -52
net/netfilter/nft_meta.c
··· 25 25 #include <net/netfilter/nft_meta.h> 26 26 27 27 void nft_meta_get_eval(const struct nft_expr *expr, 28 - struct nft_data data[NFT_REG_MAX + 1], 28 + struct nft_regs *regs, 29 29 const struct nft_pktinfo *pkt) 30 30 { 31 31 const struct nft_meta *priv = nft_expr_priv(expr); 32 32 const struct sk_buff *skb = pkt->skb; 33 33 const struct net_device *in = pkt->in, *out = pkt->out; 34 - struct nft_data *dest = &data[priv->dreg]; 34 + u32 *dest = &regs->data[priv->dreg]; 35 35 36 36 switch (priv->key) { 37 37 case NFT_META_LEN: 38 - dest->data[0] = skb->len; 38 + *dest = skb->len; 39 39 break; 40 40 case NFT_META_PROTOCOL: 41 - *(__be16 *)dest->data = skb->protocol; 41 + *dest = 0; 42 + *(__be16 *)dest = skb->protocol; 42 43 break; 43 44 case NFT_META_NFPROTO: 44 - dest->data[0] = pkt->ops->pf; 45 + *dest = pkt->ops->pf; 45 46 break; 46 47 case NFT_META_L4PROTO: 47 - dest->data[0] = pkt->tprot; 48 + *dest = pkt->tprot; 48 49 break; 49 50 case NFT_META_PRIORITY: 50 - dest->data[0] = skb->priority; 51 + *dest = skb->priority; 51 52 break; 52 53 case NFT_META_MARK: 53 - dest->data[0] = skb->mark; 54 + *dest = skb->mark; 54 55 break; 55 56 case NFT_META_IIF: 56 57 if (in == NULL) 57 58 goto err; 58 - dest->data[0] = in->ifindex; 59 + *dest = in->ifindex; 59 60 break; 60 61 case NFT_META_OIF: 61 62 if (out == NULL) 62 63 goto err; 63 - dest->data[0] = out->ifindex; 64 + *dest = out->ifindex; 64 65 break; 65 66 case NFT_META_IIFNAME: 66 67 if (in == NULL) 67 68 goto err; 68 - strncpy((char *)dest->data, in->name, sizeof(dest->data)); 69 + strncpy((char *)dest, in->name, IFNAMSIZ); 69 70 break; 70 71 case NFT_META_OIFNAME: 71 72 if (out == NULL) 72 73 goto err; 73 - strncpy((char *)dest->data, out->name, sizeof(dest->data)); 74 + strncpy((char *)dest, out->name, IFNAMSIZ); 74 75 break; 75 76 case NFT_META_IIFTYPE: 76 77 if (in == NULL) 77 78 goto err; 78 - *(u16 *)dest->data = in->type; 79 + *dest = 0; 80 + *(u16 *)dest = in->type; 79 81 break; 80 82 case NFT_META_OIFTYPE: 81 83 if (out == NULL) 82 84 goto err; 83 - *(u16 *)dest->data = out->type; 85 + *dest = 0; 86 + *(u16 *)dest = out->type; 84 87 break; 85 88 case NFT_META_SKUID: 86 89 if (skb->sk == NULL || !sk_fullsock(skb->sk)) ··· 96 93 goto err; 97 94 } 98 95 99 - dest->data[0] = 100 - from_kuid_munged(&init_user_ns, 96 + *dest = from_kuid_munged(&init_user_ns, 101 97 skb->sk->sk_socket->file->f_cred->fsuid); 102 98 read_unlock_bh(&skb->sk->sk_callback_lock); 103 99 break; ··· 110 108 read_unlock_bh(&skb->sk->sk_callback_lock); 111 109 goto err; 112 110 } 113 - dest->data[0] = 114 - from_kgid_munged(&init_user_ns, 111 + *dest = from_kgid_munged(&init_user_ns, 115 112 skb->sk->sk_socket->file->f_cred->fsgid); 116 113 read_unlock_bh(&skb->sk->sk_callback_lock); 117 114 break; ··· 120 119 121 120 if (dst == NULL) 122 121 goto err; 123 - dest->data[0] = dst->tclassid; 122 + *dest = dst->tclassid; 124 123 break; 125 124 } 126 125 #endif 127 126 #ifdef CONFIG_NETWORK_SECMARK 128 127 case NFT_META_SECMARK: 129 - dest->data[0] = skb->secmark; 128 + *dest = skb->secmark; 130 129 break; 131 130 #endif 132 131 case NFT_META_PKTTYPE: 133 132 if (skb->pkt_type != PACKET_LOOPBACK) { 134 - dest->data[0] = skb->pkt_type; 133 + *dest = skb->pkt_type; 135 134 break; 136 135 } 137 136 138 137 switch (pkt->ops->pf) { 139 138 case NFPROTO_IPV4: 140 139 if (ipv4_is_multicast(ip_hdr(skb)->daddr)) 141 - dest->data[0] = PACKET_MULTICAST; 140 + *dest = PACKET_MULTICAST; 142 141 else 143 - dest->data[0] = PACKET_BROADCAST; 142 + *dest = PACKET_BROADCAST; 144 143 break; 145 144 case NFPROTO_IPV6: 146 145 if (ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF) 147 - dest->data[0] = PACKET_MULTICAST; 146 + *dest = PACKET_MULTICAST; 148 147 else 149 - dest->data[0] = PACKET_BROADCAST; 148 + *dest = PACKET_BROADCAST; 150 149 break; 151 150 default: 152 151 WARN_ON(1); ··· 154 153 } 155 154 break; 156 155 case NFT_META_CPU: 157 - dest->data[0] = raw_smp_processor_id(); 156 + *dest = raw_smp_processor_id(); 158 157 break; 159 158 case NFT_META_IIFGROUP: 160 159 if (in == NULL) 161 160 goto err; 162 - dest->data[0] = in->group; 161 + *dest = in->group; 163 162 break; 164 163 case NFT_META_OIFGROUP: 165 164 if (out == NULL) 166 165 goto err; 167 - dest->data[0] = out->group; 166 + *dest = out->group; 168 167 break; 169 168 case NFT_META_CGROUP: 170 169 if (skb->sk == NULL || !sk_fullsock(skb->sk)) 171 170 goto err; 172 - dest->data[0] = skb->sk->sk_classid; 171 + *dest = skb->sk->sk_classid; 173 172 break; 174 173 default: 175 174 WARN_ON(1); ··· 178 177 return; 179 178 180 179 err: 181 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 180 + regs->verdict.code = NFT_BREAK; 182 181 } 183 182 EXPORT_SYMBOL_GPL(nft_meta_get_eval); 184 183 185 184 void nft_meta_set_eval(const struct nft_expr *expr, 186 - struct nft_data data[NFT_REG_MAX + 1], 185 + struct nft_regs *regs, 187 186 const struct nft_pktinfo *pkt) 188 187 { 189 188 const struct nft_meta *meta = nft_expr_priv(expr); 190 189 struct sk_buff *skb = pkt->skb; 191 - u32 value = data[meta->sreg].data[0]; 190 + u32 value = regs->data[meta->sreg]; 192 191 193 192 switch (meta->key) { 194 193 case NFT_META_MARK: ··· 218 217 const struct nlattr * const tb[]) 219 218 { 220 219 struct nft_meta *priv = nft_expr_priv(expr); 221 - int err; 220 + unsigned int len; 222 221 223 222 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 224 223 switch (priv->key) { 225 - case NFT_META_LEN: 226 224 case NFT_META_PROTOCOL: 225 + case NFT_META_IIFTYPE: 226 + case NFT_META_OIFTYPE: 227 + len = sizeof(u16); 228 + break; 227 229 case NFT_META_NFPROTO: 228 230 case NFT_META_L4PROTO: 231 + case NFT_META_LEN: 229 232 case NFT_META_PRIORITY: 230 233 case NFT_META_MARK: 231 234 case NFT_META_IIF: 232 235 case NFT_META_OIF: 233 - case NFT_META_IIFNAME: 234 - case NFT_META_OIFNAME: 235 - case NFT_META_IIFTYPE: 236 - case NFT_META_OIFTYPE: 237 236 case NFT_META_SKUID: 238 237 case NFT_META_SKGID: 239 238 #ifdef CONFIG_IP_ROUTE_CLASSID ··· 247 246 case NFT_META_IIFGROUP: 248 247 case NFT_META_OIFGROUP: 249 248 case NFT_META_CGROUP: 249 + len = sizeof(u32); 250 + break; 251 + case NFT_META_IIFNAME: 252 + case NFT_META_OIFNAME: 253 + len = IFNAMSIZ; 250 254 break; 251 255 default: 252 256 return -EOPNOTSUPP; 253 257 } 254 258 255 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_META_DREG])); 256 - err = nft_validate_output_register(priv->dreg); 257 - if (err < 0) 258 - return err; 259 - 260 - err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 261 - if (err < 0) 262 - return err; 263 - 264 - return 0; 259 + priv->dreg = nft_parse_register(tb[NFTA_META_DREG]); 260 + return nft_validate_register_store(ctx, priv->dreg, NULL, 261 + NFT_DATA_VALUE, len); 265 262 } 266 263 EXPORT_SYMBOL_GPL(nft_meta_get_init); 267 264 ··· 268 269 const struct nlattr * const tb[]) 269 270 { 270 271 struct nft_meta *priv = nft_expr_priv(expr); 272 + unsigned int len; 271 273 int err; 272 274 273 275 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); 274 276 switch (priv->key) { 275 277 case NFT_META_MARK: 276 278 case NFT_META_PRIORITY: 279 + len = sizeof(u32); 280 + break; 277 281 case NFT_META_NFTRACE: 282 + len = sizeof(u8); 278 283 break; 279 284 default: 280 285 return -EOPNOTSUPP; 281 286 } 282 287 283 - priv->sreg = ntohl(nla_get_be32(tb[NFTA_META_SREG])); 284 - err = nft_validate_input_register(priv->sreg); 288 + priv->sreg = nft_parse_register(tb[NFTA_META_SREG]); 289 + err = nft_validate_register_load(priv->sreg, len); 285 290 if (err < 0) 286 291 return err; 287 292 ··· 300 297 301 298 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) 302 299 goto nla_put_failure; 303 - if (nla_put_be32(skb, NFTA_META_DREG, htonl(priv->dreg))) 300 + if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg)) 304 301 goto nla_put_failure; 305 302 return 0; 306 303 ··· 316 313 317 314 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key))) 318 315 goto nla_put_failure; 319 - if (nla_put_be32(skb, NFTA_META_SREG, htonl(priv->sreg))) 316 + if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg)) 320 317 goto nla_put_failure; 321 318 322 319 return 0;
+41 -30
net/netfilter/nft_nat.c
··· 37 37 }; 38 38 39 39 static void nft_nat_eval(const struct nft_expr *expr, 40 - struct nft_data data[NFT_REG_MAX + 1], 40 + struct nft_regs *regs, 41 41 const struct nft_pktinfo *pkt) 42 42 { 43 43 const struct nft_nat *priv = nft_expr_priv(expr); ··· 49 49 if (priv->sreg_addr_min) { 50 50 if (priv->family == AF_INET) { 51 51 range.min_addr.ip = (__force __be32) 52 - data[priv->sreg_addr_min].data[0]; 52 + regs->data[priv->sreg_addr_min]; 53 53 range.max_addr.ip = (__force __be32) 54 - data[priv->sreg_addr_max].data[0]; 54 + regs->data[priv->sreg_addr_max]; 55 55 56 56 } else { 57 57 memcpy(range.min_addr.ip6, 58 - data[priv->sreg_addr_min].data, 59 - sizeof(struct nft_data)); 58 + &regs->data[priv->sreg_addr_min], 59 + sizeof(range.min_addr.ip6)); 60 60 memcpy(range.max_addr.ip6, 61 - data[priv->sreg_addr_max].data, 62 - sizeof(struct nft_data)); 61 + &regs->data[priv->sreg_addr_max], 62 + sizeof(range.max_addr.ip6)); 63 63 } 64 64 range.flags |= NF_NAT_RANGE_MAP_IPS; 65 65 } 66 66 67 67 if (priv->sreg_proto_min) { 68 68 range.min_proto.all = 69 - *(__be16 *)&data[priv->sreg_proto_min].data[0]; 69 + *(__be16 *)&regs->data[priv->sreg_proto_min]; 70 70 range.max_proto.all = 71 - *(__be16 *)&data[priv->sreg_proto_max].data[0]; 71 + *(__be16 *)&regs->data[priv->sreg_proto_max]; 72 72 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 73 73 } 74 74 75 75 range.flags |= priv->flags; 76 76 77 - data[NFT_REG_VERDICT].verdict = 78 - nf_nat_setup_info(ct, &range, priv->type); 77 + regs->verdict.code = nf_nat_setup_info(ct, &range, priv->type); 79 78 } 80 79 81 80 static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = { ··· 118 119 const struct nlattr * const tb[]) 119 120 { 120 121 struct nft_nat *priv = nft_expr_priv(expr); 122 + unsigned int alen, plen; 121 123 u32 family; 122 124 int err; 123 125 ··· 146 146 return -EINVAL; 147 147 148 148 family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); 149 - if (family != AF_INET && family != AF_INET6) 150 - return -EAFNOSUPPORT; 151 149 if (family != ctx->afi->family) 152 150 return -EOPNOTSUPP; 151 + 152 + switch (family) { 153 + case NFPROTO_IPV4: 154 + alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip); 155 + break; 156 + case NFPROTO_IPV6: 157 + alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip6); 158 + break; 159 + default: 160 + return -EAFNOSUPPORT; 161 + } 153 162 priv->family = family; 154 163 155 164 if (tb[NFTA_NAT_REG_ADDR_MIN]) { 156 165 priv->sreg_addr_min = 157 - ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN])); 158 - 159 - err = nft_validate_input_register(priv->sreg_addr_min); 166 + nft_parse_register(tb[NFTA_NAT_REG_ADDR_MIN]); 167 + err = nft_validate_register_load(priv->sreg_addr_min, alen); 160 168 if (err < 0) 161 169 return err; 162 170 163 171 if (tb[NFTA_NAT_REG_ADDR_MAX]) { 164 172 priv->sreg_addr_max = 165 - ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX])); 173 + nft_parse_register(tb[NFTA_NAT_REG_ADDR_MAX]); 166 174 167 - err = nft_validate_input_register(priv->sreg_addr_max); 175 + err = nft_validate_register_load(priv->sreg_addr_max, 176 + alen); 168 177 if (err < 0) 169 178 return err; 170 179 } else { ··· 181 172 } 182 173 } 183 174 175 + plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); 184 176 if (tb[NFTA_NAT_REG_PROTO_MIN]) { 185 177 priv->sreg_proto_min = 186 - ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN])); 178 + nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]); 187 179 188 - err = nft_validate_input_register(priv->sreg_proto_min); 180 + err = nft_validate_register_load(priv->sreg_proto_min, plen); 189 181 if (err < 0) 190 182 return err; 191 183 192 184 if (tb[NFTA_NAT_REG_PROTO_MAX]) { 193 185 priv->sreg_proto_max = 194 - ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX])); 186 + nft_parse_register(tb[NFTA_NAT_REG_PROTO_MAX]); 195 187 196 - err = nft_validate_input_register(priv->sreg_proto_max); 188 + err = nft_validate_register_load(priv->sreg_proto_max, 189 + plen); 197 190 if (err < 0) 198 191 return err; 199 192 } else { ··· 231 220 goto nla_put_failure; 232 221 233 222 if (priv->sreg_addr_min) { 234 - if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN, 235 - htonl(priv->sreg_addr_min)) || 236 - nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX, 237 - htonl(priv->sreg_addr_max))) 223 + if (nft_dump_register(skb, NFTA_NAT_REG_ADDR_MIN, 224 + priv->sreg_addr_min) || 225 + nft_dump_register(skb, NFTA_NAT_REG_ADDR_MAX, 226 + priv->sreg_addr_max)) 238 227 goto nla_put_failure; 239 228 } 240 229 241 230 if (priv->sreg_proto_min) { 242 - if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN, 243 - htonl(priv->sreg_proto_min)) || 244 - nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX, 245 - htonl(priv->sreg_proto_max))) 231 + if (nft_dump_register(skb, NFTA_NAT_REG_PROTO_MIN, 232 + priv->sreg_proto_min) || 233 + nft_dump_register(skb, NFTA_NAT_REG_PROTO_MAX, 234 + priv->sreg_proto_max)) 246 235 goto nla_put_failure; 247 236 } 248 237
+10 -14
net/netfilter/nft_payload.c
··· 18 18 #include <net/netfilter/nf_tables.h> 19 19 20 20 static void nft_payload_eval(const struct nft_expr *expr, 21 - struct nft_data data[NFT_REG_MAX + 1], 21 + struct nft_regs *regs, 22 22 const struct nft_pktinfo *pkt) 23 23 { 24 24 const struct nft_payload *priv = nft_expr_priv(expr); 25 25 const struct sk_buff *skb = pkt->skb; 26 - struct nft_data *dest = &data[priv->dreg]; 26 + u32 *dest = &regs->data[priv->dreg]; 27 27 int offset; 28 28 29 29 switch (priv->base) { ··· 43 43 } 44 44 offset += priv->offset; 45 45 46 - if (skb_copy_bits(skb, offset, dest->data, priv->len) < 0) 46 + dest[priv->len / NFT_REG32_SIZE] = 0; 47 + if (skb_copy_bits(skb, offset, dest, priv->len) < 0) 47 48 goto err; 48 49 return; 49 50 err: 50 - data[NFT_REG_VERDICT].verdict = NFT_BREAK; 51 + regs->verdict.code = NFT_BREAK; 51 52 } 52 53 53 54 static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { ··· 63 62 const struct nlattr * const tb[]) 64 63 { 65 64 struct nft_payload *priv = nft_expr_priv(expr); 66 - int err; 67 65 68 66 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 69 67 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 70 68 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 69 + priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]); 71 70 72 - priv->dreg = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_DREG])); 73 - err = nft_validate_output_register(priv->dreg); 74 - if (err < 0) 75 - return err; 76 - return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); 71 + return nft_validate_register_store(ctx, priv->dreg, NULL, 72 + NFT_DATA_VALUE, priv->len); 77 73 } 78 74 79 75 static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) 80 76 { 81 77 const struct nft_payload *priv = nft_expr_priv(expr); 82 78 83 - if (nla_put_be32(skb, NFTA_PAYLOAD_DREG, htonl(priv->dreg)) || 79 + if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) || 84 80 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || 85 81 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || 86 82 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len))) ··· 129 131 } 130 132 131 133 offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 132 - len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 133 - if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data)) 134 - return ERR_PTR(-EINVAL); 134 + len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 135 135 136 136 if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && 137 137 base != NFT_PAYLOAD_LL_HEADER)
+2 -2
net/netfilter/nft_queue.c
··· 28 28 }; 29 29 30 30 static void nft_queue_eval(const struct nft_expr *expr, 31 - struct nft_data data[NFT_REG_MAX + 1], 31 + struct nft_regs *regs, 32 32 const struct nft_pktinfo *pkt) 33 33 { 34 34 struct nft_queue *priv = nft_expr_priv(expr); ··· 51 51 if (priv->flags & NFT_QUEUE_FLAG_BYPASS) 52 52 ret |= NF_VERDICT_FLAG_QUEUE_BYPASS; 53 53 54 - data[NFT_REG_VERDICT].verdict = ret; 54 + regs->verdict.code = ret; 55 55 } 56 56 57 57 static const struct nla_policy nft_queue_policy[NFTA_QUEUE_MAX + 1] = {
+7 -8
net/netfilter/nft_rbtree.c
··· 30 30 }; 31 31 32 32 33 - static bool nft_rbtree_lookup(const struct nft_set *set, 34 - const struct nft_data *key, 33 + static bool nft_rbtree_lookup(const struct nft_set *set, const u32 *key, 35 34 const struct nft_set_ext **ext) 36 35 { 37 36 const struct nft_rbtree *priv = nft_set_priv(set); ··· 44 45 while (parent != NULL) { 45 46 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 46 47 47 - d = nft_data_cmp(nft_set_ext_key(&rbe->ext), key, set->klen); 48 + d = memcmp(nft_set_ext_key(&rbe->ext), key, set->klen); 48 49 if (d < 0) { 49 50 parent = parent->rb_left; 50 51 interval = rbe; ··· 90 91 while (*p != NULL) { 91 92 parent = *p; 92 93 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 93 - d = nft_data_cmp(nft_set_ext_key(&rbe->ext), 94 - nft_set_ext_key(&new->ext), 95 - set->klen); 94 + d = memcmp(nft_set_ext_key(&rbe->ext), 95 + nft_set_ext_key(&new->ext), 96 + set->klen); 96 97 if (d < 0) 97 98 p = &parent->rb_left; 98 99 else if (d > 0) ··· 152 153 while (parent != NULL) { 153 154 rbe = rb_entry(parent, struct nft_rbtree_elem, node); 154 155 155 - d = nft_data_cmp(nft_set_ext_key(&rbe->ext), &elem->key, 156 - set->klen); 156 + d = memcmp(nft_set_ext_key(&rbe->ext), &elem->key.val, 157 + set->klen); 157 158 if (d < 0) 158 159 parent = parent->rb_left; 159 160 else if (d > 0)
+11 -8
net/netfilter/nft_redir.c
··· 44 44 const struct nlattr * const tb[]) 45 45 { 46 46 struct nft_redir *priv = nft_expr_priv(expr); 47 + unsigned int plen; 47 48 int err; 48 49 49 50 err = nft_redir_validate(ctx, expr, NULL); 50 51 if (err < 0) 51 52 return err; 52 53 54 + plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all); 53 55 if (tb[NFTA_REDIR_REG_PROTO_MIN]) { 54 56 priv->sreg_proto_min = 55 - ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MIN])); 57 + nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]); 56 58 57 - err = nft_validate_input_register(priv->sreg_proto_min); 59 + err = nft_validate_register_load(priv->sreg_proto_min, plen); 58 60 if (err < 0) 59 61 return err; 60 62 61 63 if (tb[NFTA_REDIR_REG_PROTO_MAX]) { 62 64 priv->sreg_proto_max = 63 - ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MAX])); 65 + nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MAX]); 64 66 65 - err = nft_validate_input_register(priv->sreg_proto_max); 67 + err = nft_validate_register_load(priv->sreg_proto_max, 68 + plen); 66 69 if (err < 0) 67 70 return err; 68 71 } else { ··· 88 85 const struct nft_redir *priv = nft_expr_priv(expr); 89 86 90 87 if (priv->sreg_proto_min) { 91 - if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MIN, 92 - htonl(priv->sreg_proto_min))) 88 + if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MIN, 89 + priv->sreg_proto_min)) 93 90 goto nla_put_failure; 94 - if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MAX, 95 - htonl(priv->sreg_proto_max))) 91 + if (nft_dump_register(skb, NFTA_REDIR_REG_PROTO_MAX, 92 + priv->sreg_proto_max)) 96 93 goto nla_put_failure; 97 94 } 98 95
+3 -2
net/netfilter/nft_reject_inet.c
··· 18 18 #include <net/netfilter/ipv6/nf_reject.h> 19 19 20 20 static void nft_reject_inet_eval(const struct nft_expr *expr, 21 - struct nft_data data[NFT_REG_MAX + 1], 21 + struct nft_regs *regs, 22 22 const struct nft_pktinfo *pkt) 23 23 { 24 24 struct nft_reject *priv = nft_expr_priv(expr); ··· 58 58 } 59 59 break; 60 60 } 61 - data[NFT_REG_VERDICT].verdict = NF_DROP; 61 + 62 + regs->verdict.code = NF_DROP; 62 63 } 63 64 64 65 static int nft_reject_inet_init(const struct nft_ctx *ctx,