2 * Copyright (C) 2013-2015 Kay Sievers
3 * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
4 * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
5 * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
6 * Copyright (C) 2013-2015 Linux Foundation
7 * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
9 * kdbus is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU Lesser General Public License as published by the
11 * Free Software Foundation; either version 2.1 of the License, or (at
12 * your option) any later version.
16 #include <linux/idr.h>
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/sched.h>
20 #include <linux/sizes.h>
21 #include <linux/slab.h>
22 #include <linux/uaccess.h>
31 static void kdbus_domain_control_free(struct kdbus_node *node)
36 static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain,
39 struct kdbus_node *node;
42 node = kzalloc(sizeof(*node), GFP_KERNEL);
44 return ERR_PTR(-ENOMEM);
46 kdbus_node_init(node, KDBUS_NODE_CONTROL);
48 node->free_cb = kdbus_domain_control_free;
49 node->mode = domain->node.mode;
50 node->mode = S_IRUSR | S_IWUSR;
51 if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
52 node->mode |= S_IRGRP | S_IWGRP;
53 if (access & KDBUS_MAKE_ACCESS_WORLD)
54 node->mode |= S_IROTH | S_IWOTH;
56 ret = kdbus_node_link(node, &domain->node, "control");
63 kdbus_node_deactivate(node);
64 kdbus_node_unref(node);
68 static void kdbus_domain_free(struct kdbus_node *node)
70 struct kdbus_domain *domain =
71 container_of(node, struct kdbus_domain, node);
73 put_user_ns(domain->user_namespace);
74 ida_destroy(&domain->user_ida);
75 idr_destroy(&domain->user_idr);
80 * kdbus_domain_new() - create a new domain
81 * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*)
83 * Return: a new kdbus_domain on success, ERR_PTR on failure
85 struct kdbus_domain *kdbus_domain_new(unsigned int access)
87 struct kdbus_domain *d;
90 d = kzalloc(sizeof(*d), GFP_KERNEL);
92 return ERR_PTR(-ENOMEM);
94 kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN);
96 d->node.free_cb = kdbus_domain_free;
97 d->node.mode = S_IRUSR | S_IXUSR;
98 if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
99 d->node.mode |= S_IRGRP | S_IXGRP;
100 if (access & KDBUS_MAKE_ACCESS_WORLD)
101 d->node.mode |= S_IROTH | S_IXOTH;
103 mutex_init(&d->lock);
104 idr_init(&d->user_idr);
105 ida_init(&d->user_ida);
107 /* Pin user namespace so we can guarantee domain-unique bus * names. */
108 d->user_namespace = get_user_ns(current_user_ns());
110 ret = kdbus_node_link(&d->node, NULL, NULL);
117 kdbus_node_deactivate(&d->node);
118 kdbus_node_unref(&d->node);
123 * kdbus_domain_ref() - take a domain reference
126 * Return: the domain itself
128 struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain)
131 kdbus_node_ref(&domain->node);
136 * kdbus_domain_unref() - drop a domain reference
139 * When the last reference is dropped, the domain internal structure
144 struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain)
147 kdbus_node_unref(&domain->node);
152 * kdbus_domain_populate() - populate static domain nodes
153 * @domain: domain to populate
154 * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes
156 * Allocate and activate static sub-nodes of the given domain. This will fail if
157 * you call it on a non-active node or if the domain was already populated.
159 * Return: 0 on success, negative error code on failure.
161 int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access)
163 struct kdbus_node *control;
166 * Create a control-node for this domain. We drop our own reference
167 * immediately, effectively causing the node to be deactivated and
168 * released when the parent domain is.
170 control = kdbus_domain_control_new(domain, access);
172 return PTR_ERR(control);
174 kdbus_node_activate(control);
175 kdbus_node_unref(control);
180 * kdbus_user_lookup() - lookup a kdbus_user object
181 * @domain: domain of the user
182 * @uid: uid of the user; INVALID_UID for an anon user
184 * Lookup the kdbus user accounting object for the given domain. If INVALID_UID
185 * is passed, a new anonymous user is created which is private to the caller.
187 * Return: The user object is returned, ERR_PTR on failure.
189 struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid)
191 struct kdbus_user *u = NULL, *old = NULL;
194 mutex_lock(&domain->lock);
196 if (uid_valid(uid)) {
197 old = idr_find(&domain->user_idr, __kuid_val(uid));
199 * If the object is about to be destroyed, ignore it and
200 * replace the slot in the IDR later on.
202 if (old && kref_get_unless_zero(&old->kref)) {
203 mutex_unlock(&domain->lock);
208 u = kzalloc(sizeof(*u), GFP_KERNEL);
215 u->domain = kdbus_domain_ref(domain);
217 atomic_set(&u->buses, 0);
218 atomic_set(&u->connections, 0);
220 if (uid_valid(uid)) {
222 idr_replace(&domain->user_idr, u, __kuid_val(uid));
223 old->uid = INVALID_UID; /* mark old as removed */
225 ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid),
226 __kuid_val(uid) + 1, GFP_KERNEL);
233 * Allocate the smallest possible index for this user; used
234 * in arrays for accounting user quota in receiver queues.
236 ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL);
241 mutex_unlock(&domain->lock);
246 if (uid_valid(u->uid))
247 idr_remove(&domain->user_idr, __kuid_val(u->uid));
248 kdbus_domain_unref(u->domain);
251 mutex_unlock(&domain->lock);
255 static void __kdbus_user_free(struct kref *kref)
257 struct kdbus_user *user = container_of(kref, struct kdbus_user, kref);
259 WARN_ON(atomic_read(&user->buses) > 0);
260 WARN_ON(atomic_read(&user->connections) > 0);
262 mutex_lock(&user->domain->lock);
263 ida_simple_remove(&user->domain->user_ida, user->id);
264 if (uid_valid(user->uid))
265 idr_remove(&user->domain->user_idr, __kuid_val(user->uid));
266 mutex_unlock(&user->domain->lock);
268 kdbus_domain_unref(user->domain);
273 * kdbus_user_ref() - take a user reference
276 * Return: @u is returned
278 struct kdbus_user *kdbus_user_ref(struct kdbus_user *u)
286 * kdbus_user_unref() - drop a user reference
291 struct kdbus_user *kdbus_user_unref(struct kdbus_user *u)
294 kref_put(&u->kref, __kdbus_user_free);