浏览代码

netfilter: xtables: ignore unassigned hooks in check_entry_size_and_hooks

The "hook_entry" and "underflow" array contains values even for hooks
not provided, such as PREROUTING in conjunction with the "filter"
table. Usually, the values point to whatever the next rule is. For
the upcoming unconditionality and underflow checking patches however,
we must not inspect that arbitrary rule.

Skipping unassigned hooks seems like a good idea, also because
newinfo->hook_entry and newinfo->underflow will then continue to have
the poison value for detecting abnormalities.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Jan Engelhardt 16 年之前
父节点
当前提交
a7d51738e7
共有 3 个文件被更改,包括 12 次插入3 次删除
  1. 4 1
      net/ipv4/netfilter/arp_tables.c
  2. 4 1
      net/ipv4/netfilter/ip_tables.c
  3. 4 1
      net/ipv6/netfilter/ip6_tables.c

+ 4 - 1
net/ipv4/netfilter/arp_tables.c

@@ -539,6 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
 					     unsigned char *limit,
 					     unsigned char *limit,
 					     const unsigned int *hook_entries,
 					     const unsigned int *hook_entries,
 					     const unsigned int *underflows,
 					     const unsigned int *underflows,
+					     unsigned int valid_hooks,
 					     unsigned int *i)
 					     unsigned int *i)
 {
 {
 	unsigned int h;
 	unsigned int h;
@@ -558,6 +559,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
 
 
 	/* Check hooks & underflows */
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
 	for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
+		if (!(valid_hooks & (1 << h)))
+			continue;
 		if ((unsigned char *)e - base == hook_entries[h])
 		if ((unsigned char *)e - base == hook_entries[h])
 			newinfo->hook_entry[h] = hook_entries[h];
 			newinfo->hook_entry[h] = hook_entries[h];
 		if ((unsigned char *)e - base == underflows[h])
 		if ((unsigned char *)e - base == underflows[h])
@@ -626,7 +629,7 @@ static int translate_table(const char *name,
 				 newinfo,
 				 newinfo,
 				 entry0,
 				 entry0,
 				 entry0 + size,
 				 entry0 + size,
-				 hook_entries, underflows, &i);
+				 hook_entries, underflows, valid_hooks, &i);
 	duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
 	duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
 	if (ret != 0)
 	if (ret != 0)
 		return ret;
 		return ret;

+ 4 - 1
net/ipv4/netfilter/ip_tables.c

@@ -714,6 +714,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
 			   unsigned char *limit,
 			   unsigned char *limit,
 			   const unsigned int *hook_entries,
 			   const unsigned int *hook_entries,
 			   const unsigned int *underflows,
 			   const unsigned int *underflows,
+			   unsigned int valid_hooks,
 			   unsigned int *i)
 			   unsigned int *i)
 {
 {
 	unsigned int h;
 	unsigned int h;
@@ -733,6 +734,8 @@ check_entry_size_and_hooks(struct ipt_entry *e,
 
 
 	/* Check hooks & underflows */
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
+		if (!(valid_hooks & (1 << h)))
+			continue;
 		if ((unsigned char *)e - base == hook_entries[h])
 		if ((unsigned char *)e - base == hook_entries[h])
 			newinfo->hook_entry[h] = hook_entries[h];
 			newinfo->hook_entry[h] = hook_entries[h];
 		if ((unsigned char *)e - base == underflows[h])
 		if ((unsigned char *)e - base == underflows[h])
@@ -804,7 +807,7 @@ translate_table(const char *name,
 				newinfo,
 				newinfo,
 				entry0,
 				entry0,
 				entry0 + size,
 				entry0 + size,
-				hook_entries, underflows, &i);
+				hook_entries, underflows, valid_hooks, &i);
 	if (ret != 0)
 	if (ret != 0)
 		return ret;
 		return ret;
 
 

+ 4 - 1
net/ipv6/netfilter/ip6_tables.c

@@ -747,6 +747,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
 			   unsigned char *limit,
 			   unsigned char *limit,
 			   const unsigned int *hook_entries,
 			   const unsigned int *hook_entries,
 			   const unsigned int *underflows,
 			   const unsigned int *underflows,
+			   unsigned int valid_hooks,
 			   unsigned int *i)
 			   unsigned int *i)
 {
 {
 	unsigned int h;
 	unsigned int h;
@@ -766,6 +767,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
 
 
 	/* Check hooks & underflows */
 	/* Check hooks & underflows */
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
+		if (!(valid_hooks & (1 << h)))
+			continue;
 		if ((unsigned char *)e - base == hook_entries[h])
 		if ((unsigned char *)e - base == hook_entries[h])
 			newinfo->hook_entry[h] = hook_entries[h];
 			newinfo->hook_entry[h] = hook_entries[h];
 		if ((unsigned char *)e - base == underflows[h])
 		if ((unsigned char *)e - base == underflows[h])
@@ -837,7 +840,7 @@ translate_table(const char *name,
 				newinfo,
 				newinfo,
 				entry0,
 				entry0,
 				entry0 + size,
 				entry0 + size,
-				hook_entries, underflows, &i);
+				hook_entries, underflows, valid_hooks, &i);
 	if (ret != 0)
 	if (ret != 0)
 		return ret;
 		return ret;