Home » Mailing lists » Devel » [PATCH 1/2] iptables 32bit compat layer
[PATCH 1/2] iptables 32bit compat layer [message #1688] |
Mon, 20 February 2006 08:10 ![Go to next message Go to previous message](/theme/ovz3/images/down.png) |
Mishin Dmitry
Messages: 112 Registered: February 2006
|
Senior Member |
|
|
Hello,
This patch set extends current iptables compatibility layer in order to get
32bit iptables to work on 64bit kernel. Current layer is insufficient
due to alignment checks both in kernel and user space tools.
This patch introduces base compatibility interface for other ip_tables modules
--
Thanks,
Dmitry.
--- ./include/linux/netfilter/x_tables.h.iptcompat 2006-02-15 16:16:02.000000000 +0300
+++ ./include/linux/netfilter/x_tables.h 2006-02-15 18:53:09.000000000 +0300
@@ -80,12 +80,19 @@ struct xt_counters_info
#ifdef __KERNEL__
+#include <linux/config.h>
#include <linux/netdevice.h>
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
+#ifdef CONFIG_COMPAT
+#define COMPAT_TO_USER 1
+#define COMPAT_FROM_USER -1
+#define COMPAT_CALC_SIZE 0
+#endif
+
struct xt_match
{
struct list_head list;
@@ -118,6 +125,10 @@ struct xt_match
/* Called when entry of this type deleted. */
void (*destroy)(void *matchinfo, unsigned int matchinfosize);
+#ifdef CONFIG_COMPAT
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *match, void **dstptr, int *size, int convert);
+#endif
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
};
@@ -154,6 +165,10 @@ struct xt_target
/* Called when entry of this type deleted. */
void (*destroy)(void *targinfo, unsigned int targinfosize);
+#ifdef CONFIG_COMPAT
+ /* Called when userspace align differs from kernel space one */
+ int (*compat)(void *target, void **dstptr, int *size, int convert);
+#endif
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
};
@@ -233,6 +248,34 @@ extern void xt_proto_fini(int af);
extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
extern void xt_free_table_info(struct xt_table_info *info);
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+/* FIXME: this works only on 32 bit tasks
+ * need to change whole approach in order to calculate align as function of
+ * current task alignment */
+
+struct compat_xt_counters
+{
+ u_int32_t cnt[4];
+};
+
+struct compat_xt_counters_info
+{
+ char name[XT_TABLE_MAXNAMELEN];
+ compat_uint_t num_counters;
+ struct compat_xt_counters counters[0];
+};
+
+#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \
+ & ~(__alignof__(struct compat_xt_counters)-1))
+
+extern int ipt_match_align_compat(void *match, void **dstptr,
+ int *size, int off, int convert);
+extern int ipt_target_align_compat(void *target, void **dstptr,
+ int *size, int off, int convert);
+
+#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* _X_TABLES_H */
--- ./include/linux/netfilter_ipv4/ip_tables.h.iptcompat 2006-02-15 16:06:41.000000000 +0300
+++ ./include/linux/netfilter_ipv4/ip_tables.h 2006-02-15 16:37:12.000000000 +0300
@@ -16,6 +16,7 @@
#define _IPTABLES_H
#ifdef __KERNEL__
+#include <linux/config.h>
#include <linux/if.h>
#include <linux/types.h>
#include <linux/in.h>
@@ -364,5 +365,62 @@ extern unsigned int ipt_do_table(struct
void *userdata);
#define IPT_ALIGN(s) XT_ALIGN(s)
+
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_ipt_getinfo
+{
+ char name[IPT_TABLE_MAXNAMELEN];
+ compat_uint_t valid_hooks;
+ compat_uint_t hook_entry[NF_IP_NUMHOOKS];
+ compat_uint_t underflow[NF_IP_NUMHOOKS];
+ compat_uint_t num_entries;
+ compat_uint_t size;
+};
+
+struct compat_ipt_entry
+{
+ struct ipt_ip ip;
+ 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];
+};
+
+struct compat_ipt_entry_match
+{
+ union {
+ struct {
+ u_int16_t match_size;
+ char name[IPT_FUNCTION_MAXNAMELEN];
+ } user;
+ u_int16_t match_size;
+ } u;
+ unsigned char data[0];
+};
+
+struct compat_ipt_entry_target
+{
+ union {
+ struct {
+ u_int16_t target_size;
+ char name[IPT_FUNCTION_MAXNAMELEN];
+ } user;
+ u_int16_t target_size;
+ } u;
+ unsigned char data[0];
+};
+
+#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)
+
+extern int ipt_match_align_compat(void *match, void **dstptr,
+ int *size, int off, int convert);
+extern int ipt_target_align_compat(void *target, void **dstptr,
+ int *size, int off, int convert);
+
+#endif /* CONFIG_COMPAT */
#endif /*__KERNEL__*/
#endif /* _IPTABLES_H */
--- ./include/net/compat.h.iptcompat 2006-01-03 06:21:10.000000000 +0300
+++ ./include/net/compat.h 2006-02-15 18:45:49.000000000 +0300
@@ -23,6 +23,14 @@ struct compat_cmsghdr {
compat_int_t cmsg_type;
};
+#if defined(CONFIG_X86_64)
+#define is_current_32bits() (current_thread_info()->flags & _TIF_IA32)
+#elif defined(CONFIG_IA64)
+#define is_current_32bits() (IS_IA32_PROCESS(ia64_task_regs(current)))
+#else
+#define is_current_32bits() 0
+#endif
+
#else /* defined(CONFIG_COMPAT) */
#define compat_msghdr msghdr /* to avoid compiler warnings */
#endif /* defined(CONFIG_COMPAT) */
--- ./net/compat.c.iptcompat 2006-01-03 06:21:10.000000000 +0300
+++ ./net/compat.c 2006-02-15 16:38:45.000000000 +0300
@@ -308,107 +308,6 @@ void scm_detach_fds_compat(struct msghdr
}
/*
- * 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_IP_NUMHOOKS];
- u32 underflow[NF_IP_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_IP_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.
*/
struct compat_sock_fprog {
@@ -460,10 +359,6 @@ static int do_set_sock_timeout(int fd, i
asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
char __user *optval, int optlen)
{
- /* SO_SET_REPLACE seems to be the same in all levels */
- if (optname == IPT_SO_SET_REPLACE)
- return do_netfilter_replace(fd, level, optname,
- optval, optlen);
if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
return do_set_attach_filter(fd, level, optname,
optval, optlen);
--- ./net/ipv4/netfilter/ip_tables.c.iptcompat 2006-02-15 16:06:42.000000000 +0300
+++ ./net/ipv4/netfilter/ip_tables.c 2006-02-17 19:38:05.000000000 +0300
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/icmp.h>
#include <net/ip.h>
+#include <net/compat.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/proc_fs.h>
@@ -480,7 +481,7 @@ standard_check(const struct ipt_entry_ta
if (t->u.target_size
!= IPT_ALIGN(sizeof(struct ipt_standard_target))) {
duprintf("standard_check: target size %u != %u\n",
- t->u.target_size,
+ t->u.target_size, (unsigned int)
IPT_ALIGN(sizeof(struct ipt_standard_target)));
return 0;
}
@@ -790,17 +791,11 @@ get_counters(const struct xt_table_info
}
}
-static int
-copy_entries_to_user(unsigned int total_size,
- struct ipt_table *table,
- void __user *userptr)
+static inline struct xt_counters * alloc_counters(struct ipt_table *table)
{
- unsigned int off, num, countersize;
- struct ipt_entry *e;
+ unsigned int countersize;
struct xt_counters *counters;
struct xt_table_info
...
|
|
|
Goto Forum:
Current Time: Thu Aug 15 06:29:20 GMT 2024
Total time taken to generate the page: 0.02764 seconds
|