From: Greg Kroah-Hartman Date: Sun, 29 May 2016 21:51:56 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.14.71~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8650fb7c017337e377b7fcfa9c2f1d69d25b9a9e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches 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 --- 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 index 00000000000..579608a5338 --- /dev/null +++ b/queue-3.14/cifs-create-dedicated-keyring-for-spnego-operations.patch @@ -0,0 +1,167 @@ +From b74cb9a80268be5c80cf4c87c74debf0ff2129ac Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Tue, 17 May 2016 18:20:13 -0500 +Subject: cifs: Create dedicated keyring for spnego operations + +From: Sachin Prabhu + +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 +Reported-by: Scott Mayhew +Reviewed-by: Shirish Pargaonkar +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include + #include + #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 index 00000000000..182d017909c --- /dev/null +++ b/queue-3.14/crypto-caam-fix-caam_jr_alloc-ret-code.patch @@ -0,0 +1,37 @@ +From e930c765ca5c6b039cd22ebfb4504ea7b5dab43d Mon Sep 17 00:00:00 2001 +From: Catalin Vasile +Date: Fri, 6 May 2016 16:18:53 +0300 +Subject: crypto: caam - fix caam_jr_alloc() ret code + +From: Catalin Vasile + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a02a93df00e --- /dev/null +++ b/queue-3.14/crypto-sun4i-ss-replace-spinlock_bh-by-spin_lock_irq-save-restore.patch @@ -0,0 +1,75 @@ +From bdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e Mon Sep 17 00:00:00 2001 +From: Corentin LABBE +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +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 index 00000000000..851373dfbc8 --- /dev/null +++ b/queue-3.14/fs-cifs-correctly-to-anonymous-authentication-via-ntlmssp.patch @@ -0,0 +1,79 @@ +From cfda35d98298131bf38fbad3ce4cd5ecb3cf18db Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 3 May 2016 10:52:30 +0200 +Subject: fs/cifs: correctly to anonymous authentication via NTLMSSP + +From: Stefan Metzmacher + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..ad84e9fdb60 --- /dev/null +++ b/queue-3.14/remove-directory-incorrectly-tries-to-set-delete-on-close-on-non-empty-directories.patch @@ -0,0 +1,102 @@ +From 897fba1172d637d344f009d700f7eb8a1fa262f1 Mon Sep 17 00:00:00 2001 +From: Steve French +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 + +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 +Acked-by: Sachin Prabhu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e7a86fb5c40 --- /dev/null +++ b/queue-3.14/ring-buffer-prevent-overflow-of-size-in-ring_buffer_resize.patch @@ -0,0 +1,89 @@ +From 59643d1535eb220668692a5359de22545af579f6 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" +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) + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..ef224e6f7cb --- /dev/null +++ b/queue-3.14/ring-buffer-use-long-for-nr_pages-to-avoid-overflow-failures.patch @@ -0,0 +1,161 @@ +From 9b94a8fba501f38368aef6ac1b30e7335252a220 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" +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) + +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 +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-3.14/series b/queue-3.14/series index 9ed5a051f3f..a1016ce4e0b 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -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