aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2001-12-20 15:38:05 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2001-12-20 15:38:05 +0000
commitfe25def3344095825738deba119e1400b8e2315f (patch)
treea277304923d54e0495558c1e4e6720c2c114d78d /kernel
parent2e50d4376f3124a87d5723ae66c09fa71c7ecf88 (diff)
permission checking implemented
Diffstat (limited to 'kernel')
-rw-r--r--kernel/dir.c68
-rw-r--r--kernel/file.c8
-rw-r--r--kernel/fuse_i.h7
-rw-r--r--kernel/inode.c1
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)