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@opendz.org>
*/
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 */
* 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;
}