summaryrefslogtreecommitdiff
path: root/trans/mtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'trans/mtab.c')
-rw-r--r--trans/mtab.c225
1 files changed, 87 insertions, 138 deletions
diff --git a/trans/mtab.c b/trans/mtab.c
index a69ede6e..794c07f4 100644
--- a/trans/mtab.c
+++ b/trans/mtab.c
@@ -26,6 +26,12 @@
#include <hurd.h>
#include <hurd/ihash.h>
#include <hurd/trivfs.h>
+#if XXX_libc_has_included_our_new_rpc
+#include <hurd/fsys.h>
+... also remember to remove the client code from the Makefile...
+#else
+#include "fsys_U.h"
+#endif
#include <inttypes.h>
#include <mntent.h>
#include <nullauth.h>
@@ -39,11 +45,13 @@
#include <version.h>
#include "libtrivfs/trivfs_io_S.h"
-#include "fs_U.h"
+
+/* The targets control port. */
+static mach_port_t target_control;
static char *target_path = NULL;
-static int insecure = 0;
-static int all_translators = 0;
+#define MAX_DEPTH 10
+static int max_depth = MAX_DEPTH;
/* Our control port. */
struct trivfs_control *control;
@@ -63,25 +71,21 @@ const char *argp_program_version = STANDARD_HURD_VERSION (mtab);
static const struct argp_option options[] =
{
- {"insecure", 'I', 0, 0,
- "Follow translators not bound to nodes owned by you or root"},
- {"all-translators", 'A', 0, 0,
- "List all translators, even those that are probably not "
- "filesystem translators"},
+ {"depth", 'd', "DEPTH", 0,
+ "Maximum depth to traverse"},
{}
};
/* Parse a command line option. */
error_t parse_opt (int key, char *arg, struct argp_state *state)
{
+ char *end;
switch (key)
{
- case 'I':
- insecure = 1;
- break;
-
- case 'A':
- all_translators = 1;
+ case 'd':
+ max_depth = strtoull (arg, &end, 10);
+ if (arg == end || end[0] != 0)
+ argp_error (state, "Could not parse depth '%s'.", arg);
break;
case ARGP_KEY_ARG:
@@ -117,9 +121,14 @@ trivfs_append_args (struct trivfs_control *fsys,
{
error_t err;
- if (insecure)
+ if (max_depth != MAX_DEPTH)
{
- err = argz_add (argz, argz_len, target_path);
+ char *arg;
+ if (asprintf (&arg, "--depth=%d", max_depth) < 0)
+ return errno;
+
+ err = argz_add (argz, argz_len, arg);
+ free (arg);
if (err)
return err;
}
@@ -201,7 +210,8 @@ is_owner (io_statbuf_t *st)
}
error_t
-mtab_populate (struct mtab *mtab, const char *path, int insecure);
+mtab_populate (struct mtab *mtab, const char *path, mach_port_t control,
+ int depth);
error_t
argz_add_device (char **options, size_t *options_len, const char *device);
@@ -213,6 +223,7 @@ int
main (int argc, char *argv[])
{
error_t err;
+ mach_port_t node;
err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
if (err)
@@ -222,14 +233,27 @@ main (int argc, char *argv[])
if (err)
error (2, err, "getting credentials");
+ /* Do the lookup without O_NOTRANS to get the root node. */
+ node = file_name_lookup (target_path, 0, 0);
+ if (! MACH_PORT_VALID (node))
+ error (2, errno, "%s", target_path);
+
+ /* Get the control port. */
+ err = file_getcontrol (node, &target_control);
+ if (err)
+ error (2, err, "file_getcontrol");
+
+ /* Now that we have the control port, we can drop our
+ privileges. */
+ err = setnullauth ();
+ if (err)
+ error (3, err, "dropping credentials");
+
mach_port_t bootstrap;
task_get_bootstrap_port (mach_task_self (), &bootstrap);
if (bootstrap != MACH_PORT_NULL)
{
/* Started as a translator. */
- err = setnullauth ();
- if (err)
- error (3, err, "dropping credentials");
/* Reply to our parent. */
err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &control);
@@ -254,7 +278,7 @@ main (int argc, char *argv[])
.lock = PTHREAD_MUTEX_INITIALIZER,
.ports_seen = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP),
};
- err = mtab_populate (&mtab, target_path, insecure);
+ err = mtab_populate (&mtab, target_path, target_control, max_depth);
if (err)
error (5, err, "%s", target_path);
@@ -284,56 +308,23 @@ mtab_add_entry (struct mtab *mtab, const char *entry, size_t length)
return 0;
}
-/* Check whether the given NODE is a directory on a filesystem
- translator. */
-static boolean_t
-is_filesystem_translator (file_t node)
-{
- error_t err;
- char *data = NULL;
- size_t datacnt = 0;
- int amount;
- err = dir_readdir (node, &data, &datacnt, 0, 1, 0, &amount);
- if (data != NULL && datacnt > 0)
- vm_deallocate (mach_task_self (), (vm_address_t) data, datacnt);
-
- /* Filesystem translators return either no error, or, if NODE has
- not been looked up with O_READ, EBADF to dir_readdir
- requests. */
- switch (err)
- {
- case 0:
- case EBADF:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-/* Records NODE's idport in ports_seen, returns true if we have
- already seen this node or there was an error getting the id
- port. */
+/* Records CONTROL in ports_seen, returns true if we have already seen
+ this port. */
boolean_t
-mtab_mark_as_seen (struct mtab *mtab, mach_port_t node)
+mtab_mark_as_seen (struct mtab *mtab, mach_port_t control)
{
error_t err;
- mach_port_t idport, fsidport;
- ino_t fileno;
+ if (hurd_ihash_find (&mtab->ports_seen, (hurd_ihash_key_t) control))
+ return TRUE;
- err = io_identity (node, &idport, &fsidport, &fileno);
+ err = mach_port_mod_refs (mach_task_self (), control,
+ MACH_PORT_RIGHT_SEND, +1);
if (err)
+ /* Ewww. */
return TRUE;
- mach_port_deallocate (mach_task_self (), fsidport);
-
- if (hurd_ihash_find (&mtab->ports_seen, idport))
- {
- /* Already seen. Get rid of the extra reference. */
- mach_port_deallocate (mach_task_self (), idport);
- return TRUE;
- }
-
- hurd_ihash_add (&mtab->ports_seen, idport, (hurd_ihash_value_t) idport);
+ hurd_ihash_add (&mtab->ports_seen,
+ (hurd_ihash_key_t) control, (hurd_ihash_value_t) control);
return FALSE;
}
@@ -342,12 +333,13 @@ mtab_mark_as_seen (struct mtab *mtab, mach_port_t node)
by root or the current user. */
/* XXX split up */
error_t
-mtab_populate (struct mtab *mtab, const char *path, int insecure)
+mtab_populate (struct mtab *mtab, const char *path, mach_port_t control,
+ int depth)
{
error_t err = 0;
/* These resources are freed in the epilogue. */
- file_t node = MACH_PORT_NULL, underlying_node = MACH_PORT_NULL;
+ file_t node = MACH_PORT_NULL;
char *argz = NULL;
size_t argz_len = 0;
char **argv = NULL;
@@ -359,53 +351,22 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
size_t entry_len = 0;
char *children = NULL;
size_t children_len = 0;
+ mach_port_t *controls = NULL;
+ size_t controls_count = 0;
+ size_t i;
- /* Get the underlying node. */
- underlying_node = file_name_lookup (path, O_NOTRANS, 0666);
- if (underlying_node == MACH_PORT_NULL)
- {
- err = errno;
- goto errout;
- }
-
- if (! insecure)
- {
- /* Check who owns the node the translator is bound to. */
- io_statbuf_t st;
- err = io_stat (underlying_node, &st);
- if (err)
- goto errout;
-
- if (st.st_uid != 0 && st.st_gid != 0 && ! is_owner (&st))
- {
- err = EPERM;
- goto errout;
- }
- }
-
- /* (Re-)do the lookup without O_NOTRANS to get the root node. */
- node = file_name_lookup (path, 0, 0666);
- if (node == MACH_PORT_NULL)
- {
- err = errno;
- goto errout;
- }
-
- if (! (all_translators || is_filesystem_translator (node)))
- {
- err = 0;
- goto errout;
- }
+ if (depth < 0)
+ return 0;
/* Avoid running in circles. */
- if (mtab_mark_as_seen (mtab, underlying_node))
+ if (mtab_mark_as_seen (mtab, control))
{
err = 0;
goto errout;
}
/* Query its options. */
- err = file_get_fs_options (node, &argz, &argz_len);
+ err = fsys_get_options (control, &argz, &argz_len);
if (err)
{
if (err == EOPNOTSUPP)
@@ -452,7 +413,7 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
argz_stringify (options, options_len, ',');
string_t source;
- err = file_get_source (node, source);
+ err = fsys_get_source (control, source);
if (err)
goto errout;
@@ -473,8 +434,9 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
if (err)
goto errout;
- /* path has an active translator, query its children. */
- err = file_get_children (node, &children, &children_len);
+ /* Recurse. */
+ err = fsys_get_children (control, &children, &children_len,
+ &controls, &controls_count);
if (err == EOPNOTSUPP)
{
err = 0;
@@ -484,10 +446,16 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
if (err)
goto errout;
- if (children_len)
- for (char *c = children; c; c = argz_next (children, children_len, c))
+ char *c;
+ if (children_len && controls_count)
+ for (c = children, i = 0; c && i < controls_count;
+ c = argz_next (children, children_len, c), i++)
{
char *p = NULL;
+
+ if (! MACH_PORT_VALID (controls[i]))
+ continue;
+
asprintf (&p, "%s%s%s",
path,
path[strlen (path) - 1] == '/'? "": "/",
@@ -498,7 +466,7 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
goto errout;
}
- err = mtab_populate (mtab, p, insecure);
+ err = mtab_populate (mtab, p, controls[i], depth - 1);
if (err)
{
/* There is really not much we can do about errors here. */
@@ -507,11 +475,12 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
}
free (p);
+ err = mach_port_deallocate (mach_task_self (), controls[i]);
+ assert_perror_backtrace (err);
+ controls[i] = MACH_PORT_NULL;
}
errout:
- if (underlying_node != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self (), underlying_node);
if (node != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), node);
@@ -529,6 +498,9 @@ mtab_populate (struct mtab *mtab, const char *path, int insecure)
if (children)
vm_deallocate (mach_task_self (), (vm_address_t) children, children_len);
+ if (controls)
+ vm_deallocate (mach_task_self (), (vm_address_t) controls,
+ controls_count * sizeof *controls);
return err;
}
@@ -647,29 +619,6 @@ open_hook (struct trivfs_peropen *peropen)
mtab->contents_len = 0;
hurd_ihash_init (&mtab->ports_seen, HURD_IHASH_NO_LOCP);
- /* The mtab object is initialized, but not yet populated. We delay
- that until that data is really needed. This avoids the following
- problems:
-
- Suppose you have
-
- settrans -ac /foo /hurd/mtab /
-
- If you now access /foo, the mtab translator will walk the tree of
- all active translators starting from /. If it visits /foo, it
- will talk to itself. Previously the translator migitated this by
- comparing the control port of the translator with its own. This
- does not work if you got two mtab translators like this:
-
- settrans -ac /foo /hurd/mtab /
- settrans -ac /bar /hurd/mtab /
-
- With a single-threaded mtab server this results in a dead-lock,
- with a multi-threaded server this will create more and more
- threads.
-
- Delaying the data generation until it is really needed cleanly
- avoids these kind of problems. */
return 0;
}
@@ -710,7 +659,7 @@ trivfs_S_io_read (struct trivfs_protid *cred,
if (op->contents == NULL)
{
- err = mtab_populate (op, target_path, insecure);
+ err = mtab_populate (op, target_path, target_control, max_depth);
if (err)
goto out;
}
@@ -766,7 +715,7 @@ trivfs_S_io_seek (struct trivfs_protid *cred,
if (op->contents == NULL)
{
- err = mtab_populate (op, target_path, insecure);
+ err = mtab_populate (op, target_path, target_control, max_depth);
if (err)
goto out;
}
@@ -823,7 +772,7 @@ trivfs_S_io_readable (struct trivfs_protid *cred,
if (op->contents == NULL)
{
- error_t err = mtab_populate (op, target_path, insecure);
+ error_t err = mtab_populate (op, target_path, target_control, max_depth);
if (err)
goto out;
}