From 04f7d02390659f6984f13f6c9e6a2657d9bf55d6 Mon Sep 17 00:00:00 2001 From: Maximilian Attems Date: Fri, 16 Apr 2010 14:48:56 +0000 Subject: [PATCH] update to latest openvz fixing bugs for 32bit containers and netfilter. svn path=/dists/sid/linux-2.6/; revision=15514 --- debian/changelog | 1 + .../patches/features/all/openvz/openvz.patch | 1804 ++++++++++++++++- 2 files changed, 1708 insertions(+), 97 deletions(-) diff --git a/debian/changelog b/debian/changelog index b9e833944..accff5b44 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,6 +20,7 @@ linux-2.6 (2.6.32-12) UNRELEASED; urgency=low [ maximilian attems] * Ignore ABI breakage due to libata switch. * [ia64] Built in fbcon. + * Update openvz patch to 6b5607eeec54. (closes: #574598) [ dann frazier ] * Add DRBD backport diff --git a/debian/patches/features/all/openvz/openvz.patch b/debian/patches/features/all/openvz/openvz.patch index e1d764101..4aaca1c39 100644 --- a/debian/patches/features/all/openvz/openvz.patch +++ b/debian/patches/features/all/openvz/openvz.patch @@ -1,3 +1,188 @@ +commit 6b5607eeec54fcef60c25fa7a72bc30f69446933 +Author: Pavel Emelyanov +Date: Fri Apr 16 12:34:01 2010 +0400 + + timers: Don't take task from the pid field of timer + + http://bugzilla.openvz.org/show_bug.cgi?id=1461 + + Signed-off-by: Pavel Emelyanov + +commit 8893da4d5000630819ce4f5edf5bb71c8f65c01c +Author: Pavel Emelyanov +Date: Thu Apr 15 17:25:09 2010 +0400 + + netfilter: Add headers missed by the previous commit + + Signed-off-by: Pavel Emelyanov + +commit f360aa43e0782543a6e8fece20b71ec25ef36568 +Author: Cyrill Gorcunov +Date: Mon Apr 12 23:41:46 2010 +0400 + + netfilter: Restore match/target support for revision 0 + + Revision 0 is still used in our VE templates (iptables-1.3.5) + so we just can't drop this kind of support. Bring them back. + + What is restored: + + - target "CONNMARK" + - target "TOS" + - target "MARK" + - match "connmark" + - match "tos" + - match "iprange" + - match "mark" + - match "owner" + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit 81959d6fac075a62150d9e726f27e09254b3cf0e +Author: Pavel Emelyanov +Date: Thu Apr 8 21:28:03 2010 +0400 + + OpenVZ kernel 2.6.32-atkov released + + Named after Oleg Yur'yevich At'kov - a Russian cosmonaut. + + Signed-off-by: Pavel Emelyanov + +commit b97a0293d29009398eb7abd2e9887ab64741b98d +Merge: 44e953b 1b6e168 +Author: Pavel Emelyanov +Date: Thu Apr 8 21:24:36 2010 +0400 + + Merged 2.6.32.11 + + Conflicts: + + Makefile + + Signed-off-by: Pavel Emelyanov + +commit 44e953b5f69888d88ceaa236ddb41086404a9dbd +Author: Cyrill Gorcunov +Date: Thu Apr 8 18:59:26 2010 +0400 + + netfilter: xtables: Return xt_conntrack v0 back + + In commit 9e05ec4b1804a1ba51f61fe169aef9b86edcd3f7 + the revision 0 of xt_conntrack was dropped which made + iptables-1.3.5 not funtional in VE. + + Return compatibility back. + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit 451c01314a07c01e55e79a8134e0adc55a584465 +Author: Cyrill Gorcunov +Date: Mon Mar 29 01:50:51 2010 +0400 + + iptables: Tables should be checked for permission via mask only + + The sequence of module loading is not controllable by the kernel anymore + (due to KSYM removal). As result we may fail testing if dependant module is + already loaded(allowed for usage via config) at moment of granting the module + permissions to run in particular VE. + + Instead the _MOD bits are used as flags pointing out that netns is borrowing + some resources and we need to release them at exit (we can't just fail in + netns init/fini routines otherwise VE would not start at all). + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit ea5540ba9694531c6a74092c29f5e61e393b9ac8 +Author: Cyrill Gorcunov +Date: Mon Mar 29 01:15:52 2010 +0400 + + netfiler: Introduce per-net stubs for l3proto_ipv4 + + Prepare ground for future l3proto_ipv4 virtualization. + This snippets only setup pernet ops without any serious actions. + We still need to make sysctls netns compatible. + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit 2cf066b2d96b58e1594965d102d48cd3eb6d6168 +Author: Cyrill Gorcunov +Date: Sun Mar 28 03:24:36 2010 +0400 + + netfilter: Do not create NAT rules if not allowed + + In case if NAT is not allowed in particular VE we just drop the creation + of tuples for such VE (this way dropping this functionality). + + Note that there is no need for setting up VE_NF_CONNTRACK_MOD in + nf_conntrack_net_init. We are going to get rid of module dependency checking + by completely switch to net-namespace functionality. + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit 8d9ba8b69ff82a2c335f2cf860265b5240460228 +Author: Pavel Emelyanov +Date: Tue Apr 6 20:09:50 2010 +0400 + + meminfo: Initialize mi.si before passing it to virtinfo + + Otherwise the listener (vecalls.c) will see grbage and may produce + bullshit in ve's /proc/meminfo + + http://bugzilla.openvz.org/show_bug.cgi?id=1487 + + Signed-off-by: Pavel Emelyanov + +commit 3e16fd3fd9101ef59d38d60b989b62cb9a11df2b +Author: Sven-Haegar Koch +Date: Tue Apr 6 15:39:02 2010 +0400 + + Fix compile error in mm/slab.c + + Commit f385db6d4 (MM: Kmemsize accounting bits) introduced a syntax + error into mm/slab.c: + + CC mm/slab.o + mm/slab.c: In function 'alloc_slabmgmt': + mm/slab.c:2687: error: too few arguments to function 'kmem_cache_alloc_node + mm/slab.c:2687: warning: left-hand operand of comma expression has no effec + mm/slab.c:2687: warning: statement with no effect + mm/slab.c:2687: error: expected ';' before ')' token + mm/slab.c:2687: error: expected statement before ')' token + make[1]: *** [mm/slab.o] Error 1 + make: *** [mm] Error 2 + + http://bugzilla.openvz.org/show_bug.cgi?id=1486 + + Signed-off-by: Sven-Haegar Koch + Signed-off-by: Pavel Emelyanov + +commit 2a40c7f120c9239ffa4cf7b151974351c2f54796 +Author: Cyrill Gorcunov +Date: Sun Mar 28 01:44:02 2010 +0300 + + iptables, nat: Add missing flag that namespace is used + + Otherwise we may leak the namespace resource. + + Signed-off-by: Cyrill Gorcunov + Signed-off-by: Pavel Emelyanov + +commit 5186a0a6d011e4b8c2bbd2ca4cf1aa40507e2078 +Author: Pavel Emelyanov +Date: Mon Apr 5 14:28:45 2010 +0400 + + cpt: Save and restore task_user_gs(). + + Without it 32bit container stops right after the restore + due to #GP. + + Signed-off-by: Pavel Emelyanov + commit 14a9729fab679c9c9f15e2ff44070806247b62c5 Author: Pavel Emelyanov Date: Fri Apr 2 23:00:10 2010 +0400 @@ -2614,14 +2799,14 @@ index 0000000..9856a2b +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile -index 2becebb..0af517e 100644 +index 78611d9..6c58263 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 32 EXTRAVERSION = -+VZVERSION = afanasyev ++VZVERSION = atkov NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* @@ -3217,7 +3402,7 @@ index 4cf7956..69478e4 100644 regs.bx = (unsigned long) fn; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c -index f9ce04f..328aef7 100644 +index 6eabe90..490f4f5 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -25,8 +25,10 @@ @@ -3269,7 +3454,7 @@ index f9ce04f..328aef7 100644 } void release_thread(struct task_struct *dead_task) -@@ -680,3 +683,20 @@ unsigned long KSTK_ESP(struct task_struct *task) +@@ -681,3 +684,20 @@ unsigned long KSTK_ESP(struct task_struct *task) return (test_tsk_thread_flag(task, TIF_IA32)) ? (task_pt_regs(task)->sp) : ((task)->thread.usersp); } @@ -3423,7 +3608,7 @@ index ec1de97..b74f73d 100644 * this function calls the 'stop' function on all other CPUs in the system. */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c -index 565ebc6..0ac4f1d 100644 +index 28e963d..54a0ecf 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -733,6 +733,12 @@ do_rest: @@ -9046,7 +9231,7 @@ index 085c5c0..8f10643 100644 /* * The following function implements the controller interface for diff --git a/fs/exec.c b/fs/exec.c -index 9b88366..ffbd2a7 100644 +index a2a3944..bac9cfa 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -26,6 +26,7 @@ @@ -12778,7 +12963,7 @@ index 1afa4dd..cfd8d8b 100644 } module_init(proc_loadavg_init); diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c -index a65239c..f31f243 100644 +index a65239c..76206c4 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -10,6 +10,7 @@ @@ -12818,10 +13003,14 @@ index a65239c..f31f243 100644 unsigned long committed; unsigned long allowed; struct vmalloc_info vmi; -@@ -29,10 +49,15 @@ static int meminfo_proc_show(struct seq_file *m, void *v) +@@ -29,12 +49,19 @@ static int meminfo_proc_show(struct seq_file *m, void *v) unsigned long pages[NR_LRU_LISTS]; int lru; ++ si_meminfo(&i); ++ si_swapinfo(&i); ++ mi.si = i; ++ + ret = virtinfo_notifier_call(VITYPE_GENERAL, VIRTINFO_MEMINFO, &mi); + if (ret & NOTIFY_FAIL) + return 0; @@ -12832,10 +13021,12 @@ index a65239c..f31f243 100644 * display in kilobytes. */ -#define K(x) ((x) << (PAGE_SHIFT - 10)) - si_meminfo(&i); - si_swapinfo(&i); +- si_meminfo(&i); +- si_swapinfo(&i); committed = percpu_counter_read_positive(&vm_committed_as); -@@ -175,7 +200,7 @@ static const struct file_operations meminfo_proc_fops = { + allowed = ((totalram_pages - hugetlb_total_pages()) + * sysctl_overcommit_ratio / 100) + total_swap_pages; +@@ -175,7 +202,7 @@ static const struct file_operations meminfo_proc_fops = { static int __init proc_meminfo_init(void) { @@ -13216,7 +13407,7 @@ index 68d4f6d..4c2159c 100644 + +obj-y += vzdquota/ diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c -index 2534987..beda08c 100644 +index 2ed79a9..acfde60 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -170,8 +170,9 @@ static struct quota_format_type *find_quota_format(int id) @@ -22870,7 +23061,7 @@ index 0000000..be88d2d + diff --git a/include/linux/cpt_image.h b/include/linux/cpt_image.h new file mode 100644 -index 0000000..e25c3ce +index 0000000..6ab78b7 --- /dev/null +++ b/include/linux/cpt_image.h @@ -0,0 +1,1799 @@ @@ -24094,7 +24285,7 @@ index 0000000..e25c3ce + __u32 cpt_eflags; + __u32 cpt_esp; + __u32 cpt_xss; -+ __u32 pad; ++ __u32 cpt_ugs; +}; + +struct cpt_x86_64_regs @@ -25446,10 +25637,10 @@ index 6d527ee..f46e01f 100644 } while (0) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h -index 9bace4b..df56eb7 100644 +index 040b679..70658bc 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h -@@ -411,6 +411,9 @@ extern long hrtimer_nanosleep(struct timespec *rqtp, +@@ -416,6 +416,9 @@ extern long hrtimer_nanosleep(struct timespec *rqtp, const enum hrtimer_mode mode, const clockid_t clockid); extern long hrtimer_nanosleep_restart(struct restart_block *restart_block); @@ -26072,16 +26263,19 @@ index 812a5f3..94887e1 100644 { int feature = gso_type << NETIF_F_GSO_SHIFT; diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index 6132b5e..cc0d48e 100644 +index 6132b5e..56ec50d 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h -@@ -353,5 +353,25 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *); +@@ -353,5 +353,28 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *); static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} #endif +#ifdef CONFIG_VE_IPTABLES +#include + ++#define net_ipt_permitted(netns, ipt) \ ++ (mask_ipt_allow((netns)->owner_ve->ipt_mask, ipt)) ++ +#define net_ipt_module_permitted(netns, ipt) \ + (mask_ipt_allow((netns)->owner_ve->ipt_mask, ipt) && \ + mask_ipt_allow((netns)->owner_ve->_iptables_modules, \ @@ -26137,6 +26331,114 @@ index 812cb15..4339ac7 100644 #endif /* __KERNEL__ */ #endif /* _X_TABLES_H */ +diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h +index 0a85458..7635c8f 100644 +--- a/include/linux/netfilter/xt_CONNMARK.h ++++ b/include/linux/netfilter/xt_CONNMARK.h +@@ -18,6 +18,12 @@ enum { + XT_CONNMARK_RESTORE + }; + ++struct xt_connmark_target_info { ++ unsigned long mark; ++ unsigned long mask; ++ __u8 mode; ++}; ++ + struct xt_connmark_tginfo1 { + __u32 ctmark, ctmask, nfmask; + __u8 mode; +diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h +index bc9561b..028304b 100644 +--- a/include/linux/netfilter/xt_MARK.h ++++ b/include/linux/netfilter/xt_MARK.h +@@ -3,6 +3,23 @@ + + #include + ++/* Version 0 */ ++struct xt_mark_target_info { ++ unsigned long mark; ++}; ++ ++/* Version 1 */ ++enum { ++ XT_MARK_SET=0, ++ XT_MARK_AND, ++ XT_MARK_OR, ++}; ++ ++struct xt_mark_target_info_v1 { ++ unsigned long mark; ++ __u8 mode; ++}; ++ + struct xt_mark_tginfo2 { + __u32 mark, mask; + }; +diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h +index 619e47c..571e266 100644 +--- a/include/linux/netfilter/xt_connmark.h ++++ b/include/linux/netfilter/xt_connmark.h +@@ -12,6 +12,11 @@ + * (at your option) any later version. + */ + ++struct xt_connmark_info { ++ unsigned long mark, mask; ++ __u8 invert; ++}; ++ + struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h +index 54f47a2..7ae0533 100644 +--- a/include/linux/netfilter/xt_conntrack.h ++++ b/include/linux/netfilter/xt_conntrack.h +@@ -32,6 +32,42 @@ enum { + XT_CONNTRACK_DIRECTION = 1 << 12, + }; + ++/* This is exposed to userspace, so remains frozen in time. */ ++struct ip_conntrack_old_tuple ++{ ++ struct { ++ __be32 ip; ++ union { ++ __u16 all; ++ } u; ++ } src; ++ ++ struct { ++ __be32 ip; ++ union { ++ __u16 all; ++ } u; ++ ++ /* The protocol. */ ++ __u16 protonum; ++ } dst; ++}; ++ ++struct xt_conntrack_info ++{ ++ unsigned int statemask, statusmask; ++ ++ struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; ++ struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; ++ ++ unsigned long expires_min, expires_max; ++ ++ /* Flags word */ ++ __u8 flags; ++ /* Inverse flags */ ++ __u8 invflags; ++}; ++ + struct xt_conntrack_mtinfo1 { + union nf_inet_addr origsrc_addr, origsrc_mask; + union nf_inet_addr origdst_addr, origdst_mask; diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h index b1925b5..65eaf2b 100644 --- a/include/linux/netfilter/xt_hashlimit.h @@ -26153,6 +26455,22 @@ index b1925b5..65eaf2b 100644 +}; +#endif #endif /*_XT_HASHLIMIT_H*/ +diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h +index 6607c8f..6fa460a 100644 +--- a/include/linux/netfilter/xt_mark.h ++++ b/include/linux/netfilter/xt_mark.h +@@ -3,6 +3,11 @@ + + #include + ++struct xt_mark_info { ++ unsigned long mark, mask; ++ __u8 invert; ++}; ++ + struct xt_mark_mtinfo1 { + __u32 mark, mask; + __u8 invert; diff --git a/include/linux/netfilter/xt_recent.h b/include/linux/netfilter/xt_recent.h index d2c2766..8a12181 100644 --- a/include/linux/netfilter/xt_recent.h @@ -26173,6 +26491,122 @@ index d2c2766..8a12181 100644 +}; +#endif #endif /* _LINUX_NETFILTER_XT_RECENT_H */ +diff --git a/include/linux/netfilter_ipv4/ipt_TOS.h b/include/linux/netfilter_ipv4/ipt_TOS.h +new file mode 100644 +index 0000000..6752240 +--- /dev/null ++++ b/include/linux/netfilter_ipv4/ipt_TOS.h +@@ -0,0 +1,12 @@ ++#ifndef _IPT_TOS_H_target ++#define _IPT_TOS_H_target ++ ++#ifndef IPTOS_NORMALSVC ++#define IPTOS_NORMALSVC 0 ++#endif ++ ++struct ipt_tos_target_info { ++ u_int8_t tos; ++}; ++ ++#endif /*_IPT_TOS_H_target*/ +diff --git a/include/linux/netfilter_ipv4/ipt_iprange.h b/include/linux/netfilter_ipv4/ipt_iprange.h +new file mode 100644 +index 0000000..517e8b1 +--- /dev/null ++++ b/include/linux/netfilter_ipv4/ipt_iprange.h +@@ -0,0 +1,23 @@ ++#ifndef _IPT_IPRANGE_H ++#define _IPT_IPRANGE_H ++ ++#define IPRANGE_SRC 0x01 /* Match source IP address */ ++#define IPRANGE_DST 0x02 /* Match destination IP address */ ++#define IPRANGE_SRC_INV 0x10 /* Negate the condition */ ++#define IPRANGE_DST_INV 0x20 /* Negate the condition */ ++ ++struct ipt_iprange { ++ /* Inclusive: network order. */ ++ u_int32_t min_ip, max_ip; ++}; ++ ++struct ipt_iprange_info ++{ ++ struct ipt_iprange src; ++ struct ipt_iprange dst; ++ ++ /* Flags from above */ ++ u_int8_t flags; ++}; ++ ++#endif /* _IPT_IPRANGE_H */ +diff --git a/include/linux/netfilter_ipv4/ipt_owner.h b/include/linux/netfilter_ipv4/ipt_owner.h +new file mode 100644 +index 0000000..72ea6c3 +--- /dev/null ++++ b/include/linux/netfilter_ipv4/ipt_owner.h +@@ -0,0 +1,20 @@ ++#ifndef _IPT_OWNER_H ++#define _IPT_OWNER_H ++ ++/* match and invert flags */ ++#define IPT_OWNER_UID 0x01 ++#define IPT_OWNER_GID 0x02 ++#define IPT_OWNER_PID 0x04 ++#define IPT_OWNER_SID 0x08 ++#define IPT_OWNER_COMM 0x10 ++ ++struct ipt_owner_info { ++ uid_t uid; ++ gid_t gid; ++ pid_t pid; ++ pid_t sid; ++ char comm[16]; ++ u_int8_t match, invert; /* flags */ ++}; ++ ++#endif /*_IPT_OWNER_H*/ +diff --git a/include/linux/netfilter_ipv4/ipt_tos.h b/include/linux/netfilter_ipv4/ipt_tos.h +new file mode 100644 +index 0000000..a21f5df +--- /dev/null ++++ b/include/linux/netfilter_ipv4/ipt_tos.h +@@ -0,0 +1,13 @@ ++#ifndef _IPT_TOS_H ++#define _IPT_TOS_H ++ ++struct ipt_tos_info { ++ u_int8_t tos; ++ u_int8_t invert; ++}; ++ ++#ifndef IPTOS_NORMALSVC ++#define IPTOS_NORMALSVC 0 ++#endif ++ ++#endif /*_IPT_TOS_H*/ +diff --git a/include/linux/netfilter_ipv6/ip6t_owner.h b/include/linux/netfilter_ipv6/ip6t_owner.h +new file mode 100644 +index 0000000..e9f10ba +--- /dev/null ++++ b/include/linux/netfilter_ipv6/ip6t_owner.h +@@ -0,0 +1,18 @@ ++#ifndef _IP6T_OWNER_H ++#define _IP6T_OWNER_H ++ ++/* match and invert flags */ ++#define IP6T_OWNER_UID 0x01 ++#define IP6T_OWNER_GID 0x02 ++#define IP6T_OWNER_PID 0x04 ++#define IP6T_OWNER_SID 0x08 ++ ++struct ip6t_owner_info { ++ uid_t uid; ++ gid_t gid; ++ pid_t pid; ++ pid_t sid; ++ u_int8_t match, invert; /* flags */ ++}; ++ ++#endif /*_IPT_OWNER_H*/ diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 320569e..8e0d228 100644 --- a/include/linux/nfs_fs_sb.h @@ -26435,10 +26869,10 @@ index 8fd8efc..8cd6b71 100644 int register_quota_format(struct quota_format_type *fmt); diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h -index 3ebb231..aa3a028 100644 +index a529d86..579a15c 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h -@@ -257,6 +257,19 @@ static inline void vfs_dq_free_inode(struct inode *inode) +@@ -264,6 +264,19 @@ static inline void vfs_dq_free_inode(struct inode *inode) inode->i_sb->dq_op->free_inode(inode, 1); } @@ -26458,7 +26892,7 @@ index 3ebb231..aa3a028 100644 /* Cannot be called inside a transaction */ static inline int vfs_dq_off(struct super_block *sb, int remount) { -@@ -356,6 +369,12 @@ static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) +@@ -363,6 +376,12 @@ static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr) return 0; } @@ -27679,10 +28113,10 @@ index 61723a7..fe8494b 100644 struct inet_timewait_sock tw_sk; u32 tw_rcv_nxt; diff --git a/include/linux/tty.h b/include/linux/tty.h -index f0f43d0..0bdd24d 100644 +index e9c57e9..cc60313 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h -@@ -302,6 +302,7 @@ struct tty_struct { +@@ -313,6 +313,7 @@ struct tty_struct { /* If the tty has a pending do_SAK, queue it here - akpm */ struct work_struct SAK_work; struct tty_port *port; @@ -27690,7 +28124,7 @@ index f0f43d0..0bdd24d 100644 }; /* tty magic number */ -@@ -333,6 +334,7 @@ struct tty_struct { +@@ -344,6 +345,7 @@ struct tty_struct { #define TTY_HUPPED 18 /* Post driver->hangup() */ #define TTY_FLUSHING 19 /* Flushing to ldisc in progress */ #define TTY_FLUSHPENDING 20 /* Queued buffer flush pending */ @@ -27698,7 +28132,7 @@ index f0f43d0..0bdd24d 100644 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty)) -@@ -438,7 +440,7 @@ extern void free_tty_struct(struct tty_struct *tty); +@@ -449,7 +451,7 @@ extern void free_tty_struct(struct tty_struct *tty); extern void initialize_tty_struct(struct tty_struct *tty, struct tty_driver *driver, int idx); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, @@ -30592,7 +31026,7 @@ index 6eb48e5..b07e8d6 100644 printed = true; } diff --git a/init/main.c b/init/main.c -index 4051d75..e80873d 100644 +index bc109c7..d7f4866 100644 --- a/init/main.c +++ b/init/main.c @@ -70,6 +70,9 @@ @@ -30622,7 +31056,7 @@ index 4051d75..e80873d 100644 /* * Boot command-line arguments */ -@@ -521,6 +534,9 @@ asmlinkage void __init start_kernel(void) +@@ -516,6 +529,9 @@ asmlinkage void __init start_kernel(void) smp_setup_processor_id(); @@ -30632,7 +31066,7 @@ index 4051d75..e80873d 100644 /* * Need to run as early as possible, to initialize the * lockdep hash: -@@ -553,6 +569,7 @@ asmlinkage void __init start_kernel(void) +@@ -548,6 +564,7 @@ asmlinkage void __init start_kernel(void) setup_command_line(command_line); setup_nr_cpu_ids(); setup_per_cpu_areas(); @@ -30640,7 +31074,7 @@ index 4051d75..e80873d 100644 smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ build_all_zonelists(); -@@ -660,6 +677,7 @@ asmlinkage void __init start_kernel(void) +@@ -655,6 +672,7 @@ asmlinkage void __init start_kernel(void) cred_init(); fork_init(totalram_pages); proc_caches_init(); @@ -30648,7 +31082,7 @@ index 4051d75..e80873d 100644 buffer_init(); key_init(); security_init(); -@@ -683,6 +701,10 @@ asmlinkage void __init start_kernel(void) +@@ -678,6 +696,10 @@ asmlinkage void __init start_kernel(void) ftrace_init(); @@ -30659,7 +31093,7 @@ index 4051d75..e80873d 100644 /* Do the rest non-__init'ed, we're now alive */ rest_init(); } -@@ -773,6 +795,7 @@ static void __init do_initcalls(void) +@@ -768,6 +790,7 @@ static void __init do_initcalls(void) */ static void __init do_basic_setup(void) { @@ -30667,7 +31101,7 @@ index 4051d75..e80873d 100644 init_workqueues(); cpuset_init_smp(); usermodehelper_init(); -@@ -874,6 +897,7 @@ static int __init kernel_init(void * unused) +@@ -869,6 +892,7 @@ static int __init kernel_init(void * unused) start_boot_trace(); smp_init(); @@ -45078,10 +45512,10 @@ index 0000000..918fe2a +module_exit(exit_cpt); diff --git a/kernel/cpt/cpt_process.c b/kernel/cpt/cpt_process.c new file mode 100644 -index 0000000..a9d90cf +index 0000000..2afc171 --- /dev/null +++ b/kernel/cpt/cpt_process.c -@@ -0,0 +1,1382 @@ +@@ -0,0 +1,1383 @@ +/* + * + * kernel/cpt/cpt_process.c @@ -45282,6 +45716,7 @@ index 0000000..a9d90cf + + ri.cpt_fs = encode_segment(pt_regs->fs); + ri.cpt_gs = encode_segment(tsk->thread.gs); ++ ri.cpt_ugs = encode_segment(task_user_gs(tsk)); + + ri.cpt_ebx = pt_regs->bx; + ri.cpt_ecx = pt_regs->cx; @@ -53825,10 +54260,10 @@ index 0000000..2b0b283 +module_exit(exit_rst); diff --git a/kernel/cpt/rst_process.c b/kernel/cpt/rst_process.c new file mode 100644 -index 0000000..264959a +index 0000000..19915b3 --- /dev/null +++ b/kernel/cpt/rst_process.c -@@ -0,0 +1,1613 @@ +@@ -0,0 +1,1614 @@ +/* + * + * kernel/cpt/rst_process.c @@ -54677,6 +55112,7 @@ index 0000000..264959a + tsk->thread.ip = (unsigned long) &i386_ret_from_resume; + + tsk->thread.gs = decode_segment(b->cpt_gs); ++ task_user_gs(tsk) = decode_segment(b->cpt_ugs); + tsk->thread.debugreg0 = b->cpt_debugreg[0]; + tsk->thread.debugreg1 = b->cpt_debugreg[1]; + tsk->thread.debugreg2 = b->cpt_debugreg[2]; @@ -60396,10 +60832,10 @@ index 1ad4fa6..b65727e 100644 /* diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c -index 3e1c36e..aeda76a 100644 +index 931a4d9..b34a0b9 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c -@@ -1527,6 +1527,7 @@ out: +@@ -1545,6 +1545,7 @@ out: destroy_hrtimer_on_stack(&t.timer); return ret; } @@ -60498,7 +60934,7 @@ index 5240d75..064a191 100644 loop_end: thaw_processes(); diff --git a/kernel/kthread.c b/kernel/kthread.c -index ab7ae57..928b673 100644 +index 84027cf..d3151a1 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -14,6 +14,7 @@ @@ -61160,7 +61596,7 @@ index 86b3796..6d3f029 100644 } diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c -index 4954407..cc6fcd1 100644 +index 4954407..da76c51 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -31,6 +31,8 @@ @@ -61193,28 +61629,32 @@ index 4954407..cc6fcd1 100644 idr_init(&posix_timers_id); return 0; } -@@ -363,6 +368,12 @@ int posix_timer_event(struct k_itimer *timr, int si_private) +@@ -363,6 +368,7 @@ int posix_timer_event(struct k_itimer *timr, int si_private) { struct task_struct *task; int shared, ret = -1; -+ struct ve_struct *ve; -+ struct user_beancounter *ub; -+ -+ ve = set_exec_env(timr->it_process->ve_task_info.owner_env); -+ ub = set_exec_ub(timr->it_process->task_bc.task_ub); + /* * FIXME: if ->sigq is queued we can race with * dequeue_signal()->do_schedule_next_timer(). -@@ -384,6 +395,8 @@ int posix_timer_event(struct k_itimer *timr, int si_private) +@@ -379,8 +385,17 @@ int posix_timer_event(struct k_itimer *timr, int si_private) + rcu_read_lock(); + task = pid_task(timr->it_pid, PIDTYPE_PID); + if (task) { ++ struct ve_struct *ve; ++ struct user_beancounter *ub; ++ ++ ve = set_exec_env(task->ve_task_info.owner_env); ++ ub = set_exec_ub(task->task_bc.task_ub); ++ + shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID); + ret = send_sigqueue(timr->sigq, task, shared); ++ ++ (void)set_exec_ub(ub); ++ (void)set_exec_env(ve); } rcu_read_unlock(); /* If we failed to send the signal the timer stops. */ -+ (void)set_exec_ub(ub); -+ (void)set_exec_env(ve); - return ret > 0; - } - EXPORT_SYMBOL_GPL(posix_timer_event); diff --git a/kernel/power/process.c b/kernel/power/process.c index cc2e553..3122fcb 100644 --- a/kernel/power/process.c @@ -61719,7 +62159,7 @@ index 23bd09c..8967db7 100644 child = find_task_by_vpid(pid); if (child) diff --git a/kernel/sched.c b/kernel/sched.c -index 380e1fa..738a84c 100644 +index ed61192..e66f256 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -71,6 +71,8 @@ @@ -62272,7 +62712,7 @@ index 380e1fa..738a84c 100644 activate_task(this_rq, p, 0); check_preempt_curr(this_rq, p, 0); } -@@ -5044,10 +5437,13 @@ void account_user_time(struct task_struct *p, cputime_t cputime, +@@ -5054,10 +5447,13 @@ void account_user_time(struct task_struct *p, cputime_t cputime, /* Add user time to cpustat. */ tmp = cputime_to_cputime64(cputime); @@ -62288,7 +62728,7 @@ index 380e1fa..738a84c 100644 cpuacct_update_stats(p, CPUACCT_STAT_USER, cputime); /* Account for user time used */ -@@ -5104,6 +5500,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset, +@@ -5114,6 +5510,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset, /* Add system time to cpustat. */ tmp = cputime_to_cputime64(cputime); @@ -62296,7 +62736,7 @@ index 380e1fa..738a84c 100644 if (hardirq_count() - hardirq_offset) cpustat->irq = cputime64_add(cpustat->irq, tmp); else if (softirq_count()) -@@ -5482,6 +5879,8 @@ need_resched_nonpreemptible: +@@ -5492,6 +5889,8 @@ need_resched_nonpreemptible: next = pick_next_task(rq); if (likely(prev != next)) { @@ -62305,7 +62745,7 @@ index 380e1fa..738a84c 100644 sched_info_switch(prev, next); perf_event_task_sched_out(prev, next, cpu); -@@ -5489,6 +5888,22 @@ need_resched_nonpreemptible: +@@ -5499,6 +5898,22 @@ need_resched_nonpreemptible: rq->curr = next; ++*switch_count; @@ -62328,7 +62768,7 @@ index 380e1fa..738a84c 100644 context_switch(rq, prev, next); /* unlocks the rq */ /* * the context switch might have flipped the stack from under -@@ -5496,8 +5911,10 @@ need_resched_nonpreemptible: +@@ -5506,8 +5921,10 @@ need_resched_nonpreemptible: */ cpu = smp_processor_id(); rq = cpu_rq(cpu); @@ -62340,7 +62780,7 @@ index 380e1fa..738a84c 100644 post_schedule(rq); -@@ -6281,7 +6698,7 @@ recheck: +@@ -6291,7 +6708,7 @@ recheck: /* * Allow unprivileged RT tasks to decrease priority: */ @@ -62349,7 +62789,7 @@ index 380e1fa..738a84c 100644 if (rt_policy(policy)) { unsigned long rlim_rtprio; -@@ -6788,11 +7205,16 @@ EXPORT_SYMBOL(yield); +@@ -6798,11 +7215,16 @@ EXPORT_SYMBOL(yield); void __sched io_schedule(void) { struct rq *rq = raw_rq(); @@ -62366,7 +62806,7 @@ index 380e1fa..738a84c 100644 current->in_iowait = 0; atomic_dec(&rq->nr_iowait); delayacct_blkio_end(); -@@ -6803,11 +7225,16 @@ long __sched io_schedule_timeout(long timeout) +@@ -6813,11 +7235,16 @@ long __sched io_schedule_timeout(long timeout) { struct rq *rq = raw_rq(); long ret; @@ -62383,7 +62823,7 @@ index 380e1fa..738a84c 100644 current->in_iowait = 0; atomic_dec(&rq->nr_iowait); delayacct_blkio_end(); -@@ -6914,17 +7341,7 @@ void sched_show_task(struct task_struct *p) +@@ -6924,17 +7351,7 @@ void sched_show_task(struct task_struct *p) state = p->state ? __ffs(p->state) + 1 : 0; printk(KERN_INFO "%-13.13s %c", p->comm, state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?'); @@ -62402,7 +62842,7 @@ index 380e1fa..738a84c 100644 #ifdef CONFIG_DEBUG_STACK_USAGE free = stack_not_used(p); #endif -@@ -6941,13 +7358,13 @@ void show_state_filter(unsigned long state_filter) +@@ -6951,13 +7368,13 @@ void show_state_filter(unsigned long state_filter) #if BITS_PER_LONG == 32 printk(KERN_INFO @@ -62419,7 +62859,7 @@ index 380e1fa..738a84c 100644 /* * reset the NMI-timeout, listing all files on a slow * console might take alot of time: -@@ -6955,7 +7372,7 @@ void show_state_filter(unsigned long state_filter) +@@ -6965,7 +7382,7 @@ void show_state_filter(unsigned long state_filter) touch_nmi_watchdog(); if (!state_filter || (p->state & state_filter)) sched_show_task(p); @@ -62428,7 +62868,7 @@ index 380e1fa..738a84c 100644 touch_all_softlockup_watchdogs(); -@@ -7321,13 +7738,13 @@ static void migrate_live_tasks(int src_cpu) +@@ -7331,13 +7748,13 @@ static void migrate_live_tasks(int src_cpu) read_lock(&tasklist_lock); @@ -62444,7 +62884,7 @@ index 380e1fa..738a84c 100644 read_unlock(&tasklist_lock); } -@@ -9488,7 +9905,7 @@ void __init sched_init(void) +@@ -9498,7 +9915,7 @@ void __init sched_init(void) #ifdef CONFIG_FAIR_GROUP_SCHED init_task_group.shares = init_task_group_load; INIT_LIST_HEAD(&rq->leaf_cfs_rq_list); @@ -62453,7 +62893,7 @@ index 380e1fa..738a84c 100644 /* * How much cpu bandwidth does init_task_group get? * -@@ -9534,7 +9951,7 @@ void __init sched_init(void) +@@ -9544,7 +9961,7 @@ void __init sched_init(void) rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime; #ifdef CONFIG_RT_GROUP_SCHED INIT_LIST_HEAD(&rq->leaf_rt_rq_list); @@ -62462,7 +62902,7 @@ index 380e1fa..738a84c 100644 init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL); #elif defined CONFIG_USER_SCHED init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, 0, NULL); -@@ -9600,6 +10017,7 @@ void __init sched_init(void) +@@ -9610,6 +10027,7 @@ void __init sched_init(void) * During early bootup we pretend to be a normal task: */ current->sched_class = &fair_sched_class; @@ -62470,7 +62910,7 @@ index 380e1fa..738a84c 100644 /* Allocate the nohz_cpu_mask if CONFIG_CPUMASK_OFFSTACK */ zalloc_cpumask_var(&nohz_cpu_mask, GFP_NOWAIT); -@@ -9678,7 +10096,7 @@ void normalize_rt_tasks(void) +@@ -9688,7 +10106,7 @@ void normalize_rt_tasks(void) struct rq *rq; read_lock_irqsave(&tasklist_lock, flags); @@ -62479,7 +62919,7 @@ index 380e1fa..738a84c 100644 /* * Only normalize user tasks: */ -@@ -9709,7 +10127,7 @@ void normalize_rt_tasks(void) +@@ -9719,7 +10137,7 @@ void normalize_rt_tasks(void) __task_rq_unlock(rq); spin_unlock(&p->pi_lock); @@ -62488,7 +62928,7 @@ index 380e1fa..738a84c 100644 read_unlock_irqrestore(&tasklist_lock, flags); } -@@ -10155,10 +10573,10 @@ static inline int tg_has_rt_tasks(struct task_group *tg) +@@ -10165,10 +10583,10 @@ static inline int tg_has_rt_tasks(struct task_group *tg) { struct task_struct *g, *p; @@ -63433,7 +63873,7 @@ index 5db5a8d..0ba4a86 100644 * If the sum of all the available memory (i.e. ram + swap) * is less than can be stored in a 32 bit unsigned long then diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index 6dc4e5e..f8d1912 100644 +index 0cccb6c..03d83f5 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3091,7 +3091,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) @@ -69099,7 +69539,7 @@ index 356dd99..141b181 100644 vma->vm_ops = &shmem_vm_ops; return 0; diff --git a/mm/slab.c b/mm/slab.c -index 5d1a782..7b62d7b 100644 +index 5d1a782..2502955 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -115,30 +115,14 @@ @@ -69613,7 +70053,7 @@ index 5d1a782..7b62d7b 100644 /* Slab management obj is off-slab. */ slabp = kmem_cache_alloc_node(cachep->slabp_cache, - local_flags, nodeid); -+ local_flags & ~__GFP_UBC), nodeid); ++ (local_flags & ~__GFP_UBC), nodeid); /* * If the first object in the slab is leaked (it's allocated * but no one has a reference to it), we want to make sure @@ -73903,7 +74343,7 @@ index c156db2..3d4e78f 100644 write_unlock_bh(&queue_lock); } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c -index 62aff31..93e2fd1 100644 +index 62aff31..c135650 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -321,6 +321,9 @@ ipt_do_table(struct sk_buff *skb, @@ -74024,7 +74464,7 @@ index 62aff31..93e2fd1 100644 - return xt_proto_init(net, NFPROTO_IPV4); + int res; + -+ if (!net_ipt_module_permitted(net, VE_IP_IPTABLES)) ++ if (!net_ipt_permitted(net, VE_IP_IPTABLES)) + return 0; + + res = xt_proto_init(net, NFPROTO_IPV4); @@ -74510,14 +74950,14 @@ index c93ae44..764a19c 100644 } } diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c -index df566cb..23d088d 100644 +index df566cb..b129326 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -128,16 +128,24 @@ module_param(forward, bool, 0000); static int __net_init iptable_filter_net_init(struct net *net) { -+ if (!net_ipt_module_permitted(net, VE_IP_FILTER)) ++ if (!net_ipt_permitted(net, VE_IP_FILTER)) + return 0; + /* Register table */ @@ -74539,14 +74979,14 @@ index df566cb..23d088d 100644 } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c -index 036047f..bd20c54 100644 +index 036047f..47730f3 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -198,16 +198,24 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = { static int __net_init iptable_mangle_net_init(struct net *net) { -+ if (!net_ipt_module_permitted(net, VE_IP_MANGLE)) ++ if (!net_ipt_permitted(net, VE_IP_MANGLE)) + return 0; + /* Register table */ @@ -74567,6 +75007,70 @@ index 036047f..bd20c54 100644 ipt_unregister_table(net->ipv4.iptable_mangle); } +diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +index 1032a15..8765b1b 100644 +--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -367,6 +368,30 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { + .me = THIS_MODULE, + }; + ++static int nf_conntrack_l3proto_ipv4_init_net(struct net *net) ++{ ++ if (!net_ipt_permitted(net, VE_IP_CONNTRACK)) ++ return 0; ++ /* ++ * FIXME: ++ * Need virtualize per-net sysctls ++ */ ++ ++ net_ipt_module_set(net, VE_IP_CONNTRACK); ++ return 0; ++} ++ ++static void nf_conntrack_l3proto_ipv4_fini_net(struct net *net) ++{ ++ if (!net_is_ipt_module_set(net, VE_IP_CONNTRACK)) ++ return; ++} ++ ++static struct pernet_operations nf_conntrack_ipv4_net_ops = { ++ .init = nf_conntrack_l3proto_ipv4_init_net, ++ .exit = nf_conntrack_l3proto_ipv4_fini_net, ++}; ++ + module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, + &nf_conntrack_htable_size, 0600); + +@@ -381,6 +406,12 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) + need_conntrack(); + nf_defrag_ipv4_enable(); + ++ ret = register_pernet_subsys(&nf_conntrack_ipv4_net_ops); ++ if (ret) { ++ printk(KERN_ERR "nf_conntrack_ipv4: Unable to register pernet operations\n"); ++ return ret; ++ } ++ + ret = nf_register_sockopt(&so_getorigdst); + if (ret < 0) { + printk(KERN_ERR "Unable to register netfilter socket option\n"); +@@ -452,6 +483,7 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); + nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); + nf_unregister_sockopt(&so_getorigdst); ++ unregister_pernet_subsys(&nf_conntrack_ipv4_net_ops); + } + + module_init(nf_conntrack_l3proto_ipv4_init); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 26066a2..2c77ffe 100644 --- a/net/ipv4/netfilter/nf_nat_core.c @@ -74616,20 +75120,25 @@ index 26066a2..2c77ffe 100644 /* It's done. */ if (maniptype == IP_NAT_MANIP_DST) diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c -index 9e81e0d..883cd2e 100644 +index 9e81e0d..e6798d6 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c -@@ -186,6 +186,9 @@ static struct xt_target ipt_dnat_reg __read_mostly = { +@@ -186,15 +186,24 @@ static struct xt_target ipt_dnat_reg __read_mostly = { static int __net_init nf_nat_rule_net_init(struct net *net) { -+ if (!net_ipt_module_permitted(net, VE_IP_IPTABLE_NAT)) ++ if (!net_ipt_permitted(net, VE_IP_IPTABLE_NAT)) + return 0; + net->ipv4.nat_table = ipt_register_table(net, &nat_table, &nat_initial_table.repl); if (IS_ERR(net->ipv4.nat_table)) -@@ -195,6 +198,9 @@ static int __net_init nf_nat_rule_net_init(struct net *net) + return PTR_ERR(net->ipv4.nat_table); ++ ++ net_ipt_module_set(net, VE_IP_IPTABLE_NAT); ++ + return 0; + } static void __net_exit nf_nat_rule_net_exit(struct net *net) { @@ -76242,7 +76751,7 @@ index 1cf3f0c..791bc00 100644 write_unlock_bh(&queue_lock); } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c -index 1de56fd..4260468 100644 +index 1de56fd..645d172 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -351,6 +351,9 @@ ip6t_do_table(struct sk_buff *skb, @@ -76289,7 +76798,7 @@ index 1de56fd..4260468 100644 - return xt_proto_init(net, NFPROTO_IPV6); + int res; + -+ if (!net_ipt_module_permitted(net, VE_IP_IPTABLES6)) ++ if (!net_ipt_permitted(net, VE_IP_IPTABLES6)) + return 0; + + res = xt_proto_init(net, NFPROTO_IPV6); @@ -76307,14 +76816,14 @@ index 1de56fd..4260468 100644 } diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c -index 6f4383a..eaaeec1 100644 +index 6f4383a..6b9dc0b 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -121,16 +121,24 @@ module_param(forward, bool, 0000); static int __net_init ip6table_filter_net_init(struct net *net) { -+ if (!net_ipt_module_permitted(net, VE_IP_FILTER6)) ++ if (!net_ipt_permitted(net, VE_IP_FILTER6)) + return 0; + /* Register table */ @@ -76336,14 +76845,14 @@ index 6f4383a..eaaeec1 100644 } diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c -index 0ad9143..32ac0e0 100644 +index 0ad9143..7960d5e 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -172,16 +172,24 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { static int __net_init ip6table_mangle_net_init(struct net *net) { -+ if (!net_ipt_module_permitted(net, VE_IP_MANGLE6)) ++ if (!net_ipt_permitted(net, VE_IP_MANGLE6)) + return 0; + /* Register table */ @@ -77029,7 +77538,7 @@ index e177f0d..1b301df 100644 addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c -index 1374179..fe0cc41 100644 +index 1374179..0692fd2 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -45,6 +45,9 @@ @@ -77108,7 +77617,16 @@ index 1374179..fe0cc41 100644 if (IS_ERR(ct)) { pr_debug("Can't allocate conntrack.\n"); return (struct nf_conntrack_tuple_hash *)ct; -@@ -1168,12 +1190,12 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) +@@ -714,6 +736,8 @@ resolve_normal_ct(struct net *net, + /* look for tuple match */ + h = nf_conntrack_find_get(net, &tuple); + if (!h) { ++ if (!mask_ipt_allow(get_exec_env()->ipt_mask, VE_NF_CONNTRACK)) ++ return NULL; + h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff); + if (!h) + return NULL; +@@ -1168,12 +1192,12 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); sz = nr_slots * sizeof(struct hlist_nulls_head); @@ -77393,11 +77911,186 @@ index f01955c..40f7121 100644 return private; } +diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c +index 5934570..d6e5ab4 100644 +--- a/net/netfilter/xt_CONNMARK.c ++++ b/net/netfilter/xt_CONNMARK.c +@@ -36,6 +36,45 @@ MODULE_ALIAS("ip6t_CONNMARK"); + #include + + static unsigned int ++connmark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) ++{ ++ const struct xt_connmark_target_info *markinfo = par->targinfo; ++ struct nf_conn *ct; ++ enum ip_conntrack_info ctinfo; ++ u_int32_t diff; ++ u_int32_t mark; ++ u_int32_t newmark; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct) { ++ switch(markinfo->mode) { ++ case XT_CONNMARK_SET: ++ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; ++ if (newmark != ct->mark) { ++ ct->mark = newmark; ++ nf_conntrack_event_cache(IPCT_MARK, ct); ++ } ++ break; ++ case XT_CONNMARK_SAVE: ++ newmark = (ct->mark & ~markinfo->mask) | ++ (skb->mark & markinfo->mask); ++ if (ct->mark != newmark) { ++ ct->mark = newmark; ++ nf_conntrack_event_cache(IPCT_MARK, ct); ++ } ++ break; ++ case XT_CONNMARK_RESTORE: ++ mark = skb->mark; ++ diff = (ct->mark ^ mark) & markinfo->mask; ++ skb->mark = mark ^ diff; ++ break; ++ } ++ } ++ ++ return XT_CONTINUE; ++} ++ ++static unsigned int + connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) + { + const struct xt_connmark_tginfo1 *info = par->targinfo; +@@ -73,6 +112,30 @@ connmark_tg(struct sk_buff *skb, const struct xt_target_param *par) + return XT_CONTINUE; + } + ++static bool connmark_tg_check_v0(const struct xt_tgchk_param *par) ++{ ++ const struct xt_connmark_target_info *matchinfo = par->targinfo; ++ ++ if (matchinfo->mode == XT_CONNMARK_RESTORE) { ++ if (strcmp(par->table, "mangle") != 0) { ++ printk(KERN_WARNING "CONNMARK: restore can only be " ++ "called from \"mangle\" table, not \"%s\"\n", ++ par->table); ++ return false; ++ } ++ } ++ if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { ++ printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); ++ return false; ++ } ++ if (nf_ct_l3proto_try_module_get(par->family) < 0) { ++ printk(KERN_WARNING "can't load conntrack support for " ++ "proto=%u\n", par->family); ++ return false; ++ } ++ return true; ++} ++ + static bool connmark_tg_check(const struct xt_tgchk_param *par) + { + if (nf_ct_l3proto_try_module_get(par->family) < 0) { +@@ -88,25 +151,74 @@ static void connmark_tg_destroy(const struct xt_tgdtor_param *par) + nf_ct_l3proto_module_put(par->family); + } + +-static struct xt_target connmark_tg_reg __read_mostly = { +- .name = "CONNMARK", +- .revision = 1, +- .family = NFPROTO_UNSPEC, +- .checkentry = connmark_tg_check, +- .target = connmark_tg, +- .targetsize = sizeof(struct xt_connmark_tginfo1), +- .destroy = connmark_tg_destroy, +- .me = THIS_MODULE, ++#ifdef CONFIG_COMPAT ++struct compat_xt_connmark_target_info { ++ compat_ulong_t mark, mask; ++ u_int8_t mode; ++ u_int8_t __pad1; ++ u_int16_t __pad2; ++}; ++ ++static void connmark_tg_compat_from_user_v0(void *dst, void *src) ++{ ++ const struct compat_xt_connmark_target_info *cm = src; ++ struct xt_connmark_target_info m = { ++ .mark = cm->mark, ++ .mask = cm->mask, ++ .mode = cm->mode, ++ }; ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int connmark_tg_compat_to_user_v0(void __user *dst, void *src) ++{ ++ const struct xt_connmark_target_info *m = src; ++ struct compat_xt_connmark_target_info cm = { ++ .mark = m->mark, ++ .mask = m->mask, ++ .mode = m->mode, ++ }; ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++#endif /* CONFIG_COMPAT */ ++ ++static struct xt_target connmark_tg_reg[] __read_mostly = { ++ { ++ .name = "CONNMARK", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_tg_check_v0, ++ .destroy = connmark_tg_destroy, ++ .target = connmark_tg_v0, ++ .targetsize = sizeof(struct xt_connmark_target_info), ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_connmark_target_info), ++ .compat_from_user = connmark_tg_compat_from_user_v0, ++ .compat_to_user = connmark_tg_compat_to_user_v0, ++#endif ++ .me = THIS_MODULE ++ }, ++ { ++ .name = "CONNMARK", ++ .revision = 1, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_tg_check, ++ .target = connmark_tg, ++ .targetsize = sizeof(struct xt_connmark_tginfo1), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, ++ }, + }; + + static int __init connmark_tg_init(void) + { +- return xt_register_target(&connmark_tg_reg); ++ return xt_register_targets(connmark_tg_reg, ++ ARRAY_SIZE(connmark_tg_reg)); + } + + static void __exit connmark_tg_exit(void) + { +- xt_unregister_target(&connmark_tg_reg); ++ xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); + } + + module_init(connmark_tg_init); diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c -index 74ce892..96ac9a4 100644 +index 74ce892..72b469b 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c -@@ -65,7 +65,7 @@ static bool dscp_tg_check(const struct xt_tgchk_param *par) +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + MODULE_AUTHOR("Harald Welte "); + MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); +@@ -65,13 +66,48 @@ static bool dscp_tg_check(const struct xt_tgchk_param *par) const struct xt_DSCP_info *info = par->targinfo; if (info->dscp > XT_DSCP_MAX) { @@ -77406,6 +78099,253 @@ index 74ce892..96ac9a4 100644 return false; } return true; + } + + static unsigned int ++tos_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) ++{ ++ const struct ipt_tos_target_info *info = par->targinfo; ++ struct iphdr *iph = ip_hdr(skb); ++ u_int8_t oldtos; ++ ++ if ((iph->tos & IPTOS_TOS_MASK) != info->tos) { ++ if (!skb_make_writable(skb, sizeof(struct iphdr))) ++ return NF_DROP; ++ ++ iph = ip_hdr(skb); ++ oldtos = iph->tos; ++ iph->tos = (iph->tos & IPTOS_PREC_MASK) | info->tos; ++ csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); ++ } ++ ++ return XT_CONTINUE; ++} ++ ++static bool tos_tg_check_v0(const struct xt_tgchk_param *par) ++{ ++ const struct ipt_tos_target_info *info = par->targinfo; ++ const uint8_t tos = info->tos; ++ ++ if (tos != IPTOS_LOWDELAY && tos != IPTOS_THROUGHPUT && ++ tos != IPTOS_RELIABILITY && tos != IPTOS_MINCOST && ++ tos != IPTOS_NORMALSVC) { ++ printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); ++ return false; ++ } ++ ++ return true; ++} ++ ++static unsigned int + tos_tg(struct sk_buff *skb, const struct xt_target_param *par) + { + const struct xt_tos_target_info *info = par->targinfo; +@@ -132,6 +168,16 @@ static struct xt_target dscp_tg_reg[] __read_mostly = { + }, + { + .name = "TOS", ++ .revision = 0, ++ .family = NFPROTO_IPV4, ++ .table = "mangle", ++ .target = tos_tg_v0, ++ .targetsize = sizeof(struct ipt_tos_target_info), ++ .checkentry = tos_tg_check_v0, ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "TOS", + .revision = 1, + .family = NFPROTO_IPV4, + .table = "mangle", +diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c +index 225f8d1..67574bc 100644 +--- a/net/netfilter/xt_MARK.c ++++ b/net/netfilter/xt_MARK.c +@@ -25,6 +25,39 @@ MODULE_ALIAS("ipt_MARK"); + MODULE_ALIAS("ip6t_MARK"); + + static unsigned int ++mark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par) ++{ ++ const struct xt_mark_target_info *markinfo = par->targinfo; ++ ++ skb->mark = markinfo->mark; ++ return XT_CONTINUE; ++} ++ ++static unsigned int ++mark_tg_v1(struct sk_buff *skb, const struct xt_target_param *par) ++{ ++ const struct xt_mark_target_info_v1 *markinfo = par->targinfo; ++ int mark = 0; ++ ++ switch (markinfo->mode) { ++ case XT_MARK_SET: ++ mark = markinfo->mark; ++ break; ++ ++ case XT_MARK_AND: ++ mark = skb->mark & markinfo->mark; ++ break; ++ ++ case XT_MARK_OR: ++ mark = skb->mark | markinfo->mark; ++ break; ++ } ++ ++ skb->mark = mark; ++ return XT_CONTINUE; ++} ++ ++static unsigned int + mark_tg(struct sk_buff *skb, const struct xt_target_param *par) + { + const struct xt_mark_tginfo2 *info = par->targinfo; +@@ -33,23 +66,135 @@ mark_tg(struct sk_buff *skb, const struct xt_target_param *par) + return XT_CONTINUE; + } + +-static struct xt_target mark_tg_reg __read_mostly = { +- .name = "MARK", +- .revision = 2, +- .family = NFPROTO_UNSPEC, +- .target = mark_tg, +- .targetsize = sizeof(struct xt_mark_tginfo2), +- .me = THIS_MODULE, ++static bool mark_tg_check_v0(const struct xt_tgchk_param *par) ++{ ++ const struct xt_mark_target_info *markinfo = par->targinfo; ++ ++ if (markinfo->mark > 0xffffffff) { ++ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); ++ return false; ++ } ++ return true; ++} ++ ++static bool mark_tg_check_v1(const struct xt_tgchk_param *par) ++{ ++ const struct xt_mark_target_info_v1 *markinfo = par->targinfo; ++ ++ if (markinfo->mode != XT_MARK_SET ++ && markinfo->mode != XT_MARK_AND ++ && markinfo->mode != XT_MARK_OR) { ++ printk(KERN_WARNING "MARK: unknown mode %u\n", ++ markinfo->mode); ++ return false; ++ } ++ if (markinfo->mark > 0xffffffff) { ++ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); ++ return false; ++ } ++ return true; ++} ++ ++#ifdef CONFIG_COMPAT ++struct compat_xt_mark_target_info { ++ compat_ulong_t mark; ++}; ++ ++static void mark_tg_compat_from_user_v0(void *dst, void *src) ++{ ++ const struct compat_xt_mark_target_info *cm = src; ++ struct xt_mark_target_info m = { ++ .mark = cm->mark, ++ }; ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int mark_tg_compat_to_user_v0(void __user *dst, void *src) ++{ ++ const struct xt_mark_target_info *m = src; ++ struct compat_xt_mark_target_info cm = { ++ .mark = m->mark, ++ }; ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++ ++struct compat_xt_mark_target_info_v1 { ++ compat_ulong_t mark; ++ u_int8_t mode; ++ u_int8_t __pad1; ++ u_int16_t __pad2; ++}; ++ ++static void mark_tg_compat_from_user_v1(void *dst, void *src) ++{ ++ const struct compat_xt_mark_target_info_v1 *cm = src; ++ struct xt_mark_target_info_v1 m = { ++ .mark = cm->mark, ++ .mode = cm->mode, ++ }; ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int mark_tg_compat_to_user_v1(void __user *dst, void *src) ++{ ++ const struct xt_mark_target_info_v1 *m = src; ++ struct compat_xt_mark_target_info_v1 cm = { ++ .mark = m->mark, ++ .mode = m->mode, ++ }; ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++#endif /* CONFIG_COMPAT */ ++ ++static struct xt_target mark_tg_reg[] __read_mostly = { ++ { ++ .name = "MARK", ++ .family = NFPROTO_UNSPEC, ++ .revision = 0, ++ .checkentry = mark_tg_check_v0, ++ .target = mark_tg_v0, ++ .targetsize = sizeof(struct xt_mark_target_info), ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_mark_target_info), ++ .compat_from_user = mark_tg_compat_from_user_v0, ++ .compat_to_user = mark_tg_compat_to_user_v0, ++#endif ++ .table = "mangle", ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "MARK", ++ .family = NFPROTO_UNSPEC, ++ .revision = 1, ++ .checkentry = mark_tg_check_v1, ++ .target = mark_tg_v1, ++ .targetsize = sizeof(struct xt_mark_target_info_v1), ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_mark_target_info_v1), ++ .compat_from_user = mark_tg_compat_from_user_v1, ++ .compat_to_user = mark_tg_compat_to_user_v1, ++#endif ++ .table = "mangle", ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "MARK", ++ .revision = 2, ++ .family = NFPROTO_UNSPEC, ++ .target = mark_tg, ++ .targetsize = sizeof(struct xt_mark_tginfo2), ++ .me = THIS_MODULE, ++ }, + }; + + static int __init mark_tg_init(void) + { +- return xt_register_target(&mark_tg_reg); ++ return xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg)); + } + + static void __exit mark_tg_exit(void) + { +- xt_unregister_target(&mark_tg_reg); ++ xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg)); + } + + module_init(mark_tg_init); diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index eda64c1..48d49da 100644 --- a/net/netfilter/xt_TCPMSS.c @@ -77468,6 +78408,353 @@ index eda64c1..48d49da 100644 return false; } #endif +diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c +index 122aa8b..86cacab 100644 +--- a/net/netfilter/xt_connmark.c ++++ b/net/netfilter/xt_connmark.c +@@ -47,6 +47,36 @@ connmark_mt(const struct sk_buff *skb, const struct xt_match_param *par) + return ((ct->mark & info->mask) == info->mark) ^ info->invert; + } + ++static bool ++connmark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct xt_connmark_info *info = par->matchinfo; ++ const struct nf_conn *ct; ++ enum ip_conntrack_info ctinfo; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (!ct) ++ return false; ++ ++ return ((ct->mark & info->mask) == info->mark) ^ info->invert; ++} ++ ++static bool connmark_mt_check_v0(const struct xt_mtchk_param *par) ++{ ++ const struct xt_connmark_info *cm = par->matchinfo; ++ ++ if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { ++ printk(KERN_WARNING "connmark: only support 32bit mark\n"); ++ return false; ++ } ++ if (nf_ct_l3proto_try_module_get(par->family) < 0) { ++ printk(KERN_WARNING "can't load conntrack support for " ++ "proto=%u\n", par->family); ++ return false; ++ } ++ return true; ++} ++ + static bool connmark_mt_check(const struct xt_mtchk_param *par) + { + if (nf_ct_l3proto_try_module_get(par->family) < 0) { +@@ -62,25 +92,74 @@ static void connmark_mt_destroy(const struct xt_mtdtor_param *par) + nf_ct_l3proto_module_put(par->family); + } + +-static struct xt_match connmark_mt_reg __read_mostly = { +- .name = "connmark", +- .revision = 1, +- .family = NFPROTO_UNSPEC, +- .checkentry = connmark_mt_check, +- .match = connmark_mt, +- .matchsize = sizeof(struct xt_connmark_mtinfo1), +- .destroy = connmark_mt_destroy, +- .me = THIS_MODULE, ++#ifdef CONFIG_COMPAT ++struct compat_xt_connmark_info { ++ compat_ulong_t mark, mask; ++ u_int8_t invert; ++ u_int8_t __pad1; ++ u_int16_t __pad2; ++}; ++ ++static void connmark_mt_compat_from_user_v0(void *dst, void *src) ++{ ++ const struct compat_xt_connmark_info *cm = src; ++ struct xt_connmark_info m = { ++ .mark = cm->mark, ++ .mask = cm->mask, ++ .invert = cm->invert, ++ }; ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int connmark_mt_compat_to_user_v0(void __user *dst, void *src) ++{ ++ const struct xt_connmark_info *m = src; ++ struct compat_xt_connmark_info cm = { ++ .mark = m->mark, ++ .mask = m->mask, ++ .invert = m->invert, ++ }; ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++#endif /* CONFIG_COMPAT */ ++ ++static struct xt_match connmark_mt_reg[] __read_mostly = { ++ { ++ .name = "connmark", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_mt_check_v0, ++ .match = connmark_mt_v0, ++ .destroy = connmark_mt_destroy, ++ .matchsize = sizeof(struct xt_connmark_info), ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_connmark_info), ++ .compat_from_user = connmark_mt_compat_from_user_v0, ++ .compat_to_user = connmark_mt_compat_to_user_v0, ++#endif ++ .me = THIS_MODULE ++ }, ++ { ++ .name = "connmark", ++ .revision = 1, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = connmark_mt_check, ++ .match = connmark_mt, ++ .matchsize = sizeof(struct xt_connmark_mtinfo1), ++ .destroy = connmark_mt_destroy, ++ .me = THIS_MODULE, ++ }, + }; + + static int __init connmark_mt_init(void) + { +- return xt_register_match(&connmark_mt_reg); ++ return xt_register_matches(connmark_mt_reg, ++ ARRAY_SIZE(connmark_mt_reg)); + } + + static void __exit connmark_mt_exit(void) + { +- xt_unregister_match(&connmark_mt_reg); ++ xt_unregister_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg)); + } + + module_init(connmark_mt_init); +diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c +index ae66305..30ca13c 100644 +--- a/net/netfilter/xt_conntrack.c ++++ b/net/netfilter/xt_conntrack.c +@@ -25,6 +25,95 @@ MODULE_ALIAS("ipt_conntrack"); + MODULE_ALIAS("ip6t_conntrack"); + + static bool ++conntrack_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct xt_conntrack_info *sinfo = par->matchinfo; ++ const struct nf_conn *ct; ++ enum ip_conntrack_info ctinfo; ++ unsigned int statebit; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ ++#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & (invflg))) ++ ++ if (ct == &nf_conntrack_untracked) ++ statebit = XT_CONNTRACK_STATE_UNTRACKED; ++ else if (ct) ++ statebit = XT_CONNTRACK_STATE_BIT(ctinfo); ++ else ++ statebit = XT_CONNTRACK_STATE_INVALID; ++ ++ if (sinfo->flags & XT_CONNTRACK_STATE) { ++ if (ct) { ++ if (test_bit(IPS_SRC_NAT_BIT, &ct->status)) ++ statebit |= XT_CONNTRACK_STATE_SNAT; ++ if (test_bit(IPS_DST_NAT_BIT, &ct->status)) ++ statebit |= XT_CONNTRACK_STATE_DNAT; ++ } ++ if (FWINV((statebit & sinfo->statemask) == 0, ++ XT_CONNTRACK_STATE)) ++ return false; ++ } ++ ++ if (ct == NULL) { ++ if (sinfo->flags & ~XT_CONNTRACK_STATE) ++ return false; ++ return true; ++ } ++ ++ if (sinfo->flags & XT_CONNTRACK_PROTO && ++ FWINV(nf_ct_protonum(ct) != ++ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, ++ XT_CONNTRACK_PROTO)) ++ return false; ++ ++ if (sinfo->flags & XT_CONNTRACK_ORIGSRC && ++ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip & ++ sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != ++ sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, ++ XT_CONNTRACK_ORIGSRC)) ++ return false; ++ ++ if (sinfo->flags & XT_CONNTRACK_ORIGDST && ++ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip & ++ sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != ++ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, ++ XT_CONNTRACK_ORIGDST)) ++ return false; ++ ++ if (sinfo->flags & XT_CONNTRACK_REPLSRC && ++ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip & ++ sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != ++ sinfo->tuple[IP_CT_DIR_REPLY].src.ip, ++ XT_CONNTRACK_REPLSRC)) ++ return false; ++ ++ if (sinfo->flags & XT_CONNTRACK_REPLDST && ++ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip & ++ sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != ++ sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, ++ XT_CONNTRACK_REPLDST)) ++ return false; ++ ++ if (sinfo->flags & XT_CONNTRACK_STATUS && ++ FWINV((ct->status & sinfo->statusmask) == 0, ++ XT_CONNTRACK_STATUS)) ++ return false; ++ ++ if(sinfo->flags & XT_CONNTRACK_EXPIRES) { ++ unsigned long expires = timer_pending(&ct->timeout) ? ++ (ct->timeout.expires - jiffies)/HZ : 0; ++ ++ if (FWINV(!(expires >= sinfo->expires_min && ++ expires <= sinfo->expires_max), ++ XT_CONNTRACK_EXPIRES)) ++ return false; ++ } ++ return true; ++#undef FWINV ++} ++ ++static bool + conntrack_addrcmp(const union nf_inet_addr *kaddr, + const union nf_inet_addr *uaddr, + const union nf_inet_addr *umask, unsigned int l3proto) +@@ -112,6 +201,55 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, + return true; + } + ++#ifdef CONFIG_COMPAT ++struct compat_xt_conntrack_info ++{ ++ compat_uint_t statemask; ++ compat_uint_t statusmask; ++ struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; ++ struct in_addr sipmsk[IP_CT_DIR_MAX]; ++ struct in_addr dipmsk[IP_CT_DIR_MAX]; ++ compat_ulong_t expires_min; ++ compat_ulong_t expires_max; ++ u_int8_t flags; ++ u_int8_t invflags; ++}; ++ ++static void conntrack_mt_compat_from_user_v0(void *dst, void *src) ++{ ++ const struct compat_xt_conntrack_info *cm = src; ++ struct xt_conntrack_info m = { ++ .statemask = cm->statemask, ++ .statusmask = cm->statusmask, ++ .expires_min = cm->expires_min, ++ .expires_max = cm->expires_max, ++ .flags = cm->flags, ++ .invflags = cm->invflags, ++ }; ++ memcpy(m.tuple, cm->tuple, sizeof(m.tuple)); ++ memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk)); ++ memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk)); ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int conntrack_mt_compat_to_user_v0(void __user *dst, void *src) ++{ ++ const struct xt_conntrack_info *m = src; ++ struct compat_xt_conntrack_info cm = { ++ .statemask = m->statemask, ++ .statusmask = m->statusmask, ++ .expires_min = m->expires_min, ++ .expires_max = m->expires_max, ++ .flags = m->flags, ++ .invflags = m->invflags, ++ }; ++ memcpy(cm.tuple, m->tuple, sizeof(cm.tuple)); ++ memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk)); ++ memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk)); ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++#endif ++ + static bool + conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par, + u16 state_mask, u16 status_mask) +@@ -224,6 +362,21 @@ static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) + static struct xt_match conntrack_mt_reg[] __read_mostly = { + { + .name = "conntrack", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .match = conntrack_mt_v0, ++ .checkentry = conntrack_mt_check, ++ .destroy = conntrack_mt_destroy, ++ .matchsize = sizeof(struct xt_conntrack_info), ++ .me = THIS_MODULE, ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_conntrack_info), ++ .compat_from_user = conntrack_mt_compat_from_user_v0, ++ .compat_to_user = conntrack_mt_compat_to_user_v0, ++#endif ++ }, ++ { ++ .name = "conntrack", + .revision = 1, + .family = NFPROTO_UNSPEC, + .matchsize = sizeof(struct xt_conntrack_mtinfo1), +diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c +index 0280d3a..c3f8085 100644 +--- a/net/netfilter/xt_dscp.c ++++ b/net/netfilter/xt_dscp.c +@@ -15,6 +15,7 @@ + + #include + #include ++#include + + MODULE_AUTHOR("Harald Welte "); + MODULE_DESCRIPTION("Xtables: DSCP/TOS field match"); +@@ -54,6 +55,14 @@ static bool dscp_mt_check(const struct xt_mtchk_param *par) + return true; + } + ++static bool ++tos_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct ipt_tos_info *info = par->matchinfo; ++ ++ return (ip_hdr(skb)->tos == info->tos) ^ info->invert; ++} ++ + static bool tos_mt(const struct sk_buff *skb, const struct xt_match_param *par) + { + const struct xt_tos_match_info *info = par->matchinfo; +@@ -85,6 +94,14 @@ static struct xt_match dscp_mt_reg[] __read_mostly = { + }, + { + .name = "tos", ++ .revision = 0, ++ .family = NFPROTO_IPV4, ++ .match = tos_mt_v0, ++ .matchsize = sizeof(struct ipt_tos_info), ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "tos", + .revision = 1, + .family = NFPROTO_IPV4, + .match = tos_mt, diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index dd16e40..72e297b 100644 --- a/net/netfilter/xt_hashlimit.c @@ -77667,6 +78954,66 @@ index dd16e40..72e297b 100644 kmem_cache_destroy(hashlimit_cachep); xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); } +diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c +index ffc9638..5450cda 100644 +--- a/net/netfilter/xt_iprange.c ++++ b/net/netfilter/xt_iprange.c +@@ -14,6 +14,40 @@ + #include + #include + #include ++#include ++ ++static bool ++iprange_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct ipt_iprange_info *info = par->matchinfo; ++ const struct iphdr *iph = ip_hdr(skb); ++ ++ if (info->flags & IPRANGE_SRC) { ++ if ((ntohl(iph->saddr) < ntohl(info->src.min_ip) ++ || ntohl(iph->saddr) > ntohl(info->src.max_ip)) ++ ^ !!(info->flags & IPRANGE_SRC_INV)) { ++ pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n", ++ &iph->saddr, ++ info->flags & IPRANGE_SRC_INV ? "(INV) " : "", ++ &info->src.min_ip, ++ &info->src.max_ip); ++ return false; ++ } ++ } ++ if (info->flags & IPRANGE_DST) { ++ if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip) ++ || ntohl(iph->daddr) > ntohl(info->dst.max_ip)) ++ ^ !!(info->flags & IPRANGE_DST_INV)) { ++ pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n", ++ &iph->daddr, ++ info->flags & IPRANGE_DST_INV ? "(INV) " : "", ++ &info->dst.min_ip, ++ &info->dst.max_ip); ++ return false; ++ } ++ } ++ return true; ++} + + static bool + iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par) +@@ -93,6 +127,14 @@ iprange_mt6(const struct sk_buff *skb, const struct xt_match_param *par) + static struct xt_match iprange_mt_reg[] __read_mostly = { + { + .name = "iprange", ++ .revision = 0, ++ .family = NFPROTO_IPV4, ++ .match = iprange_mt_v0, ++ .matchsize = sizeof(struct ipt_iprange_info), ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "iprange", + .revision = 1, + .family = NFPROTO_IPV4, + .match = iprange_mt4, diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 2773be6..847f081 100644 --- a/net/netfilter/xt_limit.c @@ -77680,8 +79027,271 @@ index 2773be6..847f081 100644 r->avg, r->burst); return false; } +diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c +index 1db07d8..0c17eca 100644 +--- a/net/netfilter/xt_mark.c ++++ b/net/netfilter/xt_mark.c +@@ -23,6 +23,14 @@ MODULE_ALIAS("ipt_mark"); + MODULE_ALIAS("ip6t_mark"); + + static bool ++mark_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct xt_mark_info *info = par->matchinfo; ++ ++ return ((skb->mark & info->mask) == info->mark) ^ info->invert; ++} ++ ++static bool + mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) + { + const struct xt_mark_mtinfo1 *info = par->matchinfo; +@@ -30,23 +38,81 @@ mark_mt(const struct sk_buff *skb, const struct xt_match_param *par) + return ((skb->mark & info->mask) == info->mark) ^ info->invert; + } + +-static struct xt_match mark_mt_reg __read_mostly = { +- .name = "mark", +- .revision = 1, +- .family = NFPROTO_UNSPEC, +- .match = mark_mt, +- .matchsize = sizeof(struct xt_mark_mtinfo1), +- .me = THIS_MODULE, ++static bool mark_mt_check_v0(const struct xt_mtchk_param *par) ++{ ++ const struct xt_mark_info *minfo = par->matchinfo; ++ ++ if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { ++ printk(KERN_WARNING "mark: only supports 32bit mark\n"); ++ return false; ++ } ++ return true; ++} ++ ++#ifdef CONFIG_COMPAT ++struct compat_xt_mark_info { ++ compat_ulong_t mark, mask; ++ u_int8_t invert; ++ u_int8_t __pad1; ++ u_int16_t __pad2; ++}; ++ ++static void mark_mt_compat_from_user_v0(void *dst, void *src) ++{ ++ const struct compat_xt_mark_info *cm = src; ++ struct xt_mark_info m = { ++ .mark = cm->mark, ++ .mask = cm->mask, ++ .invert = cm->invert, ++ }; ++ memcpy(dst, &m, sizeof(m)); ++} ++ ++static int mark_mt_compat_to_user_v0(void __user *dst, void *src) ++{ ++ const struct xt_mark_info *m = src; ++ struct compat_xt_mark_info cm = { ++ .mark = m->mark, ++ .mask = m->mask, ++ .invert = m->invert, ++ }; ++ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; ++} ++#endif /* CONFIG_COMPAT */ ++ ++static struct xt_match mark_mt_reg[] __read_mostly = { ++ { ++ .name = "mark", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .checkentry = mark_mt_check_v0, ++ .match = mark_mt_v0, ++ .matchsize = sizeof(struct xt_mark_info), ++#ifdef CONFIG_COMPAT ++ .compatsize = sizeof(struct compat_xt_mark_info), ++ .compat_from_user = mark_mt_compat_from_user_v0, ++ .compat_to_user = mark_mt_compat_to_user_v0, ++#endif ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "mark", ++ .revision = 1, ++ .family = NFPROTO_UNSPEC, ++ .match = mark_mt, ++ .matchsize = sizeof(struct xt_mark_mtinfo1), ++ .me = THIS_MODULE, ++ }, + }; + + static int __init mark_mt_init(void) + { +- return xt_register_match(&mark_mt_reg); ++ return xt_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg)); + } + + static void __exit mark_mt_exit(void) + { +- xt_unregister_match(&mark_mt_reg); ++ xt_unregister_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg)); + } + + module_init(mark_mt_init); +diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c +index d24c76d..79d6a0b 100644 +--- a/net/netfilter/xt_owner.c ++++ b/net/netfilter/xt_owner.c +@@ -16,6 +16,60 @@ + #include + #include + #include ++#include ++#include ++ ++static bool ++owner_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct ipt_owner_info *info = par->matchinfo; ++ const struct file *filp; ++ ++ if (skb->sk == NULL || skb->sk->sk_socket == NULL) ++ return false; ++ ++ filp = skb->sk->sk_socket->file; ++ if (filp == NULL) ++ return false; ++ ++ if (info->match & IPT_OWNER_UID) ++ if ((filp->f_cred->fsuid != info->uid) ^ ++ !!(info->invert & IPT_OWNER_UID)) ++ return false; ++ ++ if (info->match & IPT_OWNER_GID) ++ if ((filp->f_cred->fsgid != info->gid) ^ ++ !!(info->invert & IPT_OWNER_GID)) ++ return false; ++ ++ return true; ++} ++ ++static bool ++owner_mt6_v0(const struct sk_buff *skb, const struct xt_match_param *par) ++{ ++ const struct ip6t_owner_info *info = par->matchinfo; ++ const struct file *filp; ++ ++ if (skb->sk == NULL || skb->sk->sk_socket == NULL) ++ return false; ++ ++ filp = skb->sk->sk_socket->file; ++ if (filp == NULL) ++ return false; ++ ++ if (info->match & IP6T_OWNER_UID) ++ if ((filp->f_cred->fsuid != info->uid) ^ ++ !!(info->invert & IP6T_OWNER_UID)) ++ return false; ++ ++ if (info->match & IP6T_OWNER_GID) ++ if ((filp->f_cred->fsgid != info->gid) ^ ++ !!(info->invert & IP6T_OWNER_GID)) ++ return false; ++ ++ return true; ++} + + static bool + owner_mt(const struct sk_buff *skb, const struct xt_match_param *par) +@@ -52,25 +106,76 @@ owner_mt(const struct sk_buff *skb, const struct xt_match_param *par) + return true; + } + +-static struct xt_match owner_mt_reg __read_mostly = { +- .name = "owner", +- .revision = 1, +- .family = NFPROTO_UNSPEC, +- .match = owner_mt, +- .matchsize = sizeof(struct xt_owner_match_info), +- .hooks = (1 << NF_INET_LOCAL_OUT) | +- (1 << NF_INET_POST_ROUTING), +- .me = THIS_MODULE, ++static bool owner_mt_check_v0(const struct xt_mtchk_param *par) ++{ ++ const struct ipt_owner_info *info = par->matchinfo; ++ ++ if (info->match & (IPT_OWNER_PID | IPT_OWNER_SID | IPT_OWNER_COMM)) { ++ printk(KERN_WARNING KBUILD_MODNAME ++ ": PID, SID and command matching is not " ++ "supported anymore\n"); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool owner_mt6_check_v0(const struct xt_mtchk_param *par) ++{ ++ const struct ip6t_owner_info *info = par->matchinfo; ++ ++ if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) { ++ printk(KERN_WARNING KBUILD_MODNAME ++ ": PID and SID matching is not supported anymore\n"); ++ return false; ++ } ++ ++ return true; ++} ++ ++static struct xt_match owner_mt_reg[] __read_mostly = { ++ { ++ .name = "owner", ++ .revision = 0, ++ .family = NFPROTO_IPV4, ++ .match = owner_mt_v0, ++ .matchsize = sizeof(struct ipt_owner_info), ++ .checkentry = owner_mt_check_v0, ++ .hooks = (1 << NF_INET_LOCAL_OUT) | ++ (1 << NF_INET_POST_ROUTING), ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "owner", ++ .revision = 0, ++ .family = NFPROTO_IPV6, ++ .match = owner_mt6_v0, ++ .matchsize = sizeof(struct ip6t_owner_info), ++ .checkentry = owner_mt6_check_v0, ++ .hooks = (1 << NF_INET_LOCAL_OUT) | ++ (1 << NF_INET_POST_ROUTING), ++ .me = THIS_MODULE, ++ }, ++ { ++ .name = "owner", ++ .revision = 1, ++ .family = NFPROTO_UNSPEC, ++ .match = owner_mt, ++ .matchsize = sizeof(struct xt_owner_match_info), ++ .hooks = (1 << NF_INET_LOCAL_OUT) | ++ (1 << NF_INET_POST_ROUTING), ++ .me = THIS_MODULE, ++ }, + }; + + static int __init owner_mt_init(void) + { +- return xt_register_match(&owner_mt_reg); ++ return xt_register_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg)); + } + + static void __exit owner_mt_exit(void) + { +- xt_unregister_match(&owner_mt_reg); ++ xt_unregister_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg)); + } + + module_init(owner_mt_init); diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c -index 1a3b650..af6515a 100644 +index 2f181aa..3499fb2 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -17,6 +17,8 @@ @@ -78533,10 +80143,10 @@ index 38829e2..fad3e2b 100644 +} +#endif diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c -index 49278f8..61705dd 100644 +index 27a2378..93cb0c5 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c -@@ -1026,6 +1026,7 @@ static struct file_system_type rpc_pipe_fs_type = { +@@ -1028,6 +1028,7 @@ static struct file_system_type rpc_pipe_fs_type = { .name = "rpc_pipefs", .get_sb = rpc_get_sb, .kill_sb = kill_litter_super,