Commit ffc9a3c3 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] symlink 3/9: trivial filesystems

trivial cases - ones where we have no need to clean up after pathname
traversal (link body embedded into inode, etc.).

Plugged leak in devfs_follow_link(), while we are at it.
parent 6143b9ad
...@@ -12,19 +12,14 @@ ...@@ -12,19 +12,14 @@
#include "autofs_i.h" #include "autofs_i.h"
static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
return vfs_readlink(dentry, buffer, buflen, s);
}
static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd) static int autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
return vfs_follow_link(nd, s); nd_set_link(nd, s);
return 0;
} }
struct inode_operations autofs_symlink_inode_operations = { struct inode_operations autofs_symlink_inode_operations = {
.readlink = autofs_readlink, .readlink = generic_readlink,
.follow_link = autofs_follow_link .follow_link = autofs_follow_link
}; };
...@@ -12,21 +12,14 @@ ...@@ -12,21 +12,14 @@
#include "autofs_i.h" #include "autofs_i.h"
static int autofs4_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct autofs_info *ino = autofs4_dentry_ino(dentry);
return vfs_readlink(dentry, buffer, buflen, ino->u.symlink);
}
static int autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) static int autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
struct autofs_info *ino = autofs4_dentry_ino(dentry); struct autofs_info *ino = autofs4_dentry_ino(dentry);
nd_set_link(nd, (char *)ino->u.symlink);
return vfs_follow_link(nd, ino->u.symlink); return 0;
} }
struct inode_operations autofs4_symlink_inode_operations = { struct inode_operations autofs4_symlink_inode_operations = {
.readlink = autofs4_readlink, .readlink = generic_readlink,
.follow_link = autofs4_follow_link .follow_link = autofs4_follow_link
}; };
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/namei.h>
/* /*
* The follow_link operation is special: it must behave as a no-op * The follow_link operation is special: it must behave as a no-op
...@@ -21,7 +22,8 @@ ...@@ -21,7 +22,8 @@
*/ */
static int bad_follow_link(struct dentry *dent, struct nameidata *nd) static int bad_follow_link(struct dentry *dent, struct nameidata *nd)
{ {
return vfs_follow_link(nd, ERR_PTR(-EIO)); nd_set_link(nd, ERR_PTR(-EIO));
return 0;
} }
static int return_EIO(void) static int return_EIO(void)
......
...@@ -2490,29 +2490,11 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, ...@@ -2490,29 +2490,11 @@ static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
return 0; return 0;
} /* End Function devfs_mknod */ } /* End Function devfs_mknod */
static int devfs_readlink(struct dentry *dentry, char __user *buffer,
int buflen)
{
int err;
struct devfs_entry *de;
de = get_devfs_entry_from_vfs_inode(dentry->d_inode);
if (!de)
return -ENODEV;
err = vfs_readlink(dentry, buffer, buflen, de->u.symlink.linkname);
return err;
} /* End Function devfs_readlink */
static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd) static int devfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
int err; struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode);
struct devfs_entry *de; nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV));
return 0;
de = get_devfs_entry_from_vfs_inode(dentry->d_inode);
if (!de)
return -ENODEV;
err = vfs_follow_link(nd, de->u.symlink.linkname);
return err;
} /* End Function devfs_follow_link */ } /* End Function devfs_follow_link */
static struct inode_operations devfs_iops = { static struct inode_operations devfs_iops = {
...@@ -2530,7 +2512,7 @@ static struct inode_operations devfs_dir_iops = { ...@@ -2530,7 +2512,7 @@ static struct inode_operations devfs_dir_iops = {
}; };
static struct inode_operations devfs_symlink_iops = { static struct inode_operations devfs_symlink_iops = {
.readlink = devfs_readlink, .readlink = generic_readlink,
.follow_link = devfs_follow_link, .follow_link = devfs_follow_link,
.setattr = devfs_notify_change, .setattr = devfs_notify_change,
}; };
......
...@@ -32,12 +32,12 @@ ...@@ -32,12 +32,12 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/namei.h>
#include "vxfs.h" #include "vxfs.h"
#include "vxfs_inode.h" #include "vxfs_inode.h"
static int vxfs_immed_readlink(struct dentry *, char __user *, int);
static int vxfs_immed_follow_link(struct dentry *, struct nameidata *); static int vxfs_immed_follow_link(struct dentry *, struct nameidata *);
static int vxfs_immed_readpage(struct file *, struct page *); static int vxfs_immed_readpage(struct file *, struct page *);
...@@ -49,7 +49,7 @@ static int vxfs_immed_readpage(struct file *, struct page *); ...@@ -49,7 +49,7 @@ static int vxfs_immed_readpage(struct file *, struct page *);
* but do all work directly on the inode. * but do all work directly on the inode.
*/ */
struct inode_operations vxfs_immed_symlink_iops = { struct inode_operations vxfs_immed_symlink_iops = {
.readlink = vxfs_immed_readlink, .readlink = generic_readlink,
.follow_link = vxfs_immed_follow_link, .follow_link = vxfs_immed_follow_link,
}; };
...@@ -60,28 +60,6 @@ struct address_space_operations vxfs_immed_aops = { ...@@ -60,28 +60,6 @@ struct address_space_operations vxfs_immed_aops = {
.readpage = vxfs_immed_readpage, .readpage = vxfs_immed_readpage,
}; };
/**
* vxfs_immed_readlink - read immed symlink
* @dp: dentry for the link
* @bp: output buffer
* @buflen: length of @bp
*
* Description:
* vxfs_immed_readlink calls vfs_readlink to read the link
* described by @dp into userspace.
*
* Returns:
* Number of bytes successfully copied to userspace.
*/
static int
vxfs_immed_readlink(struct dentry *dp, char __user *bp, int buflen)
{
struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode);
return (vfs_readlink(dp, bp, buflen, vip->vii_immed.vi_immed));
}
/** /**
* vxfs_immed_follow_link - follow immed symlink * vxfs_immed_follow_link - follow immed symlink
* @dp: dentry for the link * @dp: dentry for the link
...@@ -98,8 +76,8 @@ static int ...@@ -98,8 +76,8 @@ static int
vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np) vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
{ {
struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode); struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode);
nd_set_link(np, vip->vii_immed.vi_immed);
return (vfs_follow_link(np, vip->vii_immed.vi_immed)); return 0;
} }
/** /**
......
...@@ -17,23 +17,19 @@ ...@@ -17,23 +17,19 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_xattr.h" #include "jfs_xattr.h"
static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd) static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *s = JFS_IP(dentry->d_inode)->i_inline; char *s = JFS_IP(dentry->d_inode)->i_inline;
return vfs_follow_link(nd, s); nd_set_link(nd, s);
} return 0;
static int jfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
char *s = JFS_IP(dentry->d_inode)->i_inline;
return vfs_readlink(dentry, buffer, buflen, s);
} }
struct inode_operations jfs_symlink_inode_operations = { struct inode_operations jfs_symlink_inode_operations = {
.readlink = jfs_readlink, .readlink = generic_readlink,
.follow_link = jfs_follow_link, .follow_link = jfs_follow_link,
.setxattr = jfs_setxattr, .setxattr = jfs_setxattr,
.getxattr = jfs_getxattr, .getxattr = jfs_getxattr,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/namei.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -321,21 +322,14 @@ static void release_inode_number(unsigned int inum) ...@@ -321,21 +322,14 @@ static void release_inode_number(unsigned int inum)
spin_unlock(&proc_inum_lock); spin_unlock(&proc_inum_lock);
} }
static int
proc_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
char *s = PDE(dentry->d_inode)->data;
return vfs_readlink(dentry, buffer, buflen, s);
}
static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) static int proc_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *s = PDE(dentry->d_inode)->data; nd_set_link(nd, PDE(dentry->d_inode)->data);
return vfs_follow_link(nd, s); return 0;
} }
static struct inode_operations proc_link_inode_operations = { static struct inode_operations proc_link_inode_operations = {
.readlink = proc_readlink, .readlink = generic_readlink,
.follow_link = proc_follow_link, .follow_link = proc_follow_link,
}; };
......
...@@ -6,20 +6,15 @@ ...@@ -6,20 +6,15 @@
*/ */
#include "sysv.h" #include "sysv.h"
#include <linux/namei.h>
static int sysv_readlink(struct dentry *dentry, char *buffer, int buflen)
{
char *s = (char *)SYSV_I(dentry->d_inode)->i_data;
return vfs_readlink(dentry, buffer, buflen, s);
}
static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd) static int sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
char *s = (char *)SYSV_I(dentry->d_inode)->i_data; nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data);
return vfs_follow_link(nd, s); return 0;
} }
struct inode_operations sysv_fast_symlink_inode_operations = { struct inode_operations sysv_fast_symlink_inode_operations = {
.readlink = sysv_readlink, .readlink = generic_readlink,
.follow_link = sysv_follow_link, .follow_link = sysv_follow_link,
}; };
...@@ -26,21 +26,17 @@ ...@@ -26,21 +26,17 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h>
#include <linux/ufs_fs.h> #include <linux/ufs_fs.h>
static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct ufs_inode_info *p = UFS_I(dentry->d_inode);
return vfs_readlink(dentry, buffer, buflen, (char*)p->i_u1.i_symlink);
}
static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd) static int ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
{ {
struct ufs_inode_info *p = UFS_I(dentry->d_inode); struct ufs_inode_info *p = UFS_I(dentry->d_inode);
return vfs_follow_link(nd, (char*)p->i_u1.i_symlink); nd_set_link(nd, (char*)p->i_u1.i_symlink);
return 0;
} }
struct inode_operations ufs_fast_symlink_inode_operations = { struct inode_operations ufs_fast_symlink_inode_operations = {
.readlink = ufs_readlink, .readlink = generic_readlink,
.follow_link = ufs_follow_link, .follow_link = ufs_follow_link,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment