From: Greg Kroah-Hartman Date: Tue, 13 Aug 2013 05:53:35 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.0.91~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ab44d1a8172e4ae2c436f28935352daab4f3240d;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches 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 --- 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 index 00000000000..8183548e235 --- /dev/null +++ b/queue-3.0/cifs-silence-compiler-warnings-showing-up-with-gcc-4.7.0.patch @@ -0,0 +1,101 @@ +From b2a3ad9ca502169fc4c11296fa20f56059c7c031 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Mon, 26 Mar 2012 09:55:29 -0400 +Subject: cifs: silence compiler warnings showing up with gcc-4.7.0 + +From: Jeff Layton + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1f2b6a28015 --- /dev/null +++ b/queue-3.0/debugfs-debugfs_remove_recursive-must-not-rely-on-list_empty-d_subdirs.patch @@ -0,0 +1,166 @@ +From 776164c1faac4966ab14418bb0922e1820da1d19 Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +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 + +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 +Signed-off-by: Oleg Nesterov +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-3.0/series b/queue-3.0/series index 04aaad66413..08296c62395 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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