From: Greg Kroah-Hartman Date: Fri, 21 Apr 2017 08:42:15 +0000 (+0200) Subject: 4.10-stable patches X-Git-Tag: v3.18.50~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ccc07fe3ce927aaa3f08baa3f3ef5b0f7e5d49f7;p=thirdparty%2Fkernel%2Fstable-queue.git 4.10-stable patches added patches: cifs-do-not-send-echoes-before-negotiate-is-complete.patch cifs-remove-bad_network_name-flag.patch hid-wacom-treat-hid_dg_toolserialnumber-as-unsigned.patch keys-change-the-name-of-the-dead-type-to-.dead-to-prevent-user-access.patch keys-disallow-keyrings-beginning-with-.-to-be-joined-as-session-keyrings.patch keys-fix-keyctl_set_reqkey_keyring-to-not-leak-thread-keyrings.patch mm-prevent-nr_isolate_-stats-from-going-negative.patch ring-buffer-have-ring_buffer_iter_empty-return-true-when-empty.patch tracing-allocate-the-snapshot-buffer-before-enabling-probe.patch --- diff --git a/queue-4.10/cifs-do-not-send-echoes-before-negotiate-is-complete.patch b/queue-4.10/cifs-do-not-send-echoes-before-negotiate-is-complete.patch new file mode 100644 index 00000000000..25c87e9d625 --- /dev/null +++ b/queue-4.10/cifs-do-not-send-echoes-before-negotiate-is-complete.patch @@ -0,0 +1,65 @@ +From 62a6cfddcc0a5313e7da3e8311ba16226fe0ac10 Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Sun, 16 Apr 2017 20:37:24 +0100 +Subject: cifs: Do not send echoes before Negotiate is complete + +From: Sachin Prabhu + +commit 62a6cfddcc0a5313e7da3e8311ba16226fe0ac10 upstream. + +commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect +long after socket reconnect") added support for Negotiate requests to +be initiated by echo calls. + +To avoid delays in calling echo after a reconnect, I added the patch +introduced by the commit b8c600120fc8 ("Call echo service immediately +after socket reconnect"). + +This has however caused a regression with cifs shares which do not have +support for echo calls to trigger Negotiate requests. On connections +which need to call Negotiation, the echo calls trigger an error which +triggers a reconnect which in turn triggers another echo call. This +results in a loop which is only broken when an operation is performed on +the cifs share. For an idle share, it can DOS a server. + +The patch uses the smb_operation can_echo() for cifs so that it is +called only if connection has been already been setup. + +kernel bz: 194531 + +Signed-off-by: Sachin Prabhu +Tested-by: Jonathan Liu +Acked-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb1ops.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -1015,6 +1015,15 @@ cifs_dir_needs_close(struct cifsFileInfo + return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle; + } + ++static bool ++cifs_can_echo(struct TCP_Server_Info *server) ++{ ++ if (server->tcpStatus == CifsGood) ++ return true; ++ ++ return false; ++} ++ + struct smb_version_operations smb1_operations = { + .send_cancel = send_nt_cancel, + .compare_fids = cifs_compare_fids, +@@ -1049,6 +1058,7 @@ struct smb_version_operations smb1_opera + .get_dfs_refer = CIFSGetDFSRefer, + .qfs_tcon = cifs_qfs_tcon, + .is_path_accessible = cifs_is_path_accessible, ++ .can_echo = cifs_can_echo, + .query_path_info = cifs_query_path_info, + .query_file_info = cifs_query_file_info, + .get_srv_inum = cifs_get_srv_inum, diff --git a/queue-4.10/cifs-remove-bad_network_name-flag.patch b/queue-4.10/cifs-remove-bad_network_name-flag.patch new file mode 100644 index 00000000000..f97197f71ec --- /dev/null +++ b/queue-4.10/cifs-remove-bad_network_name-flag.patch @@ -0,0 +1,64 @@ +From a0918f1ce6a43ac980b42b300ec443c154970979 Mon Sep 17 00:00:00 2001 +From: Germano Percossi +Date: Fri, 7 Apr 2017 12:29:37 +0100 +Subject: CIFS: remove bad_network_name flag + +From: Germano Percossi + +commit a0918f1ce6a43ac980b42b300ec443c154970979 upstream. + +STATUS_BAD_NETWORK_NAME can be received during node failover, +causing the flag to be set and making the reconnect thread +always unsuccessful, thereafter. + +Once the only place where it is set is removed, the remaining +bits are rendered moot. + +Removing it does not prevent "mount" from failing when a non +existent share is passed. + +What happens when the share really ceases to exist while the +share is mounted is undefined now as much as it was before. + +Signed-off-by: Germano Percossi +Reviewed-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/cifs/cifsglob.h | 1 - + fs/cifs/smb2pdu.c | 5 ----- + 2 files changed, 6 deletions(-) + +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -933,7 +933,6 @@ struct cifs_tcon { + bool use_persistent:1; /* use persistent instead of durable handles */ + #ifdef CONFIG_CIFS_SMB2 + bool print:1; /* set if connection to printer share */ +- bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */ + __le32 capabilities; + __u32 share_flags; + __u32 maximal_access; +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1084,9 +1084,6 @@ SMB2_tcon(const unsigned int xid, struct + else + return -EIO; + +- if (tcon && tcon->bad_network_name) +- return -ENOENT; +- + if ((tcon && tcon->seal) && + ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) { + cifs_dbg(VFS, "encryption requested but no server support"); +@@ -1188,8 +1185,6 @@ tcon_exit: + tcon_error_exit: + if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { + cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); +- if (tcon) +- tcon->bad_network_name = true; + } + goto tcon_exit; + } diff --git a/queue-4.10/hid-wacom-treat-hid_dg_toolserialnumber-as-unsigned.patch b/queue-4.10/hid-wacom-treat-hid_dg_toolserialnumber-as-unsigned.patch new file mode 100644 index 00000000000..4d6b25a0dd3 --- /dev/null +++ b/queue-4.10/hid-wacom-treat-hid_dg_toolserialnumber-as-unsigned.patch @@ -0,0 +1,56 @@ +From 286f3f478796fb4f9e003e9f7d649f3c33f08d2f Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Thu, 13 Apr 2017 08:39:49 -0700 +Subject: HID: wacom: Treat HID_DG_TOOLSERIALNUMBER as unsigned + +From: Jason Gerecke + +commit 286f3f478796fb4f9e003e9f7d649f3c33f08d2f upstream. + +Because HID_DG_TOOLSERIALNUMBER doesn't first cast the value recieved from HID +to an unsigned type, sign-extension rules can cause the value of +wacom_wac->serial[0] to inadvertently wind up with all 32 of its highest bits +set if the highest bit of "value" was set. + +This can cause problems for Tablet PC devices which use AES sensors and the +xf86-input-wacom userspace driver. It is not uncommon for AES sensors to send a +serial number of '0' while the pen is entering or leaving proximity. The +xf86-input-wacom driver ignores events with a serial number of '0' since it +cannot match them up to an in-use tool. To ensure the xf86-input-wacom driver +does not ignore the final out-of-proximity event, the kernel does not send +MSC_SERIAL events when the value of wacom_wac->serial[0] is '0'. If the highest +bit of HID_DG_TOOLSERIALNUMBER is set by an in-prox pen which later leaves +proximity and sends a '0' for HID_DG_TOOLSERIALNUMBER, then only the lowest 32 +bits of wacom_wac->serial[0] are actually cleared, causing the kernel to send +an MSC_SERIAL event. Since the 'input_event' function takes an 'int' as +argument, only those lowest (now-cleared) 32 bits of wacom_wac->serial[0] are +sent to userspace, causing xf86-input-wacom to ignore the event. If the event +was the final out-of-prox event, then xf86-input-wacom may remain in a state +where it believes the pen is in proximity and refuses to allow other devices +under its control (e.g. the touchscreen) to move the cursor. + +It should be noted that EMR devices and devices which use both the +HID_DG_TOOLSERIALNUMBER and WACOM_HID_WD_SERIALHI usages (in that order) would +be immune to this issue. It appears only AES devices are affected. + +Fixes: f85c9dc678a ("HID: wacom: generic: Support tool ID and additional tool types") +Signed-off-by: Jason Gerecke +Acked-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/wacom_wac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -1798,7 +1798,7 @@ static void wacom_wac_pen_event(struct h + return; + case HID_DG_TOOLSERIALNUMBER: + wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL); +- wacom_wac->serial[0] |= value; ++ wacom_wac->serial[0] |= (__u32)value; + return; + case WACOM_HID_WD_SENSE: + wacom_wac->hid_data.sense_state = value; diff --git a/queue-4.10/keys-change-the-name-of-the-dead-type-to-.dead-to-prevent-user-access.patch b/queue-4.10/keys-change-the-name-of-the-dead-type-to-.dead-to-prevent-user-access.patch new file mode 100644 index 00000000000..4de659447dc --- /dev/null +++ b/queue-4.10/keys-change-the-name-of-the-dead-type-to-.dead-to-prevent-user-access.patch @@ -0,0 +1,46 @@ +From c1644fe041ebaf6519f6809146a77c3ead9193af Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 18 Apr 2017 15:31:08 +0100 +Subject: KEYS: Change the name of the dead type to ".dead" to prevent user access + +From: David Howells + +commit c1644fe041ebaf6519f6809146a77c3ead9193af upstream. + +This fixes CVE-2017-6951. + +Userspace should not be able to do things with the "dead" key type as it +doesn't have some of the helper functions set upon it that the kernel +needs. Attempting to use it may cause the kernel to crash. + +Fix this by changing the name of the type to ".dead" so that it's rejected +up front on userspace syscalls by key_get_type_from_user(). + +Though this doesn't seem to affect recent kernels, it does affect older +ones, certainly those prior to: + + commit c06cfb08b88dfbe13be44a69ae2fdc3a7c902d81 + Author: David Howells + Date: Tue Sep 16 17:36:06 2014 +0100 + KEYS: Remove key_type::match in favour of overriding default by match_preparse + +which went in before 3.18-rc1. + +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + security/keys/gc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -46,7 +46,7 @@ static unsigned long key_gc_flags; + * immediately unlinked. + */ + struct key_type key_type_dead = { +- .name = "dead", ++ .name = ".dead", + }; + + /* diff --git a/queue-4.10/keys-disallow-keyrings-beginning-with-.-to-be-joined-as-session-keyrings.patch b/queue-4.10/keys-disallow-keyrings-beginning-with-.-to-be-joined-as-session-keyrings.patch new file mode 100644 index 00000000000..b126a4bed5c --- /dev/null +++ b/queue-4.10/keys-disallow-keyrings-beginning-with-.-to-be-joined-as-session-keyrings.patch @@ -0,0 +1,79 @@ +From ee8f844e3c5a73b999edf733df1c529d6503ec2f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 18 Apr 2017 15:31:07 +0100 +Subject: KEYS: Disallow keyrings beginning with '.' to be joined as session keyrings + +From: David Howells + +commit ee8f844e3c5a73b999edf733df1c529d6503ec2f upstream. + +This fixes CVE-2016-9604. + +Keyrings whose name begin with a '.' are special internal keyrings and so +userspace isn't allowed to create keyrings by this name to prevent +shadowing. However, the patch that added the guard didn't fix +KEYCTL_JOIN_SESSION_KEYRING. Not only can that create dot-named keyrings, +it can also subscribe to them as a session keyring if they grant SEARCH +permission to the user. + +This, for example, allows a root process to set .builtin_trusted_keys as +its session keyring, at which point it has full access because now the +possessor permissions are added. This permits root to add extra public +keys, thereby bypassing module verification. + +This also affects kexec and IMA. + +This can be tested by (as root): + + keyctl session .builtin_trusted_keys + keyctl add user a a @s + keyctl list @s + +which on my test box gives me: + + 2 keys in keyring: + 180010936: ---lswrv 0 0 asymmetric: Build time autogenerated kernel key: ae3d4a31b82daa8e1a75b49dc2bba949fd992a05 + 801382539: --alswrv 0 0 user: a + + +Fix this by rejecting names beginning with a '.' in the keyctl. + +Signed-off-by: David Howells +Acked-by: Mimi Zohar +cc: linux-ima-devel@lists.sourceforge.net +Signed-off-by: Greg Kroah-Hartman + +--- + security/keys/keyctl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -271,7 +271,8 @@ error: + * Create and join an anonymous session keyring or join a named session + * keyring, creating it if necessary. A named session keyring must have Search + * permission for it to be joined. Session keyrings without this permit will +- * be skipped over. ++ * be skipped over. It is not permitted for userspace to create or join ++ * keyrings whose name begin with a dot. + * + * If successful, the ID of the joined session keyring will be returned. + */ +@@ -288,12 +289,16 @@ long keyctl_join_session_keyring(const c + ret = PTR_ERR(name); + goto error; + } ++ ++ ret = -EPERM; ++ if (name[0] == '.') ++ goto error_name; + } + + /* join the session */ + ret = join_session_keyring(name); ++error_name: + kfree(name); +- + error: + return ret; + } diff --git a/queue-4.10/keys-fix-keyctl_set_reqkey_keyring-to-not-leak-thread-keyrings.patch b/queue-4.10/keys-fix-keyctl_set_reqkey_keyring-to-not-leak-thread-keyrings.patch new file mode 100644 index 00000000000..52dcc182d59 --- /dev/null +++ b/queue-4.10/keys-fix-keyctl_set_reqkey_keyring-to-not-leak-thread-keyrings.patch @@ -0,0 +1,178 @@ +From c9f838d104fed6f2f61d68164712e3204bf5271b Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 18 Apr 2017 15:31:09 +0100 +Subject: KEYS: fix keyctl_set_reqkey_keyring() to not leak thread keyrings + +From: Eric Biggers + +commit c9f838d104fed6f2f61d68164712e3204bf5271b upstream. + +This fixes CVE-2017-7472. + +Running the following program as an unprivileged user exhausts kernel +memory by leaking thread keyrings: + + #include + + int main() + { + for (;;) + keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_THREAD_KEYRING); + } + +Fix it by only creating a new thread keyring if there wasn't one before. +To make things more consistent, make install_thread_keyring_to_cred() +and install_process_keyring_to_cred() both return 0 if the corresponding +keyring is already present. + +Fixes: d84f4f992cbd ("CRED: Inaugurate COW credentials") +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman + +--- + security/keys/keyctl.c | 11 +++------- + security/keys/process_keys.c | 44 ++++++++++++++++++++++++++----------------- + 2 files changed, 31 insertions(+), 24 deletions(-) + +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -1256,8 +1256,8 @@ error: + * Read or set the default keyring in which request_key() will cache keys and + * return the old setting. + * +- * If a process keyring is specified then this will be created if it doesn't +- * yet exist. The old setting will be returned if successful. ++ * If a thread or process keyring is specified then it will be created if it ++ * doesn't yet exist. The old setting will be returned if successful. + */ + long keyctl_set_reqkey_keyring(int reqkey_defl) + { +@@ -1282,11 +1282,8 @@ long keyctl_set_reqkey_keyring(int reqke + + case KEY_REQKEY_DEFL_PROCESS_KEYRING: + ret = install_process_keyring_to_cred(new); +- if (ret < 0) { +- if (ret != -EEXIST) +- goto error; +- ret = 0; +- } ++ if (ret < 0) ++ goto error; + goto set; + + case KEY_REQKEY_DEFL_DEFAULT: +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -127,13 +127,18 @@ error: + } + + /* +- * Install a fresh thread keyring directly to new credentials. This keyring is +- * allowed to overrun the quota. ++ * Install a thread keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + int install_thread_keyring_to_cred(struct cred *new) + { + struct key *keyring; + ++ if (new->thread_keyring) ++ return 0; ++ + keyring = keyring_alloc("_tid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, + KEY_ALLOC_QUOTA_OVERRUN, +@@ -146,7 +151,9 @@ int install_thread_keyring_to_cred(struc + } + + /* +- * Install a fresh thread keyring, discarding the old one. ++ * Install a thread keyring to the current task if it didn't have one already. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + static int install_thread_keyring(void) + { +@@ -157,8 +164,6 @@ static int install_thread_keyring(void) + if (!new) + return -ENOMEM; + +- BUG_ON(new->thread_keyring); +- + ret = install_thread_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +@@ -169,17 +174,17 @@ static int install_thread_keyring(void) + } + + /* +- * Install a process keyring directly to a credentials struct. ++ * Install a process keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. + * +- * Returns -EEXIST if there was already a process keyring, 0 if one installed, +- * and other value on any other error ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + int install_process_keyring_to_cred(struct cred *new) + { + struct key *keyring; + + if (new->process_keyring) +- return -EEXIST; ++ return 0; + + keyring = keyring_alloc("_pid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, +@@ -193,11 +198,9 @@ int install_process_keyring_to_cred(stru + } + + /* +- * Make sure a process keyring is installed for the current process. The +- * existing process keyring is not replaced. ++ * Install a process keyring to the current task if it didn't have one already. + * +- * Returns 0 if there is a process keyring by the end of this function, some +- * error otherwise. ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + static int install_process_keyring(void) + { +@@ -211,14 +214,18 @@ static int install_process_keyring(void) + ret = install_process_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +- return ret != -EEXIST ? ret : 0; ++ return ret; + } + + return commit_creds(new); + } + + /* +- * Install a session keyring directly to a credentials struct. ++ * Install the given keyring as the session keyring of the given credentials ++ * struct, replacing the existing one if any. If the given keyring is NULL, ++ * then install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + { +@@ -253,8 +260,11 @@ int install_session_keyring_to_cred(stru + } + + /* +- * Install a session keyring, discarding the old one. If a keyring is not +- * supplied, an empty one is invented. ++ * Install the given keyring as the session keyring of the current task, ++ * replacing the existing one if any. If the given keyring is NULL, then ++ * install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + static int install_session_keyring(struct key *keyring) + { diff --git a/queue-4.10/mm-prevent-nr_isolate_-stats-from-going-negative.patch b/queue-4.10/mm-prevent-nr_isolate_-stats-from-going-negative.patch new file mode 100644 index 00000000000..dd5e3f20c0b --- /dev/null +++ b/queue-4.10/mm-prevent-nr_isolate_-stats-from-going-negative.patch @@ -0,0 +1,58 @@ +From fc280fe871449ead4bdbd1665fa52c7c01c64765 Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Thu, 20 Apr 2017 14:37:46 -0700 +Subject: mm: prevent NR_ISOLATE_* stats from going negative + +From: Rabin Vincent + +commit fc280fe871449ead4bdbd1665fa52c7c01c64765 upstream. + +Commit 6afcf8ef0ca0 ("mm, compaction: fix NR_ISOLATED_* stats for pfn +based migration") moved the dec_node_page_state() call (along with the +page_is_file_cache() call) to after putback_lru_page(). + +But page_is_file_cache() can change after putback_lru_page() is called, +so it should be called before putback_lru_page(), as it was before that +patch, to prevent NR_ISOLATE_* stats from going negative. + +Without this fix, non-CONFIG_SMP kernels end up hanging in the +while(too_many_isolated()) { congestion_wait() } loop in +shrink_active_list() due to the negative stats. + + Mem-Info: + active_anon:32567 inactive_anon:121 isolated_anon:1 + active_file:6066 inactive_file:6639 isolated_file:4294967295 + ^^^^^^^^^^ + unevictable:0 dirty:115 writeback:0 unstable:0 + slab_reclaimable:2086 slab_unreclaimable:3167 + mapped:3398 shmem:18366 pagetables:1145 bounce:0 + free:1798 free_pcp:13 free_cma:0 + +Fixes: 6afcf8ef0ca0 ("mm, compaction: fix NR_ISOLATED_* stats for pfn based migration") +Link: http://lkml.kernel.org/r/1492683865-27549-1-git-send-email-rabin.vincent@axis.com +Signed-off-by: Rabin Vincent +Acked-by: Michal Hocko +Cc: Ming Ling +Cc: Minchan Kim +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/migrate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -183,9 +183,9 @@ void putback_movable_pages(struct list_h + unlock_page(page); + put_page(page); + } else { +- putback_lru_page(page); + dec_node_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); ++ putback_lru_page(page); + } + } + } diff --git a/queue-4.10/ring-buffer-have-ring_buffer_iter_empty-return-true-when-empty.patch b/queue-4.10/ring-buffer-have-ring_buffer_iter_empty-return-true-when-empty.patch new file mode 100644 index 00000000000..3d5b738c875 --- /dev/null +++ b/queue-4.10/ring-buffer-have-ring_buffer_iter_empty-return-true-when-empty.patch @@ -0,0 +1,86 @@ +From 78f7a45dac2a2d2002f98a3a95f7979867868d73 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Wed, 19 Apr 2017 14:29:46 -0400 +Subject: ring-buffer: Have ring_buffer_iter_empty() return true when empty + +From: Steven Rostedt (VMware) + +commit 78f7a45dac2a2d2002f98a3a95f7979867868d73 upstream. + +I noticed that reading the snapshot file when it is empty no longer gives a +status. It suppose to show the status of the snapshot buffer as well as how +to allocate and use it. For example: + + ># cat snapshot + # tracer: nop + # + # + # * Snapshot is allocated * + # + # Snapshot commands: + # echo 0 > snapshot : Clears and frees snapshot buffer + # echo 1 > snapshot : Allocates snapshot buffer, if not already allocated. + # Takes a snapshot of the main buffer. + # echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free) + # (Doesn't have to be '2' works with any number that + # is not a '0' or '1') + +But instead it just showed an empty buffer: + + ># cat snapshot + # tracer: nop + # + # entries-in-buffer/entries-written: 0/0 #P:4 + # + # _-----=> irqs-off + # / _----=> need-resched + # | / _---=> hardirq/softirq + # || / _--=> preempt-depth + # ||| / delay + # TASK-PID CPU# |||| TIMESTAMP FUNCTION + # | | | |||| | | + +What happened was that it was using the ring_buffer_iter_empty() function to +see if it was empty, and if it was, it showed the status. But that function +was returning false when it was empty. The reason was that the iter header +page was on the reader page, and the reader page was empty, but so was the +buffer itself. The check only tested to see if the iter was on the commit +page, but the commit page was no longer pointing to the reader page, but as +all pages were empty, the buffer is also. + +Fixes: 651e22f2701b ("ring-buffer: Always reset iterator to reader page") +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/ring_buffer.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -3404,11 +3404,23 @@ EXPORT_SYMBOL_GPL(ring_buffer_iter_reset + int ring_buffer_iter_empty(struct ring_buffer_iter *iter) + { + struct ring_buffer_per_cpu *cpu_buffer; ++ struct buffer_page *reader; ++ struct buffer_page *head_page; ++ struct buffer_page *commit_page; ++ unsigned commit; + + cpu_buffer = iter->cpu_buffer; + +- return iter->head_page == cpu_buffer->commit_page && +- iter->head == rb_commit_index(cpu_buffer); ++ /* Remember, trace recording is off when iterator is in use */ ++ reader = cpu_buffer->reader_page; ++ head_page = cpu_buffer->head_page; ++ commit_page = cpu_buffer->commit_page; ++ commit = rb_page_commit(commit_page); ++ ++ return ((iter->head_page == commit_page && iter->head == commit) || ++ (iter->head_page == reader && commit_page == head_page && ++ head_page->read == commit && ++ iter->head == rb_page_commit(cpu_buffer->reader_page))); + } + EXPORT_SYMBOL_GPL(ring_buffer_iter_empty); + diff --git a/queue-4.10/tracing-allocate-the-snapshot-buffer-before-enabling-probe.patch b/queue-4.10/tracing-allocate-the-snapshot-buffer-before-enabling-probe.patch new file mode 100644 index 00000000000..7f477b5a70d --- /dev/null +++ b/queue-4.10/tracing-allocate-the-snapshot-buffer-before-enabling-probe.patch @@ -0,0 +1,45 @@ +From df62db5be2e5f070ecd1a5ece5945b590ee112e0 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Wed, 19 Apr 2017 12:07:08 -0400 +Subject: tracing: Allocate the snapshot buffer before enabling probe + +From: Steven Rostedt (VMware) + +commit df62db5be2e5f070ecd1a5ece5945b590ee112e0 upstream. + +Currently the snapshot trigger enables the probe and then allocates the +snapshot. If the probe triggers before the allocation, it could cause the +snapshot to fail and turn tracing off. It's best to allocate the snapshot +buffer first, and then enable the trigger. If something goes wrong in the +enabling of the trigger, the snapshot buffer is still allocated, but it can +also be freed by the user by writting zero into the snapshot buffer file. + +Also add a check of the return status of alloc_snapshot(). + +Fixes: 77fd5c15e3 ("tracing: Add snapshot trigger to function probes") +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -6740,11 +6740,13 @@ ftrace_trace_snapshot_callback(struct ft + return ret; + + out_reg: +- ret = register_ftrace_function_probe(glob, ops, count); ++ ret = alloc_snapshot(&global_trace); ++ if (ret < 0) ++ goto out; + +- if (ret >= 0) +- alloc_snapshot(&global_trace); ++ ret = register_ftrace_function_probe(glob, ops, count); + ++ out: + return ret < 0 ? ret : 0; + } +