diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2001-12-20 15:38:05 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2001-12-20 15:38:05 +0000 |
commit | fe25def3344095825738deba119e1400b8e2315f (patch) | |
tree | a277304923d54e0495558c1e4e6720c2c114d78d /kernel | |
parent | 2e50d4376f3124a87d5723ae66c09fa71c7ecf88 (diff) |
permission checking implemented
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/dir.c | 68 | ||||
-rw-r--r-- | kernel/file.c | 8 | ||||
-rw-r--r-- | kernel/fuse_i.h | 7 | ||||
-rw-r--r-- | kernel/inode.c | 1 |
4 files changed, 67 insertions, 17 deletions
diff --git a/kernel/dir.c b/kernel/dir.c index a3f1485..7068d37 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -315,29 +315,14 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, return out.h.error; } -static int fuse_permission(struct inode *inode, int mask) -{ - struct fuse_conn *fc = INO_FC(inode); - - /* (too) simple protection */ - if(current->fsuid == fc->uid) - return 0; - else - return -EACCES; -} -static int fuse_revalidate(struct dentry *entry) +int fuse_getattr(struct inode *inode) { - struct inode *inode = entry->d_inode; struct fuse_conn *fc = INO_FC(inode); struct fuse_in in = FUSE_IN_INIT; struct fuse_out out = FUSE_OUT_INIT; struct fuse_getattr_out arg; - if(inode->i_ino != FUSE_ROOT_INO && - time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME)) - return 0; - in.h.opcode = FUSE_GETATTR; in.h.ino = inode->i_ino; out.numargs = 1; @@ -351,6 +336,57 @@ static int fuse_revalidate(struct dentry *entry) return out.h.error; } +static int fuse_revalidate(struct dentry *entry) +{ + struct inode *inode = entry->d_inode; + struct fuse_conn *fc = INO_FC(inode); + + if(inode->i_ino == FUSE_ROOT_INO) { + if(!(fc->flags & FUSE_ALLOW_OTHER) + && current->fsuid != fc->uid) + return -EACCES; + } + else if(time_before_eq(jiffies, entry->d_time + FUSE_REVALIDATE_TIME)) + return 0; + + return fuse_getattr(inode); +} + +static int fuse_permission(struct inode *inode, int mask) +{ + struct fuse_conn *fc = INO_FC(inode); + + if(!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid) + return -EACCES; + else if(fc->flags & FUSE_DEFAULT_PERMISSIONS) { + int err = vfs_permission(inode, mask); + + /* If permission is denied, try to refresh file + attributes. This is also needed, because the root + node will at first have no permissions */ + + if(err == -EACCES) { + err = fuse_getattr(inode); + if(!err) + err = vfs_permission(inode, mask); + } + + /* FIXME: Need some mechanism to revoke permissions: + currently if the filesystem suddenly changes the + file mode, we will not be informed abot that, and + continue to allow access to the file/directory. + + This is actually not so grave, since the user can + simply keep access to the file/directory anyway by + keeping it open... */ + + return err; + } + else + return 0; +} + + static int parse_dirfile(char *buf, size_t nbytes, struct file *file, void *dstbuf, filldir_t filldir) { diff --git a/kernel/file.c b/kernel/file.c index b7cb2f4..0622e51 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -17,6 +17,14 @@ static int fuse_open(struct inode *inode, struct file *file) struct fuse_out out = FUSE_OUT_INIT; struct fuse_open_in inarg; + /* If opening the root node, no lookup has been performed on + it, so the attributes must be refreshed */ + if(inode->i_ino == FUSE_ROOT_INO) { + int err = fuse_getattr(inode); + if(err) + return err; + } + memset(&inarg, 0, sizeof(inarg)); inarg.flags = file->f_flags & ~O_EXCL; diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 27d8eb3..262e05d 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -77,7 +77,7 @@ struct fuse_out { struct fuse_out_arg args[3]; }; -#define FUSE_IN_INIT { {0, 0, 0}, 0} +#define FUSE_IN_INIT { {0, 0, 0, current->fsuid, current->fsgid}, 0} #define FUSE_OUT_INIT { {0, 0}, 0, 0} /** @@ -178,6 +178,11 @@ void request_send(struct fuse_conn *fc, struct fuse_in *in, */ int request_send_noreply(struct fuse_conn *fc, struct fuse_in *in); +/** + * Get the attributes of a file + */ +int fuse_getattr(struct inode *inode); + /* * Local Variables: * indent-tabs-mode: t diff --git a/kernel/inode.c b/kernel/inode.c index 7d211cb..7fc5cfe 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -32,6 +32,7 @@ static void fuse_clear_inode(struct inode *inode) in = kmalloc(sizeof(struct fuse_in), GFP_NOFS); if(!in) return; + memset(in, 0, sizeof(struct fuse_in)); inarg = kmalloc(sizeof(struct fuse_forget_in), GFP_NOFS); if(!inarg) |