bug-hurd
[Top][All Lists]
Advanced

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

Re: [PATCH 2/3] Start the mountee in a lazy fashion


From: Sergiu Ivanov
Subject: Re: [PATCH 2/3] Start the mountee in a lazy fashion
Date: Mon, 6 Jul 2009 00:15:55 +0300
User-agent: Mutt/1.5.18 (2008-05-17)

>From 236bcec849c5775a4567c7d8fbceb75beb29dc48 Mon Sep 17 00:00:00 2001
From: Sergiu Ivanov <unlimitedscolobb@gmail.com>
Date: Sun, 5 Jul 2009 23:08:44 +0300
Subject: [PATCH] Start the mountee in a lazy fashion.

* mount.c (unionmount_proxy): New variable.
(mountee_port): Likewise.
(mountee_started): Likewise.
(setup_unionmount): New function.
(start_mountee): New function (based on node_set_translator
in nsmux).
* mount.h (unionmount_proxy): New variable.
(mountee_port): Likewise.
(mountee_started): Likewise.
(setup_unionmount): New function.
(start_mountee): New function.
(setup_unionmount): New function.
* netfs.c (netfs_validate_stat): Start the mountee at the
first invocation.
---
 mount.c |  179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mount.h |   23 ++++++++
 netfs.c |   14 +++++-
 3 files changed, 215 insertions(+), 1 deletions(-)

diff --git a/mount.c b/mount.c
index 7bc1fb8..f05fe7c 100644
--- a/mount.c
+++ b/mount.c
@@ -22,8 +22,187 @@
 
 #define _GNU_SOURCE
 
+#include <hurd/fsys.h>
+#include <fcntl.h>
+
 #include "mount.h"
+#include "lib.h"
 
 /* The command line for starting the mountee.  */
 char * mountee_argz;
 size_t mountee_argz_len;
+
+/* The node the mountee is sitting on.  */
+node_t * unionmount_proxy;
+
+mach_port_t mountee_port;
+
+int mountee_started = 0;
+
+/* Starts the mountee (given by `argz` and `argz_len`), sets it on
+   node `np` and opens a port `port` to with `flags`.  */
+error_t
+start_mountee (node_t * np, char * argz, size_t argz_len, int flags,
+              mach_port_t * port)
+{
+  error_t err;
+  mach_port_t underlying_port;
+
+  /* The intermediate container for the port to the root of the
+     mountee.  */
+  mach_port_t res_port;
+
+  /* An unauthenticated port to the root of the translator, which
+     plays the role of the directory containing the underlying node of
+     the mountee. This one is used in fsys_getroot as the dotdot
+     parameter, so it is not really important what we put here because
+     the dotdot parameter is used mostly with symlinks.  */
+  mach_port_t unauth_dir;
+
+  /* The control port of the mountee.  */
+  mach_port_t control;
+
+  /* The user which has created this process.  */
+  struct iouser * user;
+
+  /* The user who has no priveleges at all.  */
+  struct iouser * nobody;
+
+  /* A protid which will be created from the supplied node.  */
+  struct protid * newpi;
+
+  /* Identity information about the current process (for
+     fsys_getroot).  */
+  uid_t * uids;
+  size_t nuids;
+
+  gid_t * gids;
+  size_t ngids;
+
+  /* The retry information returned by fsys_getroot.  */
+  string_t retry_name;
+  mach_port_t retry_port;
+
+  /* Fetch the effective UIDs of this process.  */
+  nuids = geteuids (0, 0);
+  if (nuids < 0)
+    return EPERM;
+  uids = alloca (nuids * sizeof (uid_t));
+
+  nuids = geteuids (nuids, uids);
+  assert (nuids > 0);
+
+  /* Fetch the effective GIDs of this process.  */
+  ngids = getgroups (0, 0);
+  if (ngids < 0)
+    return EPERM;
+  gids = alloca (ngids * sizeof (gid_t));
+
+  ngids = getgroups (ngids, gids);
+  assert (ngids > 0);
+
+  /* Create an iouser instance basing on the obtained authority
+     information.  */
+  err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids);
+  if (err)
+    return err;
+
+  /* Opens the port on which to set the mountee.  */
+  error_t
+    open_port (int flags, mach_port_t * underlying,
+              mach_msg_type_name_t * underlying_type, task_t task,
+              void *cookie)
+  {
+    err = 0;
+
+    /* Create a port to `np`.  */
+    newpi = netfs_make_protid
+      (netfs_make_peropen (np, flags, NULL), user);
+    if (!newpi)
+      {
+       iohelp_free_iouser (user);
+       return errno;
+      }
+
+    *underlying = underlying_port = ports_get_send_right (newpi);
+    *underlying_type = MACH_MSG_TYPE_COPY_SEND;
+
+    ports_port_deref (newpi);
+
+    return err;
+  }                            /*open_port */
+
+  /* Create a completely unprivileged user.  */
+  err = iohelp_create_iouser(&nobody, NULL, NULL);
+
+  /* Create a port to `np` for the unprivileged user.  */
+  newpi = netfs_make_protid
+    (netfs_make_peropen (np, flags, NULL), nobody);
+  if (!newpi)
+    {
+      iohelp_free_iouser (nobody);
+      err = errno;
+      return err;
+    }
+
+  unauth_dir = ports_get_send_right (newpi);
+  ports_port_deref (newpi);
+
+  /* Start the translator.  The value 60000 for the timeout is the one
+     found in settrans.  */
+  err = fshelp_start_translator (open_port, NULL, argz, argz, argz_len,
+                                60000, &control);
+  if (err)
+    return err;
+
+  /* Attempt to attach the mountee to the port opened in the previous
+     call.  */
+  err = file_set_translator (underlying_port, 0, FS_TRANS_SET, 0, argz,
+                            argz_len, control, MACH_MSG_TYPE_COPY_SEND);
+  port_dealloc (underlying_port);
+  if (err)
+    return err;
+
+  /* Obtain the port to the root of the newly-set translator.  */
+  err = fsys_getroot (control, unauth_dir, MACH_MSG_TYPE_COPY_SEND,
+                     uids, nuids, gids, ngids, flags, &retry_port,
+                     retry_name, &res_port);
+  if (err)
+    return err;
+
+  *port = res_port;
+
+  return 0;
+}                              /* start_mountee */
+
+/* Sets up a proxy node, sets the translator on it, and registers the
+   filesystem published by the translator in the list of merged
+   filesystems.  */
+error_t
+setup_unionmount (void)
+{
+  error_t err = 0;
+
+  /* The proxy node on which the mountee will be sitting must be able
+     to forward some of the RPCs coming from the mountee to the
+     underlying filesystem.  That is why we create this proxy node as
+     a clone of the root node: the mountee will feel as if there is no
+     unionfs under itself.  */
+  unionmount_proxy = netfs_make_node (netfs_root_node->nn);
+  if (!unionmount_proxy)
+    return ENOMEM;
+
+  /* Set the mountee on the proxy node.
+     Note that the O_READ flag does not actually limit access to the
+     mountee's filesystem considerably.  Whenever a client looks up a
+     node which is not a directory, unionfs will give off a port to
+     the node itself, withouth proxying it.  Proxying happens only for
+     directory nodes.  */
+  err = start_mountee (unionmount_proxy, mountee_argz,
+                      mountee_argz_len, O_READ, &mountee_port);
+
+  mountee_started = 1;
+
+  return err;
+}                              /* setup_unionmount */
+
diff --git a/mount.h b/mount.h
index a7dd933..181608c 100644
--- a/mount.h
+++ b/mount.h
@@ -23,10 +23,33 @@
 #ifndef INCLUDED_MOUNT_H
 #define INCLUDED_MOUNT_H
 
