summaryrefslogtreecommitdiffstats
path: root/kdbus.patch
diff options
context:
space:
mode:
Diffstat (limited to 'kdbus.patch')
-rw-r--r--kdbus.patch766
1 files changed, 766 insertions, 0 deletions
diff --git a/kdbus.patch b/kdbus.patch
index 6293d7038..307d2fcbd 100644
--- a/kdbus.patch
+++ b/kdbus.patch
@@ -49186,3 +49186,769 @@ index 27a5021fe70f..432dba4dcfdc 100644
--
2.4.3
+From 12000cd279ab5502006441c406ceba5bde44be71 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:20 +0200
+Subject: [PATCH 1/9] kdbus: return EBADSLT on replies without slot
+
+If you send a reply without an active reply slot, we used to return EPERM.
+However, this makes it impossible to distinguish this case from a real
+permission-denied error (eg., LSM). Hence, make sure we return a unique
+error-code if the reply-slot is missing.
+
+With this patch, you get EBADSLT ("Invalid slot") if you call
+KDBUS_CMD_SEND with a reply-cookie that has no valid slot.
+
+Reviewed-by: Daniel Mack <daniel@zonque.org>
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/connection.c | 2 +-
+ tools/testing/selftests/kdbus/test-message.c | 2 +-
+ tools/testing/selftests/kdbus/test-sync.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
+index d94b417e0f32..2787bd7d00c1 100644
+--- a/ipc/kdbus/connection.c
++++ b/ipc/kdbus/connection.c
+@@ -1123,7 +1123,7 @@ static int kdbus_conn_reply(struct kdbus_conn *src,
+ mutex_unlock(&dst->lock);
+
+ if (!reply) {
+- ret = -EPERM;
++ ret = -EBADSLT;
+ goto exit;
+ }
+
+diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c
+index ddc1e0af877b..563dc859077a 100644
+--- a/tools/testing/selftests/kdbus/test-message.c
++++ b/tools/testing/selftests/kdbus/test-message.c
+@@ -75,7 +75,7 @@ int kdbus_test_message_basic(struct kdbus_test_env *env)
+
+ /* Faked replies with a valid reply cookie are rejected */
+ ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id);
+- ASSERT_RETURN(ret == -EPERM);
++ ASSERT_RETURN(ret == -EBADSLT);
+
+ ret = kdbus_free(conn, offset);
+ ASSERT_RETURN(ret == 0);
+diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c
+index e2be910d2ece..0655a545fbf1 100644
+--- a/tools/testing/selftests/kdbus/test-sync.c
++++ b/tools/testing/selftests/kdbus/test-sync.c
+@@ -235,7 +235,7 @@ static void *run_thread_reply(void *data)
+
+ /* using an unknown cookie must fail */
+ ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id);
+- if (ret != -EPERM) {
++ if (ret != -EBADSLT) {
+ status = TEST_ERR;
+ goto exit_thread;
+ }
+--
+2.4.3
+
+
+From 2fee35fd480b2387e1f148fdc2125cc93708501b Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:21 +0200
+Subject: [PATCH 2/9] kdbus: reduce stack buffer to 256 bytes
+
+This reduces the stack-buffer for small ioctl payloads to 256 bytes. As
+seen during real workloads, this is more than enough. And we really
+should reduce stack pressure. Hence, lets limit the stack buffers to 256
+bytes.
+
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Daniel Mack <daniel@zonque.org>
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/handle.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
+index 8a36c0595091..5dde2c10bed4 100644
+--- a/ipc/kdbus/handle.h
++++ b/ipc/kdbus/handle.h
+@@ -45,7 +45,7 @@ struct kdbus_arg {
+ * @argv: array of items this command supports
+ * @user: set by parser to user-space location of current command
+ * @cmd: set by parser to kernel copy of command payload
+- * @cmd_buf: 512 bytes inline buf to avoid kmalloc() on small cmds
++ * @cmd_buf: inline buf to avoid kmalloc() on small cmds
+ * @items: points to item array in @cmd
+ * @items_size: size of @items in bytes
+ * @is_cmd: whether this is a command-payload or msg-payload
+@@ -55,7 +55,7 @@ struct kdbus_arg {
+ * the object to kdbus_args_parse(). The parser will copy the command payload
+ * into kernel-space and verify the correctness of the data.
+ *
+- * We use a 512 bytes buffer for small command payloads, to be allocated on
++ * We use a 256 bytes buffer for small command payloads, to be allocated on
+ * stack on syscall entrance.
+ */
+ struct kdbus_args {
+@@ -65,7 +65,7 @@ struct kdbus_args {
+
+ struct kdbus_cmd __user *user;
+ struct kdbus_cmd *cmd;
+- u8 cmd_buf[512];
++ u8 cmd_buf[256];
+
+ struct kdbus_item *items;
+ size_t items_size;
+--
+2.4.3
+
+
+From cff26ca42ae55286f5b8366302812d16bbc4a90a Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:22 +0200
+Subject: [PATCH 3/9] kdbus: use separate counter for message IDs
+
+For each kdbus domain, we maintain an ID-counter to guarantee unique IDs
+across all objects. We also used to use it for message IDs. However, this
+requires touching a shared cacheline on each message transaction, even
+though we never guaranteed global ordering across buses, anyway.
+
+Introduce a separate counter which is used solely for message IDs.
+Semantics stay the same, but it no longer relates to IDs across buses.
+
+Reviewed-by: Daniel Mack <daniel@zonque.org>
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/bus.h | 2 ++
+ ipc/kdbus/message.c | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h
+index 238986eff92f..8c2acaed6258 100644
+--- a/ipc/kdbus/bus.h
++++ b/ipc/kdbus/bus.h
+@@ -44,6 +44,7 @@ struct kdbus_user;
+ * @domain: Domain of this bus
+ * @creator: Creator of the bus
+ * @creator_meta: Meta information about the bus creator
++ * @last_message_id: Last used message id
+ * @policy_db: Policy database for this bus
+ * @name_registry: Name registry of this bus
+ * @conn_rwlock: Read/Write lock for all lists of child connections
+@@ -67,6 +68,7 @@ struct kdbus_bus {
+ struct kdbus_meta_proc *creator_meta;
+
+ /* protected by own locks */
++ atomic64_t last_message_id;
+ struct kdbus_policy_db policy_db;
+ struct kdbus_name_registry *name_registry;
+
+diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
+index 432dba4dcfdc..ae565cd343f8 100644
+--- a/ipc/kdbus/message.c
++++ b/ipc/kdbus/message.c
+@@ -671,7 +671,7 @@ static struct kdbus_staging *kdbus_staging_new(struct kdbus_bus *bus,
+ if (!staging)
+ return ERR_PTR(-ENOMEM);
+
+- staging->msg_seqnum = atomic64_inc_return(&bus->domain->last_id);
++ staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id);
+ staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */
+ staging->parts = (void *)(staging + 1);
+
+--
+2.4.3
+
+
+From 41c64712fef883818dadd5796f7522f675931d16 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:23 +0200
+Subject: [PATCH 4/9] kdbus: move privilege checking in kdbus_conn_new()
+
+Instead of relying on handle.c to perform privilege evaluation and
+passing information along, move this into kdbus_conn_new(). This has the
+benefit that we can now split 'owner' level and 'privileged' levels
+apart. This will be required for following extensions that need to
+distinguish both cases.
+
+Also, pass on 'struct file*' from handle into kdbus_conn_new(). Most
+kernel helpers cannot accept 'struct cred*' but instead only operate on
+files (and access file->f_cred then).
+
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/connection.c | 41 ++++++++++++++++++++++++++++++++---------
+ ipc/kdbus/connection.h | 6 ++++--
+ ipc/kdbus/handle.c | 2 +-
+ 3 files changed, 37 insertions(+), 12 deletions(-)
+
+diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
+index 2787bd7d00c1..243cbc77624e 100644
+--- a/ipc/kdbus/connection.c
++++ b/ipc/kdbus/connection.c
+@@ -52,7 +52,8 @@
+ #define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2)
+ #define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1)
+
+-static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
++static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
++ struct file *file,
+ struct kdbus_cmd_hello *hello,
+ const char *name,
+ const struct kdbus_creds *creds,
+@@ -72,6 +73,8 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
+ bool is_policy_holder;
+ bool is_activator;
+ bool is_monitor;
++ bool privileged;
++ bool owner;
+ struct kvec kvec;
+ int ret;
+
+@@ -81,6 +84,25 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
+ struct kdbus_bloom_parameter bloom;
+ } bloom_item;
+
++ /*
++ * A connection is considered privileged, if, and only if, it didn't
++ * connect through a custom endpoint *and* it has CAP_IPC_OWNER on the
++ * namespace of the current domain.
++ * Additionally, a connection is considered equivalent to the bus owner
++ * if it didn't connect through a custom endpoint *and* it either is
++ * privileged or the same user as the bus owner.
++ *
++ * Bus owners and alike can bypass bus policies. Privileged connections
++ * can additionally change accounting, modify kernel resources and
++ * perform restricted operations, as long as they're privileged on the
++ * same level as the resources they touch.
++ */
++ privileged = !ep->user &&
++ file_ns_capable(file, ep->bus->domain->user_namespace,
++ CAP_IPC_OWNER);
++ owner = !ep->user &&
++ (privileged || uid_eq(file->f_cred->euid, ep->bus->node.uid));
++
+ is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
+ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
+ is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER;
+@@ -97,9 +119,9 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
+ return ERR_PTR(-EINVAL);
+ if (is_monitor && ep->user)
+ return ERR_PTR(-EOPNOTSUPP);
+- if (!privileged && (is_activator || is_policy_holder || is_monitor))
++ if (!owner && (is_activator || is_policy_holder || is_monitor))
+ return ERR_PTR(-EPERM);
+- if ((creds || pids || seclabel) && !privileged)
++ if (!owner && (creds || pids || seclabel))
+ return ERR_PTR(-EPERM);
+
+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_send,
+@@ -129,12 +151,13 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
+ atomic_set(&conn->request_count, 0);
+ atomic_set(&conn->lost_count, 0);
+ INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
+- conn->cred = get_current_cred();
++ conn->cred = get_cred(file->f_cred);
+ conn->pid = get_pid(task_pid(current));
+ get_fs_root(current->fs, &conn->root_path);
+ init_waitqueue_head(&conn->wait);
+ kdbus_queue_init(&conn->queue);
+ conn->privileged = privileged;
++ conn->owner = owner;
+ conn->ep = kdbus_ep_ref(ep);
+ conn->id = atomic64_inc_return(&bus->domain->last_id);
+ conn->flags = hello->flags;
+@@ -1418,7 +1441,7 @@ bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
+ return false;
+ }
+
+- if (conn->privileged)
++ if (conn->owner)
+ return true;
+
+ res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds,
+@@ -1448,7 +1471,7 @@ bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
+ to, KDBUS_POLICY_TALK))
+ return false;
+
+- if (conn->privileged)
++ if (conn->owner)
+ return true;
+ if (uid_eq(conn_creds->euid, to->cred->uid))
+ return true;
+@@ -1567,12 +1590,12 @@ bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
+ /**
+ * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO
+ * @ep: Endpoint to operate on
+- * @privileged: Whether the caller is privileged
++ * @file: File this connection is opened on
+ * @argp: Command payload
+ *
+ * Return: NULL or newly created connection on success, ERR_PTR on failure.
+ */
+-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
+ void __user *argp)
+ {
+ struct kdbus_cmd_hello *cmd;
+@@ -1607,7 +1630,7 @@ struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
+
+ item_name = argv[1].item ? argv[1].item->str : NULL;
+
+- c = kdbus_conn_new(ep, privileged, cmd, item_name,
++ c = kdbus_conn_new(ep, file, cmd, item_name,
+ argv[2].item ? &argv[2].item->creds : NULL,
+ argv[3].item ? &argv[3].item->pids : NULL,
+ argv[4].item ? argv[4].item->str : NULL,
+diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h
+index 5ee864eb0e41..8e0180ace3f6 100644
+--- a/ipc/kdbus/connection.h
++++ b/ipc/kdbus/connection.h
+@@ -73,7 +73,8 @@ struct kdbus_staging;
+ * @activator_of: Well-known name entry this connection acts as an
+ * @names_list: List of well-known names
+ * @names_queue_list: Well-known names this connection waits for
+- * @privileged: Whether this connection is privileged on the bus
++ * @privileged: Whether this connection is privileged on the domain
++ * @owner: Owned by the same user as the bus owner
+ */
+ struct kdbus_conn {
+ struct kref kref;
+@@ -116,6 +117,7 @@ struct kdbus_conn {
+ struct list_head names_queue_list;
+
+ bool privileged:1;
++ bool owner:1;
+ };
+
+ struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn);
+@@ -154,7 +156,7 @@ bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
+ const struct kdbus_msg *msg);
+
+ /* command dispatcher */
+-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
+ void __user *argp);
+ int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
+ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
+diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
+index e0e06b0e1114..a93c385c6280 100644
+--- a/ipc/kdbus/handle.c
++++ b/ipc/kdbus/handle.c
+@@ -431,7 +431,7 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
+ break;
+
+ case KDBUS_CMD_HELLO:
+- conn = kdbus_cmd_hello(file_ep, handle->privileged, buf);
++ conn = kdbus_cmd_hello(file_ep, file, buf);
+ if (IS_ERR_OR_NULL(conn)) {
+ ret = PTR_ERR_OR_ZERO(conn);
+ break;
+--
+2.4.3
+
+
+From 1cd893dae99f8169c0f0620f343e3ee2379d0d28 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:24 +0200
+Subject: [PATCH 5/9] kdbus: perform accounting on proxied uids
+
+If a connection proxies a uid, we should make sure to perform accounting
+on that passed uid. Otherwise, limits will be shared across all proxied
+users (or we'd require the proxy to run setuid() and thus require
+CAP_SETUID).
+However, this is only allowed if the proxy is privileged on the bus. That
+is, it must have CAP_IPC_ADMIN on the domain and the passed uid must be
+mapped in that domain.
+
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/connection.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
+index 243cbc77624e..c81888ed1138 100644
+--- a/ipc/kdbus/connection.c
++++ b/ipc/kdbus/connection.c
+@@ -237,11 +237,21 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
+ * Note that limits are always accounted against the real UID, not
+ * the effective UID (cred->user always points to the accounting of
+ * cred->uid, not cred->euid).
++ * In case the caller is privileged, we allow changing the accounting
++ * to the faked user.
+ */
+ if (ep->user) {
+ conn->user = kdbus_user_ref(ep->user);
+ } else {
+- conn->user = kdbus_user_lookup(ep->bus->domain, current_uid());
++ kuid_t uid;
++
++ if (conn->meta_fake && uid_valid(conn->meta_fake->uid) &&
++ conn->privileged)
++ uid = conn->meta_fake->uid;
++ else
++ uid = conn->cred->uid;
++
++ conn->user = kdbus_user_lookup(ep->bus->domain, uid);
+ if (IS_ERR(conn->user)) {
+ ret = PTR_ERR(conn->user);
+ conn->user = NULL;
+--
+2.4.3
+
+
+From 9dad3c87e273ac8e895ec86252bd79792d49da77 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:25 +0200
+Subject: [PATCH 6/9] kdbus: inline privilege checks
+
+Instead of caching privilege information in 'kdbus_handle' (and thus
+increasing the size of each handle by 8 byte), perform privilege checks
+on the cached creds in file->f_cred inline. None of the functions that
+need those checks is a fast path (in fact, it's just EP_MAKE that needs
+it right now), so there's no need to cache the data.
+
+If more functions need this check later on, we should turn it into a
+small static helper.
+
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/handle.c | 34 +++++++++++-----------------------
+ 1 file changed, 11 insertions(+), 23 deletions(-)
+
+diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
+index a93c385c6280..4d41ecf9cc7d 100644
+--- a/ipc/kdbus/handle.c
++++ b/ipc/kdbus/handle.c
+@@ -264,7 +264,6 @@ enum kdbus_handle_type {
+ * @bus_owner: bus this handle owns
+ * @ep_owner: endpoint this handle owns
+ * @conn: connection this handle owns
+- * @privileged: Flag to mark a handle as privileged
+ */
+ struct kdbus_handle {
+ struct mutex lock;
+@@ -275,8 +274,6 @@ struct kdbus_handle {
+ struct kdbus_ep *ep_owner;
+ struct kdbus_conn *conn;
+ };
+-
+- bool privileged:1;
+ };
+
+ static int kdbus_handle_open(struct inode *inode, struct file *file)
+@@ -298,23 +295,6 @@ static int kdbus_handle_open(struct inode *inode, struct file *file)
+ mutex_init(&handle->lock);
+ handle->type = KDBUS_HANDLE_NONE;
+
+- if (node->type == KDBUS_NODE_ENDPOINT) {
+- struct kdbus_ep *ep = kdbus_ep_from_node(node);
+- struct kdbus_bus *bus = ep->bus;
+-
+- /*
+- * A connection is privileged if it is opened on an endpoint
+- * without custom policy and either:
+- * * the user has CAP_IPC_OWNER in the domain user namespace
+- * or
+- * * the callers euid matches the uid of the bus creator
+- */
+- if (!ep->user &&
+- (ns_capable(bus->domain->user_namespace, CAP_IPC_OWNER) ||
+- uid_eq(file->f_cred->euid, bus->node.uid)))
+- handle->privileged = true;
+- }
+-
+ file->private_data = handle;
+ ret = 0;
+
+@@ -406,6 +386,7 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
+ struct kdbus_handle *handle = file->private_data;
+ struct kdbus_node *node = file_inode(file)->i_private;
+ struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node);
++ struct kdbus_bus *bus = file_ep->bus;
+ struct kdbus_conn *conn;
+ int ret = 0;
+
+@@ -413,14 +394,20 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
+ return -ESHUTDOWN;
+
+ switch (cmd) {
+- case KDBUS_CMD_ENDPOINT_MAKE:
++ case KDBUS_CMD_ENDPOINT_MAKE: {
++ bool priv;
++
++ priv = uid_eq(file->f_cred->euid, bus->node.uid) ||
++ file_ns_capable(file, bus->domain->user_namespace,
++ CAP_IPC_OWNER);
++
+ /* creating custom endpoints is a privileged operation */
+- if (!handle->privileged) {
++ if (file_ep->user || !priv) {
+ ret = -EPERM;
+ break;
+ }
+
+- ep = kdbus_cmd_ep_make(file_ep->bus, buf);
++ ep = kdbus_cmd_ep_make(bus, buf);
+ if (IS_ERR_OR_NULL(ep)) {
+ ret = PTR_ERR_OR_ZERO(ep);
+ break;
+@@ -429,6 +416,7 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
+ handle->ep_owner = ep;
+ ret = KDBUS_HANDLE_EP_OWNER;
+ break;
++ }
+
+ case KDBUS_CMD_HELLO:
+ conn = kdbus_cmd_hello(file_ep, file, buf);
+--
+2.4.3
+
+
+From c4bf3679fb862abfc7064c975a5782cdb2a01c9e Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:26 +0200
+Subject: [PATCH 7/9] kdbus: consolidate common code
+
+Move the file-credential checkers into kdbus_ep_*() helper functions to
+avoid hard-coding the same behavior in multiple places.
+
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ ipc/kdbus/connection.c | 20 ++------------------
+ ipc/kdbus/endpoint.c | 28 ++++++++++++++++++++++++++++
+ ipc/kdbus/endpoint.h | 3 +++
+ ipc/kdbus/handle.c | 8 +-------
+ 4 files changed, 34 insertions(+), 25 deletions(-)
+
+diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
+index c81888ed1138..aa3296ea4f93 100644
+--- a/ipc/kdbus/connection.c
++++ b/ipc/kdbus/connection.c
+@@ -84,24 +84,8 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
+ struct kdbus_bloom_parameter bloom;
+ } bloom_item;
+
+- /*
+- * A connection is considered privileged, if, and only if, it didn't
+- * connect through a custom endpoint *and* it has CAP_IPC_OWNER on the
+- * namespace of the current domain.
+- * Additionally, a connection is considered equivalent to the bus owner
+- * if it didn't connect through a custom endpoint *and* it either is
+- * privileged or the same user as the bus owner.
+- *
+- * Bus owners and alike can bypass bus policies. Privileged connections
+- * can additionally change accounting, modify kernel resources and
+- * perform restricted operations, as long as they're privileged on the
+- * same level as the resources they touch.
+- */
+- privileged = !ep->user &&
+- file_ns_capable(file, ep->bus->domain->user_namespace,
+- CAP_IPC_OWNER);
+- owner = !ep->user &&
+- (privileged || uid_eq(file->f_cred->euid, ep->bus->node.uid));
++ privileged = kdbus_ep_is_privileged(ep, file);
++ owner = kdbus_ep_is_owner(ep, file);
+
+ is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
+ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
+diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c
+index 977964dbb44a..44e7a20de9c2 100644
+--- a/ipc/kdbus/endpoint.c
++++ b/ipc/kdbus/endpoint.c
+@@ -184,6 +184,34 @@ struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
+ }
+
+ /**
++ * kdbus_ep_is_privileged() - check whether a file is privileged
++ * @ep: endpoint to operate on
++ * @file: file to test
++ *
++ * Return: True if @file is privileged in the domain of @ep.
++ */
++bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file)
++{
++ return !ep->user &&
++ file_ns_capable(file, ep->bus->domain->user_namespace,
++ CAP_IPC_OWNER);
++}
++
++/**
++ * kdbus_ep_is_owner() - check whether a file should be treated as bus owner
++ * @ep: endpoint to operate on
++ * @file: file to test
++ *
++ * Return: True if @file should be treated as bus owner on @ep
++ */
++bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file)
++{
++ return !ep->user &&
++ (uid_eq(file->f_cred->euid, ep->bus->node.uid) ||
++ kdbus_ep_is_privileged(ep, file));
++}
++
++/**
+ * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE
+ * @bus: bus to operate on
+ * @argp: command payload
+diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h
+index bc1b94a70f93..e0da59f01a7a 100644
+--- a/ipc/kdbus/endpoint.h
++++ b/ipc/kdbus/endpoint.h
+@@ -61,6 +61,9 @@ struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name,
+ struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep);
+ struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
+
++bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file);
++bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file);
++
+ struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp);
+ int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp);
+
+diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
+index 4d41ecf9cc7d..fc60932d69c7 100644
+--- a/ipc/kdbus/handle.c
++++ b/ipc/kdbus/handle.c
+@@ -395,14 +395,8 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
+
+ switch (cmd) {
+ case KDBUS_CMD_ENDPOINT_MAKE: {
+- bool priv;
+-
+- priv = uid_eq(file->f_cred->euid, bus->node.uid) ||
+- file_ns_capable(file, bus->domain->user_namespace,
+- CAP_IPC_OWNER);
+-
+ /* creating custom endpoints is a privileged operation */
+- if (file_ep->user || !priv) {
++ if (!kdbus_ep_is_owner(file_ep, file)) {
+ ret = -EPERM;
+ break;
+ }
+--
+2.4.3
+
+
+From 146f50d92e16b684da73ecbb290d980babe98366 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:27 +0200
+Subject: [PATCH 8/9] kdbus/samples: skip if __NR_memfd_create is not defined
+
+We require __NR_memfd_create for the kdbus samples. Make sure we skip
+compilation if the target architecture and kernel do not support memfds.
+
+Reported-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Reviewed-by: Daniel Mack <daniel@zonque.org>
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ samples/kdbus/kdbus-workers.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
+index c3ba958639f3..5a6dfdce3bfd 100644
+--- a/samples/kdbus/kdbus-workers.c
++++ b/samples/kdbus/kdbus-workers.c
+@@ -59,9 +59,11 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <sys/syscall.h>
+
+ /* glibc < 2.7 does not ship sys/signalfd.h */
+-#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7
++/* we require kernels with __NR_memfd_create */
++#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7 && defined(__NR_memfd_create)
+
+ #include <ctype.h>
+ #include <errno.h>
+@@ -75,7 +77,6 @@
+ #include <sys/mman.h>
+ #include <sys/poll.h>
+ #include <sys/signalfd.h>
+-#include <sys/syscall.h>
+ #include <sys/time.h>
+ #include <sys/wait.h>
+ #include <time.h>
+--
+2.4.3
+
+
+From 917ee9c6252234fdb8e08670d3c31b6cef18e902 Mon Sep 17 00:00:00 2001
+From: David Herrmann <dh.herrmann@gmail.com>
+Date: Thu, 6 Aug 2015 10:21:28 +0200
+Subject: [PATCH 9/9] kdbus/tests: properly parse KDBUS_CMD_LIST objects
+
+There is no reason to assume the information returned by KDBUS_CMD_LIST
+contains only a single KDBUS_ITEM_OWNED_NAME. Parse each of them properly
+and don't bail out early.
+
+Reviewed-by: Daniel Mack <daniel@zonque.org>
+Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/kdbus/kdbus-util.c | 9 +++++----
+ tools/testing/selftests/kdbus/test-names.c | 17 +++++++++++------
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
+index a5e54ca3a492..82fa89b1a881 100644
+--- a/tools/testing/selftests/kdbus/kdbus-util.c
++++ b/tools/testing/selftests/kdbus/kdbus-util.c
+@@ -1155,11 +1155,12 @@ int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
+ if (item->type == KDBUS_ITEM_OWNED_NAME) {
+ n = item->name.name;
+ flags = item->name.flags;
+- }
+
+- kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
+- name->id, (unsigned long long) flags,
+- name->flags, n);
++ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
++ name->id,
++ (unsigned long long) flags,
++ name->flags, n);
++ }
+ }
+ kdbus_printf("\n");
+
+diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c
+index 66ebb47370eb..fd4ac5adc6d2 100644
+--- a/tools/testing/selftests/kdbus/test-names.c
++++ b/tools/testing/selftests/kdbus/test-names.c
+@@ -35,15 +35,20 @@ static int conn_is_name_owner(const struct kdbus_conn *conn,
+ struct kdbus_item *item;
+ const char *n = NULL;
+
+- KDBUS_ITEM_FOREACH(item, name, items)
+- if (item->type == KDBUS_ITEM_OWNED_NAME)
++ KDBUS_ITEM_FOREACH(item, name, items) {
++ if (item->type == KDBUS_ITEM_OWNED_NAME) {
+ n = item->name.name;
+
+- if (name->id == conn->id &&
+- n && strcmp(needle, n) == 0) {
+- found = true;
+- break;
++ if (name->id == conn->id &&
++ n && strcmp(needle, n) == 0) {
++ found = true;
++ break;
++ }
++ }
+ }
++
++ if (found)
++ break;
+ }
+
+ ret = kdbus_free(conn, cmd_list.offset);
+--
+2.4.3
+