[PATCH 10/11] xenstore: Implement watching of nodes which don't exist.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 10/11] xenstore: Implement watching of nodes which don't exist.

Rusty Russell
# HG changeset patch
# User Rusty Russell <[hidden email]>
# Node ID 92fd066729d9656628b4221da64139cedab63f91
# Parent  7afa9d82082a6dde722995b22b59a0819fb70f87
xenstore: Implement watching of nodes which don't exist.
Requires permission check every time event is generated.
Requires generalization of permissions: ask arbitrary number of parents whether it's OK to tell about node (eg. watching /dir/subdir/x when /dir is deleted: root permissions will now determine whether we fire event).

Signed-off-by: Rusty Russell <[hidden email]>

diff -r 7afa9d82082a -r 92fd066729d9 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Thu Aug  4 11:44:12 2005
+++ b/tools/xenstore/xenstored_core.c Thu Aug  4 12:18:42 2005
@@ -707,7 +707,7 @@
 
  /* Owners and tools get it all... */
  if (!id || perms[0].id == id)
- return XS_PERM_READ|XS_PERM_WRITE|XS_PERM_CREATE|XS_PERM_OWNER;
+ return XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER;
 
  for (i = 1; i < num; i++)
  if (perms[i].id == id)
@@ -716,19 +716,12 @@
  return perms[0].perms;
 }
 
-/* We have a weird permissions system.  You can allow someone into a
- * specific node without allowing it in the parents.  If it's going to
- * fail, however, we don't want the errno to indicate any information
- * about the node. */
-static int check_with_parents(struct connection *conn, const char *node,
-      int errnum)
+/* What do parents say? */
+static enum xs_perm_type ask_parents(struct connection *conn,
+     const char *node)
 {
  struct xs_permissions *perms;
  unsigned int num;
-
- /* We always tell them about memory failures. */
- if (errnum == ENOMEM)
- return errnum;
 
  do {
  node = get_parent(node);
@@ -741,10 +734,23 @@
  if (!perms)
  corrupt(conn, "No permissions file at root");
 
- if (!(perm_for_id(conn->id, perms, num) & XS_PERM_READ))
- return EACCES;
-
- return errnum;
+ return perm_for_id(conn->id, perms, num);
+}
+
+/* We have a weird permissions system.  You can allow someone into a
+ * specific node without allowing it in the parents.  If it's going to
+ * fail, however, we don't want the errno to indicate any information
+ * about the node. */
+static int errno_from_parents(struct connection *conn, const char *node,
+      int errnum)
+{
+ /* We always tell them about memory failures. */
+ if (errnum == ENOMEM)
+ return errnum;
+
+ if (ask_parents(conn, node) & XS_PERM_READ)
+ return errnum;
+ return EACCES;
 }
 
 char *canonicalize(struct connection *conn, const char *node)
@@ -776,24 +782,26 @@
  }
 
  perms = get_perms(conn->transaction, node, &num);
- /* No permissions.  If we want to create it and
- * it doesn't exist, check parent directory. */
- if (!perms && errno == ENOENT && (perm & XS_PERM_CREATE)) {
- char *parent = get_parent(node);
- if (!parent)
- return false;
-
- perms = get_perms(conn->transaction, parent, &num);
- }
- if (!perms) {
- errno = check_with_parents(conn, node, errno);
+
+ if (perms) {
+ if (perm_for_id(conn->id, perms, num) & perm)
+ return true;
+ errno = EACCES;
  return false;
  }
 
- if (perm_for_id(conn->id, perms, num) & perm)
- return true;
-
- errno = check_with_parents(conn, node, EACCES);
+ /* If it's OK not to exist, we consult parents. */
+ if (errno == ENOENT && (perm & XS_PERM_ENOENT_OK)) {
+ if (ask_parents(conn, node) & perm)
+ return true;
+ /* Parents say they should not know. */
+ errno = EACCES;
+ return false;
+ }
+
+ /* They might not have permission to even *see* this node, in
+ * which case we return EACCES even if it's ENOENT or EIO. */
+ errno = errno_from_parents(conn, node, errno);
  return false;
 }
 
