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

netfilter: nf_tables: do not reduce read-only expressions

Skip register tracking for expressions that perform read-only operations
on the registers. Define and use a cookie pointer NFT_REDUCE_READONLY to
avoid defining stubs for these expressions.

This patch re-enables register tracking which was disabled in ed5f85d42290
("netfilter: nf_tables: disable register tracking"). Follow up patches
add remaining register tracking for existing expressions.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+58 -1
+8
include/net/netfilter/nf_tables.h
··· 1633 1633 return net_generic(net, nf_tables_net_id); 1634 1634 } 1635 1635 1636 + #define __NFT_REDUCE_READONLY 1UL 1637 + #define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY 1638 + 1639 + static inline bool nft_reduce_is_readonly(const struct nft_expr *expr) 1640 + { 1641 + return expr->ops->reduce == NFT_REDUCE_READONLY; 1642 + } 1643 + 1636 1644 #endif /* _NET_NF_TABLES_H */
+1
net/bridge/netfilter/nft_reject_bridge.c
··· 185 185 .init = nft_reject_init, 186 186 .dump = nft_reject_dump, 187 187 .validate = nft_reject_bridge_validate, 188 + .reduce = NFT_REDUCE_READONLY, 188 189 }; 189 190 190 191 static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
+1
net/ipv4/netfilter/nft_dup_ipv4.c
··· 75 75 .eval = nft_dup_ipv4_eval, 76 76 .init = nft_dup_ipv4_init, 77 77 .dump = nft_dup_ipv4_dump, 78 + .reduce = NFT_REDUCE_READONLY, 78 79 }; 79 80 80 81 static const struct nla_policy nft_dup_ipv4_policy[NFTA_DUP_MAX + 1] = {
+1
net/ipv4/netfilter/nft_reject_ipv4.c
··· 45 45 .init = nft_reject_init, 46 46 .dump = nft_reject_dump, 47 47 .validate = nft_reject_validate, 48 + .reduce = NFT_REDUCE_READONLY, 48 49 }; 49 50 50 51 static struct nft_expr_type nft_reject_ipv4_type __read_mostly = {
+1
net/ipv6/netfilter/nft_dup_ipv6.c
··· 73 73 .eval = nft_dup_ipv6_eval, 74 74 .init = nft_dup_ipv6_init, 75 75 .dump = nft_dup_ipv6_dump, 76 + .reduce = NFT_REDUCE_READONLY, 76 77 }; 77 78 78 79 static const struct nla_policy nft_dup_ipv6_policy[NFTA_DUP_MAX + 1] = {
+1
net/ipv6/netfilter/nft_reject_ipv6.c
··· 46 46 .init = nft_reject_init, 47 47 .dump = nft_reject_dump, 48 48 .validate = nft_reject_validate, 49 + .reduce = NFT_REDUCE_READONLY, 49 50 }; 50 51 51 52 static struct nft_expr_type nft_reject_ipv6_type __read_mostly = {
+10 -1
net/netfilter/nf_tables_api.c
··· 8290 8290 static bool nft_expr_reduce(struct nft_regs_track *track, 8291 8291 const struct nft_expr *expr) 8292 8292 { 8293 - return false; 8293 + if (!expr->ops->reduce) { 8294 + pr_warn_once("missing reduce for expression %s ", 8295 + expr->ops->type->name); 8296 + return false; 8297 + } 8298 + 8299 + if (nft_reduce_is_readonly(expr)) 8300 + return false; 8301 + 8302 + return expr->ops->reduce(track, expr); 8294 8303 } 8295 8304 8296 8305 static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
+3
net/netfilter/nft_cmp.c
··· 193 193 .eval = nft_cmp_eval, 194 194 .init = nft_cmp_init, 195 195 .dump = nft_cmp_dump, 196 + .reduce = NFT_REDUCE_READONLY, 196 197 .offload = nft_cmp_offload, 197 198 }; 198 199 ··· 270 269 .eval = NULL, /* inlined */ 271 270 .init = nft_cmp_fast_init, 272 271 .dump = nft_cmp_fast_dump, 272 + .reduce = NFT_REDUCE_READONLY, 273 273 .offload = nft_cmp_fast_offload, 274 274 }; 275 275 ··· 361 359 .eval = NULL, /* inlined */ 362 360 .init = nft_cmp16_fast_init, 363 361 .dump = nft_cmp16_fast_dump, 362 + .reduce = NFT_REDUCE_READONLY, 364 363 .offload = nft_cmp16_fast_offload, 365 364 }; 366 365
+1
net/netfilter/nft_compat.c
··· 871 871 ops->dump = nft_target_dump; 872 872 ops->validate = nft_target_validate; 873 873 ops->data = target; 874 + ops->reduce = NFT_REDUCE_READONLY; 874 875 875 876 if (family == NFPROTO_BRIDGE) 876 877 ops->eval = nft_target_eval_bridge;
+1
net/netfilter/nft_connlimit.c
··· 257 257 .destroy_clone = nft_connlimit_destroy_clone, 258 258 .dump = nft_connlimit_dump, 259 259 .gc = nft_connlimit_gc, 260 + .reduce = NFT_REDUCE_READONLY, 260 261 }; 261 262 262 263 static struct nft_expr_type nft_connlimit_type __read_mostly = {
+1
net/netfilter/nft_counter.c
··· 293 293 .destroy_clone = nft_counter_destroy, 294 294 .dump = nft_counter_dump, 295 295 .clone = nft_counter_clone, 296 + .reduce = NFT_REDUCE_READONLY, 296 297 .offload = nft_counter_offload, 297 298 .offload_stats = nft_counter_offload_stats, 298 299 };
+1
net/netfilter/nft_ct.c
··· 785 785 .type = &nft_notrack_type, 786 786 .size = NFT_EXPR_SIZE(0), 787 787 .eval = nft_notrack_eval, 788 + .reduce = NFT_REDUCE_READONLY, 788 789 }; 789 790 790 791 static struct nft_expr_type nft_notrack_type __read_mostly = {
+1
net/netfilter/nft_dup_netdev.c
··· 79 79 .eval = nft_dup_netdev_eval, 80 80 .init = nft_dup_netdev_init, 81 81 .dump = nft_dup_netdev_dump, 82 + .reduce = NFT_REDUCE_READONLY, 82 83 .offload = nft_dup_netdev_offload, 83 84 .offload_action = nft_dup_netdev_offload_action, 84 85 };
+1
net/netfilter/nft_dynset.c
··· 413 413 .activate = nft_dynset_activate, 414 414 .deactivate = nft_dynset_deactivate, 415 415 .dump = nft_dynset_dump, 416 + .reduce = NFT_REDUCE_READONLY, 416 417 }; 417 418 418 419 struct nft_expr_type nft_dynset_type __read_mostly = {
+1
net/netfilter/nft_flow_offload.c
··· 441 441 .destroy = nft_flow_offload_destroy, 442 442 .validate = nft_flow_offload_validate, 443 443 .dump = nft_flow_offload_dump, 444 + .reduce = NFT_REDUCE_READONLY, 444 445 }; 445 446 446 447 static struct nft_expr_type nft_flow_offload_type __read_mostly = {
+2
net/netfilter/nft_fwd_netdev.c
··· 217 217 .init = nft_fwd_neigh_init, 218 218 .dump = nft_fwd_neigh_dump, 219 219 .validate = nft_fwd_validate, 220 + .reduce = NFT_REDUCE_READONLY, 220 221 }; 221 222 222 223 static const struct nft_expr_ops nft_fwd_netdev_ops = { ··· 227 226 .init = nft_fwd_netdev_init, 228 227 .dump = nft_fwd_netdev_dump, 229 228 .validate = nft_fwd_validate, 229 + .reduce = NFT_REDUCE_READONLY, 230 230 .offload = nft_fwd_netdev_offload, 231 231 .offload_action = nft_fwd_netdev_offload_action, 232 232 };
+1
net/netfilter/nft_last.c
··· 120 120 .destroy = nft_last_destroy, 121 121 .clone = nft_last_clone, 122 122 .dump = nft_last_dump, 123 + .reduce = NFT_REDUCE_READONLY, 123 124 }; 124 125 125 126 struct nft_expr_type nft_last_type __read_mostly = {
+2
net/netfilter/nft_limit.c
··· 225 225 .destroy = nft_limit_pkts_destroy, 226 226 .clone = nft_limit_pkts_clone, 227 227 .dump = nft_limit_pkts_dump, 228 + .reduce = NFT_REDUCE_READONLY, 228 229 }; 229 230 230 231 static void nft_limit_bytes_eval(const struct nft_expr *expr, ··· 280 279 .dump = nft_limit_bytes_dump, 281 280 .clone = nft_limit_bytes_clone, 282 281 .destroy = nft_limit_bytes_destroy, 282 + .reduce = NFT_REDUCE_READONLY, 283 283 }; 284 284 285 285 static const struct nft_expr_ops *
+1
net/netfilter/nft_log.c
··· 290 290 .init = nft_log_init, 291 291 .destroy = nft_log_destroy, 292 292 .dump = nft_log_dump, 293 + .reduce = NFT_REDUCE_READONLY, 293 294 }; 294 295 295 296 static struct nft_expr_type nft_log_type __read_mostly = {
+3
net/netfilter/nft_masq.c
··· 129 129 .destroy = nft_masq_ipv4_destroy, 130 130 .dump = nft_masq_dump, 131 131 .validate = nft_masq_validate, 132 + .reduce = NFT_REDUCE_READONLY, 132 133 }; 133 134 134 135 static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { ··· 176 175 .destroy = nft_masq_ipv6_destroy, 177 176 .dump = nft_masq_dump, 178 177 .validate = nft_masq_validate, 178 + .reduce = NFT_REDUCE_READONLY, 179 179 }; 180 180 181 181 static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { ··· 232 230 .destroy = nft_masq_inet_destroy, 233 231 .dump = nft_masq_dump, 234 232 .validate = nft_masq_validate, 233 + .reduce = NFT_REDUCE_READONLY, 235 234 }; 236 235 237 236 static struct nft_expr_type nft_masq_inet_type __read_mostly = {
+2
net/netfilter/nft_nat.c
··· 317 317 .destroy = nft_nat_destroy, 318 318 .dump = nft_nat_dump, 319 319 .validate = nft_nat_validate, 320 + .reduce = NFT_REDUCE_READONLY, 320 321 }; 321 322 322 323 static struct nft_expr_type nft_nat_type __read_mostly = { ··· 347 346 .destroy = nft_nat_destroy, 348 347 .dump = nft_nat_dump, 349 348 .validate = nft_nat_validate, 349 + .reduce = NFT_REDUCE_READONLY, 350 350 }; 351 351 352 352 static struct nft_expr_type nft_inet_nat_type __read_mostly = {
+2
net/netfilter/nft_objref.c
··· 91 91 .activate = nft_objref_activate, 92 92 .deactivate = nft_objref_deactivate, 93 93 .dump = nft_objref_dump, 94 + .reduce = NFT_REDUCE_READONLY, 94 95 }; 95 96 96 97 struct nft_objref_map { ··· 205 204 .deactivate = nft_objref_map_deactivate, 206 205 .destroy = nft_objref_map_destroy, 207 206 .dump = nft_objref_map_dump, 207 + .reduce = NFT_REDUCE_READONLY, 208 208 }; 209 209 210 210 static const struct nft_expr_ops *
+2
net/netfilter/nft_queue.c
··· 164 164 .eval = nft_queue_eval, 165 165 .init = nft_queue_init, 166 166 .dump = nft_queue_dump, 167 + .reduce = NFT_REDUCE_READONLY, 167 168 }; 168 169 169 170 static const struct nft_expr_ops nft_queue_sreg_ops = { ··· 173 172 .eval = nft_queue_sreg_eval, 174 173 .init = nft_queue_sreg_init, 175 174 .dump = nft_queue_sreg_dump, 175 + .reduce = NFT_REDUCE_READONLY, 176 176 }; 177 177 178 178 static const struct nft_expr_ops *
+1
net/netfilter/nft_quota.c
··· 254 254 .destroy = nft_quota_destroy, 255 255 .clone = nft_quota_clone, 256 256 .dump = nft_quota_dump, 257 + .reduce = NFT_REDUCE_READONLY, 257 258 }; 258 259 259 260 static struct nft_expr_type nft_quota_type __read_mostly = {
+1
net/netfilter/nft_range.c
··· 140 140 .eval = nft_range_eval, 141 141 .init = nft_range_init, 142 142 .dump = nft_range_dump, 143 + .reduce = NFT_REDUCE_READONLY, 143 144 }; 144 145 145 146 struct nft_expr_type nft_range_type __read_mostly = {
+3
net/netfilter/nft_redir.c
··· 134 134 .destroy = nft_redir_ipv4_destroy, 135 135 .dump = nft_redir_dump, 136 136 .validate = nft_redir_validate, 137 + .reduce = NFT_REDUCE_READONLY, 137 138 }; 138 139 139 140 static struct nft_expr_type nft_redir_ipv4_type __read_mostly = { ··· 184 183 .destroy = nft_redir_ipv6_destroy, 185 184 .dump = nft_redir_dump, 186 185 .validate = nft_redir_validate, 186 + .reduce = NFT_REDUCE_READONLY, 187 187 }; 188 188 189 189 static struct nft_expr_type nft_redir_ipv6_type __read_mostly = { ··· 227 225 .destroy = nft_redir_inet_destroy, 228 226 .dump = nft_redir_dump, 229 227 .validate = nft_redir_validate, 228 + .reduce = NFT_REDUCE_READONLY, 230 229 }; 231 230 232 231 static struct nft_expr_type nft_redir_inet_type __read_mostly = {
+1
net/netfilter/nft_reject_inet.c
··· 80 80 .init = nft_reject_init, 81 81 .dump = nft_reject_dump, 82 82 .validate = nft_reject_inet_validate, 83 + .reduce = NFT_REDUCE_READONLY, 83 84 }; 84 85 85 86 static struct nft_expr_type nft_reject_inet_type __read_mostly = {
+1
net/netfilter/nft_reject_netdev.c
··· 159 159 .init = nft_reject_init, 160 160 .dump = nft_reject_dump, 161 161 .validate = nft_reject_netdev_validate, 162 + .reduce = NFT_REDUCE_READONLY, 162 163 }; 163 164 164 165 static struct nft_expr_type nft_reject_netdev_type __read_mostly = {
+1
net/netfilter/nft_rt.c
··· 191 191 .init = nft_rt_get_init, 192 192 .dump = nft_rt_get_dump, 193 193 .validate = nft_rt_validate, 194 + .reduce = NFT_REDUCE_READONLY, 194 195 }; 195 196 196 197 struct nft_expr_type nft_rt_type __read_mostly = {
+1
net/netfilter/nft_synproxy.c
··· 288 288 .dump = nft_synproxy_dump, 289 289 .type = &nft_synproxy_type, 290 290 .validate = nft_synproxy_validate, 291 + .reduce = NFT_REDUCE_READONLY, 291 292 }; 292 293 293 294 static struct nft_expr_type nft_synproxy_type __read_mostly = {
+1
net/netfilter/nft_tproxy.c
··· 320 320 .init = nft_tproxy_init, 321 321 .destroy = nft_tproxy_destroy, 322 322 .dump = nft_tproxy_dump, 323 + .reduce = NFT_REDUCE_READONLY, 323 324 }; 324 325 325 326 static struct nft_expr_type nft_tproxy_type __read_mostly = {