[systemd-devel] [PATCH 3/3] kdbus: get some creds during meta append for optimization

Djalal Harouni tixxdz at opendz.org
Mon Aug 18 18:43:58 PDT 2014


Some creds can be gathered during kdbus_meta_append() instead of
kdbus_conn_queue_alloc() where they will be gathered for all the
receivers and saved into each receivers queue before installing
on the slices.

By moving to kdbus_meta_append() it permits to do it only one time
for all the receivers, and we reduce some latency in
kdbus_conn_queue_alloc().

Another point is that all the receivers will get the same uid/gid even
if the current sender changes its creds while we are still queueing for
all receivers.

It seems that we can do the same with auxgroups, but this patch does
not implement it.

Patch tested with the test-kdbus-metadata-ns

Signed-off-by: Djalal Harouni <tixxdz at opendz.org>
---
 connection.c | 56 ++++++++++++++++++++++++++++++++++++--------------------
 metadata.c   |  6 +++++-
 metadata.h   | 26 ++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/connection.c b/connection.c
index 9250dab..49c5045 100644
--- a/connection.c
+++ b/connection.c
@@ -42,6 +42,24 @@
 struct kdbus_conn_reply;
 
 /**
+ * struct kdbus_queue_creds - internal creds data for receiver's
+ *			      queue
+ * @uid:		The UID to patch into the final message
+ * @gid:		The GID to patch into the final message
+ * @pid:		The PID to patch into the final message
+ * @tid:		The TID to patch into the final message
+ *
+ * Creds that must be translated into the receiver's namespaces
+ * when the message is installed into its slice.
+ */
+struct kdbus_queue_creds {
+	kuid_t uid;
+	kgid_t gid;
+	struct pid *pid;
+	struct pid *tid;
+};
+
+/**
  * struct kdbus_conn_queue - messages waiting to be read
  * @entry:		Entry in the connection's list
  * @prio_node:		Entry in the priority queue tree
@@ -67,10 +85,8 @@ struct kdbus_conn_reply;
  * @auxgrp_item_offset:	The offset of the auxgrp item inside the slice, if
  *			the user requested this metainfo in its attach flags.
  *			0 if unused.
- * @uid:		The UID to patch into the final message
- * @gid:		The GID to patch into the final message
- * @pid:		The PID to patch into the final message
- * @tid:		The TID to patch into the final message
+ * @qcreds		The creds that must be translated before
+ *			installing.
  * @auxgrps:		An array storing the sender's aux groups, in kgid_t.
  * 			This information is translated into the user's
  * 			namespace when the message is installed.
@@ -97,10 +113,7 @@ struct kdbus_conn_queue {
 	off_t auxgrp_item_offset;
 
 	/* to honor namespaces, we have to store the following here */
-	kuid_t uid;
-	kgid_t gid;
-	struct pid *pid;
-	struct pid *tid;
+	struct kdbus_queue_creds qcreds;
 
 	kgid_t *auxgrps;
 	unsigned int auxgrps_count;
