diff options
author | David Howells <dhowells@redhat.com> | 2008-11-14 10:39:19 +1100 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-14 10:39:19 +1100 |
commit | c69e8d9c01db2adc503464993c358901c9af9de4 (patch) | |
tree | bed94aaa9aeb7a7834d1c880f72b62a11a752c78 /fs/fuse | |
parent | 86a264abe542cfececb4df129bc45a0338d8cdb9 (diff) | |
download | linux-stable-c69e8d9c01db2adc503464993c358901c9af9de4.tar.gz linux-stable-c69e8d9c01db2adc503464993c358901c9af9de4.tar.bz2 linux-stable-c69e8d9c01db2adc503464993c358901c9af9de4.zip |
CRED: Use RCU to access another task's creds and to release a task's own creds
Use RCU to access another task's creds and to release a task's own creds.
This means that it will be possible for the credentials of a task to be
replaced without another task (a) requiring a full lock to read them, and (b)
seeing deallocated memory.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dir.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e97a98981862..95bc22bdd060 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -869,18 +869,25 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, */ int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) { + const struct cred *cred; + int ret; + if (fc->flags & FUSE_ALLOW_OTHER) return 1; - if (task->cred->euid == fc->user_id && - task->cred->suid == fc->user_id && - task->cred->uid == fc->user_id && - task->cred->egid == fc->group_id && - task->cred->sgid == fc->group_id && - task->cred->gid == fc->group_id) - return 1; + rcu_read_lock(); + ret = 0; + cred = __task_cred(task); + if (cred->euid == fc->user_id && + cred->suid == fc->user_id && + cred->uid == fc->user_id && + cred->egid == fc->group_id && + cred->sgid == fc->group_id && + cred->gid == fc->group_id) + ret = 1; + rcu_read_unlock(); - return 0; + return ret; } static int fuse_access(struct inode *inode, int mask) |