aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_tables.c57
1 files changed, 12 insertions, 45 deletions
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 4b10b98640ac..b9b189c26208 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1492,8 +1492,10 @@ static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
1492 return xt_compat_match_to_user(m, dstptr, size); 1492 return xt_compat_match_to_user(m, dstptr, size);
1493} 1493}
1494 1494
1495static int compat_copy_entry_to_user(struct ipt_entry *e, 1495static int
1496 void __user **dstptr, compat_uint_t *size) 1496compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1497 compat_uint_t *size, struct xt_counters *counters,
1498 unsigned int *i)
1497{ 1499{
1498 struct ipt_entry_target *t; 1500 struct ipt_entry_target *t;
1499 struct compat_ipt_entry __user *ce; 1501 struct compat_ipt_entry __user *ce;
@@ -1507,6 +1509,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
1507 if (copy_to_user(ce, e, sizeof(struct ipt_entry))) 1509 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1508 goto out; 1510 goto out;
1509 1511
1512 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1513 goto out;
1514
1510 *dstptr += sizeof(struct compat_ipt_entry); 1515 *dstptr += sizeof(struct compat_ipt_entry);
1511 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size); 1516 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
1512 target_offset = e->target_offset - (origsize - *size); 1517 target_offset = e->target_offset - (origsize - *size);
@@ -1522,6 +1527,8 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
1522 goto out; 1527 goto out;
1523 if (put_user(next_offset, &ce->next_offset)) 1528 if (put_user(next_offset, &ce->next_offset))
1524 goto out; 1529 goto out;
1530
1531 (*i)++;
1525 return 0; 1532 return 0;
1526out: 1533out:
1527 return ret; 1534 return ret;
@@ -1937,14 +1944,13 @@ struct compat_ipt_get_entries
1937static int compat_copy_entries_to_user(unsigned int total_size, 1944static int compat_copy_entries_to_user(unsigned int total_size,
1938 struct xt_table *table, void __user *userptr) 1945 struct xt_table *table, void __user *userptr)
1939{ 1946{
1940 unsigned int off, num;
1941 struct compat_ipt_entry e;
1942 struct xt_counters *counters; 1947 struct xt_counters *counters;
1943 struct xt_table_info *private = table->private; 1948 struct xt_table_info *private = table->private;
1944 void __user *pos; 1949 void __user *pos;
1945 unsigned int size; 1950 unsigned int size;
1946 int ret = 0; 1951 int ret = 0;
1947 void *loc_cpu_entry; 1952 void *loc_cpu_entry;
1953 unsigned int i = 0;
1948 1954
1949 counters = alloc_counters(table); 1955 counters = alloc_counters(table);
1950 if (IS_ERR(counters)) 1956 if (IS_ERR(counters))
@@ -1958,48 +1964,9 @@ static int compat_copy_entries_to_user(unsigned int total_size,
1958 pos = userptr; 1964 pos = userptr;
1959 size = total_size; 1965 size = total_size;
1960 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, 1966 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1961 compat_copy_entry_to_user, &pos, &size); 1967 compat_copy_entry_to_user,
1962 if (ret) 1968 &pos, &size, counters, &i);
1963 goto free_counters;
1964
1965 /* ... then go back and fix counters and names */
1966 for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
1967 unsigned int i;
1968 struct ipt_entry_match m;
1969 struct ipt_entry_target t;
1970 1969
1971 ret = -EFAULT;
1972 if (copy_from_user(&e, userptr + off,
1973 sizeof(struct compat_ipt_entry)))
1974 goto free_counters;
1975 if (copy_to_user(userptr + off +
1976 offsetof(struct compat_ipt_entry, counters),
1977 &counters[num], sizeof(counters[num])))
1978 goto free_counters;
1979
1980 for (i = sizeof(struct compat_ipt_entry);
1981 i < e.target_offset; i += m.u.match_size) {
1982 if (copy_from_user(&m, userptr + off + i,
1983 sizeof(struct ipt_entry_match)))
1984 goto free_counters;
1985 if (copy_to_user(userptr + off + i +
1986 offsetof(struct ipt_entry_match, u.user.name),
1987 m.u.kernel.match->name,
1988 strlen(m.u.kernel.match->name) + 1))
1989 goto free_counters;
1990 }
1991
1992 if (copy_from_user(&t, userptr + off + e.target_offset,
1993 sizeof(struct ipt_entry_target)))
1994 goto free_counters;
1995 if (copy_to_user(userptr + off + e.target_offset +
1996 offsetof(struct ipt_entry_target, u.user.name),
1997 t.u.kernel.target->name,
1998 strlen(t.u.kernel.target->name) + 1))
1999 goto free_counters;
2000 }
2001 ret = 0;
2002free_counters:
2003 vfree(counters); 1970 vfree(counters);
2004 return ret; 1971 return ret;
2005} 1972}