344-v4.16-netfilter-nf_tables-allocate-handle-and-delete-objec.patch 15 KB

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