if (!kdbus_name_is_valid(name, false))
return -EINVAL;
- /* check if 'conn' is allowed to see 'name' */
- ret = kdbus_ep_policy_check_see_access(conn->ep, conn, name);
+ ret = kdbus_conn_policy_see_name(conn, name);
if (ret < 0)
return ret;
return kdbus_policy_check_talk_access(&conn->ep->bus->policy_db,
conn, to);
}
+
+/**
+ * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given
+ * name
+ * @conn: Connection
+ * @name: Name
+ *
+ * This verifies that @conn is allowed to see the well-known name @name. Caller
+ * must hold policy-lock.
+ *
+ * Return: 0 if allowed, negative error code if not.
+ */
+int kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
+ const char *name)
+{
+ int ret;
+
+ /*
+ * By default, all names are visible on a bus. SEE policies can only be
+ * installed on custom endpoints, where by default no name is visible.
+ */
+ if (!conn->ep->has_policy)
+ return 0;
+
+ ret = kdbus_policy_check_see_access_unlocked(&conn->ep->policy_db,
+ conn->cred, name);
+
+ /* don't leak hints whether a name exists on a custom endpoint. */
+ return (ret == -EPERM) ? -ENOENT : ret;
+}
+
+/**
+ * kdbus_conn_policy_see_name() - verify a connection can see a given name
+ * @conn: Connection
+ * @name: Name
+ *
+ * This verifies that @conn is allowed to see the well-known name @name.
+ *
+ * Return: 0 if allowed, negative error code if not.
+ */
+int kdbus_conn_policy_see_name(struct kdbus_conn *conn, const char *name)
+{
+ int ret;
+
+ down_read(&conn->ep->policy_db.entries_rwlock);
+ mutex_lock(&conn->lock);
+ ret = kdbus_conn_policy_see_name_unlocked(conn, name);
+ mutex_unlock(&conn->lock);
+ up_read(&conn->ep->policy_db.entries_rwlock);
+
+ return ret;
+}
int kdbus_conn_policy_own_name(struct kdbus_conn *conn, const char *name);
int kdbus_conn_policy_talk(struct kdbus_conn *conn, struct kdbus_conn *to);
+int kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
+ const char *name);
+int kdbus_conn_policy_see_name(struct kdbus_conn *conn, const char *name);
/* command dispatcher */
int kdbus_cmd_msg_send(struct kdbus_conn *conn_src,
return kdbus_policy_set(&ep->policy_db, items, items_size, 0, true, ep);
}
-/**
- * kdbus_ep_policy_check_see_access_unlocked() - verify a connection can see
- * the passed name
- * @ep: Endpoint to operate on
- * @conn: Connection that lists names
- * @name: Name that is tried to be listed
- *
- * This verifies that @conn is allowed to see the well-known name @name via the
- * endpoint @ep.
- *
- * Return: 0 if allowed, negative error code if not.
- */
-int kdbus_ep_policy_check_see_access_unlocked(struct kdbus_ep *ep,
- struct kdbus_conn *conn,
- const char *name)
-{
- int ret;
-
- /*
- * Check policy, if the endpoint of the connection has a db.
- * Note that policy DBs instanciated along with connections
- * don't have SEE rules, so it's sufficient to check the
- * endpoint's database.
- *
- * The lock for the policy db is held across all calls of
- * kdbus_name_list_all(), so the entries in both writing
- * and non-writing runs of kdbus_name_list_write() are the
- * same.
- */
-
- if (!ep->has_policy)
- return 0;
-
- ret = kdbus_policy_check_see_access_unlocked(&ep->policy_db,
- conn->cred, name);
-
- /* don't leak hints whether a name exists on a custom endpoint. */
- if (ret == -EPERM)
- return -ENOENT;
-
- return ret;
-}
-
-/**
- * kdbus_ep_policy_check_see_access() - verify a connection can see
- * the passed name
- * @ep: Endpoint to operate on
- * @conn: Connection that lists names
- * @name: Name that is tried to be listed
- *
- * This verifies that @conn is allowed to see the well-known name @name via the
- * endpoint @ep.
- *
- * Return: 0 if allowed, negative error code if not.
- */
-int kdbus_ep_policy_check_see_access(struct kdbus_ep *ep,
- struct kdbus_conn *conn,
- const char *name)
-{
- int ret;
-
- down_read(&ep->policy_db.entries_rwlock);
- mutex_lock(&conn->lock);
-
- ret = kdbus_ep_policy_check_see_access_unlocked(ep, conn, name);
-
- mutex_unlock(&conn->lock);
- up_read(&ep->policy_db.entries_rwlock);
-
- return ret;
-}
-
/**
* kdbus_ep_policy_check_notification() - verify a connection is allowed to see
* the name in a notification
case KDBUS_ITEM_NAME_ADD:
case KDBUS_ITEM_NAME_REMOVE:
case KDBUS_ITEM_NAME_CHANGE:
- ret = kdbus_ep_policy_check_see_access(ep, conn,
- kmsg->notify_name);
+ ret = kdbus_conn_policy_see_name(conn, kmsg->notify_name);
break;
default:
break;
* conn_dst
*/
list_for_each_entry(e, &conn_src->names_list, conn_entry) {
- ret = kdbus_ep_policy_check_see_access_unlocked(ep, conn_dst,
- e->name);
+ ret = kdbus_conn_policy_see_name_unlocked(conn_dst, e->name);
if (ret == 0)
break;
}
const struct kdbus_item *items,
size_t items_size);
-int kdbus_ep_policy_check_see_access_unlocked(struct kdbus_ep *ep,
- struct kdbus_conn *conn,
- const char *name);
-int kdbus_ep_policy_check_see_access(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);
if (!kdbus_name_is_valid(name, false))
return -EINVAL;
- ret = kdbus_ep_policy_check_see_access(conn->ep, conn, name);
+ ret = kdbus_conn_policy_see_name(conn, name);
if (ret < 0)
return ret;
u64 flags;
} h = {};
- if (e && kdbus_ep_policy_check_see_access_unlocked(conn->ep, conn,
- e->name) < 0)
- return 0;
+ if (e && kdbus_conn_policy_see_name_unlocked(conn, e->name) < 0)
+ return 0;
kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
struct kdbus_cmd_name_list *cmd)
{
struct kdbus_pool_slice *slice = NULL;
- struct kdbus_policy_db *policy_db;
struct kdbus_name_list list = {};
const struct kdbus_item *item;
struct kvec kvec;
}
}
- policy_db = &conn->ep->policy_db;
-
/* lock order: domain -> bus -> ep -> names -> conn */
down_read(®->rwlock);
down_read(&conn->ep->bus->conn_rwlock);
- down_read(&policy_db->entries_rwlock);
+ down_read(&conn->ep->policy_db.entries_rwlock);
/* size of header + records */
pos = sizeof(struct kdbus_name_list);
exit_unlock:
kdbus_pool_slice_release(slice);
- up_read(&policy_db->entries_rwlock);
+ up_read(&conn->ep->policy_db.entries_rwlock);
up_read(&conn->ep->bus->conn_rwlock);
up_read(®->rwlock);
return ret;