ep: add kdbus_ep_policy_check_notification()
authorDaniel Mack <daniel@zonque.org>
Wed, 1 Oct 2014 09:44:24 +0000 (11:44 +0200)
committerDaniel Mack <daniel@zonque.org>
Wed, 1 Oct 2014 09:44:24 +0000 (11:44 +0200)
When delivering notification to connections, make sure to check whether
their carried name is allowed by the destination endpoint's policy, and
supress the notification otherwise.

This is important to we don't leak notifications on added names if the
endpoint enforces a SEE policy.

Signed-off-by: Daniel Mack <daniel@zonque.org>
connection.c
endpoint.c
endpoint.h

index bf5e23d295e00cbbca6e037ef11444930b06839f..a0e90406f9276ca2fb9bbb56d1847adbfec60ae7 100644 (file)
@@ -566,6 +566,11 @@ static int kdbus_conn_broadcast(struct kdbus_ep *ep,
                                               kmsg))
                        continue;
 
+               ret = kdbus_ep_policy_check_notification(conn_dst->ep,
+                                                        conn_dst, kmsg);
+               if (ret < 0)
+                       continue;
+
                /*
                 * The first receiver which requests additional
                 * metadata causes the message to carry it; all
index 5801137b6ca770155587ec5c4ab8ce13a6e60e15..c9514bdef237ea3b0a39e27ff52017eb1c5b9d2d 100644 (file)
@@ -26,6 +26,7 @@
 #include "domain.h"
 #include "endpoint.h"
 #include "item.h"
+#include "message.h"
 #include "policy.h"
 
 /* endpoints are by default owned by the bus owner */
@@ -309,6 +310,54 @@ int kdbus_ep_policy_check_see_access_unlocked(struct kdbus_ep *ep,
        return ret;
 }
 
+/**
+ * kdbus_ep_policy_check_notification() - verify a connection is allowed to the
+ *                                       name in a notification
+ * @ep:                        Endpoint to operate on
+ * @conn:              Connection that lists names
+ * @kmsg               The message carrying the notification
+ *
+ * This verifies that @conn is allowed to see the well-known name inside a
+ * name-change notification contained in @msg via the endpoint @ep. If @msg
+ * is not a notification for name changes, this function does nothing but
+ * return 0.
+ *
+ * Return: 0 if allowed, negative error code if not.
+ */
+int kdbus_ep_policy_check_notification(struct kdbus_ep *ep,
+                                      struct kdbus_conn *conn,
+                                      const struct kdbus_kmsg *kmsg)
+{
+       int ret = 0;
+       const char *n = NULL;
+
+       if (kmsg->msg.src_id != KDBUS_SRC_ID_KERNEL)
+               return 0;
+
+       switch (kmsg->notify_type) {
+       case KDBUS_ITEM_NAME_ADD:
+       case KDBUS_ITEM_NAME_REMOVE:
+       case KDBUS_ITEM_NAME_CHANGE:
+               ret = kdbus_items_get_str(kmsg->msg.items,
+                                         KDBUS_ITEMS_SIZE(&kmsg->msg, items),
+                                         kmsg->notify_type, &n);
+               BUG_ON(!n);
+
+               down_read(&ep->policy_db.entries_rwlock);
+               mutex_lock(&conn->lock);
+
+               ret = kdbus_ep_policy_check_see_access_unlocked(ep, conn, n);
+
+               mutex_unlock(&conn->lock);
+               up_read(&ep->policy_db.entries_rwlock);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
 /**
  * kdbus_ep_policy_check_talk_access() - verify a connection can talk to the
  *                                      the passed connection
index 95f36a14d1990afce0c1c964486aadb023f6ad94..0e98028bff6f26efe27c7fefa79c9dbadaa47377 100644 (file)
@@ -73,6 +73,9 @@ int kdbus_ep_policy_set(struct kdbus_ep *ep,
 int kdbus_ep_policy_check_see_access_unlocked(struct kdbus_ep *ep,
                                              struct kdbus_conn *conn,
                                              const char *name);
+int kdbus_ep_policy_check_notification(struct kdbus_ep *ep,
+                                      struct kdbus_conn *conn,
+                                      const struct kdbus_kmsg *kmsg);
 int kdbus_ep_policy_check_talk_access(struct kdbus_ep *ep,
                                      struct kdbus_conn *conn_src,
                                      struct kdbus_conn *conn_dst);