]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 29 May 2016 21:51:56 +0000 (14:51 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 29 May 2016 21:51:56 +0000 (14:51 -0700)
added patches:
cifs-create-dedicated-keyring-for-spnego-operations.patch
crypto-caam-fix-caam_jr_alloc-ret-code.patch
crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch
fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch
remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch
ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch
ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch

queue-3.14/cifs-create-dedicated-keyring-for-spnego-operations.patch [new file with mode: 0644]
queue-3.14/crypto-caam-fix-caam_jr_alloc-ret-code.patch [new file with mode: 0644]
queue-3.14/crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch [new file with mode: 0644]
queue-3.14/fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch [new file with mode: 0644]
queue-3.14/remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch [new file with mode: 0644]
queue-3.14/ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch [new file with mode: 0644]
queue-3.14/ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch [new file with mode: 0644]
queue-3.14/series

diff --git a/queue-3.14/cifs-create-dedicated-keyring-for-spnego-operations.patch b/queue-3.14/cifs-create-dedicated-keyring-for-spnego-operations.patch
new file mode 100644 (file)
index 0000000..579608a
--- /dev/null
@@ -0,0 +1,167 @@
+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,
diff --git a/queue-3.14/crypto-caam-fix-caam_jr_alloc-ret-code.patch b/queue-3.14/crypto-caam-fix-caam_jr_alloc-ret-code.patch
new file mode 100644 (file)
index 0000000..182d017
--- /dev/null
@@ -0,0 +1,37 @@
+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;
diff --git a/queue-3.14/crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch b/queue-3.14/crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch
new file mode 100644 (file)
index 0000000..a02a93d
--- /dev/null
@@ -0,0 +1,75 @@
+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;
+ }
diff --git a/queue-3.14/fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch b/queue-3.14/fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch
new file mode 100644 (file)
index 0000000..851373d
--- /dev/null
@@ -0,0 +1,79 @@
+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);
diff --git a/queue-3.14/remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch b/queue-3.14/remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch
new file mode 100644 (file)
index 0000000..ad84e9f
--- /dev/null
@@ -0,0 +1,102 @@
+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);
diff --git a/queue-3.14/ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch b/queue-3.14/ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch
new file mode 100644 (file)
index 0000000..e7a86fb
--- /dev/null
@@ -0,0 +1,89 @@
+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
diff --git a/queue-3.14/ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch b/queue-3.14/ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch
new file mode 100644 (file)
index 0000000..ef224e6
--- /dev/null
@@ -0,0 +1,161 @@
+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:
index 9ed5a051f3fdb728371107dc4d92b292349f5231..a1016ce4e0b14a2b773cc1795e1054e9ae7e3093 100644 (file)
@@ -1,2 +1,9 @@
 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