blob: f8e1822f38d42d75f644fc26aae6e6a8ef5d7bb9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ebtables
3 *
4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * ebtables.c,v 2.0, July, 2002
8 *
9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
19#include <linux/kmod.h>
20#include <linux/module.h>
21#include <linux/vmalloc.h>
Jan Engelhardt18219d32008-10-08 11:35:13 +020022#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/netfilter_bridge/ebtables.h>
24#include <linux/spinlock.h>
Patrick McHardydf0933d2006-09-20 11:57:53 -070025#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/uaccess.h>
27#include <linux/smp.h>
David S. Millerc8923c62005-10-13 14:41:23 -070028#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <net/sock.h>
30/* needed for logical [in,out]-dev filtering */
31#include "../br_private.h"
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090034 "report to author: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* #define BUGPRINT(format, args...) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090037 ": out of memory: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038/* #define MEMPRINT(format, args...) */
39
40
41
42/*
43 * Each cpu has its own set of counters, so there is no need for write_lock in
44 * the softirq
45 * For reading or updating the counters, the user context needs to
46 * get a write_lock
47 */
48
49/* The size of each set of counters is altered to get cache alignment */
50#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
51#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
52#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
53 COUNTER_OFFSET(n) * cpu))
54
55
56
Ingo Molnar57b47a52006-03-20 22:35:41 -080057static DEFINE_MUTEX(ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058static LIST_HEAD(ebt_tables);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Jan Engelhardt043ef462008-10-08 11:35:15 +020060static struct xt_target ebt_standard_target = {
Jan Engelhardt001a18d2008-10-08 11:35:14 +020061 .name = "standard",
62 .revision = 0,
63 .family = NFPROTO_BRIDGE,
Jan Engelhardt043ef462008-10-08 11:35:15 +020064 .targetsize = sizeof(int),
Jan Engelhardt18219d32008-10-08 11:35:13 +020065};
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
Jan Engelhardt2d06d4a2008-10-08 11:35:15 +020068 struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 const struct net_device *out)
70{
Jan Engelhardt043ef462008-10-08 11:35:15 +020071 w->u.watcher->target(skb, in, out, hooknr, w->u.watcher, w->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 /* watchers don't give a verdict */
73 return 0;
74}
75
76static inline int ebt_do_match (struct ebt_entry_match *m,
Jan Engelhardtf7108a22008-10-08 11:35:18 +020077 const struct sk_buff *skb, struct xt_match_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
Jan Engelhardtf7108a22008-10-08 11:35:18 +020079 par->match = m->u.match;
80 par->matchinfo = m->data;
81 return m->u.match->match(skb, par);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082}
83
84static inline int ebt_dev_check(char *entry, const struct net_device *device)
85{
86 int i = 0;
Meelis Roos6f5b7ef2006-11-01 18:07:27 -080087 const char *devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89 if (*entry == '\0')
90 return 0;
91 if (!device)
92 return 1;
93 /* 1 is the wildcard token */
94 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
95 i++;
96 return (devname[i] != entry[i] && entry[i] != 1);
97}
98
99#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
100/* process standard matches */
101static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
102 const struct net_device *in, const struct net_device *out)
103{
104 int verdict, i;
105
106 if (e->bitmask & EBT_802_3) {
107 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
108 return 1;
109 } else if (!(e->bitmask & EBT_NOPROTO) &&
110 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
111 return 1;
112
113 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
114 return 1;
115 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
116 return 1;
117 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
118 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
119 return 1;
120 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
121 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
122 return 1;
123
124 if (e->bitmask & EBT_SOURCEMAC) {
125 verdict = 0;
126 for (i = 0; i < 6; i++)
127 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
128 e->sourcemsk[i];
129 if (FWINV2(verdict != 0, EBT_ISOURCE) )
130 return 1;
131 }
132 if (e->bitmask & EBT_DESTMAC) {
133 verdict = 0;
134 for (i = 0; i < 6; i++)
135 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
136 e->destmsk[i];
137 if (FWINV2(verdict != 0, EBT_IDEST) )
138 return 1;
139 }
140 return 0;
141}
142
143/* Do some firewalling */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700144unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 const struct net_device *in, const struct net_device *out,
146 struct ebt_table *table)
147{
148 int i, nentries;
149 struct ebt_entry *point;
150 struct ebt_counter *counter_base, *cb_base;
151 struct ebt_entry_target *t;
152 int verdict, sp = 0;
153 struct ebt_chainstack *cs;
154 struct ebt_entries *chaininfo;
155 char *base;
156 struct ebt_table_info *private;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200157 bool hotdrop = false;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200158 struct xt_match_param mtpar;
159
160 mtpar.in = in;
161 mtpar.out = out;
162 mtpar.hotdrop = &hotdrop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163
164 read_lock_bh(&table->lock);
165 private = table->private;
166 cb_base = COUNTER_BASE(private->counters, private->nentries,
167 smp_processor_id());
168 if (private->chainstack)
169 cs = private->chainstack[smp_processor_id()];
170 else
171 cs = NULL;
172 chaininfo = private->hook_entry[hook];
173 nentries = private->hook_entry[hook]->nentries;
174 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
175 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
176 /* base for chain jumps */
177 base = private->entries;
178 i = 0;
179 while (i < nentries) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700180 if (ebt_basic_match(point, eth_hdr(skb), in, out))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 goto letscontinue;
182
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200183 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 goto letscontinue;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200185 if (hotdrop) {
186 read_unlock_bh(&table->lock);
187 return NF_DROP;
188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* increase counter */
191 (*(counter_base + i)).pcnt++;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700192 (*(counter_base + i)).bcnt += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 /* these should only watch: not modify, nor tell us
195 what to do with the packet */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700196 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, hook, in,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 out);
198
199 t = (struct ebt_entry_target *)
200 (((char *)point) + point->target_offset);
201 /* standard target */
202 if (!t->u.target->target)
203 verdict = ((struct ebt_standard_target *)t)->verdict;
204 else
Jan Engelhardt2d06d4a2008-10-08 11:35:15 +0200205 verdict = t->u.target->target(skb, in, out, hook,
Jan Engelhardt043ef462008-10-08 11:35:15 +0200206 t->u.target, t->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 if (verdict == EBT_ACCEPT) {
208 read_unlock_bh(&table->lock);
209 return NF_ACCEPT;
210 }
211 if (verdict == EBT_DROP) {
212 read_unlock_bh(&table->lock);
213 return NF_DROP;
214 }
215 if (verdict == EBT_RETURN) {
216letsreturn:
217#ifdef CONFIG_NETFILTER_DEBUG
218 if (sp == 0) {
219 BUGPRINT("RETURN on base chain");
220 /* act like this is EBT_CONTINUE */
221 goto letscontinue;
222 }
223#endif
224 sp--;
225 /* put all the local variables right */
226 i = cs[sp].n;
227 chaininfo = cs[sp].chaininfo;
228 nentries = chaininfo->nentries;
229 point = cs[sp].e;
230 counter_base = cb_base +
231 chaininfo->counter_offset;
232 continue;
233 }
234 if (verdict == EBT_CONTINUE)
235 goto letscontinue;
236#ifdef CONFIG_NETFILTER_DEBUG
237 if (verdict < 0) {
238 BUGPRINT("bogus standard verdict\n");
239 read_unlock_bh(&table->lock);
240 return NF_DROP;
241 }
242#endif
243 /* jump to a udc */
244 cs[sp].n = i + 1;
245 cs[sp].chaininfo = chaininfo;
246 cs[sp].e = (struct ebt_entry *)
247 (((char *)point) + point->next_offset);
248 i = 0;
249 chaininfo = (struct ebt_entries *) (base + verdict);
250#ifdef CONFIG_NETFILTER_DEBUG
251 if (chaininfo->distinguisher) {
252 BUGPRINT("jump to non-chain\n");
253 read_unlock_bh(&table->lock);
254 return NF_DROP;
255 }
256#endif
257 nentries = chaininfo->nentries;
258 point = (struct ebt_entry *)chaininfo->data;
259 counter_base = cb_base + chaininfo->counter_offset;
260 sp++;
261 continue;
262letscontinue:
263 point = (struct ebt_entry *)
264 (((char *)point) + point->next_offset);
265 i++;
266 }
267
268 /* I actually like this :) */
269 if (chaininfo->policy == EBT_RETURN)
270 goto letsreturn;
271 if (chaininfo->policy == EBT_ACCEPT) {
272 read_unlock_bh(&table->lock);
273 return NF_ACCEPT;
274 }
275 read_unlock_bh(&table->lock);
276 return NF_DROP;
277}
278
279/* If it succeeds, returns element and locks mutex */
280static inline void *
281find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800282 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700284 struct {
285 struct list_head list;
286 char name[EBT_FUNCTION_MAXNAMELEN];
287 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Ingo Molnar57b47a52006-03-20 22:35:41 -0800289 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 if (*error != 0)
291 return NULL;
292
Patrick McHardydf0933d2006-09-20 11:57:53 -0700293 list_for_each_entry(e, head, list) {
294 if (strcmp(e->name, name) == 0)
295 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700297 *error = -ENOENT;
298 mutex_unlock(mutex);
299 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302#ifndef CONFIG_KMOD
303#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
304#else
305static void *
306find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800307 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
309 void *ret;
310
311 ret = find_inlist_lock_noload(head, name, error, mutex);
312 if (!ret) {
313 request_module("%s%s", prefix, name);
314 ret = find_inlist_lock_noload(head, name, error, mutex);
315 }
316 return ret;
317}
318#endif
319
320static inline struct ebt_table *
Ingo Molnar57b47a52006-03-20 22:35:41 -0800321find_table_lock(const char *name, int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322{
323 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
324}
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326static inline int
327ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
328 const char *name, unsigned int hookmask, unsigned int *cnt)
329{
Jan Engelhardt043ef462008-10-08 11:35:15 +0200330 struct xt_match *match;
Al Viro14197d52006-11-30 19:25:21 -0800331 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 int ret;
333
Al Viro14197d52006-11-30 19:25:21 -0800334 if (left < sizeof(struct ebt_entry_match) ||
335 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200337
338 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
339 m->u.name, 0), "ebt_%s", m->u.name);
340 if (IS_ERR(match))
341 return PTR_ERR(match);
342 if (match == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200344 m->u.match = match;
345
346 ret = xt_check_match(match, NFPROTO_BRIDGE, m->match_size,
Jan Engelhardt367c6792008-10-08 11:35:17 +0200347 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO,
348 e, m->data);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200349 if (ret < 0) {
350 module_put(match->me);
351 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 (*cnt)++;
355 return 0;
356}
357
358static inline int
359ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
360 const char *name, unsigned int hookmask, unsigned int *cnt)
361{
Jan Engelhardt043ef462008-10-08 11:35:15 +0200362 struct xt_target *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800363 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 int ret;
365
Al Viro14197d52006-11-30 19:25:21 -0800366 if (left < sizeof(struct ebt_entry_watcher) ||
367 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200369
370 watcher = try_then_request_module(
371 xt_find_target(NFPROTO_BRIDGE, w->u.name, 0),
372 "ebt_%s", w->u.name);
373 if (IS_ERR(watcher))
374 return PTR_ERR(watcher);
375 if (watcher == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200377 w->u.watcher = watcher;
378
379 ret = xt_check_target(watcher, NFPROTO_BRIDGE, w->watcher_size,
Jan Engelhardt367c6792008-10-08 11:35:17 +0200380 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO,
381 e, w->data);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200382 if (ret < 0) {
383 module_put(watcher->me);
384 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200386
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 (*cnt)++;
388 return 0;
389}
390
Al Viro70fe9af2006-11-30 19:26:14 -0800391static int ebt_verify_pointers(struct ebt_replace *repl,
392 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Al Viro70fe9af2006-11-30 19:26:14 -0800394 unsigned int limit = repl->entries_size;
395 unsigned int valid_hooks = repl->valid_hooks;
396 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 int i;
398
Al Viroe4fd77d2006-11-30 19:26:35 -0800399 for (i = 0; i < NF_BR_NUMHOOKS; i++)
400 newinfo->hook_entry[i] = NULL;
401
402 newinfo->entries_size = repl->entries_size;
403 newinfo->nentries = repl->nentries;
404
Al Viro70fe9af2006-11-30 19:26:14 -0800405 while (offset < limit) {
406 size_t left = limit - offset;
407 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800408
Al Viro70fe9af2006-11-30 19:26:14 -0800409 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 break;
Al Viro22b440b2006-11-30 19:25:51 -0800411
Al Viro70fe9af2006-11-30 19:26:14 -0800412 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
413 if ((valid_hooks & (1 << i)) == 0)
414 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800415 if ((char __user *)repl->hook_entry[i] ==
416 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800417 break;
418 }
419
420 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
421 if (e->bitmask != 0) {
422 /* we make userspace set this right,
423 so there is no misunderstanding */
424 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
425 "in distinguisher\n");
426 return -EINVAL;
427 }
428 if (i != NF_BR_NUMHOOKS)
429 newinfo->hook_entry[i] = (struct ebt_entries *)e;
430 if (left < sizeof(struct ebt_entries))
431 break;
432 offset += sizeof(struct ebt_entries);
433 } else {
434 if (left < sizeof(struct ebt_entry))
435 break;
436 if (left < e->next_offset)
437 break;
438 offset += e->next_offset;
439 }
440 }
441 if (offset != limit) {
442 BUGPRINT("entries_size too small\n");
443 return -EINVAL;
444 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800445
446 /* check if all valid hooks have a chain */
447 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
448 if (!newinfo->hook_entry[i] &&
449 (valid_hooks & (1 << i))) {
450 BUGPRINT("Valid hook without chain\n");
451 return -EINVAL;
452 }
453 }
Al Viro70fe9af2006-11-30 19:26:14 -0800454 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800455}
456
457/*
458 * this one is very careful, as it is the first function
459 * to parse the userspace data
460 */
461static inline int
462ebt_check_entry_size_and_hooks(struct ebt_entry *e,
Al Viro0e795532006-11-30 19:27:13 -0800463 struct ebt_table_info *newinfo,
464 unsigned int *n, unsigned int *cnt,
465 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800466{
Al Viro22b440b2006-11-30 19:25:51 -0800467 int i;
468
469 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800470 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800471 break;
472 }
473 /* beginning of a new chain
474 if i == NF_BR_NUMHOOKS it must be a user defined chain */
475 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 /* this checks if the previous chain has as many entries
477 as it said it has */
478 if (*n != *cnt) {
479 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900480 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 return -EINVAL;
482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
484 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
485 /* only RETURN from udc */
486 if (i != NF_BR_NUMHOOKS ||
487 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
488 BUGPRINT("bad policy\n");
489 return -EINVAL;
490 }
491 }
492 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
493 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
495 BUGPRINT("counter_offset != totalcnt");
496 return -EINVAL;
497 }
498 *n = ((struct ebt_entries *)e)->nentries;
499 *cnt = 0;
500 return 0;
501 }
502 /* a plain old entry, heh */
503 if (sizeof(struct ebt_entry) > e->watchers_offset ||
504 e->watchers_offset > e->target_offset ||
505 e->target_offset >= e->next_offset) {
506 BUGPRINT("entry offsets not in right order\n");
507 return -EINVAL;
508 }
509 /* this is not checked anywhere else */
510 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
511 BUGPRINT("target size too small\n");
512 return -EINVAL;
513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 (*cnt)++;
515 (*totalcnt)++;
516 return 0;
517}
518
519struct ebt_cl_stack
520{
521 struct ebt_chainstack cs;
522 int from;
523 unsigned int hookmask;
524};
525
526/*
527 * we need these positions to check that the jumps to a different part of the
528 * entries is a jump to the beginning of a new chain.
529 */
530static inline int
531ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800532 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
534 int i;
535
536 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800537 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return 0;
539 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
541 break;
542 }
543 /* only care about udc */
544 if (i != NF_BR_NUMHOOKS)
545 return 0;
546
547 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
548 /* these initialisations are depended on later in check_chainloops() */
549 udc[*n].cs.n = 0;
550 udc[*n].hookmask = 0;
551
552 (*n)++;
553 return 0;
554}
555
556static inline int
557ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
558{
559 if (i && (*i)-- == 0)
560 return 1;
561 if (m->u.match->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200562 m->u.match->destroy(m->u.match, m->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 module_put(m->u.match->me);
564
565 return 0;
566}
567
568static inline int
569ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
570{
571 if (i && (*i)-- == 0)
572 return 1;
573 if (w->u.watcher->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200574 w->u.watcher->destroy(w->u.watcher, w->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 module_put(w->u.watcher->me);
576
577 return 0;
578}
579
580static inline int
581ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
582{
583 struct ebt_entry_target *t;
584
Al Viro40642f92006-11-30 19:24:12 -0800585 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return 0;
587 /* we're done */
588 if (cnt && (*cnt)-- == 0)
589 return 1;
590 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
591 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
592 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
593 if (t->u.target->destroy)
Jan Engelhardt043ef462008-10-08 11:35:15 +0200594 t->u.target->destroy(t->u.target, t->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 module_put(t->u.target->me);
596
597 return 0;
598}
599
600static inline int
601ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800602 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
604{
605 struct ebt_entry_target *t;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200606 struct xt_target *target;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800608 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 int ret;
610
611 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800612 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 return 0;
614
615 if (e->bitmask & ~EBT_F_MASK) {
616 BUGPRINT("Unknown flag for bitmask\n");
617 return -EINVAL;
618 }
619 if (e->invflags & ~EBT_INV_MASK) {
620 BUGPRINT("Unknown flag for inv bitmask\n");
621 return -EINVAL;
622 }
623 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
624 BUGPRINT("NOPROTO & 802_3 not allowed\n");
625 return -EINVAL;
626 }
627 /* what hook do we belong to? */
628 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800629 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 continue;
631 if ((char *)newinfo->hook_entry[i] < (char *)e)
632 hook = i;
633 else
634 break;
635 }
636 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
637 a base chain */
638 if (i < NF_BR_NUMHOOKS)
639 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
640 else {
641 for (i = 0; i < udc_cnt; i++)
642 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
643 break;
644 if (i == 0)
645 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
646 else
647 hookmask = cl_s[i - 1].hookmask;
648 }
649 i = 0;
650 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
651 if (ret != 0)
652 goto cleanup_matches;
653 j = 0;
654 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
655 if (ret != 0)
656 goto cleanup_watchers;
657 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800658 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Jan Engelhardt043ef462008-10-08 11:35:15 +0200660 target = try_then_request_module(
661 xt_find_target(NFPROTO_BRIDGE, t->u.name, 0),
662 "ebt_%s", t->u.name);
663 if (IS_ERR(target)) {
664 ret = PTR_ERR(target);
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200665 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200666 } else if (target == NULL) {
667 ret = -ENOENT;
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200668 goto cleanup_watchers;
669 }
670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 t->u.target = target;
672 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800673 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 BUGPRINT("Standard target size too big\n");
675 ret = -EFAULT;
676 goto cleanup_watchers;
677 }
678 if (((struct ebt_standard_target *)t)->verdict <
679 -NUM_STANDARD_TARGETS) {
680 BUGPRINT("Invalid standard target\n");
681 ret = -EFAULT;
682 goto cleanup_watchers;
683 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200684 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
685 module_put(t->u.target->me);
686 ret = -EFAULT;
687 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200688 }
689
690 ret = xt_check_target(target, NFPROTO_BRIDGE, t->target_size,
Jan Engelhardt367c6792008-10-08 11:35:17 +0200691 name, hookmask, e->ethproto, e->invflags & EBT_IPROTO,
692 e, t->data);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200693 if (ret < 0) {
694 module_put(target->me);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200695 goto cleanup_watchers;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697 (*cnt)++;
698 return 0;
699cleanup_watchers:
700 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
701cleanup_matches:
702 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
703 return ret;
704}
705
706/*
707 * checks for loops and sets the hook mask for udc
708 * the hook mask for udc tells us from which base chains the udc can be
709 * accessed. This mask is a parameter to the check() functions of the extensions
710 */
711static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
712 unsigned int udc_cnt, unsigned int hooknr, char *base)
713{
714 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
715 struct ebt_entry *e = (struct ebt_entry *)chain->data;
716 struct ebt_entry_target *t;
717
718 while (pos < nentries || chain_nr != -1) {
719 /* end of udc, go back one 'recursion' step */
720 if (pos == nentries) {
721 /* put back values of the time when this chain was called */
722 e = cl_s[chain_nr].cs.e;
723 if (cl_s[chain_nr].from != -1)
724 nentries =
725 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
726 else
727 nentries = chain->nentries;
728 pos = cl_s[chain_nr].cs.n;
729 /* make sure we won't see a loop that isn't one */
730 cl_s[chain_nr].cs.n = 0;
731 chain_nr = cl_s[chain_nr].from;
732 if (pos == nentries)
733 continue;
734 }
735 t = (struct ebt_entry_target *)
736 (((char *)e) + e->target_offset);
737 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
738 goto letscontinue;
739 if (e->target_offset + sizeof(struct ebt_standard_target) >
740 e->next_offset) {
741 BUGPRINT("Standard target size too big\n");
742 return -1;
743 }
744 verdict = ((struct ebt_standard_target *)t)->verdict;
745 if (verdict >= 0) { /* jump to another chain */
746 struct ebt_entries *hlp2 =
747 (struct ebt_entries *)(base + verdict);
748 for (i = 0; i < udc_cnt; i++)
749 if (hlp2 == cl_s[i].cs.chaininfo)
750 break;
751 /* bad destination or loop */
752 if (i == udc_cnt) {
753 BUGPRINT("bad destination\n");
754 return -1;
755 }
756 if (cl_s[i].cs.n) {
757 BUGPRINT("loop\n");
758 return -1;
759 }
Al Viro98a08242006-11-30 19:24:49 -0800760 if (cl_s[i].hookmask & (1 << hooknr))
761 goto letscontinue;
762 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 cl_s[i].cs.n = pos + 1;
764 pos = 0;
765 cl_s[i].cs.e = ((void *)e + e->next_offset);
766 e = (struct ebt_entry *)(hlp2->data);
767 nentries = hlp2->nentries;
768 cl_s[i].from = chain_nr;
769 chain_nr = i;
770 /* this udc is accessible from the base chain for hooknr */
771 cl_s[i].hookmask |= (1 << hooknr);
772 continue;
773 }
774letscontinue:
775 e = (void *)e + e->next_offset;
776 pos++;
777 }
778 return 0;
779}
780
781/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Al Viro1bc23262006-11-30 19:28:08 -0800782static int translate_table(char *name, struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 unsigned int i, j, k, udc_cnt;
785 int ret;
786 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
787
788 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800789 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 i++;
791 if (i == NF_BR_NUMHOOKS) {
792 BUGPRINT("No valid hooks specified\n");
793 return -EINVAL;
794 }
Al Viro1f072c92006-11-30 19:26:53 -0800795 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 BUGPRINT("Chains don't start at beginning\n");
797 return -EINVAL;
798 }
799 /* make sure chains are ordered after each other in same order
800 as their corresponding hooks */
801 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800802 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800804 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 BUGPRINT("Hook order must be followed\n");
806 return -EINVAL;
807 }
808 i = j;
809 }
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 /* do some early checkings and initialize some things */
812 i = 0; /* holds the expected nr. of entries for the chain */
813 j = 0; /* holds the up to now counted entries for the chain */
814 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900815 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
817 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800818 ebt_check_entry_size_and_hooks, newinfo,
819 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 if (ret != 0)
822 return ret;
823
824 if (i != j) {
825 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900826 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return -EINVAL;
828 }
829 if (k != newinfo->nentries) {
830 BUGPRINT("Total nentries is wrong\n");
831 return -EINVAL;
832 }
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* get the location of the udc, put them in an array
835 while we're at it, allocate the chainstack */
836 if (udc_cnt) {
837 /* this will get free'd in do_replace()/ebt_register_table()
838 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700839 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800840 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 if (!newinfo->chainstack)
842 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700843 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700845 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if (!newinfo->chainstack[i]) {
847 while (i)
848 vfree(newinfo->chainstack[--i]);
849 vfree(newinfo->chainstack);
850 newinfo->chainstack = NULL;
851 return -ENOMEM;
852 }
853 }
854
Jayachandran C18bc89a2006-04-20 00:14:49 -0700855 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (!cl_s)
857 return -ENOMEM;
858 i = 0; /* the i'th udc */
859 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800860 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* sanity check */
862 if (i != udc_cnt) {
863 BUGPRINT("i != udc_cnt\n");
864 vfree(cl_s);
865 return -EFAULT;
866 }
867 }
868
869 /* Check for loops */
870 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800871 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if (check_chainloops(newinfo->hook_entry[i],
873 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700874 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return -EINVAL;
876 }
877
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200878 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 - the nr of entries in each chain is right
880 - the size of the allocated space is right
881 - all valid hooks have a corresponding chain
882 - there are no loops
883 - wrong data can still be on the level of a single entry
884 - could be there are jumps to places that are not the
885 beginning of a chain. This can only occur in chains that
886 are not accessible from any base chains, so we don't care. */
887
888 /* used to know what we need to clean up if something goes wrong */
889 i = 0;
890 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro1bc23262006-11-30 19:28:08 -0800891 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 if (ret != 0) {
893 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
894 ebt_cleanup_entry, &i);
895 }
James Lamanna68d31872005-06-22 22:12:57 -0700896 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 return ret;
898}
899
900/* called under write_lock */
901static void get_counters(struct ebt_counter *oldcounters,
902 struct ebt_counter *counters, unsigned int nentries)
903{
904 int i, cpu;
905 struct ebt_counter *counter_base;
906
907 /* counters of cpu 0 */
908 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700909 sizeof(struct ebt_counter) * nentries);
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700912 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700913 if (cpu == 0)
914 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
916 for (i = 0; i < nentries; i++) {
917 counters[i].pcnt += counter_base[i].pcnt;
918 counters[i].bcnt += counter_base[i].bcnt;
919 }
920 }
921}
922
923/* replace the table */
924static int do_replace(void __user *user, unsigned int len)
925{
926 int ret, i, countersize;
927 struct ebt_table_info *newinfo;
928 struct ebt_replace tmp;
929 struct ebt_table *t;
930 struct ebt_counter *counterstmp = NULL;
931 /* used to be able to unlock earlier */
932 struct ebt_table_info *table;
933
934 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
935 return -EFAULT;
936
937 if (len != sizeof(tmp) + tmp.entries_size) {
938 BUGPRINT("Wrong len argument\n");
939 return -EINVAL;
940 }
941
942 if (tmp.entries_size == 0) {
943 BUGPRINT("Entries_size never zero\n");
944 return -EINVAL;
945 }
Kirill Korotaevee4bb812006-02-04 02:16:56 -0800946 /* overflow check */
947 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
948 SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
949 return -ENOMEM;
950 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
951 return -ENOMEM;
952
Christoph Lameter53b8a312007-02-20 13:57:51 -0800953 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -0700954 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 if (!newinfo)
956 return -ENOMEM;
957
958 if (countersize)
959 memset(newinfo->counters, 0, countersize);
960
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800961 newinfo->entries = vmalloc(tmp.entries_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 if (!newinfo->entries) {
963 ret = -ENOMEM;
964 goto free_newinfo;
965 }
966 if (copy_from_user(
967 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
968 BUGPRINT("Couldn't copy entries from userspace\n");
969 ret = -EFAULT;
970 goto free_entries;
971 }
972
973 /* the user wants counters back
974 the check on the size is done later, when we have the lock */
975 if (tmp.num_counters) {
Jayachandran C18bc89a2006-04-20 00:14:49 -0700976 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (!counterstmp) {
978 ret = -ENOMEM;
979 goto free_entries;
980 }
981 }
982 else
983 counterstmp = NULL;
984
985 /* this can get initialized by translate_table() */
986 newinfo->chainstack = NULL;
Al Viro1bc23262006-11-30 19:28:08 -0800987 ret = ebt_verify_pointers(&tmp, newinfo);
988 if (ret != 0)
989 goto free_counterstmp;
990
991 ret = translate_table(tmp.name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 if (ret != 0)
994 goto free_counterstmp;
995
996 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
997 if (!t) {
998 ret = -ENOENT;
999 goto free_iterate;
1000 }
1001
1002 /* the table doesn't like it */
1003 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
1004 goto free_unlock;
1005
1006 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
1007 BUGPRINT("Wrong nr. of counters requested\n");
1008 ret = -EINVAL;
1009 goto free_unlock;
1010 }
1011
1012 /* we have the mutex lock, so no danger in reading this pointer */
1013 table = t->private;
1014 /* make sure the table can only be rmmod'ed if it contains no rules */
1015 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1016 ret = -ENOENT;
1017 goto free_unlock;
1018 } else if (table->nentries && !newinfo->nentries)
1019 module_put(t->me);
1020 /* we need an atomic snapshot of the counters */
1021 write_lock_bh(&t->lock);
1022 if (tmp.num_counters)
1023 get_counters(t->private->counters, counterstmp,
1024 t->private->nentries);
1025
1026 t->private = newinfo;
1027 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001028 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 /* so, a user can change the chains while having messed up her counter
1030 allocation. Only reason why this is done is because this way the lock
1031 is held only once, while this doesn't bring the kernel into a
1032 dangerous state. */
1033 if (tmp.num_counters &&
1034 copy_to_user(tmp.counters, counterstmp,
1035 tmp.num_counters * sizeof(struct ebt_counter))) {
1036 BUGPRINT("Couldn't copy counters to userspace\n");
1037 ret = -EFAULT;
1038 }
1039 else
1040 ret = 0;
1041
1042 /* decrease module count and free resources */
1043 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1044 ebt_cleanup_entry, NULL);
1045
1046 vfree(table->entries);
1047 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001048 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 vfree(table->chainstack[i]);
1050 vfree(table->chainstack);
1051 }
1052 vfree(table);
1053
James Lamanna68d31872005-06-22 22:12:57 -07001054 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return ret;
1056
1057free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001058 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059free_iterate:
1060 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1061 ebt_cleanup_entry, NULL);
1062free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001063 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 /* can be initialized in translate_table() */
1065 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001066 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 vfree(newinfo->chainstack[i]);
1068 vfree(newinfo->chainstack);
1069 }
1070free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001071 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001073 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return ret;
1075}
1076
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077int ebt_register_table(struct ebt_table *table)
1078{
1079 struct ebt_table_info *newinfo;
Patrick McHardydf0933d2006-09-20 11:57:53 -07001080 struct ebt_table *t;
Al Viro1e419cd2006-11-30 19:28:48 -08001081 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001083 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Al Virodf07a812006-11-30 19:28:25 -08001085 if (!table || !(repl = table->table) || !repl->entries ||
1086 repl->entries_size == 0 ||
1087 repl->counters || table->private) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1089 return -EINVAL;
1090 }
1091
Christoph Lameter53b8a312007-02-20 13:57:51 -08001092 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001093 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 ret = -ENOMEM;
1095 if (!newinfo)
1096 return -ENOMEM;
1097
Al Virodf07a812006-11-30 19:28:25 -08001098 p = vmalloc(repl->entries_size);
1099 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 goto free_newinfo;
1101
Al Virodf07a812006-11-30 19:28:25 -08001102 memcpy(p, repl->entries, repl->entries_size);
1103 newinfo->entries = p;
1104
1105 newinfo->entries_size = repl->entries_size;
1106 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 if (countersize)
1109 memset(newinfo->counters, 0, countersize);
1110
1111 /* fill in newinfo and parse the entries */
1112 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001113 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1114 if ((repl->valid_hooks & (1 << i)) == 0)
1115 newinfo->hook_entry[i] = NULL;
1116 else
1117 newinfo->hook_entry[i] = p +
1118 ((char *)repl->hook_entry[i] - repl->entries);
1119 }
1120 ret = translate_table(repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 if (ret != 0) {
1122 BUGPRINT("Translate_table failed\n");
1123 goto free_chainstack;
1124 }
1125
1126 if (table->check && table->check(newinfo, table->valid_hooks)) {
1127 BUGPRINT("The table doesn't like its own initial data, lol\n");
1128 return -EINVAL;
1129 }
1130
1131 table->private = newinfo;
1132 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001133 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 if (ret != 0)
1135 goto free_chainstack;
1136
Patrick McHardydf0933d2006-09-20 11:57:53 -07001137 list_for_each_entry(t, &ebt_tables, list) {
1138 if (strcmp(t->name, table->name) == 0) {
1139 ret = -EEXIST;
1140 BUGPRINT("Table name already exists\n");
1141 goto free_unlock;
1142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 }
1144
1145 /* Hold a reference count if the chains aren't empty */
1146 if (newinfo->nentries && !try_module_get(table->me)) {
1147 ret = -ENOENT;
1148 goto free_unlock;
1149 }
Patrick McHardydf0933d2006-09-20 11:57:53 -07001150 list_add(&table->list, &ebt_tables);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001151 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 return 0;
1153free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001154 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155free_chainstack:
1156 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001157 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 vfree(newinfo->chainstack[i]);
1159 vfree(newinfo->chainstack);
1160 }
1161 vfree(newinfo->entries);
1162free_newinfo:
1163 vfree(newinfo);
1164 return ret;
1165}
1166
1167void ebt_unregister_table(struct ebt_table *table)
1168{
1169 int i;
1170
1171 if (!table) {
1172 BUGPRINT("Request to unregister NULL table!!!\n");
1173 return;
1174 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001175 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001176 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001177 mutex_unlock(&ebt_mutex);
James Lamanna68d31872005-06-22 22:12:57 -07001178 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001180 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 vfree(table->private->chainstack[i]);
1182 vfree(table->private->chainstack);
1183 }
1184 vfree(table->private);
1185}
1186
1187/* userspace just supplied us with counters */
1188static int update_counters(void __user *user, unsigned int len)
1189{
1190 int i, ret;
1191 struct ebt_counter *tmp;
1192 struct ebt_replace hlp;
1193 struct ebt_table *t;
1194
1195 if (copy_from_user(&hlp, user, sizeof(hlp)))
1196 return -EFAULT;
1197
1198 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1199 return -EINVAL;
1200 if (hlp.num_counters == 0)
1201 return -EINVAL;
1202
Jayachandran C18bc89a2006-04-20 00:14:49 -07001203 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 MEMPRINT("Update_counters && nomemory\n");
1205 return -ENOMEM;
1206 }
1207
1208 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1209 if (!t)
1210 goto free_tmp;
1211
1212 if (hlp.num_counters != t->private->nentries) {
1213 BUGPRINT("Wrong nr of counters\n");
1214 ret = -EINVAL;
1215 goto unlock_mutex;
1216 }
1217
1218 if ( copy_from_user(tmp, hlp.counters,
1219 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1220 BUGPRINT("Updata_counters && !cfu\n");
1221 ret = -EFAULT;
1222 goto unlock_mutex;
1223 }
1224
1225 /* we want an atomic add of the counters */
1226 write_lock_bh(&t->lock);
1227
1228 /* we add to the counters of the first cpu */
1229 for (i = 0; i < hlp.num_counters; i++) {
1230 t->private->counters[i].pcnt += tmp[i].pcnt;
1231 t->private->counters[i].bcnt += tmp[i].bcnt;
1232 }
1233
1234 write_unlock_bh(&t->lock);
1235 ret = 0;
1236unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001237 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238free_tmp:
1239 vfree(tmp);
1240 return ret;
1241}
1242
1243static inline int ebt_make_matchname(struct ebt_entry_match *m,
Al Viro1e419cd2006-11-30 19:28:48 -08001244 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245{
Al Viro1e419cd2006-11-30 19:28:48 -08001246 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1248 return -EFAULT;
1249 return 0;
1250}
1251
1252static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
Al Viro1e419cd2006-11-30 19:28:48 -08001253 char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254{
Al Viro1e419cd2006-11-30 19:28:48 -08001255 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1257 return -EFAULT;
1258 return 0;
1259}
1260
Al Viro1e419cd2006-11-30 19:28:48 -08001261static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
1263 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001264 char __user *hlp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 struct ebt_entry_target *t;
1266
Al Viro40642f92006-11-30 19:24:12 -08001267 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 return 0;
1269
Al Viro1e419cd2006-11-30 19:28:48 -08001270 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1274 if (ret != 0)
1275 return ret;
1276 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1277 if (ret != 0)
1278 return ret;
1279 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1280 return -EFAULT;
1281 return 0;
1282}
1283
Ingo Molnar57b47a52006-03-20 22:35:41 -08001284/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1286 int *len, int cmd)
1287{
1288 struct ebt_replace tmp;
1289 struct ebt_counter *counterstmp, *oldcounters;
1290 unsigned int entries_size, nentries;
1291 char *entries;
1292
1293 if (cmd == EBT_SO_GET_ENTRIES) {
1294 entries_size = t->private->entries_size;
1295 nentries = t->private->nentries;
1296 entries = t->private->entries;
1297 oldcounters = t->private->counters;
1298 } else {
1299 entries_size = t->table->entries_size;
1300 nentries = t->table->nentries;
1301 entries = t->table->entries;
1302 oldcounters = t->table->counters;
1303 }
1304
1305 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1306 BUGPRINT("Cfu didn't work\n");
1307 return -EFAULT;
1308 }
1309
1310 if (*len != sizeof(struct ebt_replace) + entries_size +
1311 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1312 BUGPRINT("Wrong size\n");
1313 return -EINVAL;
1314 }
1315
1316 if (tmp.nentries != nentries) {
1317 BUGPRINT("Nentries wrong\n");
1318 return -EINVAL;
1319 }
1320
1321 if (tmp.entries_size != entries_size) {
1322 BUGPRINT("Wrong size\n");
1323 return -EINVAL;
1324 }
1325
1326 /* userspace might not need the counters */
1327 if (tmp.num_counters) {
1328 if (tmp.num_counters != nentries) {
1329 BUGPRINT("Num_counters wrong\n");
1330 return -EINVAL;
1331 }
Jayachandran C18bc89a2006-04-20 00:14:49 -07001332 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (!counterstmp) {
1334 MEMPRINT("Couldn't copy counters, out of memory\n");
1335 return -ENOMEM;
1336 }
1337 write_lock_bh(&t->lock);
1338 get_counters(oldcounters, counterstmp, nentries);
1339 write_unlock_bh(&t->lock);
1340
1341 if (copy_to_user(tmp.counters, counterstmp,
1342 nentries * sizeof(struct ebt_counter))) {
1343 BUGPRINT("Couldn't copy counters to userspace\n");
1344 vfree(counterstmp);
1345 return -EFAULT;
1346 }
1347 vfree(counterstmp);
1348 }
1349
1350 if (copy_to_user(tmp.entries, entries, entries_size)) {
1351 BUGPRINT("Couldn't copy entries to userspace\n");
1352 return -EFAULT;
1353 }
1354 /* set the match/watcher/target names right */
1355 return EBT_ENTRY_ITERATE(entries, entries_size,
1356 ebt_make_names, entries, tmp.entries);
1357}
1358
1359static int do_ebt_set_ctl(struct sock *sk,
1360 int cmd, void __user *user, unsigned int len)
1361{
1362 int ret;
1363
1364 switch(cmd) {
1365 case EBT_SO_SET_ENTRIES:
1366 ret = do_replace(user, len);
1367 break;
1368 case EBT_SO_SET_COUNTERS:
1369 ret = update_counters(user, len);
1370 break;
1371 default:
1372 ret = -EINVAL;
1373 }
1374 return ret;
1375}
1376
1377static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1378{
1379 int ret;
1380 struct ebt_replace tmp;
1381 struct ebt_table *t;
1382
1383 if (copy_from_user(&tmp, user, sizeof(tmp)))
1384 return -EFAULT;
1385
1386 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1387 if (!t)
1388 return ret;
1389
1390 switch(cmd) {
1391 case EBT_SO_GET_INFO:
1392 case EBT_SO_GET_INIT_INFO:
1393 if (*len != sizeof(struct ebt_replace)){
1394 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001395 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 break;
1397 }
1398 if (cmd == EBT_SO_GET_INFO) {
1399 tmp.nentries = t->private->nentries;
1400 tmp.entries_size = t->private->entries_size;
1401 tmp.valid_hooks = t->valid_hooks;
1402 } else {
1403 tmp.nentries = t->table->nentries;
1404 tmp.entries_size = t->table->entries_size;
1405 tmp.valid_hooks = t->table->valid_hooks;
1406 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001407 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 if (copy_to_user(user, &tmp, *len) != 0){
1409 BUGPRINT("c2u Didn't work\n");
1410 ret = -EFAULT;
1411 break;
1412 }
1413 ret = 0;
1414 break;
1415
1416 case EBT_SO_GET_ENTRIES:
1417 case EBT_SO_GET_INIT_ENTRIES:
1418 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001419 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 break;
1421
1422 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001423 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 ret = -EINVAL;
1425 }
1426
1427 return ret;
1428}
1429
1430static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08001431{
1432 .pf = PF_INET,
1433 .set_optmin = EBT_BASE_CTL,
1434 .set_optmax = EBT_SO_SET_MAX + 1,
1435 .set = do_ebt_set_ctl,
1436 .get_optmin = EBT_BASE_CTL,
1437 .get_optmax = EBT_SO_GET_MAX + 1,
1438 .get = do_ebt_get_ctl,
Neil Horman16fcec32007-09-11 11:28:26 +02001439 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440};
1441
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001442static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443{
1444 int ret;
1445
Jan Engelhardt043ef462008-10-08 11:35:15 +02001446 ret = xt_register_target(&ebt_standard_target);
1447 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 return ret;
Jan Engelhardt043ef462008-10-08 11:35:15 +02001449 ret = nf_register_sockopt(&ebt_sockopts);
1450 if (ret < 0) {
1451 xt_unregister_target(&ebt_standard_target);
1452 return ret;
1453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Patrick McHardya887c1c2007-07-14 20:46:15 -07001455 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 return 0;
1457}
1458
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001459static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
1461 nf_unregister_sockopt(&ebt_sockopts);
Jan Engelhardt043ef462008-10-08 11:35:15 +02001462 xt_unregister_target(&ebt_standard_target);
Patrick McHardya887c1c2007-07-14 20:46:15 -07001463 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464}
1465
1466EXPORT_SYMBOL(ebt_register_table);
1467EXPORT_SYMBOL(ebt_unregister_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08001469module_init(ebtables_init);
1470module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471MODULE_LICENSE("GPL");