+#include <error.h>
 #include <unistd.h>
+#include <hurd/hurd_types.h>
+
+#include "node.h"
 
 /* The command line for starting the mountee.  */
 extern char * mountee_argz;
 extern size_t mountee_argz_len;
 
+/* The node the mountee is sitting on.  */
+extern node_t * unionmount_proxy;
+
+extern mach_port_t mountee_port;
+
+extern int mountee_started;
+
+/* Starts the mountee (given by `argz` and `argz_len`), sets it on
+   node `np` and opens a port `port` to with `flags`.  */
+error_t
+start_mountee (node_t * np, char * argz, size_t argz_len, int flags,
+              mach_port_t * port);
+
+/* Sets up a proxy node, sets the translator on it, and registers the
+   filesystem published by the translator in the list of merged
+   filesystems.  */
+error_t
+setup_unionmount (void);
+
 #endif /* not INCLUDED_MOUNT_H */
diff --git a/netfs.c b/netfs.c
index 89d1bf6..01e8ae9 100644
--- a/netfs.c
+++ b/netfs.c
@@ -1,7 +1,11 @@
 /* Hurd unionfs
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2005, 2009
+     Free Software Foundation, Inc.
+
    Written by Moritz Schulte <moritz@duesseldorf.ccc.de>.
 
+   Adapted for unionmount by Sergiu Ivanov <unlimitedscolobb@gmail.com>.
+
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
@@ -36,6 +40,7 @@
 #include "lib.h"
 #include "ncache.h"
 #include "options.h"
+#include "mount.h"
 
 /* Return an argz string describing the current options.  Fill *ARGZ
    with a pointer to newly malloced storage holding the list and *LEN
@@ -165,6 +170,13 @@ netfs_validate_stat (struct node *np, struct iouser *cred)
     }
   else 
     {
+      if (!mountee_started)
+       {
+         err = setup_unionmount ();
+         if (err)
+           error (EXIT_FAILURE, err, "failed to setup the mountee");
+       }
+
       _get_node_size (np, &np->nn_stat.st_size); 
     }
 
-- 
1.5.2.4




reply via email to

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