aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c045cc70c749..3a47247a889e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -74,6 +74,19 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
74 return 1; 74 return 1;
75} 75}
76 76
77static int dir_alias(struct inode *inode)
78{
79 if (S_ISDIR(inode->i_mode)) {
80 /* Don't allow creating an alias to a directory */
81 struct dentry *alias = d_find_alias(inode);
82 if (alias) {
83 dput(alias);
84 return 1;
85 }
86 }
87 return 0;
88}
89
77static struct dentry_operations fuse_dentry_operations = { 90static struct dentry_operations fuse_dentry_operations = {
78 .d_revalidate = fuse_dentry_revalidate, 91 .d_revalidate = fuse_dentry_revalidate,
79}; 92};
@@ -263,7 +276,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
263 fuse_put_request(fc, req); 276 fuse_put_request(fc, req);
264 277
265 /* Don't allow userspace to do really stupid things... */ 278 /* Don't allow userspace to do really stupid things... */
266 if ((inode->i_mode ^ mode) & S_IFMT) { 279 if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) {
267 iput(inode); 280 iput(inode);
268 return -EIO; 281 return -EIO;
269 } 282 }
@@ -874,14 +887,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
874 err = fuse_lookup_iget(dir, entry, &inode); 887 err = fuse_lookup_iget(dir, entry, &inode);
875 if (err) 888 if (err)
876 return ERR_PTR(err); 889 return ERR_PTR(err);
877 if (inode && S_ISDIR(inode->i_mode)) { 890 if (inode && dir_alias(inode)) {
878 /* Don't allow creating an alias to a directory */ 891 iput(inode);
879 struct dentry *alias = d_find_alias(inode); 892 return ERR_PTR(-EIO);
880 if (alias) {
881 dput(alias);
882 iput(inode);
883 return ERR_PTR(-EIO);
884 }
885 } 893 }
886 d_add(entry, inode); 894 d_add(entry, inode);
887 return NULL; 895 return NULL;