[systemd-devel] [PATCH v2 4/7] kdbus: improve user quota accounting by using kdbus_domain_user_account()

Djalal Harouni tixxdz at opendz.org
Wed Jul 30 13:11:55 PDT 2014


Currently kdbus_domain_user_find_or_new() is used to find a user
domain or create a new one and link it into the domain.

kdbus_domain_user_find_or_new() may fail due to memory allocation
errors or if the domain was shutdown, but since callers will
receive only a NULL pointer on failure, they assume -ENOMEM and
ignore -ESHUTDOWN. Fix this in kdbus_domain_user_account() by returning
the appropriate error code.

There are also some races with kdbus_domain_user_find_or_new(), if it is
called with the same parameters and if we do not find a previously
linked domain user, then both threads will race to assign a different ID
for the same uid, thus, invalidating the users array. We fix this in the
new kdbus_domain_user_account() and __kdbus_domain_user_account() by
taking the domain lock only one time.

Replace some kdbus_domain_user_find_or_new() calls with
kdbus_domain_user_account(). The last one in bus.c is updated in the
next patch.

Signed-off-by: Djalal Harouni <tixxdz at opendz.org>
---
 connection.c | 12 ++++++------
 handle.c     |  8 ++++----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/connection.c b/connection.c
index 1658a92..8838029 100644
--- a/connection.c
+++ b/connection.c
@@ -2092,12 +2092,12 @@ int kdbus_conn_new(struct kdbus_ep *ep,
 	 */
 	if (ep->user)
 		conn->user = kdbus_domain_user_ref(ep->user);
-	else
-		conn->user = kdbus_domain_user_find_or_new(ep->bus->domain,
-							   current_fsuid());
-	if (!conn->user) {
-		ret = -ENOMEM;
-		goto exit_free_meta;
+	else {
+		ret = kdbus_domain_user_account(ep->bus->domain,
+						current_fsuid(),
+						&conn->user);
+		if (ret < 0)
+			goto exit_free_meta;
 	}
 
 	/* lock order: domain -> bus -> ep -> names -> conn */
diff --git a/handle.c b/handle.c
index bf32c6e..d8e1dc6 100644
--- a/handle.c
+++ b/handle.c
@@ -464,11 +464,11 @@ static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
 		 * endpoint users do not share the budget with the ordinary
 		 * users created for a UID.
 		 */
-		ep->user = kdbus_domain_user_find_or_new(
-				handle->ep->bus->domain, INVALID_UID);
-		if (!ep->user) {
+		ret = kdbus_domain_user_account(
+				handle->ep->bus->domain,
+				INVALID_UID, &ep->user);
+		if (ret < 0) {
 			kdbus_ep_unref(ep);
-			ret = -ENOMEM;
 			break;
 		}
 
-- 
1.9.3



More information about the systemd-devel mailing list