@ -74,6 +74,19 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 1 ;
}
static int dir_alias ( struct inode * inode )
{
if ( S_ISDIR ( inode - > i_mode ) ) {
/* Don't allow creating an alias to a directory */
struct dentry * alias = d_find_alias ( inode ) ;
if ( alias ) {
dput ( alias ) ;
return 1 ;
}
}
return 0 ;
}
static struct dentry_operations fuse_dentry_operations = {
. d_revalidate = fuse_dentry_revalidate ,
} ;
@ -263,7 +276,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
fuse_put_request ( fc , req ) ;
/* Don't allow userspace to do really stupid things... */
if ( ( inode - > i_mode ^ mode ) & S_IFMT ) {
if ( ( ( inode - > i_mode ^ mode ) & S_IFMT ) | | dir_alias ( inode ) ) {
iput ( inode ) ;
return - EIO ;
}
@ -874,14 +887,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
err = fuse_lookup_iget ( dir , entry , & inode ) ;
if ( err )
return ERR_PTR ( err ) ;
if ( inode & & S_ISDIR ( inode - > i_mode ) ) {
/* Don't allow creating an alias to a directory */
struct dentry * alias = d_find_alias ( inode ) ;
if ( alias ) {
dput ( alias ) ;
iput ( inode ) ;
return ERR_PTR ( - EIO ) ;
}
if ( inode & & dir_alias ( inode ) ) {
iput ( inode ) ;
return ERR_PTR ( - EIO ) ;
}
d_add ( entry , inode ) ;
return NULL ;