diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 136ed7d4bd7320fc679e21720c5cfd33fb072f52..e79c0fbd9e89f793435306e5d8313fa9bf843fe4 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -393,15 +393,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
 	return 0;
 }
 
-/*
- * this one is very careful, as it is the first function
- * to parse the userspace data
- */
 static inline int
-ebt_check_entry_size_and_hooks(struct ebt_entry *e,
+__ebt_verify_pointers(struct ebt_entry *e,
    struct ebt_table_info *newinfo, char *base, char *limit,
-   struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
-   unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
+   struct ebt_entries **hook_entries,
+   unsigned int valid_hooks)
 {
 	unsigned int offset = (char *)e - newinfo->entries;
 	size_t left = (limit - base) - offset;
@@ -416,8 +412,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 		if ((char *)hook_entries[i] == base + offset)
 			break;
 	}
-	/* beginning of a new chain
-	   if i == NF_BR_NUMHOOKS it must be a user defined chain */
 	if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
 		if (e->bitmask != 0) {
 			/* we make userspace set this right,
@@ -426,6 +420,45 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 			         "in distinguisher\n");
 			return -EINVAL;
 		}
+		if (left < sizeof(struct ebt_entries))
+			goto Esmall;
+		if (i != NF_BR_NUMHOOKS)
+			newinfo->hook_entry[i] = (struct ebt_entries *)e;
+		return 0;
+	}
+	if (left < sizeof(struct ebt_entry))
+		goto Esmall;
+	if (left < e->next_offset)
+		goto Esmall;
+	return 0;
+
+Esmall:
+	BUGPRINT("entries_size too small\n");
+	return -EINVAL;
+}
+
+/*
+ * this one is very careful, as it is the first function
+ * to parse the userspace data
+ */
+static inline int
+ebt_check_entry_size_and_hooks(struct ebt_entry *e,
+   struct ebt_table_info *newinfo, char *base,
+   struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
+   unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
+{
+	unsigned int offset = (char *)e - newinfo->entries;
+	int i;
+
+	for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+		if ((valid_hooks & (1 << i)) == 0)
+			continue;
+		if ((char *)hook_entries[i] == base + offset)
+			break;
+	}
+	/* beginning of a new chain
+	   if i == NF_BR_NUMHOOKS it must be a user defined chain */
+	if (i != NF_BR_NUMHOOKS || !e->bitmask) {
 		/* this checks if the previous chain has as many entries
 		   as it said it has */
 		if (*n != *cnt) {
@@ -433,9 +466,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 		                 "in the chain\n");
 			return -EINVAL;
 		}
-		/* before we look at the struct, be sure it is not too big */
-		if (left < sizeof(struct ebt_entries))
-			goto Esmall;
 		if (((struct ebt_entries *)e)->policy != EBT_DROP &&
 		   ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
 			/* only RETURN from udc */
@@ -447,8 +477,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 		}
 		if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
 			(*udc_cnt)++;
-		else
-			newinfo->hook_entry[i] = (struct ebt_entries *)e;
 		if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
 			BUGPRINT("counter_offset != totalcnt");
 			return -EINVAL;
@@ -458,8 +486,6 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 		return 0;
 	}
 	/* a plain old entry, heh */
-	if (left < sizeof(struct ebt_entry))
-		goto Esmall;
 	if (sizeof(struct ebt_entry) > e->watchers_offset ||
 	   e->watchers_offset > e->target_offset ||
 	   e->target_offset >= e->next_offset) {
@@ -471,16 +497,9 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
 		BUGPRINT("target size too small\n");
 		return -EINVAL;
 	}
-	if (left < e->next_offset)
-		goto Esmall;
-
 	(*cnt)++;
 	(*totalcnt)++;
 	return 0;
-
-Esmall:
-	BUGPRINT("entries_size too small\n");
-	return -EINVAL;
 }
 
 struct ebt_cl_stack
@@ -776,6 +795,12 @@ static int translate_table(struct ebt_replace *repl,
 	newinfo->entries_size = repl->entries_size;
 	newinfo->nentries = repl->nentries;
 
+	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
+	   __ebt_verify_pointers, newinfo, repl->entries,
+	   repl->entries + repl->entries_size, repl->hook_entry, repl->valid_hooks);
+	if (ret != 0)
+		return ret;
+
 	/* do some early checkings and initialize some things */
 	i = 0; /* holds the expected nr. of entries for the chain */
 	j = 0; /* holds the up to now counted entries for the chain */
@@ -784,7 +809,7 @@ static int translate_table(struct ebt_replace *repl,
 	udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
 	ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 	   ebt_check_entry_size_and_hooks, newinfo, repl->entries,
-	   repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
+	   repl->hook_entry, &i, &j, &k,
 	   &udc_cnt, repl->valid_hooks);
 
 	if (ret != 0)