diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 681316e40c6f..6fcc0d5bc27f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1082,17 +1082,29 @@ static int get_info(void __user *user, int *len) | |||
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | static int | 1084 | static int |
1085 | get_entries(const struct ip6t_get_entries *entries, | 1085 | get_entries(struct ip6t_get_entries __user *uptr, int *len) |
1086 | struct ip6t_get_entries __user *uptr) | ||
1087 | { | 1086 | { |
1088 | int ret; | 1087 | int ret; |
1088 | struct ip6t_get_entries get; | ||
1089 | struct xt_table *t; | 1089 | struct xt_table *t; |
1090 | 1090 | ||
1091 | t = xt_find_table_lock(AF_INET6, entries->name); | 1091 | if (*len < sizeof(get)) { |
1092 | duprintf("get_entries: %u < %u\n", *len, sizeof(get)); | ||
1093 | return -EINVAL; | ||
1094 | } | ||
1095 | if (copy_from_user(&get, uptr, sizeof(get)) != 0) | ||
1096 | return -EFAULT; | ||
1097 | if (*len != sizeof(struct ip6t_get_entries) + get.size) { | ||
1098 | duprintf("get_entries: %u != %u\n", *len, | ||
1099 | sizeof(struct ip6t_get_entries) + get.size); | ||
1100 | return -EINVAL; | ||
1101 | } | ||
1102 | |||
1103 | t = xt_find_table_lock(AF_INET6, get.name); | ||
1092 | if (t && !IS_ERR(t)) { | 1104 | if (t && !IS_ERR(t)) { |
1093 | struct xt_table_info *private = t->private; | 1105 | struct xt_table_info *private = t->private; |
1094 | duprintf("t->private->number = %u\n", private->number); | 1106 | duprintf("t->private->number = %u\n", private->number); |
1095 | if (entries->size == private->size) | 1107 | if (get.size == private->size) |
1096 | ret = copy_entries_to_user(private->size, | 1108 | ret = copy_entries_to_user(private->size, |
1097 | t, uptr->entrytable); | 1109 | t, uptr->entrytable); |
1098 | else { | 1110 | else { |
@@ -1322,22 +1334,9 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1322 | ret = get_info(user, len); | 1334 | ret = get_info(user, len); |
1323 | break; | 1335 | break; |
1324 | 1336 | ||
1325 | case IP6T_SO_GET_ENTRIES: { | 1337 | case IP6T_SO_GET_ENTRIES: |
1326 | struct ip6t_get_entries get; | 1338 | ret = get_entries(user, len); |
1327 | |||
1328 | if (*len < sizeof(get)) { | ||
1329 | duprintf("get_entries: %u < %u\n", *len, sizeof(get)); | ||
1330 | ret = -EINVAL; | ||
1331 | } else if (copy_from_user(&get, user, sizeof(get)) != 0) { | ||
1332 | ret = -EFAULT; | ||
1333 | } else if (*len != sizeof(struct ip6t_get_entries) + get.size) { | ||
1334 | duprintf("get_entries: %u != %u\n", *len, | ||
1335 | sizeof(struct ip6t_get_entries) + get.size); | ||
1336 | ret = -EINVAL; | ||
1337 | } else | ||
1338 | ret = get_entries(&get, user); | ||
1339 | break; | 1339 | break; |
1340 | } | ||
1341 | 1340 | ||
1342 | case IP6T_SO_GET_REVISION_MATCH: | 1341 | case IP6T_SO_GET_REVISION_MATCH: |
1343 | case IP6T_SO_GET_REVISION_TARGET: { | 1342 | case IP6T_SO_GET_REVISION_TARGET: { |