From 2fb1e3086df9b454538491fba8121298da37cd23 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 19 Aug 2005 22:42:16 +0100 Subject: [PATCH] jffs2: fix symlink error handling The current calling conventions for ->follow_link() are already fairly complex. What we have is 1) you can return -error; then you must release nameidata yourself and ->put_link() will _not_ be called. 2) you can do nd_set_link(nd, ERR_PTR(-error)) and return 0 3) you can do nd_set_link(nd, path) and return 0 4) you can return 0 (after having moved nameidata yourself) jffs2 follow_link() is broken - it has an exit where it returns -EIO and leaks nameidata. Signed-off-by: Linus Torvalds --- fs/jffs2/symlink.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 65ab6b001dc..073633e11ea 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -30,6 +30,7 @@ struct inode_operations jffs2_symlink_inode_operations = static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); + char *p = (char *)f->dents; /* * We don't acquire the f->sem mutex here since the only data we @@ -45,13 +46,14 @@ static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * nd_set_link() call. */ - if (!f->dents) { + if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); - return -EIO; + p = ERR_PTR(-EIO); + } else { + D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); } - D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); - nd_set_link(nd, (char *)f->dents); + nd_set_link(nd, p); /* * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe -- cgit v1.2.3 From cc314eef0128a807e50fa03baf2d0abc0647952c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 19 Aug 2005 18:02:56 -0700 Subject: 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 --- fs/autofs/symlink.c | 5 +++-- fs/cifs/cifsfs.h | 4 ++-- fs/cifs/link.c | 6 +++--- fs/ext2/symlink.c | 4 ++-- fs/ext3/symlink.c | 4 ++-- fs/namei.c | 40 +++++++++++++++++++++------------------- fs/nfs/symlink.c | 37 ++++++++----------------------------- fs/sysfs/symlink.c | 6 +++--- 8 files changed, 44 insertions(+), 62 deletions(-) (limited to 'fs') diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index f028396f138..52e8772b066 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c @@ -12,11 +12,12 @@ #include "autofs_i.h" -static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd) +/* Nothing to release.. */ +static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd) { char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; nd_set_link(nd, s); - return 0; + return NULL; } struct inode_operations autofs_symlink_inode_operations = { diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 78af5850c55..1fd21f66f24 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); extern struct dentry_operations cifs_dentry_ops; /* Functions related to symlinks */ -extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); -extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd); +extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); +extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *); extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen); extern int cifs_symlink(struct inode *inode, struct dentry *direntry, diff --git a/fs/cifs/link.c b/fs/cifs/link.c index bde0fabfece..ab925ef4f86 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -92,7 +92,7 @@ cifs_hl_exit: return rc; } -int +void * cifs_follow_link(struct dentry *direntry, struct nameidata *nd) { struct inode *inode = direntry->d_inode; @@ -148,7 +148,7 @@ out: out_no_free: FreeXid(xid); nd_set_link(nd, target_path); - return 0; + return NULL; /* No cookie */ } int @@ -330,7 +330,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) return rc; } -void cifs_put_link(struct dentry *direntry, struct nameidata *nd) +void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) { char *p = nd_get_link(nd); if (!IS_ERR(p)) diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 9f7bac01d55..1e67d87cfa9 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -21,11 +21,11 @@ #include "xattr.h" #include -static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); nd_set_link(nd, (char *)ei->i_data); - return 0; + return NULL; } struct inode_operations ext2_symlink_inode_operations = { diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c index 8c3e72818fb..4f79122cde6 100644 --- a/fs/ext3/symlink.c +++ b/fs/ext3/symlink.c @@ -23,11 +23,11 @@ #include #include "xattr.h" -static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd) +static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); nd_set_link(nd, (char*)ei->i_data); - return 0; + return NULL; } struct inode_operations ext3_symlink_inode_operations = { diff --git a/fs/namei.c b/fs/namei.c index b85f158aef0..6ec1f0fefc5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -501,6 +501,7 @@ struct path { static inline int __do_follow_link(struct path *path, struct nameidata *nd) { int error; + void *cookie; struct dentry *dentry = path->dentry; touch_atime(path->mnt, dentry); @@ -508,13 +509,15 @@ static inline int __do_follow_link(struct path *path, struct nameidata *nd) if (path->mnt == nd->mnt) mntget(path->mnt); - error = dentry->d_inode->i_op->follow_link(dentry, nd); - if (!error) { + cookie = dentry->d_inode->i_op->follow_link(dentry, nd); + error = PTR_ERR(cookie); + if (!IS_ERR(cookie)) { char *s = nd_get_link(nd); + error = 0; if (s) error = __vfs_follow_link(nd, s); if (dentry->d_inode->i_op->put_link) - dentry->d_inode->i_op->put_link(dentry, nd); + dentry->d_inode->i_op->put_link(dentry, nd, cookie); } dput(dentry); mntput(path->mnt); @@ -2344,15 +2347,17 @@ out: int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct nameidata nd; - int res; + void *cookie; + nd.depth = 0; - res = dentry->d_inode->i_op->follow_link(dentry, &nd); - if (!res) { - res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); + cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); + if (!IS_ERR(cookie)) { + int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); if (dentry->d_inode->i_op->put_link) - dentry->d_inode->i_op->put_link(dentry, &nd); + dentry->d_inode->i_op->put_link(dentry, &nd, cookie); + cookie = ERR_PTR(res); } - return res; + return PTR_ERR(cookie); } int vfs_follow_link(struct nameidata *nd, const char *link) @@ -2395,23 +2400,20 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) return res; } -int page_follow_link_light(struct dentry *dentry, struct nameidata *nd) +void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) { - struct page *page; + struct page *page = NULL; nd_set_link(nd, page_getlink(dentry, &page)); - return 0; + return page; } -void page_put_link(struct dentry *dentry, struct nameidata *nd) +void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { - if (!IS_ERR(nd_get_link(nd))) { - struct page *page; - page = find_get_page(dentry->d_inode->i_mapping, 0); - if (!page) - BUG(); + struct page *page = cookie; + + if (page) { kunmap(page); page_cache_release(page); - page_cache_release(page); } } diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 35f10659914..18dc95b0b64 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -27,26 +27,14 @@ /* Symlink caching in the page cache is even more simplistic * and straight-forward than readdir caching. - * - * At the beginning of the page we store pointer to struct page in question, - * simplifying nfs_put_link() (if inode got invalidated we can't find the page - * to be freed via pagecache lookup). - * The NUL-terminated string follows immediately thereafter. */ -struct nfs_symlink { - struct page *page; - char body[0]; -}; - static int nfs_symlink_filler(struct inode *inode, struct page *page) { - const unsigned int pgbase = offsetof(struct nfs_symlink, body); - const unsigned int pglen = PAGE_SIZE - pgbase; int error; lock_kernel(); - error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen); + error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); unlock_kernel(); if (error < 0) goto error; @@ -60,11 +48,10 @@ error: return -EIO; } -static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; struct page *page; - struct nfs_symlink *p; void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); if (err) goto read_failed; @@ -78,28 +65,20 @@ static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) err = ERR_PTR(-EIO); goto getlink_read_error; } - p = kmap(page); - p->page = page; - nd_set_link(nd, p->body); - return 0; + nd_set_link(nd, kmap(page)); + return page; getlink_read_error: page_cache_release(page); read_failed: nd_set_link(nd, err); - return 0; + return NULL; } -static void nfs_put_link(struct dentry *dentry, struct nameidata *nd) +static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { - char *s = nd_get_link(nd); - if (!IS_ERR(s)) { - struct nfs_symlink *p; - struct page *page; - - p = container_of(s, struct nfs_symlink, body[0]); - page = p->page; - + if (cookie) { + struct page *page = cookie; kunmap(page); page_cache_release(page); } diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index fae57c83a72..de402fa915f 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -151,17 +151,17 @@ static int sysfs_getlink(struct dentry *dentry, char * path) } -static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) { int error = -ENOMEM; unsigned long page = get_zeroed_page(GFP_KERNEL); if (page) error = sysfs_getlink(dentry, (char *) page); nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); - return 0; + return NULL; } -static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) +static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { char *page = nd_get_link(nd); if (!IS_ERR(page)) -- cgit v1.2.3 From 008b150a3c4d971cd65d02d107b8fcc860bc959c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 20 Aug 2005 00:17:39 +0100 Subject: [PATCH] Fix up symlink function pointers This fixes up the symlink functions for the calling convention change: * afs, autofs4, befs, devfs, freevxfs, jffs2, jfs, ncpfs, procfs, smbfs, sysvfs, ufs, xfs - prototype change for ->follow_link() * befs, smbfs, xfs - same for ->put_link() Signed-off-by: Linus Torvalds --- fs/afs/mntpt.c | 8 ++++---- fs/autofs4/symlink.c | 4 ++-- fs/befs/linuxvfs.c | 8 ++++---- fs/devfs/base.c | 4 ++-- fs/freevxfs/vxfs_immed.c | 4 ++-- fs/jffs2/symlink.c | 6 +++--- fs/jfs/symlink.c | 4 ++-- fs/proc/base.c | 8 ++++---- fs/proc/generic.c | 4 ++-- fs/smbfs/symlink.c | 6 +++--- fs/sysv/symlink.c | 4 ++-- fs/ufs/symlink.c | 4 ++-- fs/xfs/linux-2.6/xfs_iops.c | 10 +++++----- 13 files changed, 37 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index bfc28abe1cb..31ee06590de 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -30,7 +30,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); static int afs_mntpt_open(struct inode *inode, struct file *file); -static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); +static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, @@ -233,7 +233,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) /* * follow a link from a mountpoint directory, thus causing it to be mounted */ -static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) { struct vfsmount *newmnt; struct dentry *old_dentry; @@ -249,7 +249,7 @@ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) newmnt = afs_mntpt_do_automount(dentry); if (IS_ERR(newmnt)) { path_release(nd); - return PTR_ERR(newmnt); + return (void *)newmnt; } old_dentry = nd->dentry; @@ -267,7 +267,7 @@ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) } kleave(" = %d", err); - return err; + return ERR_PTR(err); } /* end afs_mntpt_follow_link() */ /*****************************************************************************/ diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index c265a66edf0..2ea2c98fd84 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -12,11 +12,11 @@ #include "autofs_i.h" -static int autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) { struct autofs_info *ino = autofs4_dentry_ino(dentry); nd_set_link(nd, (char *)ino->u.symlink); - return 0; + return NULL; } struct inode_operations autofs4_symlink_inode_operations = { diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index de5bb280a82..abf950e5b64 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -41,8 +41,8 @@ static struct inode *befs_alloc_inode(struct super_block *sb); static void befs_destroy_inode(struct inode *inode); static int befs_init_inodecache(void); static void befs_destroy_inodecache(void); -static int befs_follow_link(struct dentry *, struct nameidata *); -static void befs_put_link(struct dentry *, struct nameidata *); +static void *befs_follow_link(struct dentry *, struct nameidata *); +static void befs_put_link(struct dentry *, struct nameidata *, void *); static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, char **out, int *out_len); static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, @@ -487,10 +487,10 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) } nd_set_link(nd, link); - return 0; + return NULL; } -static void befs_put_link(struct dentry *dentry, struct nameidata *nd) +static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 1ecfe1f184d..8b679b67e5e 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2491,11 +2491,11 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, return 0; } /* End Function devfs_mknod */ -static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode); nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV)); - return 0; + return NULL; } /* End Function devfs_follow_link */ static struct inode_operations devfs_iops = { diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c index ac677ab262b..b20c3efa364 100644 --- a/fs/freevxfs/vxfs_immed.c +++ b/fs/freevxfs/vxfs_immed.c @@ -38,7 +38,7 @@ #include "vxfs_inode.h" -static int vxfs_immed_follow_link(struct dentry *, struct nameidata *); +static void * vxfs_immed_follow_link(struct dentry *, struct nameidata *); static int vxfs_immed_readpage(struct file *, struct page *); @@ -77,7 +77,7 @@ vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) { struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); nd_set_link(np, vip->vii_immed.vi_immed); - return 0; + return NULL; } /** diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 073633e11ea..82ef484f5e1 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -18,7 +18,7 @@ #include #include "nodelist.h" -static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); +static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); struct inode_operations jffs2_symlink_inode_operations = { @@ -27,7 +27,7 @@ struct inode_operations jffs2_symlink_inode_operations = .setattr = jffs2_setattr }; -static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); char *p = (char *)f->dents; @@ -60,6 +60,6 @@ static int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * since the only way that may cause f->dents to be changed is iput() operation. * But VFS will not use f->dents after iput() has been called. */ - return 0; + return NULL; } diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index 287d8d6c3cf..16477b3835e 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c @@ -22,11 +22,11 @@ #include "jfs_inode.h" #include "jfs_xattr.h" -static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd) { char *s = JFS_IP(dentry->d_inode)->i_inline; nd_set_link(nd, s); - return 0; + return NULL; } struct inode_operations jfs_symlink_inode_operations = { diff --git a/fs/proc/base.c b/fs/proc/base.c index ace151fa487..491f2d9f89a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -890,7 +890,7 @@ static struct file_operations proc_seccomp_operations = { }; #endif /* CONFIG_SECCOMP */ -static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; int error = -EACCES; @@ -907,7 +907,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; out: - return error; + return ERR_PTR(error); } static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, @@ -1692,11 +1692,11 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, return vfs_readlink(dentry,buffer,buflen,tmp); } -static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) { char tmp[30]; sprintf(tmp, "%d", current->tgid); - return vfs_follow_link(nd,tmp); + return ERR_PTR(vfs_follow_link(nd,tmp)); } static struct inode_operations proc_self_inode_operations = { diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 6c6315d0402..abe8920313f 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -329,10 +329,10 @@ static void release_inode_number(unsigned int inum) spin_unlock(&proc_inum_lock); } -static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, PDE(dentry->d_inode)->data); - return 0; + return NULL; } static struct inode_operations proc_link_inode_operations = { diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c index 8b069e06433..0c64bc3a012 100644 --- a/fs/smbfs/symlink.c +++ b/fs/smbfs/symlink.c @@ -34,7 +34,7 @@ int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname) return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname); } -static int smb_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd) { char *link = __getname(); DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry)); @@ -52,10 +52,10 @@ static int smb_follow_link(struct dentry *dentry, struct nameidata *nd) } } nd_set_link(nd, link); - return 0; + return NULL; } -static void smb_put_link(struct dentry *dentry, struct nameidata *nd) +static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { char *s = nd_get_link(nd); if (!IS_ERR(s)) diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c index ed637db2dcb..b85ce61d635 100644 --- a/fs/sysv/symlink.c +++ b/fs/sysv/symlink.c @@ -8,10 +8,10 @@ #include "sysv.h" #include -static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd) { nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data); - return 0; + return NULL; } struct inode_operations sysv_fast_symlink_inode_operations = { diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index a0e49149098..337512ed578 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -29,11 +29,11 @@ #include #include -static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct ufs_inode_info *p = UFS_I(dentry->d_inode); nd_set_link(nd, (char*)p->i_u1.i_symlink); - return 0; + return NULL; } struct inode_operations ufs_fast_symlink_inode_operations = { diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 407e9935939..f252605514e 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -374,7 +374,7 @@ linvfs_rename( * we need to be very careful about how much stack we use. * uio is kmalloced for this reason... */ -STATIC int +STATIC void * linvfs_follow_link( struct dentry *dentry, struct nameidata *nd) @@ -391,14 +391,14 @@ linvfs_follow_link( link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL); if (!link) { nd_set_link(nd, ERR_PTR(-ENOMEM)); - return 0; + return NULL; } uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL); if (!uio) { kfree(link); nd_set_link(nd, ERR_PTR(-ENOMEM)); - return 0; + return NULL; } vp = LINVFS_GET_VP(dentry->d_inode); @@ -422,10 +422,10 @@ linvfs_follow_link( kfree(uio); nd_set_link(nd, link); - return 0; + return NULL; } -static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd) +static void linvfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { char *s = nd_get_link(nd); if (!IS_ERR(s)) -- cgit v1.2.3 From 01c314a0c0f6367960a7cb1ffb5796560ccaa1c1 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Fri, 19 Aug 2005 17:57:48 -0700 Subject: [PATCH] NFSv4: unbalanced BKL in nfs_atomic_lookup() Added missing unlock_kernel() to NFSv4 atomic lookup. Signed-off-by: Steve Dickson Signed-off-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfs/dir.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 147cbf9261c..2df639f143e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -939,6 +939,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry error = nfs_revalidate_inode(NFS_SERVER(dir), dir); if (error < 0) { res = ERR_PTR(error); + unlock_kernel(); goto out; } -- cgit v1.2.3 From db873896d168217e213902c7163fda7ee798781b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 20 Aug 2005 13:20:01 -0700 Subject: befs: fix up missed follow_link declaration change We'd updated the prototype and the return value, but not the function declaration itself. --- fs/befs/linuxvfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index abf950e5b64..e0a6025f1d0 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -461,7 +461,7 @@ befs_destroy_inodecache(void) * The data stream become link name. Unless the LONG_SYMLINK * flag is set. */ -static int +static void * befs_follow_link(struct dentry *dentry, struct nameidata *nd) { befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); -- cgit v1.2.3 From a5ea169c9581553662bb79a1c8c98fed1ee84246 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 21 Aug 2005 01:08:36 +0400 Subject: [PATCH] freevxfs: fix breakage introduced by symlink fixes Signed-off-by: Alexey Dobriyan Signed-off-by: Linus Torvalds --- fs/freevxfs/vxfs_immed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c index b20c3efa364..d0401dc68d4 100644 --- a/fs/freevxfs/vxfs_immed.c +++ b/fs/freevxfs/vxfs_immed.c @@ -72,7 +72,7 @@ struct address_space_operations vxfs_immed_aops = { * Returns: * Zero on success, else a negative error code. */ -static int +static void * vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) { struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); -- cgit v1.2.3 From f6fdd7d9c273bb2a20ab467cb57067494f932fa3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 20 Aug 2005 18:51:29 -0700 Subject: Don't allow normal users to set idle IO priority It has all the normal priority inversion problems. Signed-off-by: Linus Torvalds --- fs/ioprio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/ioprio.c b/fs/ioprio.c index 97e1f088ba0..d1c1f2b2c9d 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -62,6 +62,8 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) break; case IOPRIO_CLASS_IDLE: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; break; default: return -EINVAL; -- cgit v1.2.3