blob: bcc102e3be4daa2c5f09ee27710cc5ed03b096fa [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 */
Jan Engelhardtff67e4e2010-03-19 21:08:16 +010017#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/kmod.h>
19#include <linux/module.h>
20#include <linux/vmalloc.h>
Jan Engelhardt18219d32008-10-08 11:35:13 +020021#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/netfilter_bridge/ebtables.h>
23#include <linux/spinlock.h>
Patrick McHardydf0933d2006-09-20 11:57:53 -070024#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.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
37/*
38 * Each cpu has its own set of counters, so there is no need for write_lock in
39 * the softirq
40 * For reading or updating the counters, the user context needs to
41 * get a write_lock
42 */
43
44/* The size of each set of counters is altered to get cache alignment */
45#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
46#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
47#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
48 COUNTER_OFFSET(n) * cpu))
49
50
51
Ingo Molnar57b47a52006-03-20 22:35:41 -080052static DEFINE_MUTEX(ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Florian Westphal81e675c2010-01-05 16:09:46 +010054#ifdef CONFIG_COMPAT
55static void ebt_standard_compat_from_user(void *dst, const void *src)
56{
57 int v = *(compat_int_t *)src;
58
59 if (v >= 0)
60 v += xt_compat_calc_jump(NFPROTO_BRIDGE, v);
61 memcpy(dst, &v, sizeof(v));
62}
63
64static int ebt_standard_compat_to_user(void __user *dst, const void *src)
65{
66 compat_int_t cv = *(int *)src;
67
68 if (cv >= 0)
69 cv -= xt_compat_calc_jump(NFPROTO_BRIDGE, cv);
70 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
71}
72#endif
73
74
Jan Engelhardt043ef462008-10-08 11:35:15 +020075static struct xt_target ebt_standard_target = {
Jan Engelhardt001a18d2008-10-08 11:35:14 +020076 .name = "standard",
77 .revision = 0,
78 .family = NFPROTO_BRIDGE,
Jan Engelhardt043ef462008-10-08 11:35:15 +020079 .targetsize = sizeof(int),
Florian Westphal81e675c2010-01-05 16:09:46 +010080#ifdef CONFIG_COMPAT
81 .compatsize = sizeof(compat_int_t),
82 .compat_from_user = ebt_standard_compat_from_user,
83 .compat_to_user = ebt_standard_compat_to_user,
84#endif
Jan Engelhardt18219d32008-10-08 11:35:13 +020085};
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Jan Engelhardt7eb35582008-10-08 11:35:19 +020087static inline int
88ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb,
Jan Engelhardtde74c162009-07-05 18:26:37 +020089 struct xt_action_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020091 par->target = w->u.watcher;
92 par->targinfo = w->data;
93 w->u.watcher->target(skb, par);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 /* watchers don't give a verdict */
95 return 0;
96}
97
Jan Engelhardtde74c162009-07-05 18:26:37 +020098static inline int
99ebt_do_match(struct ebt_entry_match *m, const struct sk_buff *skb,
100 struct xt_action_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101{
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200102 par->match = m->u.match;
103 par->matchinfo = m->data;
Jan Engelhardtd61ba9f2009-01-12 00:06:06 +0000104 return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105}
106
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200107static inline int
108ebt_dev_check(const char *entry, const struct net_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
110 int i = 0;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000111 const char *devname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 if (*entry == '\0')
114 return 0;
115 if (!device)
116 return 1;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000117 devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 /* 1 is the wildcard token */
119 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
120 i++;
121 return (devname[i] != entry[i] && entry[i] != 1);
122}
123
124#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
125/* process standard matches */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200126static inline int
127ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
128 const struct net_device *in, const struct net_device *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 int verdict, i;
131
132 if (e->bitmask & EBT_802_3) {
133 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
134 return 1;
135 } else if (!(e->bitmask & EBT_NOPROTO) &&
136 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
137 return 1;
138
139 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
140 return 1;
141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 return 1;
Jiri Pirkof350a0a2010-06-15 06:50:45 +0000143 /* rcu_read_lock()ed by nf_hook_slow */
144 if (in && br_port_exists(in) &&
145 FWINV2(ebt_dev_check(e->logical_in, br_port_get_rcu(in)->br->dev),
146 EBT_ILOGICALIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 return 1;
Jiri Pirkof350a0a2010-06-15 06:50:45 +0000148 if (out && br_port_exists(out) &&
149 FWINV2(ebt_dev_check(e->logical_out, br_port_get_rcu(out)->br->dev),
150 EBT_ILOGICALOUT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 return 1;
152
153 if (e->bitmask & EBT_SOURCEMAC) {
154 verdict = 0;
155 for (i = 0; i < 6; i++)
156 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
157 e->sourcemsk[i];
158 if (FWINV2(verdict != 0, EBT_ISOURCE) )
159 return 1;
160 }
161 if (e->bitmask & EBT_DESTMAC) {
162 verdict = 0;
163 for (i = 0; i < 6; i++)
164 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
165 e->destmsk[i];
166 if (FWINV2(verdict != 0, EBT_IDEST) )
167 return 1;
168 }
169 return 0;
170}
171
Jan Engelhardt98e86402009-04-15 21:06:05 +0200172static inline __pure
173struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)
174{
175 return (void *)entry + entry->next_offset;
176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/* Do some firewalling */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700179unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 const struct net_device *in, const struct net_device *out,
181 struct ebt_table *table)
182{
183 int i, nentries;
184 struct ebt_entry *point;
185 struct ebt_counter *counter_base, *cb_base;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200186 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 int verdict, sp = 0;
188 struct ebt_chainstack *cs;
189 struct ebt_entries *chaininfo;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200190 const char *base;
191 const struct ebt_table_info *private;
Jan Engelhardtde74c162009-07-05 18:26:37 +0200192 struct xt_action_param acpar;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200193
Jan Engelhardtde74c162009-07-05 18:26:37 +0200194 acpar.family = NFPROTO_BRIDGE;
195 acpar.in = in;
196 acpar.out = out;
Jan Engelhardtb4ba2612009-07-07 20:54:30 +0200197 acpar.hotdrop = false;
Jan Engelhardtde74c162009-07-05 18:26:37 +0200198 acpar.hooknum = hook;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200 read_lock_bh(&table->lock);
201 private = table->private;
202 cb_base = COUNTER_BASE(private->counters, private->nentries,
203 smp_processor_id());
204 if (private->chainstack)
205 cs = private->chainstack[smp_processor_id()];
206 else
207 cs = NULL;
208 chaininfo = private->hook_entry[hook];
209 nentries = private->hook_entry[hook]->nentries;
210 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
211 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
212 /* base for chain jumps */
213 base = private->entries;
214 i = 0;
215 while (i < nentries) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700216 if (ebt_basic_match(point, eth_hdr(skb), in, out))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 goto letscontinue;
218
Jan Engelhardtde74c162009-07-05 18:26:37 +0200219 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 goto letscontinue;
Jan Engelhardtb4ba2612009-07-07 20:54:30 +0200221 if (acpar.hotdrop) {
Jan Engelhardt5365f802008-10-08 11:35:16 +0200222 read_unlock_bh(&table->lock);
223 return NF_DROP;
224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 /* increase counter */
227 (*(counter_base + i)).pcnt++;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700228 (*(counter_base + i)).bcnt += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 /* these should only watch: not modify, nor tell us
231 what to do with the packet */
Jan Engelhardtde74c162009-07-05 18:26:37 +0200232 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234 t = (struct ebt_entry_target *)
235 (((char *)point) + point->target_offset);
236 /* standard target */
237 if (!t->u.target->target)
238 verdict = ((struct ebt_standard_target *)t)->verdict;
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200239 else {
Jan Engelhardtde74c162009-07-05 18:26:37 +0200240 acpar.target = t->u.target;
241 acpar.targinfo = t->data;
242 verdict = t->u.target->target(skb, &acpar);
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (verdict == EBT_ACCEPT) {
245 read_unlock_bh(&table->lock);
246 return NF_ACCEPT;
247 }
248 if (verdict == EBT_DROP) {
249 read_unlock_bh(&table->lock);
250 return NF_DROP;
251 }
252 if (verdict == EBT_RETURN) {
253letsreturn:
254#ifdef CONFIG_NETFILTER_DEBUG
255 if (sp == 0) {
256 BUGPRINT("RETURN on base chain");
257 /* act like this is EBT_CONTINUE */
258 goto letscontinue;
259 }
260#endif
261 sp--;
262 /* put all the local variables right */
263 i = cs[sp].n;
264 chaininfo = cs[sp].chaininfo;
265 nentries = chaininfo->nentries;
266 point = cs[sp].e;
267 counter_base = cb_base +
268 chaininfo->counter_offset;
269 continue;
270 }
271 if (verdict == EBT_CONTINUE)
272 goto letscontinue;
273#ifdef CONFIG_NETFILTER_DEBUG
274 if (verdict < 0) {
275 BUGPRINT("bogus standard verdict\n");
276 read_unlock_bh(&table->lock);
277 return NF_DROP;
278 }
279#endif
280 /* jump to a udc */
281 cs[sp].n = i + 1;
282 cs[sp].chaininfo = chaininfo;
Jan Engelhardt98e86402009-04-15 21:06:05 +0200283 cs[sp].e = ebt_next_entry(point);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 i = 0;
285 chaininfo = (struct ebt_entries *) (base + verdict);
286#ifdef CONFIG_NETFILTER_DEBUG
287 if (chaininfo->distinguisher) {
288 BUGPRINT("jump to non-chain\n");
289 read_unlock_bh(&table->lock);
290 return NF_DROP;
291 }
292#endif
293 nentries = chaininfo->nentries;
294 point = (struct ebt_entry *)chaininfo->data;
295 counter_base = cb_base + chaininfo->counter_offset;
296 sp++;
297 continue;
298letscontinue:
Jan Engelhardt98e86402009-04-15 21:06:05 +0200299 point = ebt_next_entry(point);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 i++;
301 }
302
303 /* I actually like this :) */
304 if (chaininfo->policy == EBT_RETURN)
305 goto letsreturn;
306 if (chaininfo->policy == EBT_ACCEPT) {
307 read_unlock_bh(&table->lock);
308 return NF_ACCEPT;
309 }
310 read_unlock_bh(&table->lock);
311 return NF_DROP;
312}
313
314/* If it succeeds, returns element and locks mutex */
315static inline void *
316find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800317 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700319 struct {
320 struct list_head list;
321 char name[EBT_FUNCTION_MAXNAMELEN];
322 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Ingo Molnar57b47a52006-03-20 22:35:41 -0800324 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 if (*error != 0)
326 return NULL;
327
Patrick McHardydf0933d2006-09-20 11:57:53 -0700328 list_for_each_entry(e, head, list) {
329 if (strcmp(e->name, name) == 0)
330 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700332 *error = -ENOENT;
333 mutex_unlock(mutex);
334 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335}
336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337static void *
338find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800339 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340{
Johannes Berg95a5afc2008-10-16 15:24:51 -0700341 return try_then_request_module(
342 find_inlist_lock_noload(head, name, error, mutex),
343 "%s%s", prefix, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346static inline struct ebt_table *
Alexey Dobriyan511061e2008-11-04 14:22:55 +0100347find_table_lock(struct net *net, const char *name, int *error,
348 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
Alexey Dobriyan511061e2008-11-04 14:22:55 +0100350 return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name,
351 "ebtable_", error, mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352}
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354static inline int
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200355ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
356 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200358 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200359 struct xt_match *match;
Al Viro14197d52006-11-30 19:25:21 -0800360 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 int ret;
362
Al Viro14197d52006-11-30 19:25:21 -0800363 if (left < sizeof(struct ebt_entry_match) ||
364 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200366
Jan Engelhardtfd0ec0e2009-07-10 19:27:47 +0200367 match = xt_request_find_match(NFPROTO_BRIDGE, m->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200368 if (IS_ERR(match))
369 return PTR_ERR(match);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200370 m->u.match = match;
371
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200372 par->match = match;
373 par->matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200374 ret = xt_check_match(par, m->match_size,
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200375 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200376 if (ret < 0) {
377 module_put(match->me);
378 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 (*cnt)++;
382 return 0;
383}
384
385static inline int
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200386ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
387 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200389 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200390 struct xt_target *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800391 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 int ret;
393
Al Viro14197d52006-11-30 19:25:21 -0800394 if (left < sizeof(struct ebt_entry_watcher) ||
395 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200397
Jan Engelhardtd2a7b6b2009-07-10 18:55:11 +0200398 watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200399 if (IS_ERR(watcher))
400 return PTR_ERR(watcher);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200401 w->u.watcher = watcher;
402
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200403 par->target = watcher;
404 par->targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200405 ret = xt_check_target(par, w->watcher_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200406 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200407 if (ret < 0) {
408 module_put(watcher->me);
409 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 (*cnt)++;
413 return 0;
414}
415
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200416static int ebt_verify_pointers(const struct ebt_replace *repl,
Al Viro70fe9af2006-11-30 19:26:14 -0800417 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Al Viro70fe9af2006-11-30 19:26:14 -0800419 unsigned int limit = repl->entries_size;
420 unsigned int valid_hooks = repl->valid_hooks;
421 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 int i;
423
Al Viroe4fd77d2006-11-30 19:26:35 -0800424 for (i = 0; i < NF_BR_NUMHOOKS; i++)
425 newinfo->hook_entry[i] = NULL;
426
427 newinfo->entries_size = repl->entries_size;
428 newinfo->nentries = repl->nentries;
429
Al Viro70fe9af2006-11-30 19:26:14 -0800430 while (offset < limit) {
431 size_t left = limit - offset;
432 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800433
Al Viro70fe9af2006-11-30 19:26:14 -0800434 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 break;
Al Viro22b440b2006-11-30 19:25:51 -0800436
Al Viro70fe9af2006-11-30 19:26:14 -0800437 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
438 if ((valid_hooks & (1 << i)) == 0)
439 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800440 if ((char __user *)repl->hook_entry[i] ==
441 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800442 break;
443 }
444
445 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
446 if (e->bitmask != 0) {
447 /* we make userspace set this right,
448 so there is no misunderstanding */
449 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
450 "in distinguisher\n");
451 return -EINVAL;
452 }
453 if (i != NF_BR_NUMHOOKS)
454 newinfo->hook_entry[i] = (struct ebt_entries *)e;
455 if (left < sizeof(struct ebt_entries))
456 break;
457 offset += sizeof(struct ebt_entries);
458 } else {
459 if (left < sizeof(struct ebt_entry))
460 break;
461 if (left < e->next_offset)
462 break;
Florian Westphal1756de22010-02-15 18:15:55 +0100463 if (e->next_offset < sizeof(struct ebt_entry))
464 return -EINVAL;
Al Viro70fe9af2006-11-30 19:26:14 -0800465 offset += e->next_offset;
466 }
467 }
468 if (offset != limit) {
469 BUGPRINT("entries_size too small\n");
470 return -EINVAL;
471 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800472
473 /* check if all valid hooks have a chain */
474 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
475 if (!newinfo->hook_entry[i] &&
476 (valid_hooks & (1 << i))) {
477 BUGPRINT("Valid hook without chain\n");
478 return -EINVAL;
479 }
480 }
Al Viro70fe9af2006-11-30 19:26:14 -0800481 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800482}
483
484/*
485 * this one is very careful, as it is the first function
486 * to parse the userspace data
487 */
488static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200489ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
490 const struct ebt_table_info *newinfo,
Al Viro0e795532006-11-30 19:27:13 -0800491 unsigned int *n, unsigned int *cnt,
492 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800493{
Al Viro22b440b2006-11-30 19:25:51 -0800494 int i;
495
496 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800497 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800498 break;
499 }
500 /* beginning of a new chain
501 if i == NF_BR_NUMHOOKS it must be a user defined chain */
502 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 /* this checks if the previous chain has as many entries
504 as it said it has */
505 if (*n != *cnt) {
506 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900507 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 return -EINVAL;
509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
511 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
512 /* only RETURN from udc */
513 if (i != NF_BR_NUMHOOKS ||
514 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
515 BUGPRINT("bad policy\n");
516 return -EINVAL;
517 }
518 }
519 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
520 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
522 BUGPRINT("counter_offset != totalcnt");
523 return -EINVAL;
524 }
525 *n = ((struct ebt_entries *)e)->nentries;
526 *cnt = 0;
527 return 0;
528 }
529 /* a plain old entry, heh */
530 if (sizeof(struct ebt_entry) > e->watchers_offset ||
531 e->watchers_offset > e->target_offset ||
532 e->target_offset >= e->next_offset) {
533 BUGPRINT("entry offsets not in right order\n");
534 return -EINVAL;
535 }
536 /* this is not checked anywhere else */
537 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
538 BUGPRINT("target size too small\n");
539 return -EINVAL;
540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 (*cnt)++;
542 (*totalcnt)++;
543 return 0;
544}
545
546struct ebt_cl_stack
547{
548 struct ebt_chainstack cs;
549 int from;
550 unsigned int hookmask;
551};
552
553/*
554 * we need these positions to check that the jumps to a different part of the
555 * entries is a jump to the beginning of a new chain.
556 */
557static inline int
558ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800559 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 int i;
562
563 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800564 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 return 0;
566 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
568 break;
569 }
570 /* only care about udc */
571 if (i != NF_BR_NUMHOOKS)
572 return 0;
573
574 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
575 /* these initialisations are depended on later in check_chainloops() */
576 udc[*n].cs.n = 0;
577 udc[*n].hookmask = 0;
578
579 (*n)++;
580 return 0;
581}
582
583static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100584ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200586 struct xt_mtdtor_param par;
587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (i && (*i)-- == 0)
589 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100591 par.net = net;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200592 par.match = m->u.match;
593 par.matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200594 par.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200595 if (par.match->destroy != NULL)
596 par.match->destroy(&par);
597 module_put(par.match->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 return 0;
599}
600
601static inline int
Patrick McHardyadd67462010-02-03 13:45:12 +0100602ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200604 struct xt_tgdtor_param par;
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (i && (*i)-- == 0)
607 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Patrick McHardyadd67462010-02-03 13:45:12 +0100609 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200610 par.target = w->u.watcher;
611 par.targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200612 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200613 if (par.target->destroy != NULL)
614 par.target->destroy(&par);
615 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return 0;
617}
618
619static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100620ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200622 struct xt_tgdtor_param par;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 struct ebt_entry_target *t;
624
Al Viro40642f92006-11-30 19:24:12 -0800625 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 return 0;
627 /* we're done */
628 if (cnt && (*cnt)-- == 0)
629 return 1;
Patrick McHardyadd67462010-02-03 13:45:12 +0100630 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL);
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100631 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Patrick McHardyadd67462010-02-03 13:45:12 +0100634 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200635 par.target = t->u.target;
636 par.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200637 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200638 if (par.target->destroy != NULL)
639 par.target->destroy(&par);
640 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return 0;
642}
643
644static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200645ebt_check_entry(struct ebt_entry *e, struct net *net,
646 const struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800647 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
649{
650 struct ebt_entry_target *t;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200651 struct xt_target *target;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800653 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 int ret;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200655 struct xt_mtchk_param mtpar;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200656 struct xt_tgchk_param tgpar;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800659 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 return 0;
661
662 if (e->bitmask & ~EBT_F_MASK) {
663 BUGPRINT("Unknown flag for bitmask\n");
664 return -EINVAL;
665 }
666 if (e->invflags & ~EBT_INV_MASK) {
667 BUGPRINT("Unknown flag for inv bitmask\n");
668 return -EINVAL;
669 }
670 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
671 BUGPRINT("NOPROTO & 802_3 not allowed\n");
672 return -EINVAL;
673 }
674 /* what hook do we belong to? */
675 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800676 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 continue;
678 if ((char *)newinfo->hook_entry[i] < (char *)e)
679 hook = i;
680 else
681 break;
682 }
683 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
684 a base chain */
685 if (i < NF_BR_NUMHOOKS)
686 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
687 else {
688 for (i = 0; i < udc_cnt; i++)
689 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
690 break;
691 if (i == 0)
692 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
693 else
694 hookmask = cl_s[i - 1].hookmask;
695 }
696 i = 0;
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200697
Patrick McHardyadd67462010-02-03 13:45:12 +0100698 mtpar.net = tgpar.net = net;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200699 mtpar.table = tgpar.table = name;
700 mtpar.entryinfo = tgpar.entryinfo = e;
701 mtpar.hook_mask = tgpar.hook_mask = hookmask;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200702 mtpar.family = tgpar.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200703 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 if (ret != 0)
705 goto cleanup_matches;
706 j = 0;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200707 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 if (ret != 0)
709 goto cleanup_watchers;
710 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800711 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Jan Engelhardtd2a7b6b2009-07-10 18:55:11 +0200713 target = xt_request_find_target(NFPROTO_BRIDGE, t->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200714 if (IS_ERR(target)) {
715 ret = PTR_ERR(target);
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200716 goto cleanup_watchers;
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200717 }
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 t->u.target = target;
720 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800721 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 BUGPRINT("Standard target size too big\n");
723 ret = -EFAULT;
724 goto cleanup_watchers;
725 }
726 if (((struct ebt_standard_target *)t)->verdict <
727 -NUM_STANDARD_TARGETS) {
728 BUGPRINT("Invalid standard target\n");
729 ret = -EFAULT;
730 goto cleanup_watchers;
731 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200732 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
733 module_put(t->u.target->me);
734 ret = -EFAULT;
735 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200736 }
737
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200738 tgpar.target = target;
739 tgpar.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200740 ret = xt_check_target(&tgpar, t->target_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200741 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200742 if (ret < 0) {
743 module_put(target->me);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200744 goto cleanup_watchers;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746 (*cnt)++;
747 return 0;
748cleanup_watchers:
Patrick McHardyadd67462010-02-03 13:45:12 +0100749 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750cleanup_matches:
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100751 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return ret;
753}
754
755/*
756 * checks for loops and sets the hook mask for udc
757 * the hook mask for udc tells us from which base chains the udc can be
758 * accessed. This mask is a parameter to the check() functions of the extensions
759 */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200760static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 unsigned int udc_cnt, unsigned int hooknr, char *base)
762{
763 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200764 const struct ebt_entry *e = (struct ebt_entry *)chain->data;
765 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
767 while (pos < nentries || chain_nr != -1) {
768 /* end of udc, go back one 'recursion' step */
769 if (pos == nentries) {
770 /* put back values of the time when this chain was called */
771 e = cl_s[chain_nr].cs.e;
772 if (cl_s[chain_nr].from != -1)
773 nentries =
774 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
775 else
776 nentries = chain->nentries;
777 pos = cl_s[chain_nr].cs.n;
778 /* make sure we won't see a loop that isn't one */
779 cl_s[chain_nr].cs.n = 0;
780 chain_nr = cl_s[chain_nr].from;
781 if (pos == nentries)
782 continue;
783 }
784 t = (struct ebt_entry_target *)
785 (((char *)e) + e->target_offset);
786 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
787 goto letscontinue;
788 if (e->target_offset + sizeof(struct ebt_standard_target) >
789 e->next_offset) {
790 BUGPRINT("Standard target size too big\n");
791 return -1;
792 }
793 verdict = ((struct ebt_standard_target *)t)->verdict;
794 if (verdict >= 0) { /* jump to another chain */
795 struct ebt_entries *hlp2 =
796 (struct ebt_entries *)(base + verdict);
797 for (i = 0; i < udc_cnt; i++)
798 if (hlp2 == cl_s[i].cs.chaininfo)
799 break;
800 /* bad destination or loop */
801 if (i == udc_cnt) {
802 BUGPRINT("bad destination\n");
803 return -1;
804 }
805 if (cl_s[i].cs.n) {
806 BUGPRINT("loop\n");
807 return -1;
808 }
Al Viro98a08242006-11-30 19:24:49 -0800809 if (cl_s[i].hookmask & (1 << hooknr))
810 goto letscontinue;
811 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 cl_s[i].cs.n = pos + 1;
813 pos = 0;
Jan Engelhardt98e86402009-04-15 21:06:05 +0200814 cl_s[i].cs.e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 e = (struct ebt_entry *)(hlp2->data);
816 nentries = hlp2->nentries;
817 cl_s[i].from = chain_nr;
818 chain_nr = i;
819 /* this udc is accessible from the base chain for hooknr */
820 cl_s[i].hookmask |= (1 << hooknr);
821 continue;
822 }
823letscontinue:
Jan Engelhardt98e86402009-04-15 21:06:05 +0200824 e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 pos++;
826 }
827 return 0;
828}
829
830/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200831static int translate_table(struct net *net, const char *name,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100832 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833{
834 unsigned int i, j, k, udc_cnt;
835 int ret;
836 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
837
838 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800839 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 i++;
841 if (i == NF_BR_NUMHOOKS) {
842 BUGPRINT("No valid hooks specified\n");
843 return -EINVAL;
844 }
Al Viro1f072c92006-11-30 19:26:53 -0800845 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 BUGPRINT("Chains don't start at beginning\n");
847 return -EINVAL;
848 }
849 /* make sure chains are ordered after each other in same order
850 as their corresponding hooks */
851 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800852 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800854 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 BUGPRINT("Hook order must be followed\n");
856 return -EINVAL;
857 }
858 i = j;
859 }
860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* do some early checkings and initialize some things */
862 i = 0; /* holds the expected nr. of entries for the chain */
863 j = 0; /* holds the up to now counted entries for the chain */
864 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900865 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
867 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800868 ebt_check_entry_size_and_hooks, newinfo,
869 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
871 if (ret != 0)
872 return ret;
873
874 if (i != j) {
875 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900876 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 return -EINVAL;
878 }
879 if (k != newinfo->nentries) {
880 BUGPRINT("Total nentries is wrong\n");
881 return -EINVAL;
882 }
883
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 /* get the location of the udc, put them in an array
885 while we're at it, allocate the chainstack */
886 if (udc_cnt) {
887 /* this will get free'd in do_replace()/ebt_register_table()
888 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700889 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800890 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 if (!newinfo->chainstack)
892 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700893 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700895 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 if (!newinfo->chainstack[i]) {
897 while (i)
898 vfree(newinfo->chainstack[--i]);
899 vfree(newinfo->chainstack);
900 newinfo->chainstack = NULL;
901 return -ENOMEM;
902 }
903 }
904
Jayachandran C18bc89a2006-04-20 00:14:49 -0700905 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 if (!cl_s)
907 return -ENOMEM;
908 i = 0; /* the i'th udc */
909 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800910 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 /* sanity check */
912 if (i != udc_cnt) {
913 BUGPRINT("i != udc_cnt\n");
914 vfree(cl_s);
915 return -EFAULT;
916 }
917 }
918
919 /* Check for loops */
920 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800921 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 if (check_chainloops(newinfo->hook_entry[i],
923 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700924 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 return -EINVAL;
926 }
927
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200928 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 - the nr of entries in each chain is right
930 - the size of the allocated space is right
931 - all valid hooks have a corresponding chain
932 - there are no loops
933 - wrong data can still be on the level of a single entry
934 - could be there are jumps to places that are not the
935 beginning of a chain. This can only occur in chains that
936 are not accessible from any base chains, so we don't care. */
937
938 /* used to know what we need to clean up if something goes wrong */
939 i = 0;
940 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100941 ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 if (ret != 0) {
943 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100944 ebt_cleanup_entry, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 }
James Lamanna68d31872005-06-22 22:12:57 -0700946 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 return ret;
948}
949
950/* called under write_lock */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200951static void get_counters(const struct ebt_counter *oldcounters,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 struct ebt_counter *counters, unsigned int nentries)
953{
954 int i, cpu;
955 struct ebt_counter *counter_base;
956
957 /* counters of cpu 0 */
958 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700959 sizeof(struct ebt_counter) * nentries);
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700962 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700963 if (cpu == 0)
964 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
966 for (i = 0; i < nentries; i++) {
967 counters[i].pcnt += counter_base[i].pcnt;
968 counters[i].bcnt += counter_base[i].bcnt;
969 }
970 }
971}
972
Florian Westphale7887592010-02-04 18:38:53 +0100973static int do_replace_finish(struct net *net, struct ebt_replace *repl,
974 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975{
Florian Westphale7887592010-02-04 18:38:53 +0100976 int ret, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 struct ebt_counter *counterstmp = NULL;
978 /* used to be able to unlock earlier */
979 struct ebt_table_info *table;
Florian Westphale7887592010-02-04 18:38:53 +0100980 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982 /* the user wants counters back
983 the check on the size is done later, when we have the lock */
Florian Westphale7887592010-02-04 18:38:53 +0100984 if (repl->num_counters) {
985 unsigned long size = repl->num_counters * sizeof(*counterstmp);
986 counterstmp = vmalloc(size);
987 if (!counterstmp)
988 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 newinfo->chainstack = NULL;
Florian Westphale7887592010-02-04 18:38:53 +0100992 ret = ebt_verify_pointers(repl, newinfo);
Al Viro1bc23262006-11-30 19:28:08 -0800993 if (ret != 0)
994 goto free_counterstmp;
995
Florian Westphale7887592010-02-04 18:38:53 +0100996 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 if (ret != 0)
999 goto free_counterstmp;
1000
Florian Westphale7887592010-02-04 18:38:53 +01001001 t = find_table_lock(net, repl->name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 if (!t) {
1003 ret = -ENOENT;
1004 goto free_iterate;
1005 }
1006
1007 /* the table doesn't like it */
Florian Westphale7887592010-02-04 18:38:53 +01001008 if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 goto free_unlock;
1010
Florian Westphale7887592010-02-04 18:38:53 +01001011 if (repl->num_counters && repl->num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 BUGPRINT("Wrong nr. of counters requested\n");
1013 ret = -EINVAL;
1014 goto free_unlock;
1015 }
1016
1017 /* we have the mutex lock, so no danger in reading this pointer */
1018 table = t->private;
1019 /* make sure the table can only be rmmod'ed if it contains no rules */
1020 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1021 ret = -ENOENT;
1022 goto free_unlock;
1023 } else if (table->nentries && !newinfo->nentries)
1024 module_put(t->me);
1025 /* we need an atomic snapshot of the counters */
1026 write_lock_bh(&t->lock);
Florian Westphale7887592010-02-04 18:38:53 +01001027 if (repl->num_counters)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 get_counters(t->private->counters, counterstmp,
1029 t->private->nentries);
1030
1031 t->private = newinfo;
1032 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001033 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 /* so, a user can change the chains while having messed up her counter
1035 allocation. Only reason why this is done is because this way the lock
1036 is held only once, while this doesn't bring the kernel into a
1037 dangerous state. */
Florian Westphale7887592010-02-04 18:38:53 +01001038 if (repl->num_counters &&
1039 copy_to_user(repl->counters, counterstmp,
1040 repl->num_counters * sizeof(struct ebt_counter))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 ret = -EFAULT;
1042 }
1043 else
1044 ret = 0;
1045
1046 /* decrease module count and free resources */
1047 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001048 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050 vfree(table->entries);
1051 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001052 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 vfree(table->chainstack[i]);
1054 vfree(table->chainstack);
1055 }
1056 vfree(table);
1057
James Lamanna68d31872005-06-22 22:12:57 -07001058 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 return ret;
1060
1061free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001062 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063free_iterate:
1064 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001065 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001067 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 /* can be initialized in translate_table() */
1069 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001070 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 vfree(newinfo->chainstack[i]);
1072 vfree(newinfo->chainstack);
1073 }
Florian Westphale7887592010-02-04 18:38:53 +01001074 return ret;
1075}
1076
1077/* replace the table */
1078static int do_replace(struct net *net, const void __user *user,
1079 unsigned int len)
1080{
1081 int ret, countersize;
1082 struct ebt_table_info *newinfo;
1083 struct ebt_replace tmp;
1084
1085 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1086 return -EFAULT;
1087
1088 if (len != sizeof(tmp) + tmp.entries_size) {
1089 BUGPRINT("Wrong len argument\n");
1090 return -EINVAL;
1091 }
1092
1093 if (tmp.entries_size == 0) {
1094 BUGPRINT("Entries_size never zero\n");
1095 return -EINVAL;
1096 }
1097 /* overflow check */
1098 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
1099 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
1100 return -ENOMEM;
1101 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
1102 return -ENOMEM;
1103
1104 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
1105 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1106 if (!newinfo)
1107 return -ENOMEM;
1108
1109 if (countersize)
1110 memset(newinfo->counters, 0, countersize);
1111
1112 newinfo->entries = vmalloc(tmp.entries_size);
1113 if (!newinfo->entries) {
1114 ret = -ENOMEM;
1115 goto free_newinfo;
1116 }
1117 if (copy_from_user(
1118 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
1119 BUGPRINT("Couldn't copy entries from userspace\n");
1120 ret = -EFAULT;
1121 goto free_entries;
1122 }
1123
1124 ret = do_replace_finish(net, &tmp, newinfo);
1125 if (ret == 0)
1126 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001128 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001130 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 return ret;
1132}
1133
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001134struct ebt_table *
1135ebt_register_table(struct net *net, const struct ebt_table *input_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 struct ebt_table_info *newinfo;
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001138 struct ebt_table *t, *table;
Al Viro1e419cd2006-11-30 19:28:48 -08001139 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001141 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001143 if (input_table == NULL || (repl = input_table->table) == NULL ||
1144 repl->entries == 0 || repl->entries_size == 0 ||
1145 repl->counters != NULL || input_table->private != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 BUGPRINT("Bad table data for ebt_register_table!!!\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001147 return ERR_PTR(-EINVAL);
1148 }
1149
1150 /* Don't add one table to multiple lists. */
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001151 table = kmemdup(input_table, sizeof(struct ebt_table), GFP_KERNEL);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001152 if (!table) {
1153 ret = -ENOMEM;
1154 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
1156
Christoph Lameter53b8a312007-02-20 13:57:51 -08001157 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001158 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 ret = -ENOMEM;
1160 if (!newinfo)
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001161 goto free_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Al Virodf07a812006-11-30 19:28:25 -08001163 p = vmalloc(repl->entries_size);
1164 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 goto free_newinfo;
1166
Al Virodf07a812006-11-30 19:28:25 -08001167 memcpy(p, repl->entries, repl->entries_size);
1168 newinfo->entries = p;
1169
1170 newinfo->entries_size = repl->entries_size;
1171 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
1173 if (countersize)
1174 memset(newinfo->counters, 0, countersize);
1175
1176 /* fill in newinfo and parse the entries */
1177 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001178 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1179 if ((repl->valid_hooks & (1 << i)) == 0)
1180 newinfo->hook_entry[i] = NULL;
1181 else
1182 newinfo->hook_entry[i] = p +
1183 ((char *)repl->hook_entry[i] - repl->entries);
1184 }
Alexey Dobriyana83d8e82010-01-18 08:21:13 +01001185 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 if (ret != 0) {
1187 BUGPRINT("Translate_table failed\n");
1188 goto free_chainstack;
1189 }
1190
1191 if (table->check && table->check(newinfo, table->valid_hooks)) {
1192 BUGPRINT("The table doesn't like its own initial data, lol\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001193 return ERR_PTR(-EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 }
1195
1196 table->private = newinfo;
1197 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001198 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 if (ret != 0)
1200 goto free_chainstack;
1201
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001202 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
Patrick McHardydf0933d2006-09-20 11:57:53 -07001203 if (strcmp(t->name, table->name) == 0) {
1204 ret = -EEXIST;
1205 BUGPRINT("Table name already exists\n");
1206 goto free_unlock;
1207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209
1210 /* Hold a reference count if the chains aren't empty */
1211 if (newinfo->nentries && !try_module_get(table->me)) {
1212 ret = -ENOENT;
1213 goto free_unlock;
1214 }
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001215 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001216 mutex_unlock(&ebt_mutex);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001217 return table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001219 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220free_chainstack:
1221 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001222 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 vfree(newinfo->chainstack[i]);
1224 vfree(newinfo->chainstack);
1225 }
1226 vfree(newinfo->entries);
1227free_newinfo:
1228 vfree(newinfo);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001229free_table:
1230 kfree(table);
1231out:
1232 return ERR_PTR(ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233}
1234
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001235void ebt_unregister_table(struct net *net, struct ebt_table *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
1237 int i;
1238
1239 if (!table) {
1240 BUGPRINT("Request to unregister NULL table!!!\n");
1241 return;
1242 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001243 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001244 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001245 mutex_unlock(&ebt_mutex);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001246 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001247 ebt_cleanup_entry, net, NULL);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001248 if (table->private->nentries)
1249 module_put(table->me);
James Lamanna68d31872005-06-22 22:12:57 -07001250 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001252 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 vfree(table->private->chainstack[i]);
1254 vfree(table->private->chainstack);
1255 }
1256 vfree(table->private);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001257 kfree(table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258}
1259
1260/* userspace just supplied us with counters */
Florian Westphal49facff2010-02-07 02:48:47 +01001261static int do_update_counters(struct net *net, const char *name,
1262 struct ebt_counter __user *counters,
1263 unsigned int num_counters,
1264 const void __user *user, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265{
1266 int i, ret;
1267 struct ebt_counter *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 struct ebt_table *t;
1269
Florian Westphal49facff2010-02-07 02:48:47 +01001270 if (num_counters == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return -EINVAL;
1272
Florian Westphal49facff2010-02-07 02:48:47 +01001273 tmp = vmalloc(num_counters * sizeof(*tmp));
1274 if (!tmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Florian Westphal49facff2010-02-07 02:48:47 +01001277 t = find_table_lock(net, name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 if (!t)
1279 goto free_tmp;
1280
Florian Westphal49facff2010-02-07 02:48:47 +01001281 if (num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 BUGPRINT("Wrong nr of counters\n");
1283 ret = -EINVAL;
1284 goto unlock_mutex;
1285 }
1286
Florian Westphal49facff2010-02-07 02:48:47 +01001287 if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 ret = -EFAULT;
1289 goto unlock_mutex;
1290 }
1291
1292 /* we want an atomic add of the counters */
1293 write_lock_bh(&t->lock);
1294
1295 /* we add to the counters of the first cpu */
Florian Westphal49facff2010-02-07 02:48:47 +01001296 for (i = 0; i < num_counters; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 t->private->counters[i].pcnt += tmp[i].pcnt;
1298 t->private->counters[i].bcnt += tmp[i].bcnt;
1299 }
1300
1301 write_unlock_bh(&t->lock);
1302 ret = 0;
1303unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001304 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305free_tmp:
1306 vfree(tmp);
1307 return ret;
1308}
1309
Florian Westphal49facff2010-02-07 02:48:47 +01001310static int update_counters(struct net *net, const void __user *user,
1311 unsigned int len)
1312{
1313 struct ebt_replace hlp;
1314
1315 if (copy_from_user(&hlp, user, sizeof(hlp)))
1316 return -EFAULT;
1317
1318 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1319 return -EINVAL;
1320
1321 return do_update_counters(net, hlp.name, hlp.counters,
1322 hlp.num_counters, user, len);
1323}
1324
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001325static inline int ebt_make_matchname(const struct ebt_entry_match *m,
1326 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327{
Al Viro1e419cd2006-11-30 19:28:48 -08001328 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1330 return -EFAULT;
1331 return 0;
1332}
1333
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001334static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
1335 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
Al Viro1e419cd2006-11-30 19:28:48 -08001337 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1339 return -EFAULT;
1340 return 0;
1341}
1342
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001343static inline int
1344ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
1346 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001347 char __user *hlp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001348 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Al Viro40642f92006-11-30 19:24:12 -08001350 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return 0;
1352
Al Viro1e419cd2006-11-30 19:28:48 -08001353 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1357 if (ret != 0)
1358 return ret;
1359 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1360 if (ret != 0)
1361 return ret;
1362 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1363 return -EFAULT;
1364 return 0;
1365}
1366
Florian Westphal837395a2010-02-07 02:11:34 +01001367static int copy_counters_to_user(struct ebt_table *t,
1368 const struct ebt_counter *oldcounters,
1369 void __user *user, unsigned int num_counters,
1370 unsigned int nentries)
1371{
1372 struct ebt_counter *counterstmp;
1373 int ret = 0;
1374
1375 /* userspace might not need the counters */
1376 if (num_counters == 0)
1377 return 0;
1378
1379 if (num_counters != nentries) {
1380 BUGPRINT("Num_counters wrong\n");
1381 return -EINVAL;
1382 }
1383
1384 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1385 if (!counterstmp)
1386 return -ENOMEM;
1387
1388 write_lock_bh(&t->lock);
1389 get_counters(oldcounters, counterstmp, nentries);
1390 write_unlock_bh(&t->lock);
1391
1392 if (copy_to_user(user, counterstmp,
1393 nentries * sizeof(struct ebt_counter)))
1394 ret = -EFAULT;
1395 vfree(counterstmp);
1396 return ret;
1397}
1398
Ingo Molnar57b47a52006-03-20 22:35:41 -08001399/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400static int copy_everything_to_user(struct ebt_table *t, void __user *user,
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001401 const int *len, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402{
1403 struct ebt_replace tmp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001404 const struct ebt_counter *oldcounters;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 unsigned int entries_size, nentries;
Florian Westphal837395a2010-02-07 02:11:34 +01001406 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 char *entries;
1408
1409 if (cmd == EBT_SO_GET_ENTRIES) {
1410 entries_size = t->private->entries_size;
1411 nentries = t->private->nentries;
1412 entries = t->private->entries;
1413 oldcounters = t->private->counters;
1414 } else {
1415 entries_size = t->table->entries_size;
1416 nentries = t->table->nentries;
1417 entries = t->table->entries;
1418 oldcounters = t->table->counters;
1419 }
1420
Florian Westphal90b89af2010-02-07 03:19:12 +01001421 if (copy_from_user(&tmp, user, sizeof(tmp)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
1424 if (*len != sizeof(struct ebt_replace) + entries_size +
Florian Westphal90b89af2010-02-07 03:19:12 +01001425 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
1428 if (tmp.nentries != nentries) {
1429 BUGPRINT("Nentries wrong\n");
1430 return -EINVAL;
1431 }
1432
1433 if (tmp.entries_size != entries_size) {
1434 BUGPRINT("Wrong size\n");
1435 return -EINVAL;
1436 }
1437
Florian Westphal837395a2010-02-07 02:11:34 +01001438 ret = copy_counters_to_user(t, oldcounters, tmp.counters,
1439 tmp.num_counters, nentries);
1440 if (ret)
1441 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
1443 if (copy_to_user(tmp.entries, entries, entries_size)) {
1444 BUGPRINT("Couldn't copy entries to userspace\n");
1445 return -EFAULT;
1446 }
1447 /* set the match/watcher/target names right */
1448 return EBT_ENTRY_ITERATE(entries, entries_size,
1449 ebt_make_names, entries, tmp.entries);
1450}
1451
1452static int do_ebt_set_ctl(struct sock *sk,
1453 int cmd, void __user *user, unsigned int len)
1454{
1455 int ret;
1456
Florian Westphaldce766a2010-01-08 17:31:24 +01001457 if (!capable(CAP_NET_ADMIN))
1458 return -EPERM;
1459
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 switch(cmd) {
1461 case EBT_SO_SET_ENTRIES:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001462 ret = do_replace(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 break;
1464 case EBT_SO_SET_COUNTERS:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001465 ret = update_counters(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 break;
1467 default:
1468 ret = -EINVAL;
Florian Westphal81e675c2010-01-05 16:09:46 +01001469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return ret;
1471}
1472
1473static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1474{
1475 int ret;
1476 struct ebt_replace tmp;
1477 struct ebt_table *t;
1478
Florian Westphaldce766a2010-01-08 17:31:24 +01001479 if (!capable(CAP_NET_ADMIN))
1480 return -EPERM;
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 if (copy_from_user(&tmp, user, sizeof(tmp)))
1483 return -EFAULT;
1484
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001485 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 if (!t)
1487 return ret;
1488
1489 switch(cmd) {
1490 case EBT_SO_GET_INFO:
1491 case EBT_SO_GET_INIT_INFO:
1492 if (*len != sizeof(struct ebt_replace)){
1493 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001494 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 break;
1496 }
1497 if (cmd == EBT_SO_GET_INFO) {
1498 tmp.nentries = t->private->nentries;
1499 tmp.entries_size = t->private->entries_size;
1500 tmp.valid_hooks = t->valid_hooks;
1501 } else {
1502 tmp.nentries = t->table->nentries;
1503 tmp.entries_size = t->table->entries_size;
1504 tmp.valid_hooks = t->table->valid_hooks;
1505 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001506 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 if (copy_to_user(user, &tmp, *len) != 0){
1508 BUGPRINT("c2u Didn't work\n");
1509 ret = -EFAULT;
1510 break;
1511 }
1512 ret = 0;
1513 break;
1514
1515 case EBT_SO_GET_ENTRIES:
1516 case EBT_SO_GET_INIT_ENTRIES:
1517 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001518 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520
1521 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001522 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 ret = -EINVAL;
1524 }
1525
1526 return ret;
1527}
1528
Florian Westphal81e675c2010-01-05 16:09:46 +01001529#ifdef CONFIG_COMPAT
1530/* 32 bit-userspace compatibility definitions. */
1531struct compat_ebt_replace {
1532 char name[EBT_TABLE_MAXNAMELEN];
1533 compat_uint_t valid_hooks;
1534 compat_uint_t nentries;
1535 compat_uint_t entries_size;
1536 /* start of the chains */
1537 compat_uptr_t hook_entry[NF_BR_NUMHOOKS];
1538 /* nr of counters userspace expects back */
1539 compat_uint_t num_counters;
1540 /* where the kernel will put the old counters. */
1541 compat_uptr_t counters;
1542 compat_uptr_t entries;
1543};
1544
1545/* struct ebt_entry_match, _target and _watcher have same layout */
1546struct compat_ebt_entry_mwt {
1547 union {
1548 char name[EBT_FUNCTION_MAXNAMELEN];
1549 compat_uptr_t ptr;
1550 } u;
1551 compat_uint_t match_size;
1552 compat_uint_t data[0];
1553};
1554
1555/* account for possible padding between match_size and ->data */
1556static int ebt_compat_entry_padsize(void)
1557{
1558 BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
1559 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
1560 return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
1561 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
1562}
1563
1564static int ebt_compat_match_offset(const struct xt_match *match,
1565 unsigned int userlen)
1566{
1567 /*
1568 * ebt_among needs special handling. The kernel .matchsize is
1569 * set to -1 at registration time; at runtime an EBT_ALIGN()ed
1570 * value is expected.
1571 * Example: userspace sends 4500, ebt_among.c wants 4504.
1572 */
1573 if (unlikely(match->matchsize == -1))
1574 return XT_ALIGN(userlen) - COMPAT_XT_ALIGN(userlen);
1575 return xt_compat_match_offset(match);
1576}
1577
1578static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
1579 unsigned int *size)
1580{
1581 const struct xt_match *match = m->u.match;
1582 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1583 int off = ebt_compat_match_offset(match, m->match_size);
1584 compat_uint_t msize = m->match_size - off;
1585
1586 BUG_ON(off >= m->match_size);
1587
1588 if (copy_to_user(cm->u.name, match->name,
1589 strlen(match->name) + 1) || put_user(msize, &cm->match_size))
1590 return -EFAULT;
1591
1592 if (match->compat_to_user) {
1593 if (match->compat_to_user(cm->data, m->data))
1594 return -EFAULT;
1595 } else if (copy_to_user(cm->data, m->data, msize))
1596 return -EFAULT;
1597
1598 *size -= ebt_compat_entry_padsize() + off;
1599 *dstptr = cm->data;
1600 *dstptr += msize;
1601 return 0;
1602}
1603
1604static int compat_target_to_user(struct ebt_entry_target *t,
1605 void __user **dstptr,
1606 unsigned int *size)
1607{
1608 const struct xt_target *target = t->u.target;
1609 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1610 int off = xt_compat_target_offset(target);
1611 compat_uint_t tsize = t->target_size - off;
1612
1613 BUG_ON(off >= t->target_size);
1614
1615 if (copy_to_user(cm->u.name, target->name,
1616 strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
1617 return -EFAULT;
1618
1619 if (target->compat_to_user) {
1620 if (target->compat_to_user(cm->data, t->data))
1621 return -EFAULT;
1622 } else if (copy_to_user(cm->data, t->data, tsize))
1623 return -EFAULT;
1624
1625 *size -= ebt_compat_entry_padsize() + off;
1626 *dstptr = cm->data;
1627 *dstptr += tsize;
1628 return 0;
1629}
1630
1631static int compat_watcher_to_user(struct ebt_entry_watcher *w,
1632 void __user **dstptr,
1633 unsigned int *size)
1634{
1635 return compat_target_to_user((struct ebt_entry_target *)w,
1636 dstptr, size);
1637}
1638
1639static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr,
1640 unsigned int *size)
1641{
1642 struct ebt_entry_target *t;
1643 struct ebt_entry __user *ce;
1644 u32 watchers_offset, target_offset, next_offset;
1645 compat_uint_t origsize;
1646 int ret;
1647
1648 if (e->bitmask == 0) {
1649 if (*size < sizeof(struct ebt_entries))
1650 return -EINVAL;
1651 if (copy_to_user(*dstptr, e, sizeof(struct ebt_entries)))
1652 return -EFAULT;
1653
1654 *dstptr += sizeof(struct ebt_entries);
1655 *size -= sizeof(struct ebt_entries);
1656 return 0;
1657 }
1658
1659 if (*size < sizeof(*ce))
1660 return -EINVAL;
1661
1662 ce = (struct ebt_entry __user *)*dstptr;
1663 if (copy_to_user(ce, e, sizeof(*ce)))
1664 return -EFAULT;
1665
1666 origsize = *size;
1667 *dstptr += sizeof(*ce);
1668
1669 ret = EBT_MATCH_ITERATE(e, compat_match_to_user, dstptr, size);
1670 if (ret)
1671 return ret;
1672 watchers_offset = e->watchers_offset - (origsize - *size);
1673
1674 ret = EBT_WATCHER_ITERATE(e, compat_watcher_to_user, dstptr, size);
1675 if (ret)
1676 return ret;
1677 target_offset = e->target_offset - (origsize - *size);
1678
1679 t = (struct ebt_entry_target *) ((char *) e + e->target_offset);
1680
1681 ret = compat_target_to_user(t, dstptr, size);
1682 if (ret)
1683 return ret;
1684 next_offset = e->next_offset - (origsize - *size);
1685
1686 if (put_user(watchers_offset, &ce->watchers_offset) ||
1687 put_user(target_offset, &ce->target_offset) ||
1688 put_user(next_offset, &ce->next_offset))
1689 return -EFAULT;
1690
1691 *size -= sizeof(*ce);
1692 return 0;
1693}
1694
1695static int compat_calc_match(struct ebt_entry_match *m, int *off)
1696{
1697 *off += ebt_compat_match_offset(m->u.match, m->match_size);
1698 *off += ebt_compat_entry_padsize();
1699 return 0;
1700}
1701
1702static int compat_calc_watcher(struct ebt_entry_watcher *w, int *off)
1703{
1704 *off += xt_compat_target_offset(w->u.watcher);
1705 *off += ebt_compat_entry_padsize();
1706 return 0;
1707}
1708
1709static int compat_calc_entry(const struct ebt_entry *e,
1710 const struct ebt_table_info *info,
1711 const void *base,
1712 struct compat_ebt_replace *newinfo)
1713{
1714 const struct ebt_entry_target *t;
1715 unsigned int entry_offset;
1716 int off, ret, i;
1717
1718 if (e->bitmask == 0)
1719 return 0;
1720
1721 off = 0;
1722 entry_offset = (void *)e - base;
1723
1724 EBT_MATCH_ITERATE(e, compat_calc_match, &off);
1725 EBT_WATCHER_ITERATE(e, compat_calc_watcher, &off);
1726
1727 t = (const struct ebt_entry_target *) ((char *) e + e->target_offset);
1728
1729 off += xt_compat_target_offset(t->u.target);
1730 off += ebt_compat_entry_padsize();
1731
1732 newinfo->entries_size -= off;
1733
1734 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, off);
1735 if (ret)
1736 return ret;
1737
1738 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1739 const void *hookptr = info->hook_entry[i];
1740 if (info->hook_entry[i] &&
1741 (e < (struct ebt_entry *)(base - hookptr))) {
1742 newinfo->hook_entry[i] -= off;
1743 pr_debug("0x%08X -> 0x%08X\n",
1744 newinfo->hook_entry[i] + off,
1745 newinfo->hook_entry[i]);
1746 }
1747 }
1748
1749 return 0;
1750}
1751
1752
1753static int compat_table_info(const struct ebt_table_info *info,
1754 struct compat_ebt_replace *newinfo)
1755{
1756 unsigned int size = info->entries_size;
1757 const void *entries = info->entries;
1758
1759 newinfo->entries_size = size;
1760
1761 return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
1762 entries, newinfo);
1763}
1764
1765static int compat_copy_everything_to_user(struct ebt_table *t,
1766 void __user *user, int *len, int cmd)
1767{
1768 struct compat_ebt_replace repl, tmp;
1769 struct ebt_counter *oldcounters;
1770 struct ebt_table_info tinfo;
1771 int ret;
1772 void __user *pos;
1773
1774 memset(&tinfo, 0, sizeof(tinfo));
1775
1776 if (cmd == EBT_SO_GET_ENTRIES) {
1777 tinfo.entries_size = t->private->entries_size;
1778 tinfo.nentries = t->private->nentries;
1779 tinfo.entries = t->private->entries;
1780 oldcounters = t->private->counters;
1781 } else {
1782 tinfo.entries_size = t->table->entries_size;
1783 tinfo.nentries = t->table->nentries;
1784 tinfo.entries = t->table->entries;
1785 oldcounters = t->table->counters;
1786 }
1787
1788 if (copy_from_user(&tmp, user, sizeof(tmp)))
1789 return -EFAULT;
1790
1791 if (tmp.nentries != tinfo.nentries ||
1792 (tmp.num_counters && tmp.num_counters != tinfo.nentries))
1793 return -EINVAL;
1794
1795 memcpy(&repl, &tmp, sizeof(repl));
1796 if (cmd == EBT_SO_GET_ENTRIES)
1797 ret = compat_table_info(t->private, &repl);
1798 else
1799 ret = compat_table_info(&tinfo, &repl);
1800 if (ret)
1801 return ret;
1802
1803 if (*len != sizeof(tmp) + repl.entries_size +
1804 (tmp.num_counters? tinfo.nentries * sizeof(struct ebt_counter): 0)) {
1805 pr_err("wrong size: *len %d, entries_size %u, replsz %d\n",
1806 *len, tinfo.entries_size, repl.entries_size);
1807 return -EINVAL;
1808 }
1809
1810 /* userspace might not need the counters */
1811 ret = copy_counters_to_user(t, oldcounters, compat_ptr(tmp.counters),
1812 tmp.num_counters, tinfo.nentries);
1813 if (ret)
1814 return ret;
1815
1816 pos = compat_ptr(tmp.entries);
1817 return EBT_ENTRY_ITERATE(tinfo.entries, tinfo.entries_size,
1818 compat_copy_entry_to_user, &pos, &tmp.entries_size);
1819}
1820
1821struct ebt_entries_buf_state {
1822 char *buf_kern_start; /* kernel buffer to copy (translated) data to */
1823 u32 buf_kern_len; /* total size of kernel buffer */
1824 u32 buf_kern_offset; /* amount of data copied so far */
1825 u32 buf_user_offset; /* read position in userspace buffer */
1826};
1827
1828static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
1829{
1830 state->buf_kern_offset += sz;
1831 return state->buf_kern_offset >= sz ? 0 : -EINVAL;
1832}
1833
1834static int ebt_buf_add(struct ebt_entries_buf_state *state,
1835 void *data, unsigned int sz)
1836{
1837 if (state->buf_kern_start == NULL)
1838 goto count_only;
1839
1840 BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
1841
1842 memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
1843
1844 count_only:
1845 state->buf_user_offset += sz;
1846 return ebt_buf_count(state, sz);
1847}
1848
1849static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz)
1850{
1851 char *b = state->buf_kern_start;
1852
1853 BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
1854
1855 if (b != NULL && sz > 0)
1856 memset(b + state->buf_kern_offset, 0, sz);
1857 /* do not adjust ->buf_user_offset here, we added kernel-side padding */
1858 return ebt_buf_count(state, sz);
1859}
1860
1861enum compat_mwt {
1862 EBT_COMPAT_MATCH,
1863 EBT_COMPAT_WATCHER,
1864 EBT_COMPAT_TARGET,
1865};
1866
1867static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
1868 enum compat_mwt compat_mwt,
1869 struct ebt_entries_buf_state *state,
1870 const unsigned char *base)
1871{
1872 char name[EBT_FUNCTION_MAXNAMELEN];
1873 struct xt_match *match;
1874 struct xt_target *wt;
1875 void *dst = NULL;
1876 int off, pad = 0, ret = 0;
1877 unsigned int size_kern, entry_offset, match_size = mwt->match_size;
1878
1879 strlcpy(name, mwt->u.name, sizeof(name));
1880
1881 if (state->buf_kern_start)
1882 dst = state->buf_kern_start + state->buf_kern_offset;
1883
1884 entry_offset = (unsigned char *) mwt - base;
1885 switch (compat_mwt) {
1886 case EBT_COMPAT_MATCH:
1887 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
1888 name, 0), "ebt_%s", name);
1889 if (match == NULL)
1890 return -ENOENT;
1891 if (IS_ERR(match))
1892 return PTR_ERR(match);
1893
1894 off = ebt_compat_match_offset(match, match_size);
1895 if (dst) {
1896 if (match->compat_from_user)
1897 match->compat_from_user(dst, mwt->data);
1898 else
1899 memcpy(dst, mwt->data, match_size);
1900 }
1901
1902 size_kern = match->matchsize;
1903 if (unlikely(size_kern == -1))
1904 size_kern = match_size;
1905 module_put(match->me);
1906 break;
1907 case EBT_COMPAT_WATCHER: /* fallthrough */
1908 case EBT_COMPAT_TARGET:
1909 wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE,
1910 name, 0), "ebt_%s", name);
1911 if (wt == NULL)
1912 return -ENOENT;
1913 if (IS_ERR(wt))
1914 return PTR_ERR(wt);
1915 off = xt_compat_target_offset(wt);
1916
1917 if (dst) {
1918 if (wt->compat_from_user)
1919 wt->compat_from_user(dst, mwt->data);
1920 else
1921 memcpy(dst, mwt->data, match_size);
1922 }
1923
1924 size_kern = wt->targetsize;
1925 module_put(wt->me);
1926 break;
1927 }
1928
1929 if (!dst) {
1930 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
1931 off + ebt_compat_entry_padsize());
1932 if (ret < 0)
1933 return ret;
1934 }
1935
1936 state->buf_kern_offset += match_size + off;
1937 state->buf_user_offset += match_size;
1938 pad = XT_ALIGN(size_kern) - size_kern;
1939
1940 if (pad > 0 && dst) {
1941 BUG_ON(state->buf_kern_len <= pad);
1942 BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
1943 memset(dst + size_kern, 0, pad);
1944 }
1945 return off + match_size;
1946}
1947
1948/*
1949 * return size of all matches, watchers or target, including necessary
1950 * alignment and padding.
1951 */
1952static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
1953 unsigned int size_left, enum compat_mwt type,
1954 struct ebt_entries_buf_state *state, const void *base)
1955{
1956 int growth = 0;
1957 char *buf;
1958
1959 if (size_left == 0)
1960 return 0;
1961
1962 buf = (char *) match32;
1963
1964 while (size_left >= sizeof(*match32)) {
1965 struct ebt_entry_match *match_kern;
1966 int ret;
1967
1968 match_kern = (struct ebt_entry_match *) state->buf_kern_start;
1969 if (match_kern) {
1970 char *tmp;
1971 tmp = state->buf_kern_start + state->buf_kern_offset;
1972 match_kern = (struct ebt_entry_match *) tmp;
1973 }
1974 ret = ebt_buf_add(state, buf, sizeof(*match32));
1975 if (ret < 0)
1976 return ret;
1977 size_left -= sizeof(*match32);
1978
1979 /* add padding before match->data (if any) */
1980 ret = ebt_buf_add_pad(state, ebt_compat_entry_padsize());
1981 if (ret < 0)
1982 return ret;
1983
1984 if (match32->match_size > size_left)
1985 return -EINVAL;
1986
1987 size_left -= match32->match_size;
1988
1989 ret = compat_mtw_from_user(match32, type, state, base);
1990 if (ret < 0)
1991 return ret;
1992
1993 BUG_ON(ret < match32->match_size);
1994 growth += ret - match32->match_size;
1995 growth += ebt_compat_entry_padsize();
1996
1997 buf += sizeof(*match32);
1998 buf += match32->match_size;
1999
2000 if (match_kern)
2001 match_kern->match_size = ret;
2002
2003 WARN_ON(type == EBT_COMPAT_TARGET && size_left);
2004 match32 = (struct compat_ebt_entry_mwt *) buf;
2005 }
2006
2007 return growth;
2008}
2009
2010#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \
2011({ \
2012 unsigned int __i; \
2013 int __ret = 0; \
2014 struct compat_ebt_entry_mwt *__watcher; \
2015 \
2016 for (__i = e->watchers_offset; \
2017 __i < (e)->target_offset; \
2018 __i += __watcher->watcher_size + \
2019 sizeof(struct compat_ebt_entry_mwt)) { \
2020 __watcher = (void *)(e) + __i; \
2021 __ret = fn(__watcher , ## args); \
2022 if (__ret != 0) \
2023 break; \
2024 } \
2025 if (__ret == 0) { \
2026 if (__i != (e)->target_offset) \
2027 __ret = -EINVAL; \
2028 } \
2029 __ret; \
2030})
2031
2032#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \
2033({ \
2034 unsigned int __i; \
2035 int __ret = 0; \
2036 struct compat_ebt_entry_mwt *__match; \
2037 \
2038 for (__i = sizeof(struct ebt_entry); \
2039 __i < (e)->watchers_offset; \
2040 __i += __match->match_size + \
2041 sizeof(struct compat_ebt_entry_mwt)) { \
2042 __match = (void *)(e) + __i; \
2043 __ret = fn(__match , ## args); \
2044 if (__ret != 0) \
2045 break; \
2046 } \
2047 if (__ret == 0) { \
2048 if (__i != (e)->watchers_offset) \
2049 __ret = -EINVAL; \
2050 } \
2051 __ret; \
2052})
2053
2054/* called for all ebt_entry structures. */
2055static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
2056 unsigned int *total,
2057 struct ebt_entries_buf_state *state)
2058{
2059 unsigned int i, j, startoff, new_offset = 0;
2060 /* stores match/watchers/targets & offset of next struct ebt_entry: */
2061 unsigned int offsets[4];
2062 unsigned int *offsets_update = NULL;
2063 int ret;
2064 char *buf_start;
2065
2066 if (*total < sizeof(struct ebt_entries))
2067 return -EINVAL;
2068
2069 if (!entry->bitmask) {
2070 *total -= sizeof(struct ebt_entries);
2071 return ebt_buf_add(state, entry, sizeof(struct ebt_entries));
2072 }
2073 if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry))
2074 return -EINVAL;
2075
2076 startoff = state->buf_user_offset;
2077 /* pull in most part of ebt_entry, it does not need to be changed. */
2078 ret = ebt_buf_add(state, entry,
2079 offsetof(struct ebt_entry, watchers_offset));
2080 if (ret < 0)
2081 return ret;
2082
2083 offsets[0] = sizeof(struct ebt_entry); /* matches come first */
2084 memcpy(&offsets[1], &entry->watchers_offset,
2085 sizeof(offsets) - sizeof(offsets[0]));
2086
2087 if (state->buf_kern_start) {
2088 buf_start = state->buf_kern_start + state->buf_kern_offset;
2089 offsets_update = (unsigned int *) buf_start;
2090 }
2091 ret = ebt_buf_add(state, &offsets[1],
2092 sizeof(offsets) - sizeof(offsets[0]));
2093 if (ret < 0)
2094 return ret;
2095 buf_start = (char *) entry;
2096 /*
2097 * 0: matches offset, always follows ebt_entry.
2098 * 1: watchers offset, from ebt_entry structure
2099 * 2: target offset, from ebt_entry structure
2100 * 3: next ebt_entry offset, from ebt_entry structure
2101 *
2102 * offsets are relative to beginning of struct ebt_entry (i.e., 0).
2103 */
2104 for (i = 0, j = 1 ; j < 4 ; j++, i++) {
2105 struct compat_ebt_entry_mwt *match32;
2106 unsigned int size;
2107 char *buf = buf_start;
2108
2109 buf = buf_start + offsets[i];
2110 if (offsets[i] > offsets[j])
2111 return -EINVAL;
2112
2113 match32 = (struct compat_ebt_entry_mwt *) buf;
2114 size = offsets[j] - offsets[i];
2115 ret = ebt_size_mwt(match32, size, i, state, base);
2116 if (ret < 0)
2117 return ret;
2118 new_offset += ret;
2119 if (offsets_update && new_offset) {
Jan Engelhardtff67e4e2010-03-19 21:08:16 +01002120 pr_debug("change offset %d to %d\n",
Florian Westphal81e675c2010-01-05 16:09:46 +01002121 offsets_update[i], offsets[j] + new_offset);
2122 offsets_update[i] = offsets[j] + new_offset;
2123 }
2124 }
2125
2126 startoff = state->buf_user_offset - startoff;
2127
2128 BUG_ON(*total < startoff);
2129 *total -= startoff;
2130 return 0;
2131}
2132
2133/*
2134 * repl->entries_size is the size of the ebt_entry blob in userspace.
2135 * It might need more memory when copied to a 64 bit kernel in case
2136 * userspace is 32-bit. So, first task: find out how much memory is needed.
2137 *
2138 * Called before validation is performed.
2139 */
2140static int compat_copy_entries(unsigned char *data, unsigned int size_user,
2141 struct ebt_entries_buf_state *state)
2142{
2143 unsigned int size_remaining = size_user;
2144 int ret;
2145
2146 ret = EBT_ENTRY_ITERATE(data, size_user, size_entry_mwt, data,
2147 &size_remaining, state);
2148 if (ret < 0)
2149 return ret;
2150
2151 WARN_ON(size_remaining);
2152 return state->buf_kern_offset;
2153}
2154
2155
2156static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2157 void __user *user, unsigned int len)
2158{
2159 struct compat_ebt_replace tmp;
2160 int i;
2161
2162 if (len < sizeof(tmp))
2163 return -EINVAL;
2164
2165 if (copy_from_user(&tmp, user, sizeof(tmp)))
2166 return -EFAULT;
2167
2168 if (len != sizeof(tmp) + tmp.entries_size)
2169 return -EINVAL;
2170
2171 if (tmp.entries_size == 0)
2172 return -EINVAL;
2173
2174 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
2175 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
2176 return -ENOMEM;
2177 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
2178 return -ENOMEM;
2179
2180 memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
2181
2182 /* starting with hook_entry, 32 vs. 64 bit structures are different */
2183 for (i = 0; i < NF_BR_NUMHOOKS; i++)
2184 repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]);
2185
2186 repl->num_counters = tmp.num_counters;
2187 repl->counters = compat_ptr(tmp.counters);
2188 repl->entries = compat_ptr(tmp.entries);
2189 return 0;
2190}
2191
2192static int compat_do_replace(struct net *net, void __user *user,
2193 unsigned int len)
2194{
2195 int ret, i, countersize, size64;
2196 struct ebt_table_info *newinfo;
2197 struct ebt_replace tmp;
2198 struct ebt_entries_buf_state state;
2199 void *entries_tmp;
2200
2201 ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
Florian Westphal90b89af2010-02-07 03:19:12 +01002202 if (ret) {
2203 /* try real handler in case userland supplied needed padding */
2204 if (ret == -EINVAL && do_replace(net, user, len) == 0)
2205 ret = 0;
Florian Westphal81e675c2010-01-05 16:09:46 +01002206 return ret;
Florian Westphal90b89af2010-02-07 03:19:12 +01002207 }
Florian Westphal81e675c2010-01-05 16:09:46 +01002208
2209 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
2210 newinfo = vmalloc(sizeof(*newinfo) + countersize);
2211 if (!newinfo)
2212 return -ENOMEM;
2213
2214 if (countersize)
2215 memset(newinfo->counters, 0, countersize);
2216
2217 memset(&state, 0, sizeof(state));
2218
2219 newinfo->entries = vmalloc(tmp.entries_size);
2220 if (!newinfo->entries) {
2221 ret = -ENOMEM;
2222 goto free_newinfo;
2223 }
2224 if (copy_from_user(
2225 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
2226 ret = -EFAULT;
2227 goto free_entries;
2228 }
2229
2230 entries_tmp = newinfo->entries;
2231
2232 xt_compat_lock(NFPROTO_BRIDGE);
2233
2234 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2235 if (ret < 0)
2236 goto out_unlock;
2237
2238 pr_debug("tmp.entries_size %d, kern off %d, user off %d delta %d\n",
2239 tmp.entries_size, state.buf_kern_offset, state.buf_user_offset,
2240 xt_compat_calc_jump(NFPROTO_BRIDGE, tmp.entries_size));
2241
2242 size64 = ret;
2243 newinfo->entries = vmalloc(size64);
2244 if (!newinfo->entries) {
2245 vfree(entries_tmp);
2246 ret = -ENOMEM;
2247 goto out_unlock;
2248 }
2249
2250 memset(&state, 0, sizeof(state));
2251 state.buf_kern_start = newinfo->entries;
2252 state.buf_kern_len = size64;
2253
2254 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2255 BUG_ON(ret < 0); /* parses same data again */
2256
2257 vfree(entries_tmp);
2258 tmp.entries_size = size64;
2259
2260 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
2261 char __user *usrptr;
2262 if (tmp.hook_entry[i]) {
2263 unsigned int delta;
2264 usrptr = (char __user *) tmp.hook_entry[i];
2265 delta = usrptr - tmp.entries;
2266 usrptr += xt_compat_calc_jump(NFPROTO_BRIDGE, delta);
2267 tmp.hook_entry[i] = (struct ebt_entries __user *)usrptr;
2268 }
2269 }
2270
2271 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2272 xt_compat_unlock(NFPROTO_BRIDGE);
2273
2274 ret = do_replace_finish(net, &tmp, newinfo);
2275 if (ret == 0)
2276 return ret;
2277free_entries:
2278 vfree(newinfo->entries);
2279free_newinfo:
2280 vfree(newinfo);
2281 return ret;
2282out_unlock:
2283 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2284 xt_compat_unlock(NFPROTO_BRIDGE);
2285 goto free_entries;
2286}
2287
2288static int compat_update_counters(struct net *net, void __user *user,
2289 unsigned int len)
2290{
2291 struct compat_ebt_replace hlp;
2292
2293 if (copy_from_user(&hlp, user, sizeof(hlp)))
2294 return -EFAULT;
2295
Florian Westphal90b89af2010-02-07 03:19:12 +01002296 /* try real handler in case userland supplied needed padding */
Florian Westphal81e675c2010-01-05 16:09:46 +01002297 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
Florian Westphal90b89af2010-02-07 03:19:12 +01002298 return update_counters(net, user, len);
Florian Westphal81e675c2010-01-05 16:09:46 +01002299
2300 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2301 hlp.num_counters, user, len);
2302}
2303
2304static int compat_do_ebt_set_ctl(struct sock *sk,
2305 int cmd, void __user *user, unsigned int len)
2306{
2307 int ret;
2308
2309 if (!capable(CAP_NET_ADMIN))
2310 return -EPERM;
2311
2312 switch (cmd) {
2313 case EBT_SO_SET_ENTRIES:
2314 ret = compat_do_replace(sock_net(sk), user, len);
2315 break;
2316 case EBT_SO_SET_COUNTERS:
2317 ret = compat_update_counters(sock_net(sk), user, len);
2318 break;
2319 default:
2320 ret = -EINVAL;
2321 }
2322 return ret;
2323}
2324
2325static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2326 void __user *user, int *len)
2327{
2328 int ret;
2329 struct compat_ebt_replace tmp;
2330 struct ebt_table *t;
2331
2332 if (!capable(CAP_NET_ADMIN))
2333 return -EPERM;
2334
Florian Westphal90b89af2010-02-07 03:19:12 +01002335 /* try real handler in case userland supplied needed padding */
Florian Westphal81e675c2010-01-05 16:09:46 +01002336 if ((cmd == EBT_SO_GET_INFO ||
2337 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
Florian Westphal90b89af2010-02-07 03:19:12 +01002338 return do_ebt_get_ctl(sk, cmd, user, len);
Florian Westphal81e675c2010-01-05 16:09:46 +01002339
2340 if (copy_from_user(&tmp, user, sizeof(tmp)))
2341 return -EFAULT;
2342
2343 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
2344 if (!t)
2345 return ret;
2346
2347 xt_compat_lock(NFPROTO_BRIDGE);
2348 switch (cmd) {
2349 case EBT_SO_GET_INFO:
2350 tmp.nentries = t->private->nentries;
2351 ret = compat_table_info(t->private, &tmp);
2352 if (ret)
2353 goto out;
2354 tmp.valid_hooks = t->valid_hooks;
2355
2356 if (copy_to_user(user, &tmp, *len) != 0) {
2357 ret = -EFAULT;
2358 break;
2359 }
2360 ret = 0;
2361 break;
2362 case EBT_SO_GET_INIT_INFO:
2363 tmp.nentries = t->table->nentries;
2364 tmp.entries_size = t->table->entries_size;
2365 tmp.valid_hooks = t->table->valid_hooks;
2366
2367 if (copy_to_user(user, &tmp, *len) != 0) {
2368 ret = -EFAULT;
2369 break;
2370 }
2371 ret = 0;
2372 break;
2373 case EBT_SO_GET_ENTRIES:
2374 case EBT_SO_GET_INIT_ENTRIES:
Florian Westphal90b89af2010-02-07 03:19:12 +01002375 /*
2376 * try real handler first in case of userland-side padding.
2377 * in case we are dealing with an 'ordinary' 32 bit binary
2378 * without 64bit compatibility padding, this will fail right
2379 * after copy_from_user when the *len argument is validated.
2380 *
2381 * the compat_ variant needs to do one pass over the kernel
2382 * data set to adjust for size differences before it the check.
2383 */
2384 if (copy_everything_to_user(t, user, len, cmd) == 0)
2385 ret = 0;
2386 else
2387 ret = compat_copy_everything_to_user(t, user, len, cmd);
Florian Westphal81e675c2010-01-05 16:09:46 +01002388 break;
2389 default:
2390 ret = -EINVAL;
2391 }
2392 out:
2393 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2394 xt_compat_unlock(NFPROTO_BRIDGE);
2395 mutex_unlock(&ebt_mutex);
2396 return ret;
2397}
2398#endif
2399
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002401{
2402 .pf = PF_INET,
2403 .set_optmin = EBT_BASE_CTL,
2404 .set_optmax = EBT_SO_SET_MAX + 1,
2405 .set = do_ebt_set_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002406#ifdef CONFIG_COMPAT
2407 .compat_set = compat_do_ebt_set_ctl,
2408#endif
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002409 .get_optmin = EBT_BASE_CTL,
2410 .get_optmax = EBT_SO_GET_MAX + 1,
2411 .get = do_ebt_get_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002412#ifdef CONFIG_COMPAT
2413 .compat_get = compat_do_ebt_get_ctl,
2414#endif
Neil Horman16fcec32007-09-11 11:28:26 +02002415 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416};
2417
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002418static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419{
2420 int ret;
2421
Jan Engelhardt043ef462008-10-08 11:35:15 +02002422 ret = xt_register_target(&ebt_standard_target);
2423 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return ret;
Jan Engelhardt043ef462008-10-08 11:35:15 +02002425 ret = nf_register_sockopt(&ebt_sockopts);
2426 if (ret < 0) {
2427 xt_unregister_target(&ebt_standard_target);
2428 return ret;
2429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
Patrick McHardya887c1c2007-07-14 20:46:15 -07002431 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return 0;
2433}
2434
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002435static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436{
2437 nf_unregister_sockopt(&ebt_sockopts);
Jan Engelhardt043ef462008-10-08 11:35:15 +02002438 xt_unregister_target(&ebt_standard_target);
Patrick McHardya887c1c2007-07-14 20:46:15 -07002439 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440}
2441
2442EXPORT_SYMBOL(ebt_register_table);
2443EXPORT_SYMBOL(ebt_unregister_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002445module_init(ebtables_init);
2446module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447MODULE_LICENSE("GPL");