diff options
author | Anthony G. Basile <blueness@gentoo.org> | 2013-05-30 07:43:36 -0400 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2013-05-30 07:43:36 -0400 |
commit | 98f0944d5d4dcb71e3c77924f54f81cd836c04b4 (patch) | |
tree | cfec06e4ef05f9991de8dda879044eaba429837f | |
parent | Grsec/PaX: 2.9.1-{2.6.32.60,3.2.45,3.9.4}-201305251009 (diff) | |
download | hardened-patchset-20130529.tar.gz hardened-patchset-20130529.tar.bz2 hardened-patchset-20130529.zip |
Grsec/PaX: 2.9.1-{2.6.32.60,3.2.45,3.9.4}-20130529215120130529
-rw-r--r-- | 2.6.32/0000_README | 2 | ||||
-rw-r--r-- | 2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305292148.patch (renamed from 2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305251007.patch) | 141 | ||||
-rw-r--r-- | 3.2.45/0000_README | 2 | ||||
-rw-r--r-- | 3.2.45/4420_grsecurity-2.9.1-3.2.45-201305292150.patch (renamed from 3.2.45/4420_grsecurity-2.9.1-3.2.45-201305251007.patch) | 426 | ||||
-rw-r--r-- | 3.9.4/0000_README | 2 | ||||
-rw-r--r-- | 3.9.4/4420_grsecurity-2.9.1-3.9.4-201305292151.patch (renamed from 3.9.4/4420_grsecurity-2.9.1-3.9.4-201305251009.patch) | 751 |
6 files changed, 1141 insertions, 183 deletions
diff --git a/2.6.32/0000_README b/2.6.32/0000_README index 5ca0857..378709b 100644 --- a/2.6.32/0000_README +++ b/2.6.32/0000_README @@ -34,7 +34,7 @@ Patch: 1059_linux-2.6.32.60.patch From: http://www.kernel.org Desc: Linux 2.6.32.59 -Patch: 4420_grsecurity-2.9.1-2.6.32.60-201305251007.patch +Patch: 4420_grsecurity-2.9.1-2.6.32.60-201305292148.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305251007.patch b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305292148.patch index f7ef7a8..a6ebcd3 100644 --- a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305251007.patch +++ b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201305292148.patch @@ -43345,7 +43345,7 @@ index 62f282e..e45c45c 100644 cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || diff --git a/drivers/char/random.c b/drivers/char/random.c -index 446b20a..710568a 100644 +index 446b20a..1193fa7 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -269,8 +269,13 @@ @@ -43399,36 +43399,94 @@ index 446b20a..710568a 100644 smp_wmb(); if (out) -@@ -942,6 +955,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, +@@ -840,6 +853,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + int reserved) + { + unsigned long flags; ++ int wakeup_write = 0; + + /* Hold lock while accounting */ + spin_lock_irqsave(&r->lock, flags); +@@ -852,19 +866,25 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + if (r->entropy_count / 8 < min + reserved) { + nbytes = 0; + } else { ++ int entropy_count, orig; ++retry: ++ entropy_count = orig = ACCESS_ONCE(r->entropy_count); + /* If limited, never pull more than available */ +- if (r->limit && nbytes + reserved >= r->entropy_count / 8) +- nbytes = r->entropy_count/8 - reserved; ++ if (r->limit && nbytes + reserved >= entropy_count / 8) ++ nbytes = entropy_count/8 - reserved; + +- if (r->entropy_count / 8 >= nbytes + reserved) +- r->entropy_count -= nbytes*8; +- else +- r->entropy_count = reserved; +- +- if (r->entropy_count < random_write_wakeup_thresh) { +- wake_up_interruptible(&random_write_wait); +- kill_fasync(&fasync, SIGIO, POLL_OUT); ++ if (entropy_count / 8 >= nbytes + reserved) { ++ entropy_count -= nbytes*8; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; ++ } else { ++ entropy_count = reserved; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; + } ++ ++ if (entropy_count < random_write_wakeup_thresh) ++ wakeup_write = 1; + } + + DEBUG_ENT("debiting %d entropy credits from %s%s\n", +@@ -872,6 +892,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + + spin_unlock_irqrestore(&r->lock, flags); + ++ if (wakeup_write) { ++ wake_up_interruptible(&random_write_wait); ++ kill_fasync(&fasync, SIGIO, POLL_OUT); ++ } ++ + return nbytes; + } + +@@ -941,6 +966,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; - -+ /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ -+ if (fips_enabled && !r->last_data_init) -+ nbytes += EXTRACT_SIZE; ++ unsigned long flags; + ++ /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ ++ if (fips_enabled) { ++ spin_lock_irqsave(&r->lock, flags); ++ if (!r->last_data_init) { ++ r->last_data_init = true; ++ spin_unlock_irqrestore(&r->lock, flags); ++ xfer_secondary_pool(r, EXTRACT_SIZE); ++ extract_buf(r, tmp); ++ spin_lock_irqsave(&r->lock, flags); ++ memcpy(r->last_data, tmp, EXTRACT_SIZE); ++ } ++ spin_unlock_irqrestore(&r->lock, flags); ++ } + xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); +@@ -949,8 +989,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + extract_buf(r, tmp); -@@ -951,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, if (fips_enabled) { - unsigned long flags; - -+ -+ /* prime last_data value if need be, per fips 140-2 */ -+ if (!r->last_data_init) { -+ spin_lock_irqsave(&r->lock, flags); -+ memcpy(r->last_data, tmp, EXTRACT_SIZE); -+ r->last_data_init = true; -+ nbytes -= EXTRACT_SIZE; -+ spin_unlock_irqrestore(&r->lock, flags); -+ extract_buf(r, tmp); -+ } -+ +- unsigned long flags; +- spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); -@@ -1015,7 +1043,21 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, +@@ -1015,7 +1053,21 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, */ void get_random_bytes(void *buf, int nbytes) { @@ -43451,7 +43509,7 @@ index 446b20a..710568a 100644 } EXPORT_SYMBOL(get_random_bytes); -@@ -1068,6 +1110,7 @@ static void init_std_data(struct entropy_store *r) +@@ -1068,6 +1120,7 @@ static void init_std_data(struct entropy_store *r) r->entropy_count = 0; r->entropy_total = 0; @@ -43459,7 +43517,7 @@ index 446b20a..710568a 100644 mix_pool_bytes(r, &now, sizeof(now), NULL); for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { if (!arch_get_random_long(&rv)) -@@ -1322,7 +1365,7 @@ EXPORT_SYMBOL(generate_random_uuid); +@@ -1322,7 +1375,7 @@ EXPORT_SYMBOL(generate_random_uuid); #include <linux/sysctl.h> static int min_read_thresh = 8, min_write_thresh; @@ -43468,7 +43526,7 @@ index 446b20a..710568a 100644 static int max_write_thresh = INPUT_POOL_WORDS * 32; static char sysctl_bootid[16]; -@@ -1397,6 +1440,7 @@ static int uuid_strategy(ctl_table *table, +@@ -1397,6 +1450,7 @@ static int uuid_strategy(ctl_table *table, } static int sysctl_poolsize = INPUT_POOL_WORDS * 32; @@ -43476,7 +43534,7 @@ index 446b20a..710568a 100644 ctl_table random_table[] = { { .ctl_name = RANDOM_POOLSIZE, -@@ -1472,7 +1516,7 @@ late_initcall(random_int_secret_init); +@@ -1472,7 +1526,7 @@ late_initcall(random_int_secret_init); * value is not cryptographically secure but for several uses the cost of * depleting entropy is too high */ @@ -71823,7 +71881,7 @@ index 913b4a4..4de325a9 100644 crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c -index 1a056ad..221bd6a 100644 +index 1a056ad..221bd6ae 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -127,7 +127,7 @@ static int radeon_bl_get_brightness(struct backlight_device *bd) @@ -79170,7 +79228,7 @@ index f1e7077..edd86b2 100644 .store = ext4_attr_store, }; diff --git a/fs/fat/inode.c b/fs/fat/inode.c -index 76b7961..c187e92 100644 +index 76b7961..ca5f1c9 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -558,7 +558,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -79182,6 +79240,35 @@ index 76b7961..c187e92 100644 return 0; } +@@ -1206,6 +1206,19 @@ static int fat_read_root(struct inode *inode) + return 0; + } + ++static unsigned long calc_fat_clusters(struct super_block *sb) ++{ ++ struct msdos_sb_info *sbi = MSDOS_SB(sb); ++ ++ /* Divide first to avoid overflow */ ++ if (sbi->fat_bits != 12) { ++ unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits; ++ return ent_per_sec * sbi->fat_length; ++ } ++ ++ return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++} ++ + /* + * Read the super block of an MS-DOS FS. + */ +@@ -1400,7 +1413,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, + sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; + + /* check that FAT table does not overflow */ +- fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++ fat_clusters = calc_fat_clusters(sb); + total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); + if (total_clusters > MAX_FAT(sb)) { + if (!silent) diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 72646e2..4251f35 100644 --- a/fs/fat/namei_vfat.c diff --git a/3.2.45/0000_README b/3.2.45/0000_README index ba3ec05..577c9db 100644 --- a/3.2.45/0000_README +++ b/3.2.45/0000_README @@ -98,7 +98,7 @@ Patch: 1044_linux-3.2.45.patch From: http://www.kernel.org Desc: Linux 3.2.45 -Patch: 4420_grsecurity-2.9.1-3.2.45-201305251007.patch +Patch: 4420_grsecurity-2.9.1-3.2.45-201305292150.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/3.2.45/4420_grsecurity-2.9.1-3.2.45-201305251007.patch b/3.2.45/4420_grsecurity-2.9.1-3.2.45-201305292150.patch index bc81306..52e473e 100644 --- a/3.2.45/4420_grsecurity-2.9.1-3.2.45-201305251007.patch +++ b/3.2.45/4420_grsecurity-2.9.1-3.2.45-201305292150.patch @@ -1858,6 +1858,28 @@ index 7ac5dfd..0ce09c2 100644 if (ret != NOTIFY_STOP) do_exit(SIGSEGV); } +diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S +index 20b3041..da44b1f 100644 +--- a/arch/arm/kernel/vmlinux.lds.S ++++ b/arch/arm/kernel/vmlinux.lds.S +@@ -103,6 +103,8 @@ SECTIONS + ARM_CPU_KEEP(PROC_INFO) + } + ++ _etext = .; /* End of text section */ ++ + RO_DATA(PAGE_SIZE) + + #ifdef CONFIG_ARM_UNWIND +@@ -122,8 +124,6 @@ SECTIONS + } + #endif + +- _etext = .; /* End of text and rodata section */ +- + #ifndef CONFIG_XIP_KERNEL + . = ALIGN(PAGE_SIZE); + __init_begin = .; diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 66a477a..bee61d3 100644 --- a/arch/arm/lib/copy_from_user.S @@ -2210,7 +2232,7 @@ index c3a58a1..78fbf54 100644 /* * Memory returned by kmalloc() may be used for DMA, so we must make diff --git a/arch/avr32/include/asm/elf.h b/arch/avr32/include/asm/elf.h -index 3b3159b..425ea94 100644 +index 3b3159b..425ea94d 100644 --- a/arch/avr32/include/asm/elf.h +++ b/arch/avr32/include/asm/elf.h @@ -84,8 +84,14 @@ typedef struct user_fpu_struct elf_fpregset_t; @@ -28041,7 +28063,7 @@ index 6687022..ceabcfa 100644 + pax_force_retaddr ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c -index 5a5b6e4..2265c0f 100644 +index 5a5b6e4..37ccbe3 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -11,6 +11,7 @@ @@ -28052,7 +28074,7 @@ index 5a5b6e4..2265c0f 100644 /* * Conventions : -@@ -45,13 +46,87 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) +@@ -45,13 +46,84 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) return ptr + len; } @@ -28104,6 +28126,10 @@ index 5a5b6e4..2265c0f 100644 + /* mov esi, ecx */ \ + EMIT2(0x89, 0xce); \ + break; \ ++ case 0xe8: /* call rel imm32, always to known funcs */ \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ break; \ + case 0xe9: /* jmp rel imm32 */ \ + EMIT1(b1); \ + EMIT(_off, 4); \ @@ -28112,25 +28138,18 @@ index 5a5b6e4..2265c0f 100644 + EMIT(0xcccccccc, 4); \ + break; \ + default: \ -+ EMIT1(b1); \ -+ EMIT(_off, 4); \ ++ BUILD_BUG_ON(1); \ + } \ +} while (0) + +#define EMIT2_off32(b1, b2, _off) \ +do { \ -+ if ((b1) == 0x8d && (b2) == 0xb3) { /* lea esi, [rbx+imm32] */ \ -+ EMIT2(0x8d, 0xb3); /* lea esi, [rbx+randkey] */ \ -+ EMIT(randkey, 4); \ -+ EMIT2(0x8d, 0xb6); /* lea esi, [esi+off-randkey] */ \ -+ EMIT((_off) - randkey, 4); \ -+ } else if ((b1) == 0x69 && (b2) == 0xc0) { /* imul eax, imm32 */\ ++ if ((b1) == 0x69 && (b2) == 0xc0) { /* imul eax, imm32 */ \ + DILUTE_CONST_SEQUENCE(_off, randkey); \ + /* imul eax, ecx */ \ + EMIT3(0x0f, 0xaf, 0xc1); \ + } else { \ -+ EMIT2(b1, b2); \ -+ EMIT(_off, 4); \ ++ BUILD_BUG_ON(1); \ + } \ +} while (0) +#else @@ -28140,7 +28159,7 @@ index 5a5b6e4..2265c0f 100644 #define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ #define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ -@@ -86,6 +161,24 @@ do { \ +@@ -86,6 +158,24 @@ do { \ #define X86_JBE 0x76 #define X86_JA 0x77 @@ -28165,7 +28184,7 @@ index 5a5b6e4..2265c0f 100644 #define EMIT_COND_JMP(op, offset) \ do { \ if (is_near(offset)) \ -@@ -93,6 +186,7 @@ do { \ +@@ -93,6 +183,7 @@ do { \ else { \ EMIT2(0x0f, op + 0x10); \ EMIT(offset, 4); /* jxx .+off32 */ \ @@ -28173,7 +28192,7 @@ index 5a5b6e4..2265c0f 100644 } \ } while (0) -@@ -117,10 +211,14 @@ static inline void bpf_flush_icache(void *start, void *end) +@@ -117,10 +208,14 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } @@ -28189,7 +28208,7 @@ index 5a5b6e4..2265c0f 100644 u8 *prog; unsigned int proglen, oldproglen = 0; int ilen, i; -@@ -133,6 +231,9 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -133,6 +228,9 @@ void bpf_jit_compile(struct sk_filter *fp) unsigned int *addrs; const struct sock_filter *filter = fp->insns; int flen = fp->len; @@ -28199,7 +28218,7 @@ index 5a5b6e4..2265c0f 100644 if (!bpf_jit_enable) return; -@@ -141,11 +242,19 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -141,11 +239,19 @@ void bpf_jit_compile(struct sk_filter *fp) if (addrs == NULL) return; @@ -28221,7 +28240,7 @@ index 5a5b6e4..2265c0f 100644 addrs[i] = proglen; } cleanup_addr = proglen; /* epilogue address */ -@@ -253,10 +362,8 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -253,10 +359,8 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_ALU_MUL_K: /* A *= K */ if (is_imm8(K)) EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ @@ -28234,7 +28253,7 @@ index 5a5b6e4..2265c0f 100644 break; case BPF_S_ALU_DIV_X: /* A /= X; */ seen |= SEEN_XREG; -@@ -276,8 +383,14 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -276,8 +380,14 @@ void bpf_jit_compile(struct sk_filter *fp) EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */ break; case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ @@ -28249,7 +28268,7 @@ index 5a5b6e4..2265c0f 100644 EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ break; case BPF_S_ALU_AND_X: -@@ -477,7 +590,7 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -477,7 +587,7 @@ void bpf_jit_compile(struct sk_filter *fp) common_load: seen |= SEEN_DATAREF; if ((int)K < 0) { /* Abort the JIT because __load_pointer() is needed. */ @@ -28258,7 +28277,7 @@ index 5a5b6e4..2265c0f 100644 } t_offset = func - (image + addrs[i]); EMIT1_off32(0xbe, K); /* mov imm32,%esi */ -@@ -492,7 +605,7 @@ common_load: seen |= SEEN_DATAREF; +@@ -492,7 +602,7 @@ common_load: seen |= SEEN_DATAREF; case BPF_S_LDX_B_MSH: if ((int)K < 0) { /* Abort the JIT because __load_pointer() is needed. */ @@ -28267,7 +28286,7 @@ index 5a5b6e4..2265c0f 100644 } seen |= SEEN_DATAREF | SEEN_XREG; t_offset = sk_load_byte_msh - (image + addrs[i]); -@@ -582,17 +695,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -582,17 +692,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; default: /* hmm, too complex filter, give up with jit compiler */ @@ -28290,7 +28309,7 @@ index 5a5b6e4..2265c0f 100644 } proglen += ilen; addrs[i] = proglen; -@@ -613,11 +727,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -613,11 +724,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { @@ -28304,7 +28323,7 @@ index 5a5b6e4..2265c0f 100644 } oldproglen = proglen; } -@@ -633,7 +745,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -633,7 +742,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; @@ -28316,7 +28335,7 @@ index 5a5b6e4..2265c0f 100644 out: kfree(addrs); return; -@@ -641,18 +756,20 @@ out: +@@ -641,18 +753,20 @@ out: static void jit_free_defer(struct work_struct *arg) { @@ -32413,7 +32432,7 @@ index da3cfee..a5a6606 100644 *ppos = i; diff --git a/drivers/char/random.c b/drivers/char/random.c -index 8ae9235..ea94cf2 100644 +index 8ae9235..788c4ba 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -269,8 +269,13 @@ @@ -32467,36 +32486,94 @@ index 8ae9235..ea94cf2 100644 smp_wmb(); if (out) -@@ -979,6 +992,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, +@@ -877,6 +890,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + int reserved) + { + unsigned long flags; ++ int wakeup_write = 0; + + /* Hold lock while accounting */ + spin_lock_irqsave(&r->lock, flags); +@@ -889,19 +903,25 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + if (r->entropy_count / 8 < min + reserved) { + nbytes = 0; + } else { ++ int entropy_count, orig; ++retry: ++ entropy_count = orig = ACCESS_ONCE(r->entropy_count); + /* If limited, never pull more than available */ +- if (r->limit && nbytes + reserved >= r->entropy_count / 8) +- nbytes = r->entropy_count/8 - reserved; ++ if (r->limit && nbytes + reserved >= entropy_count / 8) ++ nbytes = entropy_count/8 - reserved; + +- if (r->entropy_count / 8 >= nbytes + reserved) +- r->entropy_count -= nbytes*8; +- else +- r->entropy_count = reserved; +- +- if (r->entropy_count < random_write_wakeup_thresh) { +- wake_up_interruptible(&random_write_wait); +- kill_fasync(&fasync, SIGIO, POLL_OUT); ++ if (entropy_count / 8 >= nbytes + reserved) { ++ entropy_count -= nbytes*8; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; ++ } else { ++ entropy_count = reserved; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; + } ++ ++ if (entropy_count < random_write_wakeup_thresh) ++ wakeup_write = 1; + } + + DEBUG_ENT("debiting %d entropy credits from %s%s\n", +@@ -909,6 +929,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + + spin_unlock_irqrestore(&r->lock, flags); + ++ if (wakeup_write) { ++ wake_up_interruptible(&random_write_wait); ++ kill_fasync(&fasync, SIGIO, POLL_OUT); ++ } ++ + return nbytes; + } + +@@ -978,6 +1003,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; - -+ /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ -+ if (fips_enabled && !r->last_data_init) -+ nbytes += EXTRACT_SIZE; ++ unsigned long flags; + ++ /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ ++ if (fips_enabled) { ++ spin_lock_irqsave(&r->lock, flags); ++ if (!r->last_data_init) { ++ r->last_data_init = true; ++ spin_unlock_irqrestore(&r->lock, flags); ++ xfer_secondary_pool(r, EXTRACT_SIZE); ++ extract_buf(r, tmp); ++ spin_lock_irqsave(&r->lock, flags); ++ memcpy(r->last_data, tmp, EXTRACT_SIZE); ++ } ++ spin_unlock_irqrestore(&r->lock, flags); ++ } + xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); +@@ -986,8 +1026,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + extract_buf(r, tmp); -@@ -988,6 +1005,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, if (fips_enabled) { - unsigned long flags; - -+ -+ /* prime last_data value if need be, per fips 140-2 */ -+ if (!r->last_data_init) { -+ spin_lock_irqsave(&r->lock, flags); -+ memcpy(r->last_data, tmp, EXTRACT_SIZE); -+ r->last_data_init = true; -+ nbytes -= EXTRACT_SIZE; -+ spin_unlock_irqrestore(&r->lock, flags); -+ extract_buf(r, tmp); -+ } -+ +- unsigned long flags; +- spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); -@@ -1028,7 +1056,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, +@@ -1028,7 +1066,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, extract_buf(r, tmp); i = min_t(int, nbytes, EXTRACT_SIZE); @@ -32505,7 +32582,7 @@ index 8ae9235..ea94cf2 100644 ret = -EFAULT; break; } -@@ -1105,6 +1133,7 @@ static void init_std_data(struct entropy_store *r) +@@ -1105,6 +1143,7 @@ static void init_std_data(struct entropy_store *r) r->entropy_count = 0; r->entropy_total = 0; @@ -32513,7 +32590,7 @@ index 8ae9235..ea94cf2 100644 mix_pool_bytes(r, &now, sizeof(now), NULL); for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { if (!arch_get_random_long(&rv)) -@@ -1379,7 +1408,7 @@ EXPORT_SYMBOL(generate_random_uuid); +@@ -1379,7 +1418,7 @@ EXPORT_SYMBOL(generate_random_uuid); #include <linux/sysctl.h> static int min_read_thresh = 8, min_write_thresh; @@ -32522,7 +32599,7 @@ index 8ae9235..ea94cf2 100644 static int max_write_thresh = INPUT_POOL_WORDS * 32; static char sysctl_bootid[16]; -@@ -1395,7 +1424,7 @@ static char sysctl_bootid[16]; +@@ -1395,7 +1434,7 @@ static char sysctl_bootid[16]; static int proc_do_uuid(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -49494,10 +49571,10 @@ index 451b9b8..12e5a03 100644 out_free_fd: diff --git a/fs/exec.c b/fs/exec.c -index 312e297..437233e 100644 +index 312e297..4c133f2 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -55,12 +55,34 @@ +@@ -55,12 +55,35 @@ #include <linux/pipe_fs_i.h> #include <linux/oom.h> #include <linux/compat.h> @@ -49513,6 +49590,7 @@ index 312e297..437233e 100644 +#include <trace/events/fs.h> #include <asm/uaccess.h> ++#include <asm/sections.h> #include <asm/mmu_context.h> #include <asm/tlb.h> #include "internal.h" @@ -49532,7 +49610,7 @@ index 312e297..437233e 100644 int core_uses_pid; char core_pattern[CORENAME_MAX_SIZE] = "core"; unsigned int core_pipe_limit; -@@ -70,7 +92,7 @@ struct core_name { +@@ -70,7 +93,7 @@ struct core_name { char *corename; int used, size; }; @@ -49541,7 +49619,7 @@ index 312e297..437233e 100644 /* The maximal length of core_pattern is also specified in sysctl.c */ -@@ -82,8 +104,8 @@ int __register_binfmt(struct linux_binfmt * fmt, int insert) +@@ -82,8 +105,8 @@ int __register_binfmt(struct linux_binfmt * fmt, int insert) if (!fmt) return -EINVAL; write_lock(&binfmt_lock); @@ -49552,7 +49630,7 @@ index 312e297..437233e 100644 write_unlock(&binfmt_lock); return 0; } -@@ -93,7 +115,7 @@ EXPORT_SYMBOL(__register_binfmt); +@@ -93,7 +116,7 @@ EXPORT_SYMBOL(__register_binfmt); void unregister_binfmt(struct linux_binfmt * fmt) { write_lock(&binfmt_lock); @@ -49561,7 +49639,7 @@ index 312e297..437233e 100644 write_unlock(&binfmt_lock); } -@@ -188,18 +210,10 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +@@ -188,18 +211,10 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, int write) { struct page *page; @@ -49583,7 +49661,7 @@ index 312e297..437233e 100644 return NULL; if (write) { -@@ -215,6 +229,17 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, +@@ -215,6 +230,17 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, if (size <= ARG_MAX) return page; @@ -49601,7 +49679,7 @@ index 312e297..437233e 100644 /* * Limit to 1/4-th the stack size for the argv+env strings. * This ensures that: -@@ -274,6 +299,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) +@@ -274,6 +300,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) vma->vm_end = STACK_TOP_MAX; vma->vm_start = vma->vm_end - PAGE_SIZE; vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; @@ -49613,7 +49691,7 @@ index 312e297..437233e 100644 vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); INIT_LIST_HEAD(&vma->anon_vma_chain); -@@ -288,6 +318,12 @@ static int __bprm_mm_init(struct linux_binprm *bprm) +@@ -288,6 +319,12 @@ static int __bprm_mm_init(struct linux_binprm *bprm) mm->stack_vm = mm->total_vm = 1; up_write(&mm->mmap_sem); bprm->p = vma->vm_end - sizeof(void *); @@ -49626,7 +49704,7 @@ index 312e297..437233e 100644 return 0; err: up_write(&mm->mmap_sem); -@@ -403,12 +439,12 @@ struct user_arg_ptr { +@@ -403,12 +440,12 @@ struct user_arg_ptr { union { const char __user *const __user *native; #ifdef CONFIG_COMPAT @@ -49641,7 +49719,7 @@ index 312e297..437233e 100644 { const char __user *native; -@@ -417,14 +453,14 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) +@@ -417,14 +454,14 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) compat_uptr_t compat; if (get_user(compat, argv.ptr.compat + nr)) @@ -49658,7 +49736,7 @@ index 312e297..437233e 100644 return native; } -@@ -443,11 +479,12 @@ static int count(struct user_arg_ptr argv, int max) +@@ -443,11 +480,12 @@ static int count(struct user_arg_ptr argv, int max) if (!p) break; @@ -49673,7 +49751,7 @@ index 312e297..437233e 100644 if (fatal_signal_pending(current)) return -ERESTARTNOHAND; -@@ -477,7 +514,7 @@ static int copy_strings(int argc, struct user_arg_ptr argv, +@@ -477,7 +515,7 @@ static int copy_strings(int argc, struct user_arg_ptr argv, ret = -EFAULT; str = get_user_arg_ptr(argv, argc); @@ -49682,7 +49760,7 @@ index 312e297..437233e 100644 goto out; len = strnlen_user(str, MAX_ARG_STRLEN); -@@ -559,7 +596,7 @@ int copy_strings_kernel(int argc, const char *const *__argv, +@@ -559,7 +597,7 @@ int copy_strings_kernel(int argc, const char *const *__argv, int r; mm_segment_t oldfs = get_fs(); struct user_arg_ptr argv = { @@ -49691,7 +49769,7 @@ index 312e297..437233e 100644 }; set_fs(KERNEL_DS); -@@ -594,7 +631,8 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) +@@ -594,7 +632,8 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) unsigned long new_end = old_end - shift; struct mmu_gather tlb; @@ -49701,7 +49779,7 @@ index 312e297..437233e 100644 /* * ensure there are no vmas between where we want to go -@@ -603,6 +641,10 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) +@@ -603,6 +642,10 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) if (vma != find_vma(mm, new_start)) return -EFAULT; @@ -49712,7 +49790,7 @@ index 312e297..437233e 100644 /* * cover the whole range: [new_start, old_end) */ -@@ -683,10 +725,6 @@ int setup_arg_pages(struct linux_binprm *bprm, +@@ -683,10 +726,6 @@ int setup_arg_pages(struct linux_binprm *bprm, stack_top = arch_align_stack(stack_top); stack_top = PAGE_ALIGN(stack_top); @@ -49723,7 +49801,7 @@ index 312e297..437233e 100644 stack_shift = vma->vm_end - stack_top; bprm->p -= stack_shift; -@@ -698,8 +736,28 @@ int setup_arg_pages(struct linux_binprm *bprm, +@@ -698,8 +737,28 @@ int setup_arg_pages(struct linux_binprm *bprm, bprm->exec -= stack_shift; down_write(&mm->mmap_sem); @@ -49752,7 +49830,7 @@ index 312e297..437233e 100644 /* * Adjust stack execute permissions; explicitly enable for * EXSTACK_ENABLE_X, disable for EXSTACK_DISABLE_X and leave alone -@@ -718,13 +776,6 @@ int setup_arg_pages(struct linux_binprm *bprm, +@@ -718,13 +777,6 @@ int setup_arg_pages(struct linux_binprm *bprm, goto out_unlock; BUG_ON(prev != vma); @@ -49766,7 +49844,7 @@ index 312e297..437233e 100644 /* mprotect_fixup is overkill to remove the temporary stack flags */ vma->vm_flags &= ~VM_STACK_INCOMPLETE_SETUP; -@@ -748,6 +799,27 @@ int setup_arg_pages(struct linux_binprm *bprm, +@@ -748,6 +800,27 @@ int setup_arg_pages(struct linux_binprm *bprm, #endif current->mm->start_stack = bprm->p; ret = expand_stack(vma, stack_base); @@ -49794,7 +49872,7 @@ index 312e297..437233e 100644 if (ret) ret = -EFAULT; -@@ -782,6 +854,8 @@ struct file *open_exec(const char *name) +@@ -782,6 +855,8 @@ struct file *open_exec(const char *name) fsnotify_open(file); @@ -49803,7 +49881,7 @@ index 312e297..437233e 100644 err = deny_write_access(file); if (err) goto exit; -@@ -805,7 +879,7 @@ int kernel_read(struct file *file, loff_t offset, +@@ -805,7 +880,7 @@ int kernel_read(struct file *file, loff_t offset, old_fs = get_fs(); set_fs(get_ds()); /* The cast to a user pointer is valid due to the set_fs() */ @@ -49812,7 +49890,7 @@ index 312e297..437233e 100644 set_fs(old_fs); return result; } -@@ -1070,6 +1144,21 @@ void set_task_comm(struct task_struct *tsk, char *buf) +@@ -1070,6 +1145,21 @@ void set_task_comm(struct task_struct *tsk, char *buf) perf_event_comm(tsk); } @@ -49834,7 +49912,7 @@ index 312e297..437233e 100644 int flush_old_exec(struct linux_binprm * bprm) { int retval; -@@ -1084,6 +1173,7 @@ int flush_old_exec(struct linux_binprm * bprm) +@@ -1084,6 +1174,7 @@ int flush_old_exec(struct linux_binprm * bprm) set_mm_exe_file(bprm->mm, bprm->file); @@ -49842,7 +49920,7 @@ index 312e297..437233e 100644 /* * Release all of the old mmap stuff */ -@@ -1116,10 +1206,6 @@ EXPORT_SYMBOL(would_dump); +@@ -1116,10 +1207,6 @@ EXPORT_SYMBOL(would_dump); void setup_new_exec(struct linux_binprm * bprm) { @@ -49853,7 +49931,7 @@ index 312e297..437233e 100644 arch_pick_mmap_layout(current->mm); /* This is the point of no return */ -@@ -1130,18 +1216,7 @@ void setup_new_exec(struct linux_binprm * bprm) +@@ -1130,18 +1217,7 @@ void setup_new_exec(struct linux_binprm * bprm) else set_dumpable(current->mm, suid_dumpable); @@ -49873,7 +49951,7 @@ index 312e297..437233e 100644 /* Set the new mm task size. We have to do that late because it may * depend on TIF_32BIT which is only updated in flush_thread() on -@@ -1266,7 +1341,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) +@@ -1266,7 +1342,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) } rcu_read_unlock(); @@ -49882,7 +49960,7 @@ index 312e297..437233e 100644 bprm->unsafe |= LSM_UNSAFE_SHARE; } else { res = -EAGAIN; -@@ -1461,6 +1536,31 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) +@@ -1461,6 +1537,31 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) EXPORT_SYMBOL(search_binary_handler); @@ -49914,7 +49992,7 @@ index 312e297..437233e 100644 /* * sys_execve() executes a new program. */ -@@ -1469,6 +1569,11 @@ static int do_execve_common(const char *filename, +@@ -1469,6 +1570,11 @@ static int do_execve_common(const char *filename, struct user_arg_ptr envp, struct pt_regs *regs) { @@ -49926,7 +50004,7 @@ index 312e297..437233e 100644 struct linux_binprm *bprm; struct file *file; struct files_struct *displaced; -@@ -1476,6 +1581,8 @@ static int do_execve_common(const char *filename, +@@ -1476,6 +1582,8 @@ static int do_execve_common(const char *filename, int retval; const struct cred *cred = current_cred(); @@ -49935,7 +50013,7 @@ index 312e297..437233e 100644 /* * We move the actual failure in case of RLIMIT_NPROC excess from * set*uid() to execve() because too many poorly written programs -@@ -1516,12 +1623,27 @@ static int do_execve_common(const char *filename, +@@ -1516,12 +1624,27 @@ static int do_execve_common(const char *filename, if (IS_ERR(file)) goto out_unmark; @@ -49963,7 +50041,7 @@ index 312e297..437233e 100644 retval = bprm_mm_init(bprm); if (retval) goto out_file; -@@ -1538,24 +1660,65 @@ static int do_execve_common(const char *filename, +@@ -1538,24 +1661,65 @@ static int do_execve_common(const char *filename, if (retval < 0) goto out; @@ -50033,7 +50111,7 @@ index 312e297..437233e 100644 current->fs->in_exec = 0; current->in_execve = 0; acct_update_integrals(current); -@@ -1564,6 +1727,14 @@ static int do_execve_common(const char *filename, +@@ -1564,6 +1728,14 @@ static int do_execve_common(const char *filename, put_files_struct(displaced); return retval; @@ -50048,7 +50126,7 @@ index 312e297..437233e 100644 out: if (bprm->mm) { acct_arg_size(bprm, 0); -@@ -1637,7 +1808,7 @@ static int expand_corename(struct core_name *cn) +@@ -1637,7 +1809,7 @@ static int expand_corename(struct core_name *cn) { char *old_corename = cn->corename; @@ -50057,7 +50135,7 @@ index 312e297..437233e 100644 cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL); if (!cn->corename) { -@@ -1734,7 +1905,7 @@ static int format_corename(struct core_name *cn, long signr) +@@ -1734,7 +1906,7 @@ static int format_corename(struct core_name *cn, long signr) int pid_in_pattern = 0; int err = 0; @@ -50066,7 +50144,7 @@ index 312e297..437233e 100644 cn->corename = kmalloc(cn->size, GFP_KERNEL); cn->used = 0; -@@ -1831,6 +2002,250 @@ out: +@@ -1831,6 +2003,280 @@ out: return ispipe; } @@ -50271,7 +50349,30 @@ index 312e297..437233e 100644 +} +#endif + -+void __check_object_size(const void *ptr, unsigned long n, bool to) ++#ifdef CONFIG_PAX_USERCOPY ++static inline bool check_kernel_text_object(unsigned long low, unsigned long high) ++{ ++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) ++ unsigned long textlow = ktla_ktva((unsigned long)_stext); ++#ifdef CONFIG_MODULES ++ unsigned long texthigh = (unsigned long)MODULES_EXEC_VADDR; ++#else ++ unsigned long texthigh = ktla_ktva((unsigned long)_etext); ++#endif ++ ++#else ++ unsigned long textlow = _stext; ++ unsigned long texthigh = _etext; ++#endif ++ ++ if (high <= textlow || low > texthigh) ++ return false; ++ else ++ return true; ++} ++#endif ++ ++void __check_object_size(const void *ptr, unsigned long n, bool to_user) +{ + +#ifdef CONFIG_PAX_USERCOPY @@ -50282,12 +50383,19 @@ index 312e297..437233e 100644 + + type = check_heap_object(ptr, n); + if (!type) { -+ if (check_stack_object(ptr, n) != -1) ++ int ret = check_stack_object(ptr, n); ++ if (ret == 1 || ret == 2) + return; -+ type = "<process stack>"; ++ if (ret == 0) { ++ if (check_kernel_text_object((unsigned long)ptr, (unsigned long)ptr + n)) ++ type = "<kernel text>"; ++ else ++ return; ++ } else ++ type = "<process stack>"; + } + -+ pax_report_usercopy(ptr, n, to, type); ++ pax_report_usercopy(ptr, n, to_user, type); +#endif + +} @@ -50317,7 +50425,7 @@ index 312e297..437233e 100644 static int zap_process(struct task_struct *start, int exit_code) { struct task_struct *t; -@@ -2004,17 +2419,17 @@ static void coredump_finish(struct mm_struct *mm) +@@ -2004,17 +2450,17 @@ static void coredump_finish(struct mm_struct *mm) void set_dumpable(struct mm_struct *mm, int value) { switch (value) { @@ -50338,7 +50446,7 @@ index 312e297..437233e 100644 set_bit(MMF_DUMP_SECURELY, &mm->flags); smp_wmb(); set_bit(MMF_DUMPABLE, &mm->flags); -@@ -2027,7 +2442,7 @@ static int __get_dumpable(unsigned long mm_flags) +@@ -2027,7 +2473,7 @@ static int __get_dumpable(unsigned long mm_flags) int ret; ret = mm_flags & MMF_DUMPABLE_MASK; @@ -50347,7 +50455,7 @@ index 312e297..437233e 100644 } int get_dumpable(struct mm_struct *mm) -@@ -2042,17 +2457,17 @@ static void wait_for_dump_helpers(struct file *file) +@@ -2042,17 +2488,17 @@ static void wait_for_dump_helpers(struct file *file) pipe = file->f_path.dentry->d_inode->i_pipe; pipe_lock(pipe); @@ -50370,7 +50478,7 @@ index 312e297..437233e 100644 pipe_unlock(pipe); } -@@ -2113,7 +2528,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2113,7 +2559,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) int retval = 0; int flag = 0; int ispipe; @@ -50380,7 +50488,7 @@ index 312e297..437233e 100644 struct coredump_params cprm = { .signr = signr, .regs = regs, -@@ -2128,6 +2544,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2128,6 +2575,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) audit_core_dumps(signr); @@ -50390,7 +50498,7 @@ index 312e297..437233e 100644 binfmt = mm->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; -@@ -2138,14 +2557,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2138,14 +2588,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) if (!cred) goto fail; /* @@ -50411,7 +50519,7 @@ index 312e297..437233e 100644 } retval = coredump_wait(exit_code, &core_state); -@@ -2195,7 +2616,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2195,7 +2647,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) } cprm.limit = RLIM_INFINITY; @@ -50420,7 +50528,7 @@ index 312e297..437233e 100644 if (core_pipe_limit && (core_pipe_limit < dump_count)) { printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", task_tgid_vnr(current), current->comm); -@@ -2222,9 +2643,19 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) +@@ -2222,9 +2674,19 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) } else { struct inode *inode; @@ -50440,7 +50548,7 @@ index 312e297..437233e 100644 cprm.file = filp_open(cn.corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); -@@ -2265,7 +2696,7 @@ close_fail: +@@ -2265,7 +2727,7 @@ close_fail: filp_close(cprm.file, NULL); fail_dropcount: if (ispipe) @@ -50449,7 +50557,7 @@ index 312e297..437233e 100644 fail_unlock: kfree(cn.corename); fail_corename: -@@ -2284,7 +2715,7 @@ fail: +@@ -2284,7 +2746,7 @@ fail: */ int dump_write(struct file *file, const void *addr, int nr) { @@ -50753,6 +50861,39 @@ index cc386b2..22725d2 100644 static int __init ext4_init_feat_adverts(void) { +diff --git a/fs/fat/inode.c b/fs/fat/inode.c +index 808cac7..fc33ca1 100644 +--- a/fs/fat/inode.c ++++ b/fs/fat/inode.c +@@ -1238,6 +1238,19 @@ static int fat_read_root(struct inode *inode) + return 0; + } + ++static unsigned long calc_fat_clusters(struct super_block *sb) ++{ ++ struct msdos_sb_info *sbi = MSDOS_SB(sb); ++ ++ /* Divide first to avoid overflow */ ++ if (sbi->fat_bits != 12) { ++ unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits; ++ return ent_per_sec * sbi->fat_length; ++ } ++ ++ return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++} ++ + /* + * Read the super block of an MS-DOS FS. + */ +@@ -1434,7 +1447,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, + sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; + + /* check that FAT table does not overflow */ +- fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++ fat_clusters = calc_fat_clusters(sb); + total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); + if (total_clusters > MAX_FAT(sb)) { + if (!silent) diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 216b419..350a088 100644 --- a/fs/fat/namei_msdos.c @@ -67711,7 +67852,7 @@ index dfadc96..23c5182 100644 #if __GNUC_MINOR__ > 0 diff --git a/include/linux/compiler.h b/include/linux/compiler.h -index 320d6c9..df26a76 100644 +index 320d6c9..2d1df6b 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -5,31 +5,51 @@ @@ -67824,22 +67965,26 @@ index 320d6c9..df26a76 100644 /* Simple shorthand for a section definition */ #ifndef __section # define __section(S) __attribute__ ((__section__(#S))) -@@ -294,6 +348,14 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); - # define __compiletime_error(message) +@@ -292,6 +346,18 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #endif - + #ifndef __compiletime_error + # define __compiletime_error(message) ++# define __compiletime_error_fallback(condition) \ ++ do { ((void)sizeof(char[1 - 2*!!(condition)])); } while (0) ++#else ++# define __compiletime_error_fallback(condition) do { } while (0) ++#endif ++ +#ifndef __size_overflow +# define __size_overflow(...) +#endif + +#ifndef __intentional_overflow +# define __intentional_overflow(...) -+#endif -+ + #endif + /* - * Prevent the compiler from merging or refetching accesses. The compiler - * is also forbidden from reordering successive instances of ACCESS_ONCE(), -@@ -306,6 +368,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); +@@ -306,6 +372,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); * use is to mediate communication between process-level code and irq/NMI * handlers, all running on the same CPU. */ @@ -69802,6 +69947,53 @@ index 3875719..4cd454c 100644 /* This macro allows us to keep printk typechecking */ static __printf(1, 2) +diff --git a/include/linux/kernel.h b/include/linux/kernel.h +index a70783d..77f7750 100644 +--- a/include/linux/kernel.h ++++ b/include/linux/kernel.h +@@ -696,24 +696,30 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } + * @condition: the condition which the compiler should know is false. + * + * If you have some code which relies on certain constants being equal, or +- * other compile-time-evaluated condition, you should use BUILD_BUG_ON to ++ * some other compile-time-evaluated condition, you should use BUILD_BUG_ON to + * detect if someone changes it. + * +- * The implementation uses gcc's reluctance to create a negative array, but +- * gcc (as of 4.4) only emits that error for obvious cases (eg. not arguments +- * to inline functions). So as a fallback we use the optimizer; if it can't +- * prove the condition is false, it will cause a link error on the undefined +- * "__build_bug_on_failed". This error message can be harder to track down +- * though, hence the two different methods. ++ * The implementation uses gcc's reluctance to create a negative array, but gcc ++ * (as of 4.4) only emits that error for obvious cases (e.g. not arguments to ++ * inline functions). Luckily, in 4.3 they added the "error" function ++ * attribute just for this type of case. Thus, we use a negative sized array ++ * (should always create an error on gcc versions older than 4.4) and then call ++ * an undefined function with the error attribute (should always create an ++ * error on gcc 4.3 and later). If for some reason, neither creates a ++ * compile-time error, we'll still have a link-time error, which is harder to ++ * track down. + */ + #ifndef __OPTIMIZE__ + #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + #else +-extern int __build_bug_on_failed; +-#define BUILD_BUG_ON(condition) \ +- do { \ +- ((void)sizeof(char[1 - 2*!!(condition)])); \ +- if (condition) __build_bug_on_failed = 1; \ ++#define BUILD_BUG_ON(condition) \ ++ do { \ ++ bool __cond = !!(condition); \ ++ extern void __build_bug_on_failed(void) \ ++ __compiletime_error("BUILD_BUG_ON failed"); \ ++ if (__cond) \ ++ __build_bug_on_failed(); \ ++ __compiletime_error_fallback(__cond); \ + } while(0) + #endif + #endif /* __CHECKER__ */ diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 9efd081..19f989c 100644 --- a/include/linux/key-type.h @@ -80550,7 +80742,7 @@ index 2a07f97..2cdc054 100644 set_page_address(page, (void *)vaddr); diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 470cbb4..8d01b5a 100644 +index 470cbb4..9fd73bc 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -704,7 +704,7 @@ out: @@ -80562,6 +80754,20 @@ index 470cbb4..8d01b5a 100644 return VM_FAULT_OOM; /* if an huge pmd materialized from under us just retry later */ if (unlikely(pmd_trans_huge(*pmd))) +@@ -1937,7 +1937,12 @@ static void collapse_huge_page(struct mm_struct *mm, + pte_unmap(pte); + spin_lock(&mm->page_table_lock); + BUG_ON(!pmd_none(*pmd)); +- set_pmd_at(mm, address, pmd, _pmd); ++ /* ++ * We can only use set_pmd_at when establishing ++ * hugepmds and never for establishing regular pmds that ++ * points to regular pagetables. Use pmd_populate for that ++ */ ++ pmd_populate(mm, pmd, pmd_pgtable(_pmd)); + spin_unlock(&mm->page_table_lock); + anon_vma_unlock(vma->anon_vma); + goto out; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 70b4733..ab692a7 100644 --- a/mm/hugetlb.c diff --git a/3.9.4/0000_README b/3.9.4/0000_README index 5540390..66c5468 100644 --- a/3.9.4/0000_README +++ b/3.9.4/0000_README @@ -2,7 +2,7 @@ README ----------------------------------------------------------------------------- Individual Patch Descriptions: ----------------------------------------------------------------------------- -Patch: 4420_grsecurity-2.9.1-3.9.4-201305251009.patch +Patch: 4420_grsecurity-2.9.1-3.9.4-201305292151.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/3.9.4/4420_grsecurity-2.9.1-3.9.4-201305251009.patch b/3.9.4/4420_grsecurity-2.9.1-3.9.4-201305292151.patch index 6715b49..8cdedca 100644 --- a/3.9.4/4420_grsecurity-2.9.1-3.9.4-201305251009.patch +++ b/3.9.4/4420_grsecurity-2.9.1-3.9.4-201305292151.patch @@ -17725,6 +17725,19 @@ index 74467fe..18793d5 100644 crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } +diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c +index afa64ad..dce67dd 100644 +--- a/arch/x86/kernel/crash_dump_64.c ++++ b/arch/x86/kernel/crash_dump_64.c +@@ -36,7 +36,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, + return -ENOMEM; + + if (userbuf) { +- if (copy_to_user(buf, vaddr + offset, csize)) { ++ if (copy_to_user((char __force_user *)buf, vaddr + offset, csize)) { + iounmap(vaddr); + return -EFAULT; + } diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index 37250fe..bf2ec74 100644 --- a/arch/x86/kernel/doublefault_32.c @@ -29551,7 +29564,7 @@ index 877b9a1..a8ecf42 100644 + pax_force_retaddr ret diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c -index 3cbe4538..fd756dc 100644 +index 3cbe4538..003d011 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -12,6 +12,7 @@ @@ -29562,7 +29575,7 @@ index 3cbe4538..fd756dc 100644 /* * Conventions : -@@ -49,13 +50,87 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) +@@ -49,13 +50,90 @@ static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) return ptr + len; } @@ -29599,6 +29612,7 @@ index 3cbe4538..fd756dc 100644 + case 0x25: /* and eax, imm32 */ \ + case 0x0d: /* or eax, imm32 */ \ + case 0xb8: /* mov eax, imm32 */ \ ++ case 0x35: /* xor eax, imm32 */ \ + case 0x3d: /* cmp eax, imm32 */ \ + case 0xa9: /* test eax, imm32 */ \ + DILUTE_CONST_SEQUENCE(_off, randkey); \ @@ -29614,6 +29628,10 @@ index 3cbe4538..fd756dc 100644 + /* mov esi, ecx */ \ + EMIT2(0x89, 0xce); \ + break; \ ++ case 0xe8: /* call rel imm32, always to known funcs */ \ ++ EMIT1(b1); \ ++ EMIT(_off, 4); \ ++ break; \ + case 0xe9: /* jmp rel imm32 */ \ + EMIT1(b1); \ + EMIT(_off, 4); \ @@ -29622,8 +29640,7 @@ index 3cbe4538..fd756dc 100644 + EMIT(0xcccccccc, 4); \ + break; \ + default: \ -+ EMIT1(b1); \ -+ EMIT(_off, 4); \ ++ BUILD_BUG(); \ + } \ +} while (0) + @@ -29639,8 +29656,7 @@ index 3cbe4538..fd756dc 100644 + /* imul eax, ecx */ \ + EMIT3(0x0f, 0xaf, 0xc1); \ + } else { \ -+ EMIT2(b1, b2); \ -+ EMIT(_off, 4); \ ++ BUILD_BUG(); \ + } \ +} while (0) +#else @@ -29650,7 +29666,7 @@ index 3cbe4538..fd756dc 100644 #define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */ #define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */ -@@ -90,6 +165,24 @@ do { \ +@@ -90,6 +168,24 @@ do { \ #define X86_JBE 0x76 #define X86_JA 0x77 @@ -29675,7 +29691,7 @@ index 3cbe4538..fd756dc 100644 #define EMIT_COND_JMP(op, offset) \ do { \ if (is_near(offset)) \ -@@ -97,6 +190,7 @@ do { \ +@@ -97,6 +193,7 @@ do { \ else { \ EMIT2(0x0f, op + 0x10); \ EMIT(offset, 4); /* jxx .+off32 */ \ @@ -29683,7 +29699,7 @@ index 3cbe4538..fd756dc 100644 } \ } while (0) -@@ -121,6 +215,11 @@ static inline void bpf_flush_icache(void *start, void *end) +@@ -121,6 +218,11 @@ static inline void bpf_flush_icache(void *start, void *end) set_fs(old_fs); } @@ -29695,7 +29711,7 @@ index 3cbe4538..fd756dc 100644 #define CHOOSE_LOAD_FUNC(K, func) \ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset) -@@ -146,7 +245,7 @@ static int pkt_type_offset(void) +@@ -146,7 +248,7 @@ static int pkt_type_offset(void) void bpf_jit_compile(struct sk_filter *fp) { @@ -29704,7 +29720,7 @@ index 3cbe4538..fd756dc 100644 u8 *prog; unsigned int proglen, oldproglen = 0; int ilen, i; -@@ -159,6 +258,9 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -159,6 +261,9 @@ void bpf_jit_compile(struct sk_filter *fp) unsigned int *addrs; const struct sock_filter *filter = fp->insns; int flen = fp->len; @@ -29714,7 +29730,7 @@ index 3cbe4538..fd756dc 100644 if (!bpf_jit_enable) return; -@@ -167,11 +269,19 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -167,11 +272,19 @@ void bpf_jit_compile(struct sk_filter *fp) if (addrs == NULL) return; @@ -29736,7 +29752,7 @@ index 3cbe4538..fd756dc 100644 addrs[i] = proglen; } cleanup_addr = proglen; /* epilogue address */ -@@ -282,10 +392,8 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -282,10 +395,8 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_ALU_MUL_K: /* A *= K */ if (is_imm8(K)) EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */ @@ -29749,7 +29765,7 @@ index 3cbe4538..fd756dc 100644 break; case BPF_S_ALU_DIV_X: /* A /= X; */ seen |= SEEN_XREG; -@@ -325,13 +433,23 @@ void bpf_jit_compile(struct sk_filter *fp) +@@ -325,13 +436,23 @@ void bpf_jit_compile(struct sk_filter *fp) break; case BPF_S_ALU_MOD_K: /* A %= K; */ EMIT2(0x31, 0xd2); /* xor %edx,%edx */ @@ -29773,7 +29789,7 @@ index 3cbe4538..fd756dc 100644 EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ break; case BPF_S_ALU_AND_X: -@@ -602,8 +720,7 @@ common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; +@@ -602,8 +723,7 @@ common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG; if (is_imm8(K)) { EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */ } else { @@ -29783,7 +29799,7 @@ index 3cbe4538..fd756dc 100644 } } else { EMIT2(0x89,0xde); /* mov %ebx,%esi */ -@@ -686,17 +803,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -686,17 +806,18 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; default: /* hmm, too complex filter, give up with jit compiler */ @@ -29806,7 +29822,7 @@ index 3cbe4538..fd756dc 100644 } proglen += ilen; addrs[i] = proglen; -@@ -717,11 +835,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -717,11 +838,9 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { @@ -29820,7 +29836,7 @@ index 3cbe4538..fd756dc 100644 } oldproglen = proglen; } -@@ -737,7 +853,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; +@@ -737,7 +856,10 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; bpf_flush_icache(image, image + proglen); fp->bpf_func = (void *)image; @@ -29832,7 +29848,7 @@ index 3cbe4538..fd756dc 100644 out: kfree(addrs); return; -@@ -745,18 +864,20 @@ out: +@@ -745,18 +867,20 @@ out: static void jit_free_defer(struct work_struct *arg) { @@ -32940,7 +32956,7 @@ index 519865b..e540db3 100644 subsys_dev_iter_init(&iter, subsys, NULL, NULL); while ((dev = subsys_dev_iter_next(&iter))) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c -index 01fc5b0..d0ed716 100644 +index 01fc5b0..917801f 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -348,7 +348,7 @@ int devtmpfs_mount(const char *mntdir) @@ -32952,6 +32968,21 @@ index 01fc5b0..d0ed716 100644 if (err) printk(KERN_INFO "devtmpfs: error mounting %i\n", err); else +@@ -373,11 +373,11 @@ static int devtmpfsd(void *p) + *err = sys_unshare(CLONE_NEWNS); + if (*err) + goto out; +- *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options); ++ *err = sys_mount((char __force_user *)"devtmpfs", (char __force_user *)"/", (char __force_user *)"devtmpfs", MS_SILENT, (char __force_user *)options); + if (*err) + goto out; +- sys_chdir("/.."); /* will traverse into overmounted root */ +- sys_chroot("."); ++ sys_chdir((char __force_user *)"/.."); /* will traverse into overmounted root */ ++ sys_chroot((char __force_user *)"."); + complete(&setup_done); + while (1) { + spin_lock(&req_lock); diff --git a/drivers/base/node.c b/drivers/base/node.c index fac124a..66bd4ab 100644 --- a/drivers/base/node.c @@ -33578,8 +33609,21 @@ index 3bb6fa3..34013fb 100644 default y source "drivers/s390/char/Kconfig" +diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c +index a48e05b..6bac831 100644 +--- a/drivers/char/agp/compat_ioctl.c ++++ b/drivers/char/agp/compat_ioctl.c +@@ -108,7 +108,7 @@ static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user + return -ENOMEM; + } + +- if (copy_from_user(usegment, (void __user *) ureserve.seg_list, ++ if (copy_from_user(usegment, (void __force_user *) ureserve.seg_list, + sizeof(*usegment) * ureserve.seg_count)) { + kfree(usegment); + kfree(ksegment); diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c -index 2e04433..22afc64 100644 +index 2e04433..771f2cc 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -817,7 +817,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) @@ -33591,6 +33635,15 @@ index 2e04433..22afc64 100644 return -EFAULT; client = agp_find_client_by_pid(reserve.pid); +@@ -847,7 +847,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) + if (segment == NULL) + return -ENOMEM; + +- if (copy_from_user(segment, (void __user *) reserve.seg_list, ++ if (copy_from_user(segment, (void __force_user *) reserve.seg_list, + sizeof(struct agp_segment) * reserve.seg_count)) { + kfree(segment); + return -EFAULT; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 21cb980..f15107c 100644 --- a/drivers/char/genrtc.c @@ -33685,7 +33738,7 @@ index 0ac9b45..6179fb5 100644 new_smi->interrupt_disabled = 1; atomic_set(&new_smi->stop_operation, 0); diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 2c644af..b867b3e 100644 +index 2c644af..d4d7f17 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -18,6 +18,7 @@ @@ -33766,6 +33819,15 @@ index 2c644af..b867b3e 100644 unxlate_dev_mem_ptr(p, ptr); if (remaining) return -EFAULT; +@@ -378,7 +409,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf, + else + csize = count; + +- rc = copy_oldmem_page(pfn, buf, csize, offset, 1); ++ rc = copy_oldmem_page(pfn, (char __force_kernel *)buf, csize, offset, 1); + if (rc < 0) + return rc; + buf += csize; @@ -398,9 +429,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -33909,7 +33971,7 @@ index 5c5cc00..ac9edb7 100644 if (cmd != SIOCWANDEV) diff --git a/drivers/char/random.c b/drivers/char/random.c -index 32a6c57..e7f0f7b 100644 +index 32a6c57..98038d5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -272,8 +272,13 @@ @@ -33955,7 +34017,85 @@ index 32a6c57..e7f0f7b 100644 smp_wmb(); if (out) -@@ -1024,7 +1036,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, +@@ -865,16 +877,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, + if (r->entropy_count / 8 < min + reserved) { + nbytes = 0; + } else { ++ int entropy_count, orig; ++retry: ++ entropy_count = orig = ACCESS_ONCE(r->entropy_count); + /* If limited, never pull more than available */ +- if (r->limit && nbytes + reserved >= r->entropy_count / 8) +- nbytes = r->entropy_count/8 - reserved; ++ if (r->limit && nbytes + reserved >= entropy_count / 8) ++ nbytes = entropy_count/8 - reserved; + +- if (r->entropy_count / 8 >= nbytes + reserved) +- r->entropy_count -= nbytes*8; +- else +- r->entropy_count = reserved; ++ if (entropy_count / 8 >= nbytes + reserved) { ++ entropy_count -= nbytes*8; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; ++ } else { ++ entropy_count = reserved; ++ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) ++ goto retry; ++ } + +- if (r->entropy_count < random_write_wakeup_thresh) ++ if (entropy_count < random_write_wakeup_thresh) + wakeup_write = 1; + } + +@@ -957,10 +977,23 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + { + ssize_t ret = 0, i; + __u8 tmp[EXTRACT_SIZE]; ++ unsigned long flags; + + /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ +- if (fips_enabled && !r->last_data_init) +- nbytes += EXTRACT_SIZE; ++ if (fips_enabled) { ++ spin_lock_irqsave(&r->lock, flags); ++ if (!r->last_data_init) { ++ r->last_data_init = true; ++ spin_unlock_irqrestore(&r->lock, flags); ++ trace_extract_entropy(r->name, EXTRACT_SIZE, ++ r->entropy_count, _RET_IP_); ++ xfer_secondary_pool(r, EXTRACT_SIZE); ++ extract_buf(r, tmp); ++ spin_lock_irqsave(&r->lock, flags); ++ memcpy(r->last_data, tmp, EXTRACT_SIZE); ++ } ++ spin_unlock_irqrestore(&r->lock, flags); ++ } + + trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); + xfer_secondary_pool(r, nbytes); +@@ -970,19 +1003,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + extract_buf(r, tmp); + + if (fips_enabled) { +- unsigned long flags; +- +- +- /* prime last_data value if need be, per fips 140-2 */ +- if (!r->last_data_init) { +- spin_lock_irqsave(&r->lock, flags); +- memcpy(r->last_data, tmp, EXTRACT_SIZE); +- r->last_data_init = true; +- nbytes -= EXTRACT_SIZE; +- spin_unlock_irqrestore(&r->lock, flags); +- extract_buf(r, tmp); +- } +- + spin_lock_irqsave(&r->lock, flags); + if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) + panic("Hardware RNG duplicated output!\n"); +@@ -1024,7 +1044,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, extract_buf(r, tmp); i = min_t(int, nbytes, EXTRACT_SIZE); @@ -33964,7 +34104,7 @@ index 32a6c57..e7f0f7b 100644 ret = -EFAULT; break; } -@@ -1360,7 +1372,7 @@ EXPORT_SYMBOL(generate_random_uuid); +@@ -1360,7 +1380,7 @@ EXPORT_SYMBOL(generate_random_uuid); #include <linux/sysctl.h> static int min_read_thresh = 8, min_write_thresh; @@ -33973,7 +34113,7 @@ index 32a6c57..e7f0f7b 100644 static int max_write_thresh = INPUT_POOL_WORDS * 32; static char sysctl_bootid[16]; -@@ -1376,7 +1388,7 @@ static char sysctl_bootid[16]; +@@ -1376,7 +1396,7 @@ static char sysctl_bootid[16]; static int proc_do_uuid(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -35984,6 +36124,28 @@ index 3eb1486..0a47ee9 100644 } while (*seqno == 0); if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) { +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +index c509d40..3b640c3 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +@@ -138,7 +138,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, + int ret; + + num_clips = arg->num_clips; +- clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; ++ clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr; + + if (unlikely(num_clips == 0)) + return 0; +@@ -222,7 +222,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, + int ret; + + num_clips = arg->num_clips; +- clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; ++ clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr; + + if (unlikely(num_clips == 0)) + return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 4640adb..e1384ed 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -36341,6 +36503,19 @@ index 29015eb..af2d8e9 100644 /* Wrapper access functions for multiplexed SMBus */ static DEFINE_MUTEX(nforce2_lock); +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index c3ccdea..5b3dc1a 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -271,7 +271,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, + break; + } + +- data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; ++ data_ptrs[i] = (u8 __force_user *)rdwr_pa[i].buf; + rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); + if (IS_ERR(rdwr_pa[i].buf)) { + res = PTR_ERR(rdwr_pa[i].buf); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 8126824..55a2798 100644 --- a/drivers/ide/ide-cd.c @@ -38425,11 +38600,72 @@ index 9578a67..31aa652 100644 /* debug */ static int dvb_usb_dw2102_debug; +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index 7157af3..139e91a 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -326,7 +326,7 @@ struct v4l2_buffer32 { + __u32 reserved; + }; + +-static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, ++static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, + enum v4l2_memory memory) + { + void __user *up_pln; +@@ -355,7 +355,7 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, + return 0; + } + +-static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32, ++static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, + enum v4l2_memory memory) + { + if (copy_in_user(up32, up, 2 * sizeof(__u32)) || +@@ -772,7 +772,7 @@ static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subde + put_user(kp->start_block, &up->start_block) || + put_user(kp->blocks, &up->blocks) || + put_user(tmp, &up->edid) || +- copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved))) ++ copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + return -EFAULT; + return 0; + } diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index aa6e7c7..4cd8061 100644 +index aa6e7c7..cb5de87 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1923,7 +1923,8 @@ struct v4l2_ioctl_info { +@@ -236,7 +236,7 @@ static void v4l_print_format(const void *arg, bool write_only) + const struct v4l2_vbi_format *vbi; + const struct v4l2_sliced_vbi_format *sliced; + const struct v4l2_window *win; +- const struct v4l2_clip *clip; ++ const struct v4l2_clip __user *pclip; + unsigned i; + + pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); +@@ -284,12 +284,16 @@ static void v4l_print_format(const void *arg, bool write_only) + win->w.left, win->w.top, + prt_names(win->field, v4l2_field_names), + win->chromakey, win->bitmap, win->global_alpha); +- clip = win->clips; ++ pclip = win->clips; + for (i = 0; i < win->clipcount; i++) { ++ struct v4l2_clip clip; ++ ++ if (copy_from_user(&clip, pclip, sizeof clip)) ++ break; + printk(KERN_DEBUG "clip %u: wxh=%dx%d, x,y=%d,%d\n", +- i, clip->c.width, clip->c.height, +- clip->c.left, clip->c.top); +- clip = clip->next; ++ i, clip.c.width, clip.c.height, ++ clip.c.left, clip.c.top); ++ pclip = clip.next; + } + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: +@@ -1923,7 +1927,8 @@ struct v4l2_ioctl_info { struct file *file, void *fh, void *p); } u; void (*debug)(const void *arg, bool write_only); @@ -38439,7 +38675,7 @@ index aa6e7c7..4cd8061 100644 /* This control needs a priority check */ #define INFO_FL_PRIO (1 << 0) -@@ -2108,7 +2109,7 @@ static long __video_do_ioctl(struct file *file, +@@ -2108,7 +2113,7 @@ static long __video_do_ioctl(struct file *file, struct video_device *vfd = video_devdata(file); const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; bool write_only = false; @@ -38448,6 +38684,33 @@ index aa6e7c7..4cd8061 100644 const struct v4l2_ioctl_info *info; void *fh = file->private_data; struct v4l2_fh *vfh = NULL; +@@ -2193,7 +2198,7 @@ done: + } + + static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, +- void * __user *user_ptr, void ***kernel_ptr) ++ void __user **user_ptr, void ***kernel_ptr) + { + int ret = 0; + +@@ -2209,7 +2214,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, + ret = -EINVAL; + break; + } +- *user_ptr = (void __user *)buf->m.planes; ++ *user_ptr = (void __force_user *)buf->m.planes; + *kernel_ptr = (void *)&buf->m.planes; + *array_size = sizeof(struct v4l2_plane) * buf->length; + ret = 1; +@@ -2244,7 +2249,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, + ret = -EINVAL; + break; + } +- *user_ptr = (void __user *)ctrls->controls; ++ *user_ptr = (void __force_user *)ctrls->controls; + *kernel_ptr = (void *)&ctrls->controls; + *array_size = sizeof(struct v4l2_ext_control) + * ctrls->count; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index fb69baa..3aeea2e 100644 --- a/drivers/message/fusion/mptbase.c @@ -47532,6 +47795,19 @@ index fef20db..d28b1ab 100644 if (!file->private_data) return -ENOMEM; return 0; +diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c +index 0ad61c6..f198bd7 100644 +--- a/fs/9p/vfs_addr.c ++++ b/fs/9p/vfs_addr.c +@@ -185,7 +185,7 @@ static int v9fs_vfs_writepage_locked(struct page *page) + + retval = v9fs_file_write_internal(inode, + v9inode->writeback_fid, +- (__force const char __user *)buffer, ++ (const char __force_user *)buffer, + len, &offset, 0); + if (retval > 0) + retval = 0; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index d86edc8..40ff2fb 100644 --- a/fs/9p/vfs_inode.c @@ -47769,7 +48045,7 @@ index bbc8f88..7c7ac97 100644 fd_offset + ex.a_text); if (error != N_DATADDR(ex)) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 86af964..8a1da7e 100644 +index 86af964..5d53bf6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -34,6 +34,7 @@ @@ -48004,7 +48280,7 @@ index 86af964..8a1da7e 100644 +#endif + +#ifdef CONFIG_PAX_EMUTRAMP -+ if (pax_flags_softmode & MF_PAX_EMUTRAMP) ++ if ((pax_flags_softmode & MF_PAX_EMUTRAMP) && (pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))) + pax_flags |= MF_PAX_EMUTRAMP; +#endif + @@ -48465,6 +48741,15 @@ index 86af964..8a1da7e 100644 fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); } +@@ -1394,7 +1841,7 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata, + { + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); +- copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo); ++ copy_siginfo_to_user((user_siginfo_t __force_user *) csigdata, siginfo); + set_fs(old_fs); + fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata); + } @@ -2015,14 +2462,14 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, } @@ -49580,7 +49865,7 @@ index a81147e..20bf2b5 100644 /* diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c -index 3ced75f..1eeca06 100644 +index 3ced75f..b28d192 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -623,7 +623,7 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, @@ -49592,6 +49877,17 @@ index 3ced75f..1eeca06 100644 if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || __get_user(ss.port_high, &ss32->port_high)) return -EFAULT; +@@ -704,8 +704,8 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, + for (i = 0; i < nmsgs; i++) { + if (copy_in_user(&tmsgs[i].addr, &umsgs[i].addr, 3*sizeof(u16))) + return -EFAULT; +- if (get_user(datap, &umsgs[i].buf) || +- put_user(compat_ptr(datap), &tmsgs[i].buf)) ++ if (get_user(datap, (u8 __user * __user *)&umsgs[i].buf) || ++ put_user(compat_ptr(datap), (u8 __user * __user *)&tmsgs[i].buf)) + return -EFAULT; + } + return sys_ioctl(fd, cmd, (unsigned long)tdata); @@ -798,7 +798,7 @@ static int compat_ioctl_preallocate(struct file *file, copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) || copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) || @@ -49839,7 +50135,7 @@ index 6a16053..2155147 100644 return rc; } diff --git a/fs/exec.c b/fs/exec.c -index 6d56ff2..fe44505 100644 +index 6d56ff2..3bc6638 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -55,8 +55,20 @@ @@ -50016,7 +50312,7 @@ index 6d56ff2..fe44505 100644 mm_segment_t oldfs = get_fs(); struct user_arg_ptr argv = { - .ptr.native = (const char __user *const __user *)__argv, -+ .ptr.native = (const char __force_user *const __force_user *)__argv, ++ .ptr.native = (const char __force_user * const __force_user *)__argv, }; set_fs(KERNEL_DS); @@ -50540,8 +50836,8 @@ index 6d56ff2..fe44505 100644 +#endif + +#else -+ unsigned long textlow = _stext; -+ unsigned long texthigh = _etext; ++ unsigned long textlow = (unsigned long)_stext; ++ unsigned long texthigh = (unsigned long)_etext; +#endif + + if (high <= textlow || low > texthigh) @@ -50813,6 +51109,39 @@ index febbe0e..782c4fd 100644 static int parse_strtoul(const char *buf, unsigned long max, unsigned long *value) +diff --git a/fs/fat/inode.c b/fs/fat/inode.c +index acf6e47..e7a7fde 100644 +--- a/fs/fat/inode.c ++++ b/fs/fat/inode.c +@@ -1223,6 +1223,19 @@ static int fat_read_root(struct inode *inode) + return 0; + } + ++static unsigned long calc_fat_clusters(struct super_block *sb) ++{ ++ struct msdos_sb_info *sbi = MSDOS_SB(sb); ++ ++ /* Divide first to avoid overflow */ ++ if (sbi->fat_bits != 12) { ++ unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits; ++ return ent_per_sec * sbi->fat_length; ++ } ++ ++ return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++} ++ + /* + * Read the super block of an MS-DOS FS. + */ +@@ -1427,7 +1440,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, + sbi->dirty = b->fat16.state & FAT_STATE_DIRTY; + + /* check that FAT table does not overflow */ +- fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; ++ fat_clusters = calc_fat_clusters(sb); + total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); + if (total_clusters > MAX_FAT(sb)) { + if (!silent) diff --git a/fs/fcntl.c b/fs/fcntl.c index 6599222..e7bf0de 100644 --- a/fs/fcntl.c @@ -53240,7 +53569,7 @@ index 85e40d1..b66744e 100644 out: return len; diff --git a/fs/namespace.c b/fs/namespace.c -index e945b81..1dd8104 100644 +index e945b81..fc018e2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1219,6 +1219,9 @@ static int do_umount(struct mount *mnt, int flags) @@ -53263,6 +53592,24 @@ index e945b81..1dd8104 100644 return retval; } +@@ -1257,7 +1263,7 @@ static inline bool may_mount(void) + * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD + */ + +-SYSCALL_DEFINE2(umount, char __user *, name, int, flags) ++SYSCALL_DEFINE2(umount, const char __user *, name, int, flags) + { + struct path path; + struct mount *mnt; +@@ -1297,7 +1303,7 @@ out: + /* + * The 2.0 compatible umount. No flags. + */ +-SYSCALL_DEFINE1(oldumount, char __user *, name) ++SYSCALL_DEFINE1(oldumount, const char __user *, name) + { + return sys_umount(name, 0); + } @@ -2267,6 +2273,16 @@ long do_mount(const char *dev_name, const char *dir_name, MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | MS_STRICTATIME); @@ -53290,6 +53637,17 @@ index e945b81..1dd8104 100644 return retval; } +@@ -2454,8 +2473,8 @@ struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) + } + EXPORT_SYMBOL(mount_subtree); + +-SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, +- char __user *, type, unsigned long, flags, void __user *, data) ++SYSCALL_DEFINE5(mount, const char __user *, dev_name, const char __user *, dir_name, ++ const char __user *, type, unsigned long, flags, void __user *, data) + { + int ret; + char *kernel_type; @@ -2567,6 +2586,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, if (error) goto out2; @@ -55257,6 +55615,36 @@ index 56123a6..5a2f6ec 100644 } else if (mm) { pid_t tid = vm_is_stack(priv->task, vma, is_pid); +diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c +index b870f74..e9048df 100644 +--- a/fs/proc/vmcore.c ++++ b/fs/proc/vmcore.c +@@ -98,9 +98,13 @@ static ssize_t read_from_oldmem(char *buf, size_t count, + nr_bytes = count; + + /* If pfn is not ram, return zeros for sparse dump files */ +- if (pfn_is_ram(pfn) == 0) +- memset(buf, 0, nr_bytes); +- else { ++ if (pfn_is_ram(pfn) == 0) { ++ if (userbuf) { ++ if (clear_user((char __force_user *)buf, nr_bytes)) ++ return -EFAULT; ++ } else ++ memset(buf, 0, nr_bytes); ++ } else { + tmp = copy_oldmem_page(pfn, buf, nr_bytes, + offset, userbuf); + if (tmp < 0) +@@ -185,7 +189,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, + if (tsz > nr_bytes) + tsz = nr_bytes; + +- tmp = read_from_oldmem(buffer, tsz, &start, 1); ++ tmp = read_from_oldmem((char __force_kernel *)buffer, tsz, &start, 1); + if (tmp < 0) + return tmp; + buflen -= tsz; diff --git a/fs/qnx6/qnx6.h b/fs/qnx6/qnx6.h index b00fcc9..e0c6381 100644 --- a/fs/qnx6/qnx6.h @@ -55301,6 +55689,19 @@ index 16e8abb..2dcf914 100644 "a_genl_family, 0, QUOTA_NL_C_WARNING); if (!msg_head) { printk(KERN_ERR +diff --git a/fs/read_write.c b/fs/read_write.c +index e6ddc8d..9155227 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -429,7 +429,7 @@ ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t + + old_fs = get_fs(); + set_fs(get_ds()); +- p = (__force const char __user *)buf; ++ p = (const char __force_user *)buf; + if (count > MAX_RW_COUNT) + count = MAX_RW_COUNT; + if (file->f_op->write) diff --git a/fs/readdir.c b/fs/readdir.c index fee38e0..12fdf47 100644 --- a/fs/readdir.c @@ -71166,9 +71567,25 @@ index a5ffd32..0935dea 100644 extern dma_addr_t swiotlb_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h -index 313a8e0..1da8fc6 100644 +index 313a8e0..6b273a9 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h +@@ -418,11 +418,11 @@ asmlinkage long sys_sync(void); + asmlinkage long sys_fsync(unsigned int fd); + asmlinkage long sys_fdatasync(unsigned int fd); + asmlinkage long sys_bdflush(int func, long data); +-asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, +- char __user *type, unsigned long flags, ++asmlinkage long sys_mount(const char __user *dev_name, const char __user *dir_name, ++ const char __user *type, unsigned long flags, + void __user *data); +-asmlinkage long sys_umount(char __user *name, int flags); +-asmlinkage long sys_oldumount(char __user *name); ++asmlinkage long sys_umount(const char __user *name, int flags); ++asmlinkage long sys_oldumount(const char __user *name); + asmlinkage long sys_truncate(const char __user *path, long length); + asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); + asmlinkage long sys_stat(const char __user *filename, @@ -634,7 +634,7 @@ asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); asmlinkage long sys_send(int, void __user *, size_t, unsigned); @@ -72924,9 +73341,27 @@ index f5b978a..69dbfe8 100644 if (!S_ISBLK(stat.st_mode)) return 0; diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c -index a32ec1c..ac08811 100644 +index a32ec1c..60a6659 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c +@@ -37,13 +37,13 @@ static int init_linuxrc(struct subprocess_info *info, struct cred *new) + { + sys_unshare(CLONE_FS | CLONE_FILES); + /* stdin/stdout/stderr for /linuxrc */ +- sys_open("/dev/console", O_RDWR, 0); ++ sys_open((const char __force_user *)"/dev/console", O_RDWR, 0); + sys_dup(0); + sys_dup(0); + /* move initrd over / and chdir/chroot in initrd root */ +- sys_chdir("/root"); +- sys_mount(".", "/", NULL, MS_MOVE, NULL); +- sys_chroot("."); ++ sys_chdir((const char __force_user *)"/root"); ++ sys_mount((char __force_user *)".", (char __force_user *)"/", NULL, MS_MOVE, NULL); ++ sys_chroot((const char __force_user *)"."); + sys_setsid(); + return 0; + } @@ -58,8 +58,8 @@ static void __init handle_initrd(void) create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ @@ -73149,7 +73584,7 @@ index a67ef9d..3d88592 100644 next_state = Reset; return 0; diff --git a/init/main.c b/init/main.c -index 63534a1..8abcaf1 100644 +index 63534a1..85feae2 100644 --- a/init/main.c +++ b/init/main.c @@ -98,6 +98,8 @@ static inline void mark_rodata_ro(void) { } @@ -73286,6 +73721,17 @@ index 63534a1..8abcaf1 100644 } /* +@@ -811,8 +884,8 @@ static int run_init_process(const char *init_filename) + { + argv_init[0] = init_filename; + return do_execve(init_filename, +- (const char __user *const __user *)argv_init, +- (const char __user *const __user *)envp_init); ++ (const char __user *const __force_user *)argv_init, ++ (const char __user *const __force_user *)envp_init); + } + + static noinline void __init kernel_init_freeable(void); @@ -890,7 +963,7 @@ static noinline void __init kernel_init_freeable(void) do_basic_setup(); @@ -74134,7 +74580,7 @@ index 00eb8f7..d7e3244 100644 #ifdef CONFIG_MODULE_UNLOAD { diff --git a/kernel/events/core.c b/kernel/events/core.c -index 9fcb094..5c06aeb 100644 +index 9fcb094..fd68c54 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -155,7 +155,11 @@ static struct srcu_struct pmus_srcu; @@ -74193,6 +74639,15 @@ index 9fcb094..5c06aeb 100644 arch_perf_update_userpage(userpg, now); +@@ -3886,7 +3890,7 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size, + + /* Data. */ + sp = perf_user_stack_pointer(regs); +- rem = __output_copy_user(handle, (void *) sp, dump_size); ++ rem = __output_copy_user(handle, (void __user *) sp, dump_size); + dyn_size = dump_size - rem; + + perf_output_skip(handle, rem); @@ -3974,11 +3978,11 @@ static void perf_output_read_one(struct perf_output_handle *handle, values[n++] = perf_event_count(event); if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { @@ -74245,6 +74700,44 @@ index 9fcb094..5c06aeb 100644 &parent_event->child_total_time_running); /* +diff --git a/kernel/events/internal.h b/kernel/events/internal.h +index eb675c4..54912ff 100644 +--- a/kernel/events/internal.h ++++ b/kernel/events/internal.h +@@ -77,10 +77,10 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb) + return rb->nr_pages << (PAGE_SHIFT + page_order(rb)); + } + +-#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ ++#define DEFINE_OUTPUT_COPY(func_name, memcpy_func, user) \ + static inline unsigned int \ + func_name(struct perf_output_handle *handle, \ +- const void *buf, unsigned int len) \ ++ const void user *buf, unsigned int len) \ + { \ + unsigned long size, written; \ + \ +@@ -112,17 +112,17 @@ static inline int memcpy_common(void *dst, const void *src, size_t n) + return n; + } + +-DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) ++DEFINE_OUTPUT_COPY(__output_copy, memcpy_common, ) + + #define MEMCPY_SKIP(dst, src, n) (n) + +-DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) ++DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP, ) + + #ifndef arch_perf_out_copy_user + #define arch_perf_out_copy_user __copy_from_user_inatomic + #endif + +-DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user) ++DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user, __user) + + /* Callchain handling */ + extern struct perf_callchain_entry * diff --git a/kernel/exit.c b/kernel/exit.c index 60bc027..ca6d727 100644 --- a/kernel/exit.c @@ -79822,6 +80315,24 @@ index b32b70c..e512eb0 100644 pkmap_count[last_pkmap_nr] = 1; set_page_address(page, (void *)vaddr); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index e2f7f5aa..a4510d4 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2318,7 +2318,12 @@ static void collapse_huge_page(struct mm_struct *mm, + pte_unmap(pte); + spin_lock(&mm->page_table_lock); + BUG_ON(!pmd_none(*pmd)); +- set_pmd_at(mm, address, pmd, _pmd); ++ /* ++ * We can only use set_pmd_at when establishing ++ * hugepmds and never for establishing regular pmds that ++ * points to regular pagetables. Use pmd_populate for that ++ */ ++ pmd_populate(mm, pmd, pmd_pgtable(_pmd)); + spin_unlock(&mm->page_table_lock); + anon_vma_unlock_write(vma->anon_vma); + goto out; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 1a12f5b..a85b8fc 100644 --- a/mm/hugetlb.c @@ -82287,6 +82798,133 @@ index 0dceed8..671951c 100644 vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); +diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c +index be04122..6725ff1 100644 +--- a/mm/mmu_notifier.c ++++ b/mm/mmu_notifier.c +@@ -40,48 +40,44 @@ void __mmu_notifier_release(struct mm_struct *mm) + int id; + + /* +- * srcu_read_lock() here will block synchronize_srcu() in +- * mmu_notifier_unregister() until all registered +- * ->release() callouts this function makes have +- * returned. ++ * SRCU here will block mmu_notifier_unregister until ++ * ->release returns. + */ + id = srcu_read_lock(&srcu); ++ hlist_for_each_entry_rcu(mn, &mm->mmu_notifier_mm->list, hlist) ++ /* ++ * If ->release runs before mmu_notifier_unregister it must be ++ * handled, as it's the only way for the driver to flush all ++ * existing sptes and stop the driver from establishing any more ++ * sptes before all the pages in the mm are freed. ++ */ ++ if (mn->ops->release) ++ mn->ops->release(mn, mm); ++ srcu_read_unlock(&srcu, id); ++ + spin_lock(&mm->mmu_notifier_mm->lock); + while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { + mn = hlist_entry(mm->mmu_notifier_mm->list.first, + struct mmu_notifier, + hlist); +- + /* +- * Unlink. This will prevent mmu_notifier_unregister() +- * from also making the ->release() callout. ++ * We arrived before mmu_notifier_unregister so ++ * mmu_notifier_unregister will do nothing other than to wait ++ * for ->release to finish and for mmu_notifier_unregister to ++ * return. + */ + hlist_del_init_rcu(&mn->hlist); +- spin_unlock(&mm->mmu_notifier_mm->lock); +- +- /* +- * Clear sptes. (see 'release' description in mmu_notifier.h) +- */ +- if (mn->ops->release) +- mn->ops->release(mn, mm); +- +- spin_lock(&mm->mmu_notifier_mm->lock); + } + spin_unlock(&mm->mmu_notifier_mm->lock); + + /* +- * All callouts to ->release() which we have done are complete. +- * Allow synchronize_srcu() in mmu_notifier_unregister() to complete +- */ +- srcu_read_unlock(&srcu, id); +- +- /* +- * mmu_notifier_unregister() may have unlinked a notifier and may +- * still be calling out to it. Additionally, other notifiers +- * may have been active via vmtruncate() et. al. Block here +- * to ensure that all notifier callouts for this mm have been +- * completed and the sptes are really cleaned up before returning +- * to exit_mmap(). ++ * synchronize_srcu here prevents mmu_notifier_release from returning to ++ * exit_mmap (which would proceed with freeing all pages in the mm) ++ * until the ->release method returns, if it was invoked by ++ * mmu_notifier_unregister. ++ * ++ * The mmu_notifier_mm can't go away from under us because one mm_count ++ * is held by exit_mmap. + */ + synchronize_srcu(&srcu); + } +@@ -292,31 +288,34 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) + { + BUG_ON(atomic_read(&mm->mm_count) <= 0); + +- spin_lock(&mm->mmu_notifier_mm->lock); + if (!hlist_unhashed(&mn->hlist)) { ++ /* ++ * SRCU here will force exit_mmap to wait for ->release to ++ * finish before freeing the pages. ++ */ + int id; + +- /* +- * Ensure we synchronize up with __mmu_notifier_release(). +- */ + id = srcu_read_lock(&srcu); +- +- hlist_del_rcu(&mn->hlist); +- spin_unlock(&mm->mmu_notifier_mm->lock); +- +- if (mn->ops->release) +- mn->ops->release(mn, mm); +- + /* +- * Allow __mmu_notifier_release() to complete. ++ * exit_mmap will block in mmu_notifier_release to guarantee ++ * that ->release is called before freeing the pages. + */ ++ if (mn->ops->release) ++ mn->ops->release(mn, mm); + srcu_read_unlock(&srcu, id); +- } else ++ ++ spin_lock(&mm->mmu_notifier_mm->lock); ++ /* ++ * Can not use list_del_rcu() since __mmu_notifier_release ++ * can delete it before we hold the lock. ++ */ ++ hlist_del_init_rcu(&mn->hlist); + spin_unlock(&mm->mmu_notifier_mm->lock); ++ } + + /* +- * Wait for any running method to finish, including ->release() if it +- * was run by __mmu_notifier_release() instead of us. ++ * Wait for any running method to finish, of course including ++ * ->release if it was run by mmu_notifier_relase instead of us. + */ + synchronize_srcu(&srcu); + diff --git a/mm/mprotect.c b/mm/mprotect.c index 94722a4..07d9926 100644 --- a/mm/mprotect.c @@ -82811,6 +83449,19 @@ index 8fcced7..ebcd481 100644 if (order && (gfp_flags & __GFP_COMP)) prep_compound_page(page, order); +diff --git a/mm/page_io.c b/mm/page_io.c +index 6182870..4bba6a2 100644 +--- a/mm/page_io.c ++++ b/mm/page_io.c +@@ -205,7 +205,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) + struct file *swap_file = sis->swap_file; + struct address_space *mapping = swap_file->f_mapping; + struct iovec iov = { +- .iov_base = kmap(page), ++ .iov_base = (void __force_user *)kmap(page), + .iov_len = PAGE_SIZE, + }; + diff --git a/mm/percpu.c b/mm/percpu.c index 8c8e08f..73a5cda 100644 --- a/mm/percpu.c @@ -91446,6 +92097,19 @@ index d65fa7f..cbfe366 100644 err: if (iov != iovstack) kfree(iov); +diff --git a/security/keys/internal.h b/security/keys/internal.h +index 8bbefc3..299d03f 100644 +--- a/security/keys/internal.h ++++ b/security/keys/internal.h +@@ -240,7 +240,7 @@ extern long keyctl_instantiate_key_iov(key_serial_t, + extern long keyctl_invalidate_key(key_serial_t); + + extern long keyctl_instantiate_key_common(key_serial_t, +- const struct iovec *, ++ const struct iovec __user *, + unsigned, size_t, key_serial_t); + + /* diff --git a/security/keys/key.c b/security/keys/key.c index 8fb7c7b..ba3610d 100644 --- a/security/keys/key.c @@ -92335,10 +92999,10 @@ index 0000000..144dbee +targets += size_overflow_hash.h diff --git a/tools/gcc/checker_plugin.c b/tools/gcc/checker_plugin.c new file mode 100644 -index 0000000..d41b5af +index 0000000..22f03c0 --- /dev/null +++ b/tools/gcc/checker_plugin.c -@@ -0,0 +1,171 @@ +@@ -0,0 +1,172 @@ +/* + * Copyright 2011 by the PaX Team <pageexec@freemail.hu> + * Licensed under the GPL v2 @@ -92392,6 +93056,7 @@ index 0000000..d41b5af + +static struct plugin_info checker_plugin_info = { + .version = "201111150100", ++ .help = NULL, +}; + +#define ADDR_SPACE_KERNEL 0 |