diff options
-rw-r--r-- | bus.c | 10 | ||||
-rw-r--r-- | bus.h | 2 | ||||
-rw-r--r-- | connection.c | 48 | ||||
-rw-r--r-- | connection.h | 2 | ||||
-rw-r--r-- | domain.c | 14 | ||||
-rw-r--r-- | domain.h | 1 | ||||
-rw-r--r-- | endpoint.c | 11 | ||||
-rw-r--r-- | names.c | 9 |
8 files changed, 94 insertions, 3 deletions
@@ -21,6 +21,7 @@ #include <linux/sizes.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/security.h> #include "bus.h" #include "connection.h" @@ -78,6 +79,7 @@ static void __kdbus_bus_free(struct kref *kref) kdbus_name_registry_free(bus->name_registry); kdbus_domain_unref(bus->domain); kdbus_policy_db_free(bus->policy_db); + security_kdbus_bus_free(bus); kfree(bus->name); kfree(bus); } @@ -259,9 +261,13 @@ int kdbus_bus_new(struct kdbus_domain *domain, if (ret < 0) goto exit_free_name; + ret = security_kdbus_bus_alloc(b); + if (ret) + goto exit_free_reg; + ret = kdbus_ep_new(b, "bus", mode, uid, gid, false, &b->ep); if (ret < 0) - goto exit_free_reg; + goto exit_free_security; /* account the bus against the user */ b->user = kdbus_domain_user_find_or_new(domain, uid); @@ -296,6 +302,8 @@ exit_unref_user_unlock: kdbus_domain_user_unref(b->user); exit_ep_unref: kdbus_ep_unref(b->ep); +exit_free_security: + security_kdbus_bus_free(b); exit_free_reg: kdbus_name_registry_free(b->name_registry); exit_free_name: @@ -41,6 +41,7 @@ * @id128: Unique random 128 bit ID of this bus * @user: Owner of the connection * @policy_db: Policy database for this bus + * @security: LSM security blob * * A bus provides a "bus" endpoint / device node. * @@ -70,6 +71,7 @@ struct kdbus_bus { u8 id128[16]; struct kdbus_domain_user *user; struct kdbus_policy_db *policy_db; + void *security; }; int kdbus_bus_make_user(const struct kdbus_cmd_make *make, diff --git a/connection.c b/connection.c index 06f8438394d..f7c57a37f2b 100644 --- a/connection.c +++ b/connection.c @@ -25,6 +25,7 @@ #include <linux/sizes.h> #include <linux/slab.h> #include <linux/syscalls.h> +#include <linux/security.h> #include "bus.h" #include "connection.h" @@ -849,6 +850,12 @@ static int kdbus_conn_fds_install(struct kdbus_conn *conn, int ret, *fds; size_t size; + for (i = 0; i < queue->fds_count; i++) { + ret = security_file_receive(queue->fds_fp[i]); + if (ret) + return ret; + } + /* get array of file descriptors */ size = queue->fds_count * sizeof(int); fds = kmalloc(size, GFP_KERNEL); @@ -897,6 +904,13 @@ static int kdbus_conn_memfds_install(struct kdbus_conn *conn, size_t size; int ret = 0; + for (i = 0; i < queue->memfds_count; i++) { + ret = security_file_receive(queue->memfds_fp[i]); + if (ret) + return ret; + } + + size = queue->memfds_count * sizeof(int); fds = kmalloc(size, GFP_KERNEL); if (!fds) @@ -993,6 +1007,10 @@ int kdbus_cmd_msg_recv(struct kdbus_conn *conn, LIST_HEAD(notify_list); int ret = 0; + ret = security_kdbus_recv(conn, conn->ep->bus); + if (ret) + return ret; + mutex_lock(&conn->lock); if (conn->msg_count == 0) { ret = -EAGAIN; @@ -1141,6 +1159,10 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, bool sync = msg->flags & KDBUS_MSG_FLAGS_SYNC_REPLY; int ret; + ret = security_kdbus_send(conn_src, bus); + if (ret) + return ret; + /* assign domain-global message sequence number */ BUG_ON(kmsg->seq > 0); kmsg->seq = atomic64_inc_return(&bus->domain->msg_seq_last); @@ -1199,6 +1221,10 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep, if (!conn_src) goto meta_append; + ret = security_kdbus_talk(conn_src, conn_dst); + if (ret) + return ret; + if (msg->flags & KDBUS_MSG_FLAGS_EXPECT_REPLY) { struct timespec ts; @@ -1592,6 +1618,7 @@ static void __kdbus_conn_free(struct kref *kref) kdbus_pool_free(conn->pool); kdbus_ep_unref(conn->ep); kdbus_bus_unref(conn->bus); + security_kdbus_conn_free(conn); kfree(conn->name); kfree(conn); } @@ -1736,6 +1763,10 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, mutex_unlock(&conn->bus->lock); } + ret = security_kdbus_conn_info(conn); + if (ret) + goto exit; + /* * If a lookup by name was requested, set owner_conn to the * matching entry's connection pointer. Otherwise, owner_conn @@ -1865,6 +1896,10 @@ int kdbus_cmd_conn_update(struct kdbus_conn *conn, return ret; } + ret = security_kdbus_ep_setpolicy(conn->bus); + if (ret) + return ret; + ret = kdbus_policy_set(conn->bus->policy_db, cmd->items, KDBUS_ITEMS_SIZE(cmd, items), 1, false, conn); @@ -1898,6 +1933,8 @@ int kdbus_conn_new(struct kdbus_ep *ep, bool is_policy_holder; bool is_activator; bool is_monitor; + u32 len, sid; + char *label; int ret; bus = ep->bus; @@ -1990,6 +2027,10 @@ int kdbus_conn_new(struct kdbus_ep *ep, goto exit_free_conn; } + ret = security_kdbus_ep_setpolicy(bus); + if (ret) + goto exit_free_conn; + /* * Policy holders may install any number of names, and * are allowed to use wildcards as well. @@ -2087,6 +2128,7 @@ int kdbus_conn_new(struct kdbus_ep *ep, } if (seclabel) { + /* XXX - this needs investigation, relabel? -- Paul */ ret = kdbus_meta_append_data(conn->owner_meta, KDBUS_ITEM_SECLABEL, seclabel, seclabel_len); @@ -2131,6 +2173,12 @@ int kdbus_conn_new(struct kdbus_ep *ep, goto exit_unref_user_unlock; } + security_task_getsecid(current, &sid); + security_secid_to_secctx(sid, &label, &len); + ret = security_kdbus_connect(conn, label, len); + if (ret < 0) + goto exit_unref_user_unlock; + /* link into bus and endpoint */ list_add_tail(&conn->ep_entry, &ep->conn_list); hash_add(bus->conn_hash, &conn->hentry, conn->id); diff --git a/connection.h b/connection.h index 43a9b6191d3..36e41583316 100644 --- a/connection.h +++ b/connection.h @@ -58,6 +58,7 @@ * @reply_count: Number of requests this connection has issued, and * waits for replies from the peer * @wait: Wake up this endpoint + * @security: LSM security blob */ struct kdbus_conn { struct kref kref; @@ -92,6 +93,7 @@ struct kdbus_conn { size_t msg_count; atomic_t reply_count; wait_queue_head_t wait; + void *security; }; struct kdbus_kmsg; @@ -19,6 +19,7 @@ #include <linux/sizes.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/security.h> #include "bus.h" #include "defaults.h" @@ -166,6 +167,7 @@ static void __kdbus_domain_free(struct kref *kref) kdbus_domain_disconnect(domain); kdbus_domain_unref(domain->parent); + security_kdbus_domain_free(domain); kfree(domain->name); kfree(domain->devpath); kfree(domain); @@ -262,12 +264,17 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name, atomic64_set(&d->msg_seq_last, 0); idr_init(&d->user_idr); + ret = security_kdbus_domain_alloc(d); + if (ret) + return ret; + /* lock order: parent domain -> domain -> subsys_lock */ if (parent) { mutex_lock(&parent->lock); if (parent->disconnected) { mutex_unlock(&parent->lock); - return -ESHUTDOWN; + ret = -ESHUTDOWN; + goto exit_free_security; } } @@ -363,6 +370,9 @@ exit_unlock: if (parent) mutex_unlock(&parent->lock); kdbus_domain_unref(d); +exit_free_security: + security_kdbus_domain_free(d); + return ret; } @@ -486,7 +496,7 @@ static void __kdbus_domain_user_free(struct kref *kref) idr_remove(&user->domain->user_idr, user->idr); hash_del(&user->hentry); mutex_unlock(&user->domain->lock); - + security_kdbus_domain_free(user->domain); kdbus_domain_unref(user->domain); kfree(user); } @@ -66,6 +66,7 @@ struct kdbus_domain { struct list_head bus_list; DECLARE_HASHTABLE(user_hash, 6); struct idr user_idr; + void *security; }; /** diff --git a/endpoint.c b/endpoint.c index 7e807db384f..d610569beda 100644 --- a/endpoint.c +++ b/endpoint.c @@ -19,6 +19,7 @@ #include <linux/sizes.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/security.h> #include "connection.h" #include "bus.h" @@ -232,6 +233,10 @@ int kdbus_ep_new(struct kdbus_bus *bus, const char *name, goto exit_dev_unregister; } + ret = security_kdbus_ep_create(bus); + if (ret) + goto exit_policy_db_free; + /* link into bus */ mutex_lock(&bus->lock); if (bus->disconnected) { @@ -276,12 +281,18 @@ int kdbus_ep_policy_set(struct kdbus_ep *ep, const struct kdbus_item *items, size_t items_size) { + int ret; + if (!ep->policy_db) return -ENOTSUPP; if (items_size == 0) return 0; + ret = security_kdbus_ep_setpolicy(ep->bus); + if (ret) + return ret; + return kdbus_policy_set(ep->policy_db, items, items_size, 0, true, ep); } @@ -21,6 +21,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/security.h> #include "bus.h" #include "connection.h" @@ -617,6 +618,10 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg, kdbus_conn_ref(conn); } + ret = security_kdbus_name_acquire(conn, cmd->name); + if (ret < 0) + goto exit_unref_conn; + if (conn->bus->policy_db) { ret = kdbus_policy_check_own_access(conn->bus->policy_db, conn, cmd->name); @@ -859,6 +864,10 @@ int kdbus_cmd_name_list(struct kdbus_name_registry *reg, policy_db = conn->ep->policy_db; + ret = security_kdbus_name_list(conn->bus); + if (ret) + return ret; + /* lock order: domain -> bus -> ep -> names -> conn */ mutex_lock(&conn->bus->lock); mutex_lock(®->lock); |