diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-10-28 00:17:54 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-10-28 00:39:09 -0400 |
commit | 2ed2d5b33cb564025b1eb90650d70a0a3592c0e3 (patch) | |
tree | 650796f8962c82818464f1c03feecbc9d0bc551f /fs/f2fs/acl.c | |
parent | b8b60e1a65893728ca868493cb4c4b64b55e7f9c (diff) |
f2fs: fix a deadlock during init_acl procedure
The deadlock is found through the following scenario.
sys_mkdir()
-> f2fs_add_link()
-> __f2fs_add_link()
-> init_inode_metadata()
: lock_page(inode);
-> f2fs_init_acl()
-> f2fs_set_acl()
-> f2fs_setxattr(..., NULL)
: This NULL page incurs a deadlock at update_inode_page().
So, likewise f2fs_init_security(), this patch adds a parameter to transfer the
locked inode page to f2fs_setxattr().
Found by Linux File System Verification project (linuxtesting.org).
Reported-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/acl.c')
-rw-r--r-- | fs/f2fs/acl.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index f1a697584651..d0fc287efeff 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -205,7 +205,8 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) | |||
205 | return acl; | 205 | return acl; |
206 | } | 206 | } |
207 | 207 | ||
208 | static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | 208 | static int f2fs_set_acl(struct inode *inode, int type, |
209 | struct posix_acl *acl, struct page *ipage) | ||
209 | { | 210 | { |
210 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 211 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
211 | struct f2fs_inode_info *fi = F2FS_I(inode); | 212 | struct f2fs_inode_info *fi = F2FS_I(inode); |
@@ -250,7 +251,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
250 | } | 251 | } |
251 | } | 252 | } |
252 | 253 | ||
253 | error = f2fs_setxattr(inode, name_index, "", value, size, NULL); | 254 | error = f2fs_setxattr(inode, name_index, "", value, size, ipage); |
254 | 255 | ||
255 | kfree(value); | 256 | kfree(value); |
256 | if (!error) | 257 | if (!error) |
@@ -260,7 +261,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
260 | return error; | 261 | return error; |
261 | } | 262 | } |
262 | 263 | ||
263 | int f2fs_init_acl(struct inode *inode, struct inode *dir) | 264 | int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage) |
264 | { | 265 | { |
265 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | 266 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); |
266 | struct posix_acl *acl = NULL; | 267 | struct posix_acl *acl = NULL; |
@@ -280,7 +281,7 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir) | |||
280 | goto cleanup; | 281 | goto cleanup; |
281 | 282 | ||
282 | if (S_ISDIR(inode->i_mode)) { | 283 | if (S_ISDIR(inode->i_mode)) { |
283 | error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl); | 284 | error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage); |
284 | if (error) | 285 | if (error) |
285 | goto cleanup; | 286 | goto cleanup; |
286 | } | 287 | } |
@@ -288,7 +289,7 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir) | |||
288 | if (error < 0) | 289 | if (error < 0) |
289 | return error; | 290 | return error; |
290 | if (error > 0) | 291 | if (error > 0) |
291 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl); | 292 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage); |
292 | cleanup: | 293 | cleanup: |
293 | posix_acl_release(acl); | 294 | posix_acl_release(acl); |
294 | return error; | 295 | return error; |
@@ -314,7 +315,7 @@ int f2fs_acl_chmod(struct inode *inode) | |||
314 | if (error) | 315 | if (error) |
315 | return error; | 316 | return error; |
316 | 317 | ||
317 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl); | 318 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, NULL); |
318 | posix_acl_release(acl); | 319 | posix_acl_release(acl); |
319 | return error; | 320 | return error; |
320 | } | 321 | } |
@@ -389,7 +390,7 @@ static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name, | |||
389 | acl = NULL; | 390 | acl = NULL; |
390 | } | 391 | } |
391 | 392 | ||
392 | error = f2fs_set_acl(inode, type, acl); | 393 | error = f2fs_set_acl(inode, type, acl, NULL); |
393 | 394 | ||
394 | release_and_out: | 395 | release_and_out: |
395 | posix_acl_release(acl); | 396 | posix_acl_release(acl); |