Fix nasty ncpfs symlink handling bug.

This bug could cause oopses and page state corruption, because ncpfs
used the generic page-cache symlink handlign functions. But those
functions only work if the page cache is guaranteed to be "stable", ie a
page that was installed when the symlink walk was started has to still
be installed in the page cache at the end of the walk.

We could have fixed ncpfs to not use the generic helper routines, but it
is in many ways much cleaner to instead improve on the symlink walking
helper routines so that they don't require that absolute stability.

We do this by allowing "follow_link()" to return a error-pointer as a
cookie, which is fed back to the cleanup "put_link()" routine. This
also simplifies NFS symlink handling.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>

+54 -77
+3 -2
fs/autofs/symlink.c
··· 12 13 #include "autofs_i.h" 14 15 - static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd) 16 { 17 char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; 18 nd_set_link(nd, s); 19 - return 0; 20 } 21 22 struct inode_operations autofs_symlink_inode_operations = {
··· 12 13 #include "autofs_i.h" 14 15 + /* Nothing to release.. */ 16 + static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd) 17 { 18 char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; 19 nd_set_link(nd, s); 20 + return NULL; 21 } 22 23 struct inode_operations autofs_symlink_inode_operations = {
+2 -2
fs/cifs/cifsfs.h
··· 83 extern struct dentry_operations cifs_dentry_ops; 84 85 /* Functions related to symlinks */ 86 - extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 87 - extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd); 88 extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 89 int buflen); 90 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
··· 83 extern struct dentry_operations cifs_dentry_ops; 84 85 /* Functions related to symlinks */ 86 + extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 87 + extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *); 88 extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 89 int buflen); 90 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
+3 -3
fs/cifs/link.c
··· 92 return rc; 93 } 94 95 - int 96 cifs_follow_link(struct dentry *direntry, struct nameidata *nd) 97 { 98 struct inode *inode = direntry->d_inode; ··· 148 out_no_free: 149 FreeXid(xid); 150 nd_set_link(nd, target_path); 151 - return 0; 152 } 153 154 int ··· 330 return rc; 331 } 332 333 - void cifs_put_link(struct dentry *direntry, struct nameidata *nd) 334 { 335 char *p = nd_get_link(nd); 336 if (!IS_ERR(p))
··· 92 return rc; 93 } 94 95 + void * 96 cifs_follow_link(struct dentry *direntry, struct nameidata *nd) 97 { 98 struct inode *inode = direntry->d_inode; ··· 148 out_no_free: 149 FreeXid(xid); 150 nd_set_link(nd, target_path); 151 + return NULL; /* No cookie */ 152 } 153 154 int ··· 330 return rc; 331 } 332 333 + void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) 334 { 335 char *p = nd_get_link(nd); 336 if (!IS_ERR(p))
+2 -2
fs/ext2/symlink.c
··· 21 #include "xattr.h" 22 #include <linux/namei.h> 23 24 - static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd) 25 { 26 struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); 27 nd_set_link(nd, (char *)ei->i_data); 28 - return 0; 29 } 30 31 struct inode_operations ext2_symlink_inode_operations = {
··· 21 #include "xattr.h" 22 #include <linux/namei.h> 23 24 + static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) 25 { 26 struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); 27 nd_set_link(nd, (char *)ei->i_data); 28 + return NULL; 29 } 30 31 struct inode_operations ext2_symlink_inode_operations = {
+2 -2
fs/ext3/symlink.c
··· 23 #include <linux/namei.h> 24 #include "xattr.h" 25 26 - static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd) 27 { 28 struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); 29 nd_set_link(nd, (char*)ei->i_data); 30 - return 0; 31 } 32 33 struct inode_operations ext3_symlink_inode_operations = {
··· 23 #include <linux/namei.h> 24 #include "xattr.h" 25 26 + static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd) 27 { 28 struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); 29 nd_set_link(nd, (char*)ei->i_data); 30 + return NULL; 31 } 32 33 struct inode_operations ext3_symlink_inode_operations = {
+21 -19
fs/namei.c
··· 501 static inline int __do_follow_link(struct path *path, struct nameidata *nd) 502 { 503 int error; 504 struct dentry *dentry = path->dentry; 505 506 touch_atime(path->mnt, dentry); ··· 509 510 if (path->mnt == nd->mnt) 511 mntget(path->mnt); 512 - error = dentry->d_inode->i_op->follow_link(dentry, nd); 513 - if (!error) { 514 char *s = nd_get_link(nd); 515 if (s) 516 error = __vfs_follow_link(nd, s); 517 if (dentry->d_inode->i_op->put_link) 518 - dentry->d_inode->i_op->put_link(dentry, nd); 519 } 520 dput(dentry); 521 mntput(path->mnt); ··· 2347 int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) 2348 { 2349 struct nameidata nd; 2350 - int res; 2351 nd.depth = 0; 2352 - res = dentry->d_inode->i_op->follow_link(dentry, &nd); 2353 - if (!res) { 2354 - res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 2355 if (dentry->d_inode->i_op->put_link) 2356 - dentry->d_inode->i_op->put_link(dentry, &nd); 2357 } 2358 - return res; 2359 } 2360 2361 int vfs_follow_link(struct nameidata *nd, const char *link) ··· 2400 return res; 2401 } 2402 2403 - int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) 2404 { 2405 - struct page *page; 2406 nd_set_link(nd, page_getlink(dentry, &page)); 2407 - return 0; 2408 } 2409 2410 - void page_put_link(struct dentry *dentry, struct nameidata *nd) 2411 { 2412 - if (!IS_ERR(nd_get_link(nd))) { 2413 - struct page *page; 2414 - page = find_get_page(dentry->d_inode->i_mapping, 0); 2415 - if (!page) 2416 - BUG(); 2417 kunmap(page); 2418 - page_cache_release(page); 2419 page_cache_release(page); 2420 } 2421 }
··· 501 static inline int __do_follow_link(struct path *path, struct nameidata *nd) 502 { 503 int error; 504 + void *cookie; 505 struct dentry *dentry = path->dentry; 506 507 touch_atime(path->mnt, dentry); ··· 508 509 if (path->mnt == nd->mnt) 510 mntget(path->mnt); 511 + cookie = dentry->d_inode->i_op->follow_link(dentry, nd); 512 + error = PTR_ERR(cookie); 513 + if (!IS_ERR(cookie)) { 514 char *s = nd_get_link(nd); 515 + error = 0; 516 if (s) 517 error = __vfs_follow_link(nd, s); 518 if (dentry->d_inode->i_op->put_link) 519 + dentry->d_inode->i_op->put_link(dentry, nd, cookie); 520 } 521 dput(dentry); 522 mntput(path->mnt); ··· 2344 int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) 2345 { 2346 struct nameidata nd; 2347 + void *cookie; 2348 + 2349 nd.depth = 0; 2350 + cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); 2351 + if (!IS_ERR(cookie)) { 2352 + int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 2353 if (dentry->d_inode->i_op->put_link) 2354 + dentry->d_inode->i_op->put_link(dentry, &nd, cookie); 2355 + cookie = ERR_PTR(res); 2356 } 2357 + return PTR_ERR(cookie); 2358 } 2359 2360 int vfs_follow_link(struct nameidata *nd, const char *link) ··· 2395 return res; 2396 } 2397 2398 + void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) 2399 { 2400 + struct page *page = NULL; 2401 nd_set_link(nd, page_getlink(dentry, &page)); 2402 + return page; 2403 } 2404 2405 + void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 2406 { 2407 + struct page *page = cookie; 2408 + 2409 + if (page) { 2410 kunmap(page); 2411 page_cache_release(page); 2412 } 2413 }
+8 -29
fs/nfs/symlink.c
··· 27 28 /* Symlink caching in the page cache is even more simplistic 29 * and straight-forward than readdir caching. 30 - * 31 - * At the beginning of the page we store pointer to struct page in question, 32 - * simplifying nfs_put_link() (if inode got invalidated we can't find the page 33 - * to be freed via pagecache lookup). 34 - * The NUL-terminated string follows immediately thereafter. 35 */ 36 - 37 - struct nfs_symlink { 38 - struct page *page; 39 - char body[0]; 40 - }; 41 42 static int nfs_symlink_filler(struct inode *inode, struct page *page) 43 { 44 - const unsigned int pgbase = offsetof(struct nfs_symlink, body); 45 - const unsigned int pglen = PAGE_SIZE - pgbase; 46 int error; 47 48 lock_kernel(); 49 - error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen); 50 unlock_kernel(); 51 if (error < 0) 52 goto error; ··· 48 return -EIO; 49 } 50 51 - static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) 52 { 53 struct inode *inode = dentry->d_inode; 54 struct page *page; 55 - struct nfs_symlink *p; 56 void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); 57 if (err) 58 goto read_failed; ··· 65 err = ERR_PTR(-EIO); 66 goto getlink_read_error; 67 } 68 - p = kmap(page); 69 - p->page = page; 70 - nd_set_link(nd, p->body); 71 - return 0; 72 73 getlink_read_error: 74 page_cache_release(page); 75 read_failed: 76 nd_set_link(nd, err); 77 - return 0; 78 } 79 80 - static void nfs_put_link(struct dentry *dentry, struct nameidata *nd) 81 { 82 - char *s = nd_get_link(nd); 83 - if (!IS_ERR(s)) { 84 - struct nfs_symlink *p; 85 - struct page *page; 86 - 87 - p = container_of(s, struct nfs_symlink, body[0]); 88 - page = p->page; 89 - 90 kunmap(page); 91 page_cache_release(page); 92 }
··· 27 28 /* Symlink caching in the page cache is even more simplistic 29 * and straight-forward than readdir caching. 30 */ 31 32 static int nfs_symlink_filler(struct inode *inode, struct page *page) 33 { 34 int error; 35 36 lock_kernel(); 37 + error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); 38 unlock_kernel(); 39 if (error < 0) 40 goto error; ··· 60 return -EIO; 61 } 62 63 + static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) 64 { 65 struct inode *inode = dentry->d_inode; 66 struct page *page; 67 void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); 68 if (err) 69 goto read_failed; ··· 78 err = ERR_PTR(-EIO); 79 goto getlink_read_error; 80 } 81 + nd_set_link(nd, kmap(page)); 82 + return page; 83 84 getlink_read_error: 85 page_cache_release(page); 86 read_failed: 87 nd_set_link(nd, err); 88 + return NULL; 89 } 90 91 + static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 92 { 93 + if (cookie) { 94 + struct page *page = cookie; 95 kunmap(page); 96 page_cache_release(page); 97 }
+3 -3
fs/sysfs/symlink.c
··· 151 152 } 153 154 - static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) 155 { 156 int error = -ENOMEM; 157 unsigned long page = get_zeroed_page(GFP_KERNEL); 158 if (page) 159 error = sysfs_getlink(dentry, (char *) page); 160 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); 161 - return 0; 162 } 163 164 - static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) 165 { 166 char *page = nd_get_link(nd); 167 if (!IS_ERR(page))
··· 151 152 } 153 154 + static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) 155 { 156 int error = -ENOMEM; 157 unsigned long page = get_zeroed_page(GFP_KERNEL); 158 if (page) 159 error = sysfs_getlink(dentry, (char *) page); 160 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); 161 + return NULL; 162 } 163 164 + static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 165 { 166 char *page = nd_get_link(nd); 167 if (!IS_ERR(page))
+4 -4
include/linux/fs.h
··· 993 int (*rename) (struct inode *, struct dentry *, 994 struct inode *, struct dentry *); 995 int (*readlink) (struct dentry *, char __user *,int); 996 - int (*follow_link) (struct dentry *, struct nameidata *); 997 - void (*put_link) (struct dentry *, struct nameidata *); 998 void (*truncate) (struct inode *); 999 int (*permission) (struct inode *, int, struct nameidata *); 1000 int (*setattr) (struct dentry *, struct iattr *); ··· 1602 extern int vfs_readlink(struct dentry *, char __user *, int, const char *); 1603 extern int vfs_follow_link(struct nameidata *, const char *); 1604 extern int page_readlink(struct dentry *, char __user *, int); 1605 - extern int page_follow_link_light(struct dentry *, struct nameidata *); 1606 - extern void page_put_link(struct dentry *, struct nameidata *); 1607 extern int page_symlink(struct inode *inode, const char *symname, int len); 1608 extern struct inode_operations page_symlink_inode_operations; 1609 extern int generic_readlink(struct dentry *, char __user *, int);
··· 993 int (*rename) (struct inode *, struct dentry *, 994 struct inode *, struct dentry *); 995 int (*readlink) (struct dentry *, char __user *,int); 996 + void * (*follow_link) (struct dentry *, struct nameidata *); 997 + void (*put_link) (struct dentry *, struct nameidata *, void *); 998 void (*truncate) (struct inode *); 999 int (*permission) (struct inode *, int, struct nameidata *); 1000 int (*setattr) (struct dentry *, struct iattr *); ··· 1602 extern int vfs_readlink(struct dentry *, char __user *, int, const char *); 1603 extern int vfs_follow_link(struct nameidata *, const char *); 1604 extern int page_readlink(struct dentry *, char __user *, int); 1605 + extern void *page_follow_link_light(struct dentry *, struct nameidata *); 1606 + extern void page_put_link(struct dentry *, struct nameidata *, void *); 1607 extern int page_symlink(struct inode *inode, const char *symname, int len); 1608 extern struct inode_operations page_symlink_inode_operations; 1609 extern int generic_readlink(struct dentry *, char __user *, int);
+6 -11
mm/shmem.c
··· 1773 return 0; 1774 } 1775 1776 - static int shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) 1777 { 1778 nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode)); 1779 - return 0; 1780 } 1781 1782 - static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd) 1783 { 1784 struct page *page = NULL; 1785 int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL); 1786 nd_set_link(nd, res ? ERR_PTR(res) : kmap(page)); 1787 - return 0; 1788 } 1789 1790 - static void shmem_put_link(struct dentry *dentry, struct nameidata *nd) 1791 { 1792 if (!IS_ERR(nd_get_link(nd))) { 1793 - struct page *page; 1794 - 1795 - page = find_get_page(dentry->d_inode->i_mapping, 0); 1796 - if (!page) 1797 - BUG(); 1798 kunmap(page); 1799 mark_page_accessed(page); 1800 - page_cache_release(page); 1801 page_cache_release(page); 1802 } 1803 }
··· 1773 return 0; 1774 } 1775 1776 + static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) 1777 { 1778 nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode)); 1779 + return NULL; 1780 } 1781 1782 + static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd) 1783 { 1784 struct page *page = NULL; 1785 int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL); 1786 nd_set_link(nd, res ? ERR_PTR(res) : kmap(page)); 1787 + return page; 1788 } 1789 1790 + static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 1791 { 1792 if (!IS_ERR(nd_get_link(nd))) { 1793 + struct page *page = cookie; 1794 kunmap(page); 1795 mark_page_accessed(page); 1796 page_cache_release(page); 1797 } 1798 }