diff options
Diffstat (limited to 'net/bridge/netfilter/ebtables.c')
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index a94d23b0a9af..032e0fe45940 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -223,9 +223,7 @@ unsigned int ebt_do_table(struct sk_buff *skb, return NF_DROP; } - /* increase counter */ - (*(counter_base + i)).pcnt++; - (*(counter_base + i)).bcnt += skb->len; + ADD_COUNTER(*(counter_base + i), 1, skb->len); /* these should only watch: not modify, nor tell us * what to do with the packet @@ -358,12 +356,12 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, left - sizeof(struct ebt_entry_match) < m->match_size) return -EINVAL; - match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); + match = xt_find_match(NFPROTO_BRIDGE, m->u.name, m->u.revision); if (IS_ERR(match) || match->family != NFPROTO_BRIDGE) { if (!IS_ERR(match)) module_put(match->me); request_module("ebt_%s", m->u.name); - match = xt_find_match(NFPROTO_BRIDGE, m->u.name, 0); + match = xt_find_match(NFPROTO_BRIDGE, m->u.name, m->u.revision); } if (IS_ERR(match)) return PTR_ERR(match); @@ -968,10 +966,9 @@ static void get_counters(const struct ebt_counter *oldcounters, if (cpu == 0) continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); - for (i = 0; i < nentries; i++) { - counters[i].pcnt += counter_base[i].pcnt; - counters[i].bcnt += counter_base[i].bcnt; - } + for (i = 0; i < nentries; i++) + ADD_COUNTER(counters[i], counter_base[i].pcnt, + counter_base[i].bcnt); } } @@ -1324,10 +1321,8 @@ static int do_update_counters(struct net *net, const char *name, write_lock_bh(&t->lock); /* we add to the counters of the first cpu */ - for (i = 0; i < num_counters; i++) { - t->private->counters[i].pcnt += tmp[i].pcnt; - t->private->counters[i].bcnt += tmp[i].bcnt; - } + for (i = 0; i < num_counters; i++) + ADD_COUNTER(t->private->counters[i], tmp[i].pcnt, tmp[i].bcnt); write_unlock_bh(&t->lock); ret = 0; @@ -1355,16 +1350,17 @@ static int update_counters(struct net *net, const void __user *user, static inline int ebt_obj_to_user(char __user *um, const char *_name, const char *data, int entrysize, - int usersize, int datasize) + int usersize, int datasize, u8 revision) { - char name[EBT_FUNCTION_MAXNAMELEN] = {0}; + char name[EBT_EXTENSION_MAXNAMELEN] = {0}; - /* ebtables expects 32 bytes long names but xt_match names are 29 bytes + /* ebtables expects 31 bytes long names but xt_match names are 29 bytes * long. Copy 29 bytes and fill remaining bytes with zeroes. */ strlcpy(name, _name, sizeof(name)); - if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) || - put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) || + if (copy_to_user(um, name, EBT_EXTENSION_MAXNAMELEN) || + put_user(revision, (u8 __user *)(um + EBT_EXTENSION_MAXNAMELEN)) || + put_user(datasize, (int __user *)(um + EBT_EXTENSION_MAXNAMELEN + 1)) || xt_data_to_user(um + entrysize, data, usersize, datasize, XT_ALIGN(datasize))) return -EFAULT; @@ -1377,7 +1373,8 @@ static inline int ebt_match_to_user(const struct ebt_entry_match *m, { return ebt_obj_to_user(ubase + ((char *)m - base), m->u.match->name, m->data, sizeof(*m), - m->u.match->usersize, m->match_size); + m->u.match->usersize, m->match_size, + m->u.match->revision); } static inline int ebt_watcher_to_user(const struct ebt_entry_watcher *w, @@ -1385,7 +1382,8 @@ static inline int ebt_watcher_to_user(const struct ebt_entry_watcher *w, { return ebt_obj_to_user(ubase + ((char *)w - base), w->u.watcher->name, w->data, sizeof(*w), - w->u.watcher->usersize, w->watcher_size); + w->u.watcher->usersize, w->watcher_size, + w->u.watcher->revision); } static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base, @@ -1416,7 +1414,8 @@ static inline int ebt_entry_to_user(struct ebt_entry *e, const char *base, if (ret != 0) return ret; ret = ebt_obj_to_user(hlp, t->u.target->name, t->data, sizeof(*t), - t->u.target->usersize, t->target_size); + t->u.target->usersize, t->target_size, + t->u.target->revision); if (ret != 0) return ret; @@ -1604,7 +1603,10 @@ struct compat_ebt_replace { /* struct ebt_entry_match, _target and _watcher have same layout */ struct compat_ebt_entry_mwt { union { - char name[EBT_FUNCTION_MAXNAMELEN]; + struct { + char name[EBT_EXTENSION_MAXNAMELEN]; + u8 revision; + }; compat_uptr_t ptr; } u; compat_uint_t match_size; @@ -1644,8 +1646,9 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr, if (WARN_ON(off >= m->match_size)) return -EINVAL; - if (copy_to_user(cm->u.name, match->name, - strlen(match->name) + 1) || put_user(msize, &cm->match_size)) + if (copy_to_user(cm->u.name, match->name, strlen(match->name) + 1) || + put_user(match->revision, &cm->u.revision) || + put_user(msize, &cm->match_size)) return -EFAULT; if (match->compat_to_user) { @@ -1675,8 +1678,9 @@ static int compat_target_to_user(struct ebt_entry_target *t, if (WARN_ON(off >= t->target_size)) return -EINVAL; - if (copy_to_user(cm->u.name, target->name, - strlen(target->name) + 1) || put_user(tsize, &cm->match_size)) + if (copy_to_user(cm->u.name, target->name, strlen(target->name) + 1) || + put_user(target->revision, &cm->u.revision) || + put_user(tsize, &cm->match_size)) return -EFAULT; if (target->compat_to_user) { @@ -1821,10 +1825,14 @@ static int compat_table_info(const struct ebt_table_info *info, { unsigned int size = info->entries_size; const void *entries = info->entries; + int ret; newinfo->entries_size = size; - xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); + ret = xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); + if (ret) + return ret; + return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, entries, newinfo); } @@ -1938,7 +1946,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, struct ebt_entries_buf_state *state, const unsigned char *base) { - char name[EBT_FUNCTION_MAXNAMELEN]; + char name[EBT_EXTENSION_MAXNAMELEN]; struct xt_match *match; struct xt_target *wt; void *dst = NULL; @@ -1952,7 +1960,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, switch (compat_mwt) { case EBT_COMPAT_MATCH: - match = xt_request_find_match(NFPROTO_BRIDGE, name, 0); + match = xt_request_find_match(NFPROTO_BRIDGE, name, + mwt->u.revision); if (IS_ERR(match)) return PTR_ERR(match); @@ -1971,7 +1980,8 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, break; case EBT_COMPAT_WATCHER: /* fallthrough */ case EBT_COMPAT_TARGET: - wt = xt_request_find_target(NFPROTO_BRIDGE, name, 0); + wt = xt_request_find_target(NFPROTO_BRIDGE, name, + mwt->u.revision); if (IS_ERR(wt)) return PTR_ERR(wt); off = xt_compat_target_offset(wt); @@ -2268,7 +2278,9 @@ static int compat_do_replace(struct net *net, void __user *user, xt_compat_lock(NFPROTO_BRIDGE); - xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); + ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); + if (ret < 0) + goto out_unlock; ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); if (ret < 0) goto out_unlock; |