diff options
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 33e8d53eebf8..029df76b9707 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -825,23 +825,35 @@ static int get_info(void __user *user, int *len) | |||
825 | return ret; | 825 | return ret; |
826 | } | 826 | } |
827 | 827 | ||
828 | static int get_entries(const struct arpt_get_entries *entries, | 828 | static int get_entries(struct arpt_get_entries __user *uptr, int *len) |
829 | struct arpt_get_entries __user *uptr) | ||
830 | { | 829 | { |
831 | int ret; | 830 | int ret; |
831 | struct arpt_get_entries get; | ||
832 | struct arpt_table *t; | 832 | struct arpt_table *t; |
833 | 833 | ||
834 | t = xt_find_table_lock(NF_ARP, entries->name); | 834 | if (*len < sizeof(get)) { |
835 | duprintf("get_entries: %u < %Zu\n", *len, sizeof(get)); | ||
836 | return -EINVAL; | ||
837 | } | ||
838 | if (copy_from_user(&get, uptr, sizeof(get)) != 0) | ||
839 | return -EFAULT; | ||
840 | if (*len != sizeof(struct arpt_get_entries) + get.size) { | ||
841 | duprintf("get_entries: %u != %Zu\n", *len, | ||
842 | sizeof(struct arpt_get_entries) + get.size); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | t = xt_find_table_lock(NF_ARP, get.name); | ||
835 | if (t && !IS_ERR(t)) { | 847 | if (t && !IS_ERR(t)) { |
836 | struct xt_table_info *private = t->private; | 848 | struct xt_table_info *private = t->private; |
837 | duprintf("t->private->number = %u\n", | 849 | duprintf("t->private->number = %u\n", |
838 | private->number); | 850 | private->number); |
839 | if (entries->size == private->size) | 851 | if (get.size == private->size) |
840 | ret = copy_entries_to_user(private->size, | 852 | ret = copy_entries_to_user(private->size, |
841 | t, uptr->entrytable); | 853 | t, uptr->entrytable); |
842 | else { | 854 | else { |
843 | duprintf("get_entries: I've got %u not %u!\n", | 855 | duprintf("get_entries: I've got %u not %u!\n", |
844 | private->size, entries->size); | 856 | private->size, get.size); |
845 | ret = -EINVAL; | 857 | ret = -EINVAL; |
846 | } | 858 | } |
847 | module_put(t->me); | 859 | module_put(t->me); |
@@ -1055,22 +1067,9 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1055 | ret = get_info(user, len); | 1067 | ret = get_info(user, len); |
1056 | break; | 1068 | break; |
1057 | 1069 | ||
1058 | case ARPT_SO_GET_ENTRIES: { | 1070 | case ARPT_SO_GET_ENTRIES: |
1059 | struct arpt_get_entries get; | 1071 | ret = get_entries(user, len); |
1060 | |||
1061 | if (*len < sizeof(get)) { | ||
1062 | duprintf("get_entries: %u < %Zu\n", *len, sizeof(get)); | ||
1063 | ret = -EINVAL; | ||
1064 | } else if (copy_from_user(&get, user, sizeof(get)) != 0) { | ||
1065 | ret = -EFAULT; | ||
1066 | } else if (*len != sizeof(struct arpt_get_entries) + get.size) { | ||
1067 | duprintf("get_entries: %u != %Zu\n", *len, | ||
1068 | sizeof(struct arpt_get_entries) + get.size); | ||
1069 | ret = -EINVAL; | ||
1070 | } else | ||
1071 | ret = get_entries(&get, user); | ||
1072 | break; | 1072 | break; |
1073 | } | ||
1074 | 1073 | ||
1075 | case ARPT_SO_GET_REVISION_TARGET: { | 1074 | case ARPT_SO_GET_REVISION_TARGET: { |
1076 | struct xt_get_revision rev; | 1075 | struct xt_get_revision rev; |