Branch data Line data Source code
1 : : /* netfilter.c: look after the filters for various protocols.
2 : : * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
3 : : *
4 : : * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
5 : : * way.
6 : : *
7 : : * Rusty Russell (C)2000 -- This code is GPL.
8 : : * Patrick McHardy (c) 2006-2012
9 : : */
10 : : #include <linux/kernel.h>
11 : : #include <linux/netfilter.h>
12 : : #include <net/protocol.h>
13 : : #include <linux/init.h>
14 : : #include <linux/skbuff.h>
15 : : #include <linux/wait.h>
16 : : #include <linux/module.h>
17 : : #include <linux/interrupt.h>
18 : : #include <linux/if.h>
19 : : #include <linux/netdevice.h>
20 : : #include <linux/inetdevice.h>
21 : : #include <linux/proc_fs.h>
22 : : #include <linux/mutex.h>
23 : : #include <linux/slab.h>
24 : : #include <net/net_namespace.h>
25 : : #include <net/sock.h>
26 : :
27 : : #include "nf_internals.h"
28 : :
29 : : static DEFINE_MUTEX(afinfo_mutex);
30 : :
31 : : const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
32 : : EXPORT_SYMBOL(nf_afinfo);
33 : : const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
34 : : EXPORT_SYMBOL_GPL(nf_ipv6_ops);
35 : :
36 : 0 : int nf_register_afinfo(const struct nf_afinfo *afinfo)
37 : : {
38 : : int err;
39 : :
40 : 0 : err = mutex_lock_interruptible(&afinfo_mutex);
41 [ # # ]: 0 : if (err < 0)
42 : : return err;
43 : 0 : RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
44 : 0 : mutex_unlock(&afinfo_mutex);
45 : 0 : return 0;
46 : : }
47 : : EXPORT_SYMBOL_GPL(nf_register_afinfo);
48 : :
49 : 0 : void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
50 : : {
51 : 0 : mutex_lock(&afinfo_mutex);
52 : 0 : RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL);
53 : 0 : mutex_unlock(&afinfo_mutex);
54 : : synchronize_rcu();
55 : 0 : }
56 : : EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
57 : :
58 : : struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
59 : : EXPORT_SYMBOL(nf_hooks);
60 : :
61 : : #if defined(CONFIG_JUMP_LABEL)
62 : : struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
63 : : EXPORT_SYMBOL(nf_hooks_needed);
64 : : #endif
65 : :
66 : : static DEFINE_MUTEX(nf_hook_mutex);
67 : :
68 : 0 : int nf_register_hook(struct nf_hook_ops *reg)
69 : : {
70 : : struct nf_hook_ops *elem;
71 : : int err;
72 : :
73 : 0 : err = mutex_lock_interruptible(&nf_hook_mutex);
74 [ # # ]: 0 : if (err < 0)
75 : : return err;
76 [ # # ]: 0 : list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
77 [ # # ]: 0 : if (reg->priority < elem->priority)
78 : : break;
79 : : }
80 : 0 : list_add_rcu(®->list, elem->list.prev);
81 : 0 : mutex_unlock(&nf_hook_mutex);
82 : : #if defined(CONFIG_JUMP_LABEL)
83 : : static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
84 : : #endif
85 : 0 : return 0;
86 : : }
87 : : EXPORT_SYMBOL(nf_register_hook);
88 : :
89 : 0 : void nf_unregister_hook(struct nf_hook_ops *reg)
90 : : {
91 : 0 : mutex_lock(&nf_hook_mutex);
92 : : list_del_rcu(®->list);
93 : 0 : mutex_unlock(&nf_hook_mutex);
94 : : #if defined(CONFIG_JUMP_LABEL)
95 : : static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]);
96 : : #endif
97 : 0 : synchronize_net();
98 : 0 : }
99 : : EXPORT_SYMBOL(nf_unregister_hook);
100 : :
101 : 0 : int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
102 : : {
103 : : unsigned int i;
104 : : int err = 0;
105 : :
106 [ # # ]: 0 : for (i = 0; i < n; i++) {
107 : 0 : err = nf_register_hook(®[i]);
108 [ # # ]: 0 : if (err)
109 : : goto err;
110 : : }
111 : : return err;
112 : :
113 : : err:
114 [ # # ]: 0 : if (i > 0)
115 : : nf_unregister_hooks(reg, i);
116 : 0 : return err;
117 : : }
118 : : EXPORT_SYMBOL(nf_register_hooks);
119 : :
120 : 0 : void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
121 : : {
122 [ # # ][ # # ]: 0 : while (n-- > 0)
123 : 0 : nf_unregister_hook(®[n]);
124 : 0 : }
125 : : EXPORT_SYMBOL(nf_unregister_hooks);
126 : :
127 : 0 : unsigned int nf_iterate(struct list_head *head,
128 : : struct sk_buff *skb,
129 : : unsigned int hook,
130 : : const struct net_device *indev,
131 : : const struct net_device *outdev,
132 : : struct nf_hook_ops **elemp,
133 : : int (*okfn)(struct sk_buff *),
134 : : int hook_thresh)
135 : : {
136 : : unsigned int verdict;
137 : :
138 : : /*
139 : : * The caller must not block between calls to this
140 : : * function because of risk of continuing from deleted element.
141 : : */
142 [ # # ]: 0 : list_for_each_entry_continue_rcu((*elemp), head, list) {
143 [ # # ]: 0 : if (hook_thresh > (*elemp)->priority)
144 : 0 : continue;
145 : :
146 : : /* Optimization: we don't need to hold module
147 : : reference here, since function can't sleep. --RR */
148 : : repeat:
149 : 0 : verdict = (*elemp)->hook(*elemp, skb, indev, outdev, okfn);
150 [ # # ]: 0 : if (verdict != NF_ACCEPT) {
151 : : #ifdef CONFIG_NETFILTER_DEBUG
152 : : if (unlikely((verdict & NF_VERDICT_MASK)
153 : : > NF_MAX_VERDICT)) {
154 : : NFDEBUG("Evil return from %p(%u).\n",
155 : : (*elemp)->hook, hook);
156 : : continue;
157 : : }
158 : : #endif
159 [ # # ]: 0 : if (verdict != NF_REPEAT)
160 : : return verdict;
161 : : goto repeat;
162 : : }
163 : : }
164 : : return NF_ACCEPT;
165 : : }
166 : :
167 : :
168 : : /* Returns 1 if okfn() needs to be executed by the caller,
169 : : * -EPERM for NF_DROP, 0 otherwise. */
170 : 0 : int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
171 : : struct net_device *indev,
172 : : struct net_device *outdev,
173 : : int (*okfn)(struct sk_buff *),
174 : : int hook_thresh)
175 : : {
176 : : struct nf_hook_ops *elem;
177 : : unsigned int verdict;
178 : : int ret = 0;
179 : :
180 : : /* We may already have this, but read-locks nest anyway */
181 : : rcu_read_lock();
182 : :
183 : 0 : elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list);
184 : : next_hook:
185 : 0 : verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,
186 : : outdev, &elem, okfn, hook_thresh);
187 [ # # ]: 0 : if (verdict == NF_ACCEPT || verdict == NF_STOP) {
188 : : ret = 1;
189 [ # # ]: 0 : } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
190 : 0 : kfree_skb(skb);
191 : 0 : ret = NF_DROP_GETERR(verdict);
192 [ # # ]: 0 : if (ret == 0)
193 : : ret = -EPERM;
194 [ # # ]: 0 : } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
195 : 0 : int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
196 : : verdict >> NF_VERDICT_QBITS);
197 [ # # ]: 0 : if (err < 0) {
198 [ # # ]: 0 : if (err == -ECANCELED)
199 : : goto next_hook;
200 [ # # ][ # # ]: 0 : if (err == -ESRCH &&
201 : 0 : (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
202 : : goto next_hook;
203 : 0 : kfree_skb(skb);
204 : : }
205 : : }
206 : : rcu_read_unlock();
207 : 0 : return ret;
208 : : }
209 : : EXPORT_SYMBOL(nf_hook_slow);
210 : :
211 : :
212 : 0 : int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
213 : : {
214 [ # # ]: 0 : if (writable_len > skb->len)
215 : : return 0;
216 : :
217 : : /* Not exclusive use of packet? Must copy. */
218 [ # # ]: 0 : if (!skb_cloned(skb)) {
219 [ # # ]: 0 : if (writable_len <= skb_headlen(skb))
220 : : return 1;
221 [ # # ]: 0 : } else if (skb_clone_writable(skb, writable_len))
222 : : return 1;
223 : :
224 [ # # ]: 0 : if (writable_len <= skb_headlen(skb))
225 : : writable_len = 0;
226 : : else
227 : 0 : writable_len -= skb_headlen(skb);
228 : :
229 : 0 : return !!__pskb_pull_tail(skb, writable_len);
230 : : }
231 : : EXPORT_SYMBOL(skb_make_writable);
232 : :
233 : : #if IS_ENABLED(CONFIG_NF_CONNTRACK)
234 : : /* This does not belong here, but locally generated errors need it if connection
235 : : tracking in use: without this, connection may not be in hash table, and hence
236 : : manufactured ICMP or RST packets will not be associated with it. */
237 : : void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *)
238 : : __rcu __read_mostly;
239 : : EXPORT_SYMBOL(ip_ct_attach);
240 : :
241 : 0 : void nf_ct_attach(struct sk_buff *new, const struct sk_buff *skb)
242 : : {
243 : : void (*attach)(struct sk_buff *, const struct sk_buff *);
244 : :
245 [ # # ]: 0 : if (skb->nfct) {
246 : : rcu_read_lock();
247 : 0 : attach = rcu_dereference(ip_ct_attach);
248 [ # # ]: 0 : if (attach)
249 : 0 : attach(new, skb);
250 : : rcu_read_unlock();
251 : : }
252 : 0 : }
253 : : EXPORT_SYMBOL(nf_ct_attach);
254 : :
255 : : void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
256 : : EXPORT_SYMBOL(nf_ct_destroy);
257 : :
258 : 0 : void nf_conntrack_destroy(struct nf_conntrack *nfct)
259 : : {
260 : : void (*destroy)(struct nf_conntrack *);
261 : :
262 : : rcu_read_lock();
263 : 0 : destroy = rcu_dereference(nf_ct_destroy);
264 [ # # ]: 0 : BUG_ON(destroy == NULL);
265 : 0 : destroy(nfct);
266 : : rcu_read_unlock();
267 : 0 : }
268 : : EXPORT_SYMBOL(nf_conntrack_destroy);
269 : :
270 : : struct nfq_ct_hook __rcu *nfq_ct_hook __read_mostly;
271 : : EXPORT_SYMBOL_GPL(nfq_ct_hook);
272 : :
273 : : struct nfq_ct_nat_hook __rcu *nfq_ct_nat_hook __read_mostly;
274 : : EXPORT_SYMBOL_GPL(nfq_ct_nat_hook);
275 : :
276 : : #endif /* CONFIG_NF_CONNTRACK */
277 : :
278 : : #ifdef CONFIG_NF_NAT_NEEDED
279 : : void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
280 : : EXPORT_SYMBOL(nf_nat_decode_session_hook);
281 : : #endif
282 : :
283 : 0 : static int __net_init netfilter_net_init(struct net *net)
284 : : {
285 : : #ifdef CONFIG_PROC_FS
286 : 0 : net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
287 : : net->proc_net);
288 [ # # ]: 0 : if (!net->nf.proc_netfilter) {
289 : : if (!net_eq(net, &init_net))
290 : : pr_err("cannot create netfilter proc entry");
291 : :
292 : : return -ENOMEM;
293 : : }
294 : : #endif
295 : : return 0;
296 : : }
297 : :
298 : 0 : static void __net_exit netfilter_net_exit(struct net *net)
299 : : {
300 : 0 : remove_proc_entry("netfilter", net->proc_net);
301 : 0 : }
302 : :
303 : : static struct pernet_operations netfilter_net_ops = {
304 : : .init = netfilter_net_init,
305 : : .exit = netfilter_net_exit,
306 : : };
307 : :
308 : 0 : int __init netfilter_init(void)
309 : : {
310 : : int i, h, ret;
311 : :
312 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
313 [ # # ]: 0 : for (h = 0; h < NF_MAX_HOOKS; h++)
314 : 0 : INIT_LIST_HEAD(&nf_hooks[i][h]);
315 : : }
316 : :
317 : 0 : ret = register_pernet_subsys(&netfilter_net_ops);
318 [ # # ]: 0 : if (ret < 0)
319 : : goto err;
320 : :
321 : 0 : ret = netfilter_log_init();
322 [ # # ]: 0 : if (ret < 0)
323 : : goto err_pernet;
324 : :
325 : : return 0;
326 : : err_pernet:
327 : 0 : unregister_pernet_subsys(&netfilter_net_ops);
328 : : err:
329 : 0 : return ret;
330 : : }
|