[parisc-linux-cvs] linux grundler
Grant Grundler
grundler@parisc-linux.org
Tue, 15 Jul 2003 01:58:19 -0600
On Tue, Jul 15, 2003 at 01:36:54AM -0600, Grant Grundler wrote:
> Log message:
> 2.4.21-pa6 add IPT_SO_SET_REPLACE to sys32_setsockopt
>
> I caught this when reviewing the 2.4.20 vs 2.4.21 sparc64 syscall wrapper.
> 2.6 already has this in net/compat.c:compat_sys_setsockopt().
diff appended.
I didn't test this - have no clue really what it's supposed to do.
grant
Index: Makefile
===================================================================
RCS file: /var/cvs/linux/Makefile,v
retrieving revision 1.403
diff -u -p -r1.403 Makefile
--- Makefile 15 Jul 2003 04:35:17 -0000 1.403
+++ Makefile 15 Jul 2003 07:27:03 -0000
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 21
-EXTRAVERSION = -pa5
+EXTRAVERSION = -pa6
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
Index: arch/parisc/kernel/sys_parisc32.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/sys_parisc32.c,v
retrieving revision 1.28
diff -u -p -r1.28 sys_parisc32.c
--- arch/parisc/kernel/sys_parisc32.c 15 Jul 2003 04:35:18 -0000 1.28
+++ arch/parisc/kernel/sys_parisc32.c 15 Jul 2003 07:27:04 -0000
@@ -2298,6 +2298,82 @@ out:
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
char *optval, int optlen);
+static inline void *compat_ptr(u32 uptr)
+{
+ return (void *)(unsigned long)uptr;
+}
+
+static int do_netfilter_replace(int fd, int level, int optname,
+ char *optval, int optlen)
+{
+ struct ipt_replace32 {
+ 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;
+ __u32 counters;
+ struct ipt_entry entries[0];
+ } *repl32 = (struct ipt_replace32 *)optval;
+ struct ipt_replace *krepl;
+ struct ipt_counters *counters32;
+ __u32 origsize;
+ unsigned int kreplsize, kcountersize;
+ mm_segment_t old_fs;
+ int ret;
+
+ if (optlen < sizeof(repl32))
+ return -EINVAL;
+
+ if (copy_from_user(&origsize,
+ &repl32->size,
+ sizeof(origsize)))
+ return -EFAULT;
+
+ kreplsize = sizeof(*krepl) + origsize;
+ kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+
+ /* Hack: Causes ipchains to give correct error msg --RR */
+ if (optlen != kreplsize)
+ return -ENOPROTOOPT;
+
+ krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
+ if (krepl == NULL)
+ return -ENOMEM;
+
+ if (copy_from_user(krepl, optval, kreplsize)) {
+ kfree(krepl);
+ return -EFAULT;
+ }
+
+ counters32 = (struct ipt_counters *) compat_ptr(((struct ipt_replace32 *)krepl)->counters);
+
+ kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
+ krepl->counters = (struct ipt_counters *)kmalloc(
+ kcountersize, GFP_KERNEL);
+ if (krepl->counters == NULL) {
+ kfree(krepl);
+ return -ENOMEM;
+ }
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_setsockopt(fd, level, optname,
+ (char *)krepl, kreplsize);
+ set_fs(old_fs);
+
+ if (ret == 0 &&
+ copy_to_user(counters32, krepl->counters, kcountersize))
+ ret = -EFAULT;
+
+ kfree(krepl->counters);
+ kfree(krepl);
+
+ return ret;
+}
+
static int do_set_attach_filter(int fd, int level, int optname,
char *optval, int optlen)
{
@@ -2473,6 +2549,9 @@ err02:
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
char *optval, int optlen)
{
+ if (optname == IPT_SO_SET_REPLACE)
+ return do_netfilter_replace(fd, level, optname, optval, optlen);
+
if (optname == SO_ATTACH_FILTER)
return do_set_attach_filter(fd, level, optname, optval, optlen);
@@ -3031,6 +3110,7 @@ asmlinkage long sys32_adjtimex(struct ti
CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
CP(stbcnt);
ret = do_adjtimex(&txc);
+#undef CP
#define CP(x) t32.x = txc.x
CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
CP(status); CP(constant); CP(precision); CP(tolerance);