kernel : Bump to 4.14.325
[librecmc/librecmc.git] / target / linux / generic / backport-4.14 / 344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch
1 From: Harsha Sharma <harshasharmaiitr@gmail.com>
2 Date: Wed, 27 Dec 2017 00:59:00 +0530
3 Subject: [PATCH] netfilter: nf_tables: allocate handle and delete objects via
4  handle
5
6 This patch allows deletion of objects via unique handle which can be
7 listed via '-a' option.
8
9 Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com>
10 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 ---
12
13 --- a/include/net/netfilter/nf_tables.h
14 +++ b/include/net/netfilter/nf_tables.h
15 @@ -376,6 +376,7 @@ void nft_unregister_set(struct nft_set_t
16   *     @bindings: list of set bindings
17   *     @table: table this set belongs to
18   *     @name: name of the set
19 + *     @handle: unique handle of the set
20   *     @ktype: key type (numeric type defined by userspace, not used in the kernel)
21   *     @dtype: data type (verdict or numeric type defined by userspace)
22   *     @objtype: object type (see NFT_OBJECT_* definitions)
23 @@ -400,6 +401,7 @@ struct nft_set {
24         struct list_head                bindings;
25         struct nft_table                *table;
26         char                            *name;
27 +       u64                             handle;
28         u32                             ktype;
29         u32                             dtype;
30         u32                             objtype;
31 @@ -991,6 +993,7 @@ static inline void nft_use_inc_restore(u
32   *     @objects: stateful objects in the table
33   *     @flowtables: flow tables in the table
34   *     @hgenerator: handle generator state
35 + *     @handle: table handle
36   *     @use: number of chain references to this table
37   *     @flags: table flag (see enum nft_table_flags)
38   *     @genmask: generation mask
39 @@ -1004,6 +1007,7 @@ struct nft_table {
40         struct list_head                objects;
41         struct list_head                flowtables;
42         u64                             hgenerator;
43 +       u64                             handle;
44         u32                             use;
45         u16                             family:6,
46                                         flags:8,
47 @@ -1028,14 +1032,15 @@ int nft_verdict_dump(struct sk_buff *skb
48   *     @name: name of this stateful object
49   *     @genmask: generation mask
50   *     @use: number of references to this stateful object
51 - *     @data: object data, layout depends on type
52 + *     @handle: unique object handle
53   *     @ops: object operations
54 - *     @data: pointer to object data
55 + *     @data: object data, layout depends on type
56   */
57  struct nft_object {
58         struct list_head                list;
59         char                            *name;
60         struct nft_table                *table;
61 +       u64                             handle;
62         u32                             genmask:2;
63         u32                             use;
64         /* runtime data below here */
65 @@ -1119,6 +1124,7 @@ void nft_unregister_obj(struct nft_objec
66   *     @ops_len: number of hooks in array
67   *     @genmask: generation mask
68   *     @use: number of references to this flow table
69 + *     @handle: unique object handle
70   *     @data: rhashtable and garbage collector
71   *     @ops: array of hooks
72   */
73 @@ -1131,6 +1137,7 @@ struct nft_flowtable {
74         int                             ops_len;
75         u32                             genmask:2,
76                                         use:30;
77 +       u64                             handle;
78         /* runtime data below here */
79         struct nf_hook_ops              *ops ____cacheline_aligned;
80         struct nf_flowtable             data;
81 --- a/include/uapi/linux/netfilter/nf_tables.h
82 +++ b/include/uapi/linux/netfilter/nf_tables.h
83 @@ -174,6 +174,8 @@ enum nft_table_attributes {
84         NFTA_TABLE_NAME,
85         NFTA_TABLE_FLAGS,
86         NFTA_TABLE_USE,
87 +       NFTA_TABLE_HANDLE,
88 +       NFTA_TABLE_PAD,
89         __NFTA_TABLE_MAX
90  };
91  #define NFTA_TABLE_MAX         (__NFTA_TABLE_MAX - 1)
92 @@ -317,6 +319,7 @@ enum nft_set_desc_attributes {
93   * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
94   * @NFTA_SET_USERDATA: user data (NLA_BINARY)
95   * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
96 + * @NFTA_SET_HANDLE: set handle (NLA_U64)
97   */
98  enum nft_set_attributes {
99         NFTA_SET_UNSPEC,
100 @@ -335,6 +338,7 @@ enum nft_set_attributes {
101         NFTA_SET_USERDATA,
102         NFTA_SET_PAD,
103         NFTA_SET_OBJ_TYPE,
104 +       NFTA_SET_HANDLE,
105         __NFTA_SET_MAX
106  };
107  #define NFTA_SET_MAX           (__NFTA_SET_MAX - 1)
108 @@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes {
109   * @NFTA_OBJ_TYPE: stateful object type (NLA_U32)
110   * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
111   * @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
112 + * @NFTA_OBJ_HANDLE: object handle (NLA_U64)
113   */
114  enum nft_object_attributes {
115         NFTA_OBJ_UNSPEC,
116 @@ -1322,6 +1327,8 @@ enum nft_object_attributes {
117         NFTA_OBJ_TYPE,
118         NFTA_OBJ_DATA,
119         NFTA_OBJ_USE,
120 +       NFTA_OBJ_HANDLE,
121 +       NFTA_OBJ_PAD,
122         __NFTA_OBJ_MAX
123  };
124  #define NFTA_OBJ_MAX           (__NFTA_OBJ_MAX - 1)
125 @@ -1333,6 +1340,7 @@ enum nft_object_attributes {
126   * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING)
127   * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
128   * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
129 + * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
130   */
131  enum nft_flowtable_attributes {
132         NFTA_FLOWTABLE_UNSPEC,
133 @@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes {
134         NFTA_FLOWTABLE_NAME,
135         NFTA_FLOWTABLE_HOOK,
136         NFTA_FLOWTABLE_USE,
137 +       NFTA_FLOWTABLE_HANDLE,
138 +       NFTA_FLOWTABLE_PAD,
139         __NFTA_FLOWTABLE_MAX
140  };
141  #define NFTA_FLOWTABLE_MAX     (__NFTA_FLOWTABLE_MAX - 1)
142 --- a/net/netfilter/nf_tables_api.c
143 +++ b/net/netfilter/nf_tables_api.c
144 @@ -26,6 +26,7 @@
145  static LIST_HEAD(nf_tables_expressions);
146  static LIST_HEAD(nf_tables_objects);
147  static LIST_HEAD(nf_tables_flowtables);
148 +static u64 table_handle;
149  
150  static void nft_ctx_init(struct nft_ctx *ctx,
151                          struct net *net,
152 @@ -399,6 +400,20 @@ static struct nft_table *nft_table_looku
153         return NULL;
154  }
155  
156 +static struct nft_table *nft_table_lookup_byhandle(const struct net *net,
157 +                                                  const struct nlattr *nla,
158 +                                                  u8 genmask)
159 +{
160 +       struct nft_table *table;
161 +
162 +       list_for_each_entry(table, &net->nft.tables, list) {
163 +               if (be64_to_cpu(nla_get_be64(nla)) == table->handle &&
164 +                   nft_active_genmask(table, genmask))
165 +                       return table;
166 +       }
167 +       return NULL;
168 +}
169 +
170  static struct nft_table *nf_tables_table_lookup(const struct net *net,
171                                                 const struct nlattr *nla,
172                                                 u8 family, u8 genmask)
173 @@ -415,6 +430,22 @@ static struct nft_table *nf_tables_table
174         return ERR_PTR(-ENOENT);
175  }
176  
177 +static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net,
178 +                                                        const struct nlattr *nla,
179 +                                                        u8 genmask)
180 +{
181 +       struct nft_table *table;
182 +
183 +       if (nla == NULL)
184 +               return ERR_PTR(-EINVAL);
185 +
186 +       table = nft_table_lookup_byhandle(net, nla, genmask);
187 +       if (table != NULL)
188 +               return table;
189 +
190 +       return ERR_PTR(-ENOENT);
191 +}
192 +
193  static inline u64 nf_tables_alloc_handle(struct nft_table *table)
194  {
195         return ++table->hgenerator;
196 @@ -461,6 +492,7 @@ static const struct nla_policy nft_table
197         [NFTA_TABLE_NAME]       = { .type = NLA_STRING,
198                                     .len = NFT_TABLE_MAXNAMELEN - 1 },
199         [NFTA_TABLE_FLAGS]      = { .type = NLA_U32 },
200 +       [NFTA_TABLE_HANDLE]     = { .type = NLA_U64 },
201  };
202  
203  static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
204 @@ -482,7 +514,9 @@ static int nf_tables_fill_table_info(str
205  
206         if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
207             nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
208 -           nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)))
209 +           nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) ||
210 +           nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle),
211 +                        NFTA_TABLE_PAD))
212                 goto nla_put_failure;
213  
214         nlmsg_end(skb, nlh);
215 @@ -741,6 +775,7 @@ static int nf_tables_newtable(struct net
216         INIT_LIST_HEAD(&table->flowtables);
217         table->family = family;
218         table->flags = flags;
219 +       table->handle = ++table_handle;
220  
221         nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
222         err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
223 @@ -858,11 +893,18 @@ static int nf_tables_deltable(struct net
224         struct nft_ctx ctx;
225  
226         nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla);
227 -       if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL)
228 +       if (family == AF_UNSPEC ||
229 +           (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))
230                 return nft_flush(&ctx, family);
231  
232 -       table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family,
233 -                                      genmask);
234 +       if (nla[NFTA_TABLE_HANDLE])
235 +               table = nf_tables_table_lookup_byhandle(net,
236 +                                                       nla[NFTA_TABLE_HANDLE],
237 +                                                       genmask);
238 +       else
239 +               table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME],
240 +                                              family, genmask);
241 +
242         if (IS_ERR(table))
243                 return PTR_ERR(table);
244  
245 @@ -1622,6 +1664,7 @@ static int nf_tables_delchain(struct net
246         struct nft_rule *rule;
247         int family = nfmsg->nfgen_family;
248         struct nft_ctx ctx;
249 +       u64 handle;
250         u32 use;
251         int err;
252  
253 @@ -1630,7 +1673,12 @@ static int nf_tables_delchain(struct net
254         if (IS_ERR(table))
255                 return PTR_ERR(table);
256  
257 -       chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
258 +       if (nla[NFTA_CHAIN_HANDLE]) {
259 +               handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
260 +               chain = nf_tables_chain_lookup_byhandle(table, handle, genmask);
261 +       } else {
262 +               chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
263 +       }
264         if (IS_ERR(chain))
265                 return PTR_ERR(chain);
266  
267 @@ -2609,6 +2657,7 @@ static const struct nla_policy nft_set_p
268         [NFTA_SET_USERDATA]             = { .type = NLA_BINARY,
269                                             .len  = NFT_USERDATA_MAXLEN },
270         [NFTA_SET_OBJ_TYPE]             = { .type = NLA_U32 },
271 +       [NFTA_SET_HANDLE]               = { .type = NLA_U64 },
272  };
273  
274  static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
275 @@ -2652,6 +2701,22 @@ static struct nft_set *nf_tables_set_loo
276         return ERR_PTR(-ENOENT);
277  }
278  
279 +static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table,
280 +                                                    const struct nlattr *nla, u8 genmask)
281 +{
282 +       struct nft_set *set;
283 +
284 +       if (nla == NULL)
285 +               return ERR_PTR(-EINVAL);
286 +
287 +       list_for_each_entry(set, &table->sets, list) {
288 +               if (be64_to_cpu(nla_get_be64(nla)) == set->handle &&
289 +                   nft_active_genmask(set, genmask))
290 +                       return set;
291 +       }
292 +       return ERR_PTR(-ENOENT);
293 +}
294 +
295  static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
296                                                  const struct nft_table *table,
297                                                  const struct nlattr *nla,
298 @@ -2770,6 +2835,9 @@ static int nf_tables_fill_set(struct sk_
299                 goto nla_put_failure;
300         if (nla_put_string(skb, NFTA_SET_NAME, set->name))
301                 goto nla_put_failure;
302 +       if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle),
303 +                        NFTA_SET_PAD))
304 +               goto nla_put_failure;
305         if (set->flags != 0)
306                 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
307                         goto nla_put_failure;
308 @@ -3188,6 +3256,7 @@ static int nf_tables_newset(struct net *
309         set->udata  = udata;
310         set->timeout = timeout;
311         set->gc_int = gc_int;
312 +       set->handle = nf_tables_alloc_handle(table);
313  
314         err = ops->init(set, &desc, nla);
315         if (err < 0)
316 @@ -3245,7 +3314,10 @@ static int nf_tables_delset(struct net *
317         if (err < 0)
318                 return err;
319  
320 -       set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
321 +       if (nla[NFTA_SET_HANDLE])
322 +               set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask);
323 +       else
324 +               set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
325         if (IS_ERR(set))
326                 return PTR_ERR(set);
327  
328 @@ -4416,6 +4488,21 @@ struct nft_object *nf_tables_obj_lookup(
329  }
330  EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
331  
332 +struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table,
333 +                                                const struct nlattr *nla,
334 +                                                u32 objtype, u8 genmask)
335 +{
336 +       struct nft_object *obj;
337 +
338 +       list_for_each_entry(obj, &table->objects, list) {
339 +               if (be64_to_cpu(nla_get_be64(nla)) == obj->handle &&
340 +                   objtype == obj->ops->type->type &&
341 +                   nft_active_genmask(obj, genmask))
342 +                       return obj;
343 +       }
344 +       return ERR_PTR(-ENOENT);
345 +}
346 +
347  static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
348         [NFTA_OBJ_TABLE]        = { .type = NLA_STRING,
349                                     .len = NFT_TABLE_MAXNAMELEN - 1 },
350 @@ -4423,6 +4510,7 @@ static const struct nla_policy nft_obj_p
351                                     .len = NFT_OBJ_MAXNAMELEN - 1 },
352         [NFTA_OBJ_TYPE]         = { .type = NLA_U32 },
353         [NFTA_OBJ_DATA]         = { .type = NLA_NESTED },
354 +       [NFTA_OBJ_HANDLE]       = { .type = NLA_U64},
355  };
356  
357  static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
358 @@ -4575,6 +4663,8 @@ static int nf_tables_newobj(struct net *
359                 goto err1;
360         }
361         obj->table = table;
362 +       obj->handle = nf_tables_alloc_handle(table);
363 +
364         obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
365         if (!obj->name) {
366                 err = -ENOMEM;
367 @@ -4624,7 +4714,9 @@ static int nf_tables_fill_obj_info(struc
368             nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
369             nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
370             nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
371 -           nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset))
372 +           nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) ||
373 +           nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle),
374 +                        NFTA_OBJ_PAD))
375                 goto nla_put_failure;
376  
377         nlmsg_end(skb, nlh);
378 @@ -4822,7 +4914,7 @@ static int nf_tables_delobj(struct net *
379         u32 objtype;
380  
381         if (!nla[NFTA_OBJ_TYPE] ||
382 -           !nla[NFTA_OBJ_NAME])
383 +           (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE]))
384                 return -EINVAL;
385  
386         table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family,
387 @@ -4831,7 +4923,12 @@ static int nf_tables_delobj(struct net *
388                 return PTR_ERR(table);
389  
390         objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
391 -       obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
392 +       if (nla[NFTA_OBJ_HANDLE])
393 +               obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE],
394 +                                                   objtype, genmask);
395 +       else
396 +               obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME],
397 +                                          objtype, genmask);
398         if (IS_ERR(obj))
399                 return PTR_ERR(obj);
400         if (obj->use > 0)
401 @@ -4903,6 +5000,7 @@ static const struct nla_policy nft_flowt
402         [NFTA_FLOWTABLE_NAME]           = { .type = NLA_STRING,
403                                             .len = NFT_NAME_MAXLEN - 1 },
404         [NFTA_FLOWTABLE_HOOK]           = { .type = NLA_NESTED },
405 +       [NFTA_FLOWTABLE_HANDLE]         = { .type = NLA_U64 },
406  };
407  
408  struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table,
409 @@ -4920,6 +5018,20 @@ struct nft_flowtable *nf_tables_flowtabl
410  }
411  EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup);
412  
413 +struct nft_flowtable *
414 +nf_tables_flowtable_lookup_byhandle(const struct nft_table *table,
415 +                                   const struct nlattr *nla, u8 genmask)
416 +{
417 +       struct nft_flowtable *flowtable;
418 +
419 +       list_for_each_entry(flowtable, &table->flowtables, list) {
420 +               if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle &&
421 +                   nft_active_genmask(flowtable, genmask))
422 +                       return flowtable;
423 +       }
424 +       return ERR_PTR(-ENOENT);
425 +}
426 +
427  #define NFT_FLOWTABLE_DEVICE_MAX       8
428  
429  static int nf_tables_parse_devices(const struct nft_ctx *ctx,
430 @@ -5128,6 +5240,8 @@ static int nf_tables_newflowtable(struct
431                 return -ENOMEM;
432  
433         flowtable->table = table;
434 +       flowtable->handle = nf_tables_alloc_handle(table);
435 +
436         flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
437         if (!flowtable->name) {
438                 err = -ENOMEM;
439 @@ -5202,8 +5316,14 @@ static int nf_tables_delflowtable(struct
440         if (IS_ERR(table))
441                 return PTR_ERR(table);
442  
443 -       flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
444 -                                              genmask);
445 +       if (nla[NFTA_FLOWTABLE_HANDLE])
446 +               flowtable = nf_tables_flowtable_lookup_byhandle(table,
447 +                                                               nla[NFTA_FLOWTABLE_HANDLE],
448 +                                                               genmask);
449 +       else
450 +               flowtable = nf_tables_flowtable_lookup(table,
451 +                                                      nla[NFTA_FLOWTABLE_NAME],
452 +                                                      genmask);
453         if (IS_ERR(flowtable))
454                  return PTR_ERR(flowtable);
455         if (flowtable->use > 0)
456 @@ -5236,7 +5356,9 @@ static int nf_tables_fill_flowtable_info
457  
458         if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
459             nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
460 -           nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)))
461 +           nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
462 +           nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),
463 +                        NFTA_FLOWTABLE_PAD))
464                 goto nla_put_failure;
465  
466         nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK);