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

netfilter: nf_tables: add helpers to schedule objects deletion

This patch refactor the code to schedule objects deletion.
They are useful in follow-up patches.

In order to be able to use these new helper functions in all the code,
they are placed in the top of the file, with all the dependant functions
and symbols.

nft_rule_disactivate_next has been renamed to nft_rule_deactivate.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Arturo Borrero and committed by
Pablo Neira Ayuso
ee01d542 c435201b

+194 -169
+194 -169
net/netfilter/nf_tables_api.c
··· 136 136 nf_unregister_hooks(nft_base_chain(chain)->ops, hook_nops); 137 137 } 138 138 139 + /* Internal table flags */ 140 + #define NFT_TABLE_INACTIVE (1 << 15) 141 + 142 + static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) 143 + { 144 + struct nft_trans *trans; 145 + 146 + trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table)); 147 + if (trans == NULL) 148 + return -ENOMEM; 149 + 150 + if (msg_type == NFT_MSG_NEWTABLE) 151 + ctx->table->flags |= NFT_TABLE_INACTIVE; 152 + 153 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 154 + return 0; 155 + } 156 + 157 + static int nft_deltable(struct nft_ctx *ctx) 158 + { 159 + int err; 160 + 161 + err = nft_trans_table_add(ctx, NFT_MSG_DELTABLE); 162 + if (err < 0) 163 + return err; 164 + 165 + list_del_rcu(&ctx->table->list); 166 + return err; 167 + } 168 + 169 + static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) 170 + { 171 + struct nft_trans *trans; 172 + 173 + trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain)); 174 + if (trans == NULL) 175 + return -ENOMEM; 176 + 177 + if (msg_type == NFT_MSG_NEWCHAIN) 178 + ctx->chain->flags |= NFT_CHAIN_INACTIVE; 179 + 180 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 181 + return 0; 182 + } 183 + 184 + static int nft_delchain(struct nft_ctx *ctx) 185 + { 186 + int err; 187 + 188 + err = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN); 189 + if (err < 0) 190 + return err; 191 + 192 + ctx->table->use--; 193 + list_del_rcu(&ctx->chain->list); 194 + 195 + return err; 196 + } 197 + 198 + static inline bool 199 + nft_rule_is_active(struct net *net, const struct nft_rule *rule) 200 + { 201 + return (rule->genmask & (1 << net->nft.gencursor)) == 0; 202 + } 203 + 204 + static inline int gencursor_next(struct net *net) 205 + { 206 + return net->nft.gencursor+1 == 1 ? 1 : 0; 207 + } 208 + 209 + static inline int 210 + nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) 211 + { 212 + return (rule->genmask & (1 << gencursor_next(net))) == 0; 213 + } 214 + 215 + static inline void 216 + nft_rule_activate_next(struct net *net, struct nft_rule *rule) 217 + { 218 + /* Now inactive, will be active in the future */ 219 + rule->genmask = (1 << net->nft.gencursor); 220 + } 221 + 222 + static inline void 223 + nft_rule_deactivate_next(struct net *net, struct nft_rule *rule) 224 + { 225 + rule->genmask = (1 << gencursor_next(net)); 226 + } 227 + 228 + static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) 229 + { 230 + rule->genmask = 0; 231 + } 232 + 233 + static int 234 + nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) 235 + { 236 + /* You cannot delete the same rule twice */ 237 + if (nft_rule_is_active_next(ctx->net, rule)) { 238 + nft_rule_deactivate_next(ctx->net, rule); 239 + ctx->chain->use--; 240 + return 0; 241 + } 242 + return -ENOENT; 243 + } 244 + 245 + static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type, 246 + struct nft_rule *rule) 247 + { 248 + struct nft_trans *trans; 249 + 250 + trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule)); 251 + if (trans == NULL) 252 + return NULL; 253 + 254 + nft_trans_rule(trans) = rule; 255 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 256 + 257 + return trans; 258 + } 259 + 260 + static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule) 261 + { 262 + struct nft_trans *trans; 263 + int err; 264 + 265 + trans = nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule); 266 + if (trans == NULL) 267 + return -ENOMEM; 268 + 269 + err = nf_tables_delrule_deactivate(ctx, rule); 270 + if (err < 0) { 271 + nft_trans_destroy(trans); 272 + return err; 273 + } 274 + 275 + return 0; 276 + } 277 + 278 + static int nft_delrule_by_chain(struct nft_ctx *ctx) 279 + { 280 + struct nft_rule *rule; 281 + int err; 282 + 283 + list_for_each_entry(rule, &ctx->chain->rules, list) { 284 + err = nft_delrule(ctx, rule); 285 + if (err < 0) 286 + return err; 287 + } 288 + return 0; 289 + } 290 + 291 + /* Internal set flag */ 292 + #define NFT_SET_INACTIVE (1 << 15) 293 + 294 + static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type, 295 + struct nft_set *set) 296 + { 297 + struct nft_trans *trans; 298 + 299 + trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set)); 300 + if (trans == NULL) 301 + return -ENOMEM; 302 + 303 + if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) { 304 + nft_trans_set_id(trans) = 305 + ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID])); 306 + set->flags |= NFT_SET_INACTIVE; 307 + } 308 + nft_trans_set(trans) = set; 309 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 310 + 311 + return 0; 312 + } 313 + 314 + static int nft_delset(struct nft_ctx *ctx, struct nft_set *set) 315 + { 316 + int err; 317 + 318 + err = nft_trans_set_add(ctx, NFT_MSG_DELSET, set); 319 + if (err < 0) 320 + return err; 321 + 322 + list_del_rcu(&set->list); 323 + ctx->table->use--; 324 + 325 + return err; 326 + } 327 + 139 328 /* 140 329 * Tables 141 330 */ ··· 507 318 return skb->len; 508 319 } 509 320 510 - /* Internal table flags */ 511 - #define NFT_TABLE_INACTIVE (1 << 15) 512 - 513 321 static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb, 514 322 const struct nlmsghdr *nlh, 515 323 const struct nlattr * const nla[]) ··· 638 452 return ret; 639 453 } 640 454 641 - static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) 642 - { 643 - struct nft_trans *trans; 644 - 645 - trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table)); 646 - if (trans == NULL) 647 - return -ENOMEM; 648 - 649 - if (msg_type == NFT_MSG_NEWTABLE) 650 - ctx->table->flags |= NFT_TABLE_INACTIVE; 651 - 652 - list_add_tail(&trans->list, &ctx->net->nft.commit_list); 653 - return 0; 654 - } 655 - 656 455 static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, 657 456 const struct nlmsghdr *nlh, 658 457 const struct nlattr * const nla[]) ··· 715 544 struct nft_af_info *afi; 716 545 struct nft_table *table; 717 546 struct net *net = sock_net(skb->sk); 718 - int family = nfmsg->nfgen_family, err; 547 + int family = nfmsg->nfgen_family; 719 548 struct nft_ctx ctx; 720 549 721 550 afi = nf_tables_afinfo_lookup(net, family, false); ··· 731 560 return -EBUSY; 732 561 733 562 nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); 734 - err = nft_trans_table_add(&ctx, NFT_MSG_DELTABLE); 735 - if (err < 0) 736 - return err; 737 563 738 - list_del_rcu(&table->list); 739 - return 0; 564 + return nft_deltable(&ctx); 740 565 } 741 566 742 567 static void nf_tables_table_destroy(struct nft_ctx *ctx) ··· 1089 922 rcu_assign_pointer(chain->stats, newstats); 1090 923 } 1091 924 1092 - static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) 1093 - { 1094 - struct nft_trans *trans; 1095 - 1096 - trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain)); 1097 - if (trans == NULL) 1098 - return -ENOMEM; 1099 - 1100 - if (msg_type == NFT_MSG_NEWCHAIN) 1101 - ctx->chain->flags |= NFT_CHAIN_INACTIVE; 1102 - 1103 - list_add_tail(&trans->list, &ctx->net->nft.commit_list); 1104 - return 0; 1105 - } 1106 - 1107 925 static void nf_tables_chain_destroy(struct nft_chain *chain) 1108 926 { 1109 927 BUG_ON(chain->use > 0); ··· 1335 1183 struct net *net = sock_net(skb->sk); 1336 1184 int family = nfmsg->nfgen_family; 1337 1185 struct nft_ctx ctx; 1338 - int err; 1339 1186 1340 1187 afi = nf_tables_afinfo_lookup(net, family, false); 1341 1188 if (IS_ERR(afi)) ··· 1355 1204 return -EBUSY; 1356 1205 1357 1206 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); 1358 - err = nft_trans_chain_add(&ctx, NFT_MSG_DELCHAIN); 1359 - if (err < 0) 1360 - return err; 1361 1207 1362 - table->use--; 1363 - list_del_rcu(&chain->list); 1364 - return 0; 1208 + return nft_delchain(&ctx); 1365 1209 } 1366 1210 1367 1211 /* ··· 1678 1532 return err; 1679 1533 } 1680 1534 1681 - static inline bool 1682 - nft_rule_is_active(struct net *net, const struct nft_rule *rule) 1683 - { 1684 - return (rule->genmask & (1 << net->nft.gencursor)) == 0; 1685 - } 1686 - 1687 - static inline int gencursor_next(struct net *net) 1688 - { 1689 - return net->nft.gencursor+1 == 1 ? 1 : 0; 1690 - } 1691 - 1692 - static inline int 1693 - nft_rule_is_active_next(struct net *net, const struct nft_rule *rule) 1694 - { 1695 - return (rule->genmask & (1 << gencursor_next(net))) == 0; 1696 - } 1697 - 1698 - static inline void 1699 - nft_rule_activate_next(struct net *net, struct nft_rule *rule) 1700 - { 1701 - /* Now inactive, will be active in the future */ 1702 - rule->genmask = (1 << net->nft.gencursor); 1703 - } 1704 - 1705 - static inline void 1706 - nft_rule_disactivate_next(struct net *net, struct nft_rule *rule) 1707 - { 1708 - rule->genmask = (1 << gencursor_next(net)); 1709 - } 1710 - 1711 - static inline void nft_rule_clear(struct net *net, struct nft_rule *rule) 1712 - { 1713 - rule->genmask = 0; 1714 - } 1715 - 1716 1535 static int nf_tables_dump_rules(struct sk_buff *skb, 1717 1536 struct netlink_callback *cb) 1718 1537 { ··· 1803 1692 kfree(rule); 1804 1693 } 1805 1694 1806 - static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type, 1807 - struct nft_rule *rule) 1808 - { 1809 - struct nft_trans *trans; 1810 - 1811 - trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule)); 1812 - if (trans == NULL) 1813 - return NULL; 1814 - 1815 - nft_trans_rule(trans) = rule; 1816 - list_add_tail(&trans->list, &ctx->net->nft.commit_list); 1817 - 1818 - return trans; 1819 - } 1820 - 1821 1695 #define NFT_RULE_MAXEXPRS 128 1822 1696 1823 1697 static struct nft_expr_info *info; ··· 1924 1828 err = -ENOMEM; 1925 1829 goto err2; 1926 1830 } 1927 - nft_rule_disactivate_next(net, old_rule); 1831 + nft_rule_deactivate_next(net, old_rule); 1928 1832 chain->use--; 1929 1833 list_add_tail_rcu(&rule->list, &old_rule->list); 1930 1834 } else { ··· 1966 1870 module_put(info[i].ops->type->owner); 1967 1871 } 1968 1872 return err; 1969 - } 1970 - 1971 - static int 1972 - nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) 1973 - { 1974 - /* You cannot delete the same rule twice */ 1975 - if (nft_rule_is_active_next(ctx->net, rule)) { 1976 - nft_rule_disactivate_next(ctx->net, rule); 1977 - ctx->chain->use--; 1978 - return 0; 1979 - } 1980 - return -ENOENT; 1981 - } 1982 - 1983 - static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule) 1984 - { 1985 - struct nft_trans *trans; 1986 - int err; 1987 - 1988 - trans = nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule); 1989 - if (trans == NULL) 1990 - return -ENOMEM; 1991 - 1992 - err = nf_tables_delrule_deactivate(ctx, rule); 1993 - if (err < 0) { 1994 - nft_trans_destroy(trans); 1995 - return err; 1996 - } 1997 - 1998 - return 0; 1999 - } 2000 - 2001 - static int nft_delrule_by_chain(struct nft_ctx *ctx) 2002 - { 2003 - struct nft_rule *rule; 2004 - int err; 2005 - 2006 - list_for_each_entry(rule, &ctx->chain->rules, list) { 2007 - err = nft_delrule(ctx, rule); 2008 - if (err < 0) 2009 - return err; 2010 - } 2011 - return 0; 2012 1873 } 2013 1874 2014 1875 static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb, ··· 2396 2343 return 0; 2397 2344 } 2398 2345 2399 - #define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */ 2400 - 2401 2346 static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, 2402 2347 const struct nlmsghdr *nlh, 2403 2348 const struct nlattr * const nla[]) ··· 2466 2415 2467 2416 if (da[NFTA_SET_DESC_SIZE] != NULL) 2468 2417 desc->size = ntohl(nla_get_be32(da[NFTA_SET_DESC_SIZE])); 2469 - 2470 - return 0; 2471 - } 2472 - 2473 - static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type, 2474 - struct nft_set *set) 2475 - { 2476 - struct nft_trans *trans; 2477 - 2478 - trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set)); 2479 - if (trans == NULL) 2480 - return -ENOMEM; 2481 - 2482 - if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) { 2483 - nft_trans_set_id(trans) = 2484 - ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID])); 2485 - set->flags |= NFT_SET_INACTIVE; 2486 - } 2487 - nft_trans_set(trans) = set; 2488 - list_add_tail(&trans->list, &ctx->net->nft.commit_list); 2489 2418 2490 2419 return 0; 2491 2420 } ··· 2663 2632 if (!list_empty(&set->bindings)) 2664 2633 return -EBUSY; 2665 2634 2666 - err = nft_trans_set_add(&ctx, NFT_MSG_DELSET, set); 2667 - if (err < 0) 2668 - return err; 2669 - 2670 - list_del_rcu(&set->list); 2671 - ctx.table->use--; 2672 - return 0; 2635 + return nft_delset(&ctx, set); 2673 2636 } 2674 2637 2675 2638 static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,