blob: 290d43541d46c32c04ab01e959cd98fcc1111b4d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ebtables
3 *
4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * ebtables.c,v 2.0, July, 2002
8 *
9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
Jan Engelhardtff67e4e2010-03-19 21:08:16 +010017#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/kmod.h>
19#include <linux/module.h>
20#include <linux/vmalloc.h>
Jan Engelhardt18219d32008-10-08 11:35:13 +020021#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/netfilter_bridge/ebtables.h>
23#include <linux/spinlock.h>
Patrick McHardydf0933d2006-09-20 11:57:53 -070024#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/uaccess.h>
27#include <linux/smp.h>
David S. Millerc8923c62005-10-13 14:41:23 -070028#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <net/sock.h>
30/* needed for logical [in,out]-dev filtering */
31#include "../br_private.h"
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +090034 "report to author: "format, ## args)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/* #define BUGPRINT(format, args...) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37/*
38 * Each cpu has its own set of counters, so there is no need for write_lock in
39 * the softirq
40 * For reading or updating the counters, the user context needs to
41 * get a write_lock
42 */
43
44/* The size of each set of counters is altered to get cache alignment */
45#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
46#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
47#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
48 COUNTER_OFFSET(n) * cpu))
49
50
51
Ingo Molnar57b47a52006-03-20 22:35:41 -080052static DEFINE_MUTEX(ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Florian Westphal81e675c2010-01-05 16:09:46 +010054#ifdef CONFIG_COMPAT
55static void ebt_standard_compat_from_user(void *dst, const void *src)
56{
57 int v = *(compat_int_t *)src;
58
59 if (v >= 0)
60 v += xt_compat_calc_jump(NFPROTO_BRIDGE, v);
61 memcpy(dst, &v, sizeof(v));
62}
63
64static int ebt_standard_compat_to_user(void __user *dst, const void *src)
65{
66 compat_int_t cv = *(int *)src;
67
68 if (cv >= 0)
69 cv -= xt_compat_calc_jump(NFPROTO_BRIDGE, cv);
70 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
71}
72#endif
73
74
Jan Engelhardt043ef462008-10-08 11:35:15 +020075static struct xt_target ebt_standard_target = {
Jan Engelhardt001a18d2008-10-08 11:35:14 +020076 .name = "standard",
77 .revision = 0,
78 .family = NFPROTO_BRIDGE,
Jan Engelhardt043ef462008-10-08 11:35:15 +020079 .targetsize = sizeof(int),
Florian Westphal81e675c2010-01-05 16:09:46 +010080#ifdef CONFIG_COMPAT
81 .compatsize = sizeof(compat_int_t),
82 .compat_from_user = ebt_standard_compat_from_user,
83 .compat_to_user = ebt_standard_compat_to_user,
84#endif
Jan Engelhardt18219d32008-10-08 11:35:13 +020085};
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Jan Engelhardt7eb35582008-10-08 11:35:19 +020087static inline int
88ebt_do_watcher(const struct ebt_entry_watcher *w, struct sk_buff *skb,
Jan Engelhardtde74c162009-07-05 18:26:37 +020089 struct xt_action_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020091 par->target = w->u.watcher;
92 par->targinfo = w->data;
93 w->u.watcher->target(skb, par);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 /* watchers don't give a verdict */
95 return 0;
96}
97
Jan Engelhardtde74c162009-07-05 18:26:37 +020098static inline int
99ebt_do_match(struct ebt_entry_match *m, const struct sk_buff *skb,
100 struct xt_action_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101{
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200102 par->match = m->u.match;
103 par->matchinfo = m->data;
Jan Engelhardtd61ba9f2009-01-12 00:06:06 +0000104 return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105}
106
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200107static inline int
108ebt_dev_check(const char *entry, const struct net_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
110 int i = 0;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000111 const char *devname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113 if (*entry == '\0')
114 return 0;
115 if (!device)
116 return 1;
Julia Lawallf3d8b2e2009-01-09 10:22:22 +0000117 devname = device->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 /* 1 is the wildcard token */
119 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
120 i++;
121 return (devname[i] != entry[i] && entry[i] != 1);
122}
123
124#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
125/* process standard matches */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200126static inline int
127ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
128 const struct net_device *in, const struct net_device *out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 int verdict, i;
131
132 if (e->bitmask & EBT_802_3) {
133 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
134 return 1;
135 } else if (!(e->bitmask & EBT_NOPROTO) &&
136 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
137 return 1;
138
139 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
140 return 1;
141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 return 1;
143 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
144 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
145 return 1;
146 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
147 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
148 return 1;
149
150 if (e->bitmask & EBT_SOURCEMAC) {
151 verdict = 0;
152 for (i = 0; i < 6; i++)
153 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
154 e->sourcemsk[i];
155 if (FWINV2(verdict != 0, EBT_ISOURCE) )
156 return 1;
157 }
158 if (e->bitmask & EBT_DESTMAC) {
159 verdict = 0;
160 for (i = 0; i < 6; i++)
161 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
162 e->destmsk[i];
163 if (FWINV2(verdict != 0, EBT_IDEST) )
164 return 1;
165 }
166 return 0;
167}
168
Jan Engelhardt98e86402009-04-15 21:06:05 +0200169static inline __pure
170struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)
171{
172 return (void *)entry + entry->next_offset;
173}
174
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175/* Do some firewalling */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700176unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 const struct net_device *in, const struct net_device *out,
178 struct ebt_table *table)
179{
180 int i, nentries;
181 struct ebt_entry *point;
182 struct ebt_counter *counter_base, *cb_base;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200183 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 int verdict, sp = 0;
185 struct ebt_chainstack *cs;
186 struct ebt_entries *chaininfo;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200187 const char *base;
188 const struct ebt_table_info *private;
Jan Engelhardt5365f802008-10-08 11:35:16 +0200189 bool hotdrop = false;
Jan Engelhardtde74c162009-07-05 18:26:37 +0200190 struct xt_action_param acpar;
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200191
Jan Engelhardtde74c162009-07-05 18:26:37 +0200192 acpar.family = NFPROTO_BRIDGE;
193 acpar.in = in;
194 acpar.out = out;
195 acpar.hotdrop = &hotdrop;
196 acpar.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 Engelhardtde74c162009-07-05 18:26:37 +0200217 if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 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 Engelhardtde74c162009-07-05 18:26:37 +0200230 EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar);
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 {
Jan Engelhardtde74c162009-07-05 18:26:37 +0200238 acpar.target = t->u.target;
239 acpar.targinfo = t->data;
240 verdict = t->u.target->target(skb, &acpar);
Jan Engelhardt7eb35582008-10-08 11:35:19 +0200241 }
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
Jan Engelhardtfd0ec0e2009-07-10 19:27:47 +0200365 match = xt_request_find_match(NFPROTO_BRIDGE, m->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200366 if (IS_ERR(match))
367 return PTR_ERR(match);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200368 m->u.match = match;
369
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200370 par->match = match;
371 par->matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200372 ret = xt_check_match(par, m->match_size,
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200373 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200374 if (ret < 0) {
375 module_put(match->me);
376 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 (*cnt)++;
380 return 0;
381}
382
383static inline int
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200384ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
385 unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200387 const struct ebt_entry *e = par->entryinfo;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200388 struct xt_target *watcher;
Al Viro14197d52006-11-30 19:25:21 -0800389 size_t left = ((char *)e + e->target_offset) - (char *)w;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 int ret;
391
Al Viro14197d52006-11-30 19:25:21 -0800392 if (left < sizeof(struct ebt_entry_watcher) ||
393 left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return -EINVAL;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200395
Jan Engelhardtd2a7b6b2009-07-10 18:55:11 +0200396 watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200397 if (IS_ERR(watcher))
398 return PTR_ERR(watcher);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200399 w->u.watcher = watcher;
400
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200401 par->target = watcher;
402 par->targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200403 ret = xt_check_target(par, w->watcher_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200404 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200405 if (ret < 0) {
406 module_put(watcher->me);
407 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 }
Jan Engelhardt043ef462008-10-08 11:35:15 +0200409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 (*cnt)++;
411 return 0;
412}
413
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200414static int ebt_verify_pointers(const struct ebt_replace *repl,
Al Viro70fe9af2006-11-30 19:26:14 -0800415 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416{
Al Viro70fe9af2006-11-30 19:26:14 -0800417 unsigned int limit = repl->entries_size;
418 unsigned int valid_hooks = repl->valid_hooks;
419 unsigned int offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 int i;
421
Al Viroe4fd77d2006-11-30 19:26:35 -0800422 for (i = 0; i < NF_BR_NUMHOOKS; i++)
423 newinfo->hook_entry[i] = NULL;
424
425 newinfo->entries_size = repl->entries_size;
426 newinfo->nentries = repl->nentries;
427
Al Viro70fe9af2006-11-30 19:26:14 -0800428 while (offset < limit) {
429 size_t left = limit - offset;
430 struct ebt_entry *e = (void *)newinfo->entries + offset;
Al Virobb2ef252006-11-30 19:22:42 -0800431
Al Viro70fe9af2006-11-30 19:26:14 -0800432 if (left < sizeof(unsigned int))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 break;
Al Viro22b440b2006-11-30 19:25:51 -0800434
Al Viro70fe9af2006-11-30 19:26:14 -0800435 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
436 if ((valid_hooks & (1 << i)) == 0)
437 continue;
Al Viro1e419cd2006-11-30 19:28:48 -0800438 if ((char __user *)repl->hook_entry[i] ==
439 repl->entries + offset)
Al Viro70fe9af2006-11-30 19:26:14 -0800440 break;
441 }
442
443 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
444 if (e->bitmask != 0) {
445 /* we make userspace set this right,
446 so there is no misunderstanding */
447 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
448 "in distinguisher\n");
449 return -EINVAL;
450 }
451 if (i != NF_BR_NUMHOOKS)
452 newinfo->hook_entry[i] = (struct ebt_entries *)e;
453 if (left < sizeof(struct ebt_entries))
454 break;
455 offset += sizeof(struct ebt_entries);
456 } else {
457 if (left < sizeof(struct ebt_entry))
458 break;
459 if (left < e->next_offset)
460 break;
Florian Westphal1756de22010-02-15 18:15:55 +0100461 if (e->next_offset < sizeof(struct ebt_entry))
462 return -EINVAL;
Al Viro70fe9af2006-11-30 19:26:14 -0800463 offset += e->next_offset;
464 }
465 }
466 if (offset != limit) {
467 BUGPRINT("entries_size too small\n");
468 return -EINVAL;
469 }
Al Viroe4fd77d2006-11-30 19:26:35 -0800470
471 /* check if all valid hooks have a chain */
472 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
473 if (!newinfo->hook_entry[i] &&
474 (valid_hooks & (1 << i))) {
475 BUGPRINT("Valid hook without chain\n");
476 return -EINVAL;
477 }
478 }
Al Viro70fe9af2006-11-30 19:26:14 -0800479 return 0;
Al Viro22b440b2006-11-30 19:25:51 -0800480}
481
482/*
483 * this one is very careful, as it is the first function
484 * to parse the userspace data
485 */
486static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200487ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
488 const struct ebt_table_info *newinfo,
Al Viro0e795532006-11-30 19:27:13 -0800489 unsigned int *n, unsigned int *cnt,
490 unsigned int *totalcnt, unsigned int *udc_cnt)
Al Viro22b440b2006-11-30 19:25:51 -0800491{
Al Viro22b440b2006-11-30 19:25:51 -0800492 int i;
493
494 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Viro0e795532006-11-30 19:27:13 -0800495 if ((void *)e == (void *)newinfo->hook_entry[i])
Al Viro22b440b2006-11-30 19:25:51 -0800496 break;
497 }
498 /* beginning of a new chain
499 if i == NF_BR_NUMHOOKS it must be a user defined chain */
500 if (i != NF_BR_NUMHOOKS || !e->bitmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 /* this checks if the previous chain has as many entries
502 as it said it has */
503 if (*n != *cnt) {
504 BUGPRINT("nentries does not equal the nr of entries "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900505 "in the chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 return -EINVAL;
507 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
509 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
510 /* only RETURN from udc */
511 if (i != NF_BR_NUMHOOKS ||
512 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
513 BUGPRINT("bad policy\n");
514 return -EINVAL;
515 }
516 }
517 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
518 (*udc_cnt)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
520 BUGPRINT("counter_offset != totalcnt");
521 return -EINVAL;
522 }
523 *n = ((struct ebt_entries *)e)->nentries;
524 *cnt = 0;
525 return 0;
526 }
527 /* a plain old entry, heh */
528 if (sizeof(struct ebt_entry) > e->watchers_offset ||
529 e->watchers_offset > e->target_offset ||
530 e->target_offset >= e->next_offset) {
531 BUGPRINT("entry offsets not in right order\n");
532 return -EINVAL;
533 }
534 /* this is not checked anywhere else */
535 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
536 BUGPRINT("target size too small\n");
537 return -EINVAL;
538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 (*cnt)++;
540 (*totalcnt)++;
541 return 0;
542}
543
544struct ebt_cl_stack
545{
546 struct ebt_chainstack cs;
547 int from;
548 unsigned int hookmask;
549};
550
551/*
552 * we need these positions to check that the jumps to a different part of the
553 * entries is a jump to the beginning of a new chain.
554 */
555static inline int
556ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
Al Viro177abc32006-11-30 19:27:32 -0800557 unsigned int *n, struct ebt_cl_stack *udc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 int i;
560
561 /* we're only interested in chain starts */
Al Viro40642f92006-11-30 19:24:12 -0800562 if (e->bitmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 return 0;
564 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
566 break;
567 }
568 /* only care about udc */
569 if (i != NF_BR_NUMHOOKS)
570 return 0;
571
572 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
573 /* these initialisations are depended on later in check_chainloops() */
574 udc[*n].cs.n = 0;
575 udc[*n].hookmask = 0;
576
577 (*n)++;
578 return 0;
579}
580
581static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100582ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583{
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200584 struct xt_mtdtor_param par;
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 if (i && (*i)-- == 0)
587 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100589 par.net = net;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200590 par.match = m->u.match;
591 par.matchinfo = m->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200592 par.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200593 if (par.match->destroy != NULL)
594 par.match->destroy(&par);
595 module_put(par.match->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return 0;
597}
598
599static inline int
Patrick McHardyadd67462010-02-03 13:45:12 +0100600ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200602 struct xt_tgdtor_param par;
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (i && (*i)-- == 0)
605 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Patrick McHardyadd67462010-02-03 13:45:12 +0100607 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200608 par.target = w->u.watcher;
609 par.targinfo = w->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200610 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200611 if (par.target->destroy != NULL)
612 par.target->destroy(&par);
613 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 return 0;
615}
616
617static inline int
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100618ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619{
Jan Engelhardta2df1642008-10-08 11:35:19 +0200620 struct xt_tgdtor_param par;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 struct ebt_entry_target *t;
622
Al Viro40642f92006-11-30 19:24:12 -0800623 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 return 0;
625 /* we're done */
626 if (cnt && (*cnt)-- == 0)
627 return 1;
Patrick McHardyadd67462010-02-03 13:45:12 +0100628 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL);
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100629 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Patrick McHardyadd67462010-02-03 13:45:12 +0100632 par.net = net;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200633 par.target = t->u.target;
634 par.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200635 par.family = NFPROTO_BRIDGE;
Jan Engelhardta2df1642008-10-08 11:35:19 +0200636 if (par.target->destroy != NULL)
637 par.target->destroy(&par);
638 module_put(par.target->me);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return 0;
640}
641
642static inline int
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200643ebt_check_entry(struct ebt_entry *e, struct net *net,
644 const struct ebt_table_info *newinfo,
Al Virof7da79d2006-11-30 19:27:48 -0800645 const char *name, unsigned int *cnt,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
647{
648 struct ebt_entry_target *t;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200649 struct xt_target *target;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 unsigned int i, j, hook = 0, hookmask = 0;
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800651 size_t gap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 int ret;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200653 struct xt_mtchk_param mtpar;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200654 struct xt_tgchk_param tgpar;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656 /* don't mess with the struct ebt_entries */
Al Viro40642f92006-11-30 19:24:12 -0800657 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return 0;
659
660 if (e->bitmask & ~EBT_F_MASK) {
661 BUGPRINT("Unknown flag for bitmask\n");
662 return -EINVAL;
663 }
664 if (e->invflags & ~EBT_INV_MASK) {
665 BUGPRINT("Unknown flag for inv bitmask\n");
666 return -EINVAL;
667 }
668 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
669 BUGPRINT("NOPROTO & 802_3 not allowed\n");
670 return -EINVAL;
671 }
672 /* what hook do we belong to? */
673 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Al Virof7da79d2006-11-30 19:27:48 -0800674 if (!newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 continue;
676 if ((char *)newinfo->hook_entry[i] < (char *)e)
677 hook = i;
678 else
679 break;
680 }
681 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
682 a base chain */
683 if (i < NF_BR_NUMHOOKS)
684 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
685 else {
686 for (i = 0; i < udc_cnt; i++)
687 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
688 break;
689 if (i == 0)
690 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
691 else
692 hookmask = cl_s[i - 1].hookmask;
693 }
694 i = 0;
Jan Engelhardt9b4fce72008-10-08 11:35:18 +0200695
Patrick McHardyadd67462010-02-03 13:45:12 +0100696 mtpar.net = tgpar.net = net;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200697 mtpar.table = tgpar.table = name;
698 mtpar.entryinfo = tgpar.entryinfo = e;
699 mtpar.hook_mask = tgpar.hook_mask = hookmask;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200700 mtpar.family = tgpar.family = NFPROTO_BRIDGE;
Jan Engelhardt6be3d852008-10-08 11:35:19 +0200701 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 if (ret != 0)
703 goto cleanup_matches;
704 j = 0;
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200705 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, &tgpar, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 if (ret != 0)
707 goto cleanup_watchers;
708 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
Chuck Ebbert44f9a2f2007-01-04 12:17:44 -0800709 gap = e->next_offset - e->target_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Jan Engelhardtd2a7b6b2009-07-10 18:55:11 +0200711 target = xt_request_find_target(NFPROTO_BRIDGE, t->u.name, 0);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200712 if (IS_ERR(target)) {
713 ret = PTR_ERR(target);
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200714 goto cleanup_watchers;
Jan Engelhardt001a18d2008-10-08 11:35:14 +0200715 }
716
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 t->u.target = target;
718 if (t->u.target == &ebt_standard_target) {
Al Viro14197d52006-11-30 19:25:21 -0800719 if (gap < sizeof(struct ebt_standard_target)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 BUGPRINT("Standard target size too big\n");
721 ret = -EFAULT;
722 goto cleanup_watchers;
723 }
724 if (((struct ebt_standard_target *)t)->verdict <
725 -NUM_STANDARD_TARGETS) {
726 BUGPRINT("Invalid standard target\n");
727 ret = -EFAULT;
728 goto cleanup_watchers;
729 }
Jan Engelhardt18219d32008-10-08 11:35:13 +0200730 } else if (t->target_size > gap - sizeof(struct ebt_entry_target)) {
731 module_put(t->u.target->me);
732 ret = -EFAULT;
733 goto cleanup_watchers;
Jan Engelhardt043ef462008-10-08 11:35:15 +0200734 }
735
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200736 tgpar.target = target;
737 tgpar.targinfo = t->data;
Jan Engelhardt916a9172008-10-08 11:35:20 +0200738 ret = xt_check_target(&tgpar, t->target_size,
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200739 e->ethproto, e->invflags & EBT_IPROTO);
Jan Engelhardt043ef462008-10-08 11:35:15 +0200740 if (ret < 0) {
741 module_put(target->me);
Jan Engelhardt18219d32008-10-08 11:35:13 +0200742 goto cleanup_watchers;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
744 (*cnt)++;
745 return 0;
746cleanup_watchers:
Patrick McHardyadd67462010-02-03 13:45:12 +0100747 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748cleanup_matches:
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100749 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return ret;
751}
752
753/*
754 * checks for loops and sets the hook mask for udc
755 * the hook mask for udc tells us from which base chains the udc can be
756 * accessed. This mask is a parameter to the check() functions of the extensions
757 */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200758static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 unsigned int udc_cnt, unsigned int hooknr, char *base)
760{
761 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200762 const struct ebt_entry *e = (struct ebt_entry *)chain->data;
763 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
765 while (pos < nentries || chain_nr != -1) {
766 /* end of udc, go back one 'recursion' step */
767 if (pos == nentries) {
768 /* put back values of the time when this chain was called */
769 e = cl_s[chain_nr].cs.e;
770 if (cl_s[chain_nr].from != -1)
771 nentries =
772 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
773 else
774 nentries = chain->nentries;
775 pos = cl_s[chain_nr].cs.n;
776 /* make sure we won't see a loop that isn't one */
777 cl_s[chain_nr].cs.n = 0;
778 chain_nr = cl_s[chain_nr].from;
779 if (pos == nentries)
780 continue;
781 }
782 t = (struct ebt_entry_target *)
783 (((char *)e) + e->target_offset);
784 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
785 goto letscontinue;
786 if (e->target_offset + sizeof(struct ebt_standard_target) >
787 e->next_offset) {
788 BUGPRINT("Standard target size too big\n");
789 return -1;
790 }
791 verdict = ((struct ebt_standard_target *)t)->verdict;
792 if (verdict >= 0) { /* jump to another chain */
793 struct ebt_entries *hlp2 =
794 (struct ebt_entries *)(base + verdict);
795 for (i = 0; i < udc_cnt; i++)
796 if (hlp2 == cl_s[i].cs.chaininfo)
797 break;
798 /* bad destination or loop */
799 if (i == udc_cnt) {
800 BUGPRINT("bad destination\n");
801 return -1;
802 }
803 if (cl_s[i].cs.n) {
804 BUGPRINT("loop\n");
805 return -1;
806 }
Al Viro98a08242006-11-30 19:24:49 -0800807 if (cl_s[i].hookmask & (1 << hooknr))
808 goto letscontinue;
809 /* this can't be 0, so the loop test is correct */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 cl_s[i].cs.n = pos + 1;
811 pos = 0;
Jan Engelhardt98e86402009-04-15 21:06:05 +0200812 cl_s[i].cs.e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 e = (struct ebt_entry *)(hlp2->data);
814 nentries = hlp2->nentries;
815 cl_s[i].from = chain_nr;
816 chain_nr = i;
817 /* this udc is accessible from the base chain for hooknr */
818 cl_s[i].hookmask |= (1 << hooknr);
819 continue;
820 }
821letscontinue:
Jan Engelhardt98e86402009-04-15 21:06:05 +0200822 e = ebt_next_entry(e);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 pos++;
824 }
825 return 0;
826}
827
828/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200829static int translate_table(struct net *net, const char *name,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100830 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
832 unsigned int i, j, k, udc_cnt;
833 int ret;
834 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
835
836 i = 0;
Al Viro1f072c92006-11-30 19:26:53 -0800837 while (i < NF_BR_NUMHOOKS && !newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 i++;
839 if (i == NF_BR_NUMHOOKS) {
840 BUGPRINT("No valid hooks specified\n");
841 return -EINVAL;
842 }
Al Viro1f072c92006-11-30 19:26:53 -0800843 if (newinfo->hook_entry[i] != (struct ebt_entries *)newinfo->entries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 BUGPRINT("Chains don't start at beginning\n");
845 return -EINVAL;
846 }
847 /* make sure chains are ordered after each other in same order
848 as their corresponding hooks */
849 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
Al Viro1f072c92006-11-30 19:26:53 -0800850 if (!newinfo->hook_entry[j])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 continue;
Al Viro1f072c92006-11-30 19:26:53 -0800852 if (newinfo->hook_entry[j] <= newinfo->hook_entry[i]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 BUGPRINT("Hook order must be followed\n");
854 return -EINVAL;
855 }
856 i = j;
857 }
858
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 /* do some early checkings and initialize some things */
860 i = 0; /* holds the expected nr. of entries for the chain */
861 j = 0; /* holds the up to now counted entries for the chain */
862 k = 0; /* holds the total nr. of entries, should equal
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900863 newinfo->nentries afterwards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
865 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro0e795532006-11-30 19:27:13 -0800866 ebt_check_entry_size_and_hooks, newinfo,
867 &i, &j, &k, &udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869 if (ret != 0)
870 return ret;
871
872 if (i != j) {
873 BUGPRINT("nentries does not equal the nr of entries in the "
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +0900874 "(last) chain\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return -EINVAL;
876 }
877 if (k != newinfo->nentries) {
878 BUGPRINT("Total nentries is wrong\n");
879 return -EINVAL;
880 }
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /* get the location of the udc, put them in an array
883 while we're at it, allocate the chainstack */
884 if (udc_cnt) {
885 /* this will get free'd in do_replace()/ebt_register_table()
886 if an error occurs */
Jayachandran C7ad4d2f2006-04-11 17:25:38 -0700887 newinfo->chainstack =
Christoph Lameter53b8a312007-02-20 13:57:51 -0800888 vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 if (!newinfo->chainstack)
890 return -ENOMEM;
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700891 for_each_possible_cpu(i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 newinfo->chainstack[i] =
Jayachandran C18bc89a2006-04-20 00:14:49 -0700893 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 if (!newinfo->chainstack[i]) {
895 while (i)
896 vfree(newinfo->chainstack[--i]);
897 vfree(newinfo->chainstack);
898 newinfo->chainstack = NULL;
899 return -ENOMEM;
900 }
901 }
902
Jayachandran C18bc89a2006-04-20 00:14:49 -0700903 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 if (!cl_s)
905 return -ENOMEM;
906 i = 0; /* the i'th udc */
907 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Al Viro177abc32006-11-30 19:27:32 -0800908 ebt_get_udc_positions, newinfo, &i, cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 /* sanity check */
910 if (i != udc_cnt) {
911 BUGPRINT("i != udc_cnt\n");
912 vfree(cl_s);
913 return -EFAULT;
914 }
915 }
916
917 /* Check for loops */
918 for (i = 0; i < NF_BR_NUMHOOKS; i++)
Al Viro1f072c92006-11-30 19:26:53 -0800919 if (newinfo->hook_entry[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 if (check_chainloops(newinfo->hook_entry[i],
921 cl_s, udc_cnt, i, newinfo->entries)) {
James Lamanna68d31872005-06-22 22:12:57 -0700922 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 return -EINVAL;
924 }
925
Jan Engelhardt96de0e22007-10-19 23:21:04 +0200926 /* we now know the following (along with E=mc²):
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 - the nr of entries in each chain is right
928 - the size of the allocated space is right
929 - all valid hooks have a corresponding chain
930 - there are no loops
931 - wrong data can still be on the level of a single entry
932 - could be there are jumps to places that are not the
933 beginning of a chain. This can only occur in chains that
934 are not accessible from any base chains, so we don't care. */
935
936 /* used to know what we need to clean up if something goes wrong */
937 i = 0;
938 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyana83d8e82010-01-18 08:21:13 +0100939 ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if (ret != 0) {
941 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +0100942 ebt_cleanup_entry, net, &i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
James Lamanna68d31872005-06-22 22:12:57 -0700944 vfree(cl_s);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 return ret;
946}
947
948/* called under write_lock */
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +0200949static void get_counters(const struct ebt_counter *oldcounters,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 struct ebt_counter *counters, unsigned int nentries)
951{
952 int i, cpu;
953 struct ebt_counter *counter_base;
954
955 /* counters of cpu 0 */
956 memcpy(counters, oldcounters,
David S. Millerc8923c62005-10-13 14:41:23 -0700957 sizeof(struct ebt_counter) * nentries);
958
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 /* add other counters to those of cpu 0 */
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -0700960 for_each_possible_cpu(cpu) {
David S. Millerc8923c62005-10-13 14:41:23 -0700961 if (cpu == 0)
962 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
964 for (i = 0; i < nentries; i++) {
965 counters[i].pcnt += counter_base[i].pcnt;
966 counters[i].bcnt += counter_base[i].bcnt;
967 }
968 }
969}
970
Florian Westphale7887592010-02-04 18:38:53 +0100971static int do_replace_finish(struct net *net, struct ebt_replace *repl,
972 struct ebt_table_info *newinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973{
Florian Westphale7887592010-02-04 18:38:53 +0100974 int ret, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 struct ebt_counter *counterstmp = NULL;
976 /* used to be able to unlock earlier */
977 struct ebt_table_info *table;
Florian Westphale7887592010-02-04 18:38:53 +0100978 struct ebt_table *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 /* the user wants counters back
981 the check on the size is done later, when we have the lock */
Florian Westphale7887592010-02-04 18:38:53 +0100982 if (repl->num_counters) {
983 unsigned long size = repl->num_counters * sizeof(*counterstmp);
984 counterstmp = vmalloc(size);
985 if (!counterstmp)
986 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 newinfo->chainstack = NULL;
Florian Westphale7887592010-02-04 18:38:53 +0100990 ret = ebt_verify_pointers(repl, newinfo);
Al Viro1bc23262006-11-30 19:28:08 -0800991 if (ret != 0)
992 goto free_counterstmp;
993
Florian Westphale7887592010-02-04 18:38:53 +0100994 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996 if (ret != 0)
997 goto free_counterstmp;
998
Florian Westphale7887592010-02-04 18:38:53 +0100999 t = find_table_lock(net, repl->name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 if (!t) {
1001 ret = -ENOENT;
1002 goto free_iterate;
1003 }
1004
1005 /* the table doesn't like it */
Florian Westphale7887592010-02-04 18:38:53 +01001006 if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 goto free_unlock;
1008
Florian Westphale7887592010-02-04 18:38:53 +01001009 if (repl->num_counters && repl->num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 BUGPRINT("Wrong nr. of counters requested\n");
1011 ret = -EINVAL;
1012 goto free_unlock;
1013 }
1014
1015 /* we have the mutex lock, so no danger in reading this pointer */
1016 table = t->private;
1017 /* make sure the table can only be rmmod'ed if it contains no rules */
1018 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
1019 ret = -ENOENT;
1020 goto free_unlock;
1021 } else if (table->nentries && !newinfo->nentries)
1022 module_put(t->me);
1023 /* we need an atomic snapshot of the counters */
1024 write_lock_bh(&t->lock);
Florian Westphale7887592010-02-04 18:38:53 +01001025 if (repl->num_counters)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 get_counters(t->private->counters, counterstmp,
1027 t->private->nentries);
1028
1029 t->private = newinfo;
1030 write_unlock_bh(&t->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001031 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 /* so, a user can change the chains while having messed up her counter
1033 allocation. Only reason why this is done is because this way the lock
1034 is held only once, while this doesn't bring the kernel into a
1035 dangerous state. */
Florian Westphale7887592010-02-04 18:38:53 +01001036 if (repl->num_counters &&
1037 copy_to_user(repl->counters, counterstmp,
1038 repl->num_counters * sizeof(struct ebt_counter))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 ret = -EFAULT;
1040 }
1041 else
1042 ret = 0;
1043
1044 /* decrease module count and free resources */
1045 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001046 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 vfree(table->entries);
1049 if (table->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001050 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 vfree(table->chainstack[i]);
1052 vfree(table->chainstack);
1053 }
1054 vfree(table);
1055
James Lamanna68d31872005-06-22 22:12:57 -07001056 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 return ret;
1058
1059free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001060 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061free_iterate:
1062 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001063 ebt_cleanup_entry, net, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064free_counterstmp:
James Lamanna68d31872005-06-22 22:12:57 -07001065 vfree(counterstmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 /* can be initialized in translate_table() */
1067 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001068 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 vfree(newinfo->chainstack[i]);
1070 vfree(newinfo->chainstack);
1071 }
Florian Westphale7887592010-02-04 18:38:53 +01001072 return ret;
1073}
1074
1075/* replace the table */
1076static int do_replace(struct net *net, const void __user *user,
1077 unsigned int len)
1078{
1079 int ret, countersize;
1080 struct ebt_table_info *newinfo;
1081 struct ebt_replace tmp;
1082
1083 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1084 return -EFAULT;
1085
1086 if (len != sizeof(tmp) + tmp.entries_size) {
1087 BUGPRINT("Wrong len argument\n");
1088 return -EINVAL;
1089 }
1090
1091 if (tmp.entries_size == 0) {
1092 BUGPRINT("Entries_size never zero\n");
1093 return -EINVAL;
1094 }
1095 /* overflow check */
1096 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
1097 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
1098 return -ENOMEM;
1099 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
1100 return -ENOMEM;
1101
1102 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
1103 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1104 if (!newinfo)
1105 return -ENOMEM;
1106
1107 if (countersize)
1108 memset(newinfo->counters, 0, countersize);
1109
1110 newinfo->entries = vmalloc(tmp.entries_size);
1111 if (!newinfo->entries) {
1112 ret = -ENOMEM;
1113 goto free_newinfo;
1114 }
1115 if (copy_from_user(
1116 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
1117 BUGPRINT("Couldn't copy entries from userspace\n");
1118 ret = -EFAULT;
1119 goto free_entries;
1120 }
1121
1122 ret = do_replace_finish(net, &tmp, newinfo);
1123 if (ret == 0)
1124 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125free_entries:
James Lamanna68d31872005-06-22 22:12:57 -07001126 vfree(newinfo->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127free_newinfo:
James Lamanna68d31872005-06-22 22:12:57 -07001128 vfree(newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 return ret;
1130}
1131
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001132struct ebt_table *
1133ebt_register_table(struct net *net, const struct ebt_table *input_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134{
1135 struct ebt_table_info *newinfo;
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001136 struct ebt_table *t, *table;
Al Viro1e419cd2006-11-30 19:28:48 -08001137 struct ebt_replace_kernel *repl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 int ret, i, countersize;
Al Virodf07a812006-11-30 19:28:25 -08001139 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001141 if (input_table == NULL || (repl = input_table->table) == NULL ||
1142 repl->entries == 0 || repl->entries_size == 0 ||
1143 repl->counters != NULL || input_table->private != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 BUGPRINT("Bad table data for ebt_register_table!!!\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001145 return ERR_PTR(-EINVAL);
1146 }
1147
1148 /* Don't add one table to multiple lists. */
Jan Engelhardt35aad0f2009-08-24 14:56:30 +02001149 table = kmemdup(input_table, sizeof(struct ebt_table), GFP_KERNEL);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001150 if (!table) {
1151 ret = -ENOMEM;
1152 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 }
1154
Christoph Lameter53b8a312007-02-20 13:57:51 -08001155 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
Jayachandran C18bc89a2006-04-20 00:14:49 -07001156 newinfo = vmalloc(sizeof(*newinfo) + countersize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 ret = -ENOMEM;
1158 if (!newinfo)
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001159 goto free_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Al Virodf07a812006-11-30 19:28:25 -08001161 p = vmalloc(repl->entries_size);
1162 if (!p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 goto free_newinfo;
1164
Al Virodf07a812006-11-30 19:28:25 -08001165 memcpy(p, repl->entries, repl->entries_size);
1166 newinfo->entries = p;
1167
1168 newinfo->entries_size = repl->entries_size;
1169 newinfo->nentries = repl->nentries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171 if (countersize)
1172 memset(newinfo->counters, 0, countersize);
1173
1174 /* fill in newinfo and parse the entries */
1175 newinfo->chainstack = NULL;
Al Virodf07a812006-11-30 19:28:25 -08001176 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1177 if ((repl->valid_hooks & (1 << i)) == 0)
1178 newinfo->hook_entry[i] = NULL;
1179 else
1180 newinfo->hook_entry[i] = p +
1181 ((char *)repl->hook_entry[i] - repl->entries);
1182 }
Alexey Dobriyana83d8e82010-01-18 08:21:13 +01001183 ret = translate_table(net, repl->name, newinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 if (ret != 0) {
1185 BUGPRINT("Translate_table failed\n");
1186 goto free_chainstack;
1187 }
1188
1189 if (table->check && table->check(newinfo, table->valid_hooks)) {
1190 BUGPRINT("The table doesn't like its own initial data, lol\n");
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001191 return ERR_PTR(-EINVAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 }
1193
1194 table->private = newinfo;
1195 rwlock_init(&table->lock);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001196 ret = mutex_lock_interruptible(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 if (ret != 0)
1198 goto free_chainstack;
1199
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001200 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
Patrick McHardydf0933d2006-09-20 11:57:53 -07001201 if (strcmp(t->name, table->name) == 0) {
1202 ret = -EEXIST;
1203 BUGPRINT("Table name already exists\n");
1204 goto free_unlock;
1205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
1207
1208 /* Hold a reference count if the chains aren't empty */
1209 if (newinfo->nentries && !try_module_get(table->me)) {
1210 ret = -ENOENT;
1211 goto free_unlock;
1212 }
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001213 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001214 mutex_unlock(&ebt_mutex);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001215 return table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216free_unlock:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001217 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218free_chainstack:
1219 if (newinfo->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001220 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 vfree(newinfo->chainstack[i]);
1222 vfree(newinfo->chainstack);
1223 }
1224 vfree(newinfo->entries);
1225free_newinfo:
1226 vfree(newinfo);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001227free_table:
1228 kfree(table);
1229out:
1230 return ERR_PTR(ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231}
1232
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001233void ebt_unregister_table(struct net *net, struct ebt_table *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
1235 int i;
1236
1237 if (!table) {
1238 BUGPRINT("Request to unregister NULL table!!!\n");
1239 return;
1240 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001241 mutex_lock(&ebt_mutex);
Patrick McHardydf0933d2006-09-20 11:57:53 -07001242 list_del(&table->list);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001243 mutex_unlock(&ebt_mutex);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001244 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
Alexey Dobriyanf54e9362010-01-18 08:25:47 +01001245 ebt_cleanup_entry, net, NULL);
Alexey Dobriyandbcdf852008-11-04 14:28:04 +01001246 if (table->private->nentries)
1247 module_put(table->me);
James Lamanna68d31872005-06-22 22:12:57 -07001248 vfree(table->private->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 if (table->private->chainstack) {
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001250 for_each_possible_cpu(i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 vfree(table->private->chainstack[i]);
1252 vfree(table->private->chainstack);
1253 }
1254 vfree(table->private);
Alexey Dobriyan6beceee2008-11-04 14:27:15 +01001255 kfree(table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256}
1257
1258/* userspace just supplied us with counters */
Florian Westphal49facff2010-02-07 02:48:47 +01001259static int do_update_counters(struct net *net, const char *name,
1260 struct ebt_counter __user *counters,
1261 unsigned int num_counters,
1262 const void __user *user, unsigned int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
1264 int i, ret;
1265 struct ebt_counter *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 struct ebt_table *t;
1267
Florian Westphal49facff2010-02-07 02:48:47 +01001268 if (num_counters == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 return -EINVAL;
1270
Florian Westphal49facff2010-02-07 02:48:47 +01001271 tmp = vmalloc(num_counters * sizeof(*tmp));
1272 if (!tmp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Florian Westphal49facff2010-02-07 02:48:47 +01001275 t = find_table_lock(net, name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 if (!t)
1277 goto free_tmp;
1278
Florian Westphal49facff2010-02-07 02:48:47 +01001279 if (num_counters != t->private->nentries) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 BUGPRINT("Wrong nr of counters\n");
1281 ret = -EINVAL;
1282 goto unlock_mutex;
1283 }
1284
Florian Westphal49facff2010-02-07 02:48:47 +01001285 if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 ret = -EFAULT;
1287 goto unlock_mutex;
1288 }
1289
1290 /* we want an atomic add of the counters */
1291 write_lock_bh(&t->lock);
1292
1293 /* we add to the counters of the first cpu */
Florian Westphal49facff2010-02-07 02:48:47 +01001294 for (i = 0; i < num_counters; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 t->private->counters[i].pcnt += tmp[i].pcnt;
1296 t->private->counters[i].bcnt += tmp[i].bcnt;
1297 }
1298
1299 write_unlock_bh(&t->lock);
1300 ret = 0;
1301unlock_mutex:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001302 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303free_tmp:
1304 vfree(tmp);
1305 return ret;
1306}
1307
Florian Westphal49facff2010-02-07 02:48:47 +01001308static int update_counters(struct net *net, const void __user *user,
1309 unsigned int len)
1310{
1311 struct ebt_replace hlp;
1312
1313 if (copy_from_user(&hlp, user, sizeof(hlp)))
1314 return -EFAULT;
1315
1316 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1317 return -EINVAL;
1318
1319 return do_update_counters(net, hlp.name, hlp.counters,
1320 hlp.num_counters, user, len);
1321}
1322
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001323static inline int ebt_make_matchname(const struct ebt_entry_match *m,
1324 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325{
Al Viro1e419cd2006-11-30 19:28:48 -08001326 char __user *hlp = ubase + ((char *)m - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1328 return -EFAULT;
1329 return 0;
1330}
1331
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001332static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
1333 const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
Al Viro1e419cd2006-11-30 19:28:48 -08001335 char __user *hlp = ubase + ((char *)w - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1337 return -EFAULT;
1338 return 0;
1339}
1340
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001341static inline int
1342ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343{
1344 int ret;
Al Viro1e419cd2006-11-30 19:28:48 -08001345 char __user *hlp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001346 const struct ebt_entry_target *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Al Viro40642f92006-11-30 19:24:12 -08001348 if (e->bitmask == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return 0;
1350
Al Viro1e419cd2006-11-30 19:28:48 -08001351 hlp = ubase + (((char *)e + e->target_offset) - base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
YOSHIFUJI Hideaki9d6f2292007-02-09 23:24:35 +09001353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1355 if (ret != 0)
1356 return ret;
1357 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1358 if (ret != 0)
1359 return ret;
1360 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1361 return -EFAULT;
1362 return 0;
1363}
1364
Florian Westphal837395a2010-02-07 02:11:34 +01001365static int copy_counters_to_user(struct ebt_table *t,
1366 const struct ebt_counter *oldcounters,
1367 void __user *user, unsigned int num_counters,
1368 unsigned int nentries)
1369{
1370 struct ebt_counter *counterstmp;
1371 int ret = 0;
1372
1373 /* userspace might not need the counters */
1374 if (num_counters == 0)
1375 return 0;
1376
1377 if (num_counters != nentries) {
1378 BUGPRINT("Num_counters wrong\n");
1379 return -EINVAL;
1380 }
1381
1382 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1383 if (!counterstmp)
1384 return -ENOMEM;
1385
1386 write_lock_bh(&t->lock);
1387 get_counters(oldcounters, counterstmp, nentries);
1388 write_unlock_bh(&t->lock);
1389
1390 if (copy_to_user(user, counterstmp,
1391 nentries * sizeof(struct ebt_counter)))
1392 ret = -EFAULT;
1393 vfree(counterstmp);
1394 return ret;
1395}
1396
Ingo Molnar57b47a52006-03-20 22:35:41 -08001397/* called with ebt_mutex locked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398static int copy_everything_to_user(struct ebt_table *t, void __user *user,
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001399 const int *len, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
1401 struct ebt_replace tmp;
Jan Engelhardtd5d1baa2009-06-26 07:51:59 +02001402 const struct ebt_counter *oldcounters;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 unsigned int entries_size, nentries;
Florian Westphal837395a2010-02-07 02:11:34 +01001404 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 char *entries;
1406
1407 if (cmd == EBT_SO_GET_ENTRIES) {
1408 entries_size = t->private->entries_size;
1409 nentries = t->private->nentries;
1410 entries = t->private->entries;
1411 oldcounters = t->private->counters;
1412 } else {
1413 entries_size = t->table->entries_size;
1414 nentries = t->table->nentries;
1415 entries = t->table->entries;
1416 oldcounters = t->table->counters;
1417 }
1418
Florian Westphal90b89af2010-02-07 03:19:12 +01001419 if (copy_from_user(&tmp, user, sizeof(tmp)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
1422 if (*len != sizeof(struct ebt_replace) + entries_size +
Florian Westphal90b89af2010-02-07 03:19:12 +01001423 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 if (tmp.nentries != nentries) {
1427 BUGPRINT("Nentries wrong\n");
1428 return -EINVAL;
1429 }
1430
1431 if (tmp.entries_size != entries_size) {
1432 BUGPRINT("Wrong size\n");
1433 return -EINVAL;
1434 }
1435
Florian Westphal837395a2010-02-07 02:11:34 +01001436 ret = copy_counters_to_user(t, oldcounters, tmp.counters,
1437 tmp.num_counters, nentries);
1438 if (ret)
1439 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
1441 if (copy_to_user(tmp.entries, entries, entries_size)) {
1442 BUGPRINT("Couldn't copy entries to userspace\n");
1443 return -EFAULT;
1444 }
1445 /* set the match/watcher/target names right */
1446 return EBT_ENTRY_ITERATE(entries, entries_size,
1447 ebt_make_names, entries, tmp.entries);
1448}
1449
1450static int do_ebt_set_ctl(struct sock *sk,
1451 int cmd, void __user *user, unsigned int len)
1452{
1453 int ret;
1454
Florian Westphaldce766a2010-01-08 17:31:24 +01001455 if (!capable(CAP_NET_ADMIN))
1456 return -EPERM;
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 switch(cmd) {
1459 case EBT_SO_SET_ENTRIES:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001460 ret = do_replace(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 break;
1462 case EBT_SO_SET_COUNTERS:
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001463 ret = update_counters(sock_net(sk), user, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 break;
1465 default:
1466 ret = -EINVAL;
Florian Westphal81e675c2010-01-05 16:09:46 +01001467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 return ret;
1469}
1470
1471static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1472{
1473 int ret;
1474 struct ebt_replace tmp;
1475 struct ebt_table *t;
1476
Florian Westphaldce766a2010-01-08 17:31:24 +01001477 if (!capable(CAP_NET_ADMIN))
1478 return -EPERM;
1479
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 if (copy_from_user(&tmp, user, sizeof(tmp)))
1481 return -EFAULT;
1482
Alexey Dobriyan511061e2008-11-04 14:22:55 +01001483 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 if (!t)
1485 return ret;
1486
1487 switch(cmd) {
1488 case EBT_SO_GET_INFO:
1489 case EBT_SO_GET_INIT_INFO:
1490 if (*len != sizeof(struct ebt_replace)){
1491 ret = -EINVAL;
Ingo Molnar57b47a52006-03-20 22:35:41 -08001492 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 break;
1494 }
1495 if (cmd == EBT_SO_GET_INFO) {
1496 tmp.nentries = t->private->nentries;
1497 tmp.entries_size = t->private->entries_size;
1498 tmp.valid_hooks = t->valid_hooks;
1499 } else {
1500 tmp.nentries = t->table->nentries;
1501 tmp.entries_size = t->table->entries_size;
1502 tmp.valid_hooks = t->table->valid_hooks;
1503 }
Ingo Molnar57b47a52006-03-20 22:35:41 -08001504 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 if (copy_to_user(user, &tmp, *len) != 0){
1506 BUGPRINT("c2u Didn't work\n");
1507 ret = -EFAULT;
1508 break;
1509 }
1510 ret = 0;
1511 break;
1512
1513 case EBT_SO_GET_ENTRIES:
1514 case EBT_SO_GET_INIT_ENTRIES:
1515 ret = copy_everything_to_user(t, user, len, cmd);
Ingo Molnar57b47a52006-03-20 22:35:41 -08001516 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 break;
1518
1519 default:
Ingo Molnar57b47a52006-03-20 22:35:41 -08001520 mutex_unlock(&ebt_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 ret = -EINVAL;
1522 }
1523
1524 return ret;
1525}
1526
Florian Westphal81e675c2010-01-05 16:09:46 +01001527#ifdef CONFIG_COMPAT
1528/* 32 bit-userspace compatibility definitions. */
1529struct compat_ebt_replace {
1530 char name[EBT_TABLE_MAXNAMELEN];
1531 compat_uint_t valid_hooks;
1532 compat_uint_t nentries;
1533 compat_uint_t entries_size;
1534 /* start of the chains */
1535 compat_uptr_t hook_entry[NF_BR_NUMHOOKS];
1536 /* nr of counters userspace expects back */
1537 compat_uint_t num_counters;
1538 /* where the kernel will put the old counters. */
1539 compat_uptr_t counters;
1540 compat_uptr_t entries;
1541};
1542
1543/* struct ebt_entry_match, _target and _watcher have same layout */
1544struct compat_ebt_entry_mwt {
1545 union {
1546 char name[EBT_FUNCTION_MAXNAMELEN];
1547 compat_uptr_t ptr;
1548 } u;
1549 compat_uint_t match_size;
1550 compat_uint_t data[0];
1551};
1552
1553/* account for possible padding between match_size and ->data */
1554static int ebt_compat_entry_padsize(void)
1555{
1556 BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
1557 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
1558 return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
1559 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
1560}
1561
1562static int ebt_compat_match_offset(const struct xt_match *match,
1563 unsigned int userlen)
1564{
1565 /*
1566 * ebt_among needs special handling. The kernel .matchsize is
1567 * set to -1 at registration time; at runtime an EBT_ALIGN()ed
1568 * value is expected.
1569 * Example: userspace sends 4500, ebt_among.c wants 4504.
1570 */
1571 if (unlikely(match->matchsize == -1))
1572 return XT_ALIGN(userlen) - COMPAT_XT_ALIGN(userlen);
1573 return xt_compat_match_offset(match);
1574}
1575
1576static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
1577 unsigned int *size)
1578{
1579 const struct xt_match *match = m->u.match;
1580 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1581 int off = ebt_compat_match_offset(match, m->match_size);
1582 compat_uint_t msize = m->match_size - off;
1583
1584 BUG_ON(off >= m->match_size);
1585
1586 if (copy_to_user(cm->u.name, match->name,
1587 strlen(match->name) + 1) || put_user(msize, &cm->match_size))
1588 return -EFAULT;
1589
1590 if (match->compat_to_user) {
1591 if (match->compat_to_user(cm->data, m->data))
1592 return -EFAULT;
1593 } else if (copy_to_user(cm->data, m->data, msize))
1594 return -EFAULT;
1595
1596 *size -= ebt_compat_entry_padsize() + off;
1597 *dstptr = cm->data;
1598 *dstptr += msize;
1599 return 0;
1600}
1601
1602static int compat_target_to_user(struct ebt_entry_target *t,
1603 void __user **dstptr,
1604 unsigned int *size)
1605{
1606 const struct xt_target *target = t->u.target;
1607 struct compat_ebt_entry_mwt __user *cm = *dstptr;
1608 int off = xt_compat_target_offset(target);
1609 compat_uint_t tsize = t->target_size - off;
1610
1611 BUG_ON(off >= t->target_size);
1612
1613 if (copy_to_user(cm->u.name, target->name,
1614 strlen(target->name) + 1) || put_user(tsize, &cm->match_size))
1615 return -EFAULT;
1616
1617 if (target->compat_to_user) {
1618 if (target->compat_to_user(cm->data, t->data))
1619 return -EFAULT;
1620 } else if (copy_to_user(cm->data, t->data, tsize))
1621 return -EFAULT;
1622
1623 *size -= ebt_compat_entry_padsize() + off;
1624 *dstptr = cm->data;
1625 *dstptr += tsize;
1626 return 0;
1627}
1628
1629static int compat_watcher_to_user(struct ebt_entry_watcher *w,
1630 void __user **dstptr,
1631 unsigned int *size)
1632{
1633 return compat_target_to_user((struct ebt_entry_target *)w,
1634 dstptr, size);
1635}
1636
1637static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr,
1638 unsigned int *size)
1639{
1640 struct ebt_entry_target *t;
1641 struct ebt_entry __user *ce;
1642 u32 watchers_offset, target_offset, next_offset;
1643 compat_uint_t origsize;
1644 int ret;
1645
1646 if (e->bitmask == 0) {
1647 if (*size < sizeof(struct ebt_entries))
1648 return -EINVAL;
1649 if (copy_to_user(*dstptr, e, sizeof(struct ebt_entries)))
1650 return -EFAULT;
1651
1652 *dstptr += sizeof(struct ebt_entries);
1653 *size -= sizeof(struct ebt_entries);
1654 return 0;
1655 }
1656
1657 if (*size < sizeof(*ce))
1658 return -EINVAL;
1659
1660 ce = (struct ebt_entry __user *)*dstptr;
1661 if (copy_to_user(ce, e, sizeof(*ce)))
1662 return -EFAULT;
1663
1664 origsize = *size;
1665 *dstptr += sizeof(*ce);
1666
1667 ret = EBT_MATCH_ITERATE(e, compat_match_to_user, dstptr, size);
1668 if (ret)
1669 return ret;
1670 watchers_offset = e->watchers_offset - (origsize - *size);
1671
1672 ret = EBT_WATCHER_ITERATE(e, compat_watcher_to_user, dstptr, size);
1673 if (ret)
1674 return ret;
1675 target_offset = e->target_offset - (origsize - *size);
1676
1677 t = (struct ebt_entry_target *) ((char *) e + e->target_offset);
1678
1679 ret = compat_target_to_user(t, dstptr, size);
1680 if (ret)
1681 return ret;
1682 next_offset = e->next_offset - (origsize - *size);
1683
1684 if (put_user(watchers_offset, &ce->watchers_offset) ||
1685 put_user(target_offset, &ce->target_offset) ||
1686 put_user(next_offset, &ce->next_offset))
1687 return -EFAULT;
1688
1689 *size -= sizeof(*ce);
1690 return 0;
1691}
1692
1693static int compat_calc_match(struct ebt_entry_match *m, int *off)
1694{
1695 *off += ebt_compat_match_offset(m->u.match, m->match_size);
1696 *off += ebt_compat_entry_padsize();
1697 return 0;
1698}
1699
1700static int compat_calc_watcher(struct ebt_entry_watcher *w, int *off)
1701{
1702 *off += xt_compat_target_offset(w->u.watcher);
1703 *off += ebt_compat_entry_padsize();
1704 return 0;
1705}
1706
1707static int compat_calc_entry(const struct ebt_entry *e,
1708 const struct ebt_table_info *info,
1709 const void *base,
1710 struct compat_ebt_replace *newinfo)
1711{
1712 const struct ebt_entry_target *t;
1713 unsigned int entry_offset;
1714 int off, ret, i;
1715
1716 if (e->bitmask == 0)
1717 return 0;
1718
1719 off = 0;
1720 entry_offset = (void *)e - base;
1721
1722 EBT_MATCH_ITERATE(e, compat_calc_match, &off);
1723 EBT_WATCHER_ITERATE(e, compat_calc_watcher, &off);
1724
1725 t = (const struct ebt_entry_target *) ((char *) e + e->target_offset);
1726
1727 off += xt_compat_target_offset(t->u.target);
1728 off += ebt_compat_entry_padsize();
1729
1730 newinfo->entries_size -= off;
1731
1732 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, off);
1733 if (ret)
1734 return ret;
1735
1736 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1737 const void *hookptr = info->hook_entry[i];
1738 if (info->hook_entry[i] &&
1739 (e < (struct ebt_entry *)(base - hookptr))) {
1740 newinfo->hook_entry[i] -= off;
1741 pr_debug("0x%08X -> 0x%08X\n",
1742 newinfo->hook_entry[i] + off,
1743 newinfo->hook_entry[i]);
1744 }
1745 }
1746
1747 return 0;
1748}
1749
1750
1751static int compat_table_info(const struct ebt_table_info *info,
1752 struct compat_ebt_replace *newinfo)
1753{
1754 unsigned int size = info->entries_size;
1755 const void *entries = info->entries;
1756
1757 newinfo->entries_size = size;
1758
1759 return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
1760 entries, newinfo);
1761}
1762
1763static int compat_copy_everything_to_user(struct ebt_table *t,
1764 void __user *user, int *len, int cmd)
1765{
1766 struct compat_ebt_replace repl, tmp;
1767 struct ebt_counter *oldcounters;
1768 struct ebt_table_info tinfo;
1769 int ret;
1770 void __user *pos;
1771
1772 memset(&tinfo, 0, sizeof(tinfo));
1773
1774 if (cmd == EBT_SO_GET_ENTRIES) {
1775 tinfo.entries_size = t->private->entries_size;
1776 tinfo.nentries = t->private->nentries;
1777 tinfo.entries = t->private->entries;
1778 oldcounters = t->private->counters;
1779 } else {
1780 tinfo.entries_size = t->table->entries_size;
1781 tinfo.nentries = t->table->nentries;
1782 tinfo.entries = t->table->entries;
1783 oldcounters = t->table->counters;
1784 }
1785
1786 if (copy_from_user(&tmp, user, sizeof(tmp)))
1787 return -EFAULT;
1788
1789 if (tmp.nentries != tinfo.nentries ||
1790 (tmp.num_counters && tmp.num_counters != tinfo.nentries))
1791 return -EINVAL;
1792
1793 memcpy(&repl, &tmp, sizeof(repl));
1794 if (cmd == EBT_SO_GET_ENTRIES)
1795 ret = compat_table_info(t->private, &repl);
1796 else
1797 ret = compat_table_info(&tinfo, &repl);
1798 if (ret)
1799 return ret;
1800
1801 if (*len != sizeof(tmp) + repl.entries_size +
1802 (tmp.num_counters? tinfo.nentries * sizeof(struct ebt_counter): 0)) {
1803 pr_err("wrong size: *len %d, entries_size %u, replsz %d\n",
1804 *len, tinfo.entries_size, repl.entries_size);
1805 return -EINVAL;
1806 }
1807
1808 /* userspace might not need the counters */
1809 ret = copy_counters_to_user(t, oldcounters, compat_ptr(tmp.counters),
1810 tmp.num_counters, tinfo.nentries);
1811 if (ret)
1812 return ret;
1813
1814 pos = compat_ptr(tmp.entries);
1815 return EBT_ENTRY_ITERATE(tinfo.entries, tinfo.entries_size,
1816 compat_copy_entry_to_user, &pos, &tmp.entries_size);
1817}
1818
1819struct ebt_entries_buf_state {
1820 char *buf_kern_start; /* kernel buffer to copy (translated) data to */
1821 u32 buf_kern_len; /* total size of kernel buffer */
1822 u32 buf_kern_offset; /* amount of data copied so far */
1823 u32 buf_user_offset; /* read position in userspace buffer */
1824};
1825
1826static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
1827{
1828 state->buf_kern_offset += sz;
1829 return state->buf_kern_offset >= sz ? 0 : -EINVAL;
1830}
1831
1832static int ebt_buf_add(struct ebt_entries_buf_state *state,
1833 void *data, unsigned int sz)
1834{
1835 if (state->buf_kern_start == NULL)
1836 goto count_only;
1837
1838 BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len);
1839
1840 memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz);
1841
1842 count_only:
1843 state->buf_user_offset += sz;
1844 return ebt_buf_count(state, sz);
1845}
1846
1847static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz)
1848{
1849 char *b = state->buf_kern_start;
1850
1851 BUG_ON(b && state->buf_kern_offset > state->buf_kern_len);
1852
1853 if (b != NULL && sz > 0)
1854 memset(b + state->buf_kern_offset, 0, sz);
1855 /* do not adjust ->buf_user_offset here, we added kernel-side padding */
1856 return ebt_buf_count(state, sz);
1857}
1858
1859enum compat_mwt {
1860 EBT_COMPAT_MATCH,
1861 EBT_COMPAT_WATCHER,
1862 EBT_COMPAT_TARGET,
1863};
1864
1865static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
1866 enum compat_mwt compat_mwt,
1867 struct ebt_entries_buf_state *state,
1868 const unsigned char *base)
1869{
1870 char name[EBT_FUNCTION_MAXNAMELEN];
1871 struct xt_match *match;
1872 struct xt_target *wt;
1873 void *dst = NULL;
1874 int off, pad = 0, ret = 0;
1875 unsigned int size_kern, entry_offset, match_size = mwt->match_size;
1876
1877 strlcpy(name, mwt->u.name, sizeof(name));
1878
1879 if (state->buf_kern_start)
1880 dst = state->buf_kern_start + state->buf_kern_offset;
1881
1882 entry_offset = (unsigned char *) mwt - base;
1883 switch (compat_mwt) {
1884 case EBT_COMPAT_MATCH:
1885 match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE,
1886 name, 0), "ebt_%s", name);
1887 if (match == NULL)
1888 return -ENOENT;
1889 if (IS_ERR(match))
1890 return PTR_ERR(match);
1891
1892 off = ebt_compat_match_offset(match, match_size);
1893 if (dst) {
1894 if (match->compat_from_user)
1895 match->compat_from_user(dst, mwt->data);
1896 else
1897 memcpy(dst, mwt->data, match_size);
1898 }
1899
1900 size_kern = match->matchsize;
1901 if (unlikely(size_kern == -1))
1902 size_kern = match_size;
1903 module_put(match->me);
1904 break;
1905 case EBT_COMPAT_WATCHER: /* fallthrough */
1906 case EBT_COMPAT_TARGET:
1907 wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE,
1908 name, 0), "ebt_%s", name);
1909 if (wt == NULL)
1910 return -ENOENT;
1911 if (IS_ERR(wt))
1912 return PTR_ERR(wt);
1913 off = xt_compat_target_offset(wt);
1914
1915 if (dst) {
1916 if (wt->compat_from_user)
1917 wt->compat_from_user(dst, mwt->data);
1918 else
1919 memcpy(dst, mwt->data, match_size);
1920 }
1921
1922 size_kern = wt->targetsize;
1923 module_put(wt->me);
1924 break;
1925 }
1926
1927 if (!dst) {
1928 ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
1929 off + ebt_compat_entry_padsize());
1930 if (ret < 0)
1931 return ret;
1932 }
1933
1934 state->buf_kern_offset += match_size + off;
1935 state->buf_user_offset += match_size;
1936 pad = XT_ALIGN(size_kern) - size_kern;
1937
1938 if (pad > 0 && dst) {
1939 BUG_ON(state->buf_kern_len <= pad);
1940 BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad);
1941 memset(dst + size_kern, 0, pad);
1942 }
1943 return off + match_size;
1944}
1945
1946/*
1947 * return size of all matches, watchers or target, including necessary
1948 * alignment and padding.
1949 */
1950static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
1951 unsigned int size_left, enum compat_mwt type,
1952 struct ebt_entries_buf_state *state, const void *base)
1953{
1954 int growth = 0;
1955 char *buf;
1956
1957 if (size_left == 0)
1958 return 0;
1959
1960 buf = (char *) match32;
1961
1962 while (size_left >= sizeof(*match32)) {
1963 struct ebt_entry_match *match_kern;
1964 int ret;
1965
1966 match_kern = (struct ebt_entry_match *) state->buf_kern_start;
1967 if (match_kern) {
1968 char *tmp;
1969 tmp = state->buf_kern_start + state->buf_kern_offset;
1970 match_kern = (struct ebt_entry_match *) tmp;
1971 }
1972 ret = ebt_buf_add(state, buf, sizeof(*match32));
1973 if (ret < 0)
1974 return ret;
1975 size_left -= sizeof(*match32);
1976
1977 /* add padding before match->data (if any) */
1978 ret = ebt_buf_add_pad(state, ebt_compat_entry_padsize());
1979 if (ret < 0)
1980 return ret;
1981
1982 if (match32->match_size > size_left)
1983 return -EINVAL;
1984
1985 size_left -= match32->match_size;
1986
1987 ret = compat_mtw_from_user(match32, type, state, base);
1988 if (ret < 0)
1989 return ret;
1990
1991 BUG_ON(ret < match32->match_size);
1992 growth += ret - match32->match_size;
1993 growth += ebt_compat_entry_padsize();
1994
1995 buf += sizeof(*match32);
1996 buf += match32->match_size;
1997
1998 if (match_kern)
1999 match_kern->match_size = ret;
2000
2001 WARN_ON(type == EBT_COMPAT_TARGET && size_left);
2002 match32 = (struct compat_ebt_entry_mwt *) buf;
2003 }
2004
2005 return growth;
2006}
2007
2008#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \
2009({ \
2010 unsigned int __i; \
2011 int __ret = 0; \
2012 struct compat_ebt_entry_mwt *__watcher; \
2013 \
2014 for (__i = e->watchers_offset; \
2015 __i < (e)->target_offset; \
2016 __i += __watcher->watcher_size + \
2017 sizeof(struct compat_ebt_entry_mwt)) { \
2018 __watcher = (void *)(e) + __i; \
2019 __ret = fn(__watcher , ## args); \
2020 if (__ret != 0) \
2021 break; \
2022 } \
2023 if (__ret == 0) { \
2024 if (__i != (e)->target_offset) \
2025 __ret = -EINVAL; \
2026 } \
2027 __ret; \
2028})
2029
2030#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \
2031({ \
2032 unsigned int __i; \
2033 int __ret = 0; \
2034 struct compat_ebt_entry_mwt *__match; \
2035 \
2036 for (__i = sizeof(struct ebt_entry); \
2037 __i < (e)->watchers_offset; \
2038 __i += __match->match_size + \
2039 sizeof(struct compat_ebt_entry_mwt)) { \
2040 __match = (void *)(e) + __i; \
2041 __ret = fn(__match , ## args); \
2042 if (__ret != 0) \
2043 break; \
2044 } \
2045 if (__ret == 0) { \
2046 if (__i != (e)->watchers_offset) \
2047 __ret = -EINVAL; \
2048 } \
2049 __ret; \
2050})
2051
2052/* called for all ebt_entry structures. */
2053static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
2054 unsigned int *total,
2055 struct ebt_entries_buf_state *state)
2056{
2057 unsigned int i, j, startoff, new_offset = 0;
2058 /* stores match/watchers/targets & offset of next struct ebt_entry: */
2059 unsigned int offsets[4];
2060 unsigned int *offsets_update = NULL;
2061 int ret;
2062 char *buf_start;
2063
2064 if (*total < sizeof(struct ebt_entries))
2065 return -EINVAL;
2066
2067 if (!entry->bitmask) {
2068 *total -= sizeof(struct ebt_entries);
2069 return ebt_buf_add(state, entry, sizeof(struct ebt_entries));
2070 }
2071 if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry))
2072 return -EINVAL;
2073
2074 startoff = state->buf_user_offset;
2075 /* pull in most part of ebt_entry, it does not need to be changed. */
2076 ret = ebt_buf_add(state, entry,
2077 offsetof(struct ebt_entry, watchers_offset));
2078 if (ret < 0)
2079 return ret;
2080
2081 offsets[0] = sizeof(struct ebt_entry); /* matches come first */
2082 memcpy(&offsets[1], &entry->watchers_offset,
2083 sizeof(offsets) - sizeof(offsets[0]));
2084
2085 if (state->buf_kern_start) {
2086 buf_start = state->buf_kern_start + state->buf_kern_offset;
2087 offsets_update = (unsigned int *) buf_start;
2088 }
2089 ret = ebt_buf_add(state, &offsets[1],
2090 sizeof(offsets) - sizeof(offsets[0]));
2091 if (ret < 0)
2092 return ret;
2093 buf_start = (char *) entry;
2094 /*
2095 * 0: matches offset, always follows ebt_entry.
2096 * 1: watchers offset, from ebt_entry structure
2097 * 2: target offset, from ebt_entry structure
2098 * 3: next ebt_entry offset, from ebt_entry structure
2099 *
2100 * offsets are relative to beginning of struct ebt_entry (i.e., 0).
2101 */
2102 for (i = 0, j = 1 ; j < 4 ; j++, i++) {
2103 struct compat_ebt_entry_mwt *match32;
2104 unsigned int size;
2105 char *buf = buf_start;
2106
2107 buf = buf_start + offsets[i];
2108 if (offsets[i] > offsets[j])
2109 return -EINVAL;
2110
2111 match32 = (struct compat_ebt_entry_mwt *) buf;
2112 size = offsets[j] - offsets[i];
2113 ret = ebt_size_mwt(match32, size, i, state, base);
2114 if (ret < 0)
2115 return ret;
2116 new_offset += ret;
2117 if (offsets_update && new_offset) {
Jan Engelhardtff67e4e2010-03-19 21:08:16 +01002118 pr_debug("change offset %d to %d\n",
Florian Westphal81e675c2010-01-05 16:09:46 +01002119 offsets_update[i], offsets[j] + new_offset);
2120 offsets_update[i] = offsets[j] + new_offset;
2121 }
2122 }
2123
2124 startoff = state->buf_user_offset - startoff;
2125
2126 BUG_ON(*total < startoff);
2127 *total -= startoff;
2128 return 0;
2129}
2130
2131/*
2132 * repl->entries_size is the size of the ebt_entry blob in userspace.
2133 * It might need more memory when copied to a 64 bit kernel in case
2134 * userspace is 32-bit. So, first task: find out how much memory is needed.
2135 *
2136 * Called before validation is performed.
2137 */
2138static int compat_copy_entries(unsigned char *data, unsigned int size_user,
2139 struct ebt_entries_buf_state *state)
2140{
2141 unsigned int size_remaining = size_user;
2142 int ret;
2143
2144 ret = EBT_ENTRY_ITERATE(data, size_user, size_entry_mwt, data,
2145 &size_remaining, state);
2146 if (ret < 0)
2147 return ret;
2148
2149 WARN_ON(size_remaining);
2150 return state->buf_kern_offset;
2151}
2152
2153
2154static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl,
2155 void __user *user, unsigned int len)
2156{
2157 struct compat_ebt_replace tmp;
2158 int i;
2159
2160 if (len < sizeof(tmp))
2161 return -EINVAL;
2162
2163 if (copy_from_user(&tmp, user, sizeof(tmp)))
2164 return -EFAULT;
2165
2166 if (len != sizeof(tmp) + tmp.entries_size)
2167 return -EINVAL;
2168
2169 if (tmp.entries_size == 0)
2170 return -EINVAL;
2171
2172 if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) /
2173 NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
2174 return -ENOMEM;
2175 if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
2176 return -ENOMEM;
2177
2178 memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry));
2179
2180 /* starting with hook_entry, 32 vs. 64 bit structures are different */
2181 for (i = 0; i < NF_BR_NUMHOOKS; i++)
2182 repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]);
2183
2184 repl->num_counters = tmp.num_counters;
2185 repl->counters = compat_ptr(tmp.counters);
2186 repl->entries = compat_ptr(tmp.entries);
2187 return 0;
2188}
2189
2190static int compat_do_replace(struct net *net, void __user *user,
2191 unsigned int len)
2192{
2193 int ret, i, countersize, size64;
2194 struct ebt_table_info *newinfo;
2195 struct ebt_replace tmp;
2196 struct ebt_entries_buf_state state;
2197 void *entries_tmp;
2198
2199 ret = compat_copy_ebt_replace_from_user(&tmp, user, len);
Florian Westphal90b89af2010-02-07 03:19:12 +01002200 if (ret) {
2201 /* try real handler in case userland supplied needed padding */
2202 if (ret == -EINVAL && do_replace(net, user, len) == 0)
2203 ret = 0;
Florian Westphal81e675c2010-01-05 16:09:46 +01002204 return ret;
Florian Westphal90b89af2010-02-07 03:19:12 +01002205 }
Florian Westphal81e675c2010-01-05 16:09:46 +01002206
2207 countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
2208 newinfo = vmalloc(sizeof(*newinfo) + countersize);
2209 if (!newinfo)
2210 return -ENOMEM;
2211
2212 if (countersize)
2213 memset(newinfo->counters, 0, countersize);
2214
2215 memset(&state, 0, sizeof(state));
2216
2217 newinfo->entries = vmalloc(tmp.entries_size);
2218 if (!newinfo->entries) {
2219 ret = -ENOMEM;
2220 goto free_newinfo;
2221 }
2222 if (copy_from_user(
2223 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
2224 ret = -EFAULT;
2225 goto free_entries;
2226 }
2227
2228 entries_tmp = newinfo->entries;
2229
2230 xt_compat_lock(NFPROTO_BRIDGE);
2231
2232 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2233 if (ret < 0)
2234 goto out_unlock;
2235
2236 pr_debug("tmp.entries_size %d, kern off %d, user off %d delta %d\n",
2237 tmp.entries_size, state.buf_kern_offset, state.buf_user_offset,
2238 xt_compat_calc_jump(NFPROTO_BRIDGE, tmp.entries_size));
2239
2240 size64 = ret;
2241 newinfo->entries = vmalloc(size64);
2242 if (!newinfo->entries) {
2243 vfree(entries_tmp);
2244 ret = -ENOMEM;
2245 goto out_unlock;
2246 }
2247
2248 memset(&state, 0, sizeof(state));
2249 state.buf_kern_start = newinfo->entries;
2250 state.buf_kern_len = size64;
2251
2252 ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
2253 BUG_ON(ret < 0); /* parses same data again */
2254
2255 vfree(entries_tmp);
2256 tmp.entries_size = size64;
2257
2258 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
2259 char __user *usrptr;
2260 if (tmp.hook_entry[i]) {
2261 unsigned int delta;
2262 usrptr = (char __user *) tmp.hook_entry[i];
2263 delta = usrptr - tmp.entries;
2264 usrptr += xt_compat_calc_jump(NFPROTO_BRIDGE, delta);
2265 tmp.hook_entry[i] = (struct ebt_entries __user *)usrptr;
2266 }
2267 }
2268
2269 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2270 xt_compat_unlock(NFPROTO_BRIDGE);
2271
2272 ret = do_replace_finish(net, &tmp, newinfo);
2273 if (ret == 0)
2274 return ret;
2275free_entries:
2276 vfree(newinfo->entries);
2277free_newinfo:
2278 vfree(newinfo);
2279 return ret;
2280out_unlock:
2281 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2282 xt_compat_unlock(NFPROTO_BRIDGE);
2283 goto free_entries;
2284}
2285
2286static int compat_update_counters(struct net *net, void __user *user,
2287 unsigned int len)
2288{
2289 struct compat_ebt_replace hlp;
2290
2291 if (copy_from_user(&hlp, user, sizeof(hlp)))
2292 return -EFAULT;
2293
Florian Westphal90b89af2010-02-07 03:19:12 +01002294 /* try real handler in case userland supplied needed padding */
Florian Westphal81e675c2010-01-05 16:09:46 +01002295 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
Florian Westphal90b89af2010-02-07 03:19:12 +01002296 return update_counters(net, user, len);
Florian Westphal81e675c2010-01-05 16:09:46 +01002297
2298 return do_update_counters(net, hlp.name, compat_ptr(hlp.counters),
2299 hlp.num_counters, user, len);
2300}
2301
2302static int compat_do_ebt_set_ctl(struct sock *sk,
2303 int cmd, void __user *user, unsigned int len)
2304{
2305 int ret;
2306
2307 if (!capable(CAP_NET_ADMIN))
2308 return -EPERM;
2309
2310 switch (cmd) {
2311 case EBT_SO_SET_ENTRIES:
2312 ret = compat_do_replace(sock_net(sk), user, len);
2313 break;
2314 case EBT_SO_SET_COUNTERS:
2315 ret = compat_update_counters(sock_net(sk), user, len);
2316 break;
2317 default:
2318 ret = -EINVAL;
2319 }
2320 return ret;
2321}
2322
2323static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
2324 void __user *user, int *len)
2325{
2326 int ret;
2327 struct compat_ebt_replace tmp;
2328 struct ebt_table *t;
2329
2330 if (!capable(CAP_NET_ADMIN))
2331 return -EPERM;
2332
Florian Westphal90b89af2010-02-07 03:19:12 +01002333 /* try real handler in case userland supplied needed padding */
Florian Westphal81e675c2010-01-05 16:09:46 +01002334 if ((cmd == EBT_SO_GET_INFO ||
2335 cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp))
Florian Westphal90b89af2010-02-07 03:19:12 +01002336 return do_ebt_get_ctl(sk, cmd, user, len);
Florian Westphal81e675c2010-01-05 16:09:46 +01002337
2338 if (copy_from_user(&tmp, user, sizeof(tmp)))
2339 return -EFAULT;
2340
2341 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
2342 if (!t)
2343 return ret;
2344
2345 xt_compat_lock(NFPROTO_BRIDGE);
2346 switch (cmd) {
2347 case EBT_SO_GET_INFO:
2348 tmp.nentries = t->private->nentries;
2349 ret = compat_table_info(t->private, &tmp);
2350 if (ret)
2351 goto out;
2352 tmp.valid_hooks = t->valid_hooks;
2353
2354 if (copy_to_user(user, &tmp, *len) != 0) {
2355 ret = -EFAULT;
2356 break;
2357 }
2358 ret = 0;
2359 break;
2360 case EBT_SO_GET_INIT_INFO:
2361 tmp.nentries = t->table->nentries;
2362 tmp.entries_size = t->table->entries_size;
2363 tmp.valid_hooks = t->table->valid_hooks;
2364
2365 if (copy_to_user(user, &tmp, *len) != 0) {
2366 ret = -EFAULT;
2367 break;
2368 }
2369 ret = 0;
2370 break;
2371 case EBT_SO_GET_ENTRIES:
2372 case EBT_SO_GET_INIT_ENTRIES:
Florian Westphal90b89af2010-02-07 03:19:12 +01002373 /*
2374 * try real handler first in case of userland-side padding.
2375 * in case we are dealing with an 'ordinary' 32 bit binary
2376 * without 64bit compatibility padding, this will fail right
2377 * after copy_from_user when the *len argument is validated.
2378 *
2379 * the compat_ variant needs to do one pass over the kernel
2380 * data set to adjust for size differences before it the check.
2381 */
2382 if (copy_everything_to_user(t, user, len, cmd) == 0)
2383 ret = 0;
2384 else
2385 ret = compat_copy_everything_to_user(t, user, len, cmd);
Florian Westphal81e675c2010-01-05 16:09:46 +01002386 break;
2387 default:
2388 ret = -EINVAL;
2389 }
2390 out:
2391 xt_compat_flush_offsets(NFPROTO_BRIDGE);
2392 xt_compat_unlock(NFPROTO_BRIDGE);
2393 mutex_unlock(&ebt_mutex);
2394 return ret;
2395}
2396#endif
2397
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398static struct nf_sockopt_ops ebt_sockopts =
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002399{
2400 .pf = PF_INET,
2401 .set_optmin = EBT_BASE_CTL,
2402 .set_optmax = EBT_SO_SET_MAX + 1,
2403 .set = do_ebt_set_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002404#ifdef CONFIG_COMPAT
2405 .compat_set = compat_do_ebt_set_ctl,
2406#endif
Andrew Morton74ca4e5a2006-03-20 22:55:02 -08002407 .get_optmin = EBT_BASE_CTL,
2408 .get_optmax = EBT_SO_GET_MAX + 1,
2409 .get = do_ebt_get_ctl,
Florian Westphal81e675c2010-01-05 16:09:46 +01002410#ifdef CONFIG_COMPAT
2411 .compat_get = compat_do_ebt_get_ctl,
2412#endif
Neil Horman16fcec32007-09-11 11:28:26 +02002413 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414};
2415
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002416static int __init ebtables_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417{
2418 int ret;
2419
Jan Engelhardt043ef462008-10-08 11:35:15 +02002420 ret = xt_register_target(&ebt_standard_target);
2421 if (ret < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 return ret;
Jan Engelhardt043ef462008-10-08 11:35:15 +02002423 ret = nf_register_sockopt(&ebt_sockopts);
2424 if (ret < 0) {
2425 xt_unregister_target(&ebt_standard_target);
2426 return ret;
2427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Patrick McHardya887c1c2007-07-14 20:46:15 -07002429 printk(KERN_INFO "Ebtables v2.0 registered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return 0;
2431}
2432
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002433static void __exit ebtables_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434{
2435 nf_unregister_sockopt(&ebt_sockopts);
Jan Engelhardt043ef462008-10-08 11:35:15 +02002436 xt_unregister_target(&ebt_standard_target);
Patrick McHardya887c1c2007-07-14 20:46:15 -07002437 printk(KERN_INFO "Ebtables v2.0 unregistered\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438}
2439
2440EXPORT_SYMBOL(ebt_register_table);
2441EXPORT_SYMBOL(ebt_unregister_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442EXPORT_SYMBOL(ebt_do_table);
Andrew Morton65b4b4e2006-03-28 16:37:06 -08002443module_init(ebtables_init);
2444module_exit(ebtables_fini);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445MODULE_LICENSE("GPL");