aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-08-19 21:02:56 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-19 21:02:56 -0400
commitcc314eef0128a807e50fa03baf2d0abc0647952c (patch)
tree8e38db1be28006894915273b3f3cb3beaa6efda3 /fs/cifs
parent2fb1e3086df9b454538491fba8121298da37cd23 (diff)
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/link.c6
2 files changed, 5 insertions, 5 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 78af5850c558..1fd21f66f243 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -83,8 +83,8 @@ extern int cifs_dir_notify(struct file *, unsigned long arg);
83extern struct dentry_operations cifs_dentry_ops; 83extern struct dentry_operations cifs_dentry_ops;
84 84
85/* Functions related to symlinks */ 85/* Functions related to symlinks */
86extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 86extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
87extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd); 87extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
88extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 88extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
89 int buflen); 89 int buflen);
90extern int cifs_symlink(struct inode *inode, struct dentry *direntry, 90extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index bde0fabfece0..ab925ef4f863 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -92,7 +92,7 @@ cifs_hl_exit:
92 return rc; 92 return rc;
93} 93}
94 94
95int 95void *
96cifs_follow_link(struct dentry *direntry, struct nameidata *nd) 96cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
97{ 97{
98 struct inode *inode = direntry->d_inode; 98 struct inode *inode = direntry->d_inode;
@@ -148,7 +148,7 @@ out:
148out_no_free: 148out_no_free:
149 FreeXid(xid); 149 FreeXid(xid);
150 nd_set_link(nd, target_path); 150 nd_set_link(nd, target_path);
151 return 0; 151 return NULL; /* No cookie */
152} 152}
153 153
154int 154int
@@ -330,7 +330,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
330 return rc; 330 return rc;
331} 331}
332 332
333void cifs_put_link(struct dentry *direntry, struct nameidata *nd) 333void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
334{ 334{
335 char *p = nd_get_link(nd); 335 char *p = nd_get_link(nd);
336 if (!IS_ERR(p)) 336 if (!IS_ERR(p))