kdbus: add CMD_UPDATE_METADATA ioctl (reinitialize connection metadata) 74/103874/4
authorKonrad Lipinski <konrad.l@samsung.com>
Fri, 9 Dec 2016 16:21:48 +0000 (17:21 +0100)
committerInki Dae <inki.dae@samsung.com>
Thu, 12 Jan 2017 09:15:43 +0000 (01:15 -0800)
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>
include/uapi/linux/kdbus.h
ipc/kdbus/connection.c
ipc/kdbus/connection.h
ipc/kdbus/handle.c
ipc/kdbus/metadata.c
ipc/kdbus/metadata.h

index 4fc44cb..778bccb 100644 (file)
@@ -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_ */
index 02deba3..2f850bd 100644 (file)
@@ -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);
+}
index 1ad0820..bd96a1c 100644 (file)
@@ -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);
index fc60932..c5ce6cf 100644 (file)
@@ -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:
index 106ec26..e5dd313 100644 (file)
@@ -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>
 #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);
index dba7cc7..e8d8433 100644 (file)
 #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);