@@ -466,10 +479,11 @@ static void kdbus_conn_queue_remove(struct kdbus_conn *conn,
 
 static void kdbus_conn_queue_cleanup(struct kdbus_conn_queue *queue)
 {
-	if (queue->pid)
-		put_pid(queue->pid);
-	if (queue->tid)
-		put_pid(queue->tid);
+	struct kdbus_queue_creds *qcreds = &queue->qcreds;
+	if (qcreds->pid)
+		put_pid(qcreds->pid);
+	if (qcreds->tid)
+		put_pid(qcreds->tid);
 	if (queue->auxgrps)
 		kfree(queue->auxgrps);
 
@@ -618,6 +632,7 @@ static int kdbus_conn_queue_alloc(struct kdbus_conn *conn,
 	/* append message metadata/credential items */
 	if (meta_off > 0) {
 		struct kdbus_meta *meta = kmsg->meta;
+		struct kdbus_queue_creds *qcreds = &queue->qcreds;
 
 		/*
 		 * If the receiver requested credential information, store the
@@ -626,10 +641,10 @@ static int kdbus_conn_queue_alloc(struct kdbus_conn *conn,
 		 */
 		if (meta->attached & KDBUS_ATTACH_CREDS) {
 			/* store kernel-view of the credentials */
-			queue->uid = current_uid();
-			queue->gid = current_gid();
-			queue->pid = get_task_pid(current, PIDTYPE_PID);
-			queue->tid = get_task_pid(current->group_leader,
+			qcreds->uid = meta->mcreds.uid;
+			qcreds->gid = meta->mcreds.gid;
+			qcreds->pid = get_task_pid(current, PIDTYPE_PID);
+			qcreds->tid = get_task_pid(current->group_leader,
 						  PIDTYPE_PID);
 
 			queue->creds_item_offset = meta_off +
@@ -968,14 +983,15 @@ static int kdbus_conn_creds_install(struct kdbus_conn_queue *queue)
 {
 	int ret;
 	struct kdbus_creds creds = {};
+	struct kdbus_queue_creds *qcreds = &queue->qcreds;
 	struct user_namespace *current_ns = current_user_ns();
 	off_t off = queue->creds_item_offset +
 		    offsetof(struct kdbus_item, creds);
 
-	creds.uid = from_kuid_munged(current_ns, queue->uid);
-	creds.gid = from_kgid_munged(current_ns, queue->gid);
-	creds.pid = pid_nr_ns(queue->pid, task_active_pid_ns(current));
-	creds.tid = pid_nr_ns(queue->tid, task_active_pid_ns(current));
+	creds.uid = from_kuid_munged(current_ns, qcreds->uid);
+	creds.gid = from_kgid_munged(current_ns, qcreds->gid);
+	creds.pid = pid_nr_ns(qcreds->pid, task_active_pid_ns(current));
+	creds.tid = pid_nr_ns(qcreds->tid, task_active_pid_ns(current));
 
 	ret = kdbus_pool_slice_copy_user(queue->slice, off,
 					 &creds, sizeof(creds));
diff --git a/metadata.c b/metadata.c
index 3dff9ac..100787d 100644
--- a/metadata.c
+++ b/metadata.c
@@ -187,9 +187,13 @@ static int kdbus_meta_append_cred(struct kdbus_meta *meta)
 {
 	struct kdbus_creds creds = {};
 
-	/* uid, gid, pid and tid will be filled later */
+	/* pid and tid will be filled later */
 	creds.starttime = current->start_time;
 
+	/* fill here */
+	meta->mcreds.uid = current_uid();
+	meta->mcreds.gid = current_gid();
+
 	return kdbus_meta_append_data(meta, KDBUS_ITEM_CREDS,
 				      &creds, sizeof(creds));
 }
diff --git a/metadata.h b/metadata.h
index 1bdb537..806ebca 100644
--- a/metadata.h
+++ b/metadata.h
@@ -14,6 +14,27 @@
 #define __KDBUS_METADATA_H
 
 /**
+ * struct kdbus_meta_creds - internal creds data
+ * @uid:                The UID of the sender
+ * @gid:                The GID of the sender
+ *
+ * Creds used for optimizations. We need to gather the info during
+ * kdbus_meta_append() before pushing into the receiver's queue,
+ * this way we do it only one time for all the receivers.
+ *
+ * These fields are then translated according to receiver's
+ * namespaces before installing on its slice as KDBUS_ITEM_* data.
+ *
+ * Only fields that can be safely gathered during
+ * kdbus_meta_append(), and must be translated later.
+ */
+struct kdbus_meta_creds {
+	kuid_t uid;
+	kgid_t gid;
+};
+
+
+/**
  * struct kdbus_meta - metadata buffer
  * @attached:		Flags for already attached data
  * @domain:		Domain the metadata belongs to
@@ -26,6 +47,9 @@
  * @auxgrps_item_off	The offset of the auxgroups item in the
  *			@data buffer field, if the user requested
  *			this metainfo. 0 if unused.
+ * @mcreds		Optimized creds that need to be translated
+ *			into the receiver's namespaces before
+ *			installing on its slice.
  *
  * Used to collect and store connection metadata in a pre-compiled
  * buffer containing struct kdbus_item.
@@ -39,6 +63,8 @@ struct kdbus_meta {
 
 	off_t creds_item_off;
 	off_t auxgrps_item_off;
+
+	struct kdbus_meta_creds mcreds;
 };
 
 struct kdbus_conn;
-- 
1.9.3



More information about the systemd-devel mailing list