diff options
| author | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-04-15 16:49:55 -0400 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-04-16 12:45:40 -0400 |
| commit | feb7cbb079e63ebb7c0bd7022d2ba9c1dd15c69b (patch) | |
| tree | 279b5dcd63730d042ef2cda231d115f703fa14e9 | |
| parent | d0cae97cb600d84a7e00df6f83ab3b2f60d8d7f7 (diff) | |
f2fs: avoid abnormal behavior on broken symlink
When f2fs_symlink was triggered and checkpoint was done before syncing its
link path, f2fs can get broken symlink like "xxx -> \0\0\0".
This incurs abnormal path_walk by VFS.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
| -rw-r--r-- | fs/f2fs/namei.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 9f0eec4677fe..407dde3d7a92 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
| 16 | #include <linux/dcache.h> | 16 | #include <linux/dcache.h> |
| 17 | #include <linux/namei.h> | ||
| 17 | 18 | ||
| 18 | #include "f2fs.h" | 19 | #include "f2fs.h" |
| 19 | #include "node.h" | 20 | #include "node.h" |
| @@ -295,6 +296,23 @@ fail: | |||
| 295 | return err; | 296 | return err; |
| 296 | } | 297 | } |
| 297 | 298 | ||
| 299 | static void *f2fs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
| 300 | { | ||
| 301 | struct page *page; | ||
| 302 | |||
| 303 | page = page_follow_link_light(dentry, nd); | ||
| 304 | if (IS_ERR(page)) | ||
| 305 | return page; | ||
| 306 | |||
| 307 | /* this is broken symlink case */ | ||
| 308 | if (*nd_get_link(nd) == 0) { | ||
| 309 | kunmap(page); | ||
| 310 | page_cache_release(page); | ||
| 311 | return ERR_PTR(-ENOENT); | ||
| 312 | } | ||
| 313 | return page; | ||
| 314 | } | ||
| 315 | |||
| 298 | static int f2fs_symlink(struct inode *dir, struct dentry *dentry, | 316 | static int f2fs_symlink(struct inode *dir, struct dentry *dentry, |
| 299 | const char *symname) | 317 | const char *symname) |
| 300 | { | 318 | { |
| @@ -790,7 +808,7 @@ const struct inode_operations f2fs_dir_inode_operations = { | |||
| 790 | 808 | ||
| 791 | const struct inode_operations f2fs_symlink_inode_operations = { | 809 | const struct inode_operations f2fs_symlink_inode_operations = { |
| 792 | .readlink = generic_readlink, | 810 | .readlink = generic_readlink, |
| 793 | .follow_link = page_follow_link_light, | 811 | .follow_link = f2fs_follow_link, |
| 794 | .put_link = page_put_link, | 812 | .put_link = page_put_link, |
| 795 | .getattr = f2fs_getattr, | 813 | .getattr = f2fs_getattr, |
| 796 | .setattr = f2fs_setattr, | 814 | .setattr = f2fs_setattr, |
