diff options
Diffstat (limited to 'target/linux/generic/backport-4.19/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch')
-rw-r--r-- | target/linux/generic/backport-4.19/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.19/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch b/target/linux/generic/backport-4.19/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch new file mode 100644 index 0000000000..98ec5d1b7c --- /dev/null +++ b/target/linux/generic/backport-4.19/344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch @@ -0,0 +1,468 @@ +From: Harsha Sharma <harshasharmaiitr@gmail.com> +Date: Wed, 27 Dec 2017 00:59:00 +0530 +Subject: [PATCH] netfilter: nf_tables: allocate handle and delete objects via + handle + +This patch allows deletion of objects via unique handle which can be +listed via '-a' option. + +Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -370,6 +370,7 @@ void nft_unregister_set(struct nft_set_t + * @list: table set list node + * @bindings: list of set bindings + * @name: name of the set ++ * @handle: unique handle of the set + * @ktype: key type (numeric type defined by userspace, not used in the kernel) + * @dtype: data type (verdict or numeric type defined by userspace) + * @objtype: object type (see NFT_OBJECT_* definitions) +@@ -392,6 +393,7 @@ struct nft_set { + struct list_head list; + struct list_head bindings; + char *name; ++ u64 handle; + u32 ktype; + u32 dtype; + u32 objtype; +@@ -941,6 +943,7 @@ unsigned int nft_do_chain(struct nft_pkt + * @objects: stateful objects in the table + * @flowtables: flow tables in the table + * @hgenerator: handle generator state ++ * @handle: table handle + * @use: number of chain references to this table + * @flags: table flag (see enum nft_table_flags) + * @genmask: generation mask +@@ -954,6 +957,7 @@ struct nft_table { + struct list_head objects; + struct list_head flowtables; + u64 hgenerator; ++ u64 handle; + u32 use; + u16 family:6, + flags:8, +@@ -978,9 +982,9 @@ int nft_verdict_dump(struct sk_buff *skb + * @name: name of this stateful object + * @genmask: generation mask + * @use: number of references to this stateful object +- * @data: object data, layout depends on type ++ * @handle: unique object handle + * @ops: object operations +- * @data: pointer to object data ++ * @data: object data, layout depends on type + */ + struct nft_object { + struct list_head list; +@@ -988,6 +992,7 @@ struct nft_object { + struct nft_table *table; + u32 genmask:2, + use:30; ++ u64 handle; + /* runtime data below here */ + const struct nft_object_ops *ops ____cacheline_aligned; + unsigned char data[] +@@ -1069,6 +1074,7 @@ void nft_unregister_obj(struct nft_objec + * @ops_len: number of hooks in array + * @genmask: generation mask + * @use: number of references to this flow table ++ * @handle: unique object handle + * @data: rhashtable and garbage collector + * @ops: array of hooks + */ +@@ -1081,6 +1087,7 @@ struct nft_flowtable { + int ops_len; + u32 genmask:2, + use:30; ++ u64 handle; + /* runtime data below here */ + struct nf_hook_ops *ops ____cacheline_aligned; + struct nf_flowtable data; +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -174,6 +174,8 @@ enum nft_table_attributes { + NFTA_TABLE_NAME, + NFTA_TABLE_FLAGS, + NFTA_TABLE_USE, ++ NFTA_TABLE_HANDLE, ++ NFTA_TABLE_PAD, + __NFTA_TABLE_MAX + }; + #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) +@@ -317,6 +319,7 @@ enum nft_set_desc_attributes { + * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) + * @NFTA_SET_USERDATA: user data (NLA_BINARY) + * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) ++ * @NFTA_SET_HANDLE: set handle (NLA_U64) + */ + enum nft_set_attributes { + NFTA_SET_UNSPEC, +@@ -335,6 +338,7 @@ enum nft_set_attributes { + NFTA_SET_USERDATA, + NFTA_SET_PAD, + NFTA_SET_OBJ_TYPE, ++ NFTA_SET_HANDLE, + __NFTA_SET_MAX + }; + #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) +@@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes { + * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) + * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) + * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) ++ * @NFTA_OBJ_HANDLE: object handle (NLA_U64) + */ + enum nft_object_attributes { + NFTA_OBJ_UNSPEC, +@@ -1322,6 +1327,8 @@ enum nft_object_attributes { + NFTA_OBJ_TYPE, + NFTA_OBJ_DATA, + NFTA_OBJ_USE, ++ NFTA_OBJ_HANDLE, ++ NFTA_OBJ_PAD, + __NFTA_OBJ_MAX + }; + #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) +@@ -1333,6 +1340,7 @@ enum nft_object_attributes { + * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) + * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) + * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) ++ * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) + */ + enum nft_flowtable_attributes { + NFTA_FLOWTABLE_UNSPEC, +@@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes { + NFTA_FLOWTABLE_NAME, + NFTA_FLOWTABLE_HOOK, + NFTA_FLOWTABLE_USE, ++ NFTA_FLOWTABLE_HANDLE, ++ NFTA_FLOWTABLE_PAD, + __NFTA_FLOWTABLE_MAX + }; + #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -26,6 +26,7 @@ + static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); + static LIST_HEAD(nf_tables_flowtables); ++static u64 table_handle; + + static void nft_ctx_init(struct nft_ctx *ctx, + struct net *net, +@@ -361,6 +362,20 @@ static struct nft_table *nft_table_looku + return NULL; + } + ++static struct nft_table *nft_table_lookup_byhandle(const struct net *net, ++ const struct nlattr *nla, ++ u8 genmask) ++{ ++ struct nft_table *table; ++ ++ list_for_each_entry(table, &net->nft.tables, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == table->handle && ++ nft_active_genmask(table, genmask)) ++ return table; ++ } ++ return NULL; ++} ++ + static struct nft_table *nf_tables_table_lookup(const struct net *net, + const struct nlattr *nla, + u8 family, u8 genmask) +@@ -377,6 +392,22 @@ static struct nft_table *nf_tables_table + return ERR_PTR(-ENOENT); + } + ++static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, ++ const struct nlattr *nla, ++ u8 genmask) ++{ ++ struct nft_table *table; ++ ++ if (nla == NULL) ++ return ERR_PTR(-EINVAL); ++ ++ table = nft_table_lookup_byhandle(net, nla, genmask); ++ if (table != NULL) ++ return table; ++ ++ return ERR_PTR(-ENOENT); ++} ++ + static inline u64 nf_tables_alloc_handle(struct nft_table *table) + { + return ++table->hgenerator; +@@ -423,6 +454,7 @@ static const struct nla_policy nft_table + [NFTA_TABLE_NAME] = { .type = NLA_STRING, + .len = NFT_TABLE_MAXNAMELEN - 1 }, + [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, ++ [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, + }; + + static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, +@@ -444,7 +476,9 @@ static int nf_tables_fill_table_info(str + + if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || + nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || +- nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) ++ nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || ++ nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), ++ NFTA_TABLE_PAD)) + goto nla_put_failure; + + nlmsg_end(skb, nlh); +@@ -703,6 +737,7 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->flowtables); + table->family = family; + table->flags = flags; ++ table->handle = ++table_handle; + + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); +@@ -820,11 +855,18 @@ static int nf_tables_deltable(struct net + struct nft_ctx ctx; + + nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); +- if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) ++ if (family == AF_UNSPEC || ++ (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) + return nft_flush(&ctx, family); + +- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, +- genmask); ++ if (nla[NFTA_TABLE_HANDLE]) ++ table = nf_tables_table_lookup_byhandle(net, ++ nla[NFTA_TABLE_HANDLE], ++ genmask); ++ else ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], ++ family, genmask); ++ + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -1581,6 +1623,7 @@ static int nf_tables_delchain(struct net + struct nft_rule *rule; + int family = nfmsg->nfgen_family; + struct nft_ctx ctx; ++ u64 handle; + u32 use; + int err; + +@@ -1589,7 +1632,12 @@ static int nf_tables_delchain(struct net + if (IS_ERR(table)) + return PTR_ERR(table); + +- chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); ++ if (nla[NFTA_CHAIN_HANDLE]) { ++ handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); ++ chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); ++ } else { ++ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); ++ } + if (IS_ERR(chain)) + return PTR_ERR(chain); + +@@ -2563,6 +2611,7 @@ static const struct nla_policy nft_set_p + [NFTA_SET_USERDATA] = { .type = NLA_BINARY, + .len = NFT_USERDATA_MAXLEN }, + [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, ++ [NFTA_SET_HANDLE] = { .type = NLA_U64 }, + }; + + static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { +@@ -2606,6 +2655,22 @@ static struct nft_set *nf_tables_set_loo + return ERR_PTR(-ENOENT); + } + ++static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, u8 genmask) ++{ ++ struct nft_set *set; ++ ++ if (nla == NULL) ++ return ERR_PTR(-EINVAL); ++ ++ list_for_each_entry(set, &table->sets, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == set->handle && ++ nft_active_genmask(set, genmask)) ++ return set; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, + const struct nlattr *nla, + u8 genmask) +@@ -2722,6 +2787,9 @@ static int nf_tables_fill_set(struct sk_ + goto nla_put_failure; + if (nla_put_string(skb, NFTA_SET_NAME, set->name)) + goto nla_put_failure; ++ if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), ++ NFTA_SET_PAD)) ++ goto nla_put_failure; + if (set->flags != 0) + if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) + goto nla_put_failure; +@@ -3130,6 +3198,7 @@ static int nf_tables_newset(struct net * + set->udata = udata; + set->timeout = timeout; + set->gc_int = gc_int; ++ set->handle = nf_tables_alloc_handle(table); + + err = ops->init(set, &desc, nla); + if (err < 0) +@@ -3189,7 +3258,10 @@ static int nf_tables_delset(struct net * + if (err < 0) + return err; + +- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); ++ if (nla[NFTA_SET_HANDLE]) ++ set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); ++ else ++ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); + if (IS_ERR(set)) + return PTR_ERR(set); + +@@ -4250,6 +4322,21 @@ struct nft_object *nf_tables_obj_lookup( + } + EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); + ++struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, ++ u32 objtype, u8 genmask) ++{ ++ struct nft_object *obj; ++ ++ list_for_each_entry(obj, &table->objects, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && ++ objtype == obj->ops->type->type && ++ nft_active_genmask(obj, genmask)) ++ return obj; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { + [NFTA_OBJ_TABLE] = { .type = NLA_STRING, + .len = NFT_TABLE_MAXNAMELEN - 1 }, +@@ -4257,6 +4344,7 @@ static const struct nla_policy nft_obj_p + .len = NFT_OBJ_MAXNAMELEN - 1 }, + [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, + [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, ++ [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, + }; + + static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, +@@ -4404,6 +4492,8 @@ static int nf_tables_newobj(struct net * + goto err1; + } + obj->table = table; ++ obj->handle = nf_tables_alloc_handle(table); ++ + obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); + if (!obj->name) { + err = -ENOMEM; +@@ -4450,7 +4540,9 @@ static int nf_tables_fill_obj_info(struc + nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || + nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || + nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || +- nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) ++ nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || ++ nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), ++ NFTA_OBJ_PAD)) + goto nla_put_failure; + + nlmsg_end(skb, nlh); +@@ -4648,7 +4740,7 @@ static int nf_tables_delobj(struct net * + u32 objtype; + + if (!nla[NFTA_OBJ_TYPE] || +- !nla[NFTA_OBJ_NAME]) ++ (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) + return -EINVAL; + + table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, +@@ -4657,7 +4749,12 @@ static int nf_tables_delobj(struct net * + return PTR_ERR(table); + + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); +- obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); ++ if (nla[NFTA_OBJ_HANDLE]) ++ obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], ++ objtype, genmask); ++ else ++ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], ++ objtype, genmask); + if (IS_ERR(obj)) + return PTR_ERR(obj); + if (obj->use > 0) +@@ -4729,6 +4826,7 @@ static const struct nla_policy nft_flowt + [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, + .len = NFT_NAME_MAXLEN - 1 }, + [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, ++ [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, + }; + + struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, +@@ -4746,6 +4844,20 @@ struct nft_flowtable *nf_tables_flowtabl + } + EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); + ++struct nft_flowtable * ++nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, u8 genmask) ++{ ++ struct nft_flowtable *flowtable; ++ ++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && ++ nft_active_genmask(flowtable, genmask)) ++ return flowtable; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + #define NFT_FLOWTABLE_DEVICE_MAX 8 + + static int nf_tables_parse_devices(const struct nft_ctx *ctx, +@@ -4954,6 +5066,8 @@ static int nf_tables_newflowtable(struct + return -ENOMEM; + + flowtable->table = table; ++ flowtable->handle = nf_tables_alloc_handle(table); ++ + flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); + if (!flowtable->name) { + err = -ENOMEM; +@@ -5028,8 +5142,14 @@ static int nf_tables_delflowtable(struct + if (IS_ERR(table)) + return PTR_ERR(table); + +- flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], +- genmask); ++ if (nla[NFTA_FLOWTABLE_HANDLE]) ++ flowtable = nf_tables_flowtable_lookup_byhandle(table, ++ nla[NFTA_FLOWTABLE_HANDLE], ++ genmask); ++ else ++ flowtable = nf_tables_flowtable_lookup(table, ++ nla[NFTA_FLOWTABLE_NAME], ++ genmask); + if (IS_ERR(flowtable)) + return PTR_ERR(flowtable); + if (flowtable->use > 0) +@@ -5062,7 +5182,9 @@ static int nf_tables_fill_flowtable_info + + if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || + nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || +- nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) ++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || ++ nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), ++ NFTA_FLOWTABLE_PAD)) + goto nla_put_failure; + + nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); |