diff options
Diffstat (limited to 'main/linux-grsec')
-rw-r--r-- | main/linux-grsec/APKBUILD | 10 | ||||
-rw-r--r-- | main/linux-grsec/grsecurity-3.0-3.14.8-201406222110.patch (renamed from main/linux-grsec/grsecurity-3.0-3.14.8-201406191347.patch) | 644 |
2 files changed, 379 insertions, 275 deletions
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD index c6bc0e6215..8a7b82a8e1 100644 --- a/main/linux-grsec/APKBUILD +++ b/main/linux-grsec/APKBUILD @@ -7,7 +7,7 @@ case $pkgver in *.*.*) _kernver=${pkgver%.*};; *.*) _kernver=${pkgver};; esac -pkgrel=0 +pkgrel=1 pkgdesc="Linux kernel with grsecurity" url=http://grsecurity.net depends="mkinitfs linux-firmware" @@ -17,7 +17,7 @@ _config=${config:-kernelconfig.${CARCH}} install= source="http://ftp.kernel.org/pub/linux/kernel/v3.x/linux-$_kernver.tar.xz http://ftp.kernel.org/pub/linux/kernel/v3.x/patch-$pkgver.xz - grsecurity-3.0-3.14.8-201406191347.patch + grsecurity-3.0-3.14.8-201406222110.patch fix-memory-map-for-PIE-applications.patch imx6q-no-unclocked-sleep.patch @@ -166,7 +166,7 @@ dev() { md5sums="b621207b3f6ecbb67db18b13258f8ea8 linux-3.14.tar.xz f612535d2c5d954b5e885757c387ae54 patch-3.14.8.xz -f97092de8a6fa522ab9c8c510299274a grsecurity-3.0-3.14.8-201406191347.patch +a0519c8c05be0bf6a06e9c4b8fba680b grsecurity-3.0-3.14.8-201406222110.patch c6a4ae7e8ca6159e1631545515805216 fix-memory-map-for-PIE-applications.patch 1a307fc1d63231bf01d22493a4f14378 imx6q-no-unclocked-sleep.patch 83f0e1b1d2413bcb2dddcf87a10dc42b kernelconfig.x86 @@ -174,7 +174,7 @@ c6a4ae7e8ca6159e1631545515805216 fix-memory-map-for-PIE-applications.patch 887980f603af6a1ac6f67edeae2e0d07 kernelconfig.armhf" sha256sums="61558aa490855f42b6340d1a1596be47454909629327c49a5e4e10268065dffa linux-3.14.tar.xz 0edab0f772836162e5e57ef294d83e88153c15a12f394914c6a25b49e408e8f1 patch-3.14.8.xz -aa9d8c11e1c1790e71088ae0a6494b8e44b0734f8e5d4fdeb9b98e0c77427406 grsecurity-3.0-3.14.8-201406191347.patch +8acb478a24bd57145dc1524d8f2e4e1b9cc0de652b373a1eb9535e0c41385949 grsecurity-3.0-3.14.8-201406222110.patch 500f3577310be52e87b9fecdc2e9c4ca43210fd97d69089f9005d484563f74c7 fix-memory-map-for-PIE-applications.patch 21179fbb22a5b74af0a609350ae1a170e232908572b201d02e791d2ce0a685d3 imx6q-no-unclocked-sleep.patch 5431d66b9c1af413b4dc6f91de00a6e830e3d780a79c5f85d2d8b013b151c169 kernelconfig.x86 @@ -182,7 +182,7 @@ aa9d8c11e1c1790e71088ae0a6494b8e44b0734f8e5d4fdeb9b98e0c77427406 grsecurity-3.0 ab3e07f85f4dd090b2d22b485881031bd479a1c34fc9a2e9707cb8cdebfcfda4 kernelconfig.armhf" sha512sums="5730d83a7a81134c1e77c0bf89e42dee4f8251ad56c1ac2be20c59e26fdfaa7bea55f277e7af156b637f22e1584914a46089af85039177cb43485089c74ac26e linux-3.14.tar.xz a71fdb5391d664ecccef6602df638588e6202992415a788ad85fab9878ec6b76034c37de824069cfc6d6d502a1fab0eba98c69170f410d28951335e19d94db72 patch-3.14.8.xz -4e9c3e5e6be903cf523160d161633fbe0cbc17d0cb4c67284a5c8c82ca999c46b84bcade802425e25c572256fc016169679507f1ca0cd801c2197cc7b6caa2e6 grsecurity-3.0-3.14.8-201406191347.patch +4a8ef5cc67205d12721e40738551672afc6d1041509143969b043da476afdac09cc39a468ddb511bda8c1cc376c3c336d33e4333eebea773831b28b637c66099 grsecurity-3.0-3.14.8-201406222110.patch 4665c56ae1bbac311f9205d64918e84ee8b01d47d6e2396ff6b8adfb10aada7f7254531ce62e31edbb65c2a54a830f09ad05d314dfcd75d6272f4068945ad7c7 fix-memory-map-for-PIE-applications.patch 87d1ad59732f265a5b0db54490dc1762c14ea4b868e7eb1aedc3ce57b48046de7bbc08cf5cfcf6f1380fa84063b0edb16ba3d5e3c5670be9bbb229275c88b221 imx6q-no-unclocked-sleep.patch 03f817222bf5812fa8363542e4ab108767212c67efe3994ea8fe9d0751215d9c3f166ce41de41f9070c855db6c04606828dc61265a1738920b984a24077347c4 kernelconfig.x86 diff --git a/main/linux-grsec/grsecurity-3.0-3.14.8-201406191347.patch b/main/linux-grsec/grsecurity-3.0-3.14.8-201406222110.patch index cf0e6f3646..aeeb2f060e 100644 --- a/main/linux-grsec/grsecurity-3.0-3.14.8-201406191347.patch +++ b/main/linux-grsec/grsecurity-3.0-3.14.8-201406222110.patch @@ -6739,18 +6739,18 @@ index 25da651..ae2a259 100644 #endif /* __ASM_SMTC_PROC_H */ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h -index e80ae50..4404147 100644 +index e80ae50..b93dd2e 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h -@@ -116,6 +116,8 @@ static inline struct thread_info *current_thread_info(void) - #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ - #define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */ - #define TIF_32BIT_FPREGS 27 /* 32-bit floating point registers */ +@@ -105,6 +105,8 @@ static inline struct thread_info *current_thread_info(void) + #define TIF_SECCOMP 4 /* secure computing */ + #define TIF_NOTIFY_RESUME 5 /* callback before returning to user */ + #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ +/* li takes a 32bit immediate */ -+#define TIF_GRSEC_SETXID 29 /* update credentials on syscall entry/exit */ - #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ - - #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) ++#define TIF_GRSEC_SETXID 10 /* update credentials on syscall entry/exit */ + #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ + #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ + #define TIF_NOHZ 19 /* in adaptive nohz mode */ @@ -134,14 +136,15 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH) #define _TIF_32BIT_FPREGS (1<<TIF_32BIT_FPREGS) @@ -17682,7 +17682,7 @@ index 86f9301..b365cda 100644 void unregister_nmi_handler(unsigned int, const char *); diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h -index 775873d..de5f0304 100644 +index 775873d..04cd306 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -52,6 +52,7 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr, @@ -17693,6 +17693,29 @@ index 775873d..de5f0304 100644 #define __boot_va(x) __va(x) #define __boot_pa(x) __pa(x) +@@ -60,11 +61,21 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr, + * virt_to_page(kaddr) returns a valid pointer if and only if + * virt_addr_valid(kaddr) returns true. + */ +-#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) + #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + extern bool __virt_addr_valid(unsigned long kaddr); + #define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr)) + ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++#define virt_to_page(kaddr) \ ++ ({ \ ++ const void *__kaddr = (const void *)(kaddr); \ ++ BUG_ON(!virt_addr_valid(__kaddr)); \ ++ pfn_to_page(__pa(__kaddr) >> PAGE_SHIFT); \ ++ }) ++#else ++#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) ++#endif ++ + #endif /* __ASSEMBLY__ */ + + #include <asm-generic/memory_model.h> diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h index 0f1ddee..e2fc3d1 100644 --- a/arch/x86/include/asm/page_64.h @@ -61696,11 +61719,15 @@ index d19b30a..ef89c36 100644 static int can_do_hugetlb_shm(void) { diff --git a/fs/inode.c b/fs/inode.c -index e846a32..6b22e15 100644 +index e846a32..bb06bd0 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -841,8 +841,8 @@ unsigned int get_next_ino(void) +@@ -839,16 +839,20 @@ unsigned int get_next_ino(void) + unsigned int *p = &get_cpu_var(last_ino); + unsigned int res = *p; ++start: ++ #ifdef CONFIG_SMP if (unlikely((res & (LAST_INO_BATCH-1)) == 0)) { - static atomic_t shared_last_ino; @@ -61710,6 +61737,15 @@ index e846a32..6b22e15 100644 res = next - LAST_INO_BATCH; } + #endif + +- *p = ++res; ++ if (unlikely(!++res)) ++ goto start; /* never zero */ ++ *p = res; + put_cpu_var(last_ino); + return res; + } diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 4a6cf28..d3a29d3 100644 --- a/fs/jffs2/erase.c @@ -82226,8 +82262,33 @@ index b66c211..13d2915 100644 static inline void anon_vma_merge(struct vm_area_struct *vma, struct vm_area_struct *next) +diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h +index a964f72..b475afb 100644 +--- a/include/linux/scatterlist.h ++++ b/include/linux/scatterlist.h +@@ -1,6 +1,7 @@ + #ifndef _LINUX_SCATTERLIST_H + #define _LINUX_SCATTERLIST_H + ++#include <linux/sched.h> + #include <linux/string.h> + #include <linux/bug.h> + #include <linux/mm.h> +@@ -114,6 +115,12 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, + #ifdef CONFIG_DEBUG_SG + BUG_ON(!virt_addr_valid(buf)); + #endif ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ if (object_starts_on_stack(buf)) { ++ void *adjbuf = buf - current->stack + current->lowmem_stack; ++ sg_set_page(sg, virt_to_page(adjbuf), buflen, offset_in_page(adjbuf)); ++ } else ++#endif + sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); + } + diff --git a/include/linux/sched.h b/include/linux/sched.h -index ccd0c6f..39c28a4 100644 +index ccd0c6f..84d9030 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -129,6 +129,7 @@ struct fs_struct; @@ -82318,7 +82379,17 @@ index ccd0c6f..39c28a4 100644 extern int uids_sysfs_init(void); -@@ -1286,8 +1319,8 @@ struct task_struct { +@@ -1164,6 +1197,9 @@ enum perf_event_task_context { + struct task_struct { + volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ + void *stack; ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ void *lowmem_stack; ++#endif + atomic_t usage; + unsigned int flags; /* per process flags, defined below */ + unsigned int ptrace; +@@ -1286,8 +1322,8 @@ struct task_struct { struct list_head thread_node; struct completion *vfork_done; /* for vfork() */ @@ -82329,7 +82400,7 @@ index ccd0c6f..39c28a4 100644 cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; -@@ -1312,11 +1345,6 @@ struct task_struct { +@@ -1312,11 +1348,6 @@ struct task_struct { struct task_cputime cputime_expires; struct list_head cpu_timers[3]; @@ -82341,7 +82412,7 @@ index ccd0c6f..39c28a4 100644 char comm[TASK_COMM_LEN]; /* executable name excluding path - access with [gs]et_task_comm (which lock it with task_lock()) -@@ -1333,6 +1361,10 @@ struct task_struct { +@@ -1333,6 +1364,10 @@ struct task_struct { #endif /* CPU-specific state of this task */ struct thread_struct thread; @@ -82352,7 +82423,7 @@ index ccd0c6f..39c28a4 100644 /* filesystem information */ struct fs_struct *fs; /* open file information */ -@@ -1409,6 +1441,10 @@ struct task_struct { +@@ -1409,6 +1444,10 @@ struct task_struct { gfp_t lockdep_reclaim_gfp; #endif @@ -82363,7 +82434,7 @@ index ccd0c6f..39c28a4 100644 /* journalling filesystem info */ void *journal_info; -@@ -1447,6 +1483,10 @@ struct task_struct { +@@ -1447,6 +1486,10 @@ struct task_struct { /* cg_list protected by css_set_lock and tsk->alloc_lock */ struct list_head cg_list; #endif @@ -82374,7 +82445,7 @@ index ccd0c6f..39c28a4 100644 #ifdef CONFIG_FUTEX struct robust_list_head __user *robust_list; #ifdef CONFIG_COMPAT -@@ -1581,7 +1621,78 @@ struct task_struct { +@@ -1581,7 +1624,78 @@ struct task_struct { unsigned int sequential_io; unsigned int sequential_io_avg; #endif @@ -82454,7 +82525,7 @@ index ccd0c6f..39c28a4 100644 /* Future-safe accessor for struct task_struct's cpus_allowed. */ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) -@@ -1658,7 +1769,7 @@ struct pid_namespace; +@@ -1658,7 +1772,7 @@ struct pid_namespace; pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, struct pid_namespace *ns); @@ -82463,7 +82534,7 @@ index ccd0c6f..39c28a4 100644 { return tsk->pid; } -@@ -2006,6 +2117,25 @@ extern u64 sched_clock_cpu(int cpu); +@@ -2006,6 +2120,25 @@ extern u64 sched_clock_cpu(int cpu); extern void sched_clock_init(void); @@ -82489,7 +82560,7 @@ index ccd0c6f..39c28a4 100644 #ifndef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK static inline void sched_clock_tick(void) { -@@ -2130,7 +2260,9 @@ void yield(void); +@@ -2130,7 +2263,9 @@ void yield(void); extern struct exec_domain default_exec_domain; union thread_union { @@ -82499,7 +82570,7 @@ index ccd0c6f..39c28a4 100644 unsigned long stack[THREAD_SIZE/sizeof(long)]; }; -@@ -2163,6 +2295,7 @@ extern struct pid_namespace init_pid_ns; +@@ -2163,6 +2298,7 @@ extern struct pid_namespace init_pid_ns; */ extern struct task_struct *find_task_by_vpid(pid_t nr); @@ -82507,7 +82578,7 @@ index ccd0c6f..39c28a4 100644 extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns); -@@ -2325,7 +2458,7 @@ extern void __cleanup_sighand(struct sighand_struct *); +@@ -2325,7 +2461,7 @@ extern void __cleanup_sighand(struct sighand_struct *); extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); @@ -82516,12 +82587,12 @@ index ccd0c6f..39c28a4 100644 extern int allow_signal(int); extern int disallow_signal(int); -@@ -2526,9 +2659,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) +@@ -2526,9 +2662,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) #endif -static inline int object_is_on_stack(void *obj) -+static inline int object_starts_on_stack(void *obj) ++static inline int object_starts_on_stack(const void *obj) { - void *stack = task_stack_page(current); + const void *stack = task_stack_page(current); @@ -83470,7 +83541,7 @@ index 502073a..a7de024 100644 #endif #endif /* _LINUX_VGA_SWITCHEROO_H_ */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h -index 4b8a891..05f2361 100644 +index 4b8a891..e9a2863 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -16,6 +16,11 @@ struct vm_area_struct; /* vma defining user mapping in mm_types.h */ @@ -83485,15 +83556,18 @@ index 4b8a891..05f2361 100644 /* bits [20..32] reserved for arch specific ioremap internals */ /* -@@ -72,6 +77,7 @@ extern void *vzalloc_node(unsigned long size, int node); - extern void *vmalloc_exec(unsigned long size); - extern void *vmalloc_32(unsigned long size); - extern void *vmalloc_32_user(unsigned long size); -+extern void *vmalloc_stack(int node); - extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); - extern void *__vmalloc_node_range(unsigned long size, unsigned long align, - unsigned long start, unsigned long end, gfp_t gfp_mask, -@@ -142,7 +148,7 @@ extern void free_vm_area(struct vm_struct *area); +@@ -82,6 +87,10 @@ extern void *vmap(struct page **pages, unsigned int count, + unsigned long flags, pgprot_t prot); + extern void vunmap(const void *addr); + ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++extern void unmap_process_stacks(struct task_struct *task); ++#endif ++ + extern int remap_vmalloc_range_partial(struct vm_area_struct *vma, + unsigned long uaddr, void *kaddr, + unsigned long size); +@@ -142,7 +151,7 @@ extern void free_vm_area(struct vm_struct *area); /* for /dev/kmem */ extern long vread(char *buf, char *addr, unsigned long count); @@ -86582,49 +86656,112 @@ index 81b3d67..ef189a4 100644 { struct signal_struct *sig = current->signal; diff --git a/kernel/fork.c b/kernel/fork.c -index a17621c..d9e4b37 100644 +index a17621c..2a89549 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -137,6 +137,18 @@ void __weak arch_release_thread_info(struct thread_info *ti) - { - } +@@ -180,6 +180,48 @@ void thread_info_cache_init(void) + # endif + #endif +#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW -+static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, -+ int node) ++static inline struct thread_info *gr_alloc_thread_info_node(struct task_struct *tsk, ++ int node, void **lowmem_stack) +{ -+ return vmalloc_stack(node); ++ struct page *pages[THREAD_SIZE / PAGE_SIZE]; ++ void *ret = NULL; ++ unsigned int i; ++ ++ *lowmem_stack = alloc_thread_info_node(tsk, node); ++ if (*lowmem_stack == NULL) ++ goto out; ++ ++ for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++) ++ pages[i] = virt_to_page(*lowmem_stack + (i * PAGE_SIZE)); ++ ++ /* use VM_IOREMAP to gain THREAD_SIZE alignment */ ++ ret = vmap(pages, THREAD_SIZE / PAGE_SIZE, VM_IOREMAP, PAGE_KERNEL); ++ if (ret == NULL) { ++ free_thread_info(*lowmem_stack); ++ *lowmem_stack = NULL; ++ } ++ ++out: ++ return ret; +} + -+static inline void free_thread_info(struct thread_info *ti) ++static inline void gr_free_thread_info(struct task_struct *tsk, struct thread_info *ti) +{ -+ vfree(ti); ++ unmap_process_stacks(tsk); +} +#else - #ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR - - /* -@@ -179,6 +191,7 @@ void thread_info_cache_init(void) - } - # endif - #endif ++static inline struct thread_info *gr_alloc_thread_info_node(struct task_struct *tsk, ++ int node, void **lowmem_stack) ++{ ++ return alloc_thread_info_node(tsk, node); ++} ++static inline void gr_free_thread_info(struct task_struct *tsk, struct thread_info *ti) ++{ ++ free_thread_info(ti); ++} +#endif - ++ /* SLAB cache for signal_struct structures (tsk->signal) */ static struct kmem_cache *signal_cachep; -@@ -200,9 +213,11 @@ static struct kmem_cache *mm_cachep; - static void account_kernel_stack(struct thread_info *ti, int account) +@@ -198,18 +240,22 @@ struct kmem_cache *vm_area_cachep; + /* SLAB cache for mm_struct structures (tsk->mm) */ + static struct kmem_cache *mm_cachep; + +-static void account_kernel_stack(struct thread_info *ti, int account) ++static void account_kernel_stack(struct task_struct *tsk, struct thread_info *ti, int account) { -+#ifndef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ struct zone *zone = page_zone(virt_to_page(tsk->lowmem_stack)); ++#else struct zone *zone = page_zone(virt_to_page(ti)); ++#endif mod_zone_page_state(zone, NR_KERNEL_STACK, account); -+#endif } void free_task(struct task_struct *tsk) -@@ -319,7 +334,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + { +- account_kernel_stack(tsk->stack, -1); ++ account_kernel_stack(tsk, tsk->stack, -1); + arch_release_thread_info(tsk->stack); +- free_thread_info(tsk->stack); ++ gr_free_thread_info(tsk, tsk->stack); + rt_mutex_debug_task_free(tsk); + ftrace_graph_exit_task(tsk); + put_seccomp_filter(tsk); +@@ -295,6 +341,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + struct task_struct *tsk; + struct thread_info *ti; + unsigned long *stackend; ++ void *lowmem_stack; + int node = tsk_fork_get_node(orig); + int err; + +@@ -302,7 +349,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + if (!tsk) + return NULL; + +- ti = alloc_thread_info_node(tsk, node); ++ ti = gr_alloc_thread_info_node(tsk, node, &lowmem_stack); + if (!ti) + goto free_tsk; + +@@ -311,6 +358,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + goto free_ti; + + tsk->stack = ti; ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ tsk->lowmem_stack = lowmem_stack; ++#endif + + setup_thread_stack(tsk, orig); + clear_user_return_notifier(tsk); +@@ -319,7 +369,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) *stackend = STACK_END_MAGIC; /* for overflow detection */ #ifdef CONFIG_CC_STACKPROTECTOR @@ -86633,7 +86770,21 @@ index a17621c..d9e4b37 100644 #endif /* -@@ -345,12 +360,80 @@ free_tsk: +@@ -333,24 +383,92 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) + tsk->splice_pipe = NULL; + tsk->task_frag.page = NULL; + +- account_kernel_stack(ti, 1); ++ account_kernel_stack(tsk, ti, 1); + + return tsk; + + free_ti: +- free_thread_info(ti); ++ gr_free_thread_info(tsk, ti); + free_tsk: + free_task_struct(tsk); + return NULL; } #ifdef CONFIG_MMU @@ -86716,7 +86867,7 @@ index a17621c..d9e4b37 100644 uprobe_start_dup_mmap(); down_write(&oldmm->mmap_sem); -@@ -379,55 +462,15 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -379,55 +497,15 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) prev = NULL; for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) { @@ -86776,7 +86927,7 @@ index a17621c..d9e4b37 100644 } /* -@@ -459,6 +502,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -459,6 +537,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) if (retval) goto out; } @@ -86808,7 +86959,7 @@ index a17621c..d9e4b37 100644 /* a new mm has just been created */ arch_dup_mmap(oldmm, mm); retval = 0; -@@ -468,14 +536,6 @@ out: +@@ -468,14 +571,6 @@ out: up_write(&oldmm->mmap_sem); uprobe_end_dup_mmap(); return retval; @@ -86823,7 +86974,7 @@ index a17621c..d9e4b37 100644 } static inline int mm_alloc_pgd(struct mm_struct *mm) -@@ -689,8 +749,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +@@ -689,8 +784,8 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) return ERR_PTR(err); mm = get_task_mm(task); @@ -86834,7 +86985,7 @@ index a17621c..d9e4b37 100644 mmput(mm); mm = ERR_PTR(-EACCES); } -@@ -906,13 +966,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) +@@ -906,13 +1001,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk) spin_unlock(&fs->lock); return -EAGAIN; } @@ -86856,7 +87007,7 @@ index a17621c..d9e4b37 100644 return 0; } -@@ -1130,7 +1197,7 @@ init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) +@@ -1130,7 +1232,7 @@ init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ @@ -86865,7 +87016,7 @@ index a17621c..d9e4b37 100644 unsigned long stack_start, unsigned long stack_size, int __user *child_tidptr, -@@ -1202,6 +1269,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1202,6 +1304,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); #endif retval = -EAGAIN; @@ -86875,7 +87026,7 @@ index a17621c..d9e4b37 100644 if (atomic_read(&p->real_cred->user->processes) >= task_rlimit(p, RLIMIT_NPROC)) { if (p->real_cred->user != INIT_USER && -@@ -1449,6 +1519,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, +@@ -1449,6 +1554,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, goto bad_fork_free_pid; } @@ -86887,7 +87038,7 @@ index a17621c..d9e4b37 100644 if (likely(p->pid)) { ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); -@@ -1537,6 +1612,8 @@ bad_fork_cleanup_count: +@@ -1537,6 +1647,8 @@ bad_fork_cleanup_count: bad_fork_free: free_task(p); fork_out: @@ -86896,7 +87047,7 @@ index a17621c..d9e4b37 100644 return ERR_PTR(retval); } -@@ -1598,6 +1675,7 @@ long do_fork(unsigned long clone_flags, +@@ -1598,6 +1710,7 @@ long do_fork(unsigned long clone_flags, p = copy_process(clone_flags, stack_start, stack_size, child_tidptr, NULL, trace); @@ -86904,7 +87055,7 @@ index a17621c..d9e4b37 100644 /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. -@@ -1612,6 +1690,8 @@ long do_fork(unsigned long clone_flags, +@@ -1612,6 +1725,8 @@ long do_fork(unsigned long clone_flags, if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); @@ -86913,7 +87064,7 @@ index a17621c..d9e4b37 100644 if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); -@@ -1728,7 +1808,7 @@ void __init proc_caches_init(void) +@@ -1728,7 +1843,7 @@ void __init proc_caches_init(void) mm_cachep = kmem_cache_create("mm_struct", sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN, SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL); @@ -86922,7 +87073,7 @@ index a17621c..d9e4b37 100644 mmap_init(); nsproxy_cache_init(); } -@@ -1768,7 +1848,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) +@@ -1768,7 +1883,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) return 0; /* don't need lock here; in the worst case we'll do useless copy */ @@ -86931,7 +87082,7 @@ index a17621c..d9e4b37 100644 return 0; *new_fsp = copy_fs_struct(fs); -@@ -1875,7 +1955,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) +@@ -1875,7 +1990,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) fs = current->fs; spin_lock(&fs->lock); current->fs = new_fs; @@ -97107,10 +97258,65 @@ index a24aa22..a0d41ae 100644 } #endif diff --git a/mm/vmalloc.c b/mm/vmalloc.c -index 0fdf968..2183ba3 100644 +index 0fdf968..f044efb 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c -@@ -59,8 +59,19 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end) +@@ -38,6 +38,21 @@ struct vfree_deferred { + }; + static DEFINE_PER_CPU(struct vfree_deferred, vfree_deferred); + ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++struct stack_deferred_llist { ++ struct llist_head list; ++ void *stack; ++ void *lowmem_stack; ++}; ++ ++struct stack_deferred { ++ struct stack_deferred_llist list; ++ struct work_struct wq; ++}; ++ ++static DEFINE_PER_CPU(struct stack_deferred, stack_deferred); ++#endif ++ + static void __vunmap(const void *, int); + + static void free_work(struct work_struct *w) +@@ -45,12 +60,30 @@ static void free_work(struct work_struct *w) + struct vfree_deferred *p = container_of(w, struct vfree_deferred, wq); + struct llist_node *llnode = llist_del_all(&p->list); + while (llnode) { +- void *p = llnode; ++ void *x = llnode; + llnode = llist_next(llnode); +- __vunmap(p, 1); ++ __vunmap(x, 1); + } + } + ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++static void unmap_work(struct work_struct *w) ++{ ++ struct stack_deferred *p = container_of(w, struct stack_deferred, wq); ++ struct llist_node *llnode = llist_del_all(&p->list.list); ++ while (llnode) { ++ struct stack_deferred_llist *x = ++ llist_entry((struct llist_head *)llnode, ++ struct stack_deferred_llist, list); ++ void *stack = ACCESS_ONCE(x->stack); ++ void *lowmem_stack = ACCESS_ONCE(x->lowmem_stack); ++ llnode = llist_next(llnode); ++ __vunmap(stack, 0); ++ free_memcg_kmem_pages((unsigned long)lowmem_stack, THREAD_SIZE_ORDER); ++ } ++} ++#endif ++ + /*** Page table manipulation functions ***/ + + static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end) +@@ -59,8 +92,19 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end) pte = pte_offset_kernel(pmd, addr); do { @@ -97132,7 +97338,7 @@ index 0fdf968..2183ba3 100644 } while (pte++, addr += PAGE_SIZE, addr != end); } -@@ -120,16 +131,29 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, +@@ -120,16 +164,29 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr, pte = pte_alloc_kernel(pmd, addr); if (!pte) return -ENOMEM; @@ -97164,7 +97370,7 @@ index 0fdf968..2183ba3 100644 return 0; } -@@ -139,7 +163,7 @@ static int vmap_pmd_range(pud_t *pud, unsigned long addr, +@@ -139,7 +196,7 @@ static int vmap_pmd_range(pud_t *pud, unsigned long addr, pmd_t *pmd; unsigned long next; @@ -97173,7 +97379,7 @@ index 0fdf968..2183ba3 100644 if (!pmd) return -ENOMEM; do { -@@ -156,7 +180,7 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr, +@@ -156,7 +213,7 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr, pud_t *pud; unsigned long next; @@ -97182,7 +97388,7 @@ index 0fdf968..2183ba3 100644 if (!pud) return -ENOMEM; do { -@@ -216,6 +240,12 @@ int is_vmalloc_or_module_addr(const void *x) +@@ -216,6 +273,12 @@ int is_vmalloc_or_module_addr(const void *x) if (addr >= MODULES_VADDR && addr < MODULES_END) return 1; #endif @@ -97195,7 +97401,7 @@ index 0fdf968..2183ba3 100644 return is_vmalloc_addr(x); } -@@ -236,8 +266,14 @@ struct page *vmalloc_to_page(const void *vmalloc_addr) +@@ -236,8 +299,14 @@ struct page *vmalloc_to_page(const void *vmalloc_addr) if (!pgd_none(*pgd)) { pud_t *pud = pud_offset(pgd, addr); @@ -97210,7 +97416,31 @@ index 0fdf968..2183ba3 100644 if (!pmd_none(*pmd)) { pte_t *ptep, pte; -@@ -1309,6 +1345,16 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, +@@ -1175,13 +1244,23 @@ void __init vmalloc_init(void) + for_each_possible_cpu(i) { + struct vmap_block_queue *vbq; + struct vfree_deferred *p; ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ struct stack_deferred *p2; ++#endif + + vbq = &per_cpu(vmap_block_queue, i); + spin_lock_init(&vbq->lock); + INIT_LIST_HEAD(&vbq->free); ++ + p = &per_cpu(vfree_deferred, i); + init_llist_head(&p->list); + INIT_WORK(&p->wq, free_work); ++ ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++ p2 = &per_cpu(stack_deferred, i); ++ init_llist_head(&p2->list.list); ++ INIT_WORK(&p2->wq, unmap_work); ++#endif + } + + /* Import existing vmlist entries. */ +@@ -1309,6 +1388,16 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, struct vm_struct *area; BUG_ON(in_interrupt()); @@ -97227,7 +97457,40 @@ index 0fdf968..2183ba3 100644 if (flags & VM_IOREMAP) align = 1ul << clamp(fls(size), PAGE_SHIFT, IOREMAP_MAX_ORDER); -@@ -1534,6 +1580,11 @@ void *vmap(struct page **pages, unsigned int count, +@@ -1503,7 +1592,7 @@ EXPORT_SYMBOL(vfree); + * Free the virtually contiguous memory area starting at @addr, + * which was created from the page array passed to vmap(). + * +- * Must not be called in interrupt context. ++ * Must not be called in NMI context. + */ + void vunmap(const void *addr) + { +@@ -1514,6 +1603,23 @@ void vunmap(const void *addr) + } + EXPORT_SYMBOL(vunmap); + ++#ifdef CONFIG_GRKERNSEC_KSTACKOVERFLOW ++void unmap_process_stacks(struct task_struct *task) ++{ ++ if (unlikely(in_interrupt())) { ++ struct stack_deferred *p = &__get_cpu_var(stack_deferred); ++ struct stack_deferred_llist *list = task->stack; ++ list->stack = task->stack; ++ list->lowmem_stack = task->lowmem_stack; ++ if (llist_add((struct llist_node *)&list->list, &p->list.list)) ++ schedule_work(&p->wq); ++ } else { ++ __vunmap(task->stack, 0); ++ free_memcg_kmem_pages((unsigned long)task->lowmem_stack, THREAD_SIZE_ORDER); ++ } ++} ++#endif ++ + /** + * vmap - map an array of pages into virtually contiguous space + * @pages: array of page pointers +@@ -1534,6 +1640,11 @@ void *vmap(struct page **pages, unsigned int count, if (count > totalram_pages) return NULL; @@ -97239,7 +97502,7 @@ index 0fdf968..2183ba3 100644 area = get_vm_area_caller((count << PAGE_SHIFT), flags, __builtin_return_address(0)); if (!area) -@@ -1634,6 +1685,13 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, +@@ -1634,6 +1745,13 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, if (!size || (size >> PAGE_SHIFT) > totalram_pages) goto fail; @@ -97253,20 +97516,7 @@ index 0fdf968..2183ba3 100644 area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED, start, end, node, gfp_mask, caller); if (!area) -@@ -1701,6 +1759,12 @@ static inline void *__vmalloc_node_flags(unsigned long size, - node, __builtin_return_address(0)); - } - -+void *vmalloc_stack(int node) -+{ -+ return __vmalloc_node(THREAD_SIZE, THREAD_SIZE, THREADINFO_GFP, PAGE_KERNEL, -+ node, __builtin_return_address(0)); -+} -+ - /** - * vmalloc - allocate virtually contiguous memory - * @size: allocation size -@@ -1810,10 +1874,9 @@ EXPORT_SYMBOL(vzalloc_node); +@@ -1810,10 +1928,9 @@ EXPORT_SYMBOL(vzalloc_node); * For tight control over page level allocator and protection flags * use __vmalloc() instead. */ @@ -97278,7 +97528,7 @@ index 0fdf968..2183ba3 100644 NUMA_NO_NODE, __builtin_return_address(0)); } -@@ -2120,6 +2183,8 @@ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr, +@@ -2120,6 +2237,8 @@ int remap_vmalloc_range_partial(struct vm_area_struct *vma, unsigned long uaddr, { struct vm_struct *area; @@ -97287,7 +97537,7 @@ index 0fdf968..2183ba3 100644 size = PAGE_ALIGN(size); if (!PAGE_ALIGNED(uaddr) || !PAGE_ALIGNED(kaddr)) -@@ -2602,7 +2667,11 @@ static int s_show(struct seq_file *m, void *p) +@@ -2602,7 +2721,11 @@ static int s_show(struct seq_file *m, void *p) v->addr, v->addr + v->size, v->size); if (v->caller) @@ -99028,21 +99278,6 @@ index 5325b54..a0d4d69 100644 return -EFAULT; *lenp = len; -diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c -index 1846c1f..96d4a9f 100644 ---- a/net/ieee802154/dgram.c -+++ b/net/ieee802154/dgram.c -@@ -313,8 +313,9 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, - if (saddr) { - saddr->family = AF_IEEE802154; - saddr->addr = mac_cb(skb)->sa; -+ } -+ if (addr_len) - *addr_len = sizeof(*saddr); -- } - - if (flags & MSG_TRUNC) - copied = skb->len; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 19ab78a..bf575c9 100644 --- a/net/ipv4/af_inet.c @@ -99533,7 +99768,7 @@ index 2510c02..cfb34fa 100644 pr_err("Unable to proc dir entry\n"); return -ENOMEM; diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c -index e21934b..3ae545c 100644 +index e21934b..4e7cb58 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -59,7 +59,7 @@ struct ping_table { @@ -99572,28 +99807,7 @@ index e21934b..3ae545c 100644 info, (u8 *)icmph); #endif } -@@ -844,6 +844,8 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - { - struct inet_sock *isk = inet_sk(sk); - int family = sk->sk_family; -+ struct sockaddr_in *sin; -+ struct sockaddr_in6 *sin6; - struct sk_buff *skb; - int copied, err; - -@@ -853,12 +855,19 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - if (flags & MSG_OOB) - goto out; - -+ if (addr_len) { -+ if (family == AF_INET) -+ *addr_len = sizeof(*sin); -+ else if (family == AF_INET6 && addr_len) -+ *addr_len = sizeof(*sin6); -+ } -+ - if (flags & MSG_ERRQUEUE) { - if (family == AF_INET) { +@@ -858,7 +858,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return ip_recv_error(sk, msg, len, addr_len); #if IS_ENABLED(CONFIG_IPV6) } else if (family == AF_INET6) { @@ -99602,19 +99816,7 @@ index e21934b..3ae545c 100644 addr_len); #endif } -@@ -890,7 +899,6 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - sin->sin_port = 0 /* skb->h.uh->source */; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); -- *addr_len = sizeof(*sin); - } - - if (isk->cmsg_flags) -@@ -912,14 +920,13 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - sin6->sin6_scope_id = - ipv6_iface_scope_id(&sin6->sin6_addr, - IP6CB(skb)->iif); -- *addr_len = sizeof(*sin6); +@@ -916,10 +916,10 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } if (inet6_sk(sk)->rxopt.all) @@ -99627,7 +99829,7 @@ index e21934b..3ae545c 100644 else if (skb->protocol == htons(ETH_P_IP) && isk->cmsg_flags) ip_cmsg_recv(msg, skb); #endif -@@ -1111,7 +1118,7 @@ static void ping_v4_format_sock(struct sock *sp, struct seq_file *f, +@@ -1111,7 +1111,7 @@ static void ping_v4_format_sock(struct sock *sp, struct seq_file *f, from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), 0, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, @@ -99637,7 +99839,7 @@ index e21934b..3ae545c 100644 static int ping_v4_seq_show(struct seq_file *seq, void *v) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c -index c04518f..824ebe5 100644 +index c04518f..c402063 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -311,7 +311,7 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) @@ -99649,25 +99851,7 @@ index c04518f..824ebe5 100644 kfree_skb(skb); return NET_RX_DROP; } -@@ -696,6 +696,9 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - if (flags & MSG_OOB) - goto out; - -+ if (addr_len) -+ *addr_len = sizeof(*sin); -+ - if (flags & MSG_ERRQUEUE) { - err = ip_recv_error(sk, msg, len, addr_len); - goto out; -@@ -723,7 +726,6 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - sin->sin_port = 0; - memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); -- *addr_len = sizeof(*sin); - } - if (inet->cmsg_flags) - ip_cmsg_recv(msg, skb); -@@ -748,16 +750,20 @@ static int raw_init(struct sock *sk) +@@ -748,16 +748,20 @@ static int raw_init(struct sock *sk) static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen) { @@ -99689,7 +99873,7 @@ index c04518f..824ebe5 100644 if (get_user(len, optlen)) goto out; -@@ -767,8 +773,8 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o +@@ -767,8 +771,8 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o if (len > sizeof(struct icmp_filter)) len = sizeof(struct icmp_filter); ret = -EFAULT; @@ -99700,7 +99884,7 @@ index c04518f..824ebe5 100644 goto out; ret = 0; out: return ret; -@@ -997,7 +1003,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) +@@ -997,7 +1001,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) 0, 0L, 0, from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), 0, sock_i_ino(sp), @@ -100091,7 +100275,7 @@ index 64f0354..a81b39d 100644 syn_set ? 0 : icsk->icsk_user_timeout, syn_set)) { /* Has it gone just too far? */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 77bd16f..5f7174a 100644 +index 77bd16f..3ce366b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -87,6 +87,7 @@ @@ -100151,20 +100335,7 @@ index 77bd16f..5f7174a 100644 __skb_unlink(skb, rcvq); __skb_queue_tail(&list_kill, skb); } -@@ -1234,6 +1251,12 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - int is_udplite = IS_UDPLITE(sk); - bool slow; - -+ /* -+ * Check any passed addresses -+ */ -+ if (addr_len) -+ *addr_len = sizeof(*sin); -+ - if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len, addr_len); - -@@ -1243,6 +1266,10 @@ try_again: +@@ -1243,6 +1260,10 @@ try_again: if (!skb) goto out; @@ -100175,7 +100346,7 @@ index 77bd16f..5f7174a 100644 ulen = skb->len - sizeof(struct udphdr); copied = len; if (copied > ulen) -@@ -1276,7 +1303,7 @@ try_again: +@@ -1276,7 +1297,7 @@ try_again: if (unlikely(err)) { trace_kfree_skb(skb, udp_recvmsg); if (!peeked) { @@ -100184,15 +100355,7 @@ index 77bd16f..5f7174a 100644 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } -@@ -1295,7 +1322,6 @@ try_again: - sin->sin_port = udp_hdr(skb)->source; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); -- *addr_len = sizeof(*sin); - } - if (inet->cmsg_flags) - ip_cmsg_recv(msg, skb); -@@ -1566,7 +1592,7 @@ csum_error: +@@ -1566,7 +1587,7 @@ csum_error: UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); drop: UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); @@ -100201,7 +100364,7 @@ index 77bd16f..5f7174a 100644 kfree_skb(skb); return -1; } -@@ -1585,7 +1611,7 @@ static void flush_stack(struct sock **stack, unsigned int count, +@@ -1585,7 +1606,7 @@ static void flush_stack(struct sock **stack, unsigned int count, skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); if (!skb1) { @@ -100210,7 +100373,7 @@ index 77bd16f..5f7174a 100644 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, -@@ -1786,6 +1812,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, +@@ -1786,6 +1807,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, goto csum_error; UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); @@ -100220,7 +100383,7 @@ index 77bd16f..5f7174a 100644 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* -@@ -2350,7 +2379,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, +@@ -2350,7 +2374,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), 0, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, @@ -100670,7 +100833,7 @@ index 091d066..139d410 100644 goto proc_dev_snmp6_fail; return 0; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c -index 1f29996..46fe0c7 100644 +index 1f29996..7418779 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -388,7 +388,7 @@ static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb) @@ -100700,25 +100863,7 @@ index 1f29996..46fe0c7 100644 kfree_skb(skb); return NET_RX_DROP; } -@@ -469,6 +469,9 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, - if (flags & MSG_OOB) - return -EOPNOTSUPP; - -+ if (addr_len) -+ *addr_len=sizeof(*sin6); -+ - if (flags & MSG_ERRQUEUE) - return ipv6_recv_error(sk, msg, len, addr_len); - -@@ -507,7 +510,6 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, - sin6->sin6_flowinfo = 0; - sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, - IP6CB(skb)->iif); -- *addr_len = sizeof(*sin6); - } - - sock_recv_ts_and_drops(msg, sk, skb); -@@ -610,7 +612,7 @@ out: +@@ -610,7 +610,7 @@ out: return err; } @@ -100727,7 +100872,7 @@ index 1f29996..46fe0c7 100644 struct flowi6 *fl6, struct dst_entry **dstp, unsigned int flags) { -@@ -922,12 +924,15 @@ do_confirm: +@@ -922,12 +922,15 @@ do_confirm: static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -100744,7 +100889,7 @@ index 1f29996..46fe0c7 100644 return 0; default: return -ENOPROTOOPT; -@@ -940,6 +945,7 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, +@@ -940,6 +943,7 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { int len; @@ -100752,7 +100897,7 @@ index 1f29996..46fe0c7 100644 switch (optname) { case ICMPV6_FILTER: -@@ -951,7 +957,8 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, +@@ -951,7 +955,8 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, len = sizeof(struct icmp6_filter); if (put_user(len, optlen)) return -EFAULT; @@ -100912,7 +101057,7 @@ index 889079b..a04512c 100644 } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 1e586d9..384a9c9 100644 +index 1e586d9..2b8ad76 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -76,6 +76,10 @@ static unsigned int udp6_ehashfn(struct net *net, @@ -100926,17 +101071,7 @@ index 1e586d9..384a9c9 100644 int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) { const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); -@@ -392,6 +396,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, - int is_udp4; - bool slow; - -+ if (addr_len) -+ *addr_len = sizeof(struct sockaddr_in6); -+ - if (flags & MSG_ERRQUEUE) - return ipv6_recv_error(sk, msg, len, addr_len); - -@@ -435,7 +442,7 @@ try_again: +@@ -435,7 +439,7 @@ try_again: if (unlikely(err)) { trace_kfree_skb(skb, udpv6_recvmsg); if (!peeked) { @@ -100945,16 +101080,7 @@ index 1e586d9..384a9c9 100644 if (is_udp4) UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, -@@ -475,7 +482,7 @@ try_again: - ipv6_iface_scope_id(&sin6->sin6_addr, - IP6CB(skb)->iif); - } -- *addr_len = sizeof(*sin6); -+ - } - - if (np->rxopt.all) -@@ -690,7 +697,7 @@ csum_error: +@@ -690,7 +694,7 @@ csum_error: UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); drop: UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); @@ -100963,7 +101089,7 @@ index 1e586d9..384a9c9 100644 kfree_skb(skb); return -1; } -@@ -747,7 +754,7 @@ static void flush_stack(struct sock **stack, unsigned int count, +@@ -747,7 +751,7 @@ static void flush_stack(struct sock **stack, unsigned int count, if (likely(skb1 == NULL)) skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); if (!skb1) { @@ -100972,7 +101098,7 @@ index 1e586d9..384a9c9 100644 UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, -@@ -886,6 +893,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, +@@ -886,6 +890,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, goto csum_error; UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); @@ -101192,28 +101318,6 @@ index 7932697..a13d158 100644 } while (!res); return res; } -diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c -index 0b44d85..1a7f88b 100644 ---- a/net/l2tp/l2tp_ip.c -+++ b/net/l2tp/l2tp_ip.c -@@ -518,6 +518,9 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m - if (flags & MSG_OOB) - goto out; - -+ if (addr_len) -+ *addr_len = sizeof(*sin); -+ - skb = skb_recv_datagram(sk, flags, noblock, &err); - if (!skb) - goto out; -@@ -540,7 +543,6 @@ static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - sin->sin_port = 0; - memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); -- *addr_len = sizeof(*sin); - } - if (inet->cmsg_flags) - ip_cmsg_recv(msg, skb); diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 1a3c7e0..80f8b0c 100644 --- a/net/llc/llc_proc.c |