From: Miklos Szeredi Date: Tue, 16 Oct 2007 16:11:01 +0000 (+0000) Subject: pull kernel module fixes from mainline X-Git-Tag: fuse_2_7_1~2 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=a32865d843466cb66724f211a813a844e380930e;p=qemu-gpiodev%2Flibfuse.git pull kernel module fixes from mainline --- diff --git a/ChangeLog b/ChangeLog index e8252b7..0c00674 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,14 @@ * Clarify licence version to be "LGPLv2" for the library + * kernel fixes: + + * After mount set nlink attribute for the root inode to 1 + + * Fix wake up of task waiting for a reserved request + + * Fix allowing setattr, listxattr and statfs for other users + 2007-09-18 Miklos Szeredi * Add missing context initialization in fuse_fs_chmod(). Bug diff --git a/kernel/dev.c b/kernel/dev.c index 60a6bbf..f8b7f3a 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -131,7 +131,7 @@ static struct fuse_req *get_reserved_req(struct fuse_conn *fc, struct fuse_file *ff = file->private_data; do { - wait_event(fc->blocked_waitq, ff->reserved_req); + wait_event(fc->reserved_req_waitq, ff->reserved_req); spin_lock(&fc->lock); if (ff->reserved_req) { req = ff->reserved_req; @@ -157,7 +157,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) fuse_request_init(req); BUG_ON(ff->reserved_req); ff->reserved_req = req; - wake_up(&fc->blocked_waitq); + wake_up_all(&fc->reserved_req_waitq); spin_unlock(&fc->lock); fput(file); } diff --git a/kernel/dir.c b/kernel/dir.c index b493e4e..c5316d9 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -720,7 +720,7 @@ int fuse_do_getattr(struct inode *inode) * for which the owner of the mount has ptrace privilege. This * excludes processes started by other users, suid or sgid processes. */ -static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) +int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) { if (fc->flags & FUSE_ALLOW_OTHER) return 1; @@ -1059,6 +1059,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) int err; int is_truncate = 0; + if (!fuse_allow_task(fc, current)) + return -EACCES; + if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { err = inode_change_ok(inode, attr); if (err) @@ -1233,6 +1236,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) struct fuse_getxattr_out outarg; ssize_t ret; + if (!fuse_allow_task(fc, current)) + return -EACCES; + if (fc->no_listxattr) return -EOPNOTSUPP; diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index f9803b4..3ea9a57 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -368,6 +368,9 @@ struct fuse_conn { /** waitq for blocked connection */ wait_queue_head_t blocked_waitq; + /** waitq for reserved requests */ + wait_queue_head_t reserved_req_waitq; + /** The next unique request id */ u64 reqctr; @@ -639,3 +642,8 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc); * Is file type valid? */ int fuse_valid_type(int m); + +/** + * Is task allowed to perform filesystem operation? + */ +int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); diff --git a/kernel/inode.c b/kernel/inode.c index f52ee8b..8195f6e 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -258,6 +258,7 @@ static void fuse_put_super(struct super_block *sb) kill_fasync(&fc->fasync, SIGIO, POLL_IN); wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); + wake_up_all(&fc->reserved_req_waitq); mutex_lock(&fuse_mutex); list_del(&fc->entry); fuse_ctl_remove_conn(fc); @@ -293,6 +294,11 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) struct fuse_statfs_out outarg; int err; + if (!fuse_allow_task(fc, current)) { + buf->f_type = FUSE_SUPER_MAGIC; + return 0; + } + req = fuse_get_req(fc); if (IS_ERR(req)) return PTR_ERR(req); @@ -469,6 +475,7 @@ static struct fuse_conn *new_conn(void) atomic_set(&fc->count, 1); init_waitqueue_head(&fc->waitq); init_waitqueue_head(&fc->blocked_waitq); + init_waitqueue_head(&fc->reserved_req_waitq); INIT_LIST_HEAD(&fc->pending); INIT_LIST_HEAD(&fc->processing); INIT_LIST_HEAD(&fc->io); @@ -506,6 +513,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) attr.mode = mode; attr.ino = FUSE_ROOT_ID; + attr.nlink = 1; return fuse_iget(sb, 1, 0, &attr); } #ifndef FUSE_MAINLINE