]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Aug 2013 05:53:35 +0000 (22:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Aug 2013 05:53:35 +0000 (22:53 -0700)
added patches:
cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch
debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch

queue-3.0/cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch [new file with mode: 0644]
queue-3.0/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch [new file with mode: 0644]
queue-3.0/series

diff --git a/queue-3.0/cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch b/queue-3.0/cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch
new file mode 100644 (file)
index 0000000..8183548
--- /dev/null
@@ -0,0 +1,101 @@
+From b2a3ad9ca502169fc4c11296fa20f56059c7c031 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Mon, 26 Mar 2012 09:55:29 -0400
+Subject: cifs: silence compiler warnings showing up with gcc-4.7.0
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit b2a3ad9ca502169fc4c11296fa20f56059c7c031 upstream.
+
+gcc-4.7.0 has started throwing these warnings when building cifs.ko.
+
+  CC [M]  fs/cifs/cifssmb.o
+fs/cifs/cifssmb.c: In function ‘CIFSSMBSetCIFSACL’:
+fs/cifs/cifssmb.c:3905:9: warning: array subscript is above array bounds [-Warray-bounds]
+fs/cifs/cifssmb.c: In function ‘CIFSSMBSetFileInfo’:
+fs/cifs/cifssmb.c:5711:8: warning: array subscript is above array bounds [-Warray-bounds]
+fs/cifs/cifssmb.c: In function ‘CIFSSMBUnixSetFileInfo’:
+fs/cifs/cifssmb.c:6001:25: warning: array subscript is above array bounds [-Warray-bounds]
+
+This patch cleans up the code a bit by using the offsetof macro instead
+of the funky "&pSMB->hdr.Protocol" construct.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifssmb.c |   24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -3473,13 +3473,12 @@ CIFSSMBSetCIFSACL(const int xid, struct
+       int rc = 0;
+       int bytes_returned = 0;
+       SET_SEC_DESC_REQ *pSMB = NULL;
+-      NTRANSACT_RSP *pSMBr = NULL;
++      void *pSMBr;
+ setCifsAclRetry:
+-      rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
+-                      (void **) &pSMBr);
++      rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
+       if (rc)
+-                      return (rc);
++              return rc;
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+@@ -3507,9 +3506,8 @@ setCifsAclRetry:
+       pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
+       if (pntsd && acllen) {
+-              memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
+-                      (char *) pntsd,
+-                      acllen);
++              memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
++                              data_offset, pntsd, acllen);
+               inc_rfc1001_len(pSMB, byte_count + data_count);
+       } else
+               inc_rfc1001_len(pSMB, byte_count);
+@@ -5291,7 +5289,8 @@ CIFSSMBSetFileInfo(const int xid, struct
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+-      data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
++      data_offset = (char *)pSMB +
++                      offsetof(struct smb_hdr, Protocol) + offset;
+       count = sizeof(FILE_BASIC_INFO);
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+@@ -5560,7 +5559,7 @@ CIFSSMBUnixSetFileInfo(const int xid, st
+                      u16 fid, u32 pid_of_opener)
+ {
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+-      FILE_UNIX_BASIC_INFO *data_offset;
++      char *data_offset;
+       int rc = 0;
+       u16 params, param_offset, offset, byte_count, count;
+@@ -5582,8 +5581,9 @@ CIFSSMBUnixSetFileInfo(const int xid, st
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+-      data_offset = (FILE_UNIX_BASIC_INFO *)
+-                              ((char *)(&pSMB->hdr.Protocol) + offset);
++      data_offset = (char *)pSMB +
++                      offsetof(struct smb_hdr, Protocol) + offset;
++
+       count = sizeof(FILE_UNIX_BASIC_INFO);
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+@@ -5605,7 +5605,7 @@ CIFSSMBUnixSetFileInfo(const int xid, st
+       inc_rfc1001_len(pSMB, byte_count);
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+-      cifs_fill_unix_set_info(data_offset, args);
++      cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       if (rc)
diff --git a/queue-3.0/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch b/queue-3.0/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch
new file mode 100644 (file)
index 0000000..1f2b6a2
--- /dev/null
@@ -0,0 +1,166 @@
+From 776164c1faac4966ab14418bb0922e1820da1d19 Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Fri, 26 Jul 2013 17:12:56 +0200
+Subject: debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs)
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit 776164c1faac4966ab14418bb0922e1820da1d19 upstream.
+
+debugfs_remove_recursive() is wrong,
+
+1. it wrongly assumes that !list_empty(d_subdirs) means that this
+   dir should be removed.
+
+   This is not that bad by itself, but:
+
+2. if d_subdirs does not becomes empty after __debugfs_remove()
+   it gives up and silently fails, it doesn't even try to remove
+   other entries.
+
+   However ->d_subdirs can be non-empty because it still has the
+   already deleted !debugfs_positive() entries.
+
+3. simple_release_fs() is called even if __debugfs_remove() fails.
+
+Suppose we have
+
+       dir1/
+               dir2/
+                       file2
+               file1
+
+and someone opens dir1/dir2/file2.
+
+Now, debugfs_remove_recursive(dir1/dir2) succeeds, and dir1/dir2 goes
+away.
+
+But debugfs_remove_recursive(dir1) silently fails and doesn't remove
+this directory. Because it tries to delete (the already deleted)
+dir1/dir2/file2 again and then fails due to "Avoid infinite loop"
+logic.
+
+Test-case:
+
+       #!/bin/sh
+
+       cd /sys/kernel/debug/tracing
+       echo 'p:probe/sigprocmask sigprocmask' >> kprobe_events
+       sleep 1000 < events/probe/sigprocmask/id &
+       echo -n >| kprobe_events
+
+       [ -d events/probe ] && echo "ERR!! failed to rm probe"
+
+And after that it is not possible to create another probe entry.
+
+With this patch debugfs_remove_recursive() skips !debugfs_positive()
+files although this is not strictly needed. The most important change
+is that it does not try to make ->d_subdirs empty, it simply scans
+the whole list(s) recursively and removes as much as possible.
+
+Link: http://lkml.kernel.org/r/20130726151256.GC19472@redhat.com
+
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/debugfs/inode.c |   69 ++++++++++++++++-------------------------------------
+ 1 file changed, 22 insertions(+), 47 deletions(-)
+
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -380,8 +380,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
+  */
+ void debugfs_remove_recursive(struct dentry *dentry)
+ {
+-      struct dentry *child;
+-      struct dentry *parent;
++      struct dentry *child, *next, *parent;
+       if (!dentry)
+               return;
+@@ -391,61 +390,37 @@ void debugfs_remove_recursive(struct den
+               return;
+       parent = dentry;
++ down:
+       mutex_lock(&parent->d_inode->i_mutex);
++      list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
++              if (!debugfs_positive(child))
++                      continue;
+-      while (1) {
+-              /*
+-               * When all dentries under "parent" has been removed,
+-               * walk up the tree until we reach our starting point.
+-               */
+-              if (list_empty(&parent->d_subdirs)) {
+-                      mutex_unlock(&parent->d_inode->i_mutex);
+-                      if (parent == dentry)
+-                              break;
+-                      parent = parent->d_parent;
+-                      mutex_lock(&parent->d_inode->i_mutex);
+-              }
+-              child = list_entry(parent->d_subdirs.next, struct dentry,
+-                              d_u.d_child);
+- next_sibling:
+-
+-              /*
+-               * If "child" isn't empty, walk down the tree and
+-               * remove all its descendants first.
+-               */
++              /* perhaps simple_empty(child) makes more sense */
+               if (!list_empty(&child->d_subdirs)) {
+                       mutex_unlock(&parent->d_inode->i_mutex);
+                       parent = child;
+-                      mutex_lock(&parent->d_inode->i_mutex);
+-                      continue;
++                      goto down;
+               }
+-              __debugfs_remove(child, parent);
+-              if (parent->d_subdirs.next == &child->d_u.d_child) {
+-                      /*
+-                       * Try the next sibling.
+-                       */
+-                      if (child->d_u.d_child.next != &parent->d_subdirs) {
+-                              child = list_entry(child->d_u.d_child.next,
+-                                                 struct dentry,
+-                                                 d_u.d_child);
+-                              goto next_sibling;
+-                      }
+-
+-                      /*
+-                       * Avoid infinite loop if we fail to remove
+-                       * one dentry.
+-                       */
+-                      mutex_unlock(&parent->d_inode->i_mutex);
+-                      break;
+-              }
+-              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
++ up:
++              if (!__debugfs_remove(child, parent))
++                      simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       }
+-      parent = dentry->d_parent;
++      mutex_unlock(&parent->d_inode->i_mutex);
++      child = parent;
++      parent = parent->d_parent;
+       mutex_lock(&parent->d_inode->i_mutex);
+-      __debugfs_remove(dentry, parent);
++
++      if (child != dentry) {
++              next = list_entry(child->d_u.d_child.next, struct dentry,
++                                      d_u.d_child);
++              goto up;
++      }
++
++      if (!__debugfs_remove(child, parent))
++              simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       mutex_unlock(&parent->d_inode->i_mutex);
+-      simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+ }
+ EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
index 04aaad664134bcc20c494a3852de271ce6f5911f..08296c623954cbdd9d2816c441d12fda77248ddb 100644 (file)
@@ -4,3 +4,5 @@ virtio-console-fix-race-in-port_fops_open-and-port-unplug.patch
 virtio-console-clean-up-port-data-immediately-at-time-of-unplug.patch
 virtio-console-fix-raising-sigio-after-port-unplug.patch
 virtio-console-return-enodev-on-all-read-operations-after-unplug.patch
+debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch
+cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch