summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2013-06-05 16:08:19 -0400
committerAnthony G. Basile <blueness@gentoo.org>2013-06-05 16:08:19 -0400
commit7613b2514cbb5fd2e7956f2facabe3204b4449bc (patch)
tree733e7d165dd875be2966355b95e948f77a5ac948
parentGrsec/PaX: 2.9.1-{2.6.32.60,3.2.45,3.9.4}-201306011536 (diff)
downloadhardened-patchset-7613b2514cbb5fd2e7956f2facabe3204b4449bc.tar.gz
hardened-patchset-7613b2514cbb5fd2e7956f2facabe3204b4449bc.tar.bz2
hardened-patchset-7613b2514cbb5fd2e7956f2facabe3204b4449bc.zip
Grsec/PaX: 2.9.1-{2.6.32.60,3.2.45,3.9.4}-201306041949
-rw-r--r--2.6.32/0000_README2
-rw-r--r--2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306041946.patch (renamed from 2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306011535.patch)137
-rw-r--r--3.2.45/0000_README2
-rw-r--r--3.2.45/4420_grsecurity-2.9.1-3.2.46-201306041947.patch (renamed from 3.2.45/4420_grsecurity-2.9.1-3.2.46-201306011535.patch)390
-rw-r--r--3.9.4/0000_README2
-rw-r--r--3.9.4/4420_grsecurity-2.9.1-3.9.4-201306041949.patch (renamed from 3.9.4/4420_grsecurity-2.9.1-3.9.4-201306011536.patch)396
6 files changed, 857 insertions, 72 deletions
diff --git a/2.6.32/0000_README b/2.6.32/0000_README
index 4edfd58..797feaa 100644
--- a/2.6.32/0000_README
+++ b/2.6.32/0000_README
@@ -34,7 +34,7 @@ Patch: 1059_linux-2.6.32.60.patch
From: http://www.kernel.org
Desc: Linux 2.6.32.59
-Patch: 4420_grsecurity-2.9.1-2.6.32.60-201306011535.patch
+Patch: 4420_grsecurity-2.9.1-2.6.32.60-201306041946.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306011535.patch b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306041946.patch
index eb29409..8e09bd0 100644
--- a/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306011535.patch
+++ b/2.6.32/4420_grsecurity-2.9.1-2.6.32.60-201306041946.patch
@@ -3605,6 +3605,19 @@ index a27d2e2..18fd845 100644
#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
#define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
+diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
+index 994bcd9..f25247a 100644
+--- a/arch/parisc/kernel/drivers.c
++++ b/arch/parisc/kernel/drivers.c
+@@ -393,7 +393,7 @@ EXPORT_SYMBOL(print_pci_hwpath);
+ static void setup_bus_id(struct parisc_device *padev)
+ {
+ struct hardware_path path;
+- char name[20];
++ char name[28];
+ char *output = name;
+ int i;
+
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 2120746..8d70a5e 100644
--- a/arch/parisc/kernel/module.c
@@ -3708,6 +3721,20 @@ index 2120746..8d70a5e 100644
DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
me->arch.unwind_section, table, end, gp);
+diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
+index cb71f3d..306f0c0 100644
+--- a/arch/parisc/kernel/setup.c
++++ b/arch/parisc/kernel/setup.c
+@@ -68,7 +68,8 @@ void __init setup_cmdline(char **cmdline_p)
+ /* called from hpux boot loader */
+ boot_command_line[0] = '\0';
+ } else {
+- strcpy(boot_command_line, (char *)__va(boot_args[1]));
++ strlcpy(boot_command_line, (char *)__va(boot_args[1]),
++ COMMAND_LINE_SIZE);
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index fb59852..32d43e7 100644
--- a/arch/parisc/kernel/signal32.c
@@ -47545,6 +47572,28 @@ index 0236f0d..c7327f1 100644
serio->dev.bus = &serio_bus;
serio->dev.release = serio_release_port;
if (serio->parent) {
+diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
+index dc506ab..af04b54 100644
+--- a/drivers/isdn/capi/kcapi.c
++++ b/drivers/isdn/capi/kcapi.c
+@@ -95,7 +95,7 @@ capi_ctr_put(struct capi_ctr *card)
+
+ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
+ {
+- if (contr - 1 >= CAPI_MAXCONTR)
++ if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
+ return NULL;
+
+ return capi_cards[contr - 1];
+@@ -103,7 +103,7 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
+
+ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
+ {
+- if (applid - 1 >= CAPI_MAXAPPL)
++ if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return capi_applications[applid - 1];
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 33dcd8d..2783d25 100644
--- a/drivers/isdn/gigaset/common.c
@@ -82186,6 +82235,19 @@ index bfaef7b..e9d03ca 100644
}
void nfs_fattr_init(struct nfs_fattr *fattr)
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 21c7190..22688d5 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -915,7 +915,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+ struct nfs4_state *state = opendata->state;
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_delegation *delegation;
+- int open_mode = opendata->o_arg.open_flags & O_EXCL;
++ int open_mode = opendata->o_arg.open_flags;
+ fmode_t fmode = opendata->o_arg.fmode;
+ nfs4_stateid stateid;
+ int ret = -EAGAIN;
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index cc2f505..f6a236f 100644
--- a/fs/nfsd/lockd.c
@@ -84523,7 +84585,7 @@ index 7723401..30059a6 100644
error = -EFAULT;
else
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
-index d42c30c..4fd8718 100644
+index d42c30c..153b170 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -66,6 +66,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
@@ -84535,6 +84597,15 @@ index d42c30c..4fd8718 100644
reiserfs_write_lock(inode->i_sb);
reiserfs_check_lock_depth(inode->i_sb, "readdir");
+@@ -187,6 +189,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
+ next_pos = deh_offset(deh) + 1;
+
+ if (item_moved(&tmp_ih, &path_to_entry)) {
++ set_cpu_key_k_offset(&pos_key,
++ next_pos);
+ goto research;
+ }
+ } /* for */
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 128d3f7c..8840d44 100644
--- a/fs/reiserfs/do_balan.c
@@ -84548,6 +84619,29 @@ index 128d3f7c..8840d44 100644
do_balance_starts(tb);
/* balance leaf returns 0 except if combining L R and S into
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index d240c15..c38a41a 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -1786,11 +1786,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
+ TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
+ memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
+ args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
+- if (insert_inode_locked4(inode, args.objectid,
+- reiserfs_find_actor, &args) < 0) {
++
++ reiserfs_write_unlock(inode->i_sb);
++ err = insert_inode_locked4(inode, args.objectid,
++ reiserfs_find_actor, &args);
++ reiserfs_write_lock(inode->i_sb);
++ if (err) {
+ err = -EINVAL;
+ goto out_bad_inode;
+ }
++
+ if (old_format_only(sb))
+ /* not a perfect generation count, as object ids can be reused, but
+ ** this is as good as reiserfs can do right now.
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
index 72cb1cc..d0e3181 100644
--- a/fs/reiserfs/item_ops.c
@@ -115872,7 +115966,7 @@ index 2dcf04d..4656638 100644
{
.ctl_name = NET_TCP_DMA_COPYBREAK,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index b9644d8..537313b 100644
+index b9644d8..8e66b8e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2084,6 +2084,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
@@ -115893,6 +115987,19 @@ index b9644d8..537313b 100644
if (get_user(len, optlen))
return -EFAULT;
+@@ -2826,7 +2830,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
+
+ for (i = 0; i < shi->nr_frags; ++i) {
+ const struct skb_frag_struct *f = &shi->frags[i];
+- sg_set_page(&sg, f->page, f->size, f->page_offset);
++ unsigned int offset = f->page_offset;
++ struct page *page = f->page + (offset >> PAGE_SHIFT);
++
++ sg_set_page(&sg, page, f->size,
++ offset_in_page(offset));
+ if (crypto_hash_update(desc, &sg, f->size))
+ return 1;
+ }
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index 1eba160b..c35d91f 100644
--- a/net/ipv4/tcp_illinois.c
@@ -116507,6 +116614,19 @@ index 093e9b2..f72cddb 100644
const unsigned short hnum,
const struct in6_addr *daddr,
const int dif)
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 9ad5792..fa406b9 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1138,7 +1138,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ if (WARN_ON(np->cork.opt))
+ return -EINVAL;
+
+- np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
++ np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
+ if (unlikely(np->cork.opt == NULL))
+ return -ENOBUFS;
+
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 4f7aaf6..f7acf45 100644
--- a/net/ipv6/ipv6_sockglue.c
@@ -117047,6 +117167,19 @@ index 35a338b..62102d6 100644
/* Aborting, close connection! */
iriap_disconnect_request(self);
+diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
+index 7af2e74..143ae58 100644
+--- a/net/irda/irlap_frame.c
++++ b/net/irda/irlap_frame.c
+@@ -543,7 +543,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ /*
+ * We now have some discovery info to deliver!
+ */
+- discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
++ discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC);
+ if (!discovery) {
+ IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ return;
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 9cb79f9..d35d057 100644
--- a/net/irda/irttp.c
diff --git a/3.2.45/0000_README b/3.2.45/0000_README
index 00f8a3a..4a59301 100644
--- a/3.2.45/0000_README
+++ b/3.2.45/0000_README
@@ -98,7 +98,7 @@ Patch: 1044_linux-3.2.45.patch
From: http://www.kernel.org
Desc: Linux 3.2.45
-Patch: 4420_grsecurity-2.9.1-3.2.46-201306011535.patch
+Patch: 4420_grsecurity-2.9.1-3.2.46-201306041947.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/3.2.45/4420_grsecurity-2.9.1-3.2.46-201306011535.patch b/3.2.45/4420_grsecurity-2.9.1-3.2.46-201306041947.patch
index 6555c18..bf3ae8a 100644
--- a/3.2.45/4420_grsecurity-2.9.1-3.2.46-201306011535.patch
+++ b/3.2.45/4420_grsecurity-2.9.1-3.2.46-201306041947.patch
@@ -3860,6 +3860,19 @@ index 5241698..91dcb12 100644
}
EXPORT_SYMBOL(purge_tlb_entries);
+diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
+index 5709c5e..14285ca 100644
+--- a/arch/parisc/kernel/drivers.c
++++ b/arch/parisc/kernel/drivers.c
+@@ -394,7 +394,7 @@ EXPORT_SYMBOL(print_pci_hwpath);
+ static void setup_bus_id(struct parisc_device *padev)
+ {
+ struct hardware_path path;
+- char name[20];
++ char name[28];
+ char *output = name;
+ int i;
+
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 5e34ccf..672bc9c 100644
--- a/arch/parisc/kernel/module.c
@@ -3963,6 +3976,20 @@ index 5e34ccf..672bc9c 100644
DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
me->arch.unwind_section, table, end, gp);
+diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
+index a3328c2..3b812eb 100644
+--- a/arch/parisc/kernel/setup.c
++++ b/arch/parisc/kernel/setup.c
+@@ -69,7 +69,8 @@ void __init setup_cmdline(char **cmdline_p)
+ /* called from hpux boot loader */
+ boot_command_line[0] = '\0';
+ } else {
+- strcpy(boot_command_line, (char *)__va(boot_args[1]));
++ strlcpy(boot_command_line, (char *)__va(boot_args[1]),
++ COMMAND_LINE_SIZE);
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 7ea75d1..38ca97d 100644
--- a/arch/parisc/kernel/sys_parisc.c
@@ -36879,6 +36906,37 @@ index e44933d..9ba484a 100644
capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
capimsg_setu16(skb->data, 16, len); /* Data length */
+diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
+index 2b33b26..a9c638b 100644
+--- a/drivers/isdn/capi/kcapi.c
++++ b/drivers/isdn/capi/kcapi.c
+@@ -93,7 +93,7 @@ capi_ctr_put(struct capi_ctr *ctr)
+
+ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
+ {
+- if (contr - 1 >= CAPI_MAXCONTR)
++ if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
+ return NULL;
+
+ return capi_controller[contr - 1];
+@@ -103,7 +103,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+ {
+ lockdep_assert_held(&capi_controller_lock);
+
+- if (applid - 1 >= CAPI_MAXAPPL)
++ if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return capi_applications[applid - 1];
+@@ -111,7 +111,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+
+ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
+ {
+- if (applid - 1 >= CAPI_MAXAPPL)
++ if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return rcu_dereference(capi_applications[applid - 1]);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index db621db..825ea1a 100644
--- a/drivers/isdn/gigaset/common.c
@@ -53660,6 +53718,19 @@ index b78b5b6..c64d84f 100644
}
void nfs_fattr_init(struct nfs_fattr *fattr)
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 5639efd..4531174 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1037,7 +1037,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+ struct nfs4_state *state = opendata->state;
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_delegation *delegation;
+- int open_mode = opendata->o_arg.open_flags & O_EXCL;
++ int open_mode = opendata->o_arg.open_flags;
+ fmode_t fmode = opendata->o_arg.fmode;
+ nfs4_stateid stateid;
+ int ret = -EAGAIN;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 1943898..396c460 100644
--- a/fs/nfs/super.c
@@ -55971,6 +56042,19 @@ index 356f715..c918d38 100644
if (__put_user(d_off, &lastdirent->d_off))
error = -EFAULT;
else
+diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
+index 133e935..77359db 100644
+--- a/fs/reiserfs/dir.c
++++ b/fs/reiserfs/dir.c
+@@ -204,6 +204,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
+ next_pos = deh_offset(deh) + 1;
+
+ if (item_moved(&tmp_ih, &path_to_entry)) {
++ set_cpu_key_k_offset(&pos_key,
++ next_pos);
+ goto research;
+ }
+ } /* for */
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 60c0804..d814f98 100644
--- a/fs/reiserfs/do_balan.c
@@ -55984,6 +56068,29 @@ index 60c0804..d814f98 100644
do_balance_starts(tb);
/* balance leaf returns 0 except if combining L R and S into
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index fe677c0..2a15fb2 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -1816,11 +1816,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
+ TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
+ memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
+ args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
+- if (insert_inode_locked4(inode, args.objectid,
+- reiserfs_find_actor, &args) < 0) {
++
++ reiserfs_write_unlock(inode->i_sb);
++ err = insert_inode_locked4(inode, args.objectid,
++ reiserfs_find_actor, &args);
++ reiserfs_write_lock(inode->i_sb);
++ if (err) {
+ err = -EINVAL;
+ goto out_bad_inode;
+ }
++
+ if (old_format_only(sb))
+ /* not a perfect generation count, as object ids can be reused, but
+ ** this is as good as reiserfs can do right now.
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 7a99811..a7c96c4 100644
--- a/fs/reiserfs/procfs.c
@@ -56009,6 +56116,45 @@ index 569498a..0886e50f 100644
MODULE_DESCRIPTION("ReiserFS journaled filesystem");
MODULE_AUTHOR("Hans Reiser <reiser@namesys.com>");
+diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
+index 04eecc4..33f74d0 100644
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -318,7 +318,19 @@ static int delete_one_xattr(struct dentry *dentry, void *data)
+ static int chown_one_xattr(struct dentry *dentry, void *data)
+ {
+ struct iattr *attrs = data;
+- return reiserfs_setattr(dentry, attrs);
++ int ia_valid = attrs->ia_valid;
++ int err;
++
++ /*
++ * We only want the ownership bits. Otherwise, we'll do
++ * things like change a directory to a regular file if
++ * ATTR_MODE is set.
++ */
++ attrs->ia_valid &= (ATTR_UID|ATTR_GID);
++ err = reiserfs_setattr(dentry, attrs);
++ attrs->ia_valid = ia_valid;
++
++ return err;
+ }
+
+ /* No i_mutex, but the inode is unconnected. */
+diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
+index 6da0396..fc338f3 100644
+--- a/fs/reiserfs/xattr_acl.c
++++ b/fs/reiserfs/xattr_acl.c
+@@ -429,6 +429,9 @@ int reiserfs_acl_chmod(struct inode *inode)
+ int depth;
+ int error;
+
++ if (IS_PRIVATE(inode))
++ return 0;
++
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 8b4089f..2575128 100644
--- a/fs/romfs/super.c
@@ -56723,7 +56869,7 @@ index d99a905..9f88202 100644
goto out_put;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
-index 23ce927..e274cc1 100644
+index 23ce927..86fd3e8d 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -447,7 +447,7 @@ xfs_vn_put_link(
@@ -56735,6 +56881,81 @@ index 23ce927..e274cc1 100644
if (!IS_ERR(s))
kfree(s);
+@@ -507,6 +507,28 @@ xfs_vn_getattr(
+ return 0;
+ }
+
++static void
++xfs_setattr_mode(
++ struct xfs_trans *tp,
++ struct xfs_inode *ip,
++ struct iattr *iattr)
++{
++ struct inode *inode = VFS_I(ip);
++ umode_t mode = iattr->ia_mode;
++
++ ASSERT(tp);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
++
++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
++ mode &= ~S_ISGID;
++
++ ip->i_d.di_mode &= S_IFMT;
++ ip->i_d.di_mode |= mode & ~S_IFMT;
++
++ inode->i_mode &= S_IFMT;
++ inode->i_mode |= mode & ~S_IFMT;
++}
++
+ int
+ xfs_setattr_nonsize(
+ struct xfs_inode *ip,
+@@ -658,18 +680,8 @@ xfs_setattr_nonsize(
+ /*
+ * Change file access modes.
+ */
+- if (mask & ATTR_MODE) {
+- umode_t mode = iattr->ia_mode;
+-
+- if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+- mode &= ~S_ISGID;
+-
+- ip->i_d.di_mode &= S_IFMT;
+- ip->i_d.di_mode |= mode & ~S_IFMT;
+-
+- inode->i_mode &= S_IFMT;
+- inode->i_mode |= mode & ~S_IFMT;
+- }
++ if (mask & ATTR_MODE)
++ xfs_setattr_mode(tp, ip, iattr);
+
+ /*
+ * Change file access or modified times.
+@@ -768,9 +780,8 @@ xfs_setattr_size(
+ return XFS_ERROR(error);
+
+ ASSERT(S_ISREG(ip->i_d.di_mode));
+- ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+- ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID|
+- ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
++ ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
++ ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+
+ lock_flags = XFS_ILOCK_EXCL;
+ if (!(flags & XFS_ATTR_NOLOCK))
+@@ -902,6 +913,12 @@ xfs_setattr_size(
+ xfs_iflags_set(ip, XFS_ITRUNCATED);
+ }
+
++ /*
++ * Change file access modes.
++ */
++ if (mask & ATTR_MODE)
++ xfs_setattr_mode(tp, ip, iattr);
++
+ if (mask & ATTR_CTIME) {
+ inode->i_ctime = iattr->ia_ctime;
+ ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 87323f1..dab9d00 100644
--- a/fs/xfs/xfs_rtalloc.c
@@ -56762,10 +56983,10 @@ index 8a89949..6776861 100644
xfs_init_zones(void)
diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig
new file mode 100644
-index 0000000..aef8e91
+index 0000000..15aaf25
--- /dev/null
+++ b/grsecurity/Kconfig
-@@ -0,0 +1,1031 @@
+@@ -0,0 +1,1053 @@
+#
+# grecurity configuration
+#
@@ -56851,6 +57072,25 @@ index 0000000..aef8e91
+ If you're using KERNEXEC, it's recommended that you enable this option
+ to supplement the hardening of the kernel.
+
++config GRKERNSEC_PERF_HARDEN
++ bool "Disable unprivileged PERF_EVENTS usage by default"
++ default y if GRKERNSEC_CONFIG_AUTO
++ depends on PERF_EVENTS
++ help
++ If you say Y here, the range of acceptable values for the
++ /proc/sys/kernel/perf_event_paranoid sysctl will be expanded to allow and
++ default to a new value: 3. When the sysctl is set to this value, no
++ unprivileged use of the PERF_EVENTS syscall interface will be permitted.
++
++ Though PERF_EVENTS can be used legitimately for performance monitoring
++ and low-level application profiling, it is forced on regardless of
++ configuration, has been at fault for several vulnerabilities, and
++ creates new opportunities for side channels and other information leaks.
++
++ This feature puts PERF_EVENTS into a secure default state and permits
++ the administrator to change out of it temporarily if unprivileged
++ application profiling is needed.
++
+config GRKERNSEC_RAND_THREADSTACK
+ bool "Insert random gaps between thread stacks"
+ default y if GRKERNSEC_CONFIG_AUTO
@@ -56961,6 +57201,9 @@ index 0000000..aef8e91
+ useful protection against local kernel exploitation of overflows
+ and arbitrary read/write vulnerabilities.
+
++ It is highly recommended that you enable GRKERNSEC_PERF_HARDEN
++ in addition to this feature.
++
+config GRKERNSEC_KERN_LOCKOUT
+ bool "Active kernel exploit response"
+ default y if GRKERNSEC_CONFIG_AUTO
@@ -70897,7 +71140,7 @@ index 45fc162..01a4068 100644
/**
* struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
-index 9b9b2aa..22f09dc 100644
+index 9b9b2aa..df3199e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -748,8 +748,8 @@ struct perf_event {
@@ -70931,8 +71174,15 @@ index 9b9b2aa..22f09dc 100644
extern int sysctl_perf_event_mlock;
extern int sysctl_perf_event_sample_rate;
-@@ -1111,17 +1111,17 @@ extern int perf_proc_update_handler(struct ctl_table *table, int write,
+@@ -1109,19 +1109,24 @@ extern int perf_proc_update_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos);
++static inline bool perf_paranoid_any(void)
++{
++ return sysctl_perf_event_legitimately_concerned > 2;
++}
++
static inline bool perf_paranoid_tracepoint_raw(void)
{
- return sysctl_perf_event_paranoid > -1;
@@ -70952,7 +71202,7 @@ index 9b9b2aa..22f09dc 100644
}
extern void perf_event_init(void);
-@@ -1199,7 +1199,7 @@ static inline void perf_restore_debug_store(void) { }
+@@ -1199,7 +1204,7 @@ static inline void perf_restore_debug_store(void) { }
*/
#define perf_cpu_notifier(fn) \
do { \
@@ -74914,15 +75164,19 @@ index 63786e7..0780cac 100644
#ifdef CONFIG_MODULE_UNLOAD
{
diff --git a/kernel/events/core.c b/kernel/events/core.c
-index 9f21915..08e25b4 100644
+index 9f21915..840113c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
-@@ -146,7 +146,11 @@ static struct srcu_struct pmus_srcu;
+@@ -145,8 +145,15 @@ static struct srcu_struct pmus_srcu;
+ * 0 - disallow raw tracepoint access for unpriv
* 1 - disallow cpu events for unpriv
* 2 - disallow kernel profiling for unpriv
++ * 3 - disallow all unpriv perf event use
*/
-int sysctl_perf_event_paranoid __read_mostly = 1;
-+#ifdef CONFIG_GRKERNSEC_HIDESYM
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++int sysctl_perf_event_legitimately_concerned __read_mostly = 3;
++#elif CONFIG_GRKERNSEC_HIDESYM
+int sysctl_perf_event_legitimately_concerned __read_mostly = 2;
+#else
+int sysctl_perf_event_legitimately_concerned __read_mostly = 1;
@@ -74930,7 +75184,7 @@ index 9f21915..08e25b4 100644
/* Minimum for 512 kiB + 1 user control page */
int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
-@@ -173,7 +177,7 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
+@@ -173,7 +180,7 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
return 0;
}
@@ -74939,7 +75193,7 @@ index 9f21915..08e25b4 100644
static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
enum event_type_t event_type);
-@@ -2540,7 +2544,7 @@ static void __perf_event_read(void *info)
+@@ -2540,7 +2547,7 @@ static void __perf_event_read(void *info)
static inline u64 perf_event_count(struct perf_event *event)
{
@@ -74948,7 +75202,7 @@ index 9f21915..08e25b4 100644
}
static u64 perf_event_read(struct perf_event *event)
-@@ -3071,9 +3075,9 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
+@@ -3071,9 +3078,9 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
mutex_lock(&event->child_mutex);
total += perf_event_read(event);
*enabled += event->total_time_enabled +
@@ -74960,7 +75214,7 @@ index 9f21915..08e25b4 100644
list_for_each_entry(child, &event->child_list, child_list) {
total += perf_event_read(child);
-@@ -3482,10 +3486,10 @@ void perf_event_update_userpage(struct perf_event *event)
+@@ -3482,10 +3489,10 @@ void perf_event_update_userpage(struct perf_event *event)
userpg->offset -= local64_read(&event->hw.prev_count);
userpg->time_enabled = enabled +
@@ -74973,7 +75227,7 @@ index 9f21915..08e25b4 100644
barrier();
++userpg->lock;
-@@ -3914,11 +3918,11 @@ static void perf_output_read_one(struct perf_output_handle *handle,
+@@ -3914,11 +3921,11 @@ static void perf_output_read_one(struct perf_output_handle *handle,
values[n++] = perf_event_count(event);
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
values[n++] = enabled +
@@ -74987,7 +75241,7 @@ index 9f21915..08e25b4 100644
}
if (read_format & PERF_FORMAT_ID)
values[n++] = primary_event_id(event);
-@@ -4569,12 +4573,12 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
+@@ -4569,12 +4576,12 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
* need to add enough zero bytes after the string to handle
* the 64bit alignment we do later.
*/
@@ -75002,7 +75256,7 @@ index 9f21915..08e25b4 100644
if (IS_ERR(name)) {
name = strncpy(tmp, "//toolong", sizeof(tmp));
goto got_name;
-@@ -5931,7 +5935,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
+@@ -5931,7 +5938,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
event->parent = parent_event;
event->ns = get_pid_ns(current->nsproxy->pid_ns);
@@ -75011,7 +75265,19 @@ index 9f21915..08e25b4 100644
event->state = PERF_EVENT_STATE_INACTIVE;
-@@ -6451,10 +6455,10 @@ static void sync_child_event(struct perf_event *child_event,
+@@ -6164,6 +6171,11 @@ SYSCALL_DEFINE5(perf_event_open,
+ if (flags & ~PERF_FLAG_ALL)
+ return -EINVAL;
+
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN))
++ return -EACCES;
++#endif
++
+ err = perf_copy_attr(attr_uptr, &attr);
+ if (err)
+ return err;
+@@ -6451,10 +6463,10 @@ static void sync_child_event(struct perf_event *child_event,
/*
* Add back the child's count to the parent's count:
*/
@@ -78654,7 +78920,7 @@ index be5fa8b..a8c2090 100644
break;
}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index ea7ec7f..b1c7c88 100644
+index ea7ec7f..a823e62 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -86,6 +86,13 @@
@@ -78779,7 +79045,7 @@ index ea7ec7f..b1c7c88 100644
{
.procname = "ngroups_max",
.data = &ngroups_max,
-@@ -957,8 +1002,8 @@ static struct ctl_table kern_table[] = {
+@@ -957,10 +1002,17 @@ static struct ctl_table kern_table[] = {
*/
{
.procname = "perf_event_paranoid",
@@ -78788,9 +79054,19 @@ index ea7ec7f..b1c7c88 100644
+ .data = &sysctl_perf_event_legitimately_concerned,
+ .maxlen = sizeof(sysctl_perf_event_legitimately_concerned),
.mode = 0644,
- .proc_handler = proc_dointvec,
+- .proc_handler = proc_dointvec,
++ /* go ahead, be a hero */
++ .proc_handler = proc_dointvec_minmax_sysadmin,
++ .extra1 = &zero,
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++ .extra2 = &three,
++#else
++ .extra2 = &two,
++#endif
},
-@@ -1216,6 +1261,13 @@ static struct ctl_table vm_table[] = {
+ {
+ .procname = "perf_event_mlock_kb",
+@@ -1216,6 +1268,13 @@ static struct ctl_table vm_table[] = {
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
},
@@ -78804,7 +79080,7 @@ index ea7ec7f..b1c7c88 100644
#else
{
.procname = "nr_trim_pages",
-@@ -1499,7 +1551,7 @@ static struct ctl_table fs_table[] = {
+@@ -1499,7 +1558,7 @@ static struct ctl_table fs_table[] = {
.data = &suid_dumpable,
.maxlen = sizeof(int),
.mode = 0644,
@@ -78813,7 +79089,7 @@ index ea7ec7f..b1c7c88 100644
.extra1 = &zero,
.extra2 = &two,
},
-@@ -1720,6 +1772,17 @@ static int test_perm(int mode, int op)
+@@ -1720,6 +1779,17 @@ static int test_perm(int mode, int op)
int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
{
int mode;
@@ -78831,7 +79107,7 @@ index ea7ec7f..b1c7c88 100644
if (root->permissions)
mode = root->permissions(root, current->nsproxy, table);
-@@ -1732,7 +1795,9 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
+@@ -1732,7 +1802,9 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
{
for (; table->procname; table++) {
@@ -78842,7 +79118,7 @@ index ea7ec7f..b1c7c88 100644
if (table->child)
sysctl_set_parent(table, table->child);
}
-@@ -1856,7 +1921,8 @@ struct ctl_table_header *__register_sysctl_paths(
+@@ -1856,7 +1928,8 @@ struct ctl_table_header *__register_sysctl_paths(
const struct ctl_path *path, struct ctl_table *table)
{
struct ctl_table_header *header;
@@ -78852,7 +79128,7 @@ index ea7ec7f..b1c7c88 100644
unsigned int n, npath;
struct ctl_table_set *set;
-@@ -1877,7 +1943,7 @@ struct ctl_table_header *__register_sysctl_paths(
+@@ -1877,7 +1950,7 @@ struct ctl_table_header *__register_sysctl_paths(
if (!header)
return NULL;
@@ -78861,7 +79137,7 @@ index ea7ec7f..b1c7c88 100644
/* Now connect the dots */
prevp = &header->ctl_table;
-@@ -2124,6 +2190,16 @@ int proc_dostring(struct ctl_table *table, int write,
+@@ -2124,6 +2197,16 @@ int proc_dostring(struct ctl_table *table, int write,
buffer, lenp, ppos);
}
@@ -78878,7 +79154,7 @@ index ea7ec7f..b1c7c88 100644
static size_t proc_skip_spaces(char **buf)
{
size_t ret;
-@@ -2229,6 +2305,8 @@ static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
+@@ -2229,6 +2312,8 @@ static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
len = strlen(tmp);
if (len > *size)
len = *size;
@@ -78887,7 +79163,7 @@ index ea7ec7f..b1c7c88 100644
if (copy_to_user(*buf, tmp, len))
return -EFAULT;
*size -= len;
-@@ -2393,7 +2471,7 @@ int proc_dointvec(struct ctl_table *table, int write,
+@@ -2393,7 +2478,7 @@ int proc_dointvec(struct ctl_table *table, int write,
static int proc_taint(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
@@ -78896,7 +79172,7 @@ index ea7ec7f..b1c7c88 100644
unsigned long tmptaint = get_taint();
int err;
-@@ -2421,7 +2499,6 @@ static int proc_taint(struct ctl_table *table, int write,
+@@ -2421,7 +2506,6 @@ static int proc_taint(struct ctl_table *table, int write,
return err;
}
@@ -78904,7 +79180,7 @@ index ea7ec7f..b1c7c88 100644
static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
-@@ -2430,7 +2507,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
+@@ -2430,7 +2514,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
}
@@ -78912,7 +79188,7 @@ index ea7ec7f..b1c7c88 100644
struct do_proc_dointvec_minmax_conv_param {
int *min;
-@@ -2488,6 +2564,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
+@@ -2488,6 +2571,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
do_proc_dointvec_minmax_conv, &param);
}
@@ -78947,7 +79223,7 @@ index ea7ec7f..b1c7c88 100644
static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos,
-@@ -2545,8 +2649,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
+@@ -2545,8 +2656,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
*i = val;
} else {
val = convdiv * (*i) / convmul;
@@ -78960,7 +79236,7 @@ index ea7ec7f..b1c7c88 100644
err = proc_put_long(&buffer, &left, val, false);
if (err)
break;
-@@ -2941,6 +3048,12 @@ int proc_dostring(struct ctl_table *table, int write,
+@@ -2941,6 +3055,12 @@ int proc_dostring(struct ctl_table *table, int write,
return -ENOSYS;
}
@@ -78973,7 +79249,7 @@ index ea7ec7f..b1c7c88 100644
int proc_dointvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
-@@ -2997,6 +3110,7 @@ EXPORT_SYMBOL(proc_dointvec_minmax);
+@@ -2997,6 +3117,7 @@ EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring);
@@ -87943,6 +88219,24 @@ index 5485077..7e37374 100644
hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table);
if (hdr == NULL)
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index fe381c2..ec8b4b7e 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -3037,8 +3037,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
+
+ for (i = 0; i < shi->nr_frags; ++i) {
+ const struct skb_frag_struct *f = &shi->frags[i];
+- struct page *page = skb_frag_page(f);
+- sg_set_page(&sg, page, skb_frag_size(f), f->page_offset);
++ unsigned int offset = f->page_offset;
++ struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
++
++ sg_set_page(&sg, page, skb_frag_size(f),
++ offset_in_page(offset));
+ if (crypto_hash_update(desc, &sg, skb_frag_size(f)))
+ return 1;
+ }
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 872b41d..54a02f1 100644
--- a/net/ipv4/tcp_input.c
@@ -88392,6 +88686,19 @@ index 1567fb1..29af910 100644
__sk_dst_reset(sk);
dst = NULL;
}
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 3ccd9b2..6aadaa8 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1233,7 +1233,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ if (WARN_ON(np->cork.opt))
+ return -EINVAL;
+
+- np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
++ np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
+ if (unlikely(np->cork.opt == NULL))
+ return -ENOBUFS;
+
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index b204df8..8f274f4 100644
--- a/net/ipv6/ipv6_sockglue.c
@@ -88926,6 +89233,19 @@ index e71e85b..29340a9 100644
/* Aborting, close connection! */
iriap_disconnect_request(self);
+diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
+index 8c00416..9ea0c93 100644
+--- a/net/irda/irlap_frame.c
++++ b/net/irda/irlap_frame.c
+@@ -544,7 +544,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ /*
+ * We now have some discovery info to deliver!
+ */
+- discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
++ discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC);
+ if (!discovery) {
+ IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ return;
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 32e3bb0..a4e5eb8 100644
--- a/net/irda/irttp.c
diff --git a/3.9.4/0000_README b/3.9.4/0000_README
index 1cbe9a3..517433d 100644
--- a/3.9.4/0000_README
+++ b/3.9.4/0000_README
@@ -2,7 +2,7 @@ README
-----------------------------------------------------------------------------
Individual Patch Descriptions:
-----------------------------------------------------------------------------
-Patch: 4420_grsecurity-2.9.1-3.9.4-201306011536.patch
+Patch: 4420_grsecurity-2.9.1-3.9.4-201306041949.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/3.9.4/4420_grsecurity-2.9.1-3.9.4-201306011536.patch b/3.9.4/4420_grsecurity-2.9.1-3.9.4-201306041949.patch
index 9a1a55c..55d122a 100644
--- a/3.9.4/4420_grsecurity-2.9.1-3.9.4-201306011536.patch
+++ b/3.9.4/4420_grsecurity-2.9.1-3.9.4-201306041949.patch
@@ -5763,6 +5763,19 @@ index e0a8235..ce2f1e1 100644
ret = __copy_from_user(to, from, n);
else
copy_from_user_overflow();
+diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
+index 5709c5e..14285ca 100644
+--- a/arch/parisc/kernel/drivers.c
++++ b/arch/parisc/kernel/drivers.c
+@@ -394,7 +394,7 @@ EXPORT_SYMBOL(print_pci_hwpath);
+ static void setup_bus_id(struct parisc_device *padev)
+ {
+ struct hardware_path path;
+- char name[20];
++ char name[28];
+ char *output = name;
+ int i;
+
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 2a625fb..9908930 100644
--- a/arch/parisc/kernel/module.c
@@ -5866,6 +5879,20 @@ index 2a625fb..9908930 100644
DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
me->arch.unwind_section, table, end, gp);
+diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
+index a3328c2..3b812eb 100644
+--- a/arch/parisc/kernel/setup.c
++++ b/arch/parisc/kernel/setup.c
+@@ -69,7 +69,8 @@ void __init setup_cmdline(char **cmdline_p)
+ /* called from hpux boot loader */
+ boot_command_line[0] = '\0';
+ } else {
+- strcpy(boot_command_line, (char *)__va(boot_args[1]));
++ strlcpy(boot_command_line, (char *)__va(boot_args[1]),
++ COMMAND_LINE_SIZE);
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 5dfd248..64914ac 100644
--- a/arch/parisc/kernel/sys_parisc.c
@@ -31951,7 +31978,7 @@ index f9b983a..887b9d8 100644
return 0;
}
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
-index 77a7480..05cde58 100644
+index 77a7480d..05cde58 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -454,7 +454,7 @@ static void tx_complete (amb_dev * dev, tx_out * tx) {
@@ -37505,6 +37532,37 @@ index 89562a8..218999b 100644
capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
capimsg_setu16(skb->data, 16, len); /* Data length */
+diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
+index 9b1b274..c123709 100644
+--- a/drivers/isdn/capi/kcapi.c
++++ b/drivers/isdn/capi/kcapi.c
+@@ -93,7 +93,7 @@ capi_ctr_put(struct capi_ctr *ctr)
+
+ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
+ {
+- if (contr - 1 >= CAPI_MAXCONTR)
++ if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
+ return NULL;
+
+ return capi_controller[contr - 1];
+@@ -103,7 +103,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+ {
+ lockdep_assert_held(&capi_controller_lock);
+
+- if (applid - 1 >= CAPI_MAXAPPL)
++ if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return capi_applications[applid - 1];
+@@ -111,7 +111,7 @@ static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
+
+ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
+ {
+- if (applid - 1 >= CAPI_MAXAPPL)
++ if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
+ return NULL;
+
+ return rcu_dereference(capi_applications[applid - 1]);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index e2b5396..c5486dc 100644
--- a/drivers/isdn/gigaset/interface.c
@@ -53758,6 +53816,19 @@ index 1f94167..79c4ce4 100644
}
void nfs_fattr_init(struct nfs_fattr *fattr)
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 0086401..261e9b9 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1022,7 +1022,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+ struct nfs4_state *state = opendata->state;
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_delegation *delegation;
+- int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC);
++ int open_mode = opendata->o_arg.open_flags;
+ fmode_t fmode = opendata->o_arg.fmode;
+ nfs4_stateid stateid;
+ int ret = -EAGAIN;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index d401d01..10b3e62 100644
--- a/fs/nfsd/nfs4proc.c
@@ -55856,6 +55927,19 @@ index fee38e0..12fdf47 100644
if (__put_user(d_off, &lastdirent->d_off))
error = -EFAULT;
else
+diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
+index 66c53b6..6c2d136 100644
+--- a/fs/reiserfs/dir.c
++++ b/fs/reiserfs/dir.c
+@@ -204,6 +204,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
+ next_pos = deh_offset(deh) + 1;
+
+ if (item_moved(&tmp_ih, &path_to_entry)) {
++ set_cpu_key_k_offset(&pos_key,
++ next_pos);
+ goto research;
+ }
+ } /* for */
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 2b7882b..1c5ef48 100644
--- a/fs/reiserfs/do_balan.c
@@ -55869,6 +55953,29 @@ index 2b7882b..1c5ef48 100644
do_balance_starts(tb);
/* balance leaf returns 0 except if combining L R and S into
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index ea5061f..c3a9de6 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -1810,11 +1810,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
+ TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
+ memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
+ args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
+- if (insert_inode_locked4(inode, args.objectid,
+- reiserfs_find_actor, &args) < 0) {
++
++ reiserfs_write_unlock(inode->i_sb);
++ err = insert_inode_locked4(inode, args.objectid,
++ reiserfs_find_actor, &args);
++ reiserfs_write_lock(inode->i_sb);
++ if (err) {
+ err = -EINVAL;
+ goto out_bad_inode;
+ }
++
+ if (old_format_only(sb))
+ /* not a perfect generation count, as object ids can be reused, but
+ ** this is as good as reiserfs can do right now.
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 9cc0740a..46bf953 100644
--- a/fs/reiserfs/procfs.c
@@ -55904,6 +56011,45 @@ index 157e474..65a6114 100644
#define FILESYSTEM_CHANGED_TB(tb) (get_generation((tb)->tb_sb) != (tb)->fs_gen)
#define __fs_changed(gen,s) (gen != get_generation (s))
#define fs_changed(gen,s) \
+diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
+index 4cce1d9..821bcf7 100644
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -318,7 +318,19 @@ static int delete_one_xattr(struct dentry *dentry, void *data)
+ static int chown_one_xattr(struct dentry *dentry, void *data)
+ {
+ struct iattr *attrs = data;
+- return reiserfs_setattr(dentry, attrs);
++ int ia_valid = attrs->ia_valid;
++ int err;
++
++ /*
++ * We only want the ownership bits. Otherwise, we'll do
++ * things like change a directory to a regular file if
++ * ATTR_MODE is set.
++ */
++ attrs->ia_valid &= (ATTR_UID|ATTR_GID);
++ err = reiserfs_setattr(dentry, attrs);
++ attrs->ia_valid = ia_valid;
++
++ return err;
+ }
+
+ /* No i_mutex, but the inode is unconnected. */
+diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
+index d7c01ef..6c8767f 100644
+--- a/fs/reiserfs/xattr_acl.c
++++ b/fs/reiserfs/xattr_acl.c
+@@ -443,6 +443,9 @@ int reiserfs_acl_chmod(struct inode *inode)
+ int depth;
+ int error;
+
++ if (IS_PRIVATE(inode))
++ return 0;
++
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+
diff --git a/fs/select.c b/fs/select.c
index 8c1c96c..a0f9b6d 100644
--- a/fs/select.c
@@ -56526,7 +56672,7 @@ index d681e34..2a3f5ab 100644
goto out_put;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
-index d82efaa..0904a8e 100644
+index d82efaa..60100c7 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -395,7 +395,7 @@ xfs_vn_put_link(
@@ -56538,12 +56684,87 @@ index d82efaa..0904a8e 100644
if (!IS_ERR(s))
kfree(s);
+@@ -455,6 +455,28 @@ xfs_vn_getattr(
+ return 0;
+ }
+
++static void
++xfs_setattr_mode(
++ struct xfs_trans *tp,
++ struct xfs_inode *ip,
++ struct iattr *iattr)
++{
++ struct inode *inode = VFS_I(ip);
++ umode_t mode = iattr->ia_mode;
++
++ ASSERT(tp);
++ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
++
++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
++ mode &= ~S_ISGID;
++
++ ip->i_d.di_mode &= S_IFMT;
++ ip->i_d.di_mode |= mode & ~S_IFMT;
++
++ inode->i_mode &= S_IFMT;
++ inode->i_mode |= mode & ~S_IFMT;
++}
++
+ int
+ xfs_setattr_nonsize(
+ struct xfs_inode *ip,
+@@ -606,18 +628,8 @@ xfs_setattr_nonsize(
+ /*
+ * Change file access modes.
+ */
+- if (mask & ATTR_MODE) {
+- umode_t mode = iattr->ia_mode;
+-
+- if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+- mode &= ~S_ISGID;
+-
+- ip->i_d.di_mode &= S_IFMT;
+- ip->i_d.di_mode |= mode & ~S_IFMT;
+-
+- inode->i_mode &= S_IFMT;
+- inode->i_mode |= mode & ~S_IFMT;
+- }
++ if (mask & ATTR_MODE)
++ xfs_setattr_mode(tp, ip, iattr);
+
+ /*
+ * Change file access or modified times.
+@@ -714,9 +726,8 @@ xfs_setattr_size(
+ return XFS_ERROR(error);
+
+ ASSERT(S_ISREG(ip->i_d.di_mode));
+- ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+- ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID|
+- ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
++ ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
++ ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+
+ if (!(flags & XFS_ATTR_NOLOCK)) {
+ lock_flags |= XFS_IOLOCK_EXCL;
+@@ -860,6 +871,12 @@ xfs_setattr_size(
+ xfs_inode_clear_eofblocks_tag(ip);
+ }
+
++ /*
++ * Change file access modes.
++ */
++ if (mask & ATTR_MODE)
++ xfs_setattr_mode(tp, ip, iattr);
++
+ if (mask & ATTR_CTIME) {
+ inode->i_ctime = iattr->ia_ctime;
+ ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig
new file mode 100644
-index 0000000..7174794
+index 0000000..ba9c5e3
--- /dev/null
+++ b/grsecurity/Kconfig
-@@ -0,0 +1,1031 @@
+@@ -0,0 +1,1053 @@
+#
+# grecurity configuration
+#
@@ -56629,6 +56850,25 @@ index 0000000..7174794
+ If you're using KERNEXEC, it's recommended that you enable this option
+ to supplement the hardening of the kernel.
+
++config GRKERNSEC_PERF_HARDEN
++ bool "Disable unprivileged PERF_EVENTS usage by default"
++ default y if GRKERNSEC_CONFIG_AUTO
++ depends on PERF_EVENTS
++ help
++ If you say Y here, the range of acceptable values for the
++ /proc/sys/kernel/perf_event_paranoid sysctl will be expanded to allow and
++ default to a new value: 3. When the sysctl is set to this value, no
++ unprivileged use of the PERF_EVENTS syscall interface will be permitted.
++
++ Though PERF_EVENTS can be used legitimately for performance monitoring
++ and low-level application profiling, it is forced on regardless of
++ configuration, has been at fault for several vulnerabilities, and
++ creates new opportunities for side channels and other information leaks.
++
++ This feature puts PERF_EVENTS into a secure default state and permits
++ the administrator to change out of it temporarily if unprivileged
++ application profiling is needed.
++
+config GRKERNSEC_RAND_THREADSTACK
+ bool "Insert random gaps between thread stacks"
+ default y if GRKERNSEC_CONFIG_AUTO
@@ -56739,6 +56979,9 @@ index 0000000..7174794
+ useful protection against local kernel exploitation of overflows
+ and arbitrary read/write vulnerabilities.
+
++ It is highly recommended that you enable GRKERNSEC_PERF_HARDEN
++ in addition to this feature.
++
+config GRKERNSEC_KERN_LOCKOUT
+ bool "Active kernel exploit response"
+ default y if GRKERNSEC_CONFIG_AUTO
@@ -70441,7 +70684,7 @@ index 45fc162..01a4068 100644
/**
* struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
-index 1d795df..727aa7b 100644
+index 1d795df..b0a6449 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -333,8 +333,8 @@ struct perf_event {
@@ -70475,8 +70718,15 @@ index 1d795df..727aa7b 100644
extern int sysctl_perf_event_mlock;
extern int sysctl_perf_event_sample_rate;
-@@ -714,17 +714,17 @@ extern int perf_proc_update_handler(struct ctl_table *table, int write,
+@@ -712,19 +712,24 @@ extern int perf_proc_update_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos);
++static inline bool perf_paranoid_any(void)
++{
++ return sysctl_perf_event_legitimately_concerned > 2;
++}
++
static inline bool perf_paranoid_tracepoint_raw(void)
{
- return sysctl_perf_event_paranoid > -1;
@@ -70496,7 +70746,7 @@ index 1d795df..727aa7b 100644
}
extern void perf_event_init(void);
-@@ -812,7 +812,7 @@ static inline void perf_restore_debug_store(void) { }
+@@ -812,7 +817,7 @@ static inline void perf_restore_debug_store(void) { }
*/
#define perf_cpu_notifier(fn) \
do { \
@@ -70505,7 +70755,7 @@ index 1d795df..727aa7b 100644
{ .notifier_call = fn, .priority = CPU_PRI_PERF }; \
unsigned long cpu = smp_processor_id(); \
unsigned long flags; \
-@@ -831,7 +831,7 @@ do { \
+@@ -831,7 +836,7 @@ do { \
struct perf_pmu_events_attr {
struct device_attribute attr;
u64 id;
@@ -74632,15 +74882,19 @@ index 00eb8f7..d7e3244 100644
#ifdef CONFIG_MODULE_UNLOAD
{
diff --git a/kernel/events/core.c b/kernel/events/core.c
-index 9fcb094..fd68c54 100644
+index 9fcb094..8370228 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
-@@ -155,7 +155,11 @@ static struct srcu_struct pmus_srcu;
+@@ -154,8 +154,15 @@ static struct srcu_struct pmus_srcu;
+ * 0 - disallow raw tracepoint access for unpriv
* 1 - disallow cpu events for unpriv
* 2 - disallow kernel profiling for unpriv
++ * 3 - disallow all unpriv perf event use
*/
-int sysctl_perf_event_paranoid __read_mostly = 1;
-+#ifdef CONFIG_GRKERNSEC_HIDESYM
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++int sysctl_perf_event_legitimately_concerned __read_mostly = 3;
++#elif CONFIG_GRKERNSEC_HIDESYM
+int sysctl_perf_event_legitimately_concerned __read_mostly = 2;
+#else
+int sysctl_perf_event_legitimately_concerned __read_mostly = 1;
@@ -74648,7 +74902,7 @@ index 9fcb094..fd68c54 100644
/* Minimum for 512 kiB + 1 user control page */
int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
-@@ -182,7 +186,7 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
+@@ -182,7 +189,7 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
return 0;
}
@@ -74657,7 +74911,7 @@ index 9fcb094..fd68c54 100644
static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
enum event_type_t event_type);
-@@ -2677,7 +2681,7 @@ static void __perf_event_read(void *info)
+@@ -2677,7 +2684,7 @@ static void __perf_event_read(void *info)
static inline u64 perf_event_count(struct perf_event *event)
{
@@ -74666,7 +74920,7 @@ index 9fcb094..fd68c54 100644
}
static u64 perf_event_read(struct perf_event *event)
-@@ -3007,9 +3011,9 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
+@@ -3007,9 +3014,9 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
mutex_lock(&event->child_mutex);
total += perf_event_read(event);
*enabled += event->total_time_enabled +
@@ -74678,7 +74932,7 @@ index 9fcb094..fd68c54 100644
list_for_each_entry(child, &event->child_list, child_list) {
total += perf_event_read(child);
-@@ -3412,10 +3416,10 @@ void perf_event_update_userpage(struct perf_event *event)
+@@ -3412,10 +3419,10 @@ void perf_event_update_userpage(struct perf_event *event)
userpg->offset -= local64_read(&event->hw.prev_count);
userpg->time_enabled = enabled +
@@ -74691,7 +74945,7 @@ index 9fcb094..fd68c54 100644
arch_perf_update_userpage(userpg, now);
-@@ -3886,7 +3890,7 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
+@@ -3886,7 +3893,7 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
/* Data. */
sp = perf_user_stack_pointer(regs);
@@ -74700,7 +74954,7 @@ index 9fcb094..fd68c54 100644
dyn_size = dump_size - rem;
perf_output_skip(handle, rem);
-@@ -3974,11 +3978,11 @@ static void perf_output_read_one(struct perf_output_handle *handle,
+@@ -3974,11 +3981,11 @@ static void perf_output_read_one(struct perf_output_handle *handle,
values[n++] = perf_event_count(event);
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
values[n++] = enabled +
@@ -74714,7 +74968,7 @@ index 9fcb094..fd68c54 100644
}
if (read_format & PERF_FORMAT_ID)
values[n++] = primary_event_id(event);
-@@ -4726,12 +4730,12 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
+@@ -4726,12 +4733,12 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
* need to add enough zero bytes after the string to handle
* the 64bit alignment we do later.
*/
@@ -74729,7 +74983,7 @@ index 9fcb094..fd68c54 100644
if (IS_ERR(name)) {
name = strncpy(tmp, "//toolong", sizeof(tmp));
goto got_name;
-@@ -6167,7 +6171,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
+@@ -6167,7 +6174,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
event->parent = parent_event;
event->ns = get_pid_ns(task_active_pid_ns(current));
@@ -74738,7 +74992,19 @@ index 9fcb094..fd68c54 100644
event->state = PERF_EVENT_STATE_INACTIVE;
-@@ -6795,10 +6799,10 @@ static void sync_child_event(struct perf_event *child_event,
+@@ -6463,6 +6470,11 @@ SYSCALL_DEFINE5(perf_event_open,
+ if (flags & ~PERF_FLAG_ALL)
+ return -EINVAL;
+
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN))
++ return -EACCES;
++#endif
++
+ err = perf_copy_attr(attr_uptr, &attr);
+ if (err)
+ return err;
+@@ -6795,10 +6807,10 @@ static void sync_child_event(struct perf_event *child_event,
/*
* Add back the child's count to the parent's count:
*/
@@ -78585,7 +78851,7 @@ index 0da73cf..5c2af3c 100644
if (!retval) {
if (old_rlim)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index afc1dc6..5e28bbf 100644
+index afc1dc6..fb0671d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -93,7 +93,6 @@
@@ -78691,7 +78957,7 @@ index afc1dc6..5e28bbf 100644
{
.procname = "ngroups_max",
.data = &ngroups_max,
-@@ -1026,8 +1059,8 @@ static struct ctl_table kern_table[] = {
+@@ -1026,10 +1059,17 @@ static struct ctl_table kern_table[] = {
*/
{
.procname = "perf_event_paranoid",
@@ -78700,9 +78966,19 @@ index afc1dc6..5e28bbf 100644
+ .data = &sysctl_perf_event_legitimately_concerned,
+ .maxlen = sizeof(sysctl_perf_event_legitimately_concerned),
.mode = 0644,
- .proc_handler = proc_dointvec,
+- .proc_handler = proc_dointvec,
++ /* go ahead, be a hero */
++ .proc_handler = proc_dointvec_minmax_sysadmin,
++ .extra1 = &zero,
++#ifdef CONFIG_GRKERNSEC_PERF_HARDEN
++ .extra2 = &three,
++#else
++ .extra2 = &two,
++#endif
},
-@@ -1283,6 +1316,13 @@ static struct ctl_table vm_table[] = {
+ {
+ .procname = "perf_event_mlock_kb",
+@@ -1283,6 +1323,13 @@ static struct ctl_table vm_table[] = {
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
},
@@ -78716,7 +78992,7 @@ index afc1dc6..5e28bbf 100644
#else
{
.procname = "nr_trim_pages",
-@@ -1733,6 +1773,16 @@ int proc_dostring(struct ctl_table *table, int write,
+@@ -1733,6 +1780,16 @@ int proc_dostring(struct ctl_table *table, int write,
buffer, lenp, ppos);
}
@@ -78733,7 +79009,7 @@ index afc1dc6..5e28bbf 100644
static size_t proc_skip_spaces(char **buf)
{
size_t ret;
-@@ -1838,6 +1888,8 @@ static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
+@@ -1838,6 +1895,8 @@ static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
len = strlen(tmp);
if (len > *size)
len = *size;
@@ -78742,7 +79018,7 @@ index afc1dc6..5e28bbf 100644
if (copy_to_user(*buf, tmp, len))
return -EFAULT;
*size -= len;
-@@ -2002,7 +2054,7 @@ int proc_dointvec(struct ctl_table *table, int write,
+@@ -2002,7 +2061,7 @@ int proc_dointvec(struct ctl_table *table, int write,
static int proc_taint(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
@@ -78751,7 +79027,7 @@ index afc1dc6..5e28bbf 100644
unsigned long tmptaint = get_taint();
int err;
-@@ -2030,7 +2082,6 @@ static int proc_taint(struct ctl_table *table, int write,
+@@ -2030,7 +2089,6 @@ static int proc_taint(struct ctl_table *table, int write,
return err;
}
@@ -78759,7 +79035,7 @@ index afc1dc6..5e28bbf 100644
static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
-@@ -2039,7 +2090,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
+@@ -2039,7 +2097,6 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
}
@@ -78767,7 +79043,7 @@ index afc1dc6..5e28bbf 100644
struct do_proc_dointvec_minmax_conv_param {
int *min;
-@@ -2186,8 +2236,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
+@@ -2186,8 +2243,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
*i = val;
} else {
val = convdiv * (*i) / convmul;
@@ -78780,7 +79056,7 @@ index afc1dc6..5e28bbf 100644
err = proc_put_long(&buffer, &left, val, false);
if (err)
break;
-@@ -2579,6 +2632,12 @@ int proc_dostring(struct ctl_table *table, int write,
+@@ -2579,6 +2639,12 @@ int proc_dostring(struct ctl_table *table, int write,
return -ENOSYS;
}
@@ -78793,7 +79069,7 @@ index afc1dc6..5e28bbf 100644
int proc_dointvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
-@@ -2635,5 +2694,6 @@ EXPORT_SYMBOL(proc_dointvec_minmax);
+@@ -2635,5 +2701,6 @@ EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring);
@@ -87120,6 +87396,24 @@ index 960fd29..d55bf64 100644
hdr = register_net_sysctl(&init_net, "net/ipv4", ipv4_table);
if (hdr == NULL)
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index e220207..cdeb839 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -3383,8 +3383,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
+
+ for (i = 0; i < shi->nr_frags; ++i) {
+ const struct skb_frag_struct *f = &shi->frags[i];
+- struct page *page = skb_frag_page(f);
+- sg_set_page(&sg, page, skb_frag_size(f), f->page_offset);
++ unsigned int offset = f->page_offset;
++ struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
++
++ sg_set_page(&sg, page, skb_frag_size(f),
++ offset_in_page(offset));
+ if (crypto_hash_update(desc, &sg, skb_frag_size(f)))
+ return 1;
+ }
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 13b9c08..d33a8d0 100644
--- a/net/ipv4/tcp_input.c
@@ -87527,6 +87821,19 @@ index 95d13c7..791fe2f 100644
.kind = "ip6gretap",
.maxtype = IFLA_GRE_MAX,
.policy = ip6gre_policy,
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 155eccf..851fdae 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1147,7 +1147,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ if (WARN_ON(np->cork.opt))
+ return -EINVAL;
+
+- np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation);
++ np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
+ if (unlikely(np->cork.opt == NULL))
+ return -ENOBUFS;
+
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index fff83cb..82d49dd 100644
--- a/net/ipv6/ip6_tunnel.c
@@ -88061,6 +88368,19 @@ index 362ba47..66196f4 100644
seq_printf(m, "Max data size: %d\n", self->max_data_size);
seq_printf(m, "Max header size: %d\n", self->max_header_size);
+diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
+index 8c00416..9ea0c93 100644
+--- a/net/irda/irlap_frame.c
++++ b/net/irda/irlap_frame.c
+@@ -544,7 +544,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ /*
+ * We now have some discovery info to deliver!
+ */
+- discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
++ discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC);
+ if (!discovery) {
+ IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ return;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 206ce6d..cfb27cd 100644
--- a/net/iucv/af_iucv.c
@@ -90413,6 +90733,18 @@ index c8717c1..08539f5 100644
err = handler(dev, info, (union iwreq_data *) iwp, extra);
iwp->length += essid_compat;
+diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
+index bcfda89..0cf003d 100644
+--- a/net/xfrm/xfrm_output.c
++++ b/net/xfrm/xfrm_output.c
+@@ -64,6 +64,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
+
+ if (unlikely(x->km.state != XFRM_STATE_VALID)) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID);
++ err = -EINVAL;
+ goto error;
+ }
+
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 167c67d..3f2ae427 100644
--- a/net/xfrm/xfrm_policy.c