@@ -929,9 +937,9 @@
  if (streq(vec[1], XS_WRITE_NONE))
  mode = XS_PERM_WRITE;
  else if (streq(vec[1], XS_WRITE_CREATE))
- mode = XS_PERM_WRITE|XS_PERM_CREATE;
+ mode = XS_PERM_WRITE|XS_PERM_ENOENT_OK;
  else if (streq(vec[1], XS_WRITE_CREATE_EXCL))
- mode = XS_PERM_WRITE|XS_PERM_CREATE;
+ mode = XS_PERM_WRITE|XS_PERM_ENOENT_OK;
  else {
  send_error(conn, EINVAL);
  return;
@@ -950,7 +958,7 @@
  }
 
  /* Not going to create it? */
- if (!(mode & XS_PERM_CREATE)) {
+ if (streq(vec[1], XS_WRITE_NONE)) {
  send_error(conn, ENOENT);
  return;
  }
@@ -984,7 +992,7 @@
 static void do_mkdir(struct connection *conn, const char *node)
 {
  node = canonicalize(conn, node);
- if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_CREATE)) {
+ if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_ENOENT_OK)) {
  send_error(conn, errno);
  return;
  }
diff -r 7afa9d82082a -r 92fd066729d9 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c Thu Aug  4 11:44:12 2005
+++ b/tools/xenstore/xenstored_watch.c Thu Aug  4 12:18:42 2005
@@ -95,9 +95,18 @@
  return 0;
 }
 
-static void add_event(struct watch *watch, const char *node)
+static void add_event(struct connection *conn,
+      struct watch *watch, const char *node)
 {
  struct watch_event *event;
+
+ /* Check read permission: no permission, no watch event.
+ * If it doesn't exist, we need permission to read parent.
+ */
+ if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK)) {
+ fprintf(stderr, "No permission for %s\n", node);
+ return;
+ }
 
  if (watch->relative_path) {
  node += strlen(watch->relative_path);
@@ -132,9 +141,9 @@
 
  list_for_each_entry(watch, &i->watches, list) {
  if (is_child(node, watch->node))
- add_event(watch, node);
+ add_event(i, watch, node);
  else if (recurse && is_child(watch->node, node))
- add_event(watch, watch->node);
+ add_event(i, watch, watch->node);
  else
  continue;
  /* If connection not doing anything, queue this. */
@@ -205,7 +214,7 @@
 
  relative = !strstarts(vec[0], "/");
  vec[0] = canonicalize(conn, vec[0]);
- if (!check_node_perms(conn, vec[0], XS_PERM_READ)) {
+ if (!is_valid_nodename(vec[0])) {
  send_error(conn, errno);
  return;
  }
diff -r 7afa9d82082a -r 92fd066729d9 tools/xenstore/xs_lib.h
--- a/tools/xenstore/xs_lib.h Thu Aug  4 11:44:12 2005
+++ b/tools/xenstore/xs_lib.h Thu Aug  4 12:18:42 2005
@@ -30,7 +30,7 @@
  XS_PERM_READ = 1,
  XS_PERM_WRITE = 2,
  /* Internal use. */
- XS_PERM_CREATE = 4,
+ XS_PERM_ENOENT_OK = 4,
  XS_PERM_OWNER = 8,
 };
 
diff -r 7afa9d82082a -r 92fd066729d9 tools/xenstore/xs_random.c
--- a/tools/xenstore/xs_random.c Thu Aug  4 11:44:12 2005
+++ b/tools/xenstore/xs_random.c Thu Aug  4 12:18:42 2005
@@ -349,19 +349,12 @@
 {
  char *dirname = path_to_name(info, path);
 
- /* Same effective order as daemon, so error returns are right. */
- if (mkdir(dirname, 0700) != 0) {
- if (errno != ENOENT && errno != ENOTDIR)
- write_ok(info, path);
- return false;
- }
-
- if (!write_ok(info, path)) {
- int saved_errno = errno;
- rmdir(dirname);
- errno = saved_errno;
- return false;
- }
+ if (!write_ok(info, path))
+ return false;
+
+ if (mkdir(dirname, 0700) != 0)
+ return false;
+
  init_perms(dirname);
  return true;
 }


_______________________________________________
Xen-devel mailing list
[hidden email]
http://lists.xensource.com/xen-devel