fix vfsmount leak bug in fuse_follow_link

This commit is contained in:
Miklos Szeredi 2001-11-13 16:11:35 +00:00
parent 0a7077f536
commit 0503304128
5 changed files with 26 additions and 27 deletions

View File

@ -30,6 +30,11 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t, const char *, int type);
* - All operations should return the negated error value (-errno) on
* error.
*
* - Getattr() doesn't need to fill in the following fields:
* st_ino
* st_dev
* st_blksize
*
* - readlink() should fill the buffer with a null terminated string. The
* buffer size argument includes the space for the terminating null
* character. If the linkname is too long to fit in the buffer, it should

View File

@ -42,7 +42,7 @@ struct fuse_attr {
unsigned int gid;
unsigned int rdev;
unsigned long long size;
unsigned long blksize;
unsigned long _dummy;
unsigned long blocks;
unsigned long atime;
unsigned long mtime;

View File

@ -8,6 +8,7 @@
#include "fuse_i.h"
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/file.h>
@ -32,7 +33,7 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
inode->i_uid = attr->uid;
inode->i_gid = attr->gid;
inode->i_size = attr->size;
inode->i_blksize = attr->blksize;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = attr->blocks;
inode->i_atime = attr->atime;
inode->i_mtime = attr->mtime;
@ -385,37 +386,37 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
return ret;
}
static int read_link(struct dentry *dentry, char **bufp)
static char *read_link(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct fuse_conn *fc = INO_FC(inode);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
unsigned long page;
char *link;
page = __get_free_page(GFP_KERNEL);
if(!page)
return -ENOMEM;
link = (char *) __get_free_page(GFP_KERNEL);
if(!link)
return ERR_PTR(-ENOMEM);
in.h.opcode = FUSE_READLINK;
in.h.ino = inode->i_ino;
out.arg = (void *) page;
out.arg = link;
out.argsize = PAGE_SIZE - 1;
out.argvar = 1;
request_send(fc, &in, &out);
if(out.h.error) {
free_page(page);
return out.h.error;
free_page((unsigned long) link);
return ERR_PTR(out.h.error);
}
*bufp = (char *) page;
(*bufp)[out.argsize] = '\0';
return 0;
link[out.argsize] = '\0';
return link;
}
static void free_link(char *link)
{
free_page((unsigned long) link);
if(!IS_ERR(link))
free_page((unsigned long) link);
}
static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
@ -423,10 +424,7 @@ static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
int ret;
char *link;
ret = read_link(dentry, &link);
if(ret)
return ret;
link = read_link(dentry);
ret = vfs_readlink(dentry, buffer, buflen, link);
free_link(link);
return ret;
@ -437,10 +435,7 @@ static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
int ret;
char *link;
ret = read_link(dentry, &link);
if(ret)
return ret;
link = read_link(dentry);
ret = vfs_follow_link(nd, link);
free_link(link);
return ret;
@ -550,8 +545,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, int flags)
{
if(!entry->d_inode)
return 0;
else if(!(flags & LOOKUP_CONTINUE) &&
time_after(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
else if(!(flags & LOOKUP_CONTINUE))
return 0;
else
return 1;

View File

@ -8,6 +8,7 @@
#include "fuse_i.h"
#include <linux/pagemap.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/file.h>
@ -104,8 +105,8 @@ static struct super_block *fuse_read_super(struct super_block *sb,
struct inode *root;
struct fuse_mount_data *d = data;
sb->s_blocksize = 1024;
sb->s_blocksize_bits = 10;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = FUSE_SUPER_MAGIC;
sb->s_op = &fuse_super_operations;

View File

@ -297,7 +297,6 @@ static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
attr->gid = stbuf->st_gid;
attr->rdev = stbuf->st_rdev;
attr->size = stbuf->st_size;
attr->blksize = stbuf->st_blksize;
attr->blocks = stbuf->st_blocks;
attr->atime = stbuf->st_atime;
attr->mtime = stbuf->st_mtime;