summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonrad Lipinski <konrad.l@samsung.com>2016-12-09 17:21:48 +0100
committerInki Dae <inki.dae@samsung.com>2017-01-12 01:15:43 -0800
commitd07e0df0ca20a1df62100485117df3d90a1a2a80 (patch)
tree4a59a966129647f40c15b7d0f6489eb3230cf1dc
parentfd9ae74878930bccb67c05bbd757b60f3c896e1c (diff)
kdbus: add CMD_UPDATE_METADATA ioctl (reinitialize connection metadata)
Added to satisfy efl/launchpad developers' request. Tizen code routinely performs the following operation sequence: 1. create kdbus connection 2. update seclabel 3. rely on updated seclabel CONN_INFO has always returned seclabel collected at HELLO time (behavior consistent across all kdbus versions and documented in kdbus man). This would break step 3 of the above sequence. KDBUS_CMD_UPDATE_METADATA ioctl updates a connection's metadata to reflect the current state. Metadata is collected in the exact same way as during HELLO. Semantics Required by efl/launchpad can be obtained by altering the sequence like so: 1. create kdbus connection 2. update seclabel +2b. ioctl(connection_fd, KDBUS_CMD_UPDATE_METADATA); 3. rely on updated seclabel Change-Id: I4a4b2aea4256f8bfb3bd1c0d3df5e963d243cb52 Signed-off-by: Konrad Lipinski <konrad.l@samsung.com>
-rw-r--r--include/uapi/linux/kdbus.h3
-rw-r--r--ipc/kdbus/connection.c85
-rw-r--r--ipc/kdbus/connection.h1
-rw-r--r--ipc/kdbus/handle.c4
-rw-r--r--ipc/kdbus/metadata.c63
-rw-r--r--ipc/kdbus/metadata.h65
6 files changed, 138 insertions, 83 deletions
diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h
index 4fc44cb1d4a8..778bccb2400e 100644
--- a/include/uapi/linux/kdbus.h
+++ b/include/uapi/linux/kdbus.h
@@ -979,6 +979,9 @@ enum kdbus_ioctl_type {
struct kdbus_cmd_match),
KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1,
struct kdbus_cmd_match),
+
+ /* Tizen */
+ KDBUS_CMD_UPDATE_METADATA = _IO(KDBUS_IOCTL_MAGIC, 0xd0),
};
#endif /* _UAPI_KDBUS_H_ */
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
index 02deba366839..2f850bdb508e 100644
--- a/ipc/kdbus/connection.c
+++ b/ipc/kdbus/connection.c
@@ -57,6 +57,8 @@
*/
#define DISABLE_KDBUS_POLICY
+static int kdbus_conn_meta_update(struct kdbus_conn *conn, bool first_time);
+
static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
struct file *file,
struct kdbus_cmd_hello *hello,
@@ -195,25 +197,7 @@ static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
if (ret < 0)
goto exit_unref;
} else {
- conn->meta_proc = kdbus_meta_proc_new();
- if (IS_ERR(conn->meta_proc)) {
- ret = PTR_ERR(conn->meta_proc);
- conn->meta_proc = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_proc_collect(conn->meta_proc,
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_EXE |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_AUDIT);
+ ret = kdbus_conn_meta_update(conn, 1);
if (ret < 0)
goto exit_unref;
}
@@ -1734,6 +1718,7 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
struct kdbus_name_owner *owner = NULL;
struct kdbus_conn *owner_conn = NULL;
struct kdbus_item *meta_items = NULL;
+ struct kdbus_meta_proc *meta_proc = NULL;
struct kdbus_info info = {};
struct kdbus_cmd_info *cmd;
struct kdbus_bus *bus = conn->ep->bus;
@@ -1805,7 +1790,13 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
if (ret < 0)
goto exit;
- ret = kdbus_meta_emit(owner_conn->meta_proc, owner_conn->meta_fake,
+ if (!owner_conn->meta_fake) {
+ rcu_read_lock();
+ meta_proc = rcu_dereference(owner_conn->meta_proc);
+ kdbus_meta_proc_ref(meta_proc);
+ rcu_read_unlock();
+ }
+ ret = kdbus_meta_emit(meta_proc, owner_conn->meta_fake,
conn_meta, conn, attach_flags,
&meta_items, &meta_size);
if (ret < 0)
@@ -1849,6 +1840,7 @@ exit:
kdbus_pool_slice_release(slice);
kfree(meta_items);
kdbus_meta_conn_unref(conn_meta);
+ kdbus_meta_proc_unref(meta_proc);
kdbus_conn_unref(owner_conn);
return kdbus_args_clear(&args, ret);
}
@@ -2243,3 +2235,56 @@ int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp)
return kdbus_args_clear(&args, ret);
}
+
+static int kdbus_conn_meta_update(struct kdbus_conn *conn, bool first_time)
+{
+ int ret;
+ struct kdbus_meta_proc *mp = kdbus_meta_proc_new();
+
+ if (IS_ERR(mp))
+ return PTR_ERR(mp);
+
+ ret = kdbus_meta_proc_collect(mp,
+ KDBUS_ATTACH_CREDS |
+ KDBUS_ATTACH_PIDS |
+ KDBUS_ATTACH_AUXGROUPS |
+ KDBUS_ATTACH_TID_COMM |
+ KDBUS_ATTACH_PID_COMM |
+ KDBUS_ATTACH_EXE |
+ KDBUS_ATTACH_CMDLINE |
+ KDBUS_ATTACH_CGROUP |
+ KDBUS_ATTACH_CAPS |
+ KDBUS_ATTACH_SECLABEL |
+ KDBUS_ATTACH_AUDIT);
+ if (ret < 0) {
+ kdbus_meta_proc_free(&mp->kref);
+ return ret;
+ }
+
+ if (first_time)
+ conn->meta_proc = mp;
+ else {
+ struct kdbus_meta_proc *old_meta;
+ mutex_lock(&conn->lock);
+ old_meta = conn->meta_proc;
+ rcu_assign_pointer(conn->meta_proc, mp);
+ synchronize_rcu();
+ mutex_unlock(&conn->lock);
+ kdbus_meta_proc_unref(old_meta);
+ }
+
+ return 0;
+}
+
+/**
+ * kdbus_cmd_update_metadata() - handle KDBUS_CMD_UPDATE_METADATA
+ * @conn: connection to operate on
+ *
+ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_update_metadata(struct kdbus_conn *conn)
+{
+ if (conn->meta_fake)
+ return -EOPNOTSUPP;
+ return kdbus_conn_meta_update(conn, 0);
+}
diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h
index 1ad082014faa..bd96a1cdb889 100644
--- a/ipc/kdbus/connection.h
+++ b/ipc/kdbus/connection.h
@@ -158,6 +158,7 @@ struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_update_metadata(struct kdbus_conn *conn);
int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp);
int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp);
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
index fc60932d69c7..c5ce6cf6f8fa 100644
--- a/ipc/kdbus/handle.c
+++ b/ipc/kdbus/handle.c
@@ -498,6 +498,9 @@ static long kdbus_handle_ioctl_connected(struct file *file,
case KDBUS_CMD_UPDATE:
ret = kdbus_cmd_update(conn, buf);
break;
+ case KDBUS_CMD_UPDATE_METADATA:
+ ret = kdbus_cmd_update_metadata(conn);
+ break;
case KDBUS_CMD_MATCH_ADD:
ret = kdbus_cmd_match_add(conn, buf);
break;
@@ -576,6 +579,7 @@ static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
case KDBUS_CMD_NAME_ACQUIRE:
case KDBUS_CMD_NAME_RELEASE:
case KDBUS_CMD_LIST:
+ case KDBUS_CMD_UPDATE_METADATA:
case KDBUS_CMD_CONN_INFO:
case KDBUS_CMD_BUS_CREATOR_INFO:
case KDBUS_CMD_UPDATE:
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index 106ec26f2882..e5dd313fb0cf 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -19,9 +19,7 @@
#include <linux/file.h>
#include <linux/fs_struct.h>
#include <linux/init.h>
-#include <linux/kref.h>
#include <linux/mutex.h>
-#include <linux/sched.h>
#include <linux/security.h>
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -39,65 +37,6 @@
#include "names.h"
/**
- * struct kdbus_meta_proc - Process metadata
- * @kref: Reference counting
- * @lock: Object lock
- * @collected: Bitmask of collected items
- * @valid: Bitmask of collected and valid items
- * @cred: Credentials
- * @pid: PID of process
- * @tgid: TGID of process
- * @ppid: PPID of process
- * @tid_comm: TID comm line
- * @pid_comm: PID comm line
- * @exe_path: Executable path
- * @root_path: Root-FS path
- * @cmdline: Command-line
- * @cgroup: Full cgroup path
- * @seclabel: Seclabel
- * @audit_loginuid: Audit login-UID
- * @audit_sessionid: Audit session-ID
- */
-struct kdbus_meta_proc {
- struct kref kref;
- struct mutex lock;
- u64 collected;
- u64 valid;
-
- /* KDBUS_ITEM_CREDS */
- /* KDBUS_ITEM_AUXGROUPS */
- /* KDBUS_ITEM_CAPS */
- const struct cred *cred;
-
- /* KDBUS_ITEM_PIDS */
- struct pid *pid;
- struct pid *tgid;
- struct pid *ppid;
-
- /* KDBUS_ITEM_TID_COMM */
- char tid_comm[TASK_COMM_LEN];
- /* KDBUS_ITEM_PID_COMM */
- char pid_comm[TASK_COMM_LEN];
-
- /* KDBUS_ITEM_EXE */
- struct path exe_path;
- struct path root_path;
-
- /* KDBUS_ITEM_CMDLINE */
- char *cmdline;
-
- /* KDBUS_ITEM_CGROUP */
- char *cgroup;
-
- /* KDBUS_ITEM_SECLABEL */
- char *seclabel;
-
- /* KDBUS_ITEM_AUDIT */
- kuid_t audit_loginuid;
- unsigned int audit_sessionid;
-};
-
-/**
* struct kdbus_meta_conn
* @kref: Reference counting
* @lock: Object lock
@@ -152,7 +91,7 @@ struct kdbus_meta_proc *kdbus_meta_proc_new(void)
return mp;
}
-static void kdbus_meta_proc_free(struct kref *kref)
+void kdbus_meta_proc_free(struct kref *kref)
{
struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc,
kref);
diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h
index dba7cc7fdbcb..e8d8433d4b0f 100644
--- a/ipc/kdbus/metadata.h
+++ b/ipc/kdbus/metadata.h
@@ -16,14 +16,76 @@
#define __KDBUS_METADATA_H
#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/path.h>
+#include <linux/sched.h>
struct kdbus_conn;
struct kdbus_pool_slice;
-struct kdbus_meta_proc;
struct kdbus_meta_conn;
/**
+ * struct kdbus_meta_proc - Process metadata
+ * @kref: Reference counting
+ * @lock: Object lock
+ * @collected: Bitmask of collected items
+ * @valid: Bitmask of collected and valid items
+ * @cred: Credentials
+ * @pid: PID of process
+ * @tgid: TGID of process
+ * @ppid: PPID of process
+ * @tid_comm: TID comm line
+ * @pid_comm: PID comm line
+ * @exe_path: Executable path
+ * @root_path: Root-FS path
+ * @cmdline: Command-line
+ * @cgroup: Full cgroup path
+ * @seclabel: Seclabel
+ * @audit_loginuid: Audit login-UID
+ * @audit_sessionid: Audit session-ID
+ */
+struct kdbus_meta_proc {
+ struct kref kref;
+ struct mutex lock;
+ u64 collected;
+ u64 valid;
+
+ /* KDBUS_ITEM_CREDS */
+ /* KDBUS_ITEM_AUXGROUPS */
+ /* KDBUS_ITEM_CAPS */
+ const struct cred *cred;
+
+ /* KDBUS_ITEM_PIDS */
+ struct pid *pid;
+ struct pid *tgid;
+ struct pid *ppid;
+
+ /* KDBUS_ITEM_TID_COMM */
+ char tid_comm[TASK_COMM_LEN];
+ /* KDBUS_ITEM_PID_COMM */
+ char pid_comm[TASK_COMM_LEN];
+
+ /* KDBUS_ITEM_EXE */
+ struct path exe_path;
+ struct path root_path;
+
+ /* KDBUS_ITEM_CMDLINE */
+ char *cmdline;
+
+ /* KDBUS_ITEM_CGROUP */
+ char *cgroup;
+
+ /* KDBUS_ITEM_SECLABEL */
+ char *seclabel;
+
+ /* KDBUS_ITEM_AUDIT */
+ kuid_t audit_loginuid;
+ unsigned int audit_sessionid;
+};
+
+
+/**
* struct kdbus_meta_fake - Fake metadata
* @valid: Bitmask of collected and valid items
* @uid: UID of process
@@ -56,6 +118,7 @@ struct kdbus_meta_fake {
struct kdbus_meta_proc *kdbus_meta_proc_new(void);
struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp);
struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp);
+void kdbus_meta_proc_free(struct kref *mpkref);
int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what);
struct kdbus_meta_fake *kdbus_meta_fake_new(void);