mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-24 20:54:16 +08:00
fix vfsmount leak bug in fuse_follow_link
This commit is contained in:
parent
0a7077f536
commit
0503304128
@ -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
|
||||
|
@ -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;
|
||||
|
40
kernel/dir.c
40
kernel/dir.c
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user