Update to latest upstream kdbus
Commit 917ee9c62522
This commit is contained in:
parent
c3a77ea556
commit
2d19b299b6
766
kdbus.patch
766
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user