With the previous patches in place, a netns nf_hook_list might be empty, even if e.g. init_net performs filtering. Thus change nf_hook_thresh to check the hook_list as well before initializing hook_state and calling nf_hook_slow(). We still make use of static keys; if no netfilter modules are loaded list is guaranteed to be empty.
Unified · Split
| @@ -141,22 +141,6 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg); · 140 unmodified lines | |||
| 141 | 141 | ||
| 142 | #ifdef HAVE_JUMP_LABEL | 142 | #ifdef HAVE_JUMP_LABEL |
| 143 | extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; | 143 | extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; |
| 144 | |||
| 145 | static inline bool nf_hook_list_active(struct list_head *hook_list, | ||
| 146 | u_int8_t pf, unsigned int hook) | ||
| 147 | { | ||
| 148 | if (__builtin_constant_p(pf) && | ||
| 149 | __builtin_constant_p(hook)) | ||
| 150 | return static_key_false(&nf_hooks_needed[pf][hook]); | ||
| 151 | |||
| 152 | return !list_empty(hook_list); | ||
| 153 | } | ||
| 154 | #else | ||
| 155 | static inline bool nf_hook_list_active(struct list_head *hook_list, | ||
| 156 | u_int8_t pf, unsigned int hook) | ||
| 157 | { | ||
| 158 | return !list_empty(hook_list); | ||
| 159 | } | ||
| 160 | #endif | 144 | #endif |
| 161 | 145 | ||
| 162 | int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state); | 146 | int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state); |
| @@ -177,9 +161,18 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, · 14 unmodified lines | |||
| 177 | int (*okfn)(struct net *, struct sock *, struct sk_buff *), | 161 | int (*okfn)(struct net *, struct sock *, struct sk_buff *), |
| 178 | int thresh) | 162 | int thresh) |
| 179 | { | 163 | { |
| 180 | struct list_head *hook_list = &net->nf.hooks[pf][hook]; | 164 | struct list_head *hook_list; |
| 165 | |||
| 166 | #ifdef HAVE_JUMP_LABEL | ||
| 167 | if (__builtin_constant_p(pf) && | ||
| 168 | __builtin_constant_p(hook) && | ||
| 169 | !static_key_false(&nf_hooks_needed[pf][hook])) | ||
| 170 | return 1; | ||
| 171 | #endif | ||
| 172 | |||
| 173 | hook_list = &net->nf.hooks[pf][hook]; | ||
| 181 | 174 | ||
| 182 | if (nf_hook_list_active(hook_list, pf, hook)) { | 175 | if (!list_empty(hook_list)) { |
| 183 | struct nf_hook_state state; | 176 | struct nf_hook_state state; |
| 184 | 177 | ||
| 185 | nf_hook_state_init(&state, hook_list, hook, thresh, | 178 | nf_hook_state_init(&state, hook_list, hook, thresh, |