blob: fcaefdd6200b4629cf2d55e078b8836254ce7083 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ebtables
3 *
4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * ebtables.c,v 2.0, July, 2002
8 *
9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
19#include <linux/kmod.h>
20#include <linux/module.h>
21#include <linux/vmalloc.h>
Jan Engelhardt18219d32008-10-08 11:35:13 +020022#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/netfilter_bridge/ebtables.h>
24#include <linux/spinlock.h>
Patrick McHardydf0933d2006-09-20 11:57:53 -070025#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/uaccess.h>
27#include <linux/smp.h>
David S. Millerc8923c62005-10-13 14:41:23 -070028#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <net/sock.h>
30/* needed for logical [in,out]-dev filtering */
31#include "../br_private.h"
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090034 "report to author: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* #define BUGPRINT(format, args...) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
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,
89 struct xt_target_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
98static inline int ebt_do_match (struct ebt_entry_match *m,
Jan Engelhardtf7108a22008-10-08 11:35:18 +020099 const struct sk_buff *skb, struct xt_match_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100{
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200101 par->match = m->u.match;
102 par->matchinfo = m->data;
Jan Engelhardtd61ba9f2009-01-12 00:06:06 +0000103 return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104}
105
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200106static inline int
107ebt_dev_check(const char *entry, const struct net_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108{
109 int i = 0;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000110 const char *devname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
112 if (*entry == '\0')
113 return 0;
114 if (!device)
115 return 1;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000116 devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 /* 1 is the wildcard token */
118 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
119 i++;
120 return (devname[i] != entry[i] && entry[i] != 1);
121}
122
123#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
124/* process standard matches */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200125static inline int
126ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
127 const struct net_device *in, const struct net_device *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128{
129 int verdict, i;
130
131 if (e->bitmask & EBT_802_3) {
132 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
133 return 1;
134 } else if (!(e->bitmask & EBT_NOPROTO) &&
135 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
136 return 1;
137
138 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
139 return 1;
140 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
141 return 1;
142 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
143 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
144 return 1;
145 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
146 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
147 return 1;
148
149 if (e->bitmask & EBT_SOURCEMAC) {
150 verdict = 0;
151 for (i = 0; i < 6; i++)
152 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
153 e->sourcemsk[i];
154 if (FWINV2(verdict != 0, EBT_ISOURCE) )
155 return 1;
156 }
157 if (e->bitmask & EBT_DESTMAC) {
158 verdict = 0;
159 for (i = 0; i < 6; i++)
160 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
161 e->destmsk[i];
162 if (FWINV2(verdict != 0, EBT_IDEST) )
163 return 1;
164 }
165 return 0;
166}
167
Jan Engelhardt98e86402009-04-15 21:06:05 +0200168static inline __pure
169struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)
170{
171 return (void *)entry + entry->next_offset;
172}
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174/* Do some firewalling */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700175unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 const struct net_device *in, const struct net_device *out,
177 struct ebt_table *table)
178{
179 int i, nentries;
180 struct ebt_entry *point;
181 struct ebt_counter *counter_base, *cb_base;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200182 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 int verdict, sp = 0;
184 struct ebt_chainstack *cs;
185 struct ebt_entries *chaininfo;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200186 const char *base;
187 const struct ebt_table_info *private;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200188 bool hotdrop = false;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200189 struct xt_match_param mtpar;
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200190 struct xt_target_param tgpar;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200191
Jan Engelhardt916a9172008-10-08 11:35:20 +0200192 mtpar.family = tgpar.family = NFPROTO_BRIDGE;
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200193 mtpar.in = tgpar.in = in;
194 mtpar.out = tgpar.out = out;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200195 mtpar.hotdrop = &hotdrop;
Evgeniy Polyakova5e78822009-06-04 16:54:42 +0200196 mtpar.hooknum = tgpar.hooknum = hook;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
198 read_lock_bh(&table->lock);
199 private = table->private;
200 cb_base = COUNTER_BASE(private->counters, private->nentries,
201 smp_processor_id());
202 if (private->chainstack)
203 cs = private->chainstack[smp_processor_id()];
204 else
205 cs = NULL;
206 chaininfo = private->hook_entry[hook];
207 nentries = private->hook_entry[hook]->nentries;
208 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
209 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
210 /* base for chain jumps */
211 base = private->entries;
212 i = 0;
213 while (i < nentries) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700214 if (ebt_basic_match(point, eth_hdr(skb), in, out))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 goto letscontinue;
216
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200217 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &mtpar) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 goto letscontinue;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200219 if (hotdrop) {
220 read_unlock_bh(&table->lock);
221 return NF_DROP;
222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
224 /* increase counter */
225 (*(counter_base + i)).pcnt++;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700226 (*(counter_base + i)).bcnt += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 /* these should only watch: not modify, nor tell us
229 what to do with the packet */
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200230 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &tgpar);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232 t = (struct ebt_entry_target *)
233 (((char *)point) + point->target_offset);
234 /* standard target */
235 if (!t->u.target->target)
236 verdict = ((struct ebt_standard_target *)t)->verdict;
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200237 else {
238 tgpar.target = t->u.target;
239 tgpar.targinfo = t->data;
240 verdict = t->u.target->target(skb, &tgpar);
241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 if (verdict == EBT_ACCEPT) {
243 read_unlock_bh(&table->lock);
244 return NF_ACCEPT;
245 }
246 if (verdict == EBT_DROP) {
247 read_unlock_bh(&table->lock);
248 return NF_DROP;
249 }
250 if (verdict == EBT_RETURN) {
251letsreturn:
252#ifdef CONFIG_NETFILTER_DEBUG
253 if (sp == 0) {
254 BUGPRINT("RETURN on base chain");
255 /* act like this is EBT_CONTINUE */
256 goto letscontinue;
257 }
258#endif
259 sp--;
260 /* put all the local variables right */
261 i = cs[sp].n;
262 chaininfo = cs[sp].chaininfo;
263 nentries = chaininfo->nentries;
264 point = cs[sp].e;
265 counter_base = cb_base +
266 chaininfo->counter_offset;
267 continue;
268 }
269 if (verdict == EBT_CONTINUE)
270 goto letscontinue;
271#ifdef CONFIG_NETFILTER_DEBUG
272 if (verdict < 0) {
273 BUGPRINT("bogus standard verdict\n");
274 read_unlock_bh(&table->lock);
275 return NF_DROP;
276 }
277#endif
278 /* jump to a udc */
279 cs[sp].n = i + 1;
280 cs[sp].chaininfo = chaininfo;
Jan Engelhardt98e86402009-04-15 21:06:05 +0200281 cs[sp].e = ebt_next_entry(point);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 i = 0;
283 chaininfo = (struct ebt_entries *) (base + verdict);
284#ifdef CONFIG_NETFILTER_DEBUG
285 if (chaininfo->distinguisher) {
286 BUGPRINT("jump to non-chain\n");
287 read_unlock_bh(&table->lock);
288 return NF_DROP;
289 }
290#endif
291 nentries = chaininfo->nentries;
292 point = (struct ebt_entry *)chaininfo->data;
293 counter_base = cb_base + chaininfo->counter_offset;
294 sp++;
295 continue;
296letscontinue:
Jan Engelhardt98e86402009-04-15 21:06:05 +0200297 point = ebt_next_entry(point);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 i++;
299 }
300
301 /* I actually like this :) */
302 if (chaininfo->policy == EBT_RETURN)
303 goto letsreturn;
304 if (chaininfo->policy == EBT_ACCEPT) {
305 read_unlock_bh(&table->lock);
306 return NF_ACCEPT;
307 }
308 read_unlock_bh(&table->lock);
309 return NF_DROP;
310}
311
312/* If it succeeds, returns element and locks mutex */
313static inline void *
314find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800315 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
Patrick McHardydf0933d2006-09-20 11:57:53 -0700317 struct {
318 struct list_head list;
319 char name[EBT_FUNCTION_MAXNAMELEN];
320 } *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Ingo Molnar57b47a52006-03-20 22:35:41 -0800322 *error = mutex_lock_interruptible(mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 if (*error != 0)
324 return NULL;
325
Patrick McHardydf0933d2006-09-20 11:57:53 -0700326 list_for_each_entry(e, head, list) {
327 if (strcmp(e->name, name) == 0)
328 return e;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 }
Patrick McHardydf0933d2006-09-20 11:57:53 -0700330 *error = -ENOENT;
331 mutex_unlock(mutex);
332 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333}
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335static void *
336find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
Ingo Molnar57b47a52006-03-20 22:35:41 -0800337 int *error, struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
Johannes Berg95a5afc2008-10-16 15:24:51 -0700339 return try_then_request_module(
340 find_inlist_lock_noload(head, name, error, mutex),
341 "%s%s", prefix, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344static inline struct ebt_table *
Alexey Dobriyan511061e2008-11-04 14:22:55 +0100345find_table_lock(struct net *net, const char *name, int *error,
346 struct mutex *mutex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Alexey Dobriyan511061e2008-11-04 14:22:55 +0100348 return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name,
349 "ebtable_", error, mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352static inline int
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200353ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
354 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355{
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200356 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200357 struct xt_match *match;
Al Viro14197d52006-11-30 19:25:21 -0800358 size_t left = ((char *)e + e->watchers_offset) - (char *)m;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 int ret;
360
Al Viro14197d52006-11-30 19:25:21 -0800361 if (left < sizeof(struct ebt_entry_match) ||
362 left - sizeof(struct ebt_entry_match) < m->match_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200364
365 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
366 m->u.name, 0), "ebt_%s", m->u.name);
367 if (IS_ERR(match))
368 return PTR_ERR(match);
369 if (match == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200371 m->u.match = match;
372
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200373 par->match = match;
374 par->matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200375 ret = xt_check_match(par, m->match_size,
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200376 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200377 if (ret < 0) {
378 module_put(match->me);
379 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 (*cnt)++;
383 return 0;
384}
385
386static inline int
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200387ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
388 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200390 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200391 struct xt_target *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800392 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 int ret;
394
Al Viro14197d52006-11-30 19:25:21 -0800395 if (left < sizeof(struct ebt_entry_watcher) ||
396 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200398
399 watcher = try_then_request_module(
400 xt_find_target(NFPROTO_BRIDGE, w->u.name, 0),
401 "ebt_%s", w->u.name);
402 if (IS_ERR(watcher))
403 return PTR_ERR(watcher);
404 if (watcher == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 return -ENOENT;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200406 w->u.watcher = watcher;
407
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200408 par->target = watcher;
409 par->targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200410 ret = xt_check_target(par, w->watcher_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200411 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200412 if (ret < 0) {
413 module_put(watcher->me);
414 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 (*cnt)++;
418 return 0;
419}
420
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200421static int ebt_verify_pointers(const struct ebt_replace *repl,
Al Viro70fe9af2006-11-30 19:26:14 -0800422 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Al Viro70fe9af2006-11-30 19:26:14 -0800424 unsigned int limit = repl->entries_size;
425 unsigned int valid_hooks = repl->valid_hooks;
426 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 int i;
428
Al Viroe4fd77d2006-11-30 19:26:35 -0800429 for (i = 0; i < NF_BR_NUMHOOKS; i++)
430 newinfo->hook_entry[i] = NULL;
431
432 newinfo->entries_size = repl->entries_size;
433 newinfo->nentries = repl->nentries;
434
Al Viro70fe9af2006-11-30 19:26:14 -0800435 while (offset < limit) {
436 size_t left = limit - offset;
437 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800438
Al Viro70fe9af2006-11-30 19:26:14 -0800439 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 break;
Al Viro22b440b2006-11-30 19:25:51 -0800441
Al Viro70fe9af2006-11-30 19:26:14 -0800442 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
443 if ((valid_hooks & (1 << i)) == 0)
444 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800445 if ((char __user *)repl->hook_entry[i] ==
446 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800447 break;
448 }
449
450 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
451 if (e->bitmask != 0) {
452 /* we make userspace set this right,
453 so there is no misunderstanding */
454 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
455 "in distinguisher\n");
456 return -EINVAL;
457 }
458 if (i != NF_BR_NUMHOOKS)
459 newinfo->hook_entry[i] = (struct ebt_entries *)e;
460 if (left < sizeof(struct ebt_entries))
461 break;
462 offset += sizeof(struct ebt_entries);
463 } else {
464 if (left < sizeof(struct ebt_entry))
465 break;
466 if (left < e->next_offset)
467 break;
Florian Westphal1756de22010-02-15 18:15:55 +0100468 if (e->next_offset < sizeof(struct ebt_entry))
469 return -EINVAL;
Al Viro70fe9af2006-11-30 19:26:14 -0800470 offset += e->next_offset;
471 }
472 }
473 if (offset != limit) {
474 BUGPRINT("entries_size too small\n");
475 return -EINVAL;
476 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800477
478 /* check if all valid hooks have a chain */
479 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
480 if (!newinfo->hook_entry[i] &&
481 (valid_hooks & (1 << i))) {
482 BUGPRINT("Valid hook without chain\n");
483 return -EINVAL;
484 }
485 }
Al Viro70fe9af2006-11-30 19:26:14 -0800486 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800487}
488
489/*
490 * this one is very careful, as it is the first function
491 * to parse the userspace data
492 */
493static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200494ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
495 const struct ebt_table_info *newinfo,
Al Viro0e795532006-11-30 19:27:13 -0800496 unsigned int *n, unsigned int *cnt,
497 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800498{
Al Viro22b440b2006-11-30 19:25:51 -0800499 int i;
500
501 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800502 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800503 break;
504 }
505 /* beginning of a new chain
506 if i == NF_BR_NUMHOOKS it must be a user defined chain */
507 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 /* this checks if the previous chain has as many entries
509 as it said it has */
510 if (*n != *cnt) {
511 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900512 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 return -EINVAL;
514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
516 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
517 /* only RETURN from udc */
518 if (i != NF_BR_NUMHOOKS ||
519 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
520 BUGPRINT("bad policy\n");
521 return -EINVAL;
522 }
523 }
524 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
525 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
527 BUGPRINT("counter_offset != totalcnt");
528 return -EINVAL;
529 }
530 *n = ((struct ebt_entries *)e)->nentries;
531 *cnt = 0;
532 return 0;
533 }
534 /* a plain old entry, heh */
535 if (sizeof(struct ebt_entry) > e->watchers_offset ||
536 e->watchers_offset > e->target_offset ||
537 e->target_offset >= e->next_offset) {
538 BUGPRINT("entry offsets not in right order\n");
539 return -EINVAL;
540 }
541 /* this is not checked anywhere else */
542 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
543 BUGPRINT("target size too small\n");
544 return -EINVAL;
545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 (*cnt)++;
547 (*totalcnt)++;
548 return 0;
549}
550
551struct ebt_cl_stack
552{
553 struct ebt_chainstack cs;
554 int from;
555 unsigned int hookmask;
556};
557
558/*
559 * we need these positions to check that the jumps to a different part of the
560 * entries is a jump to the beginning of a new chain.
561 */
562static inline int
563ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800564 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 int i;
567
568 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800569 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return 0;
571 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
573 break;
574 }
575 /* only care about udc */
576 if (i != NF_BR_NUMHOOKS)
577 return 0;
578
579 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
580 /* these initialisations are depended on later in check_chainloops() */
581 udc[*n].cs.n = 0;
582 udc[*n].hookmask = 0;
583
584 (*n)++;
585 return 0;
586}
587
588static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100589ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200591 struct xt_mtdtor_param par;
592
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 if (i && (*i)-- == 0)
594 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100596 par.net = net;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200597 par.match = m->u.match;
598 par.matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200599 par.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200600 if (par.match->destroy != NULL)
601 par.match->destroy(&par);
602 module_put(par.match->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 return 0;
604}
605
606static inline int
Patrick McHardyadd67462010-02-03 13:45:12 +0100607ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200609 struct xt_tgdtor_param par;
610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 if (i && (*i)-- == 0)
612 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Patrick McHardyadd67462010-02-03 13:45:12 +0100614 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200615 par.target = w->u.watcher;
616 par.targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200617 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200618 if (par.target->destroy != NULL)
619 par.target->destroy(&par);
620 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 return 0;
622}
623
624static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100625ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200627 struct xt_tgdtor_param par;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 struct ebt_entry_target *t;
629
Al Viro40642f92006-11-30 19:24:12 -0800630 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 return 0;
632 /* we're done */
633 if (cnt && (*cnt)-- == 0)
634 return 1;
Patrick McHardyadd67462010-02-03 13:45:12 +0100635 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL);
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100636 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Patrick McHardyadd67462010-02-03 13:45:12 +0100639 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200640 par.target = t->u.target;
641 par.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200642 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200643 if (par.target->destroy != NULL)
644 par.target->destroy(&par);
645 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return 0;
647}
648
649static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200650ebt_check_entry(struct ebt_entry *e, struct net *net,
651 const struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800652 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
654{
655 struct ebt_entry_target *t;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200656 struct xt_target *target;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800658 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 int ret;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200660 struct xt_mtchk_param mtpar;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200661 struct xt_tgchk_param tgpar;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800664 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return 0;
666
667 if (e->bitmask & ~EBT_F_MASK) {
668 BUGPRINT("Unknown flag for bitmask\n");
669 return -EINVAL;
670 }
671 if (e->invflags & ~EBT_INV_MASK) {
672 BUGPRINT("Unknown flag for inv bitmask\n");
673 return -EINVAL;
674 }
675 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
676 BUGPRINT("NOPROTO & 802_3 not allowed\n");
677 return -EINVAL;
678 }
679 /* what hook do we belong to? */
680 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800681 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 continue;
683 if ((char *)newinfo->hook_entry[i] < (char *)e)
684 hook = i;
685 else
686 break;
687 }
688 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
689 a base chain */
690 if (i < NF_BR_NUMHOOKS)
691 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
692 else {
693 for (i = 0; i < udc_cnt; i++)
694 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
695 break;
696 if (i == 0)
697 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
698 else
699 hookmask = cl_s[i - 1].hookmask;
700 }
701 i = 0;
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200702
Patrick McHardyadd67462010-02-03 13:45:12 +0100703 mtpar.net = tgpar.net = net;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200704 mtpar.table = tgpar.table = name;
705 mtpar.entryinfo = tgpar.entryinfo = e;
706 mtpar.hook_mask = tgpar.hook_mask = hookmask;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200707 mtpar.family = tgpar.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200708 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 if (ret != 0)
710 goto cleanup_matches;
711 j = 0;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200712 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 if (ret != 0)
714 goto cleanup_watchers;
715 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800716 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Jan Engelhardt043ef462008-10-08 11:35:15 +0200718 target = try_then_request_module(
719 xt_find_target(NFPROTO_BRIDGE, t->u.name, 0),
720 "ebt_%s", t->u.name);
721 if (IS_ERR(target)) {
722 ret = PTR_ERR(target);
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200723 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200724 } else if (target == NULL) {
725 ret = -ENOENT;
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200726 goto cleanup_watchers;
727 }
728
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 t->u.target = target;
730 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800731 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 BUGPRINT("Standard target size too big\n");
733 ret = -EFAULT;
734 goto cleanup_watchers;
735 }
736 if (((struct ebt_standard_target *)t)->verdict <
737 -NUM_STANDARD_TARGETS) {
738 BUGPRINT("Invalid standard target\n");
739 ret = -EFAULT;
740 goto cleanup_watchers;
741 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200742 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
743 module_put(t->u.target->me);
744 ret = -EFAULT;
745 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200746 }
747
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200748 tgpar.target = target;
749 tgpar.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200750 ret = xt_check_target(&tgpar, t->target_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200751 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200752 if (ret < 0) {
753 module_put(target->me);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200754 goto cleanup_watchers;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756 (*cnt)++;
757 return 0;
758cleanup_watchers:
Patrick McHardyadd67462010-02-03 13:45:12 +0100759 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760cleanup_matches:
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100761 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 return ret;
763}
764
765/*
766 * checks for loops and sets the hook mask for udc
767 * the hook mask for udc tells us from which base chains the udc can be
768 * accessed. This mask is a parameter to the check() functions of the extensions
769 */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200770static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 unsigned int udc_cnt, unsigned int hooknr, char *base)
772{
773 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200774 const struct ebt_entry *e = (struct ebt_entry *)chain->data;
775 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
777 while (pos < nentries || chain_nr != -1) {
778 /* end of udc, go back one 'recursion' step */
779 if (pos == nentries) {
780 /* put back values of the time when this chain was called */
781 e = cl_s[chain_nr].cs.e;
782 if (cl_s[chain_nr].from != -1)
783 nentries =
784 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
785 else
786 nentries = chain->nentries;
787 pos = cl_s[chain_nr].cs.n;
788 /* make sure we won't see a loop that isn't one */
789 cl_s[chain_nr].cs.n = 0;
790 chain_nr = cl_s[chain_nr].from;
791 if (pos == nentries)
792 continue;
793 }
794 t = (struct ebt_entry_target *)
795 (((char *)e) + e->target_offset);
796 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
797 goto letscontinue;
798 if (e->target_offset + sizeof(struct ebt_standard_target) >
799 e->next_offset) {
800 BUGPRINT("Standard target size too big\n");
801 return -1;
802 }
803 verdict = ((struct ebt_standard_target *)t)->verdict;
804 if (verdict >= 0) { /* jump to another chain */
805 struct ebt_entries *hlp2 =
806 (struct ebt_entries *)(base + verdict);
807 for (i = 0; i < udc_cnt; i++)
808 if (hlp2 == cl_s[i].cs.chaininfo)
809 break;
810 /* bad destination or loop */
811 if (i == udc_cnt) {
812 BUGPRINT("bad destination\n");
813 return -1;
814 }
815 if (cl_s[i].cs.n) {
816 BUGPRINT("loop\n");
817 return -1;
818 }
Al Viro98a08242006-11-30 19:24:49 -0800819 if (cl_s[i].hookmask & (1 << hooknr))
820 goto letscontinue;
821 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 cl_s[i].cs.n = pos + 1;
823 pos = 0;
Jan Engelhardt98e86402009-04-15 21:06:05 +0200824 cl_s[i].cs.e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 e = (struct ebt_entry *)(hlp2->data);
826 nentries = hlp2->nentries;
827 cl_s[i].from = chain_nr;
828 chain_nr = i;
829 /* this udc is accessible from the base chain for hooknr */
830 cl_s[i].hookmask |= (1 << hooknr);
831 continue;
832 }
833letscontinue:
Jan Engelhardt98e86402009-04-15 21:06:05 +0200834 e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 pos++;
836 }
837 return 0;
838}
839
840/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200841static int translate_table(struct net *net, const char *name,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100842 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843{
844 unsigned int i, j, k, udc_cnt;
845 int ret;
846 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
847
848 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800849 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 i++;
851 if (i == NF_BR_NUMHOOKS) {
852 BUGPRINT("No valid hooks specified\n");
853 return -EINVAL;
854 }
Al Viro1f072c92006-11-30 19:26:53 -0800855 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 BUGPRINT("Chains don't start at beginning\n");
857 return -EINVAL;
858 }
859 /* make sure chains are ordered after each other in same order
860 as their corresponding hooks */
861 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800862 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800864 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 BUGPRINT("Hook order must be followed\n");
866 return -EINVAL;
867 }
868 i = j;
869 }
870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 /* do some early checkings and initialize some things */
872 i = 0; /* holds the expected nr. of entries for the chain */
873 j = 0; /* holds the up to now counted entries for the chain */
874 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900875 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
877 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800878 ebt_check_entry_size_and_hooks, newinfo,
879 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 if (ret != 0)
882 return ret;
883
884 if (i != j) {
885 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900886 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return -EINVAL;
888 }
889 if (k != newinfo->nentries) {
890 BUGPRINT("Total nentries is wrong\n");
891 return -EINVAL;
892 }
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 /* get the location of the udc, put them in an array
895 while we're at it, allocate the chainstack */
896 if (udc_cnt) {
897 /* this will get free'd in do_replace()/ebt_register_table()
898 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700899 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800900 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (!newinfo->chainstack)
902 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700903 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700905 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 if (!newinfo->chainstack[i]) {
907 while (i)
908 vfree(newinfo->chainstack[--i]);
909 vfree(newinfo->chainstack);
910 newinfo->chainstack = NULL;
911 return -ENOMEM;
912 }
913 }
914
Jayachandran C18bc89a2006-04-20 00:14:49 -0700915 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 if (!cl_s)
917 return -ENOMEM;
918 i = 0; /* the i'th udc */
919 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800920 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 /* sanity check */
922 if (i != udc_cnt) {
923 BUGPRINT("i != udc_cnt\n");
924 vfree(cl_s);
925 return -EFAULT;
926 }
927 }
928
929 /* Check for loops */
930 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800931 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 if (check_chainloops(newinfo->hook_entry[i],
933 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700934 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 return -EINVAL;
936 }
937
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200938 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 - the nr of entries in each chain is right
940 - the size of the allocated space is right
941 - all valid hooks have a corresponding chain
942 - there are no loops
943 - wrong data can still be on the level of a single entry
944 - could be there are jumps to places that are not the
945 beginning of a chain. This can only occur in chains that
946 are not accessible from any base chains, so we don't care. */
947
948 /* used to know what we need to clean up if something goes wrong */
949 i = 0;
950 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100951 ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 if (ret != 0) {
953 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100954 ebt_cleanup_entry, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 }
James Lamanna68d31872005-06-22 22:12:57 -0700956 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return ret;
958}
959
960/* called under write_lock */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200961static void get_counters(const struct ebt_counter *oldcounters,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 struct ebt_counter *counters, unsigned int nentries)
963{
964 int i, cpu;
965 struct ebt_counter *counter_base;
966
967 /* counters of cpu 0 */
968 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700969 sizeof(struct ebt_counter) * nentries);
970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700972 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700973 if (cpu == 0)
974 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
976 for (i = 0; i < nentries; i++) {
977 counters[i].pcnt += counter_base[i].pcnt;
978 counters[i].bcnt += counter_base[i].bcnt;
979 }
980 }
981}
982
Florian Westphale7887592010-02-04 18:38:53 +0100983static int do_replace_finish(struct net *net, struct ebt_replace *repl,
984 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
Florian Westphale7887592010-02-04 18:38:53 +0100986 int ret, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 struct ebt_counter *counterstmp = NULL;
988 /* used to be able to unlock earlier */
989 struct ebt_table_info *table;
Florian Westphale7887592010-02-04 18:38:53 +0100990 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 /* the user wants counters back
993 the check on the size is done later, when we have the lock */
Florian Westphale7887592010-02-04 18:38:53 +0100994 if (repl->num_counters) {
995 unsigned long size = repl->num_counters * sizeof(*counterstmp);
996 counterstmp = vmalloc(size);
997 if (!counterstmp)
998 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 newinfo->chainstack = NULL;
Florian Westphale7887592010-02-04 18:38:53 +01001002 ret = ebt_verify_pointers(repl, newinfo);
Al Viro1bc23262006-11-30 19:28:08 -08001003 if (ret != 0)
1004 goto free_counterstmp;
1005
Florian Westphale7887592010-02-04 18:38:53 +01001006 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
1008 if (ret != 0)
1009 goto free_counterstmp;
1010
Florian Westphale7887592010-02-04 18:38:53 +01001011 t = find_table_lock(net, repl->name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 if (!t) {
1013 ret = -ENOENT;
1014 goto free_iterate;
1015 }
1016
1017 /* the table doesn't like it */
Florian Westphale7887592010-02-04 18:38:53 +01001018 if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 goto free_unlock;
1020
Florian Westphale7887592010-02-04 18:38:53 +01001021 if (repl->num_counters && repl->num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 BUGPRINT("Wrong nr. of counters requested\n");
1023 ret = -EINVAL;
1024 goto free_unlock;
1025 }
1026
1027 /* we have the mutex lock, so no danger in reading this pointer */
1028 table = t->private;
1029 /* make sure the table can only be rmmod'ed if it contains no rules */
1030 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1031 ret = -ENOENT;
1032 goto free_unlock;
1033 } else if (table->nentries && !newinfo->nentries)
1034 module_put(t->me);
1035 /* we need an atomic snapshot of the counters */
1036 write_lock_bh(&t->lock);
Florian Westphale7887592010-02-04 18:38:53 +01001037 if (repl->num_counters)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 get_counters(t->private->counters, counterstmp,
1039 t->private->nentries);
1040
1041 t->private = newinfo;
1042 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001043 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 /* so, a user can change the chains while having messed up her counter
1045 allocation. Only reason why this is done is because this way the lock
1046 is held only once, while this doesn't bring the kernel into a
1047 dangerous state. */
Florian Westphale7887592010-02-04 18:38:53 +01001048 if (repl->num_counters &&
1049 copy_to_user(repl->counters, counterstmp,
1050 repl->num_counters * sizeof(struct ebt_counter))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 ret = -EFAULT;
1052 }
1053 else
1054 ret = 0;
1055
1056 /* decrease module count and free resources */
1057 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001058 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060 vfree(table->entries);
1061 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001062 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 vfree(table->chainstack[i]);
1064 vfree(table->chainstack);
1065 }
1066 vfree(table);
1067
James Lamanna68d31872005-06-22 22:12:57 -07001068 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 return ret;
1070
1071free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001072 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073free_iterate:
1074 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001075 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001077 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* can be initialized in translate_table() */
1079 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001080 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 vfree(newinfo->chainstack[i]);
1082 vfree(newinfo->chainstack);
1083 }
Florian Westphale7887592010-02-04 18:38:53 +01001084 return ret;
1085}
1086
1087/* replace the table */
1088static int do_replace(struct net *net, const void __user *user,
1089 unsigned int len)
1090{
1091 int ret, countersize;
1092 struct ebt_table_info *newinfo;
1093 struct ebt_replace tmp;
1094
1095 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1096 return -EFAULT;
1097
1098 if (len != sizeof(tmp) + tmp.entries_size) {
1099 BUGPRINT("Wrong len argument\n");
1100 return -EINVAL;
1101 }
1102
1103 if (tmp.entries_size == 0) {
1104 BUGPRINT("Entries_size never zero\n");
1105 return -EINVAL;
1106 }
1107 /* overflow check */
1108 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
1109 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
1110 return -ENOMEM;
1111 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
1112 return -ENOMEM;
1113
1114 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
1115 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1116 if (!newinfo)
1117 return -ENOMEM;
1118
1119 if (countersize)
1120 memset(newinfo->counters, 0, countersize);
1121
1122 newinfo->entries = vmalloc(tmp.entries_size);
1123 if (!newinfo->entries) {
1124 ret = -ENOMEM;
1125 goto free_newinfo;
1126 }
1127 if (copy_from_user(
1128 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
1129 BUGPRINT("Couldn't copy entries from userspace\n");
1130 ret = -EFAULT;
1131 goto free_entries;
1132 }
1133
1134 ret = do_replace_finish(net, &tmp, newinfo);
1135 if (ret == 0)
1136 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001138 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001140 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return ret;
1142}
1143
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001144struct ebt_table *
1145ebt_register_table(struct net *net, const struct ebt_table *input_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
1147 struct ebt_table_info *newinfo;
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001148 struct ebt_table *t, *table;
Al Viro1e419cd2006-11-30 19:28:48 -08001149 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001151 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001153 if (input_table == NULL || (repl = input_table->table) == NULL ||
1154 repl->entries == 0 || repl->entries_size == 0 ||
1155 repl->counters != NULL || input_table->private != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 BUGPRINT("Bad table data for ebt_register_table!!!\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001157 return ERR_PTR(-EINVAL);
1158 }
1159
1160 /* Don't add one table to multiple lists. */
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001161 table = kmemdup(input_table, sizeof(struct ebt_table), GFP_KERNEL);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001162 if (!table) {
1163 ret = -ENOMEM;
1164 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 }
1166
Christoph Lameter53b8a312007-02-20 13:57:51 -08001167 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001168 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 ret = -ENOMEM;
1170 if (!newinfo)
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001171 goto free_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Al Virodf07a812006-11-30 19:28:25 -08001173 p = vmalloc(repl->entries_size);
1174 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 goto free_newinfo;
1176
Al Virodf07a812006-11-30 19:28:25 -08001177 memcpy(p, repl->entries, repl->entries_size);
1178 newinfo->entries = p;
1179
1180 newinfo->entries_size = repl->entries_size;
1181 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 if (countersize)
1184 memset(newinfo->counters, 0, countersize);
1185
1186 /* fill in newinfo and parse the entries */
1187 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001188 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1189 if ((repl->valid_hooks & (1 << i)) == 0)
1190 newinfo->hook_entry[i] = NULL;
1191 else
1192 newinfo->hook_entry[i] = p +
1193 ((char *)repl->hook_entry[i] - repl->entries);
1194 }
Alexey Dobriyana83d8e82010-01-18 08:21:13 +01001195 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 if (ret != 0) {
1197 BUGPRINT("Translate_table failed\n");
1198 goto free_chainstack;
1199 }
1200
1201 if (table->check && table->check(newinfo, table->valid_hooks)) {
1202 BUGPRINT("The table doesn't like its own initial data, lol\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001203 return ERR_PTR(-EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 }
1205
1206 table->private = newinfo;
1207 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001208 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 if (ret != 0)
1210 goto free_chainstack;
1211
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001212 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
Patrick McHardydf0933d2006-09-20 11:57:53 -07001213 if (strcmp(t->name, table->name) == 0) {
1214 ret = -EEXIST;
1215 BUGPRINT("Table name already exists\n");
1216 goto free_unlock;
1217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 }
1219
1220 /* Hold a reference count if the chains aren't empty */
1221 if (newinfo->nentries && !try_module_get(table->me)) {
1222 ret = -ENOENT;
1223 goto free_unlock;
1224 }
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001225 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001226 mutex_unlock(&ebt_mutex);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001227 return table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001229 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230free_chainstack:
1231 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001232 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 vfree(newinfo->chainstack[i]);
1234 vfree(newinfo->chainstack);
1235 }
1236 vfree(newinfo->entries);
1237free_newinfo:
1238 vfree(newinfo);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001239free_table:
1240 kfree(table);
1241out:
1242 return ERR_PTR(ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243}
1244
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001245void ebt_unregister_table(struct net *net, struct ebt_table *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246{
1247 int i;
1248
1249 if (!table) {
1250 BUGPRINT("Request to unregister NULL table!!!\n");
1251 return;
1252 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001253 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001254 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001255 mutex_unlock(&ebt_mutex);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001256 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001257 ebt_cleanup_entry, net, NULL);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001258 if (table->private->nentries)
1259 module_put(table->me);
James Lamanna68d31872005-06-22 22:12:57 -07001260 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001262 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 vfree(table->private->chainstack[i]);
1264 vfree(table->private->chainstack);
1265 }
1266 vfree(table->private);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001267 kfree(table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268}
1269
1270/* userspace just supplied us with counters */
Florian Westphal49facff2010-02-07 02:48:47 +01001271static int do_update_counters(struct net *net, const char *name,
1272 struct ebt_counter __user *counters,
1273 unsigned int num_counters,
1274 const void __user *user, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275{
1276 int i, ret;
1277 struct ebt_counter *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 struct ebt_table *t;
1279
Florian Westphal49facff2010-02-07 02:48:47 +01001280 if (num_counters == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 return -EINVAL;
1282
Florian Westphal49facff2010-02-07 02:48:47 +01001283 tmp = vmalloc(num_counters * sizeof(*tmp));
1284 if (!tmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Florian Westphal49facff2010-02-07 02:48:47 +01001287 t = find_table_lock(net, name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 if (!t)
1289 goto free_tmp;
1290
Florian Westphal49facff2010-02-07 02:48:47 +01001291 if (num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 BUGPRINT("Wrong nr of counters\n");
1293 ret = -EINVAL;
1294 goto unlock_mutex;
1295 }
1296
Florian Westphal49facff2010-02-07 02:48:47 +01001297 if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 ret = -EFAULT;
1299 goto unlock_mutex;
1300 }
1301
1302 /* we want an atomic add of the counters */
1303 write_lock_bh(&t->lock);
1304
1305 /* we add to the counters of the first cpu */
Florian Westphal49facff2010-02-07 02:48:47 +01001306 for (i = 0; i < num_counters; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 t->private->counters[i].pcnt += tmp[i].pcnt;
1308 t->private->counters[i].bcnt += tmp[i].bcnt;
1309 }
1310
1311 write_unlock_bh(&t->lock);
1312 ret = 0;
1313unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001314 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315free_tmp:
1316 vfree(tmp);
1317 return ret;
1318}
1319
Florian Westphal49facff2010-02-07 02:48:47 +01001320static int update_counters(struct net *net, const void __user *user,
1321 unsigned int len)
1322{
1323 struct ebt_replace hlp;
1324
1325 if (copy_from_user(&hlp, user, sizeof(hlp)))
1326 return -EFAULT;
1327
1328 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1329 return -EINVAL;
1330
1331 return do_update_counters(net, hlp.name, hlp.counters,
1332 hlp.num_counters, user, len);
1333}
1334
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001335static inline int ebt_make_matchname(const struct ebt_entry_match *m,
1336 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Al Viro1e419cd2006-11-30 19:28:48 -08001338 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1340 return -EFAULT;
1341 return 0;
1342}
1343
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001344static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
1345 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
Al Viro1e419cd2006-11-30 19:28:48 -08001347 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1349 return -EFAULT;
1350 return 0;
1351}
1352
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001353static inline int
1354ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355{
1356 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001357 char __user *hlp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001358 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Al Viro40642f92006-11-30 19:24:12 -08001360 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 return 0;
1362
Al Viro1e419cd2006-11-30 19:28:48 -08001363 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1367 if (ret != 0)
1368 return ret;
1369 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1370 if (ret != 0)
1371 return ret;
1372 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1373 return -EFAULT;
1374 return 0;
1375}
1376
Florian Westphal837395a2010-02-07 02:11:34 +01001377static int copy_counters_to_user(struct ebt_table *t,
1378 const struct ebt_counter *oldcounters,
1379 void __user *user, unsigned int num_counters,
1380 unsigned int nentries)
1381{
1382 struct ebt_counter *counterstmp;
1383 int ret = 0;
1384
1385 /* userspace might not need the counters */
1386 if (num_counters == 0)
1387 return 0;
1388
1389 if (num_counters != nentries) {
1390 BUGPRINT("Num_counters wrong\n");
1391 return -EINVAL;
1392 }
1393
1394 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1395 if (!counterstmp)
1396 return -ENOMEM;
1397
1398 write_lock_bh(&t->lock);
1399 get_counters(oldcounters, counterstmp, nentries);
1400 write_unlock_bh(&t->lock);
1401
1402 if (copy_to_user(user, counterstmp,
1403 nentries * sizeof(struct ebt_counter)))
1404 ret = -EFAULT;
1405 vfree(counterstmp);
1406 return ret;
1407}
1408
Ingo Molnar57b47a52006-03-20 22:35:41 -08001409/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410static int copy_everything_to_user(struct ebt_table *t, void __user *user,
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001411 const int *len, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412{
1413 struct ebt_replace tmp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001414 const struct ebt_counter *oldcounters;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 unsigned int entries_size, nentries;
Florian Westphal837395a2010-02-07 02:11:34 +01001416 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 char *entries;
1418
1419 if (cmd == EBT_SO_GET_ENTRIES) {
1420 entries_size = t->private->entries_size;
1421 nentries = t->private->nentries;
1422 entries = t->private->entries;
1423 oldcounters = t->private->counters;
1424 } else {
1425 entries_size = t->table->entries_size;
1426 nentries = t->table->nentries;
1427 entries = t->table->entries;
1428 oldcounters = t->table->counters;
1429 }
1430
1431 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1432 BUGPRINT("Cfu didn't work\n");
1433 return -EFAULT;
1434 }
1435
1436 if (*len != sizeof(struct ebt_replace) + entries_size +
1437 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1438 BUGPRINT("Wrong size\n");
1439 return -EINVAL;
1440 }
1441
1442 if (tmp.nentries != nentries) {
1443 BUGPRINT("Nentries wrong\n");
1444 return -EINVAL;
1445 }
1446
1447 if (tmp.entries_size != entries_size) {
1448 BUGPRINT("Wrong size\n");
1449 return -EINVAL;
1450 }
1451
Florian Westphal837395a2010-02-07 02:11:34 +01001452 ret = copy_counters_to_user(t, oldcounters, tmp.counters,
1453 tmp.num_counters, nentries);
1454 if (ret)
1455 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 if (copy_to_user(tmp.entries, entries, entries_size)) {
1458 BUGPRINT("Couldn't copy entries to userspace\n");
1459 return -EFAULT;
1460 }
1461 /* set the match/watcher/target names right */
1462 return EBT_ENTRY_ITERATE(entries, entries_size,
1463 ebt_make_names, entries, tmp.entries);
1464}
1465
1466static int do_ebt_set_ctl(struct sock *sk,
1467 int cmd, void __user *user, unsigned int len)
1468{
1469 int ret;
1470
Florian Westphaldce766a2010-01-08 17:31:24 +01001471 if (!capable(CAP_NET_ADMIN))
1472 return -EPERM;
1473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 switch(cmd) {
1475 case EBT_SO_SET_ENTRIES:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001476 ret = do_replace(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 break;
1478 case EBT_SO_SET_COUNTERS:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001479 ret = update_counters(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 break;
1481 default:
1482 ret = -EINVAL;
Florian Westphal81e675c2010-01-05 16:09:46 +01001483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 return ret;
1485}
1486
1487static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1488{
1489 int ret;
1490 struct ebt_replace tmp;
1491 struct ebt_table *t;
1492
Florian Westphaldce766a2010-01-08 17:31:24 +01001493 if (!capable(CAP_NET_ADMIN))
1494 return -EPERM;
1495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if (copy_from_user(&tmp, user, sizeof(tmp)))
1497 return -EFAULT;
1498
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001499 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if (!t)
1501 return ret;
1502
1503 switch(cmd) {
1504 case EBT_SO_GET_INFO:
1505 case EBT_SO_GET_INIT_INFO:
1506 if (*len != sizeof(struct ebt_replace)){
1507 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001508 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 break;
1510 }
1511 if (cmd == EBT_SO_GET_INFO) {
1512 tmp.nentries = t->private->nentries;
1513 tmp.entries_size = t->private->entries_size;
1514 tmp.valid_hooks = t->valid_hooks;
1515 } else {
1516 tmp.nentries = t->table->nentries;
1517 tmp.entries_size = t->table->entries_size;
1518 tmp.valid_hooks = t->table->valid_hooks;
1519 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001520 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 if (copy_to_user(user, &tmp, *len) != 0){
1522 BUGPRINT("c2u Didn't work\n");
1523 ret = -EFAULT;
1524 break;
1525 }
1526 ret = 0;
1527 break;
1528
1529 case EBT_SO_GET_ENTRIES:
1530 case EBT_SO_GET_INIT_ENTRIES:
1531 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001532 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 break;
1534
1535 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001536 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 ret = -EINVAL;
1538 }
1539
1540 return ret;
1541}
1542
Florian Westphal81e675c2010-01-05 16:09:46 +01001543#ifdef CONFIG_COMPAT
1544/* 32 bit-userspace compatibility definitions. */
1545struct compat_ebt_replace {
1546 char name[EBT_TABLE_MAXNAMELEN];
1547 compat_uint_t valid_hooks;
1548 compat_uint_t nentries;
1549 compat_uint_t entries_size;
1550 /* start of the chains */
1551 compat_uptr_t hook_entry[NF_BR_NUMHOOKS];
1552 /* nr of counters userspace expects back */
1553 compat_uint_t num_counters;
1554 /* where the kernel will put the old counters. */
1555 compat_uptr_t counters;
1556 compat_uptr_t entries;
1557};
1558
1559/* struct ebt_entry_match, _target and _watcher have same layout */
1560struct compat_ebt_entry_mwt {
1561 union {
1562 char name[EBT_FUNCTION_MAXNAMELEN];
1563 compat_uptr_t ptr;
1564 } u;
1565 compat_uint_t match_size;
1566 compat_uint_t data[0];
1567};
1568
1569/* account for possible padding between match_size and ->data */
1570static int ebt_compat_entry_padsize(void)
1571{
1572 BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
1573 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
1574 return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
1575 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
1576}
1577
1578static int ebt_compat_match_offset(const struct xt_match *match,
1579 unsigned int userlen)
1580{
1581 /*
1582 * ebt_among needs special handling. The kernel .matchsize is
1583 * set to -1 at registration time; at runtime an EBT_ALIGN()ed
1584 * value is expected.
1585 * Example: userspace sends 4500, ebt_among.c wants 4504.
1586 */
1587 if (unlikely(match->matchsize == -1))
1588 return XT_ALIGN(userlen) - COMPAT_XT_ALIGN(userlen);
1589 return xt_compat_match_offset(match);
1590}
1591
1592static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
1593 unsigned int *size)
1594{
1595 const struct xt_match *match = m->u.match;
1596 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1597 int off = ebt_compat_match_offset(match, m->match_size);
1598 compat_uint_t msize = m->match_size - off;
1599
1600 BUG_ON(off >= m->match_size);
1601
1602 if (copy_to_user(cm->u.name, match->name,
1603 strlen(match->name) + 1) || put_user(msize, &cm->match_size))
1604 return -EFAULT;
1605
1606 if (match->compat_to_user) {
1607 if (match->compat_to_user(cm->data, m->data))
1608 return -EFAULT;
1609 } else if (copy_to_user(cm->data, m->data, msize))
1610 return -EFAULT;
1611
1612 *size -= ebt_compat_entry_padsize() + off;
1613 *dstptr = cm->data;
1614 *dstptr += msize;
1615 return 0;
1616}
1617
1618static int compat_target_to_user(struct ebt_entry_target *t,
1619 void __user **dstptr,
1620 unsigned int *size)
1621{
1622 const struct xt_target *target = t->u.target;
1623 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1624 int off = xt_compat_target_offset(target);
1625 compat_uint_t tsize = t->target_size - off;
1626
1627 BUG_ON(off >= t->target_size);
1628
1629 if (copy_to_user(cm->u.name, target->name,
1630 strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
1631 return -EFAULT;
1632
1633 if (target->compat_to_user) {
1634 if (target->compat_to_user(cm->data, t->data))
1635 return -EFAULT;
1636 } else if (copy_to_user(cm->data, t->data, tsize))
1637 return -EFAULT;
1638
1639 *size -= ebt_compat_entry_padsize() + off;
1640 *dstptr = cm->data;
1641 *dstptr += tsize;
1642 return 0;
1643}
1644
1645static int compat_watcher_to_user(struct ebt_entry_watcher *w,
1646 void __user **dstptr,
1647 unsigned int *size)
1648{
1649 return compat_target_to_user((struct ebt_entry_target *)w,
1650 dstptr, size);
1651}
1652
1653static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr,
1654 unsigned int *size)
1655{
1656 struct ebt_entry_target *t;
1657 struct ebt_entry __user *ce;
1658 u32 watchers_offset, target_offset, next_offset;
1659 compat_uint_t origsize;
1660 int ret;
1661
1662 if (e->bitmask == 0) {
1663 if (*size < sizeof(struct ebt_entries))
1664 return -EINVAL;
1665 if (copy_to_user(*dstptr, e, sizeof(struct ebt_entries)))
1666 return -EFAULT;
1667
1668 *dstptr += sizeof(struct ebt_entries);
1669 *size -= sizeof(struct ebt_entries);
1670 return 0;
1671 }
1672
1673 if (*size < sizeof(*ce))
1674 return -EINVAL;
1675
1676 ce = (struct ebt_entry __user *)*dstptr;
1677 if (copy_to_user(ce, e, sizeof(*ce)))
1678 return -EFAULT;
1679
1680 origsize = *size;
1681 *dstptr += sizeof(*ce);
1682
1683 ret = EBT_MATCH_ITERATE(e, compat_match_to_user, dstptr, size);
1684 if (ret)
1685 return ret;
1686 watchers_offset = e->watchers_offset - (origsize - *size);
1687
1688 ret = EBT_WATCHER_ITERATE(e, compat_watcher_to_user, dstptr, size);
1689 if (ret)
1690 return ret;
1691 target_offset = e->target_offset - (origsize - *size);
1692
1693 t = (struct ebt_entry_target *) ((char *) e + e->target_offset);
1694
1695 ret = compat_target_to_user(t, dstptr, size);
1696 if (ret)
1697 return ret;
1698 next_offset = e->next_offset - (origsize - *size);
1699
1700 if (put_user(watchers_offset, &ce->watchers_offset) ||
1701 put_user(target_offset, &ce->target_offset) ||
1702 put_user(next_offset, &ce->next_offset))
1703 return -EFAULT;
1704
1705 *size -= sizeof(*ce);
1706 return 0;
1707}
1708
1709static int compat_calc_match(struct ebt_entry_match *m, int *off)
1710{
1711 *off += ebt_compat_match_offset(m->u.match, m->match_size);
1712 *off += ebt_compat_entry_padsize();
1713 return 0;
1714}
1715
1716static int compat_calc_watcher(struct ebt_entry_watcher *w, int *off)
1717{
1718 *off += xt_compat_target_offset(w->u.watcher);
1719 *off += ebt_compat_entry_padsize();
1720 return 0;
1721}
1722
1723static int compat_calc_entry(const struct ebt_entry *e,
1724 const struct ebt_table_info *info,
1725 const void *base,
1726 struct compat_ebt_replace *newinfo)
1727{
1728 const struct ebt_entry_target *t;
1729 unsigned int entry_offset;
1730 int off, ret, i;
1731
1732 if (e->bitmask == 0)
1733 return 0;
1734
1735 off = 0;
1736 entry_offset = (void *)e - base;
1737
1738 EBT_MATCH_ITERATE(e, compat_calc_match, &off);
1739 EBT_WATCHER_ITERATE(e, compat_calc_watcher, &off);
1740
1741 t = (const struct ebt_entry_target *) ((char *) e + e->target_offset);
1742
1743 off += xt_compat_target_offset(t->u.target);
1744 off += ebt_compat_entry_padsize();
1745
1746 newinfo->entries_size -= off;
1747
1748 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, off);
1749 if (ret)
1750 return ret;
1751
1752 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1753 const void *hookptr = info->hook_entry[i];
1754 if (info->hook_entry[i] &&
1755 (e < (struct ebt_entry *)(base - hookptr))) {
1756 newinfo->hook_entry[i] -= off;
1757 pr_debug("0x%08X -> 0x%08X\n",
1758 newinfo->hook_entry[i] + off,
1759 newinfo->hook_entry[i]);
1760 }
1761 }
1762
1763 return 0;
1764}
1765
1766
1767static int compat_table_info(const struct ebt_table_info *info,
1768 struct compat_ebt_replace *newinfo)
1769{
1770 unsigned int size = info->entries_size;
1771 const void *entries = info->entries;
1772
1773 newinfo->entries_size = size;
1774
1775 return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
1776 entries, newinfo);
1777}
1778
1779static int compat_copy_everything_to_user(struct ebt_table *t,
1780 void __user *user, int *len, int cmd)
1781{
1782 struct compat_ebt_replace repl, tmp;
1783 struct ebt_counter *oldcounters;
1784 struct ebt_table_info tinfo;
1785 int ret;
1786 void __user *pos;
1787
1788 memset(&tinfo, 0, sizeof(tinfo));
1789
1790 if (cmd == EBT_SO_GET_ENTRIES) {
1791 tinfo.entries_size = t->private->entries_size;
1792 tinfo.nentries = t->private->nentries;
1793 tinfo.entries = t->private->entries;
1794 oldcounters = t->private->counters;
1795 } else {
1796 tinfo.entries_size = t->table->entries_size;
1797 tinfo.nentries = t->table->nentries;
1798 tinfo.entries = t->table->entries;
1799 oldcounters = t->table->counters;
1800 }
1801
1802 if (copy_from_user(&tmp, user, sizeof(tmp)))
1803 return -EFAULT;
1804
1805 if (tmp.nentries != tinfo.nentries ||
1806 (tmp.num_counters && tmp.num_counters != tinfo.nentries))
1807 return -EINVAL;
1808
1809 memcpy(&repl, &tmp, sizeof(repl));
1810 if (cmd == EBT_SO_GET_ENTRIES)
1811 ret = compat_table_info(t->private, &repl);
1812 else
1813 ret = compat_table_info(&tinfo, &repl);
1814 if (ret)
1815 return ret;
1816
1817 if (*len != sizeof(tmp) + repl.entries_size +
1818 (tmp.num_counters? tinfo.nentries * sizeof(struct ebt_counter): 0)) {
1819 pr_err("wrong size: *len %d, entries_size %u, replsz %d\n",
1820 *len, tinfo.entries_size, repl.entries_size);
1821 return -EINVAL;
1822 }
1823
1824 /* userspace might not need the counters */
1825 ret = copy_counters_to_user(t, oldcounters, compat_ptr(tmp.counters),
1826 tmp.num_counters, tinfo.nentries);
1827 if (ret)
1828 return ret;
1829
1830 pos = compat_ptr(tmp.entries);
1831 return EBT_ENTRY_ITERATE(tinfo.entries, tinfo.entries_size,
1832 compat_copy_entry_to_user, &pos, &tmp.entries_size);
1833}
1834
1835struct ebt_entries_buf_state {
1836 char *buf_kern_start; /* kernel buffer to copy (translated) data to */
1837 u32 buf_kern_len; /* total size of kernel buffer */
1838 u32 buf_kern_offset; /* amount of data copied so far */
1839 u32 buf_user_offset; /* read position in userspace buffer */
1840};
1841
1842static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
1843{
1844 state->buf_kern_offset += sz;
1845 return state->buf_kern_offset >= sz ? 0 : -EINVAL;
1846}
1847
1848static int ebt_buf_add(struct ebt_entries_buf_state *state,
1849 void *data, unsigned int sz)
1850{
1851 if (state->buf_kern_start == NULL)
1852 goto count_only;
1853
1854 BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
1855
1856 memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
1857
1858 count_only:
1859 state->buf_user_offset += sz;
1860 return ebt_buf_count(state, sz);
1861}
1862
1863static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz)
1864{
1865 char *b = state->buf_kern_start;
1866
1867 BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
1868
1869 if (b != NULL && sz > 0)
1870 memset(b + state->buf_kern_offset, 0, sz);
1871 /* do not adjust ->buf_user_offset here, we added kernel-side padding */
1872 return ebt_buf_count(state, sz);
1873}
1874
1875enum compat_mwt {
1876 EBT_COMPAT_MATCH,
1877 EBT_COMPAT_WATCHER,
1878 EBT_COMPAT_TARGET,
1879};
1880
1881static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
1882 enum compat_mwt compat_mwt,
1883 struct ebt_entries_buf_state *state,
1884 const unsigned char *base)
1885{
1886 char name[EBT_FUNCTION_MAXNAMELEN];
1887 struct xt_match *match;
1888 struct xt_target *wt;
1889 void *dst = NULL;
1890 int off, pad = 0, ret = 0;
1891 unsigned int size_kern, entry_offset, match_size = mwt->match_size;
1892
1893 strlcpy(name, mwt->u.name, sizeof(name));
1894
1895 if (state->buf_kern_start)
1896 dst = state->buf_kern_start + state->buf_kern_offset;
1897
1898 entry_offset = (unsigned char *) mwt - base;
1899 switch (compat_mwt) {
1900 case EBT_COMPAT_MATCH:
1901 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
1902 name, 0), "ebt_%s", name);
1903 if (match == NULL)
1904 return -ENOENT;
1905 if (IS_ERR(match))
1906 return PTR_ERR(match);
1907
1908 off = ebt_compat_match_offset(match, match_size);
1909 if (dst) {
1910 if (match->compat_from_user)
1911 match->compat_from_user(dst, mwt->data);
1912 else
1913 memcpy(dst, mwt->data, match_size);
1914 }
1915
1916 size_kern = match->matchsize;
1917 if (unlikely(size_kern == -1))
1918 size_kern = match_size;
1919 module_put(match->me);
1920 break;
1921 case EBT_COMPAT_WATCHER: /* fallthrough */
1922 case EBT_COMPAT_TARGET:
1923 wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE,
1924 name, 0), "ebt_%s", name);
1925 if (wt == NULL)
1926 return -ENOENT;
1927 if (IS_ERR(wt))
1928 return PTR_ERR(wt);
1929 off = xt_compat_target_offset(wt);
1930
1931 if (dst) {
1932 if (wt->compat_from_user)
1933 wt->compat_from_user(dst, mwt->data);
1934 else
1935 memcpy(dst, mwt->data, match_size);
1936 }
1937
1938 size_kern = wt->targetsize;
1939 module_put(wt->me);
1940 break;
1941 }
1942
1943 if (!dst) {
1944 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
1945 off + ebt_compat_entry_padsize());
1946 if (ret < 0)
1947 return ret;
1948 }
1949
1950 state->buf_kern_offset += match_size + off;
1951 state->buf_user_offset += match_size;
1952 pad = XT_ALIGN(size_kern) - size_kern;
1953
1954 if (pad > 0 && dst) {
1955 BUG_ON(state->buf_kern_len <= pad);
1956 BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
1957 memset(dst + size_kern, 0, pad);
1958 }
1959 return off + match_size;
1960}
1961
1962/*
1963 * return size of all matches, watchers or target, including necessary
1964 * alignment and padding.
1965 */
1966static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
1967 unsigned int size_left, enum compat_mwt type,
1968 struct ebt_entries_buf_state *state, const void *base)
1969{
1970 int growth = 0;
1971 char *buf;
1972
1973 if (size_left == 0)
1974 return 0;
1975
1976 buf = (char *) match32;
1977
1978 while (size_left >= sizeof(*match32)) {
1979 struct ebt_entry_match *match_kern;
1980 int ret;
1981
1982 match_kern = (struct ebt_entry_match *) state->buf_kern_start;
1983 if (match_kern) {
1984 char *tmp;
1985 tmp = state->buf_kern_start + state->buf_kern_offset;
1986 match_kern = (struct ebt_entry_match *) tmp;
1987 }
1988 ret = ebt_buf_add(state, buf, sizeof(*match32));
1989 if (ret < 0)
1990 return ret;
1991 size_left -= sizeof(*match32);
1992
1993 /* add padding before match->data (if any) */
1994 ret = ebt_buf_add_pad(state, ebt_compat_entry_padsize());
1995 if (ret < 0)
1996 return ret;
1997
1998 if (match32->match_size > size_left)
1999 return -EINVAL;
2000
2001 size_left -= match32->match_size;
2002
2003 ret = compat_mtw_from_user(match32, type, state, base);
2004 if (ret < 0)
2005 return ret;
2006
2007 BUG_ON(ret < match32->match_size);
2008 growth += ret - match32->match_size;
2009 growth += ebt_compat_entry_padsize();
2010
2011 buf += sizeof(*match32);
2012 buf += match32->match_size;
2013
2014 if (match_kern)
2015 match_kern->match_size = ret;
2016
2017 WARN_ON(type == EBT_COMPAT_TARGET && size_left);
2018 match32 = (struct compat_ebt_entry_mwt *) buf;
2019 }
2020
2021 return growth;
2022}
2023
2024#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \
2025({ \
2026 unsigned int __i; \
2027 int __ret = 0; \
2028 struct compat_ebt_entry_mwt *__watcher; \
2029 \
2030 for (__i = e->watchers_offset; \
2031 __i < (e)->target_offset; \
2032 __i += __watcher->watcher_size + \
2033 sizeof(struct compat_ebt_entry_mwt)) { \
2034 __watcher = (void *)(e) + __i; \
2035 __ret = fn(__watcher , ## args); \
2036 if (__ret != 0) \
2037 break; \
2038 } \
2039 if (__ret == 0) { \
2040 if (__i != (e)->target_offset) \
2041 __ret = -EINVAL; \
2042 } \
2043 __ret; \
2044})
2045
2046#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \
2047({ \
2048 unsigned int __i; \
2049 int __ret = 0; \
2050 struct compat_ebt_entry_mwt *__match; \
2051 \
2052 for (__i = sizeof(struct ebt_entry); \
2053 __i < (e)->watchers_offset; \
2054 __i += __match->match_size + \
2055 sizeof(struct compat_ebt_entry_mwt)) { \
2056 __match = (void *)(e) + __i; \
2057 __ret = fn(__match , ## args); \
2058 if (__ret != 0) \
2059 break; \
2060 } \
2061 if (__ret == 0) { \
2062 if (__i != (e)->watchers_offset) \
2063 __ret = -EINVAL; \
2064 } \
2065 __ret; \
2066})
2067
2068/* called for all ebt_entry structures. */
2069static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
2070 unsigned int *total,
2071 struct ebt_entries_buf_state *state)
2072{
2073 unsigned int i, j, startoff, new_offset = 0;
2074 /* stores match/watchers/targets & offset of next struct ebt_entry: */
2075 unsigned int offsets[4];
2076 unsigned int *offsets_update = NULL;
2077 int ret;
2078 char *buf_start;
2079
2080 if (*total < sizeof(struct ebt_entries))
2081 return -EINVAL;
2082
2083 if (!entry->bitmask) {
2084 *total -= sizeof(struct ebt_entries);
2085 return ebt_buf_add(state, entry, sizeof(struct ebt_entries));
2086 }
2087 if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry))
2088 return -EINVAL;
2089
2090 startoff = state->buf_user_offset;
2091 /* pull in most part of ebt_entry, it does not need to be changed. */
2092 ret = ebt_buf_add(state, entry,
2093 offsetof(struct ebt_entry, watchers_offset));
2094 if (ret < 0)
2095 return ret;
2096
2097 offsets[0] = sizeof(struct ebt_entry); /* matches come first */
2098 memcpy(&offsets[1], &entry->watchers_offset,
2099 sizeof(offsets) - sizeof(offsets[0]));
2100
2101 if (state->buf_kern_start) {
2102 buf_start = state->buf_kern_start + state->buf_kern_offset;
2103 offsets_update = (unsigned int *) buf_start;
2104 }
2105 ret = ebt_buf_add(state, &offsets[1],
2106 sizeof(offsets) - sizeof(offsets[0]));
2107 if (ret < 0)
2108 return ret;
2109 buf_start = (char *) entry;
2110 /*
2111 * 0: matches offset, always follows ebt_entry.
2112 * 1: watchers offset, from ebt_entry structure
2113 * 2: target offset, from ebt_entry structure
2114 * 3: next ebt_entry offset, from ebt_entry structure
2115 *
2116 * offsets are relative to beginning of struct ebt_entry (i.e., 0).
2117 */
2118 for (i = 0, j = 1 ; j < 4 ; j++, i++) {
2119 struct compat_ebt_entry_mwt *match32;
2120 unsigned int size;
2121 char *buf = buf_start;
2122
2123 buf = buf_start + offsets[i];
2124 if (offsets[i] > offsets[j])
2125 return -EINVAL;
2126
2127 match32 = (struct compat_ebt_entry_mwt *) buf;
2128 size = offsets[j] - offsets[i];
2129 ret = ebt_size_mwt(match32, size, i, state, base);
2130 if (ret < 0)
2131 return ret;
2132 new_offset += ret;
2133 if (offsets_update && new_offset) {
2134 pr_debug("ebtables: change offset %d to %d\n",
2135 offsets_update[i], offsets[j] + new_offset);
2136 offsets_update[i] = offsets[j] + new_offset;
2137 }
2138 }
2139
2140 startoff = state->buf_user_offset - startoff;
2141
2142 BUG_ON(*total < startoff);
2143 *total -= startoff;
2144 return 0;
2145}
2146
2147/*
2148 * repl->entries_size is the size of the ebt_entry blob in userspace.
2149 * It might need more memory when copied to a 64 bit kernel in case
2150 * userspace is 32-bit. So, first task: find out how much memory is needed.
2151 *
2152 * Called before validation is performed.
2153 */
2154static int compat_copy_entries(unsigned char *data, unsigned int size_user,
2155 struct ebt_entries_buf_state *state)
2156{
2157 unsigned int size_remaining = size_user;
2158 int ret;
2159
2160 ret = EBT_ENTRY_ITERATE(data, size_user, size_entry_mwt, data,
2161 &size_remaining, state);
2162 if (ret < 0)
2163 return ret;
2164
2165 WARN_ON(size_remaining);
2166 return state->buf_kern_offset;
2167}
2168
2169
2170static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2171 void __user *user, unsigned int len)
2172{
2173 struct compat_ebt_replace tmp;
2174 int i;
2175
2176 if (len < sizeof(tmp))
2177 return -EINVAL;
2178
2179 if (copy_from_user(&tmp, user, sizeof(tmp)))
2180 return -EFAULT;
2181
2182 if (len != sizeof(tmp) + tmp.entries_size)
2183 return -EINVAL;
2184
2185 if (tmp.entries_size == 0)
2186 return -EINVAL;
2187
2188 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
2189 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
2190 return -ENOMEM;
2191 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
2192 return -ENOMEM;
2193
2194 memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
2195
2196 /* starting with hook_entry, 32 vs. 64 bit structures are different */
2197 for (i = 0; i < NF_BR_NUMHOOKS; i++)
2198 repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]);
2199
2200 repl->num_counters = tmp.num_counters;
2201 repl->counters = compat_ptr(tmp.counters);
2202 repl->entries = compat_ptr(tmp.entries);
2203 return 0;
2204}
2205
2206static int compat_do_replace(struct net *net, void __user *user,
2207 unsigned int len)
2208{
2209 int ret, i, countersize, size64;
2210 struct ebt_table_info *newinfo;
2211 struct ebt_replace tmp;
2212 struct ebt_entries_buf_state state;
2213 void *entries_tmp;
2214
2215 ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
2216 if (ret)
2217 return ret;
2218
2219 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
2220 newinfo = vmalloc(sizeof(*newinfo) + countersize);
2221 if (!newinfo)
2222 return -ENOMEM;
2223
2224 if (countersize)
2225 memset(newinfo->counters, 0, countersize);
2226
2227 memset(&state, 0, sizeof(state));
2228
2229 newinfo->entries = vmalloc(tmp.entries_size);
2230 if (!newinfo->entries) {
2231 ret = -ENOMEM;
2232 goto free_newinfo;
2233 }
2234 if (copy_from_user(
2235 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
2236 ret = -EFAULT;
2237 goto free_entries;
2238 }
2239
2240 entries_tmp = newinfo->entries;
2241
2242 xt_compat_lock(NFPROTO_BRIDGE);
2243
2244 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2245 if (ret < 0)
2246 goto out_unlock;
2247
2248 pr_debug("tmp.entries_size %d, kern off %d, user off %d delta %d\n",
2249 tmp.entries_size, state.buf_kern_offset, state.buf_user_offset,
2250 xt_compat_calc_jump(NFPROTO_BRIDGE, tmp.entries_size));
2251
2252 size64 = ret;
2253 newinfo->entries = vmalloc(size64);
2254 if (!newinfo->entries) {
2255 vfree(entries_tmp);
2256 ret = -ENOMEM;
2257 goto out_unlock;
2258 }
2259
2260 memset(&state, 0, sizeof(state));
2261 state.buf_kern_start = newinfo->entries;
2262 state.buf_kern_len = size64;
2263
2264 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2265 BUG_ON(ret < 0); /* parses same data again */
2266
2267 vfree(entries_tmp);
2268 tmp.entries_size = size64;
2269
2270 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
2271 char __user *usrptr;
2272 if (tmp.hook_entry[i]) {
2273 unsigned int delta;
2274 usrptr = (char __user *) tmp.hook_entry[i];
2275 delta = usrptr - tmp.entries;
2276 usrptr += xt_compat_calc_jump(NFPROTO_BRIDGE, delta);
2277 tmp.hook_entry[i] = (struct ebt_entries __user *)usrptr;
2278 }
2279 }
2280
2281 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2282 xt_compat_unlock(NFPROTO_BRIDGE);
2283
2284 ret = do_replace_finish(net, &tmp, newinfo);
2285 if (ret == 0)
2286 return ret;
2287free_entries:
2288 vfree(newinfo->entries);
2289free_newinfo:
2290 vfree(newinfo);
2291 return ret;
2292out_unlock:
2293 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2294 xt_compat_unlock(NFPROTO_BRIDGE);
2295 goto free_entries;
2296}
2297
2298static int compat_update_counters(struct net *net, void __user *user,
2299 unsigned int len)
2300{
2301 struct compat_ebt_replace hlp;
2302
2303 if (copy_from_user(&hlp, user, sizeof(hlp)))
2304 return -EFAULT;
2305
2306 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
2307 return -EINVAL;
2308
2309 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2310 hlp.num_counters, user, len);
2311}
2312
2313static int compat_do_ebt_set_ctl(struct sock *sk,
2314 int cmd, void __user *user, unsigned int len)
2315{
2316 int ret;
2317
2318 if (!capable(CAP_NET_ADMIN))
2319 return -EPERM;
2320
2321 switch (cmd) {
2322 case EBT_SO_SET_ENTRIES:
2323 ret = compat_do_replace(sock_net(sk), user, len);
2324 break;
2325 case EBT_SO_SET_COUNTERS:
2326 ret = compat_update_counters(sock_net(sk), user, len);
2327 break;
2328 default:
2329 ret = -EINVAL;
2330 }
2331 return ret;
2332}
2333
2334static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2335 void __user *user, int *len)
2336{
2337 int ret;
2338 struct compat_ebt_replace tmp;
2339 struct ebt_table *t;
2340
2341 if (!capable(CAP_NET_ADMIN))
2342 return -EPERM;
2343
2344 if ((cmd == EBT_SO_GET_INFO ||
2345 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
2346 return -EINVAL;
2347
2348 if (copy_from_user(&tmp, user, sizeof(tmp)))
2349 return -EFAULT;
2350
2351 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
2352 if (!t)
2353 return ret;
2354
2355 xt_compat_lock(NFPROTO_BRIDGE);
2356 switch (cmd) {
2357 case EBT_SO_GET_INFO:
2358 tmp.nentries = t->private->nentries;
2359 ret = compat_table_info(t->private, &tmp);
2360 if (ret)
2361 goto out;
2362 tmp.valid_hooks = t->valid_hooks;
2363
2364 if (copy_to_user(user, &tmp, *len) != 0) {
2365 ret = -EFAULT;
2366 break;
2367 }
2368 ret = 0;
2369 break;
2370 case EBT_SO_GET_INIT_INFO:
2371 tmp.nentries = t->table->nentries;
2372 tmp.entries_size = t->table->entries_size;
2373 tmp.valid_hooks = t->table->valid_hooks;
2374
2375 if (copy_to_user(user, &tmp, *len) != 0) {
2376 ret = -EFAULT;
2377 break;
2378 }
2379 ret = 0;
2380 break;
2381 case EBT_SO_GET_ENTRIES:
2382 case EBT_SO_GET_INIT_ENTRIES:
2383 ret = compat_copy_everything_to_user(t, user, len, cmd);
2384 break;
2385 default:
2386 ret = -EINVAL;
2387 }
2388 out:
2389 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2390 xt_compat_unlock(NFPROTO_BRIDGE);
2391 mutex_unlock(&ebt_mutex);
2392 return ret;
2393}
2394#endif
2395
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002397{
2398 .pf = PF_INET,
2399 .set_optmin = EBT_BASE_CTL,
2400 .set_optmax = EBT_SO_SET_MAX + 1,
2401 .set = do_ebt_set_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002402#ifdef CONFIG_COMPAT
2403 .compat_set = compat_do_ebt_set_ctl,
2404#endif
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002405 .get_optmin = EBT_BASE_CTL,
2406 .get_optmax = EBT_SO_GET_MAX + 1,
2407 .get = do_ebt_get_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002408#ifdef CONFIG_COMPAT
2409 .compat_get = compat_do_ebt_get_ctl,
2410#endif
Neil Horman16fcec32007-09-11 11:28:26 +02002411 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412};
2413
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002414static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415{
2416 int ret;
2417
Jan Engelhardt043ef462008-10-08 11:35:15 +02002418 ret = xt_register_target(&ebt_standard_target);
2419 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 return ret;
Jan Engelhardt043ef462008-10-08 11:35:15 +02002421 ret = nf_register_sockopt(&ebt_sockopts);
2422 if (ret < 0) {
2423 xt_unregister_target(&ebt_standard_target);
2424 return ret;
2425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Patrick McHardya887c1c2007-07-14 20:46:15 -07002427 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 return 0;
2429}
2430
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002431static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432{
2433 nf_unregister_sockopt(&ebt_sockopts);
Jan Engelhardt043ef462008-10-08 11:35:15 +02002434 xt_unregister_target(&ebt_standard_target);
Patrick McHardya887c1c2007-07-14 20:46:15 -07002435 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436}
2437
2438EXPORT_SYMBOL(ebt_register_table);
2439EXPORT_SYMBOL(ebt_unregister_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002441module_init(ebtables_init);
2442module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443MODULE_LICENSE("GPL");