From 9a1bd42e36046e289d4c16350a15e1e2ea34e299 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 30 Jul 2014 21:11:53 +0100 Subject: [PATCH] domain: add __kdbus_domain_user_account() to account domain users Add __kdbus_domain_user_account() to account and link users into a domain. Signed-off-by: Djalal Harouni --- domain.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ domain.h | 4 ++++ 2 files changed, 74 insertions(+) diff --git a/domain.c b/domain.c index af9d986..11d7439 100644 --- a/domain.c +++ b/domain.c @@ -451,6 +451,76 @@ static int kdbus_domain_user_assign_id(struct kdbus_domain *domain, return 0; } +/** + * __kdbus_domain_user_account() - account a kdbus_domain_user object + * into the specified domain + * @domain: The domain of the user + * @uid: The uid of the user; INVALID_UID for an + * anonymous user like a custom endpoint + * @user Pointer to a reference where the accounted + * domain user will be stored. + * + * Return: 0 on success, negative errno on failure. + * + * On success: if there is a uid matching, then use the already + * accounted kdbus_domain_user, increment its reference counter and + * return it in the 'user' argument. Otherwise, allocate a new one, + * link it into the domain, then return it. + * + * On failure: the 'user' argument is not updated. + * + * Caller must have the domain lock held and must ensure that the + * domain was not disconnected. + */ +int __kdbus_domain_user_account(struct kdbus_domain *domain, + kuid_t uid, + struct kdbus_domain_user **user) +{ + int ret; + struct kdbus_domain_user *tmp_user; + struct kdbus_domain_user *u = NULL; + + /* find uid and reference it */ + if (uid_valid(uid)) { + hash_for_each_possible(domain->user_hash, tmp_user, + hentry, __kuid_val(uid)) { + if (!uid_eq(tmp_user->uid, uid)) + continue; + + u = kdbus_domain_user_ref(tmp_user); + goto out; + } + } + + ret = -ENOMEM; + u = kzalloc(sizeof(*u), GFP_KERNEL); + if (!u) + return ret; + + kref_init(&u->kref); + u->domain = kdbus_domain_ref(domain); + u->uid = uid; + atomic_set(&u->buses, 0); + atomic_set(&u->connections, 0); + + /* Assign user ID and link into domain */ + ret = kdbus_domain_user_assign_id(domain, u); + if (ret < 0) + goto exit_free; + + /* UID hash map */ + hash_add(domain->user_hash, &u->hentry, __kuid_val(u->uid)); + +out: + *user = u; + return 0; + +exit_free: + kdbus_domain_unref(u->domain); + kfree(u); + return ret; +} + /** * kdbus_domain_user_find_or_new() - get a kdbus_domain_user object in a domain * @domain: The domain diff --git a/domain.h b/domain.h index 9c477db..fd2940b 100644 --- a/domain.h +++ b/domain.h @@ -99,6 +99,10 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name, int kdbus_domain_make_user(struct kdbus_cmd_make *cmd, char **name); struct kdbus_domain *kdbus_domain_find_by_major(unsigned int major); +int __kdbus_domain_user_account(struct kdbus_domain *domain, + kuid_t uid, + struct kdbus_domain_user **user); + struct kdbus_domain_user *kdbus_domain_user_find_or_new(struct kdbus_domain *domain, kuid_t uid); struct kdbus_domain_user *kdbus_domain_user_ref(struct kdbus_domain_user *u); -- 2.34.1