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 <tix...@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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel