summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarol Lewandowski <k.lewandowsk@samsung.com>2014-05-12 19:03:34 +0200
committerMaciej Wereski <m.wereski@partner.samsung.com>2014-05-29 13:51:12 +0200
commit58aa8fb6ad8fd56a5d98f2266cb904713db5c326 (patch)
treedf8cb31dd23d48e96b89c15ee4a1f1a8d22d1a85
parentec3840de2ec4f92530e774237c472f461243b753 (diff)
downloadkdbus-bus-58aa8fb6ad8fd56a5d98f2266cb904713db5c326.tar.gz
kdbus-bus-58aa8fb6ad8fd56a5d98f2266cb904713db5c326.tar.bz2
kdbus-bus-58aa8fb6ad8fd56a5d98f2266cb904713db5c326.zip
Introduce lsm hooks for kdbus
This is combination of work by Karol Lewandowski and Paul Moore on LSM hooks for kdbus. [v1 Initial version] Signed-off-by: Karol Lewandowski <k.lewandowsk@samsung.com> [v2 added: memfd_seal added: bus_alloc/free added: ep_create ; ep_setpolicy ; ep_create added: read ; write ] Signed-off-by: Paul Moore <pmoore@redhat.com> [v3 Rebased on top of 11f6693c1 (compatible with systemd v212), dropped: memfd_seal - will be addressed in separately, renamed: ep_create -> ep_alloc (for consistency), renamed: send+recv -> talk, renamed: read -> recv ; write -> send, added: domain_alloc/free added: ep_free ] Signed-off-by: Karol Lewandowski <k.lewandowsk@samsung.com> [v4 Reverted many of v3 changes after comments by Paul renamed: ep_alloc -> ep_create (as introduced in v2) dropped: ep_free changed: send+recv takes (kdbus_conn *, kdbus_bus *) params changed: name_acquire takes kdbus_conn * param (as in v2)] Signed-off-by: Karol Lewandowski <k.lewandowsk@samsung.com>
-rw-r--r--bus.c10
-rw-r--r--bus.h2
-rw-r--r--connection.c48
-rw-r--r--connection.h2
-rw-r--r--domain.c14
-rw-r--r--domain.h1
-rw-r--r--endpoint.c11
-rw-r--r--names.c9
8 files changed, 94 insertions, 3 deletions
diff --git a/bus.c b/bus.c
index eb95de797a9..18a8d513ee0 100644
--- a/bus.c
+++ b/bus.c
@@ -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:
diff --git a/bus.h b/bus.h
index 3eda7273dea..6870816bef7 100644
--- a/bus.h
+++ b/bus.h
@@ -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;
diff --git a/domain.c b/domain.c
index 317284a132f..864656f96d8 100644
--- a/domain.c
+++ b/domain.c
@@ -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);
}
diff --git a/domain.h b/domain.h
index 91a7d5ee4db..6e6c765e21b 100644
--- a/domain.h
+++ b/domain.h
@@ -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);
}
diff --git a/names.c b/names.c
index a7761d10940..c6cc9057dc2 100644
--- a/names.c
+++ b/names.c
@@ -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(&reg->lock);