|
@@ -35,8 +35,7 @@
|
|
"report to author: "format, ## args)
|
|
"report to author: "format, ## args)
|
|
/* #define BUGPRINT(format, args...) */
|
|
/* #define BUGPRINT(format, args...) */
|
|
|
|
|
|
-/*
|
|
|
|
- * Each cpu has its own set of counters, so there is no need for write_lock in
|
|
|
|
|
|
+/* Each cpu has its own set of counters, so there is no need for write_lock in
|
|
* the softirq
|
|
* the softirq
|
|
* For reading or updating the counters, the user context needs to
|
|
* For reading or updating the counters, the user context needs to
|
|
* get a write_lock
|
|
* get a write_lock
|
|
@@ -46,7 +45,7 @@
|
|
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
|
|
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
|
|
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
|
|
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
|
|
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
|
|
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
|
|
- COUNTER_OFFSET(n) * cpu))
|
|
|
|
|
|
+ COUNTER_OFFSET(n) * cpu))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -126,7 +125,7 @@ ebt_dev_check(const char *entry, const struct net_device *device)
|
|
/* process standard matches */
|
|
/* process standard matches */
|
|
static inline int
|
|
static inline int
|
|
ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
|
ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
|
- const struct net_device *in, const struct net_device *out)
|
|
|
|
|
|
+ const struct net_device *in, const struct net_device *out)
|
|
{
|
|
{
|
|
const struct ethhdr *h = eth_hdr(skb);
|
|
const struct ethhdr *h = eth_hdr(skb);
|
|
const struct net_bridge_port *p;
|
|
const struct net_bridge_port *p;
|
|
@@ -162,7 +161,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
|
for (i = 0; i < 6; i++)
|
|
for (i = 0; i < 6; i++)
|
|
verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
|
|
verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
|
|
e->sourcemsk[i];
|
|
e->sourcemsk[i];
|
|
- if (FWINV2(verdict != 0, EBT_ISOURCE) )
|
|
|
|
|
|
+ if (FWINV2(verdict != 0, EBT_ISOURCE))
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
if (e->bitmask & EBT_DESTMAC) {
|
|
if (e->bitmask & EBT_DESTMAC) {
|
|
@@ -170,7 +169,7 @@ ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
|
|
for (i = 0; i < 6; i++)
|
|
for (i = 0; i < 6; i++)
|
|
verdict |= (h->h_dest[i] ^ e->destmac[i]) &
|
|
verdict |= (h->h_dest[i] ^ e->destmac[i]) &
|
|
e->destmsk[i];
|
|
e->destmsk[i];
|
|
- if (FWINV2(verdict != 0, EBT_IDEST) )
|
|
|
|
|
|
+ if (FWINV2(verdict != 0, EBT_IDEST))
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
@@ -237,7 +236,8 @@ unsigned int ebt_do_table(struct sk_buff *skb,
|
|
(*(counter_base + i)).bcnt += skb->len;
|
|
(*(counter_base + i)).bcnt += skb->len;
|
|
|
|
|
|
/* these should only watch: not modify, nor tell us
|
|
/* these should only watch: not modify, nor tell us
|
|
- what to do with the packet */
|
|
|
|
|
|
+ * what to do with the packet
|
|
|
|
+ */
|
|
EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar);
|
|
EBT_WATCHER_ITERATE(point, ebt_do_watcher, skb, &acpar);
|
|
|
|
|
|
t = (struct ebt_entry_target *)
|
|
t = (struct ebt_entry_target *)
|
|
@@ -323,7 +323,7 @@ letscontinue:
|
|
/* If it succeeds, returns element and locks mutex */
|
|
/* If it succeeds, returns element and locks mutex */
|
|
static inline void *
|
|
static inline void *
|
|
find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
|
|
find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
|
|
- struct mutex *mutex)
|
|
|
|
|
|
+ struct mutex *mutex)
|
|
{
|
|
{
|
|
struct {
|
|
struct {
|
|
struct list_head list;
|
|
struct list_head list;
|
|
@@ -342,7 +342,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
|
|
|
|
|
|
static void *
|
|
static void *
|
|
find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
|
|
find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
|
|
- int *error, struct mutex *mutex)
|
|
|
|
|
|
+ int *error, struct mutex *mutex)
|
|
{
|
|
{
|
|
return try_then_request_module(
|
|
return try_then_request_module(
|
|
find_inlist_lock_noload(head, name, error, mutex),
|
|
find_inlist_lock_noload(head, name, error, mutex),
|
|
@@ -451,7 +451,8 @@ static int ebt_verify_pointers(const struct ebt_replace *repl,
|
|
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
|
|
if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
|
|
if (e->bitmask != 0) {
|
|
if (e->bitmask != 0) {
|
|
/* we make userspace set this right,
|
|
/* we make userspace set this right,
|
|
- so there is no misunderstanding */
|
|
|
|
|
|
+ * so there is no misunderstanding
|
|
|
|
+ */
|
|
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
|
|
BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
|
|
"in distinguisher\n");
|
|
"in distinguisher\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -487,15 +488,14 @@ static int ebt_verify_pointers(const struct ebt_replace *repl,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * this one is very careful, as it is the first function
|
|
|
|
|
|
+/* this one is very careful, as it is the first function
|
|
* to parse the userspace data
|
|
* to parse the userspace data
|
|
*/
|
|
*/
|
|
static inline int
|
|
static inline int
|
|
ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
|
|
ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
|
|
- const struct ebt_table_info *newinfo,
|
|
|
|
- unsigned int *n, unsigned int *cnt,
|
|
|
|
- unsigned int *totalcnt, unsigned int *udc_cnt)
|
|
|
|
|
|
+ const struct ebt_table_info *newinfo,
|
|
|
|
+ unsigned int *n, unsigned int *cnt,
|
|
|
|
+ unsigned int *totalcnt, unsigned int *udc_cnt)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
|
|
@@ -504,10 +504,12 @@ ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
/* beginning of a new chain
|
|
/* beginning of a new chain
|
|
- if i == NF_BR_NUMHOOKS it must be a user defined chain */
|
|
|
|
|
|
+ * if i == NF_BR_NUMHOOKS it must be a user defined chain
|
|
|
|
+ */
|
|
if (i != NF_BR_NUMHOOKS || !e->bitmask) {
|
|
if (i != NF_BR_NUMHOOKS || !e->bitmask) {
|
|
/* this checks if the previous chain has as many entries
|
|
/* this checks if the previous chain has as many entries
|
|
- as it said it has */
|
|
|
|
|
|
+ * as it said it has
|
|
|
|
+ */
|
|
if (*n != *cnt) {
|
|
if (*n != *cnt) {
|
|
BUGPRINT("nentries does not equal the nr of entries "
|
|
BUGPRINT("nentries does not equal the nr of entries "
|
|
"in the chain\n");
|
|
"in the chain\n");
|
|
@@ -549,20 +551,18 @@ ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-struct ebt_cl_stack
|
|
|
|
-{
|
|
|
|
|
|
+struct ebt_cl_stack {
|
|
struct ebt_chainstack cs;
|
|
struct ebt_chainstack cs;
|
|
int from;
|
|
int from;
|
|
unsigned int hookmask;
|
|
unsigned int hookmask;
|
|
};
|
|
};
|
|
|
|
|
|
-/*
|
|
|
|
- * we need these positions to check that the jumps to a different part of the
|
|
|
|
|
|
+/* We need these positions to check that the jumps to a different part of the
|
|
* entries is a jump to the beginning of a new chain.
|
|
* entries is a jump to the beginning of a new chain.
|
|
*/
|
|
*/
|
|
static inline int
|
|
static inline int
|
|
ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
|
ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
|
|
- unsigned int *n, struct ebt_cl_stack *udc)
|
|
|
|
|
|
+ unsigned int *n, struct ebt_cl_stack *udc)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
|
|
@@ -649,9 +649,9 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
|
|
|
|
|
|
static inline int
|
|
static inline int
|
|
ebt_check_entry(struct ebt_entry *e, struct net *net,
|
|
ebt_check_entry(struct ebt_entry *e, struct net *net,
|
|
- const struct ebt_table_info *newinfo,
|
|
|
|
- const char *name, unsigned int *cnt,
|
|
|
|
- struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
|
|
|
|
|
|
+ const struct ebt_table_info *newinfo,
|
|
|
|
+ const char *name, unsigned int *cnt,
|
|
|
|
+ struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
|
|
{
|
|
{
|
|
struct ebt_entry_target *t;
|
|
struct ebt_entry_target *t;
|
|
struct xt_target *target;
|
|
struct xt_target *target;
|
|
@@ -673,7 +673,7 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
|
|
BUGPRINT("Unknown flag for inv bitmask\n");
|
|
BUGPRINT("Unknown flag for inv bitmask\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
|
|
|
|
|
|
+ if ((e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3)) {
|
|
BUGPRINT("NOPROTO & 802_3 not allowed\n");
|
|
BUGPRINT("NOPROTO & 802_3 not allowed\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -687,7 +687,8 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
/* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
|
|
/* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
|
|
- a base chain */
|
|
|
|
|
|
+ * a base chain
|
|
|
|
+ */
|
|
if (i < NF_BR_NUMHOOKS)
|
|
if (i < NF_BR_NUMHOOKS)
|
|
hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
|
|
hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
|
|
else {
|
|
else {
|
|
@@ -758,13 +759,12 @@ cleanup_matches:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * checks for loops and sets the hook mask for udc
|
|
|
|
|
|
+/* checks for loops and sets the hook mask for udc
|
|
* the hook mask for udc tells us from which base chains the udc can be
|
|
* the hook mask for udc tells us from which base chains the udc can be
|
|
* accessed. This mask is a parameter to the check() functions of the extensions
|
|
* accessed. This mask is a parameter to the check() functions of the extensions
|
|
*/
|
|
*/
|
|
static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
|
|
static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
|
|
- unsigned int udc_cnt, unsigned int hooknr, char *base)
|
|
|
|
|
|
+ unsigned int udc_cnt, unsigned int hooknr, char *base)
|
|
{
|
|
{
|
|
int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
|
|
int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
|
|
const struct ebt_entry *e = (struct ebt_entry *)chain->data;
|
|
const struct ebt_entry *e = (struct ebt_entry *)chain->data;
|
|
@@ -853,7 +853,8 @@ static int translate_table(struct net *net, const char *name,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
/* make sure chains are ordered after each other in same order
|
|
/* make sure chains are ordered after each other in same order
|
|
- as their corresponding hooks */
|
|
|
|
|
|
+ * as their corresponding hooks
|
|
|
|
+ */
|
|
for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
|
|
for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
|
|
if (!newinfo->hook_entry[j])
|
|
if (!newinfo->hook_entry[j])
|
|
continue;
|
|
continue;
|
|
@@ -868,7 +869,8 @@ static int translate_table(struct net *net, const char *name,
|
|
i = 0; /* holds the expected nr. of entries for the chain */
|
|
i = 0; /* holds the expected nr. of entries for the chain */
|
|
j = 0; /* holds the up to now counted entries for the chain */
|
|
j = 0; /* holds the up to now counted entries for the chain */
|
|
k = 0; /* holds the total nr. of entries, should equal
|
|
k = 0; /* holds the total nr. of entries, should equal
|
|
- newinfo->nentries afterwards */
|
|
|
|
|
|
+ * newinfo->nentries afterwards
|
|
|
|
+ */
|
|
udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
|
|
udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
|
|
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
|
ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
|
|
ebt_check_entry_size_and_hooks, newinfo,
|
|
ebt_check_entry_size_and_hooks, newinfo,
|
|
@@ -888,10 +890,12 @@ static int translate_table(struct net *net, const char *name,
|
|
}
|
|
}
|
|
|
|
|
|
/* get the location of the udc, put them in an array
|
|
/* get the location of the udc, put them in an array
|
|
- while we're at it, allocate the chainstack */
|
|
|
|
|
|
+ * while we're at it, allocate the chainstack
|
|
|
|
+ */
|
|
if (udc_cnt) {
|
|
if (udc_cnt) {
|
|
/* this will get free'd in do_replace()/ebt_register_table()
|
|
/* this will get free'd in do_replace()/ebt_register_table()
|
|
- if an error occurs */
|
|
|
|
|
|
+ * if an error occurs
|
|
|
|
+ */
|
|
newinfo->chainstack =
|
|
newinfo->chainstack =
|
|
vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
|
|
vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
|
|
if (!newinfo->chainstack)
|
|
if (!newinfo->chainstack)
|
|
@@ -932,14 +936,15 @@ static int translate_table(struct net *net, const char *name,
|
|
}
|
|
}
|
|
|
|
|
|
/* we now know the following (along with E=mc²):
|
|
/* we now know the following (along with E=mc²):
|
|
- - the nr of entries in each chain is right
|
|
|
|
- - the size of the allocated space is right
|
|
|
|
- - all valid hooks have a corresponding chain
|
|
|
|
- - there are no loops
|
|
|
|
- - wrong data can still be on the level of a single entry
|
|
|
|
- - could be there are jumps to places that are not the
|
|
|
|
- beginning of a chain. This can only occur in chains that
|
|
|
|
- are not accessible from any base chains, so we don't care. */
|
|
|
|
|
|
+ * - the nr of entries in each chain is right
|
|
|
|
+ * - the size of the allocated space is right
|
|
|
|
+ * - all valid hooks have a corresponding chain
|
|
|
|
+ * - there are no loops
|
|
|
|
+ * - wrong data can still be on the level of a single entry
|
|
|
|
+ * - could be there are jumps to places that are not the
|
|
|
|
+ * beginning of a chain. This can only occur in chains that
|
|
|
|
+ * are not accessible from any base chains, so we don't care.
|
|
|
|
+ */
|
|
|
|
|
|
/* used to know what we need to clean up if something goes wrong */
|
|
/* used to know what we need to clean up if something goes wrong */
|
|
i = 0;
|
|
i = 0;
|
|
@@ -955,7 +960,7 @@ static int translate_table(struct net *net, const char *name,
|
|
|
|
|
|
/* called under write_lock */
|
|
/* called under write_lock */
|
|
static void get_counters(const struct ebt_counter *oldcounters,
|
|
static void get_counters(const struct ebt_counter *oldcounters,
|
|
- struct ebt_counter *counters, unsigned int nentries)
|
|
|
|
|
|
+ struct ebt_counter *counters, unsigned int nentries)
|
|
{
|
|
{
|
|
int i, cpu;
|
|
int i, cpu;
|
|
struct ebt_counter *counter_base;
|
|
struct ebt_counter *counter_base;
|
|
@@ -986,7 +991,8 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
|
|
struct ebt_table *t;
|
|
struct ebt_table *t;
|
|
|
|
|
|
/* the user wants counters back
|
|
/* the user wants counters back
|
|
- the check on the size is done later, when we have the lock */
|
|
|
|
|
|
+ * the check on the size is done later, when we have the lock
|
|
|
|
+ */
|
|
if (repl->num_counters) {
|
|
if (repl->num_counters) {
|
|
unsigned long size = repl->num_counters * sizeof(*counterstmp);
|
|
unsigned long size = repl->num_counters * sizeof(*counterstmp);
|
|
counterstmp = vmalloc(size);
|
|
counterstmp = vmalloc(size);
|
|
@@ -1038,9 +1044,10 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
|
|
write_unlock_bh(&t->lock);
|
|
write_unlock_bh(&t->lock);
|
|
mutex_unlock(&ebt_mutex);
|
|
mutex_unlock(&ebt_mutex);
|
|
/* so, a user can change the chains while having messed up her counter
|
|
/* so, a user can change the chains while having messed up her counter
|
|
- allocation. Only reason why this is done is because this way the lock
|
|
|
|
- is held only once, while this doesn't bring the kernel into a
|
|
|
|
- dangerous state. */
|
|
|
|
|
|
+ * allocation. Only reason why this is done is because this way the lock
|
|
|
|
+ * is held only once, while this doesn't bring the kernel into a
|
|
|
|
+ * dangerous state.
|
|
|
|
+ */
|
|
if (repl->num_counters &&
|
|
if (repl->num_counters &&
|
|
copy_to_user(repl->counters, counterstmp,
|
|
copy_to_user(repl->counters, counterstmp,
|
|
repl->num_counters * sizeof(struct ebt_counter))) {
|
|
repl->num_counters * sizeof(struct ebt_counter))) {
|
|
@@ -1342,13 +1349,14 @@ static int update_counters(struct net *net, const void __user *user,
|
|
}
|
|
}
|
|
|
|
|
|
static inline int ebt_make_matchname(const struct ebt_entry_match *m,
|
|
static inline int ebt_make_matchname(const struct ebt_entry_match *m,
|
|
- const char *base, char __user *ubase)
|
|
|
|
|
|
+ const char *base, char __user *ubase)
|
|
{
|
|
{
|
|
char __user *hlp = ubase + ((char *)m - base);
|
|
char __user *hlp = ubase + ((char *)m - base);
|
|
char name[EBT_FUNCTION_MAXNAMELEN] = {};
|
|
char name[EBT_FUNCTION_MAXNAMELEN] = {};
|
|
|
|
|
|
/* ebtables expects 32 bytes long names but xt_match names are 29 bytes
|
|
/* ebtables expects 32 bytes long names but xt_match names are 29 bytes
|
|
- long. Copy 29 bytes and fill remaining bytes with zeroes. */
|
|
|
|
|
|
+ * long. Copy 29 bytes and fill remaining bytes with zeroes.
|
|
|
|
+ */
|
|
strlcpy(name, m->u.match->name, sizeof(name));
|
|
strlcpy(name, m->u.match->name, sizeof(name));
|
|
if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))
|
|
if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
@@ -1356,19 +1364,19 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m,
|
|
}
|
|
}
|
|
|
|
|
|
static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
|
|
static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
|
|
- const char *base, char __user *ubase)
|
|
|
|
|
|
+ const char *base, char __user *ubase)
|
|
{
|
|
{
|
|
char __user *hlp = ubase + ((char *)w - base);
|
|
char __user *hlp = ubase + ((char *)w - base);
|
|
char name[EBT_FUNCTION_MAXNAMELEN] = {};
|
|
char name[EBT_FUNCTION_MAXNAMELEN] = {};
|
|
|
|
|
|
strlcpy(name, w->u.watcher->name, sizeof(name));
|
|
strlcpy(name, w->u.watcher->name, sizeof(name));
|
|
- if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN))
|
|
|
|
|
|
+ if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline int
|
|
|
|
-ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
|
|
|
|
|
|
+static inline int ebt_make_names(struct ebt_entry *e, const char *base,
|
|
|
|
+ char __user *ubase)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
char __user *hlp;
|
|
char __user *hlp;
|
|
@@ -1394,9 +1402,9 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
|
|
}
|
|
}
|
|
|
|
|
|
static int copy_counters_to_user(struct ebt_table *t,
|
|
static int copy_counters_to_user(struct ebt_table *t,
|
|
- const struct ebt_counter *oldcounters,
|
|
|
|
- void __user *user, unsigned int num_counters,
|
|
|
|
- unsigned int nentries)
|
|
|
|
|
|
+ const struct ebt_counter *oldcounters,
|
|
|
|
+ void __user *user, unsigned int num_counters,
|
|
|
|
+ unsigned int nentries)
|
|
{
|
|
{
|
|
struct ebt_counter *counterstmp;
|
|
struct ebt_counter *counterstmp;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
@@ -1427,7 +1435,7 @@ static int copy_counters_to_user(struct ebt_table *t,
|
|
|
|
|
|
/* called with ebt_mutex locked */
|
|
/* called with ebt_mutex locked */
|
|
static int copy_everything_to_user(struct ebt_table *t, void __user *user,
|
|
static int copy_everything_to_user(struct ebt_table *t, void __user *user,
|
|
- const int *len, int cmd)
|
|
|
|
|
|
+ const int *len, int cmd)
|
|
{
|
|
{
|
|
struct ebt_replace tmp;
|
|
struct ebt_replace tmp;
|
|
const struct ebt_counter *oldcounters;
|
|
const struct ebt_counter *oldcounters;
|
|
@@ -1595,8 +1603,7 @@ static int ebt_compat_entry_padsize(void)
|
|
static int ebt_compat_match_offset(const struct xt_match *match,
|
|
static int ebt_compat_match_offset(const struct xt_match *match,
|
|
unsigned int userlen)
|
|
unsigned int userlen)
|
|
{
|
|
{
|
|
- /*
|
|
|
|
- * ebt_among needs special handling. The kernel .matchsize is
|
|
|
|
|
|
+ /* ebt_among needs special handling. The kernel .matchsize is
|
|
* set to -1 at registration time; at runtime an EBT_ALIGN()ed
|
|
* set to -1 at registration time; at runtime an EBT_ALIGN()ed
|
|
* value is expected.
|
|
* value is expected.
|
|
* Example: userspace sends 4500, ebt_among.c wants 4504.
|
|
* Example: userspace sends 4500, ebt_among.c wants 4504.
|
|
@@ -1966,8 +1973,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
|
|
return off + match_size;
|
|
return off + match_size;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * return size of all matches, watchers or target, including necessary
|
|
|
|
|
|
+/* return size of all matches, watchers or target, including necessary
|
|
* alignment and padding.
|
|
* alignment and padding.
|
|
*/
|
|
*/
|
|
static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
|
|
static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
|
|
@@ -2070,8 +2076,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
buf_start = (char *) entry;
|
|
buf_start = (char *) entry;
|
|
- /*
|
|
|
|
- * 0: matches offset, always follows ebt_entry.
|
|
|
|
|
|
+ /* 0: matches offset, always follows ebt_entry.
|
|
* 1: watchers offset, from ebt_entry structure
|
|
* 1: watchers offset, from ebt_entry structure
|
|
* 2: target offset, from ebt_entry structure
|
|
* 2: target offset, from ebt_entry structure
|
|
* 3: next ebt_entry offset, from ebt_entry structure
|
|
* 3: next ebt_entry offset, from ebt_entry structure
|
|
@@ -2115,8 +2120,7 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * repl->entries_size is the size of the ebt_entry blob in userspace.
|
|
|
|
|
|
+/* repl->entries_size is the size of the ebt_entry blob in userspace.
|
|
* It might need more memory when copied to a 64 bit kernel in case
|
|
* It might need more memory when copied to a 64 bit kernel in case
|
|
* userspace is 32-bit. So, first task: find out how much memory is needed.
|
|
* userspace is 32-bit. So, first task: find out how much memory is needed.
|
|
*
|
|
*
|
|
@@ -2305,7 +2309,7 @@ static int compat_do_ebt_set_ctl(struct sock *sk,
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
- }
|
|
|
|
|
|
+ }
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2360,8 +2364,7 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd,
|
|
break;
|
|
break;
|
|
case EBT_SO_GET_ENTRIES:
|
|
case EBT_SO_GET_ENTRIES:
|
|
case EBT_SO_GET_INIT_ENTRIES:
|
|
case EBT_SO_GET_INIT_ENTRIES:
|
|
- /*
|
|
|
|
- * try real handler first in case of userland-side padding.
|
|
|
|
|
|
+ /* try real handler first in case of userland-side padding.
|
|
* in case we are dealing with an 'ordinary' 32 bit binary
|
|
* in case we are dealing with an 'ordinary' 32 bit binary
|
|
* without 64bit compatibility padding, this will fail right
|
|
* without 64bit compatibility padding, this will fail right
|
|
* after copy_from_user when the *len argument is validated.
|
|
* after copy_from_user when the *len argument is validated.
|