hurdextras-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Changes to libfuse/netfs.c


From: Stefan Siegl
Subject: Changes to libfuse/netfs.c
Date: Sun, 04 Dec 2005 13:20:44 -0500

Index: libfuse/netfs.c
diff -u libfuse/netfs.c:1.36 libfuse/netfs.c:1.37
--- libfuse/netfs.c:1.36        Sat Dec  3 23:17:06 2005
+++ libfuse/netfs.c     Sun Dec  4 18:20:44 2005
@@ -56,16 +56,60 @@
                                     int type);
 
 
+/* Check whether to allow access to a node, testing the allow_root and
+ * allow_other flag.  This does not check whether default permissions
+ * are okay to allow access.
+ *
+ * Return: 0 if access is to be granted, EPERM otherwise
+ *
+ * Sidenote: This function is mainly called from netfs_validate_stat which in
+ *           turn is called by any other of the netfs-operation-functions. This
+ *           is, we don't have to call this from all of the operation-functions
+ *           since netfs_validate_stat is called anyways!
+ */
+static error_t
+test_allow_root_or_other (struct iouser *cred)
+{
+  FUNC_PROLOGUE("test_allow_root_or_other");
+
+  /* if allow_other is set, access is okay in any case */
+  if(libfuse_params.allow_other) 
+    FUNC_RETURN_FMT(0, "allow_other is set");
+
+  unsigned int i;
+  uid_t proc_uid = getuid();
+  for(i = 0; i < cred->uids->num; i ++) 
+    {
+      DEBUG("test_allow", "testing for uid=%d\n", cred->uids->ids[i]);
+
+      if(cred->uids->ids[i] == 0 && libfuse_params.allow_root)
+       FUNC_RETURN_FMT(0, "allowing access for root");
+
+      if(cred->uids->ids[i] == proc_uid)
+       FUNC_RETURN_FMT(0, "allowing access for owner");
+    }
+
+  /* iouser is not the "filesystem-owner" and allow_other is not set,
+   * or iouser is root but allow_root is not set either */
+  FUNC_EPILOGUE(EPERM);
+}
+
+
+
 /* Make sure that NP->nn_stat is filled with current information.  CRED
-   identifies the user responsible for the operation.  */
+   identifies the user responsible for the operation. 
+
+   If the user `CRED' is not allowed to perform any operation (considering
+   the allow_root and allow_other flags), return EPERM. */
 error_t
 netfs_validate_stat (struct node *node, struct iouser *cred)
 {
-  (void) cred;
-
   FUNC_PROLOGUE_NODE("netfs_validate_stat", node);
   error_t err = EOPNOTSUPP;
 
+  if(test_allow_root_or_other(cred))
+    FUNC_RETURN(EPERM);
+
   if(FUSE_OP_HAVE(getattr))
     err = -FUSE_OP_CALL(getattr, node->nn->path, &node->nn_stat);
 
@@ -98,7 +142,7 @@
                                char *buf)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_readlink", node);
-  error_t err = EOPNOTSUPP;
+  error_t err;
 
   if((err = netfs_validate_stat(node, user))
      || (err = fshelp_access(&node->nn_stat, S_IREAD, user)))
@@ -106,6 +150,8 @@
 
   if(FUSE_OP_HAVE(readlink))
     err = -FUSE_OP_CALL(readlink, node->nn->path, buf, INT_MAX);
+  else
+    err = EOPNOTSUPP;
 
  out:
   FUNC_EPILOGUE(err);
@@ -121,16 +167,19 @@
                           char *name, mode_t mode, struct node **node)
 {
   FUNC_PROLOGUE("netfs_attempt_create_file");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   char *path = NULL;
 
-  if(! FUSE_OP_HAVE(mknod))
-    goto out;
-
   if((err = netfs_validate_stat(dir, user))
      || (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user)))
     goto out;
 
+  if(! FUSE_OP_HAVE(mknod))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2)))
     {
       err = ENOMEM;
@@ -196,15 +245,18 @@
                             uid_t uid, uid_t gid)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_chown", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(chown))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_isowner(&node->nn_stat, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(chown))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   /* FIXME, make sure, that user CRED is not able to change permissions
    * to somebody who is not. That is, don't allow $unpriv_user to change
    * owner to e.g. root.
@@ -225,14 +277,18 @@
 netfs_attempt_statfs (struct iouser *cred, struct node *node,
                      fsys_statfsbuf_t *st)
 {
-  (void) cred;
-
   FUNC_PROLOGUE_NODE("netfs_attempt_statfs", node);
-  error_t err = EOPNOTSUPP;
+  error_t err;
 
-  if(FUSE_OP_HAVE(statfs))
+  if(test_allow_root_or_other(cred))
+    err = EPERM;
+
+  else if(FUSE_OP_HAVE(statfs))
     err = -FUSE_OP_CALL(statfs, node->nn->path, st);
 
+  else
+    err = EOPNOTSUPP;
+
   FUNC_EPILOGUE(err);
 }
 
@@ -244,16 +300,19 @@
                             char *name, mode_t mode)
 {
   FUNC_PROLOGUE("netfs_attempt_mkdir");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   char *path = NULL;
 
-  if(! FUSE_OP_HAVE(mkdir))
-    goto out;
-
   if((err = netfs_validate_stat(dir, user))
      || (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user)))
     goto out;
 
+  if(! FUSE_OP_HAVE(mkdir))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2)))
     {
       err = ENOMEM;
@@ -344,15 +403,18 @@
                             mode_t mode)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_chmod", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(chmod))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_isowner(&node->nn_stat, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(chmod))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   err = -FUSE_OP_CALL(chmod, node->nn->path, mode);
   node->nn->may_need_sync = 1;
   
@@ -368,13 +430,15 @@
                              mode_t mode, struct node **node)
 {
   FUNC_PROLOGUE("netfs_attempt_mkfile");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   char name[20];
   static int num = 0;
 
-  if(FUSE_OP_HAVE(mknod))
-    if(! (err = netfs_validate_stat(dir, user)))
-      err = fshelp_checkdirmod(&dir->nn_stat, NULL, user);
+  if(! (err = netfs_validate_stat(dir, user)))
+    err = fshelp_checkdirmod(&dir->nn_stat, NULL, user);
+
+  if(! err && ! FUSE_OP_HAVE(mknod))
+    err = EOPNOTSUPP;
 
   if(err)
     {
@@ -423,12 +487,15 @@
    only after sync is completely finished.  */
 error_t netfs_attempt_syncfs (struct iouser *cred, int wait)
 {
-  (void) cred;   /* cannot use anything but translator's rights,
-                 * FIXME, maybe setuid/setgid? */
   (void) wait;   /* there's no such flag in libfuse */
 
   FUNC_PROLOGUE("netfs_attempt_syncfs");
-  error_t err = fuse_sync_filesystem();
+  error_t err;
+
+  if(test_allow_root_or_other(cred))
+    err = EPERM;
+  else
+    err = fuse_sync_filesystem();
 
   FUNC_EPILOGUE(err);
 }
@@ -443,15 +510,18 @@
   (void) wait;   /* there's no such flag in libfuse */
 
   FUNC_PROLOGUE_NODE("netfs_attempt_sync", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(fsync))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IWRITE, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(fsync))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   if(fuse_ops)
     err = -fuse_ops->fsync(node->nn->path, 0, &node->nn->info);
   else
@@ -473,12 +543,9 @@
                              char *name)
 {
   FUNC_PROLOGUE("netfs_attempt_unlink");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   struct node *node = NULL;
 
-  if(! FUSE_OP_HAVE(unlink))
-    goto out;
-
   err = netfs_attempt_lookup(user, dir, name, &node);
   assert(dir != node);
   mutex_lock(&dir->lock); /* re-lock directory, since netfs_attempt_lookup
@@ -494,7 +561,10 @@
      || (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user)))
     goto out;
 
-  err = -FUSE_OP_CALL(unlink, node->nn->path);
+  if(FUSE_OP_HAVE(unlink))
+    err = -FUSE_OP_CALL(unlink, node->nn->path);
+  else
+    err = EOPNOTSUPP;
 
   /* TODO free associated netnode. really? 
    * FIXME, make sure nn->may_need_sync is set */
@@ -513,16 +583,16 @@
                                loff_t size)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_set_size", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(truncate))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IWRITE, cred)))
     goto out;
 
-  err = -FUSE_OP_CALL(truncate, node->nn->path, size);
+  if(FUSE_OP_HAVE(truncate))
+    err = -FUSE_OP_CALL(truncate, node->nn->path, size);
+  else
+    err = EOPNOTSUPP;
 
  out:
   FUNC_EPILOGUE(err);
@@ -536,26 +606,32 @@
                             mode_t type, dev_t indexes)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_mkdev", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(mknod))
-    goto out;
-
-  /* we need to unlink the existing node, therefore, if unlink is not
-   * available, we cannot turn *node into a device.
-   */
-  if(! FUSE_OP_HAVE(unlink))
-    goto out;
+  error_t err;
 
   /* check permissions
    * XXX, shall we check permissions of the parent directory as well,
    * since we're going to unlink files?
    */
-
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IWRITE, cred)))
     goto out;
 
+  /* check whether the operations are available at all */
+  if(! FUSE_OP_HAVE(mknod))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
+  /* we need to unlink the existing node, therefore, if unlink is not
+   * available, we cannot turn *node into a device.
+   */
+  if(! FUSE_OP_HAVE(unlink))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   /* unlink the already existing node, to be able to create the (new)
    * device file
    */
@@ -697,12 +773,9 @@
 {
   FUNC_PROLOGUE_FMT("netfs_attempt_link", "link=%s/%s, to=%s",
                    dir->nn->path, name, file->nn->path);
-  error_t err = EOPNOTSUPP;
+  error_t err;
   struct node *node = NULL;
 
-  if(! FUSE_OP_HAVE(link))
-    goto out_nounlock;
-
   mutex_lock(&dir->lock);
 
   if((err = netfs_attempt_lookup(user, dir, name, &node)))
@@ -715,6 +788,11 @@
      || (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user)))
     goto out;
 
+  if(! FUSE_OP_HAVE(link)) {
+    err = EOPNOTSUPP;
+    goto out;
+  }
+
   if(! excl && FUSE_OP_HAVE(unlink))
     /* EXCL is not set, therefore we may remove the target, i.e. call
      * unlink on it.  Ignoring return value, as it's mostly not interesting,
@@ -766,12 +844,9 @@
                             struct node *dir, char *name)
 {
   FUNC_PROLOGUE("netfs_attempt_rmdir");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   struct node *node = NULL;
 
-  if(! FUSE_OP_HAVE(rmdir))
-    goto out_nounlock;
-
   err = netfs_attempt_lookup(user, dir, name, &node);
   assert(dir != node);
   mutex_lock(&dir->lock); /* netfs_attempt_lookup unlocked dir */
@@ -783,7 +858,11 @@
      || (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user)))
     goto out;
 
-  err = -FUSE_OP_CALL(rmdir, node->nn->path);
+  if(FUSE_OP_HAVE(rmdir))
+    err = -FUSE_OP_CALL(rmdir, node->nn->path);
+  else
+    err = EOPNOTSUPP;
+
 
   /* TODO free associated netnode. really? 
    * FIXME, make sure nn->may_need_sync is set */
@@ -818,27 +897,32 @@
                                 char *name)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_mksymlink", node);
-  error_t err = EOPNOTSUPP;
-
-  /* we need to unlink the existing node, therefore, if unlink is not
-   * available, we cannot create symlinks
-   */
-  if(! FUSE_OP_HAVE(unlink))
-    goto out;
-
-  /* symlink function available? if not, fail. */
-  if(! FUSE_OP_HAVE(symlink))
-    goto out;
+  error_t err;
 
   /* check permissions
    * XXX, shall we check permissions of the parent directory as well,
    * since we're going to unlink files?
    */
-
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IWRITE, cred)))
     goto out;
 
+  /* we need to unlink the existing node, therefore, if unlink is not
+   * available, we cannot create symlinks
+   */
+  if(! FUSE_OP_HAVE(unlink))
+    { 
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
+  /* symlink function available? if not, fail. */
+  if(! FUSE_OP_HAVE(symlink))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   /* try to remove the existing node (probably an anonymous file) */
   if((err = -FUSE_OP_CALL(unlink, node->nn->path)))
     goto out;
@@ -863,13 +947,10 @@
                              char *toname, int excl)
 {
   FUNC_PROLOGUE("netfs_attempt_rename");
-  error_t err = EOPNOTSUPP;
+  error_t err;
   struct node *fromnode;
   char *topath = NULL;
 
-  if(! FUSE_OP_HAVE(rename))
-    goto out_nounlock; 
-
   if(! (topath = malloc(strlen(toname) + strlen(todir->nn->path) + 2)))
     {
       err = ENOMEM;
@@ -896,6 +977,12 @@
      || fshelp_checkdirmod(&todir->nn_stat, NULL, user))
     goto out;
 
+  if(! FUSE_OP_HAVE(rename))
+    {
+      err = EOPNOTSUPP;
+      goto out; 
+    }
+
   sprintf(topath, "%s/%s", todir->nn->path, toname);
 
   if(! excl && FUSE_OP_HAVE(unlink))
@@ -938,15 +1025,18 @@
                             loff_t offset, size_t *len, void *data)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_write", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(write))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IWRITE, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(write)) 
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
   node->nn->info.writepage = 0; /* cannot distinct on the Hurd :( */
 
   int sz = fuse_ops ? 
@@ -971,21 +1061,24 @@
                      struct timespec *atime, struct timespec *mtime)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_utimes", node);
-  error_t err = EOPNOTSUPP;
-
-  /* prepare utimebuf for FUSE_OP_HAVE(utime) call */
-  struct utimbuf utb;
-  utb.actime = atime ? atime->tv_sec : node->nn_stat.st_atime;
-  utb.modtime = mtime ? mtime->tv_sec : node->nn_stat.st_mtime;
+  error_t err;
 
   /* test whether operation is supported and permission are sufficient */
-  if(! FUSE_OP_HAVE(utime))
-    goto out;
-
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_isowner(&node->nn_stat, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(utime)) 
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
+  /* prepare utimebuf for FUSE_OP_HAVE(utime) call */
+  struct utimbuf utb;
+  utb.actime = atime ? atime->tv_sec : node->nn_stat.st_atime;
+  utb.modtime = mtime ? mtime->tv_sec : node->nn_stat.st_mtime;
+
   err = -FUSE_OP_CALL(utime, node->nn->path, &utb);
 
   if (! err)
@@ -1012,15 +1105,19 @@
                            loff_t offset, size_t *len, void *data)
 {
   FUNC_PROLOGUE_NODE("netfs_attempt_read", node);
-  error_t err = EOPNOTSUPP;
-
-  if(! FUSE_OP_HAVE(read))
-    goto out;
+  error_t err;
 
   if((err = netfs_validate_stat(node, cred))
      || (err = fshelp_access(&node->nn_stat, S_IREAD, cred)))
     goto out;
 
+  if(! FUSE_OP_HAVE(read))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
+
+
   int sz = fuse_ops ? 
     (fuse_ops->read(node->nn->path, data, *len, offset, &node->nn->info)) : 
     (fuse_ops_compat->read(node->nn->path, data, *len, offset));
@@ -1187,16 +1284,19 @@
                        * i.e. never allocate any further memory */
 
   FUNC_PROLOGUE_NODE("netfs_get_dirents", dir);
-  error_t err = EOPNOTSUPP;
+  error_t err;
   fuse_dirh_t handle;
 
-  if(! FUSE_OP_HAVE(getdir))
-    goto out;
-
   if((err = netfs_validate_stat(dir, cred))
      || (err = fshelp_access(&dir->nn_stat, S_IREAD, cred))
      || (err = fshelp_access(&dir->nn_stat, S_IEXEC, cred)))
     goto out;
+
+  if(! FUSE_OP_HAVE(getdir))
+    {
+      err = EOPNOTSUPP;
+      goto out;
+    }
 
   if(! (handle = malloc(sizeof(struct fuse_dirhandle))))
     {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]