--- /dev/null
+From b74cb9a80268be5c80cf4c87c74debf0ff2129ac Mon Sep 17 00:00:00 2001
+From: Sachin Prabhu <sprabhu@redhat.com>
+Date: Tue, 17 May 2016 18:20:13 -0500
+Subject: cifs: Create dedicated keyring for spnego operations
+
+From: Sachin Prabhu <sprabhu@redhat.com>
+
+commit b74cb9a80268be5c80cf4c87c74debf0ff2129ac upstream.
+
+The session key is the default keyring set for request_key operations.
+This session key is revoked when the user owning the session logs out.
+Any long running daemon processes started by this session ends up with
+revoked session keyring which prevents these processes from using the
+request_key mechanism from obtaining the krb5 keys.
+
+The problem has been reported by a large number of autofs users. The
+problem is also seen with multiuser mounts where the share may be used
+by processes run by a user who has since logged out. A reproducer using
+automount is available on the Red Hat bz.
+
+The patch creates a new keyring which is used to cache cifs spnego
+upcalls.
+
+Red Hat bz: 1267754
+
+Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
+Reported-by: Scott Mayhew <smayhew@redhat.com>
+Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifs_spnego.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/cifs/cifsfs.c | 4 +-
+ fs/cifs/cifsproto.h | 2 +
+ 3 files changed, 71 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/cifs_spnego.c
++++ b/fs/cifs/cifs_spnego.c
+@@ -24,10 +24,13 @@
+ #include <linux/string.h>
+ #include <keys/user-type.h>
+ #include <linux/key-type.h>
++#include <linux/keyctl.h>
+ #include <linux/inet.h>
+ #include "cifsglob.h"
+ #include "cifs_spnego.h"
+ #include "cifs_debug.h"
++#include "cifsproto.h"
++static const struct cred *spnego_cred;
+
+ /* create a new cifs key */
+ static int
+@@ -103,6 +106,7 @@ cifs_get_spnego_key(struct cifs_ses *ses
+ size_t desc_len;
+ struct key *spnego_key;
+ const char *hostname = server->hostname;
++ const struct cred *saved_cred;
+
+ /* length of fields (with semicolons): ver=0xyz ip4=ipaddress
+ host=hostname sec=mechanism uid=0xFF user=username */
+@@ -164,7 +168,9 @@ cifs_get_spnego_key(struct cifs_ses *ses
+ sprintf(dp, ";pid=0x%x", current->pid);
+
+ cifs_dbg(FYI, "key description = %s\n", description);
++ saved_cred = override_creds(spnego_cred);
+ spnego_key = request_key(&cifs_spnego_key_type, description, "");
++ revert_creds(saved_cred);
+
+ #ifdef CONFIG_CIFS_DEBUG2
+ if (cifsFYI && !IS_ERR(spnego_key)) {
+@@ -178,3 +184,64 @@ out:
+ kfree(description);
+ return spnego_key;
+ }
++
++int
++init_cifs_spnego(void)
++{
++ struct cred *cred;
++ struct key *keyring;
++ int ret;
++
++ cifs_dbg(FYI, "Registering the %s key type\n",
++ cifs_spnego_key_type.name);
++
++ /*
++ * Create an override credential set with special thread keyring for
++ * spnego upcalls.
++ */
++
++ cred = prepare_kernel_cred(NULL);
++ if (!cred)
++ return -ENOMEM;
++
++ keyring = keyring_alloc(".cifs_spnego",
++ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
++ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
++ KEY_USR_VIEW | KEY_USR_READ,
++ KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
++ if (IS_ERR(keyring)) {
++ ret = PTR_ERR(keyring);
++ goto failed_put_cred;
++ }
++
++ ret = register_key_type(&cifs_spnego_key_type);
++ if (ret < 0)
++ goto failed_put_key;
++
++ /*
++ * instruct request_key() to use this special keyring as a cache for
++ * the results it looks up
++ */
++ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
++ cred->thread_keyring = keyring;
++ cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
++ spnego_cred = cred;
++
++ cifs_dbg(FYI, "cifs spnego keyring: %d\n", key_serial(keyring));
++ return 0;
++
++failed_put_key:
++ key_put(keyring);
++failed_put_cred:
++ put_cred(cred);
++ return ret;
++}
++
++void
++exit_cifs_spnego(void)
++{
++ key_revoke(spnego_cred->thread_keyring);
++ unregister_key_type(&cifs_spnego_key_type);
++ put_cred(spnego_cred);
++ cifs_dbg(FYI, "Unregistered %s key type\n", cifs_spnego_key_type.name);
++}
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -1228,7 +1228,7 @@ init_cifs(void)
+ goto out_destroy_mids;
+
+ #ifdef CONFIG_CIFS_UPCALL
+- rc = register_key_type(&cifs_spnego_key_type);
++ rc = init_cifs_spnego();
+ if (rc)
+ goto out_destroy_request_bufs;
+ #endif /* CONFIG_CIFS_UPCALL */
+@@ -1251,7 +1251,7 @@ out_init_cifs_idmap:
+ out_register_key_type:
+ #endif
+ #ifdef CONFIG_CIFS_UPCALL
+- unregister_key_type(&cifs_spnego_key_type);
++ exit_cifs_spnego();
+ out_destroy_request_bufs:
+ #endif
+ cifs_destroy_request_bufs();
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -59,6 +59,8 @@ do { \
+ } while (0)
+ extern int init_cifs_idmap(void);
+ extern void exit_cifs_idmap(void);
++extern int init_cifs_spnego(void);
++extern void exit_cifs_spnego(void);
+ extern char *build_path_from_dentry(struct dentry *);
+ extern char *cifs_build_path_to_root(struct smb_vol *vol,
+ struct cifs_sb_info *cifs_sb,
--- /dev/null
+From e930c765ca5c6b039cd22ebfb4504ea7b5dab43d Mon Sep 17 00:00:00 2001
+From: Catalin Vasile <cata.vasile@nxp.com>
+Date: Fri, 6 May 2016 16:18:53 +0300
+Subject: crypto: caam - fix caam_jr_alloc() ret code
+
+From: Catalin Vasile <cata.vasile@nxp.com>
+
+commit e930c765ca5c6b039cd22ebfb4504ea7b5dab43d upstream.
+
+caam_jr_alloc() used to return NULL if a JR device could not be
+allocated for a session. In turn, every user of this function used
+IS_ERR() function to verify if anything went wrong, which does NOT look
+for NULL values. This made the kernel crash if the sanity check failed,
+because the driver continued to think it had allocated a valid JR dev
+instance to the session and at some point it tries to do a caam_jr_free()
+on a NULL JR dev pointer.
+This patch is a fix for this issue.
+
+Signed-off-by: Catalin Vasile <cata.vasile@nxp.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/caam/jr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/caam/jr.c
++++ b/drivers/crypto/caam/jr.c
+@@ -244,7 +244,7 @@ static void caam_jr_dequeue(unsigned lon
+ struct device *caam_jr_alloc(void)
+ {
+ struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
+- struct device *dev = NULL;
++ struct device *dev = ERR_PTR(-ENODEV);
+ int min_tfm_cnt = INT_MAX;
+ int tfm_cnt;
+
--- /dev/null
+From bdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Wed, 23 Mar 2016 16:11:24 +0100
+Subject: crypto: sun4i-ss - Replace spinlock_bh by spin_lock_irq{save|restore}
+
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+
+commit bdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e upstream.
+
+The current sun4i-ss driver could generate data corruption when ciphering/deciphering.
+It occurs randomly on end of handled data.
+No root cause have been found and the only way to remove it is to replace
+all spin_lock_bh by their irq counterparts.
+
+Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
+Signed-off-by: LABBE Corentin <clabbe.montjoie@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+index 7be3fbcd8d78..3830d7c4e138 100644
+--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+@@ -35,6 +35,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
+ unsigned int todo;
+ struct sg_mapping_iter mi, mo;
+ unsigned int oi, oo; /* offset for in and out */
++ unsigned long flags;
+
+ if (areq->nbytes == 0)
+ return 0;
+@@ -49,7 +50,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
+ return -EINVAL;
+ }
+
+- spin_lock_bh(&ss->slock);
++ spin_lock_irqsave(&ss->slock, flags);
+
+ for (i = 0; i < op->keylen; i += 4)
+ writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+@@ -117,7 +118,7 @@ release_ss:
+ sg_miter_stop(&mi);
+ sg_miter_stop(&mo);
+ writel(0, ss->base + SS_CTL);
+- spin_unlock_bh(&ss->slock);
++ spin_unlock_irqrestore(&ss->slock, flags);
+ return err;
+ }
+
+@@ -149,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq)
+ unsigned int ob = 0; /* offset in buf */
+ unsigned int obo = 0; /* offset in bufo*/
+ unsigned int obl = 0; /* length of data in bufo */
++ unsigned long flags;
+
+ if (areq->nbytes == 0)
+ return 0;
+@@ -181,7 +183,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq)
+ if (no_chunk == 1)
+ return sun4i_ss_opti_poll(areq);
+
+- spin_lock_bh(&ss->slock);
++ spin_lock_irqsave(&ss->slock, flags);
+
+ for (i = 0; i < op->keylen; i += 4)
+ writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+@@ -307,7 +309,7 @@ release_ss:
+ sg_miter_stop(&mi);
+ sg_miter_stop(&mo);
+ writel(0, ss->base + SS_CTL);
+- spin_unlock_bh(&ss->slock);
++ spin_unlock_irqrestore(&ss->slock, flags);
+
+ return err;
+ }
--- /dev/null
+From cfda35d98298131bf38fbad3ce4cd5ecb3cf18db Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Tue, 3 May 2016 10:52:30 +0200
+Subject: fs/cifs: correctly to anonymous authentication via NTLMSSP
+
+From: Stefan Metzmacher <metze@samba.org>
+
+commit cfda35d98298131bf38fbad3ce4cd5ecb3cf18db upstream.
+
+See [MS-NLMP] 3.2.5.1.2 Server Receives an AUTHENTICATE_MESSAGE from the Client:
+
+ ...
+ Set NullSession to FALSE
+ If (AUTHENTICATE_MESSAGE.UserNameLen == 0 AND
+ AUTHENTICATE_MESSAGE.NtChallengeResponse.Length == 0 AND
+ (AUTHENTICATE_MESSAGE.LmChallengeResponse == Z(1)
+ OR
+ AUTHENTICATE_MESSAGE.LmChallengeResponse.Length == 0))
+ -- Special case: client requested anonymous authentication
+ Set NullSession to TRUE
+ ...
+
+Only server which map unknown users to guest will allow
+access using a non-null NTChallengeResponse.
+
+For Samba it's the "map to guest = bad user" option.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11913
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/sess.c | 32 ++++++++++++++++++++------------
+ 1 file changed, 20 insertions(+), 12 deletions(-)
+
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -399,19 +399,27 @@ int build_ntlmssp_auth_blob(unsigned cha
+ sec_blob->LmChallengeResponse.MaximumLength = 0;
+
+ sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
+- rc = setup_ntlmv2_rsp(ses, nls_cp);
+- if (rc) {
+- cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
+- goto setup_ntlmv2_ret;
+- }
+- memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+- tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
++ if (ses->user_name != NULL) {
++ rc = setup_ntlmv2_rsp(ses, nls_cp);
++ if (rc) {
++ cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
++ goto setup_ntlmv2_ret;
++ }
++ memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
++ ses->auth_key.len - CIFS_SESS_KEY_SIZE);
++ tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+
+- sec_blob->NtChallengeResponse.Length =
+- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+- sec_blob->NtChallengeResponse.MaximumLength =
+- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
++ sec_blob->NtChallengeResponse.Length =
++ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
++ sec_blob->NtChallengeResponse.MaximumLength =
++ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
++ } else {
++ /*
++ * don't send an NT Response for anonymous access
++ */
++ sec_blob->NtChallengeResponse.Length = 0;
++ sec_blob->NtChallengeResponse.MaximumLength = 0;
++ }
+
+ if (ses->domainName == NULL) {
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
--- /dev/null
+From 897fba1172d637d344f009d700f7eb8a1fa262f1 Mon Sep 17 00:00:00 2001
+From: Steve French <smfrench@gmail.com>
+Date: Thu, 12 May 2016 21:20:36 -0500
+Subject: remove directory incorrectly tries to set delete on close on non-empty directories
+
+From: Steve French <smfrench@gmail.com>
+
+commit 897fba1172d637d344f009d700f7eb8a1fa262f1 upstream.
+
+Wrong return code was being returned on SMB3 rmdir of
+non-empty directory.
+
+For SMB3 (unlike for cifs), we attempt to delete a directory by
+set of delete on close flag on the open. Windows clients set
+this flag via a set info (SET_FILE_DISPOSITION to set this flag)
+which properly checks if the directory is empty.
+
+With this patch on smb3 mounts we correctly return
+ "DIRECTORY NOT EMPTY"
+on attempts to remove a non-empty directory.
+
+Signed-off-by: Steve French <steve.french@primarydata.com>
+Acked-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2glob.h | 1 +
+ fs/cifs/smb2inode.c | 8 ++++++--
+ fs/cifs/smb2pdu.c | 16 ++++++++++++++++
+ fs/cifs/smb2proto.h | 2 ++
+ 4 files changed, 25 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/smb2glob.h
++++ b/fs/cifs/smb2glob.h
+@@ -44,6 +44,7 @@
+ #define SMB2_OP_DELETE 7
+ #define SMB2_OP_HARDLINK 8
+ #define SMB2_OP_SET_EOF 9
++#define SMB2_OP_RMDIR 10
+
+ /* Used when constructing chained read requests. */
+ #define CHAINED_REQUEST 1
+--- a/fs/cifs/smb2inode.c
++++ b/fs/cifs/smb2inode.c
+@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xi
+ * SMB2_open() call.
+ */
+ break;
++ case SMB2_OP_RMDIR:
++ tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
++ fid.volatile_fid);
++ break;
+ case SMB2_OP_RENAME:
+ tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
+ fid.volatile_fid, (__le16 *)data);
+@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struc
+ struct cifs_sb_info *cifs_sb)
+ {
+ return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
+- CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
+- NULL, SMB2_OP_DELETE);
++ CREATE_NOT_FILE,
++ NULL, SMB2_OP_RMDIR);
+ }
+
+ int
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -2291,6 +2291,22 @@ SMB2_rename(const unsigned int xid, stru
+ }
+
+ int
++SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
++ u64 persistent_fid, u64 volatile_fid)
++{
++ __u8 delete_pending = 1;
++ void *data;
++ unsigned int size;
++
++ data = &delete_pending;
++ size = 1; /* sizeof __u8 */
++
++ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
++ current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data,
++ &size);
++}
++
++int
+ SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
+ {
+--- a/fs/cifs/smb2proto.h
++++ b/fs/cifs/smb2proto.h
+@@ -134,6 +134,8 @@ extern int SMB2_query_directory(const un
+ extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ __le16 *target_file);
++extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
++ u64 persistent_fid, u64 volatile_fid);
+ extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid,
+ __le16 *target_file);
--- /dev/null
+From 59643d1535eb220668692a5359de22545af579f6 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+Date: Fri, 13 May 2016 09:34:12 -0400
+Subject: ring-buffer: Prevent overflow of size in ring_buffer_resize()
+
+From: Steven Rostedt (Red Hat) <rostedt@goodmis.org>
+
+commit 59643d1535eb220668692a5359de22545af579f6 upstream.
+
+If the size passed to ring_buffer_resize() is greater than MAX_LONG - BUF_PAGE_SIZE
+then the DIV_ROUND_UP() will return zero.
+
+Here's the details:
+
+ # echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb
+
+tracing_entries_write() processes this and converts kb to bytes.
+
+ 18014398509481980 << 10 = 18446744073709547520
+
+and this is passed to ring_buffer_resize() as unsigned long size.
+
+ size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+
+Where DIV_ROUND_UP(a, b) is (a + b - 1)/b
+
+BUF_PAGE_SIZE is 4080 and here
+
+ 18446744073709547520 + 4080 - 1 = 18446744073709551599
+
+where 18446744073709551599 is still smaller than 2^64
+
+ 2^64 - 18446744073709551599 = 17
+
+But now 18446744073709551599 / 4080 = 4521260802379792
+
+and size = size * 4080 = 18446744073709551360
+
+This is checked to make sure its still greater than 2 * 4080,
+which it is.
+
+Then we convert to the number of buffer pages needed.
+
+ nr_page = DIV_ROUND_UP(size, BUF_PAGE_SIZE)
+
+but this time size is 18446744073709551360 and
+
+ 2^64 - (18446744073709551360 + 4080 - 1) = -3823
+
+Thus it overflows and the resulting number is less than 4080, which makes
+
+ 3823 / 4080 = 0
+
+an nr_pages is set to this. As we already checked against the minimum that
+nr_pages may be, this causes the logic to fail as well, and we crash the
+kernel.
+
+There's no reason to have the two DIV_ROUND_UP() (that's just result of
+historical code changes), clean up the code and fix this bug.
+
+Fixes: 83f40318dab00 ("ring-buffer: Make removal of ring buffer pages atomic")
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/ring_buffer.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -1645,14 +1645,13 @@ int ring_buffer_resize(struct ring_buffe
+ !cpumask_test_cpu(cpu_id, buffer->cpumask))
+ return size;
+
+- size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+- size *= BUF_PAGE_SIZE;
++ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+
+ /* we need a minimum of two pages */
+- if (size < BUF_PAGE_SIZE * 2)
+- size = BUF_PAGE_SIZE * 2;
++ if (nr_pages < 2)
++ nr_pages = 2;
+
+- nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
++ size = nr_pages * BUF_PAGE_SIZE;
+
+ /*
+ * Don't succeed if resizing is disabled, as a reader might be
--- /dev/null
+From 9b94a8fba501f38368aef6ac1b30e7335252a220 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+Date: Thu, 12 May 2016 11:01:24 -0400
+Subject: ring-buffer: Use long for nr_pages to avoid overflow failures
+
+From: Steven Rostedt (Red Hat) <rostedt@goodmis.org>
+
+commit 9b94a8fba501f38368aef6ac1b30e7335252a220 upstream.
+
+The size variable to change the ring buffer in ftrace is a long. The
+nr_pages used to update the ring buffer based on the size is int. On 64 bit
+machines this can cause an overflow problem.
+
+For example, the following will cause the ring buffer to crash:
+
+ # cd /sys/kernel/debug/tracing
+ # echo 10 > buffer_size_kb
+ # echo 8556384240 > buffer_size_kb
+
+Then you get the warning of:
+
+ WARNING: CPU: 1 PID: 318 at kernel/trace/ring_buffer.c:1527 rb_update_pages+0x22f/0x260
+
+Which is:
+
+ RB_WARN_ON(cpu_buffer, nr_removed);
+
+Note each ring buffer page holds 4080 bytes.
+
+This is because:
+
+ 1) 10 causes the ring buffer to have 3 pages.
+ (10kb requires 3 * 4080 pages to hold)
+
+ 2) (2^31 / 2^10 + 1) * 4080 = 8556384240
+ The value written into buffer_size_kb is shifted by 10 and then passed
+ to ring_buffer_resize(). 8556384240 * 2^10 = 8761737461760
+
+ 3) The size passed to ring_buffer_resize() is then divided by BUF_PAGE_SIZE
+ which is 4080. 8761737461760 / 4080 = 2147484672
+
+ 4) nr_pages is subtracted from the current nr_pages (3) and we get:
+ 2147484669. This value is saved in a signed integer nr_pages_to_update
+
+ 5) 2147484669 is greater than 2^31 but smaller than 2^32, a signed int
+ turns into the value of -2147482627
+
+ 6) As the value is a negative number, in update_pages_handler() it is
+ negated and passed to rb_remove_pages() and 2147482627 pages will
+ be removed, which is much larger than 3 and it causes the warning
+ because not all the pages asked to be removed were removed.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=118001
+
+Fixes: 7a8e76a3829f1 ("tracing: unified trace buffer")
+Reported-by: Hao Qin <QEver.cn@gmail.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/ring_buffer.c | 26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -463,7 +463,7 @@ struct ring_buffer_per_cpu {
+ raw_spinlock_t reader_lock; /* serialize readers */
+ arch_spinlock_t lock;
+ struct lock_class_key lock_key;
+- unsigned int nr_pages;
++ unsigned long nr_pages;
+ struct list_head *pages;
+ struct buffer_page *head_page; /* read from head */
+ struct buffer_page *tail_page; /* write to tail */
+@@ -483,7 +483,7 @@ struct ring_buffer_per_cpu {
+ u64 write_stamp;
+ u64 read_stamp;
+ /* ring buffer pages to update, > 0 to add, < 0 to remove */
+- int nr_pages_to_update;
++ long nr_pages_to_update;
+ struct list_head new_pages; /* new pages to add */
+ struct work_struct update_pages_work;
+ struct completion update_done;
+@@ -1120,10 +1120,10 @@ static int rb_check_pages(struct ring_bu
+ return 0;
+ }
+
+-static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
++static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
+ {
+- int i;
+ struct buffer_page *bpage, *tmp;
++ long i;
+
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page;
+@@ -1160,7 +1160,7 @@ free_pages:
+ }
+
+ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
+- unsigned nr_pages)
++ unsigned long nr_pages)
+ {
+ LIST_HEAD(pages);
+
+@@ -1185,7 +1185,7 @@ static int rb_allocate_pages(struct ring
+ }
+
+ static struct ring_buffer_per_cpu *
+-rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
++rb_allocate_cpu_buffer(struct ring_buffer *buffer, long nr_pages, int cpu)
+ {
+ struct ring_buffer_per_cpu *cpu_buffer;
+ struct buffer_page *bpage;
+@@ -1284,8 +1284,9 @@ struct ring_buffer *__ring_buffer_alloc(
+ struct lock_class_key *key)
+ {
+ struct ring_buffer *buffer;
++ long nr_pages;
+ int bsize;
+- int cpu, nr_pages;
++ int cpu;
+
+ /* keep it in its own cache line */
+ buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
+@@ -1408,12 +1409,12 @@ static inline unsigned long rb_page_writ
+ }
+
+ static int
+-rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
++rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
+ {
+ struct list_head *tail_page, *to_remove, *next_page;
+ struct buffer_page *to_remove_page, *tmp_iter_page;
+ struct buffer_page *last_page, *first_page;
+- unsigned int nr_removed;
++ unsigned long nr_removed;
+ unsigned long head_bit;
+ int page_entries;
+
+@@ -1630,7 +1631,7 @@ int ring_buffer_resize(struct ring_buffe
+ int cpu_id)
+ {
+ struct ring_buffer_per_cpu *cpu_buffer;
+- unsigned nr_pages;
++ unsigned long nr_pages;
+ int cpu, err = 0;
+
+ /*
+@@ -4609,8 +4610,9 @@ static int rb_cpu_notify(struct notifier
+ struct ring_buffer *buffer =
+ container_of(self, struct ring_buffer, cpu_notify);
+ long cpu = (long)hcpu;
+- int cpu_i, nr_pages_same;
+- unsigned int nr_pages;
++ long nr_pages_same;
++ int cpu_i;
++ unsigned long nr_pages;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
btrfs-don-t-use-src-fd-for-printk.patch
arm-arm64-kvm-enforce-break-before-make-on-stage-2-page-tables.patch
+remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch
+fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch
+cifs-create-dedicated-keyring-for-spnego-operations.patch
+ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch
+ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch
+crypto-caam-fix-caam_jr_alloc-ret-code.patch
+crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch