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