diff options
author | Anthony G. Basile <blueness@gentoo.org> | 2012-03-08 21:00:06 -0500 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2012-03-08 21:00:06 -0500 |
commit | 5d847b8dac5c3df11e6bbcbb540f05d2cda90947 (patch) | |
tree | b9ec3c252274cc079254b41be99cb22e0f42717c | |
parent | Grsec/PaX: 2.9-2.6.32.57-201203022148 + 2.9-3.2.9-201203022148 (diff) | |
download | hardened-patchset-5d847b8dac5c3df11e6bbcbb540f05d2cda90947.tar.gz hardened-patchset-5d847b8dac5c3df11e6bbcbb540f05d2cda90947.tar.bz2 hardened-patchset-5d847b8dac5c3df11e6bbcbb540f05d2cda90947.zip |
Grsec/PaX: 2.9-2.6.32.58-201203062047 + 2.9-3.2.9-20120306205120120306
-rw-r--r-- | 2.6.32/0000_README | 2 | ||||
-rw-r--r-- | 2.6.32/1057_linux-2.6.32.58.patch | 1280 | ||||
-rw-r--r-- | 2.6.32/4420_grsecurity-2.9-2.6.32.58-201203062047.patch (renamed from 2.6.32/4420_grsecurity-2.9-2.6.32.57-201203022148.patch) | 794 | ||||
-rw-r--r-- | 3.2.9/0000_README | 2 | ||||
-rw-r--r-- | 3.2.9/4420_grsecurity-2.9-3.2.9-201203062051.patch (renamed from 3.2.9/4420_grsecurity-2.9-3.2.9-201203022148.patch) | 309 |
5 files changed, 1899 insertions, 488 deletions
diff --git a/2.6.32/0000_README b/2.6.32/0000_README index b14a3bc..c4a9001 100644 --- a/2.6.32/0000_README +++ b/2.6.32/0000_README @@ -22,7 +22,7 @@ Patch: 1056_linux-2.6.32.57.patch From: http://www.kernel.org Desc: Linux 2.6.32.57 -Patch: 4420_grsecurity-2.9-2.6.32.57-201203022148.patch +Patch: 4420_grsecurity-2.9-2.6.32.58-201203062047.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/2.6.32/1057_linux-2.6.32.58.patch b/2.6.32/1057_linux-2.6.32.58.patch new file mode 100644 index 0000000..5945acc --- /dev/null +++ b/2.6.32/1057_linux-2.6.32.58.patch @@ -0,0 +1,1280 @@ +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index eea4947..9cc3fe5 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -133,6 +133,11 @@ + disable_irq + .endm + ++ .macro save_and_disable_irqs_notrace, oldcpsr ++ mrs \oldcpsr, cpsr ++ disable_irq_notrace ++ .endm ++ + /* + * Restore interrupt state previously stored in a register. We don't + * guarantee that this will preserve the flags. +diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S +index e1bd975..632b626 100644 +--- a/arch/arm/mm/cache-v7.S ++++ b/arch/arm/mm/cache-v7.S +@@ -39,9 +39,15 @@ loop1: + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache ++#ifdef CONFIG_PREEMPT ++ save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic ++#endif + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr ++#ifdef CONFIG_PREEMPT ++ restore_irqs_notrace r9 ++#endif + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff +diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h +index 0c940d3..82c882c 100644 +--- a/arch/s390/include/asm/compat.h ++++ b/arch/s390/include/asm/compat.h +@@ -171,13 +171,6 @@ static inline int is_compat_task(void) + return test_thread_flag(TIF_31BIT); + } + +-#else +- +-static inline int is_compat_task(void) +-{ +- return 0; +-} +- + #endif + + static inline void __user *arch_compat_alloc_user_space(long len) +diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c +index 5417eb5..cea2855 100644 +--- a/arch/s390/kernel/process.c ++++ b/arch/s390/kernel/process.c +@@ -32,7 +32,6 @@ + #include <linux/kernel_stat.h> + #include <linux/syscalls.h> + #include <linux/compat.h> +-#include <asm/compat.h> + #include <asm/uaccess.h> + #include <asm/pgtable.h> + #include <asm/system.h> +diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c +index 08f8838..170e7af 100644 +--- a/arch/s390/kernel/ptrace.c ++++ b/arch/s390/kernel/ptrace.c +@@ -36,8 +36,8 @@ + #include <linux/regset.h> + #include <linux/tracehook.h> + #include <linux/seccomp.h> ++#include <linux/compat.h> + #include <trace/syscall.h> +-#include <asm/compat.h> + #include <asm/segment.h> + #include <asm/page.h> + #include <asm/pgtable.h> +diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c +index 061479f..0b2573a 100644 +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -43,6 +43,7 @@ + #include <linux/reboot.h> + #include <linux/topology.h> + #include <linux/ftrace.h> ++#include <linux/compat.h> + + #include <asm/ipl.h> + #include <asm/uaccess.h> +@@ -56,7 +57,6 @@ + #include <asm/ptrace.h> + #include <asm/sections.h> + #include <asm/ebcdic.h> +-#include <asm/compat.h> + #include <asm/kvm_virtio.h> + + long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | +diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c +index f4558cc..0ab74ae 100644 +--- a/arch/s390/mm/mmap.c ++++ b/arch/s390/mm/mmap.c +@@ -27,8 +27,8 @@ + #include <linux/personality.h> + #include <linux/mm.h> + #include <linux/module.h> ++#include <linux/compat.h> + #include <asm/pgalloc.h> +-#include <asm/compat.h> + + /* + * Top of mmap area (just below the process stack). +diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c +index 88f160b..107f6f7 100644 +--- a/crypto/sha512_generic.c ++++ b/crypto/sha512_generic.c +@@ -31,11 +31,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z) + return (x & y) | (z & (x | y)); + } + +-static inline u64 RORu64(u64 x, u64 y) +-{ +- return (x >> y) | (x << (64 - y)); +-} +- + static const u64 sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, +@@ -66,10 +61,10 @@ static const u64 sha512_K[80] = { + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, + }; + +-#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) +-#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) +-#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) +-#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) ++#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) ++#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) ++#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) ++#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) + + static inline void LOAD_OP(int I, u64 *W, const u8 *input) + { +@@ -78,7 +73,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input) + + static inline void BLEND_OP(int I, u64 *W) + { +- W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]); ++ W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]); + } + + static void +@@ -89,46 +84,42 @@ sha512_transform(u64 *state, const u8 *input) + int i; + u64 W[16]; + +- /* load the input */ +- for (i = 0; i < 16; i++) +- LOAD_OP(i, W, input); +- + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + +-#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \ +- t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \ +- t2 = e0(a) + Maj(a, b, c); \ +- d += t1; \ +- h = t1 + t2 +- +-#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \ +- BLEND_OP(i, W); \ +- t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \ +- t2 = e0(a) + Maj(a, b, c); \ +- d += t1; \ +- h = t1 + t2 +- +- for (i = 0; i < 16; i += 8) { +- SHA512_0_15(i, a, b, c, d, e, f, g, h); +- SHA512_0_15(i + 1, h, a, b, c, d, e, f, g); +- SHA512_0_15(i + 2, g, h, a, b, c, d, e, f); +- SHA512_0_15(i + 3, f, g, h, a, b, c, d, e); +- SHA512_0_15(i + 4, e, f, g, h, a, b, c, d); +- SHA512_0_15(i + 5, d, e, f, g, h, a, b, c); +- SHA512_0_15(i + 6, c, d, e, f, g, h, a, b); +- SHA512_0_15(i + 7, b, c, d, e, f, g, h, a); +- } +- for (i = 16; i < 80; i += 8) { +- SHA512_16_79(i, a, b, c, d, e, f, g, h); +- SHA512_16_79(i + 1, h, a, b, c, d, e, f, g); +- SHA512_16_79(i + 2, g, h, a, b, c, d, e, f); +- SHA512_16_79(i + 3, f, g, h, a, b, c, d, e); +- SHA512_16_79(i + 4, e, f, g, h, a, b, c, d); +- SHA512_16_79(i + 5, d, e, f, g, h, a, b, c); +- SHA512_16_79(i + 6, c, d, e, f, g, h, a, b); +- SHA512_16_79(i + 7, b, c, d, e, f, g, h, a); ++ /* now iterate */ ++ for (i=0; i<80; i+=8) { ++ if (!(i & 8)) { ++ int j; ++ ++ if (i < 16) { ++ /* load the input */ ++ for (j = 0; j < 16; j++) ++ LOAD_OP(i + j, W, input); ++ } else { ++ for (j = 0; j < 16; j++) { ++ BLEND_OP(i + j, W); ++ } ++ } ++ } ++ ++ t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)]; ++ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; ++ t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; ++ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; ++ t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; ++ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; ++ t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; ++ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; ++ t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; ++ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; ++ t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; ++ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; ++ t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; ++ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; ++ t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; ++ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index f6872f9..9589b7f 100644 +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -493,8 +493,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + if (!firmware) { + dev_err(device, "%s: kmalloc(struct firmware) failed\n", + __func__); +- retval = -ENOMEM; +- goto out; ++ return -ENOMEM; + } + + for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; +@@ -508,6 +507,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + return 0; + } + ++ read_lock_usermodehelper(); ++ ++ if (WARN_ON(usermodehelper_is_disabled())) { ++ dev_err(device, "firmware: %s will not be loaded\n", name); ++ retval = -EBUSY; ++ goto out; ++ } ++ + if (uevent) + dev_info(device, "firmware: requesting %s\n", name); + +@@ -545,6 +552,7 @@ error_kfree_fw: + kfree(firmware); + *firmware_p = NULL; + out: ++ read_unlock_usermodehelper(); + return retval; + } + +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index 59cccc9..a4592ec 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2057,11 +2057,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, + if (!nr) + return -ENOMEM; + +- if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { +- ret = -EFAULT; +- goto out; +- } +- + cgc.data_direction = CGC_DATA_READ; + while (nframes > 0) { + if (nr > nframes) +@@ -2070,7 +2065,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, + ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); + if (ret) + break; +- if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { ++ if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { + ret = -EFAULT; + break; + } +@@ -2078,7 +2073,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, + nframes -= nr; + lba += nr; + } +-out: + kfree(cgc.buffer); + return ret; + } +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index 96b39fc..6476022 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -892,6 +892,14 @@ static const struct dmi_system_id intel_no_lvds[] = { + }, + { + .callback = intel_no_lvds_dmi_callback, ++ .ident = "AOpen i45GMx-I", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), ++ DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"), ++ }, ++ }, ++ { ++ .callback = intel_no_lvds_dmi_callback, + .ident = "Aopen i945GTt-VFA", + .matches = { + DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"), +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index c9e93ea..a2ae151 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -218,9 +218,7 @@ int r100_irq_process(struct radeon_device *rdev) + WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM); + break; + default: +- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; +- WREG32(RADEON_MSI_REARM_EN, msi_rearm); +- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN); ++ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + break; + } + } +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index 1700297..52b7799 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -270,9 +270,7 @@ int rs600_irq_process(struct radeon_device *rdev) + WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM); + break; + default: +- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; +- WREG32(RADEON_MSI_REARM_EN, msi_rearm); +- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN); ++ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + break; + } + } +diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c +index afebc34..9ae1bae 100644 +--- a/drivers/hwmon/f75375s.c ++++ b/drivers/hwmon/f75375s.c +@@ -159,7 +159,7 @@ static inline void f75375_write8(struct i2c_client *client, u8 reg, + static inline void f75375_write16(struct i2c_client *client, u8 reg, + u16 value) + { +- int err = i2c_smbus_write_byte_data(client, reg, (value << 8)); ++ int err = i2c_smbus_write_byte_data(client, reg, (value >> 8)); + if (err) + return; + i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); +@@ -311,7 +311,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) + fanmode |= (3 << FAN_CTRL_MODE(nr)); + break; + case 2: /* AUTOMATIC*/ +- fanmode |= (2 << FAN_CTRL_MODE(nr)); ++ fanmode |= (1 << FAN_CTRL_MODE(nr)); + break; + case 3: /* fan speed */ + break; +diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c +index 2eb9dc2..09f0ee0 100644 +--- a/drivers/media/video/hdpvr/hdpvr-video.c ++++ b/drivers/media/video/hdpvr/hdpvr-video.c +@@ -279,12 +279,13 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) + + hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + ++ dev->status = STATUS_STREAMING; ++ + INIT_WORK(&dev->worker, hdpvr_transmit_buffers); + queue_work(dev->workqueue, &dev->worker); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "streaming started\n"); +- dev->status = STATUS_STREAMING; + + return 0; + } +diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c +index 4460e00..ee23d4e 100644 +--- a/drivers/s390/block/dasd_eckd.c ++++ b/drivers/s390/block/dasd_eckd.c +@@ -19,6 +19,7 @@ + #include <linux/bio.h> + #include <linux/module.h> + #include <linux/init.h> ++#include <linux/compat.h> + + #include <asm/debug.h> + #include <asm/idals.h> +diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c +index a5354b8..0400e7c 100644 +--- a/drivers/s390/block/dasd_ioctl.c ++++ b/drivers/s390/block/dasd_ioctl.c +@@ -13,6 +13,7 @@ + #define KMSG_COMPONENT "dasd" + + #include <linux/interrupt.h> ++#include <linux/compat.h> + #include <linux/major.h> + #include <linux/fs.h> + #include <linux/blkpg.h> +diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c +index 097d384..8d1d18c 100644 +--- a/drivers/s390/char/fs3270.c ++++ b/drivers/s390/char/fs3270.c +@@ -14,6 +14,7 @@ + #include <linux/list.h> + #include <linux/types.h> + #include <linux/smp_lock.h> ++#include <linux/compat.h> + + #include <asm/ccwdev.h> + #include <asm/cio.h> +diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c +index a6087ce..99cc483 100644 +--- a/drivers/s390/char/vmcp.c ++++ b/drivers/s390/char/vmcp.c +@@ -16,6 +16,7 @@ + + #include <linux/fs.h> + #include <linux/init.h> ++#include <linux/compat.h> + #include <linux/kernel.h> + #include <linux/miscdevice.h> + #include <linux/module.h> +diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c +index cc5144b..d0b03bc 100644 +--- a/drivers/s390/cio/chsc_sch.c ++++ b/drivers/s390/cio/chsc_sch.c +@@ -11,6 +11,7 @@ + #include <linux/module.h> + #include <linux/uaccess.h> + #include <linux/miscdevice.h> ++#include <linux/compat.h> + + #include <asm/cio.h> + #include <asm/chsc.h> +diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c +index ef681df..2e37ac9 100644 +--- a/drivers/s390/scsi/zfcp_cfdc.c ++++ b/drivers/s390/scsi/zfcp_cfdc.c +@@ -12,6 +12,7 @@ + + #include <linux/types.h> + #include <linux/miscdevice.h> ++#include <linux/compat.h> + #include <asm/ccwdev.h> + #include "zfcp_def.h" + #include "zfcp_ext.h" +diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c +index 3e250ca..1549eea 100644 +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -76,6 +76,7 @@ + Fix bug in twa_get_param() on 4GB+. + Use pci_resource_len() for ioremap(). + 2.26.02.012 - Add power management support. ++ 2.26.02.013 - Fix bug in twa_load_sgl(). + */ + + #include <linux/module.h> +@@ -100,7 +101,7 @@ + #include "3w-9xxx.h" + + /* Globals */ +-#define TW_DRIVER_VERSION "2.26.02.012" ++#define TW_DRIVER_VERSION "2.26.02.013" + static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; + static unsigned int twa_device_extension_count; + static int twa_major = -1; +@@ -1378,10 +1379,12 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm + newcommand = &full_command_packet->command.newcommand; + newcommand->request_id__lunl = + cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id)); +- newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); +- newcommand->sg_list[0].length = cpu_to_le32(length); ++ if (length) { ++ newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); ++ newcommand->sg_list[0].length = cpu_to_le32(length); ++ } + newcommand->sgl_entries__lunh = +- cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1)); ++ cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), length ? 1 : 0)); + } else { + oldcommand = &full_command_packet->command.oldcommand; + oldcommand->request_id = request_id; +diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c +index 8213f79..0ff157a 100644 +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -503,7 +503,17 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) + */ + if (pdev->vendor == 0x184e) /* vendor Netlogic */ + return; ++ if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_OHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_EHCI && ++ pdev->class != PCI_CLASS_SERIAL_USB_XHCI) ++ return; + ++ if (pci_enable_device(pdev) < 0) { ++ dev_warn(&pdev->dev, "Can't enable PCI device, " ++ "BIOS handoff failed.\n"); ++ return; ++ } + if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) + quirk_usb_handoff_uhci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) +@@ -512,5 +522,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) + quirk_usb_disable_ehci(pdev); + else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) + quirk_usb_handoff_xhci(pdev); ++ pci_disable_device(pdev); + } + DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index a2f2f79..8c29073 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -472,26 +472,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, + } + + /* +- * Convert bInterval expressed in frames (in 1-255 range) to exponent of ++ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of + * microframes, rounded down to nearest power of 2. + */ +-static unsigned int xhci_parse_frame_interval(struct usb_device *udev, +- struct usb_host_endpoint *ep) ++static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, ++ struct usb_host_endpoint *ep, unsigned int desc_interval, ++ unsigned int min_exponent, unsigned int max_exponent) + { + unsigned int interval; + +- interval = fls(8 * ep->desc.bInterval) - 1; +- interval = clamp_val(interval, 3, 10); +- if ((1 << interval) != 8 * ep->desc.bInterval) ++ interval = fls(desc_interval) - 1; ++ interval = clamp_val(interval, min_exponent, max_exponent); ++ if ((1 << interval) != desc_interval) + dev_warn(&udev->dev, + "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", + ep->desc.bEndpointAddress, + 1 << interval, +- 8 * ep->desc.bInterval); ++ desc_interval); + + return interval; + } + ++static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, ++ struct usb_host_endpoint *ep) ++{ ++ return xhci_microframes_to_exponent(udev, ep, ++ ep->desc.bInterval, 0, 15); ++} ++ ++ ++static unsigned int xhci_parse_frame_interval(struct usb_device *udev, ++ struct usb_host_endpoint *ep) ++{ ++ return xhci_microframes_to_exponent(udev, ep, ++ ep->desc.bInterval * 8, 3, 10); ++} ++ + /* Return the polling or NAK interval. + * + * The polling interval is expressed in "microframes". If xHCI's Interval field +@@ -510,7 +526,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, + /* Max NAK rate */ + if (usb_endpoint_xfer_control(&ep->desc) || + usb_endpoint_xfer_bulk(&ep->desc)) { +- interval = ep->desc.bInterval; ++ interval = xhci_parse_microframe_interval(udev, ep); + break; + } + /* Fall through - SS and HS isoc/int have same decoding */ +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index bb16725..feb96e9 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -136,6 +136,8 @@ static struct usb_device_id id_table [] = { + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ + { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ + { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ ++ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ ++ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ +diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h +index 8f7cdde..5d8d9a0 100644 +--- a/fs/autofs4/autofs_i.h ++++ b/fs/autofs4/autofs_i.h +@@ -125,6 +125,7 @@ struct autofs_sb_info { + int sub_version; + int min_proto; + int max_proto; ++ int compat_daemon; + unsigned long exp_timeout; + unsigned int type; + int reghost_enabled; +diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c +index 00bf8fc..5bb5a2a 100644 +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -389,6 +389,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, + sbi->pipefd = pipefd; + sbi->pipe = pipe; + sbi->catatonic = 0; ++ sbi->compat_daemon = is_compat_task(); + } + out: + mutex_unlock(&sbi->wq_mutex); +diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c +index 69c8142..0ca145a 100644 +--- a/fs/autofs4/inode.c ++++ b/fs/autofs4/inode.c +@@ -19,6 +19,7 @@ + #include <linux/parser.h> + #include <linux/bitops.h> + #include <linux/magic.h> ++#include <linux/compat.h> + #include "autofs_i.h" + #include <linux/module.h> + +@@ -341,6 +342,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) + set_autofs_type_indirect(&sbi->type); + sbi->min_proto = 0; + sbi->max_proto = 0; ++ sbi->compat_daemon = is_compat_task(); + mutex_init(&sbi->wq_mutex); + spin_lock_init(&sbi->fs_lock); + sbi->queues = NULL; +diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c +index 2341375..136a0d6 100644 +--- a/fs/autofs4/waitq.c ++++ b/fs/autofs4/waitq.c +@@ -90,7 +90,24 @@ static int autofs4_write(struct file *file, const void *addr, int bytes) + + return (bytes > 0); + } +- ++ ++/* ++ * The autofs_v5 packet was misdesigned. ++ * ++ * The packets are identical on x86-32 and x86-64, but have different ++ * alignment. Which means that 'sizeof()' will give different results. ++ * Fix it up for the case of running 32-bit user mode on a 64-bit kernel. ++ */ ++static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi) ++{ ++ size_t pktsz = sizeof(struct autofs_v5_packet); ++#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) ++ if (sbi->compat_daemon > 0) ++ pktsz -= 4; ++#endif ++ return pktsz; ++} ++ + static void autofs4_notify_daemon(struct autofs_sb_info *sbi, + struct autofs_wait_queue *wq, + int type) +@@ -147,8 +164,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, + { + struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet; + +- pktsz = sizeof(*packet); +- ++ pktsz = autofs_v5_packet_size(sbi); + packet->wait_queue_token = wq->wait_queue_token; + packet->len = wq->name.len; + memcpy(packet->name, wq->name.name, wq->name.len); +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index 4e25328..3015389 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -323,11 +323,11 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + const struct file_operations ecryptfs_dir_fops = { + .readdir = ecryptfs_readdir, ++ .read = generic_read_dir, + .unlocked_ioctl = ecryptfs_unlocked_ioctl, + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, + #endif +- .mmap = generic_file_mmap, + .open = ecryptfs_open, + .flush = ecryptfs_flush, + .release = ecryptfs_release, +diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c +index 88ba4d4..4434e8f 100644 +--- a/fs/ecryptfs/inode.c ++++ b/fs/ecryptfs/inode.c +@@ -575,8 +575,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) + dget(lower_dentry); + rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); + dput(lower_dentry); +- if (!rc) +- d_delete(lower_dentry); ++ if (!rc && dentry->d_inode) ++ clear_nlink(dentry->d_inode); + fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); + dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; + unlock_dir(lower_dir_dentry); +@@ -758,18 +758,23 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, + } + + /** +- * ecryptfs_truncate ++ * truncate_upper + * @dentry: The ecryptfs layer dentry +- * @new_length: The length to expand the file to ++ * @ia: Address of the ecryptfs inode's attributes ++ * @lower_ia: Address of the lower inode's attributes + * + * Function to handle truncations modifying the size of the file. Note + * that the file sizes are interpolated. When expanding, we are simply +- * writing strings of 0's out. When truncating, we need to modify the +- * underlying file size according to the page index interpolations. ++ * writing strings of 0's out. When truncating, we truncate the upper ++ * inode and update the lower_ia according to the page index ++ * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return, ++ * the caller must use lower_ia in a call to notify_change() to perform ++ * the truncation of the lower inode. + * + * Returns zero on success; non-zero otherwise + */ +-int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) ++static int truncate_upper(struct dentry *dentry, struct iattr *ia, ++ struct iattr *lower_ia) + { + int rc = 0; + struct inode *inode = dentry->d_inode; +@@ -780,8 +785,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) + loff_t lower_size_before_truncate; + loff_t lower_size_after_truncate; + +- if (unlikely((new_length == i_size))) ++ if (unlikely((ia->ia_size == i_size))) { ++ lower_ia->ia_valid &= ~ATTR_SIZE; + goto out; ++ } + crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; + /* Set up a fake ecryptfs file, this is used to interface with + * the file in the underlying filesystem so that the +@@ -801,28 +808,30 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) + &fake_ecryptfs_file, + ecryptfs_inode_to_private(dentry->d_inode)->lower_file); + /* Switch on growing or shrinking file */ +- if (new_length > i_size) { ++ if (ia->ia_size > i_size) { + char zero[] = { 0x00 }; + ++ lower_ia->ia_valid &= ~ATTR_SIZE; + /* Write a single 0 at the last position of the file; + * this triggers code that will fill in 0's throughout + * the intermediate portion of the previous end of the + * file and the new and of the file */ + rc = ecryptfs_write(&fake_ecryptfs_file, zero, +- (new_length - 1), 1); +- } else { /* new_length < i_size_read(inode) */ +- /* We're chopping off all the pages down do the page +- * in which new_length is located. Fill in the end of +- * that page from (new_length & ~PAGE_CACHE_MASK) to ++ (ia->ia_size - 1), 1); ++ } else { /* ia->ia_size < i_size_read(inode) */ ++ /* We're chopping off all the pages down to the page ++ * in which ia->ia_size is located. Fill in the end of ++ * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to + * PAGE_CACHE_SIZE with zeros. */ + size_t num_zeros = (PAGE_CACHE_SIZE +- - (new_length & ~PAGE_CACHE_MASK)); ++ - (ia->ia_size & ~PAGE_CACHE_MASK)); + + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { +- rc = vmtruncate(inode, new_length); ++ rc = vmtruncate(inode, ia->ia_size); + if (rc) + goto out_free; +- rc = vmtruncate(lower_dentry->d_inode, new_length); ++ lower_ia->ia_size = ia->ia_size; ++ lower_ia->ia_valid |= ATTR_SIZE; + goto out_free; + } + if (num_zeros) { +@@ -834,7 +843,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) + goto out_free; + } + rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, +- new_length, num_zeros); ++ ia->ia_size, num_zeros); + kfree(zeros_virt); + if (rc) { + printk(KERN_ERR "Error attempting to zero out " +@@ -843,7 +852,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) + goto out_free; + } + } +- vmtruncate(inode, new_length); ++ vmtruncate(inode, ia->ia_size); + rc = ecryptfs_write_inode_size_to_metadata(inode); + if (rc) { + printk(KERN_ERR "Problem with " +@@ -856,10 +865,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) + lower_size_before_truncate = + upper_size_to_lower_size(crypt_stat, i_size); + lower_size_after_truncate = +- upper_size_to_lower_size(crypt_stat, new_length); +- if (lower_size_after_truncate < lower_size_before_truncate) +- vmtruncate(lower_dentry->d_inode, +- lower_size_after_truncate); ++ upper_size_to_lower_size(crypt_stat, ia->ia_size); ++ if (lower_size_after_truncate < lower_size_before_truncate) { ++ lower_ia->ia_size = lower_size_after_truncate; ++ lower_ia->ia_valid |= ATTR_SIZE; ++ } else ++ lower_ia->ia_valid &= ~ATTR_SIZE; + } + out_free: + if (ecryptfs_file_to_private(&fake_ecryptfs_file)) +@@ -869,6 +880,33 @@ out: + return rc; + } + ++/** ++ * ecryptfs_truncate ++ * @dentry: The ecryptfs layer dentry ++ * @new_length: The length to expand the file to ++ * ++ * Simple function that handles the truncation of an eCryptfs inode and ++ * its corresponding lower inode. ++ * ++ * Returns zero on success; non-zero otherwise ++ */ ++int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) ++{ ++ struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; ++ struct iattr lower_ia = { .ia_valid = 0 }; ++ int rc; ++ ++ rc = truncate_upper(dentry, &ia, &lower_ia); ++ if (!rc && lower_ia.ia_valid & ATTR_SIZE) { ++ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); ++ ++ mutex_lock(&lower_dentry->d_inode->i_mutex); ++ rc = notify_change(lower_dentry, &lower_ia); ++ mutex_unlock(&lower_dentry->d_inode->i_mutex); ++ } ++ return rc; ++} ++ + static int + ecryptfs_permission(struct inode *inode, int mask) + { +@@ -891,6 +929,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) + { + int rc = 0; + struct dentry *lower_dentry; ++ struct iattr lower_ia; + struct inode *inode; + struct inode *lower_inode; + struct ecryptfs_crypt_stat *crypt_stat; +@@ -929,15 +968,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) + } + } + mutex_unlock(&crypt_stat->cs_mutex); ++ memcpy(&lower_ia, ia, sizeof(lower_ia)); ++ if (ia->ia_valid & ATTR_FILE) ++ lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); + if (ia->ia_valid & ATTR_SIZE) { +- ecryptfs_printk(KERN_DEBUG, +- "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", +- ia->ia_valid, ATTR_SIZE); +- rc = ecryptfs_truncate(dentry, ia->ia_size); +- /* ecryptfs_truncate handles resizing of the lower file */ +- ia->ia_valid &= ~ATTR_SIZE; +- ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n", +- ia->ia_valid); ++ rc = truncate_upper(dentry, ia, &lower_ia); + if (rc < 0) + goto out; + } +@@ -946,11 +981,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) + * mode change is for clearing setuid/setgid bits. Allow lower fs + * to interpret this in its own way. + */ +- if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) +- ia->ia_valid &= ~ATTR_MODE; ++ if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) ++ lower_ia.ia_valid &= ~ATTR_MODE; + + mutex_lock(&lower_dentry->d_inode->i_mutex); +- rc = notify_change(lower_dentry, ia); ++ rc = notify_change(lower_dentry, &lower_ia); + mutex_unlock(&lower_dentry->d_inode->i_mutex); + out: + fsstack_copy_attr_all(inode, lower_inode, NULL); +diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c +index c6ac85d..e2f18ad 100644 +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -212,7 +212,8 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, + ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata, + ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig, + ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes, +- ecryptfs_opt_unlink_sigs, ecryptfs_opt_err }; ++ ecryptfs_opt_unlink_sigs, ecryptfs_opt_check_dev_ruid, ++ ecryptfs_opt_err }; + + static const match_table_t tokens = { + {ecryptfs_opt_sig, "sig=%s"}, +@@ -227,6 +228,7 @@ static const match_table_t tokens = { + {ecryptfs_opt_fn_cipher, "ecryptfs_fn_cipher=%s"}, + {ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"}, + {ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"}, ++ {ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"}, + {ecryptfs_opt_err, NULL} + }; + +@@ -270,6 +272,7 @@ static void ecryptfs_init_mount_crypt_stat( + * ecryptfs_parse_options + * @sb: The ecryptfs super block + * @options: The options pased to the kernel ++ * @check_ruid: set to 1 if device uid should be checked against the ruid + * + * Parse mount options: + * debug=N - ecryptfs_verbosity level for debug output +@@ -285,7 +288,8 @@ static void ecryptfs_init_mount_crypt_stat( + * + * Returns zero on success; non-zero on error + */ +-static int ecryptfs_parse_options(struct super_block *sb, char *options) ++static int ecryptfs_parse_options(struct super_block *sb, char *options, ++ uid_t *check_ruid) + { + char *p; + int rc = 0; +@@ -310,6 +314,8 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) + char *cipher_key_bytes_src; + char *fn_cipher_key_bytes_src; + ++ *check_ruid = 0; ++ + if (!options) { + rc = -EINVAL; + goto out; +@@ -410,6 +416,9 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) + case ecryptfs_opt_unlink_sigs: + mount_crypt_stat->flags |= ECRYPTFS_UNLINK_SIGS; + break; ++ case ecryptfs_opt_check_dev_ruid: ++ *check_ruid = 1; ++ break; + case ecryptfs_opt_err: + default: + printk(KERN_WARNING +@@ -487,6 +496,7 @@ out: + } + + struct kmem_cache *ecryptfs_sb_info_cache; ++static struct file_system_type ecryptfs_fs_type; + + /** + * ecryptfs_fill_super +@@ -551,7 +561,8 @@ out: + * ecryptfs_interpose to create our initial inode and super block + * struct. + */ +-static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) ++static int ecryptfs_read_super(struct super_block *sb, const char *dev_name, ++ uid_t check_ruid) + { + struct path path; + int rc; +@@ -561,6 +572,22 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) + ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); + goto out; + } ++ if (path.dentry->d_sb->s_type == &ecryptfs_fs_type) { ++ rc = -EINVAL; ++ printk(KERN_ERR "Mount on filesystem of type " ++ "eCryptfs explicitly disallowed due to " ++ "known incompatibilities\n"); ++ goto out_free; ++ } ++ ++ if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) { ++ rc = -EPERM; ++ printk(KERN_ERR "Mount of device (uid: %d) not owned by " ++ "requested user (uid: %d)\n", ++ path.dentry->d_inode->i_uid, current_uid()); ++ goto out_free; ++ } ++ + ecryptfs_set_superblock_lower(sb, path.dentry->d_sb); + sb->s_maxbytes = path.dentry->d_sb->s_maxbytes; + sb->s_blocksize = path.dentry->d_sb->s_blocksize; +@@ -599,6 +626,7 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags, + { + int rc; + struct super_block *sb; ++ uid_t check_ruid; + + rc = get_sb_nodev(fs_type, flags, raw_data, ecryptfs_fill_super, mnt); + if (rc < 0) { +@@ -606,12 +634,12 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags, + goto out; + } + sb = mnt->mnt_sb; +- rc = ecryptfs_parse_options(sb, raw_data); ++ rc = ecryptfs_parse_options(sb, raw_data, &check_ruid); + if (rc) { + printk(KERN_ERR "Error parsing options; rc = [%d]\n", rc); + goto out_abort; + } +- rc = ecryptfs_read_super(sb, dev_name); ++ rc = ecryptfs_read_super(sb, dev_name, check_ruid); + if (rc) { + printk(KERN_ERR "Reading sb failed; rc = [%d]\n", rc); + goto out_abort; +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index c05a29c..56835a7 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -46,6 +46,26 @@ static inline unsigned long hweight_long(unsigned long w) + } + + /** ++ * rol64 - rotate a 64-bit value left ++ * @word: value to rotate ++ * @shift: bits to roll ++ */ ++static inline __u64 rol64(__u64 word, unsigned int shift) ++{ ++ return (word << shift) | (word >> (64 - shift)); ++} ++ ++/** ++ * ror64 - rotate a 64-bit value right ++ * @word: value to rotate ++ * @shift: bits to roll ++ */ ++static inline __u64 ror64(__u64 word, unsigned int shift) ++{ ++ return (word >> shift) | (word << (64 - shift)); ++} ++ ++/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll +diff --git a/include/linux/compat.h b/include/linux/compat.h +index cab23f2..510266f 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -311,5 +311,9 @@ asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, + + extern void __user *compat_alloc_user_space(unsigned long len); + ++#else ++ ++#define is_compat_task() (0) ++ + #endif /* CONFIG_COMPAT */ + #endif /* _LINUX_COMPAT_H */ +diff --git a/include/linux/kernel.h b/include/linux/kernel.h +index 1221fe4..9acb92d 100644 +--- a/include/linux/kernel.h ++++ b/include/linux/kernel.h +@@ -411,14 +411,13 @@ static inline char *pack_hex_byte(char *buf, u8 byte) + * no local ratelimit_state used in the !PRINTK case + */ + #ifdef CONFIG_PRINTK +-#define printk_ratelimited(fmt, ...) ({ \ +- static struct ratelimit_state _rs = { \ +- .interval = DEFAULT_RATELIMIT_INTERVAL, \ +- .burst = DEFAULT_RATELIMIT_BURST, \ +- }; \ +- \ +- if (!__ratelimit(&_rs)) \ +- printk(fmt, ##__VA_ARGS__); \ ++#define printk_ratelimited(fmt, ...) ({ \ ++ static DEFINE_RATELIMIT_STATE(_rs, \ ++ DEFAULT_RATELIMIT_INTERVAL, \ ++ DEFAULT_RATELIMIT_BURST); \ ++ \ ++ if (__ratelimit(&_rs)) \ ++ printk(fmt, ##__VA_ARGS__); \ + }) + #else + /* No effect, but we still get type checking even in the !PRINTK case: */ +diff --git a/include/linux/kmod.h b/include/linux/kmod.h +index 384ca8b..0546fe7 100644 +--- a/include/linux/kmod.h ++++ b/include/linux/kmod.h +@@ -104,7 +104,16 @@ struct file; + extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[], + struct file **filp); + ++#ifdef CONFIG_PM_SLEEP + extern int usermodehelper_disable(void); + extern void usermodehelper_enable(void); ++extern bool usermodehelper_is_disabled(void); ++extern void read_lock_usermodehelper(void); ++extern void read_unlock_usermodehelper(void); ++#else ++static inline bool usermodehelper_is_disabled(void) { return false; } ++static inline void read_lock_usermodehelper(void) {} ++static inline void read_unlock_usermodehelper(void) {} ++#endif + + #endif /* __LINUX_KMOD_H__ */ +diff --git a/include/linux/proportions.h b/include/linux/proportions.h +index cf793bb..22653d7 100644 +--- a/include/linux/proportions.h ++++ b/include/linux/proportions.h +@@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl) + * Limit the time part in order to ensure there are some bits left for the + * cycle counter and fraction multiply. + */ ++#if BITS_PER_LONG == 32 + #define PROP_MAX_SHIFT (3*BITS_PER_LONG/4) ++#else ++#define PROP_MAX_SHIFT (BITS_PER_LONG/2) ++#endif + + #define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1) + #define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT) +diff --git a/kernel/kmod.c b/kernel/kmod.c +index d206078..a061472 100644 +--- a/kernel/kmod.c ++++ b/kernel/kmod.c +@@ -35,6 +35,7 @@ + #include <linux/resource.h> + #include <linux/notifier.h> + #include <linux/suspend.h> ++#include <linux/rwsem.h> + #include <asm/uaccess.h> + + #include <trace/events/module.h> +@@ -43,6 +44,8 @@ extern int max_threads; + + static struct workqueue_struct *khelper_wq; + ++static DECLARE_RWSEM(umhelper_sem); ++ + #ifdef CONFIG_MODULES + + /* +@@ -286,6 +289,7 @@ static void __call_usermodehelper(struct work_struct *work) + * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY + * (used for preventing user land processes from being created after the user + * land has been frozen during a system-wide hibernation or suspend operation). ++ * Should always be manipulated under umhelper_sem acquired for write. + */ + static int usermodehelper_disabled; + +@@ -304,6 +308,18 @@ static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq); + */ + #define RUNNING_HELPERS_TIMEOUT (5 * HZ) + ++void read_lock_usermodehelper(void) ++{ ++ down_read(&umhelper_sem); ++} ++EXPORT_SYMBOL_GPL(read_lock_usermodehelper); ++ ++void read_unlock_usermodehelper(void) ++{ ++ up_read(&umhelper_sem); ++} ++EXPORT_SYMBOL_GPL(read_unlock_usermodehelper); ++ + /** + * usermodehelper_disable - prevent new helpers from being started + */ +@@ -311,8 +327,10 @@ int usermodehelper_disable(void) + { + long retval; + ++ down_write(&umhelper_sem); + usermodehelper_disabled = 1; +- smp_mb(); ++ up_write(&umhelper_sem); ++ + /* + * From now on call_usermodehelper_exec() won't start any new + * helpers, so it is sufficient if running_helpers turns out to +@@ -325,7 +343,9 @@ int usermodehelper_disable(void) + if (retval) + return 0; + ++ down_write(&umhelper_sem); + usermodehelper_disabled = 0; ++ up_write(&umhelper_sem); + return -EAGAIN; + } + +@@ -334,8 +354,19 @@ int usermodehelper_disable(void) + */ + void usermodehelper_enable(void) + { ++ down_write(&umhelper_sem); + usermodehelper_disabled = 0; ++ up_write(&umhelper_sem); ++} ++ ++/** ++ * usermodehelper_is_disabled - check if new helpers are allowed to be started ++ */ ++bool usermodehelper_is_disabled(void) ++{ ++ return usermodehelper_disabled; + } ++EXPORT_SYMBOL_GPL(usermodehelper_is_disabled); + + static void helper_lock(void) + { +diff --git a/kernel/relay.c b/kernel/relay.c +index 760c262..bf343f5 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -171,10 +171,14 @@ depopulate: + */ + static struct rchan_buf *relay_create_buf(struct rchan *chan) + { +- struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); +- if (!buf) ++ struct rchan_buf *buf; ++ ++ if (chan->n_subbufs > UINT_MAX / sizeof(size_t *)) + return NULL; + ++ buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); ++ if (!buf) ++ return NULL; + buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); + if (!buf->padding) + goto free_buf; +@@ -581,6 +585,8 @@ struct rchan *relay_open(const char *base_filename, + + if (!(subbuf_size && n_subbufs)) + return NULL; ++ if (subbuf_size > UINT_MAX / n_subbufs) ++ return NULL; + + chan = kzalloc(sizeof(struct rchan), GFP_KERNEL); + if (!chan) +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 38499c4..759f96f 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2363,7 +2363,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) + % tid_agg_rx->buf_size; + if (!tid_agg_rx->reorder_buf[index] && +- tid_agg_rx->stored_mpdu_num > 1) { ++ tid_agg_rx->stored_mpdu_num) { + /* + * No buffers ready to be released, but check whether any + * frames in the reorder buffer have timed out. diff --git a/2.6.32/4420_grsecurity-2.9-2.6.32.57-201203022148.patch b/2.6.32/4420_grsecurity-2.9-2.6.32.58-201203062047.patch index f2893fd..bbdf047 100644 --- a/2.6.32/4420_grsecurity-2.9-2.6.32.57-201203022148.patch +++ b/2.6.32/4420_grsecurity-2.9-2.6.32.58-201203062047.patch @@ -185,7 +185,7 @@ index c840e7d..f4c451c 100644 pcd. [PARIDE] diff --git a/Makefile b/Makefile -index 3377650..095e46d 100644 +index ed78982..bcc432e 100644 --- a/Makefile +++ b/Makefile @@ -221,8 +221,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -4174,7 +4174,7 @@ index 639380a..72e3c02 100644 if (r_type == R_390_GOTPC) *(unsigned int *) loc = val; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c -index 061479f..dbfb08c 100644 +index 0b2573a..71a22ec 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -306,9 +306,6 @@ static int __init early_parse_mem(char *p) @@ -4231,7 +4231,7 @@ index 061479f..dbfb08c 100644 { if (s390_noexec) { diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c -index f4558cc..e461f37 100644 +index 0ab74ae..c8b68f9 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -78,10 +78,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) @@ -7963,7 +7963,7 @@ index 35974a5..5662ae2 100644 + pax_force_retaddr 0, 1 ret diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c -index 14531ab..a89a0c0 100644 +index 14531ab..bc68a7b 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -169,6 +169,8 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, @@ -7988,6 +7988,34 @@ index 14531ab..a89a0c0 100644 end_coredump: set_fs(fs); return has_dumped; +@@ -327,6 +323,13 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) + current->mm->free_area_cache = TASK_UNMAPPED_BASE; + current->mm->cached_hole_size = 0; + ++ retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); ++ if (retval < 0) { ++ /* Someone check-me: is this error path enough? */ ++ send_sig(SIGKILL, current, 0); ++ return retval; ++ } ++ + install_exec_creds(bprm); + current->flags &= ~PF_FORKNOEXEC; + +@@ -422,13 +425,6 @@ beyond_if: + + set_brk(current->mm->start_brk, current->mm->brk); + +- retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); +- if (retval < 0) { +- /* Someone check-me: is this error path enough? */ +- send_sig(SIGKILL, current, 0); +- return retval; +- } +- + current->mm->start_stack = + (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); + /* start thread */ diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 588a7aa..a3468b0 100644 --- a/arch/x86/ia32/ia32_signal.c @@ -27388,6 +27416,39 @@ index 15c6308..96e83c2 100644 .show = &integrity_attr_show, .store = &integrity_attr_store, }; +diff --git a/block/blk-ioc.c b/block/blk-ioc.c +index d4ed600..cbdabb0 100644 +--- a/block/blk-ioc.c ++++ b/block/blk-ioc.c +@@ -66,22 +66,22 @@ static void cfq_exit(struct io_context *ioc) + } + + /* Called by the exitting task */ +-void exit_io_context(void) ++void exit_io_context(struct task_struct *task) + { + struct io_context *ioc; + +- task_lock(current); +- ioc = current->io_context; +- current->io_context = NULL; +- task_unlock(current); ++ task_lock(task); ++ ioc = task->io_context; ++ task->io_context = NULL; ++ task_unlock(task); + + if (atomic_dec_and_test(&ioc->nr_tasks)) { + if (ioc->aic && ioc->aic->exit) + ioc->aic->exit(ioc->aic); + cfq_exit(ioc); + +- put_io_context(ioc); + } ++ put_io_context(ioc); + } + + struct io_context *alloc_io_context(gfp_t gfp_flags, int node) diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c index ca56420..f2fc409 100644 --- a/block/blk-iopoll.c @@ -30953,39 +31014,6 @@ index a5d585d..d087be3 100644 .show = kobj_pkt_show, .store = kobj_pkt_store }; -diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c -index 59cccc9..a4592ec 100644 ---- a/drivers/cdrom/cdrom.c -+++ b/drivers/cdrom/cdrom.c -@@ -2057,11 +2057,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, - if (!nr) - return -ENOMEM; - -- if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { -- ret = -EFAULT; -- goto out; -- } -- - cgc.data_direction = CGC_DATA_READ; - while (nframes > 0) { - if (nr > nframes) -@@ -2070,7 +2065,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, - ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); - if (ret) - break; -- if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { -+ if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { - ret = -EFAULT; - break; - } -@@ -2078,7 +2073,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, - nframes -= nr; - lba += nr; - } --out: - kfree(cgc.buffer); - return ret; - } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 6aad99e..89cd142 100644 --- a/drivers/char/Kconfig @@ -46454,7 +46482,7 @@ index b4ea829..e63ef18 100644 } diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c -index 2341375..df9d1c2 100644 +index 136a0d6..a287331 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -60,7 +60,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes) @@ -46480,7 +46508,7 @@ index 9158c07..3f06659 100644 kfree(link); } diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c -index 0133b5a..b3baa9f 100644 +index 0133b5a..3710d09 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -16,6 +16,7 @@ @@ -46533,7 +46561,17 @@ index 0133b5a..b3baa9f 100644 if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; -@@ -277,6 +282,27 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +@@ -274,9 +279,37 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) + current->mm->free_area_cache = current->mm->mmap_base; + current->mm->cached_hole_size = 0; + ++ retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); ++ if (retval < 0) { ++ /* Someone check-me: is this error path enough? */ ++ send_sig(SIGKILL, current, 0); ++ return retval; ++ } ++ install_exec_creds(bprm); current->flags &= ~PF_FORKNOEXEC; @@ -46561,7 +46599,7 @@ index 0133b5a..b3baa9f 100644 if (N_MAGIC(ex) == OMAGIC) { unsigned long text_addr, map_size; loff_t pos; -@@ -349,7 +375,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +@@ -349,7 +382,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, @@ -46570,8 +46608,22 @@ index 0133b5a..b3baa9f 100644 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); +@@ -367,13 +400,6 @@ beyond_if: + return retval; + } + +- retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); +- if (retval < 0) { +- /* Someone check-me: is this error path enough? */ +- send_sig(SIGKILL, current, 0); +- return retval; +- } +- + current->mm->start_stack = + (unsigned long) create_aout_tables((char __user *) bprm->p, bprm); + #ifdef __alpha__ diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 1ed37ba..308a022 100644 +index 1ed37ba..66794b9 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -31,6 +31,7 @@ @@ -47296,6 +47348,15 @@ index 1ed37ba..308a022 100644 fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); } +@@ -1452,7 +1926,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + for (i = 1; i < view->n; ++i) { + const struct user_regset *regset = &view->regsets[i]; + do_thread_regset_writeback(t->task, regset); +- if (regset->core_note_type && ++ if (regset->core_note_type && regset->get && + (!regset->active || regset->active(t->task, regset))) { + int ret; + size_t size = regset->n * regset->size; @@ -1973,7 +2447,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un phdr.p_offset = offset; phdr.p_vaddr = vma->vm_start; @@ -48598,7 +48659,7 @@ index c010ecf..a8d8c59 100644 .store = dlm_attr_store, }; diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c -index 7a5f1ac..205b034 100644 +index 7a5f1ac..62fa913 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -418,17 +418,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, @@ -48669,16 +48730,76 @@ index 7a5f1ac..205b034 100644 out: return rc; } +@@ -1455,6 +1415,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) + ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; + } + ++void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) ++{ ++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat; ++ struct ecryptfs_crypt_stat *crypt_stat; ++ u64 file_size; ++ ++ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; ++ mount_crypt_stat = ++ &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; ++ if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { ++ file_size = i_size_read(ecryptfs_inode_to_lower(inode)); ++ if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) ++ file_size += crypt_stat->num_header_bytes_at_front; ++ } else ++ file_size = get_unaligned_be64(page_virt); ++ i_size_write(inode, (loff_t)file_size); ++ crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; ++} ++ + /** + * ecryptfs_read_headers_virt + * @page_virt: The virtual address into which to read the headers +@@ -1485,6 +1464,8 @@ static int ecryptfs_read_headers_virt(char *page_virt, + rc = -EINVAL; + goto out; + } ++ if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) ++ ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); + offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; + rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), + &bytes_read); +diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h +index 542f625..9685315 100644 +--- a/fs/ecryptfs/ecryptfs_kernel.h ++++ b/fs/ecryptfs/ecryptfs_kernel.h +@@ -270,6 +270,7 @@ struct ecryptfs_crypt_stat { + #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000 + #define ECRYPTFS_ENCFN_USE_FEK 0x00002000 + #define ECRYPTFS_UNLINK_SIGS 0x00004000 ++#define ECRYPTFS_I_SIZE_INITIALIZED 0x00008000 + u32 flags; + unsigned int file_version; + size_t iv_bytes; +@@ -619,6 +620,7 @@ struct ecryptfs_open_req { + int ecryptfs_interpose(struct dentry *hidden_dentry, + struct dentry *this_dentry, struct super_block *sb, + u32 flags); ++void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); + int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, + struct dentry *lower_dentry, + struct inode *ecryptfs_dir_inode, diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c -index 4e25328..3015389 100644 +index 3015389..49129f4 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c -@@ -323,11 +323,11 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - - const struct file_operations ecryptfs_dir_fops = { - .readdir = ecryptfs_readdir, -+ .read = generic_read_dir, - .unlocked_ioctl = ecryptfs_unlocked_ioctl, +@@ -237,7 +237,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) + goto out_free; + } + rc = 0; +- crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); ++ crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED ++ | ECRYPTFS_ENCRYPTED); + mutex_unlock(&crypt_stat->cs_mutex); + goto out; + } +@@ -347,7 +348,6 @@ const struct file_operations ecryptfs_main_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = ecryptfs_compat_ioctl, #endif @@ -48687,21 +48808,41 @@ index 4e25328..3015389 100644 .flush = ecryptfs_flush, .release = ecryptfs_release, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c -index 88ba4d4..55639ca 100644 +index 4434e8f..fa05803 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c -@@ -575,8 +575,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) - dget(lower_dentry); - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - dput(lower_dentry); -- if (!rc) -- d_delete(lower_dentry); -+ if (!rc && dentry->d_inode) -+ clear_nlink(dentry->d_inode); - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; - unlock_dir(lower_dir_dentry); -@@ -660,7 +660,7 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, +@@ -256,10 +256,8 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, + struct dentry *lower_dir_dentry; + struct vfsmount *lower_mnt; + struct inode *lower_inode; +- struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; + char *page_virt = NULL; +- u64 file_size; + int rc = 0; + + lower_dir_dentry = lower_dentry->d_parent; +@@ -334,18 +332,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, + } + crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; + } +- mount_crypt_stat = &ecryptfs_superblock_to_private( +- ecryptfs_dentry->d_sb)->mount_crypt_stat; +- if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { +- if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) +- file_size = (crypt_stat->num_header_bytes_at_front +- + i_size_read(lower_dentry->d_inode)); +- else +- file_size = i_size_read(lower_dentry->d_inode); +- } else { +- file_size = get_unaligned_be64(page_virt); +- } +- i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); ++ ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); + out_free_kmem: + kmem_cache_free(ecryptfs_header_cache_2, page_virt); + goto out; +@@ -660,7 +647,7 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, old_fs = get_fs(); set_fs(get_ds()); rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, @@ -48710,7 +48851,7 @@ index 88ba4d4..55639ca 100644 lower_bufsiz); set_fs(old_fs); if (rc < 0) -@@ -706,7 +706,7 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) +@@ -706,7 +693,7 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) } old_fs = get_fs(); set_fs(get_ds()); @@ -48719,235 +48860,16 @@ index 88ba4d4..55639ca 100644 set_fs(old_fs); if (rc < 0) goto out_free; -@@ -758,18 +758,23 @@ upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat, - } - - /** -- * ecryptfs_truncate -+ * truncate_upper - * @dentry: The ecryptfs layer dentry -- * @new_length: The length to expand the file to -+ * @ia: Address of the ecryptfs inode's attributes -+ * @lower_ia: Address of the lower inode's attributes - * - * Function to handle truncations modifying the size of the file. Note - * that the file sizes are interpolated. When expanding, we are simply -- * writing strings of 0's out. When truncating, we need to modify the -- * underlying file size according to the page index interpolations. -+ * writing strings of 0's out. When truncating, we truncate the upper -+ * inode and update the lower_ia according to the page index -+ * interpolations. If ATTR_SIZE is set in lower_ia->ia_valid upon return, -+ * the caller must use lower_ia in a call to notify_change() to perform -+ * the truncation of the lower inode. - * - * Returns zero on success; non-zero otherwise - */ --int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) -+static int truncate_upper(struct dentry *dentry, struct iattr *ia, -+ struct iattr *lower_ia) - { - int rc = 0; - struct inode *inode = dentry->d_inode; -@@ -780,8 +785,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) - loff_t lower_size_before_truncate; - loff_t lower_size_after_truncate; - -- if (unlikely((new_length == i_size))) -+ if (unlikely((ia->ia_size == i_size))) { -+ lower_ia->ia_valid &= ~ATTR_SIZE; - goto out; -+ } - crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; - /* Set up a fake ecryptfs file, this is used to interface with - * the file in the underlying filesystem so that the -@@ -801,28 +808,30 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) - &fake_ecryptfs_file, - ecryptfs_inode_to_private(dentry->d_inode)->lower_file); - /* Switch on growing or shrinking file */ -- if (new_length > i_size) { -+ if (ia->ia_size > i_size) { - char zero[] = { 0x00 }; - -+ lower_ia->ia_valid &= ~ATTR_SIZE; - /* Write a single 0 at the last position of the file; - * this triggers code that will fill in 0's throughout - * the intermediate portion of the previous end of the - * file and the new and of the file */ - rc = ecryptfs_write(&fake_ecryptfs_file, zero, -- (new_length - 1), 1); -- } else { /* new_length < i_size_read(inode) */ -- /* We're chopping off all the pages down do the page -- * in which new_length is located. Fill in the end of -- * that page from (new_length & ~PAGE_CACHE_MASK) to -+ (ia->ia_size - 1), 1); -+ } else { /* ia->ia_size < i_size_read(inode) */ -+ /* We're chopping off all the pages down to the page -+ * in which ia->ia_size is located. Fill in the end of -+ * that page from (ia->ia_size & ~PAGE_CACHE_MASK) to - * PAGE_CACHE_SIZE with zeros. */ - size_t num_zeros = (PAGE_CACHE_SIZE -- - (new_length & ~PAGE_CACHE_MASK)); -+ - (ia->ia_size & ~PAGE_CACHE_MASK)); - - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { -- rc = vmtruncate(inode, new_length); -+ rc = vmtruncate(inode, ia->ia_size); - if (rc) - goto out_free; -- rc = vmtruncate(lower_dentry->d_inode, new_length); -+ lower_ia->ia_size = ia->ia_size; -+ lower_ia->ia_valid |= ATTR_SIZE; - goto out_free; - } - if (num_zeros) { -@@ -834,7 +843,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) - goto out_free; - } - rc = ecryptfs_write(&fake_ecryptfs_file, zeros_virt, -- new_length, num_zeros); -+ ia->ia_size, num_zeros); - kfree(zeros_virt); - if (rc) { - printk(KERN_ERR "Error attempting to zero out " -@@ -843,7 +852,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) - goto out_free; +@@ -964,7 +951,8 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) + goto out; } - } -- vmtruncate(inode, new_length); -+ vmtruncate(inode, ia->ia_size); - rc = ecryptfs_write_inode_size_to_metadata(inode); - if (rc) { - printk(KERN_ERR "Problem with " -@@ -856,10 +865,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) - lower_size_before_truncate = - upper_size_to_lower_size(crypt_stat, i_size); - lower_size_after_truncate = -- upper_size_to_lower_size(crypt_stat, new_length); -- if (lower_size_after_truncate < lower_size_before_truncate) -- vmtruncate(lower_dentry->d_inode, -- lower_size_after_truncate); -+ upper_size_to_lower_size(crypt_stat, ia->ia_size); -+ if (lower_size_after_truncate < lower_size_before_truncate) { -+ lower_ia->ia_size = lower_size_after_truncate; -+ lower_ia->ia_valid |= ATTR_SIZE; -+ } else -+ lower_ia->ia_valid &= ~ATTR_SIZE; - } - out_free: - if (ecryptfs_file_to_private(&fake_ecryptfs_file)) -@@ -869,6 +880,33 @@ out: - return rc; - } - -+/** -+ * ecryptfs_truncate -+ * @dentry: The ecryptfs layer dentry -+ * @new_length: The length to expand the file to -+ * -+ * Simple function that handles the truncation of an eCryptfs inode and -+ * its corresponding lower inode. -+ * -+ * Returns zero on success; non-zero otherwise -+ */ -+int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) -+{ -+ struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; -+ struct iattr lower_ia = { .ia_valid = 0 }; -+ int rc; -+ -+ rc = truncate_upper(dentry, &ia, &lower_ia); -+ if (!rc && lower_ia.ia_valid & ATTR_SIZE) { -+ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); -+ -+ mutex_lock(&lower_dentry->d_inode->i_mutex); -+ rc = notify_change(lower_dentry, &lower_ia); -+ mutex_unlock(&lower_dentry->d_inode->i_mutex); -+ } -+ return rc; -+} -+ - static int - ecryptfs_permission(struct inode *inode, int mask) - { -@@ -891,6 +929,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) - { - int rc = 0; - struct dentry *lower_dentry; -+ struct iattr lower_ia; - struct inode *inode; - struct inode *lower_inode; - struct ecryptfs_crypt_stat *crypt_stat; -@@ -929,15 +968,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) + rc = 0; +- crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); ++ crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED ++ | ECRYPTFS_ENCRYPTED); } } mutex_unlock(&crypt_stat->cs_mutex); -+ memcpy(&lower_ia, ia, sizeof(lower_ia)); -+ if (ia->ia_valid & ATTR_FILE) -+ lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); - if (ia->ia_valid & ATTR_SIZE) { -- ecryptfs_printk(KERN_DEBUG, -- "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", -- ia->ia_valid, ATTR_SIZE); -- rc = ecryptfs_truncate(dentry, ia->ia_size); -- /* ecryptfs_truncate handles resizing of the lower file */ -- ia->ia_valid &= ~ATTR_SIZE; -- ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [%x]\n", -- ia->ia_valid); -+ rc = truncate_upper(dentry, ia, &lower_ia); - if (rc < 0) - goto out; - } -@@ -946,11 +981,11 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) - * mode change is for clearing setuid/setgid bits. Allow lower fs - * to interpret this in its own way. - */ -- if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -- ia->ia_valid &= ~ATTR_MODE; -+ if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) -+ lower_ia.ia_valid &= ~ATTR_MODE; - - mutex_lock(&lower_dentry->d_inode->i_mutex); -- rc = notify_change(lower_dentry, ia); -+ rc = notify_change(lower_dentry, &lower_ia); - mutex_unlock(&lower_dentry->d_inode->i_mutex); - out: - fsstack_copy_attr_all(inode, lower_inode, NULL); -diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c -index c6ac85d..c52df75 100644 ---- a/fs/ecryptfs/main.c -+++ b/fs/ecryptfs/main.c -@@ -487,6 +487,7 @@ out: - } - - struct kmem_cache *ecryptfs_sb_info_cache; -+static struct file_system_type ecryptfs_fs_type; - - /** - * ecryptfs_fill_super -@@ -561,6 +562,23 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) - ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); - goto out; - } -+ -+ if (path.dentry->d_sb->s_type == &ecryptfs_fs_type) { -+ rc = -EINVAL; -+ printk(KERN_ERR "Mount on filesystem of type " -+ "eCryptfs explicitly disallowed due to " -+ "known incompatibilities\n"); -+ goto out_free; -+ } -+ -+ if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) { -+ rc = -EPERM; -+ printk(KERN_ERR "Mount of device (uid: %d) not owned by " -+ "requested user (uid: %d)\n", -+ path.dentry->d_inode->i_uid, current_uid()); -+ goto out_free; -+ } -+ - ecryptfs_set_superblock_lower(sb, path.dentry->d_sb); - sb->s_maxbytes = path.dentry->d_sb->s_maxbytes; - sb->s_blocksize = path.dentry->d_sb->s_blocksize; diff --git a/fs/exec.c b/fs/exec.c index 86fafc6..6272c0e 100644 --- a/fs/exec.c @@ -56669,10 +56591,10 @@ index 0000000..1b9afa9 +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..b1c4f4d +index 0000000..dc4812b --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4149 @@ +@@ -0,0 +1,4148 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -58451,7 +58373,7 @@ index 0000000..b1c4f4d + +static struct acl_object_label * +chk_glob_label(struct acl_object_label *globbed, -+ struct dentry *dentry, struct vfsmount *mnt, char **path) ++ const struct dentry *dentry, const struct vfsmount *mnt, char **path) +{ + struct acl_object_label *tmp; + @@ -58484,8 +58406,7 @@ index 0000000..b1c4f4d + retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj); + if (retval) { + if (checkglob && retval->globbed) { -+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry, -+ (struct vfsmount *)orig_mnt, path); ++ retval2 = chk_glob_label(retval->globbed, orig_dentry, orig_mnt, path); + if (retval2) + retval = retval2; + } @@ -68414,6 +68335,28 @@ index c739150..be577b5 100644 extern void softirq_init(void); #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0) extern void raise_softirq_irqoff(unsigned int nr); +diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h +index eb73632..19abfc1 100644 +--- a/include/linux/iocontext.h ++++ b/include/linux/iocontext.h +@@ -94,14 +94,15 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc) + return NULL; + } + ++struct task_struct; + #ifdef CONFIG_BLOCK + int put_io_context(struct io_context *ioc); +-void exit_io_context(void); ++void exit_io_context(struct task_struct *task); + struct io_context *get_io_context(gfp_t gfp_flags, int node); + struct io_context *alloc_io_context(gfp_t gfp_flags, int node); + void copy_io_context(struct io_context **pdst, struct io_context **psrc); + #else +-static inline void exit_io_context(void) ++static inline void exit_io_context(struct task_struct *task) + { + } + diff --git a/include/linux/irq.h b/include/linux/irq.h index 9e5f45a..025865b 100644 --- a/include/linux/irq.h @@ -68506,7 +68449,7 @@ index 6adcc29..13369e8 100644 extern int kgdb_hex2long(char **ptr, unsigned long *long_val); extern int kgdb_mem2hex(char *mem, char *buf, int count); diff --git a/include/linux/kmod.h b/include/linux/kmod.h -index 384ca8b..83dd97d 100644 +index 0546fe7..2a22bc1 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -31,6 +31,8 @@ @@ -69336,6 +69279,30 @@ index 988e55f..17cb4ef 100644 #include <asm/emergency-restart.h> #endif +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 8abee65..5150fd1 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->get) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_WRITE, data, size)) + return -EIO; + +@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->set) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_READ, data, size)) + return -EIO; + diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index dd31e7b..5b03c5c 100644 --- a/include/linux/reiserfs_fs.h @@ -72512,7 +72479,7 @@ index 0b5b5fc..f7fe51a 100644 if (ret < 0) return ret; diff --git a/kernel/exit.c b/kernel/exit.c -index 0f8fae3..9344a56 100644 +index 0f8fae3..7916abf 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -55,6 +55,10 @@ @@ -72613,6 +72580,15 @@ index 0f8fae3..9344a56 100644 exit_mm(tsk); if (group_dead) +@@ -1020,7 +1049,7 @@ NORET_TYPE void do_exit(long code) + tsk->flags |= PF_EXITPIDONE; + + if (tsk->io_context) +- exit_io_context(); ++ exit_io_context(tsk); + + if (tsk->splice_pipe) + __free_pipe_info(tsk->splice_pipe); @@ -1188,7 +1217,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) if (unlikely(wo->wo_flags & WNOWAIT)) { @@ -72623,7 +72599,7 @@ index 0f8fae3..9344a56 100644 get_task_struct(p); read_unlock(&tasklist_lock); diff --git a/kernel/fork.c b/kernel/fork.c -index 4bde56f..29a9bab 100644 +index 4bde56f..8976a8f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -253,7 +253,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) @@ -72730,7 +72706,17 @@ index 4bde56f..29a9bab 100644 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; /* * Clear TID on mm_release()? -@@ -1333,6 +1366,8 @@ bad_fork_cleanup_count: +@@ -1299,7 +1332,8 @@ bad_fork_free_pid: + if (pid != &init_struct_pid) + free_pid(pid); + bad_fork_cleanup_io: +- put_io_context(p->io_context); ++ if (p->io_context) ++ exit_io_context(p); + bad_fork_cleanup_namespaces: + exit_task_namespaces(p); + bad_fork_cleanup_mm: +@@ -1333,6 +1367,8 @@ bad_fork_cleanup_count: bad_fork_free: free_task(p); fork_out: @@ -72739,7 +72725,7 @@ index 4bde56f..29a9bab 100644 return ERR_PTR(retval); } -@@ -1426,6 +1461,8 @@ long do_fork(unsigned long clone_flags, +@@ -1426,6 +1462,8 @@ long do_fork(unsigned long clone_flags, if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); @@ -72748,7 +72734,7 @@ index 4bde56f..29a9bab 100644 if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); -@@ -1558,7 +1595,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) +@@ -1558,7 +1596,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 */ @@ -72757,7 +72743,7 @@ index 4bde56f..29a9bab 100644 return 0; *new_fsp = copy_fs_struct(fs); -@@ -1681,7 +1718,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) +@@ -1681,7 +1719,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) fs = current->fs; write_lock(&fs->lock); current->fs = new_fs; @@ -73132,10 +73118,10 @@ index 53dae4b..9ba3743 100644 EXPORT_SYMBOL_GPL(kgdb_breakpoint); diff --git a/kernel/kmod.c b/kernel/kmod.c -index d206078..e27ba6a 100644 +index a061472..40884b6 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c -@@ -65,13 +65,12 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; +@@ -68,13 +68,12 @@ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; * If module auto-loading support is disabled then this function * becomes a no-operation. */ @@ -73151,7 +73137,7 @@ index d206078..e27ba6a 100644 static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", -@@ -84,12 +83,24 @@ int __request_module(bool wait, const char *fmt, ...) +@@ -87,12 +86,24 @@ int __request_module(bool wait, const char *fmt, ...) if (ret) return ret; @@ -73179,7 +73165,7 @@ index d206078..e27ba6a 100644 /* If modprobe needs a service that is in a module, we get a recursive * loop. Limit the number of running kmod threads to max_threads/2 or * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method -@@ -123,6 +134,48 @@ int __request_module(bool wait, const char *fmt, ...) +@@ -126,6 +137,48 @@ int __request_module(bool wait, const char *fmt, ...) atomic_dec(&kmod_concurrent); return ret; } @@ -73228,7 +73214,7 @@ index d206078..e27ba6a 100644 EXPORT_SYMBOL(__request_module); #endif /* CONFIG_MODULES */ -@@ -228,7 +281,7 @@ static int wait_for_helper(void *data) +@@ -231,7 +284,7 @@ static int wait_for_helper(void *data) * * Thus the __user pointer cast is valid here. */ @@ -75361,36 +75347,10 @@ index c03edf7..ac1b341 100644 rcu_read_unlock_special(t); } diff --git a/kernel/relay.c b/kernel/relay.c -index 760c262..908e9ee 100644 +index bf343f5..908e9ee 100644 --- a/kernel/relay.c +++ b/kernel/relay.c -@@ -171,10 +171,14 @@ depopulate: - */ - static struct rchan_buf *relay_create_buf(struct rchan *chan) - { -- struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); -+ struct rchan_buf *buf; -+ -+ if (chan->n_subbufs > UINT_MAX / sizeof(size_t *)) -+ return NULL; -+ -+ buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); - if (!buf) - return NULL; -- - buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); - if (!buf->padding) - goto free_buf; -@@ -581,6 +585,8 @@ struct rchan *relay_open(const char *base_filename, - - if (!(subbuf_size && n_subbufs)) - return NULL; -+ if (subbuf_size > UINT_MAX / n_subbufs) -+ return NULL; - - chan = kzalloc(sizeof(struct rchan), GFP_KERNEL); - if (!chan) -@@ -1222,7 +1228,7 @@ static int subbuf_splice_actor(struct file *in, +@@ -1228,7 +1228,7 @@ static int subbuf_splice_actor(struct file *in, unsigned int flags, int *nonpad_ret) { @@ -75399,7 +75359,7 @@ index 760c262..908e9ee 100644 struct rchan_buf *rbuf = in->private_data; unsigned int subbuf_size = rbuf->chan->subbuf_size; uint64_t pos = (uint64_t) *ppos; -@@ -1241,6 +1247,9 @@ static int subbuf_splice_actor(struct file *in, +@@ -1247,6 +1247,9 @@ static int subbuf_splice_actor(struct file *in, .ops = &relay_pipe_buf_ops, .spd_release = relay_page_release, }; @@ -78339,7 +78299,7 @@ index 2d846cf..98134d2 100644 capable(CAP_IPC_LOCK)) ret = do_mlockall(flags); diff --git a/mm/mmap.c b/mm/mmap.c -index 4b80cbf..cd3731c 100644 +index 4b80cbf..12a7861 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -45,6 +45,16 @@ @@ -78675,7 +78635,18 @@ index 4b80cbf..cd3731c 100644 vma->vm_mm = mm; vma->vm_start = addr; vma->vm_end = addr + len; -@@ -1195,6 +1326,19 @@ munmap_back: +@@ -1180,8 +1311,9 @@ munmap_back: + vma->vm_page_prot = vm_get_page_prot(vm_flags); + vma->vm_pgoff = pgoff; + ++ error = -EINVAL; /* when rejecting VM_GROWSDOWN|VM_GROWSUP */ ++ + if (file) { +- error = -EINVAL; + if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) + goto free_vma; + if (vm_flags & VM_DENYWRITE) { +@@ -1195,6 +1327,19 @@ munmap_back: error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; @@ -78695,7 +78666,16 @@ index 4b80cbf..cd3731c 100644 if (vm_flags & VM_EXECUTABLE) added_exe_file_vma(mm); -@@ -1218,6 +1362,11 @@ munmap_back: +@@ -1207,6 +1352,8 @@ munmap_back: + pgoff = vma->vm_pgoff; + vm_flags = vma->vm_flags; + } else if (vm_flags & VM_SHARED) { ++ if (unlikely(vm_flags & (VM_GROWSDOWN|VM_GROWSUP))) ++ goto free_vma; + error = shmem_zero_setup(vma); + if (error) + goto free_vma; +@@ -1218,6 +1365,11 @@ munmap_back: vma_link(mm, vma, prev, rb_link, rb_parent); file = vma->vm_file; @@ -78707,7 +78687,7 @@ index 4b80cbf..cd3731c 100644 /* Once vma denies write, undo our temporary denial count */ if (correct_wcount) atomic_inc(&inode->i_writecount); -@@ -1226,6 +1375,7 @@ out: +@@ -1226,6 +1378,7 @@ out: mm->total_vm += len >> PAGE_SHIFT; vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT); @@ -78715,7 +78695,7 @@ index 4b80cbf..cd3731c 100644 if (vm_flags & VM_LOCKED) { /* * makes pages present; downgrades, drops, reacquires mmap_sem -@@ -1248,6 +1398,12 @@ unmap_and_free_vma: +@@ -1248,6 +1401,12 @@ unmap_and_free_vma: unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); charged = 0; free_vma: @@ -78728,7 +78708,7 @@ index 4b80cbf..cd3731c 100644 kmem_cache_free(vm_area_cachep, vma); unacct_error: if (charged) -@@ -1255,6 +1411,44 @@ unacct_error: +@@ -1255,6 +1414,44 @@ unacct_error: return error; } @@ -78773,7 +78753,7 @@ index 4b80cbf..cd3731c 100644 /* Get an address range which is currently unmapped. * For shmat() with addr=0. * -@@ -1281,18 +1475,23 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, +@@ -1281,18 +1478,23 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, if (flags & MAP_FIXED) return addr; @@ -78804,7 +78784,7 @@ index 4b80cbf..cd3731c 100644 } full_search: -@@ -1303,34 +1502,40 @@ full_search: +@@ -1303,34 +1505,40 @@ full_search: * Start a new search - just in case we missed * some holes. */ @@ -78856,7 +78836,7 @@ index 4b80cbf..cd3731c 100644 mm->free_area_cache = addr; mm->cached_hole_size = ~0UL; } -@@ -1348,7 +1553,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1348,7 +1556,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; @@ -78865,7 +78845,7 @@ index 4b80cbf..cd3731c 100644 /* requested length too big for entire address space */ if (len > TASK_SIZE) -@@ -1357,13 +1562,18 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1357,13 +1565,18 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (flags & MAP_FIXED) return addr; @@ -78888,7 +78868,7 @@ index 4b80cbf..cd3731c 100644 } /* check if free_area_cache is useful for us */ -@@ -1378,7 +1588,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1378,7 +1591,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, /* make sure it can fit in the remaining address space */ if (addr > len) { vma = find_vma(mm, addr-len); @@ -78897,7 +78877,7 @@ index 4b80cbf..cd3731c 100644 /* remember the address as a hint for next time */ return (mm->free_area_cache = addr-len); } -@@ -1395,7 +1605,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1395,7 +1608,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, * return with success: */ vma = find_vma(mm, addr); @@ -78906,7 +78886,7 @@ index 4b80cbf..cd3731c 100644 /* remember the address as a hint for next time */ return (mm->free_area_cache = addr); -@@ -1404,8 +1614,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1404,8 +1617,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, mm->cached_hole_size = vma->vm_start - addr; /* try just below the current vma->vm_start */ @@ -78917,7 +78897,7 @@ index 4b80cbf..cd3731c 100644 bottomup: /* -@@ -1414,13 +1624,21 @@ bottomup: +@@ -1414,13 +1627,21 @@ bottomup: * can happen with large stack limits and large mmap() * allocations. */ @@ -78941,7 +78921,7 @@ index 4b80cbf..cd3731c 100644 mm->cached_hole_size = ~0UL; return addr; -@@ -1429,6 +1647,12 @@ bottomup: +@@ -1429,6 +1650,12 @@ bottomup: void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) { @@ -78954,7 +78934,7 @@ index 4b80cbf..cd3731c 100644 /* * Is this a new hole at the highest possible address? */ -@@ -1436,8 +1660,10 @@ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) +@@ -1436,8 +1663,10 @@ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) mm->free_area_cache = addr; /* dont allow allocations above current base */ @@ -78966,14 +78946,13 @@ index 4b80cbf..cd3731c 100644 } unsigned long -@@ -1510,40 +1736,41 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) +@@ -1510,40 +1739,49 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) EXPORT_SYMBOL(find_vma); -/* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ +/* + * Same as find_vma, but also return a pointer to the previous VMA in *pprev. -+ * Note: pprev is set to NULL when return value is NULL. + */ struct vm_area_struct * find_vma_prev(struct mm_struct *mm, unsigned long addr, @@ -78983,22 +78962,13 @@ index 4b80cbf..cd3731c 100644 - struct rb_node *rb_node; - if (!mm) - goto out; -+ struct vm_area_struct *vma; - +- - /* Guard against addr being lower than the first VMA */ - vma = mm->mmap; -+ vma = find_vma(mm, addr); -+ *pprev = vma ? vma->vm_prev : NULL; -+ return vma; -+} - +- - /* Go through the RB tree quickly. */ - rb_node = mm->mm_rb.rb_node; -+#ifdef CONFIG_PAX_SEGMEXEC -+struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma) -+{ -+ struct vm_area_struct *vma_m; - +- - while (rb_node) { - struct vm_area_struct *vma_tmp; - vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); @@ -79009,17 +78979,35 @@ index 4b80cbf..cd3731c 100644 - prev = vma_tmp; - if (!prev->vm_next || (addr < prev->vm_next->vm_end)) - break; -- rb_node = rb_node->rb_right; -- } -+ BUG_ON(!vma || vma->vm_start >= vma->vm_end); -+ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) { -+ BUG_ON(vma->vm_mirror); -+ return NULL; ++ struct vm_area_struct *vma; ++ ++ vma = find_vma(mm, addr); ++ if (vma) { ++ *pprev = vma->vm_prev; ++ } else { ++ struct rb_node *rb_node = mm->mm_rb.rb_node; ++ *pprev = NULL; ++ while (rb_node) { ++ *pprev = rb_entry(rb_node, struct vm_area_struct, vm_rb); + rb_node = rb_node->rb_right; + } } -- ++ return vma; ++} ++ ++#ifdef CONFIG_PAX_SEGMEXEC ++struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma) ++{ ++ struct vm_area_struct *vma_m; + -out: - *pprev = prev; - return prev ? prev->vm_next : vma; ++ BUG_ON(!vma || vma->vm_start >= vma->vm_end); ++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) { ++ BUG_ON(vma->vm_mirror); ++ return NULL; ++ } + BUG_ON(vma->vm_start < SEGMEXEC_TASK_SIZE && SEGMEXEC_TASK_SIZE < vma->vm_end); + vma_m = vma->vm_mirror; + BUG_ON(!vma_m || vma_m->vm_mirror != vma); @@ -79033,7 +79021,7 @@ index 4b80cbf..cd3731c 100644 /* * Verify that the stack growth is acceptable and -@@ -1561,6 +1788,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1561,6 +1799,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns return -ENOMEM; /* Stack limit test */ @@ -79041,7 +79029,7 @@ index 4b80cbf..cd3731c 100644 if (size > rlim[RLIMIT_STACK].rlim_cur) return -ENOMEM; -@@ -1570,6 +1798,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1570,6 +1809,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns unsigned long limit; locked = mm->locked_vm + grow; limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; @@ -79049,7 +79037,7 @@ index 4b80cbf..cd3731c 100644 if (locked > limit && !capable(CAP_IPC_LOCK)) return -ENOMEM; } -@@ -1600,37 +1829,48 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1600,37 +1840,48 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns * PA-RISC uses this for its stack; IA64 for its Register Backing Store. * vma is the last one with address > vma->vm_end. Have to extend vma. */ @@ -79107,7 +79095,7 @@ index 4b80cbf..cd3731c 100644 unsigned long size, grow; size = address - vma->vm_start; -@@ -1643,6 +1883,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) +@@ -1643,6 +1894,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) vma->vm_end = address; } } @@ -79116,7 +79104,7 @@ index 4b80cbf..cd3731c 100644 anon_vma_unlock(vma); return error; } -@@ -1655,6 +1897,8 @@ static int expand_downwards(struct vm_area_struct *vma, +@@ -1655,6 +1908,8 @@ static int expand_downwards(struct vm_area_struct *vma, unsigned long address) { int error; @@ -79125,7 +79113,7 @@ index 4b80cbf..cd3731c 100644 /* * We must make sure the anon_vma is allocated -@@ -1668,6 +1912,15 @@ static int expand_downwards(struct vm_area_struct *vma, +@@ -1668,6 +1923,15 @@ static int expand_downwards(struct vm_area_struct *vma, if (error) return error; @@ -79141,7 +79129,7 @@ index 4b80cbf..cd3731c 100644 anon_vma_lock(vma); /* -@@ -1677,9 +1930,17 @@ static int expand_downwards(struct vm_area_struct *vma, +@@ -1677,9 +1941,17 @@ static int expand_downwards(struct vm_area_struct *vma, */ /* Somebody else might have raced and expanded it already */ @@ -79160,7 +79148,7 @@ index 4b80cbf..cd3731c 100644 size = vma->vm_end - address; grow = (vma->vm_start - address) >> PAGE_SHIFT; -@@ -1689,10 +1950,22 @@ static int expand_downwards(struct vm_area_struct *vma, +@@ -1689,10 +1961,22 @@ static int expand_downwards(struct vm_area_struct *vma, if (!error) { vma->vm_start = address; vma->vm_pgoff -= grow; @@ -79183,7 +79171,7 @@ index 4b80cbf..cd3731c 100644 return error; } -@@ -1768,6 +2041,13 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) +@@ -1768,6 +2052,13 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) do { long nrpages = vma_pages(vma); @@ -79197,7 +79185,7 @@ index 4b80cbf..cd3731c 100644 mm->total_vm -= nrpages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); vma = remove_vma(vma); -@@ -1813,6 +2093,16 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -1813,6 +2104,16 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, insertion_point = (prev ? &prev->vm_next : &mm->mmap); vma->vm_prev = NULL; do { @@ -79214,7 +79202,7 @@ index 4b80cbf..cd3731c 100644 rb_erase(&vma->vm_rb, &mm->mm_rb); mm->map_count--; tail_vma = vma; -@@ -1840,10 +2130,25 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1840,10 +2141,25 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, struct mempolicy *pol; struct vm_area_struct *new; @@ -79240,7 +79228,7 @@ index 4b80cbf..cd3731c 100644 if (mm->map_count >= sysctl_max_map_count) return -ENOMEM; -@@ -1851,6 +2156,16 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1851,6 +2167,16 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, if (!new) return -ENOMEM; @@ -79257,7 +79245,7 @@ index 4b80cbf..cd3731c 100644 /* most fields are the same, copy all, and then fixup */ *new = *vma; -@@ -1861,8 +2176,29 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1861,8 +2187,29 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT); } @@ -79287,7 +79275,7 @@ index 4b80cbf..cd3731c 100644 kmem_cache_free(vm_area_cachep, new); return PTR_ERR(pol); } -@@ -1883,6 +2219,28 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1883,6 +2230,28 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, else vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); @@ -79316,7 +79304,7 @@ index 4b80cbf..cd3731c 100644 return 0; } -@@ -1891,11 +2249,30 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1891,11 +2260,30 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, * work. This now handles partial unmappings. * Jeremy Fitzhardinge <jeremy@goop.org> */ @@ -79347,7 +79335,7 @@ index 4b80cbf..cd3731c 100644 if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start) return -EINVAL; -@@ -1959,6 +2336,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) +@@ -1959,6 +2347,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) /* Fix up all other VM information */ remove_vma_list(mm, vma); @@ -79356,7 +79344,7 @@ index 4b80cbf..cd3731c 100644 return 0; } -@@ -1971,22 +2350,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +@@ -1971,22 +2361,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) profile_munmap(addr); @@ -79385,7 +79373,7 @@ index 4b80cbf..cd3731c 100644 /* * this is really a simplified "do_mmap". it only handles * anonymous maps. eventually we may be able to do some -@@ -2000,6 +2375,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2000,6 +2386,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) struct rb_node ** rb_link, * rb_parent; pgoff_t pgoff = addr >> PAGE_SHIFT; int error; @@ -79393,7 +79381,7 @@ index 4b80cbf..cd3731c 100644 len = PAGE_ALIGN(len); if (!len) -@@ -2011,16 +2387,30 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2011,16 +2398,30 @@ unsigned long do_brk(unsigned long addr, unsigned long len) flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; @@ -79425,7 +79413,7 @@ index 4b80cbf..cd3731c 100644 locked += mm->locked_vm; lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; lock_limit >>= PAGE_SHIFT; -@@ -2037,22 +2427,22 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2037,22 +2438,22 @@ unsigned long do_brk(unsigned long addr, unsigned long len) /* * Clear old maps. this also does some error checking for us */ @@ -79452,7 +79440,7 @@ index 4b80cbf..cd3731c 100644 return -ENOMEM; /* Can we just expand an old private anonymous mapping? */ -@@ -2066,7 +2456,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2066,7 +2467,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) */ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (!vma) { @@ -79461,7 +79449,7 @@ index 4b80cbf..cd3731c 100644 return -ENOMEM; } -@@ -2078,11 +2468,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2078,11 +2479,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) vma->vm_page_prot = vm_get_page_prot(flags); vma_link(mm, vma, prev, rb_link, rb_parent); out: @@ -79476,7 +79464,7 @@ index 4b80cbf..cd3731c 100644 return addr; } -@@ -2129,8 +2520,10 @@ void exit_mmap(struct mm_struct *mm) +@@ -2129,8 +2531,10 @@ void exit_mmap(struct mm_struct *mm) * Walk the list again, actually closing and freeing it, * with preemption enabled, without holding any MM locks. */ @@ -79488,7 +79476,7 @@ index 4b80cbf..cd3731c 100644 BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); } -@@ -2144,6 +2537,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) +@@ -2144,6 +2548,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) struct vm_area_struct * __vma, * prev; struct rb_node ** rb_link, * rb_parent; @@ -79499,7 +79487,7 @@ index 4b80cbf..cd3731c 100644 /* * The vm_pgoff of a purely anonymous vma should be irrelevant * until its first write fault, when page's anon_vma and index -@@ -2166,7 +2563,22 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) +@@ -2166,7 +2574,22 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) if ((vma->vm_flags & VM_ACCOUNT) && security_vm_enough_memory_mm(mm, vma_pages(vma))) return -ENOMEM; @@ -79522,7 +79510,7 @@ index 4b80cbf..cd3731c 100644 return 0; } -@@ -2184,6 +2596,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -2184,6 +2607,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, struct rb_node **rb_link, *rb_parent; struct mempolicy *pol; @@ -79531,7 +79519,7 @@ index 4b80cbf..cd3731c 100644 /* * If anonymous vma has not yet been faulted, update new pgoff * to match new location, to increase its chance of merging. -@@ -2227,6 +2641,35 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -2227,6 +2652,35 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, return new_vma; } @@ -79567,7 +79555,7 @@ index 4b80cbf..cd3731c 100644 /* * Return true if the calling process may expand its vm space by the passed * number of pages -@@ -2237,7 +2680,7 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages) +@@ -2237,7 +2691,7 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages) unsigned long lim; lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; @@ -79576,7 +79564,7 @@ index 4b80cbf..cd3731c 100644 if (cur + npages > lim) return 0; return 1; -@@ -2307,6 +2750,22 @@ int install_special_mapping(struct mm_struct *mm, +@@ -2307,6 +2761,22 @@ int install_special_mapping(struct mm_struct *mm, vma->vm_start = addr; vma->vm_end = addr + len; @@ -87257,7 +87245,7 @@ index 79633ea..9732e90 100644 } diff --git a/tools/gcc/Makefile b/tools/gcc/Makefile new file mode 100644 -index 0000000..29b6b75 +index 0000000..469b06a --- /dev/null +++ b/tools/gcc/Makefile @@ -0,0 +1,21 @@ @@ -87267,7 +87255,7 @@ index 0000000..29b6b75 +GCCPLUGINS_DIR := $(shell $(CC) -print-file-name=plugin) +#CFLAGS += -I$(GCCPLUGINS_DIR)/include -fPIC -O2 -Wall -W -std=gnu99 + -+HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -std=gnu99 ++HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(GCCPLUGINS_DIR)/include/c-family -std=gnu99 -ggdb + +hostlibs-y := constify_plugin.so +hostlibs-$(CONFIG_PAX_MEMORY_STACKLEAK) += stackleak_plugin.so diff --git a/3.2.9/0000_README b/3.2.9/0000_README index 4b71aa6..c6fa1e9 100644 --- a/3.2.9/0000_README +++ b/3.2.9/0000_README @@ -2,7 +2,7 @@ README ----------------------------------------------------------------------------- Individual Patch Descriptions: ----------------------------------------------------------------------------- -Patch: 4420_grsecurity-2.9-3.2.9-201203022148.patch +Patch: 4420_grsecurity-2.9-3.2.9-201203062051.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/3.2.9/4420_grsecurity-2.9-3.2.9-201203022148.patch b/3.2.9/4420_grsecurity-2.9-3.2.9-201203062051.patch index fa03b34..7a64df3 100644 --- a/3.2.9/4420_grsecurity-2.9-3.2.9-201203022148.patch +++ b/3.2.9/4420_grsecurity-2.9-3.2.9-201203062051.patch @@ -6839,7 +6839,7 @@ index 7bcf3fc..f53832f 100644 + pax_force_retaddr 0, 1 ret diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c -index fd84387..0b4af7d 100644 +index fd84387..887aa7e 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -162,6 +162,8 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, @@ -6851,6 +6851,34 @@ index fd84387..0b4af7d 100644 fs = get_fs(); set_fs(KERNEL_DS); has_dumped = 1; +@@ -315,6 +317,13 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) + current->mm->free_area_cache = TASK_UNMAPPED_BASE; + current->mm->cached_hole_size = 0; + ++ retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); ++ if (retval < 0) { ++ /* Someone check-me: is this error path enough? */ ++ send_sig(SIGKILL, current, 0); ++ return retval; ++ } ++ + install_exec_creds(bprm); + current->flags &= ~PF_FORKNOEXEC; + +@@ -410,13 +419,6 @@ beyond_if: + + set_brk(current->mm->start_brk, current->mm->brk); + +- retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); +- if (retval < 0) { +- /* Someone check-me: is this error path enough? */ +- send_sig(SIGKILL, current, 0); +- return retval; +- } +- + current->mm->start_stack = + (unsigned long)create_aout_tables((char __user *)bprm->p, bprm); + /* start thread */ diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 6557769..ef6ae89 100644 --- a/arch/x86/ia32/ia32_signal.c @@ -28857,6 +28885,18 @@ index 5a82b6b..9e69c73 100644 if (regcomp (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { +diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c +index cb1acff..8861bc5 100644 +--- a/drivers/gpu/drm/radeon/r600_cs.c ++++ b/drivers/gpu/drm/radeon/r600_cs.c +@@ -1304,6 +1304,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, + h0 = G_038004_TEX_HEIGHT(word1) + 1; + d0 = G_038004_TEX_DEPTH(word1); + nfaces = 1; ++ array = 0; + switch (G_038000_DIM(word0)) { + case V_038000_SQ_TEX_DIM_1D: + case V_038000_SQ_TEX_DIM_2D: diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8227e76..ce0b195 100644 --- a/drivers/gpu/drm/radeon/radeon.h @@ -35207,7 +35247,7 @@ index bafccb3..e3ac78d 100644 /* Ignore return since this msg is optional. */ rndis_filter_send_request(dev, request); diff --git a/drivers/staging/iio/buffer_generic.h b/drivers/staging/iio/buffer_generic.h -index 9e8f010..af9efb5 100644 +index 9e8f010..af9efb56 100644 --- a/drivers/staging/iio/buffer_generic.h +++ b/drivers/staging/iio/buffer_generic.h @@ -64,7 +64,7 @@ struct iio_buffer_access_funcs { @@ -39770,7 +39810,7 @@ index 8342ca6..82fd192 100644 kfree(link); } diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c -index a6395bd..a5b24c4 100644 +index a6395bd..f1e376a 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -16,6 +16,7 @@ @@ -39812,7 +39852,17 @@ index a6395bd..a5b24c4 100644 if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; -@@ -262,6 +269,27 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +@@ -259,9 +266,37 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) + current->mm->free_area_cache = current->mm->mmap_base; + current->mm->cached_hole_size = 0; + ++ retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); ++ if (retval < 0) { ++ /* Someone check-me: is this error path enough? */ ++ send_sig(SIGKILL, current, 0); ++ return retval; ++ } ++ install_exec_creds(bprm); current->flags &= ~PF_FORKNOEXEC; @@ -39840,7 +39890,7 @@ index a6395bd..a5b24c4 100644 if (N_MAGIC(ex) == OMAGIC) { unsigned long text_addr, map_size; loff_t pos; -@@ -334,7 +362,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +@@ -334,7 +369,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, @@ -39849,8 +39899,22 @@ index a6395bd..a5b24c4 100644 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); +@@ -352,13 +387,6 @@ beyond_if: + return retval; + } + +- retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); +- if (retval < 0) { +- /* Someone check-me: is this error path enough? */ +- send_sig(SIGKILL, current, 0); +- return retval; +- } +- + current->mm->start_stack = + (unsigned long) create_aout_tables((char __user *) bprm->p, bprm); + #ifdef __alpha__ diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 21ac5ee..ca0d90f 100644 +index 21ac5ee..dbf63ee 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -32,6 +32,7 @@ @@ -40541,6 +40605,15 @@ index 21ac5ee..ca0d90f 100644 fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); } +@@ -1421,7 +1886,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + for (i = 1; i < view->n; ++i) { + const struct user_regset *regset = &view->regsets[i]; + do_thread_regset_writeback(t->task, regset); +- if (regset->core_note_type && ++ if (regset->core_note_type && regset->get && + (!regset->active || regset->active(t->task, regset))) { + int ret; + size_t size = regset->n * regset->size; @@ -1862,14 +2327,14 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, } @@ -48446,10 +48519,10 @@ index 0000000..496e60d +endif diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c new file mode 100644 -index 0000000..7715893 +index 0000000..2733872 --- /dev/null +++ b/grsecurity/gracl.c -@@ -0,0 +1,4164 @@ +@@ -0,0 +1,4163 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> @@ -50225,7 +50298,7 @@ index 0000000..7715893 + +static struct acl_object_label * +chk_glob_label(struct acl_object_label *globbed, -+ struct dentry *dentry, struct vfsmount *mnt, char **path) ++ const struct dentry *dentry, const struct vfsmount *mnt, char **path) +{ + struct acl_object_label *tmp; + @@ -50258,8 +50331,7 @@ index 0000000..7715893 + retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj); + if (retval) { + if (checkglob && retval->globbed) { -+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry, -+ (struct vfsmount *)orig_mnt, path); ++ retval2 = chk_glob_label(retval->globbed, orig_dentry, orig_mnt, path); + if (retval2) + retval = retval2; + } @@ -60586,6 +60658,30 @@ index e0879a7..a12f962 100644 #include <asm/emergency-restart.h> #endif +diff --git a/include/linux/regset.h b/include/linux/regset.h +index 8abee65..5150fd1 100644 +--- a/include/linux/regset.h ++++ b/include/linux/regset.h +@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->get) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_WRITE, data, size)) + return -EIO; + +@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target, + { + const struct user_regset *regset = &view->regsets[setno]; + ++ if (!regset->set) ++ return -EOPNOTSUPP; ++ + if (!access_ok(VERIFY_READ, data, size)) + return -EIO; + diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 96d465f..b084e05 100644 --- a/include/linux/reiserfs_fs.h @@ -67680,7 +67776,7 @@ index d9df745..e73c2fe 100644 static inline void *ptr_to_indirect(void *ptr) { diff --git a/lib/vsprintf.c b/lib/vsprintf.c -index 993599e..84dc70e 100644 +index 993599e..f1dbc14 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -16,6 +16,9 @@ @@ -67752,7 +67848,26 @@ index 993599e..84dc70e 100644 case 'B': return symbol_string(buf, end, ptr, spec, *fmt); case 'R': -@@ -1608,11 +1624,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) +@@ -878,9 +894,15 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, + case 'U': + return uuid_string(buf, end, ptr, spec, fmt); + case 'V': +- return buf + vsnprintf(buf, end > buf ? end - buf : 0, +- ((struct va_format *)ptr)->fmt, +- *(((struct va_format *)ptr)->va)); ++ { ++ va_list va; ++ ++ va_copy(va, *((struct va_format *)ptr)->va); ++ buf += vsnprintf(buf, end > buf ? end - buf : 0, ++ ((struct va_format *)ptr)->fmt, va); ++ va_end(va); ++ return buf; ++ } + case 'K': + /* + * %pK cannot be used in IRQ context because its test +@@ -1608,11 +1630,11 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) typeof(type) value; \ if (sizeof(type) == 8) { \ args = PTR_ALIGN(args, sizeof(u32)); \ @@ -67767,7 +67882,7 @@ index 993599e..84dc70e 100644 } \ args += sizeof(type); \ value; \ -@@ -1675,7 +1691,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) +@@ -1675,7 +1697,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) case FORMAT_TYPE_STR: { const char *str_arg = args; args += strlen(str_arg) + 1; @@ -68934,7 +69049,7 @@ index 4f4f53b..9511904 100644 capable(CAP_IPC_LOCK)) ret = do_mlockall(flags); diff --git a/mm/mmap.c b/mm/mmap.c -index eae90af..44552cf 100644 +index eae90af..c930262 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -46,6 +46,16 @@ @@ -69268,7 +69383,18 @@ index eae90af..44552cf 100644 vma->vm_mm = mm; vma->vm_start = addr; vma->vm_end = addr + len; -@@ -1281,6 +1412,19 @@ munmap_back: +@@ -1266,8 +1397,9 @@ munmap_back: + vma->vm_pgoff = pgoff; + INIT_LIST_HEAD(&vma->anon_vma_chain); + ++ error = -EINVAL; /* when rejecting VM_GROWSDOWN|VM_GROWSUP */ ++ + if (file) { +- error = -EINVAL; + if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) + goto free_vma; + if (vm_flags & VM_DENYWRITE) { +@@ -1281,6 +1413,19 @@ munmap_back: error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; @@ -69288,7 +69414,16 @@ index eae90af..44552cf 100644 if (vm_flags & VM_EXECUTABLE) added_exe_file_vma(mm); -@@ -1316,6 +1460,11 @@ munmap_back: +@@ -1293,6 +1438,8 @@ munmap_back: + pgoff = vma->vm_pgoff; + vm_flags = vma->vm_flags; + } else if (vm_flags & VM_SHARED) { ++ if (unlikely(vm_flags & (VM_GROWSDOWN|VM_GROWSUP))) ++ goto free_vma; + error = shmem_zero_setup(vma); + if (error) + goto free_vma; +@@ -1316,6 +1463,11 @@ munmap_back: vma_link(mm, vma, prev, rb_link, rb_parent); file = vma->vm_file; @@ -69300,7 +69435,7 @@ index eae90af..44552cf 100644 /* Once vma denies write, undo our temporary denial count */ if (correct_wcount) atomic_inc(&inode->i_writecount); -@@ -1324,6 +1473,7 @@ out: +@@ -1324,6 +1476,7 @@ out: mm->total_vm += len >> PAGE_SHIFT; vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT); @@ -69308,7 +69443,7 @@ index eae90af..44552cf 100644 if (vm_flags & VM_LOCKED) { if (!mlock_vma_pages_range(vma, addr, addr + len)) mm->locked_vm += (len >> PAGE_SHIFT); -@@ -1341,6 +1491,12 @@ unmap_and_free_vma: +@@ -1341,6 +1494,12 @@ unmap_and_free_vma: unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); charged = 0; free_vma: @@ -69321,7 +69456,7 @@ index eae90af..44552cf 100644 kmem_cache_free(vm_area_cachep, vma); unacct_error: if (charged) -@@ -1348,6 +1504,44 @@ unacct_error: +@@ -1348,6 +1507,44 @@ unacct_error: return error; } @@ -69366,7 +69501,7 @@ index eae90af..44552cf 100644 /* Get an address range which is currently unmapped. * For shmat() with addr=0. * -@@ -1374,18 +1568,23 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, +@@ -1374,18 +1571,23 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, if (flags & MAP_FIXED) return addr; @@ -69397,7 +69532,7 @@ index eae90af..44552cf 100644 } full_search: -@@ -1396,34 +1595,40 @@ full_search: +@@ -1396,34 +1598,40 @@ full_search: * Start a new search - just in case we missed * some holes. */ @@ -69449,7 +69584,7 @@ index eae90af..44552cf 100644 mm->free_area_cache = addr; mm->cached_hole_size = ~0UL; } -@@ -1441,7 +1646,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1441,7 +1649,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, { struct vm_area_struct *vma; struct mm_struct *mm = current->mm; @@ -69458,7 +69593,7 @@ index eae90af..44552cf 100644 /* requested length too big for entire address space */ if (len > TASK_SIZE) -@@ -1450,13 +1655,18 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1450,13 +1658,18 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (flags & MAP_FIXED) return addr; @@ -69481,7 +69616,7 @@ index eae90af..44552cf 100644 } /* check if free_area_cache is useful for us */ -@@ -1471,7 +1681,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1471,7 +1684,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, /* make sure it can fit in the remaining address space */ if (addr > len) { vma = find_vma(mm, addr-len); @@ -69490,7 +69625,7 @@ index eae90af..44552cf 100644 /* remember the address as a hint for next time */ return (mm->free_area_cache = addr-len); } -@@ -1488,7 +1698,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1488,7 +1701,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, * return with success: */ vma = find_vma(mm, addr); @@ -69499,7 +69634,7 @@ index eae90af..44552cf 100644 /* remember the address as a hint for next time */ return (mm->free_area_cache = addr); -@@ -1497,8 +1707,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, +@@ -1497,8 +1710,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, mm->cached_hole_size = vma->vm_start - addr; /* try just below the current vma->vm_start */ @@ -69510,7 +69645,7 @@ index eae90af..44552cf 100644 bottomup: /* -@@ -1507,13 +1717,21 @@ bottomup: +@@ -1507,13 +1720,21 @@ bottomup: * can happen with large stack limits and large mmap() * allocations. */ @@ -69534,7 +69669,7 @@ index eae90af..44552cf 100644 mm->cached_hole_size = ~0UL; return addr; -@@ -1522,6 +1740,12 @@ bottomup: +@@ -1522,6 +1743,12 @@ bottomup: void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) { @@ -69547,7 +69682,7 @@ index eae90af..44552cf 100644 /* * Is this a new hole at the highest possible address? */ -@@ -1529,8 +1753,10 @@ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) +@@ -1529,8 +1756,10 @@ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) mm->free_area_cache = addr; /* dont allow allocations above current base */ @@ -69559,14 +69694,13 @@ index eae90af..44552cf 100644 } unsigned long -@@ -1603,40 +1829,42 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) +@@ -1603,40 +1832,50 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) EXPORT_SYMBOL(find_vma); -/* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ +/* + * Same as find_vma, but also return a pointer to the previous VMA in *pprev. -+ * Note: pprev is set to NULL when return value is NULL. + */ struct vm_area_struct * find_vma_prev(struct mm_struct *mm, unsigned long addr, @@ -69576,22 +69710,13 @@ index eae90af..44552cf 100644 - struct rb_node *rb_node; - if (!mm) - goto out; -+ struct vm_area_struct *vma; - +- - /* Guard against addr being lower than the first VMA */ - vma = mm->mmap; -+ vma = find_vma(mm, addr); -+ *pprev = vma ? vma->vm_prev : NULL; -+ return vma; -+} - +- - /* Go through the RB tree quickly. */ - rb_node = mm->mm_rb.rb_node; -+#ifdef CONFIG_PAX_SEGMEXEC -+struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma) -+{ -+ struct vm_area_struct *vma_m; - +- - while (rb_node) { - struct vm_area_struct *vma_tmp; - vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); @@ -69602,17 +69727,35 @@ index eae90af..44552cf 100644 - prev = vma_tmp; - if (!prev->vm_next || (addr < prev->vm_next->vm_end)) - break; -- rb_node = rb_node->rb_right; -- } -+ BUG_ON(!vma || vma->vm_start >= vma->vm_end); -+ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) { -+ BUG_ON(vma->vm_mirror); -+ return NULL; ++ struct vm_area_struct *vma; ++ ++ vma = find_vma(mm, addr); ++ if (vma) { ++ *pprev = vma->vm_prev; ++ } else { ++ struct rb_node *rb_node = mm->mm_rb.rb_node; ++ *pprev = NULL; ++ while (rb_node) { ++ *pprev = rb_entry(rb_node, struct vm_area_struct, vm_rb); + rb_node = rb_node->rb_right; + } } -- ++ return vma; ++} ++ ++#ifdef CONFIG_PAX_SEGMEXEC ++struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma) ++{ ++ struct vm_area_struct *vma_m; + -out: - *pprev = prev; - return prev ? prev->vm_next : vma; ++ BUG_ON(!vma || vma->vm_start >= vma->vm_end); ++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) { ++ BUG_ON(vma->vm_mirror); ++ return NULL; ++ } + BUG_ON(vma->vm_start < SEGMEXEC_TASK_SIZE && SEGMEXEC_TASK_SIZE < vma->vm_end); + vma_m = vma->vm_mirror; + BUG_ON(!vma_m || vma_m->vm_mirror != vma); @@ -69627,7 +69770,7 @@ index eae90af..44552cf 100644 /* * Verify that the stack growth is acceptable and -@@ -1654,6 +1882,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1654,6 +1893,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns return -ENOMEM; /* Stack limit test */ @@ -69635,7 +69778,7 @@ index eae90af..44552cf 100644 if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) return -ENOMEM; -@@ -1664,6 +1893,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1664,6 +1904,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns locked = mm->locked_vm + grow; limit = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur); limit >>= PAGE_SHIFT; @@ -69643,7 +69786,7 @@ index eae90af..44552cf 100644 if (locked > limit && !capable(CAP_IPC_LOCK)) return -ENOMEM; } -@@ -1694,37 +1924,48 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns +@@ -1694,37 +1935,48 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns * PA-RISC uses this for its stack; IA64 for its Register Backing Store. * vma is the last one with address > vma->vm_end. Have to extend vma. */ @@ -69701,7 +69844,7 @@ index eae90af..44552cf 100644 unsigned long size, grow; size = address - vma->vm_start; -@@ -1739,6 +1980,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) +@@ -1739,6 +1991,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) } } } @@ -69710,7 +69853,7 @@ index eae90af..44552cf 100644 vma_unlock_anon_vma(vma); khugepaged_enter_vma_merge(vma); return error; -@@ -1752,6 +1995,8 @@ int expand_downwards(struct vm_area_struct *vma, +@@ -1752,6 +2006,8 @@ int expand_downwards(struct vm_area_struct *vma, unsigned long address) { int error; @@ -69719,7 +69862,7 @@ index eae90af..44552cf 100644 /* * We must make sure the anon_vma is allocated -@@ -1765,6 +2010,15 @@ int expand_downwards(struct vm_area_struct *vma, +@@ -1765,6 +2021,15 @@ int expand_downwards(struct vm_area_struct *vma, if (error) return error; @@ -69735,7 +69878,7 @@ index eae90af..44552cf 100644 vma_lock_anon_vma(vma); /* -@@ -1774,9 +2028,17 @@ int expand_downwards(struct vm_area_struct *vma, +@@ -1774,9 +2039,17 @@ int expand_downwards(struct vm_area_struct *vma, */ /* Somebody else might have raced and expanded it already */ @@ -69754,7 +69897,7 @@ index eae90af..44552cf 100644 size = vma->vm_end - address; grow = (vma->vm_start - address) >> PAGE_SHIFT; -@@ -1786,11 +2048,22 @@ int expand_downwards(struct vm_area_struct *vma, +@@ -1786,11 +2059,22 @@ int expand_downwards(struct vm_area_struct *vma, if (!error) { vma->vm_start = address; vma->vm_pgoff -= grow; @@ -69777,7 +69920,7 @@ index eae90af..44552cf 100644 khugepaged_enter_vma_merge(vma); return error; } -@@ -1860,6 +2133,13 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) +@@ -1860,6 +2144,13 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) do { long nrpages = vma_pages(vma); @@ -69791,7 +69934,7 @@ index eae90af..44552cf 100644 mm->total_vm -= nrpages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); vma = remove_vma(vma); -@@ -1905,6 +2185,16 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -1905,6 +2196,16 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, insertion_point = (prev ? &prev->vm_next : &mm->mmap); vma->vm_prev = NULL; do { @@ -69808,7 +69951,7 @@ index eae90af..44552cf 100644 rb_erase(&vma->vm_rb, &mm->mm_rb); mm->map_count--; tail_vma = vma; -@@ -1933,14 +2223,33 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1933,14 +2234,33 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct *new; int err = -ENOMEM; @@ -69842,7 +69985,7 @@ index eae90af..44552cf 100644 /* most fields are the same, copy all, and then fixup */ *new = *vma; -@@ -1953,6 +2262,22 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1953,6 +2273,22 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT); } @@ -69865,7 +70008,7 @@ index eae90af..44552cf 100644 pol = mpol_dup(vma_policy(vma)); if (IS_ERR(pol)) { err = PTR_ERR(pol); -@@ -1978,6 +2303,42 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1978,6 +2314,42 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, else err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); @@ -69908,7 +70051,7 @@ index eae90af..44552cf 100644 /* Success. */ if (!err) return 0; -@@ -1990,10 +2351,18 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -1990,10 +2362,18 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, removed_exe_file_vma(mm); fput(new->vm_file); } @@ -69928,7 +70071,7 @@ index eae90af..44552cf 100644 kmem_cache_free(vm_area_cachep, new); out_err: return err; -@@ -2006,6 +2375,15 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, +@@ -2006,6 +2386,15 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int new_below) { @@ -69944,7 +70087,7 @@ index eae90af..44552cf 100644 if (mm->map_count >= sysctl_max_map_count) return -ENOMEM; -@@ -2017,11 +2395,30 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2017,11 +2406,30 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma, * work. This now handles partial unmappings. * Jeremy Fitzhardinge <jeremy@goop.org> */ @@ -69975,7 +70118,7 @@ index eae90af..44552cf 100644 if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start) return -EINVAL; -@@ -2096,6 +2493,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) +@@ -2096,6 +2504,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) /* Fix up all other VM information */ remove_vma_list(mm, vma); @@ -69984,7 +70127,7 @@ index eae90af..44552cf 100644 return 0; } -@@ -2108,22 +2507,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) +@@ -2108,22 +2518,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len) profile_munmap(addr); @@ -70013,7 +70156,7 @@ index eae90af..44552cf 100644 /* * this is really a simplified "do_mmap". it only handles * anonymous maps. eventually we may be able to do some -@@ -2137,6 +2532,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2137,6 +2543,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) struct rb_node ** rb_link, * rb_parent; pgoff_t pgoff = addr >> PAGE_SHIFT; int error; @@ -70021,7 +70164,7 @@ index eae90af..44552cf 100644 len = PAGE_ALIGN(len); if (!len) -@@ -2148,16 +2544,30 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2148,16 +2555,30 @@ unsigned long do_brk(unsigned long addr, unsigned long len) flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; @@ -70053,7 +70196,7 @@ index eae90af..44552cf 100644 locked += mm->locked_vm; lock_limit = rlimit(RLIMIT_MEMLOCK); lock_limit >>= PAGE_SHIFT; -@@ -2174,22 +2584,22 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2174,22 +2595,22 @@ unsigned long do_brk(unsigned long addr, unsigned long len) /* * Clear old maps. this also does some error checking for us */ @@ -70080,7 +70223,7 @@ index eae90af..44552cf 100644 return -ENOMEM; /* Can we just expand an old private anonymous mapping? */ -@@ -2203,7 +2613,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2203,7 +2624,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) */ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (!vma) { @@ -70089,7 +70232,7 @@ index eae90af..44552cf 100644 return -ENOMEM; } -@@ -2217,11 +2627,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) +@@ -2217,11 +2638,12 @@ unsigned long do_brk(unsigned long addr, unsigned long len) vma_link(mm, vma, prev, rb_link, rb_parent); out: perf_event_mmap(vma); @@ -70104,7 +70247,7 @@ index eae90af..44552cf 100644 return addr; } -@@ -2268,8 +2679,10 @@ void exit_mmap(struct mm_struct *mm) +@@ -2268,8 +2690,10 @@ void exit_mmap(struct mm_struct *mm) * Walk the list again, actually closing and freeing it, * with preemption enabled, without holding any MM locks. */ @@ -70116,7 +70259,7 @@ index eae90af..44552cf 100644 BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); } -@@ -2283,6 +2696,13 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) +@@ -2283,6 +2707,13 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) struct vm_area_struct * __vma, * prev; struct rb_node ** rb_link, * rb_parent; @@ -70130,7 +70273,7 @@ index eae90af..44552cf 100644 /* * The vm_pgoff of a purely anonymous vma should be irrelevant * until its first write fault, when page's anon_vma and index -@@ -2305,7 +2725,22 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) +@@ -2305,7 +2736,22 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) if ((vma->vm_flags & VM_ACCOUNT) && security_vm_enough_memory_mm(mm, vma_pages(vma))) return -ENOMEM; @@ -70153,7 +70296,7 @@ index eae90af..44552cf 100644 return 0; } -@@ -2323,6 +2758,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -2323,6 +2769,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, struct rb_node **rb_link, *rb_parent; struct mempolicy *pol; @@ -70162,7 +70305,7 @@ index eae90af..44552cf 100644 /* * If anonymous vma has not yet been faulted, update new pgoff * to match new location, to increase its chance of merging. -@@ -2373,6 +2810,39 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -2373,6 +2821,39 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, return NULL; } @@ -70202,7 +70345,7 @@ index eae90af..44552cf 100644 /* * Return true if the calling process may expand its vm space by the passed * number of pages -@@ -2383,7 +2853,7 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages) +@@ -2383,7 +2864,7 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages) unsigned long lim; lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT; @@ -70211,7 +70354,7 @@ index eae90af..44552cf 100644 if (cur + npages > lim) return 0; return 1; -@@ -2454,6 +2924,22 @@ int install_special_mapping(struct mm_struct *mm, +@@ -2454,6 +2935,22 @@ int install_special_mapping(struct mm_struct *mm, vma->vm_start = addr; vma->vm_end = addr + len; @@ -77792,7 +77935,7 @@ index a39edcc..1014050 100644 }; diff --git a/tools/gcc/Makefile b/tools/gcc/Makefile new file mode 100644 -index 0000000..481a163 +index 0000000..469b06a --- /dev/null +++ b/tools/gcc/Makefile @@ -0,0 +1,21 @@ @@ -77802,7 +77945,7 @@ index 0000000..481a163 +GCCPLUGINS_DIR := $(shell $(CC) -print-file-name=plugin) +#CFLAGS += -I$(GCCPLUGINS_DIR)/include -fPIC -O2 -Wall -W -std=gnu99 + -+HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -std=gnu99 -ggdb ++HOST_EXTRACFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(GCCPLUGINS_DIR)/include/c-family -std=gnu99 -ggdb + +hostlibs-y := constify_plugin.so +hostlibs-$(CONFIG_PAX_MEMORY_STACKLEAK) += stackleak_plugin.so |