--- /dev/null
+From 2976b10f05bd7f6dab9f9e7524451ddfed656a89 Mon Sep 17 00:00:00 2001
+From: Stephane Eranian <eranian@google.com>
+Date: Thu, 20 Jun 2013 11:36:28 +0200
+Subject: perf: Disable monitoring on setuid processes for regular users
+
+From: Stephane Eranian <eranian@google.com>
+
+commit 2976b10f05bd7f6dab9f9e7524451ddfed656a89 upstream.
+
+There was a a bug in setup_new_exec(), whereby
+the test to disabled perf monitoring was not
+correct because the new credentials for the
+process were not yet committed and therefore
+the get_dumpable() test was never firing.
+
+The patch fixes the problem by moving the
+perf_event test until after the credentials
+are committed.
+
+Signed-off-by: Stephane Eranian <eranian@google.com>
+Tested-by: Jiri Olsa <jolsa@redhat.com>
+Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/exec.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1163,13 +1163,6 @@ void setup_new_exec(struct linux_binprm
+ set_dumpable(current->mm, suid_dumpable);
+ }
+
+- /*
+- * Flush performance counters when crossing a
+- * security domain:
+- */
+- if (!get_dumpable(current->mm))
+- perf_event_exit_task(current);
+-
+ /* An exec changes our domain. We are no longer part of the thread
+ group */
+
+@@ -1233,6 +1226,15 @@ void install_exec_creds(struct linux_bin
+
+ commit_creds(bprm->cred);
+ bprm->cred = NULL;
++
++ /*
++ * Disable monitoring for regular users
++ * when executing setuid binaries. Must
++ * wait until new credentials are committed
++ * by commit_creds() above
++ */
++ if (get_dumpable(current->mm) != SUID_DUMP_USER)
++ perf_event_exit_task(current);
+ /*
+ * cred_guard_mutex must be held at least to this point to prevent
+ * ptrace_attach() from altering our determination of the task's
dlci-acquire-rtnl_lock-before-calling-__dev_get_by_name.patch
dlci-validate-the-net-device-in-dlci_del.patch
net-tg3-avoid-delay-during-mmio-access.patch
+perf-disable-monitoring-on-setuid-processes-for-regular-users.patch
+ubifs-prepare-to-fix-a-horrid-bug.patch
+ubifs-fix-a-horrid-bug.patch
--- /dev/null
+From 605c912bb843c024b1ed173dc427cd5c08e5d54d Mon Sep 17 00:00:00 2001
+From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Date: Fri, 28 Jun 2013 14:15:15 +0300
+Subject: UBIFS: fix a horrid bug
+
+From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+
+commit 605c912bb843c024b1ed173dc427cd5c08e5d54d upstream.
+
+Al Viro pointed me to the fact that '->readdir()' and '->llseek()' have no
+mutual exclusion, which means the 'ubifs_dir_llseek()' can be run while we are
+in the middle of 'ubifs_readdir()'.
+
+This means that 'file->private_data' can be freed while 'ubifs_readdir()' uses
+it, and this is a very bad bug: not only 'ubifs_readdir()' can return garbage,
+but this may corrupt memory and lead to all kinds of problems like crashes an
+security holes.
+
+This patch fixes the problem by using the 'file->f_version' field, which
+'->llseek()' always unconditionally sets to zero. We set it to 1 in
+'ubifs_readdir()' and whenever we detect that it became 0, we know there was a
+seek and it is time to clear the state saved in 'file->private_data'.
+
+I tested this patch by writing a user-space program which runds readdir and
+seek in parallell. I could easily crash the kernel without these patches, but
+could not crash it with these patches.
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Tested-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/dir.c | 30 +++++++++++++++++++++++++++---
+ 1 file changed, 27 insertions(+), 3 deletions(-)
+
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -373,6 +373,24 @@ static int ubifs_readdir(struct file *fi
+ */
+ return 0;
+
++ if (file->f_version == 0) {
++ /*
++ * The file was seek'ed, which means that @file->private_data
++ * is now invalid. This may also be just the first
++ * 'ubifs_readdir()' invocation, in which case
++ * @file->private_data is NULL, and the below code is
++ * basically a no-op.
++ */
++ kfree(file->private_data);
++ file->private_data = NULL;
++ }
++
++ /*
++ * 'generic_file_llseek()' unconditionally sets @file->f_version to
++ * zero, and we use this for detecting whether the file was seek'ed.
++ */
++ file->f_version = 1;
++
+ /* File positions 0 and 1 correspond to "." and ".." */
+ if (pos == 0) {
+ ubifs_assert(!file->private_data);
+@@ -446,6 +464,14 @@ static int ubifs_readdir(struct file *fi
+ file->f_pos = pos = key_hash_flash(c, &dent->key);
+ file->private_data = dent;
+ cond_resched();
++
++ if (file->f_version == 0)
++ /*
++ * The file was seek'ed meanwhile, lets return and start
++ * reading direntries from the new position on the next
++ * invocation.
++ */
++ return 0;
+ }
+
+ out:
+@@ -456,15 +482,13 @@ out:
+
+ kfree(file->private_data);
+ file->private_data = NULL;
++ /* 2 is a special value indicating that there are no more direntries */
+ file->f_pos = 2;
+ return 0;
+ }
+
+-/* If a directory is seeked, we have to free saved readdir() state */
+ static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin)
+ {
+- kfree(file->private_data);
+- file->private_data = NULL;
+ return generic_file_llseek(file, offset, origin);
+ }
+
--- /dev/null
+From 33f1a63ae84dfd9ad298cf275b8f1887043ced36 Mon Sep 17 00:00:00 2001
+From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Date: Fri, 28 Jun 2013 14:15:14 +0300
+Subject: UBIFS: prepare to fix a horrid bug
+
+From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+
+commit 33f1a63ae84dfd9ad298cf275b8f1887043ced36 upstream.
+
+Al Viro pointed me to the fact that '->readdir()' and '->llseek()' have no
+mutual exclusion, which means the 'ubifs_dir_llseek()' can be run while we are
+in the middle of 'ubifs_readdir()'.
+
+First of all, this means that 'file->private_data' can be freed while
+'ubifs_readdir()' uses it. But this particular patch does not fix the problem.
+This patch is only a preparation, and the fix will follow next.
+
+In this patch we make 'ubifs_readdir()' stop using 'file->f_pos' directly,
+because 'file->f_pos' can be changed by '->llseek()' at any point. This may
+lead 'ubifs_readdir()' to returning inconsistent data: directory entry names
+may correspond to incorrect file positions.
+
+So here we introduce a local variable 'pos', read 'file->f_pose' once at very
+the beginning, and then stick to 'pos'. The result of this is that when
+'ubifs_dir_llseek()' changes 'file->f_pos' while we are in the middle of
+'ubifs_readdir()', the latter "wins".
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Tested-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ubifs/dir.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -357,15 +357,16 @@ static unsigned int vfs_dent_type(uint8_
+ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir)
+ {
+ int err, over = 0;
++ loff_t pos = file->f_pos;
+ struct qstr nm;
+ union ubifs_key key;
+ struct ubifs_dent_node *dent;
+ struct inode *dir = file->f_path.dentry->d_inode;
+ struct ubifs_info *c = dir->i_sb->s_fs_info;
+
+- dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos);
++ dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos);
+
+- if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2)
++ if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2)
+ /*
+ * The directory was seek'ed to a senseless position or there
+ * are no more entries.
+@@ -373,15 +374,15 @@ static int ubifs_readdir(struct file *fi
+ return 0;
+
+ /* File positions 0 and 1 correspond to "." and ".." */
+- if (file->f_pos == 0) {
++ if (pos == 0) {
+ ubifs_assert(!file->private_data);
+ over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR);
+ if (over)
+ return 0;
+- file->f_pos = 1;
++ file->f_pos = pos = 1;
+ }
+
+- if (file->f_pos == 1) {
++ if (pos == 1) {
+ ubifs_assert(!file->private_data);
+ over = filldir(dirent, "..", 2, 1,
+ parent_ino(file->f_path.dentry), DT_DIR);
+@@ -397,7 +398,7 @@ static int ubifs_readdir(struct file *fi
+ goto out;
+ }
+
+- file->f_pos = key_hash_flash(c, &dent->key);
++ file->f_pos = pos = key_hash_flash(c, &dent->key);
+ file->private_data = dent;
+ }
+
+@@ -405,17 +406,16 @@ static int ubifs_readdir(struct file *fi
+ if (!dent) {
+ /*
+ * The directory was seek'ed to and is now readdir'ed.
+- * Find the entry corresponding to @file->f_pos or the
+- * closest one.
++ * Find the entry corresponding to @pos or the closest one.
+ */
+- dent_key_init_hash(c, &key, dir->i_ino, file->f_pos);
++ dent_key_init_hash(c, &key, dir->i_ino, pos);
+ nm.name = NULL;
+ dent = ubifs_tnc_next_ent(c, &key, &nm);
+ if (IS_ERR(dent)) {
+ err = PTR_ERR(dent);
+ goto out;
+ }
+- file->f_pos = key_hash_flash(c, &dent->key);
++ file->f_pos = pos = key_hash_flash(c, &dent->key);
+ file->private_data = dent;
+ }
+
+@@ -427,7 +427,7 @@ static int ubifs_readdir(struct file *fi
+ ubifs_inode(dir)->creat_sqnum);
+
+ nm.len = le16_to_cpu(dent->nlen);
+- over = filldir(dirent, dent->name, nm.len, file->f_pos,
++ over = filldir(dirent, dent->name, nm.len, pos,
+ le64_to_cpu(dent->inum),
+ vfs_dent_type(dent->type));
+ if (over)
+@@ -443,7 +443,7 @@ static int ubifs_readdir(struct file *fi
+ }
+
+ kfree(file->private_data);
+- file->f_pos = key_hash_flash(c, &dent->key);
++ file->f_pos = pos = key_hash_flash(c, &dent->key);
+ file->private_data = dent;
+ cond_resched();
+ }