summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2012-03-08 21:00:06 -0500
committerAnthony G. Basile <blueness@gentoo.org>2012-03-08 21:00:06 -0500
commit5d847b8dac5c3df11e6bbcbb540f05d2cda90947 (patch)
treeb9ec3c252274cc079254b41be99cb22e0f42717c
parentGrsec/PaX: 2.9-2.6.32.57-201203022148 + 2.9-3.2.9-201203022148 (diff)
downloadhardened-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_README2
-rw-r--r--2.6.32/1057_linux-2.6.32.58.patch1280
-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_README2
-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(&current->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(&current->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(&current->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(&current->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