Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

reiserfs: fix xattr root locking/refcount bug

The listxattr() and getxattr() operations are only protected by a read
lock. As a result, if either of these operations run in parallel, a race
condition exists where the xattr_root will end up being cached twice, which
results in the leaking of a reference and a BUG() on umount.

This patch refactors get_xa_root(), __get_xa_root(), and create_xa_root(),
into one get_xa_root() function that takes the appropriate locking around
the entire critical section.

Reported, diagnosed and tested by Andrea Righi <a.righi@cineca.it>

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Cc: Andrea Righi <a.righi@cineca.it>
Cc: "Vladimir V. Saveliev" <vs@namesys.com>
Cc: Edward Shishkin <edward@namesys.com>
Cc: Alex Zarochentsev <zam@namesys.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jeff Mahoney and committed by
Linus Torvalds
9b7f3755 1a641fce

+24 -68
+24 -68
fs/reiserfs/xattr.c
··· 54 54 static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char 55 55 *prefix); 56 56 57 - static struct dentry *create_xa_root(struct super_block *sb) 57 + /* Returns the dentry referring to the root of the extended attribute 58 + * directory tree. If it has already been retrieved, it is used. If it 59 + * hasn't been created and the flags indicate creation is allowed, we 60 + * attempt to create it. On error, we return a pointer-encoded error. 61 + */ 62 + static struct dentry *get_xa_root(struct super_block *sb, int flags) 58 63 { 59 64 struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); 60 65 struct dentry *xaroot; 61 66 62 67 /* This needs to be created at mount-time */ 63 68 if (!privroot) 64 - return ERR_PTR(-EOPNOTSUPP); 69 + return ERR_PTR(-ENODATA); 70 + 71 + mutex_lock(&privroot->d_inode->i_mutex); 72 + if (REISERFS_SB(sb)->xattr_root) { 73 + xaroot = dget(REISERFS_SB(sb)->xattr_root); 74 + goto out; 75 + } 65 76 66 77 xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); 67 78 if (IS_ERR(xaroot)) { 68 79 goto out; 69 80 } else if (!xaroot->d_inode) { 70 - int err; 71 - mutex_lock(&privroot->d_inode->i_mutex); 72 - err = 73 - privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot, 74 - 0700); 75 - mutex_unlock(&privroot->d_inode->i_mutex); 76 - 81 + int err = -ENODATA; 82 + if (flags == 0 || flags & XATTR_CREATE) 83 + err = privroot->d_inode->i_op->mkdir(privroot->d_inode, 84 + xaroot, 0700); 77 85 if (err) { 78 86 dput(xaroot); 79 - dput(privroot); 80 - return ERR_PTR(err); 87 + xaroot = ERR_PTR(err); 88 + goto out; 81 89 } 82 - REISERFS_SB(sb)->xattr_root = dget(xaroot); 83 90 } 91 + REISERFS_SB(sb)->xattr_root = dget(xaroot); 84 92 85 93 out: 94 + mutex_unlock(&privroot->d_inode->i_mutex); 86 95 dput(privroot); 87 96 return xaroot; 88 - } 89 - 90 - /* This will return a dentry, or error, refering to the xa root directory. 91 - * If the xa root doesn't exist yet, the dentry will be returned without 92 - * an associated inode. This dentry can be used with ->mkdir to create 93 - * the xa directory. */ 94 - static struct dentry *__get_xa_root(struct super_block *s) 95 - { 96 - struct dentry *privroot = dget(REISERFS_SB(s)->priv_root); 97 - struct dentry *xaroot = NULL; 98 - 99 - if (IS_ERR(privroot) || !privroot) 100 - return privroot; 101 - 102 - xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); 103 - if (IS_ERR(xaroot)) { 104 - goto out; 105 - } else if (!xaroot->d_inode) { 106 - dput(xaroot); 107 - xaroot = NULL; 108 - goto out; 109 - } 110 - 111 - REISERFS_SB(s)->xattr_root = dget(xaroot); 112 - 113 - out: 114 - dput(privroot); 115 - return xaroot; 116 - } 117 - 118 - /* Returns the dentry (or NULL) referring to the root of the extended 119 - * attribute directory tree. If it has already been retrieved, it is used. 120 - * Otherwise, we attempt to retrieve it from disk. It may also return 121 - * a pointer-encoded error. 122 - */ 123 - static inline struct dentry *get_xa_root(struct super_block *s) 124 - { 125 - struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root); 126 - 127 - if (!dentry) 128 - dentry = __get_xa_root(s); 129 - 130 - return dentry; 131 97 } 132 98 133 99 /* Opens the directory corresponding to the inode's extended attribute store. ··· 104 138 struct dentry *xaroot, *xadir; 105 139 char namebuf[17]; 106 140 107 - xaroot = get_xa_root(inode->i_sb); 108 - if (IS_ERR(xaroot)) { 141 + xaroot = get_xa_root(inode->i_sb, flags); 142 + if (IS_ERR(xaroot)) 109 143 return xaroot; 110 - } else if (!xaroot) { 111 - if (flags == 0 || flags & XATTR_CREATE) { 112 - xaroot = create_xa_root(inode->i_sb); 113 - if (IS_ERR(xaroot)) 114 - return xaroot; 115 - } 116 - if (!xaroot) 117 - return ERR_PTR(-ENODATA); 118 - } 119 144 120 145 /* ok, we have xaroot open */ 121 - 122 146 snprintf(namebuf, sizeof(namebuf), "%X.%X", 123 147 le32_to_cpu(INODE_PKEY(inode)->k_objectid), 124 148 inode->i_generation); ··· 777 821 778 822 /* Leftovers besides . and .. -- that's not good. */ 779 823 if (dir->d_inode->i_nlink <= 2) { 780 - root = get_xa_root(inode->i_sb); 824 + root = get_xa_root(inode->i_sb, XATTR_REPLACE); 781 825 reiserfs_write_lock_xattrs(inode->i_sb); 782 826 err = vfs_rmdir(root->d_inode, dir); 783 827 reiserfs_write_unlock_xattrs(inode->i_sb);