Loading include/linux/netfilter_ipv6/ip6_tables.h +35 −0 Original line number Diff line number Diff line Loading @@ -326,5 +326,40 @@ extern int ip6_masked_addrcmp(const struct in6_addr *addr1, #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) #ifdef CONFIG_COMPAT #include <net/compat.h> struct compat_ip6t_entry { struct ip6t_ip6 ipv6; compat_uint_t nfcache; u_int16_t target_offset; u_int16_t next_offset; compat_uint_t comefrom; struct compat_xt_counters counters; unsigned char elems[0]; }; static inline struct ip6t_entry_target * compat_ip6t_get_target(struct compat_ip6t_entry *e) { return (void *)e + e->target_offset; } #define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s) /* fn returns 0 to continue iteration */ #define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args) /* fn returns 0 to continue iteration */ #define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args) #define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \ fn, ## args) #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IP6_TABLES_H */ net/compat.c +0 −106 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <linux/syscalls.h> #include <linux/filter.h> #include <linux/compat.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/security.h> #include <net/scm.h> Loading Loading @@ -316,107 +315,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) __scm_destroy(scm); } /* * For now, we assume that the compatibility and native version * of struct ipt_entry are the same - sfr. FIXME */ struct compat_ipt_replace { char name[IPT_TABLE_MAXNAMELEN]; u32 valid_hooks; u32 num_entries; u32 size; u32 hook_entry[NF_INET_NUMHOOKS]; u32 underflow[NF_INET_NUMHOOKS]; u32 num_counters; compat_uptr_t counters; /* struct ipt_counters * */ struct ipt_entry entries[0]; }; static int do_netfilter_replace(int fd, int level, int optname, char __user *optval, int optlen) { struct compat_ipt_replace __user *urepl; struct ipt_replace __user *repl_nat; char name[IPT_TABLE_MAXNAMELEN]; u32 origsize, tmp32, num_counters; unsigned int repl_nat_size; int ret; int i; compat_uptr_t ucntrs; urepl = (struct compat_ipt_replace __user *)optval; if (get_user(origsize, &urepl->size)) return -EFAULT; /* Hack: Causes ipchains to give correct error msg --RR */ if (optlen != sizeof(*urepl) + origsize) return -ENOPROTOOPT; /* XXX Assumes that size of ipt_entry is the same both in * native and compat environments. */ repl_nat_size = sizeof(*repl_nat) + origsize; repl_nat = compat_alloc_user_space(repl_nat_size); ret = -EFAULT; if (put_user(origsize, &repl_nat->size)) goto out; if (!access_ok(VERIFY_READ, urepl, optlen) || !access_ok(VERIFY_WRITE, repl_nat, optlen)) goto out; if (__copy_from_user(name, urepl->name, sizeof(urepl->name)) || __copy_to_user(repl_nat->name, name, sizeof(repl_nat->name))) goto out; if (__get_user(tmp32, &urepl->valid_hooks) || __put_user(tmp32, &repl_nat->valid_hooks)) goto out; if (__get_user(tmp32, &urepl->num_entries) || __put_user(tmp32, &repl_nat->num_entries)) goto out; if (__get_user(num_counters, &urepl->num_counters) || __put_user(num_counters, &repl_nat->num_counters)) goto out; if (__get_user(ucntrs, &urepl->counters) || __put_user(compat_ptr(ucntrs), &repl_nat->counters)) goto out; if (__copy_in_user(&repl_nat->entries[0], &urepl->entries[0], origsize)) goto out; for (i = 0; i < NF_INET_NUMHOOKS; i++) { if (__get_user(tmp32, &urepl->hook_entry[i]) || __put_user(tmp32, &repl_nat->hook_entry[i]) || __get_user(tmp32, &urepl->underflow[i]) || __put_user(tmp32, &repl_nat->underflow[i])) goto out; } /* * Since struct ipt_counters just contains two u_int64_t members * we can just do the access_ok check here and pass the (converted) * pointer into the standard syscall. We hope that the pointer is * not misaligned ... */ if (!access_ok(VERIFY_WRITE, compat_ptr(ucntrs), num_counters * sizeof(struct ipt_counters))) goto out; ret = sys_setsockopt(fd, level, optname, (char __user *)repl_nat, repl_nat_size); out: return ret; } /* * A struct sock_filter is architecture independent. */ Loading Loading @@ -485,10 +383,6 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, int err; struct socket *sock; if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); if (optlen < 0) return -EINVAL; Loading Loading
include/linux/netfilter_ipv6/ip6_tables.h +35 −0 Original line number Diff line number Diff line Loading @@ -326,5 +326,40 @@ extern int ip6_masked_addrcmp(const struct in6_addr *addr1, #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) #ifdef CONFIG_COMPAT #include <net/compat.h> struct compat_ip6t_entry { struct ip6t_ip6 ipv6; compat_uint_t nfcache; u_int16_t target_offset; u_int16_t next_offset; compat_uint_t comefrom; struct compat_xt_counters counters; unsigned char elems[0]; }; static inline struct ip6t_entry_target * compat_ip6t_get_target(struct compat_ip6t_entry *e) { return (void *)e + e->target_offset; } #define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s) /* fn returns 0 to continue iteration */ #define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args) /* fn returns 0 to continue iteration */ #define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args) #define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \ fn, ## args) #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IP6_TABLES_H */
net/compat.c +0 −106 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ #include <linux/syscalls.h> #include <linux/filter.h> #include <linux/compat.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/security.h> #include <net/scm.h> Loading Loading @@ -316,107 +315,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) __scm_destroy(scm); } /* * For now, we assume that the compatibility and native version * of struct ipt_entry are the same - sfr. FIXME */ struct compat_ipt_replace { char name[IPT_TABLE_MAXNAMELEN]; u32 valid_hooks; u32 num_entries; u32 size; u32 hook_entry[NF_INET_NUMHOOKS]; u32 underflow[NF_INET_NUMHOOKS]; u32 num_counters; compat_uptr_t counters; /* struct ipt_counters * */ struct ipt_entry entries[0]; }; static int do_netfilter_replace(int fd, int level, int optname, char __user *optval, int optlen) { struct compat_ipt_replace __user *urepl; struct ipt_replace __user *repl_nat; char name[IPT_TABLE_MAXNAMELEN]; u32 origsize, tmp32, num_counters; unsigned int repl_nat_size; int ret; int i; compat_uptr_t ucntrs; urepl = (struct compat_ipt_replace __user *)optval; if (get_user(origsize, &urepl->size)) return -EFAULT; /* Hack: Causes ipchains to give correct error msg --RR */ if (optlen != sizeof(*urepl) + origsize) return -ENOPROTOOPT; /* XXX Assumes that size of ipt_entry is the same both in * native and compat environments. */ repl_nat_size = sizeof(*repl_nat) + origsize; repl_nat = compat_alloc_user_space(repl_nat_size); ret = -EFAULT; if (put_user(origsize, &repl_nat->size)) goto out; if (!access_ok(VERIFY_READ, urepl, optlen) || !access_ok(VERIFY_WRITE, repl_nat, optlen)) goto out; if (__copy_from_user(name, urepl->name, sizeof(urepl->name)) || __copy_to_user(repl_nat->name, name, sizeof(repl_nat->name))) goto out; if (__get_user(tmp32, &urepl->valid_hooks) || __put_user(tmp32, &repl_nat->valid_hooks)) goto out; if (__get_user(tmp32, &urepl->num_entries) || __put_user(tmp32, &repl_nat->num_entries)) goto out; if (__get_user(num_counters, &urepl->num_counters) || __put_user(num_counters, &repl_nat->num_counters)) goto out; if (__get_user(ucntrs, &urepl->counters) || __put_user(compat_ptr(ucntrs), &repl_nat->counters)) goto out; if (__copy_in_user(&repl_nat->entries[0], &urepl->entries[0], origsize)) goto out; for (i = 0; i < NF_INET_NUMHOOKS; i++) { if (__get_user(tmp32, &urepl->hook_entry[i]) || __put_user(tmp32, &repl_nat->hook_entry[i]) || __get_user(tmp32, &urepl->underflow[i]) || __put_user(tmp32, &repl_nat->underflow[i])) goto out; } /* * Since struct ipt_counters just contains two u_int64_t members * we can just do the access_ok check here and pass the (converted) * pointer into the standard syscall. We hope that the pointer is * not misaligned ... */ if (!access_ok(VERIFY_WRITE, compat_ptr(ucntrs), num_counters * sizeof(struct ipt_counters))) goto out; ret = sys_setsockopt(fd, level, optname, (char __user *)repl_nat, repl_nat_size); out: return ret; } /* * A struct sock_filter is architecture independent. */ Loading Loading @@ -485,10 +383,6 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, int err; struct socket *sock; if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); if (optlen < 0) return -EINVAL; Loading