xref: /dflybsd-src/sys/dev/drm/drm_auth.c (revision 9edbd4a07c3138f5c4f076f77de5d722fcc606cc)
179f713b0SFrançois Tigeot /*-
27f3c3d6fSHasso Tepper  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
37f3c3d6fSHasso Tepper  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
47f3c3d6fSHasso Tepper  * All Rights Reserved.
57f3c3d6fSHasso Tepper  *
67f3c3d6fSHasso Tepper  * Permission is hereby granted, free of charge, to any person obtaining a
77f3c3d6fSHasso Tepper  * copy of this software and associated documentation files (the "Software"),
87f3c3d6fSHasso Tepper  * to deal in the Software without restriction, including without limitation
97f3c3d6fSHasso Tepper  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107f3c3d6fSHasso Tepper  * and/or sell copies of the Software, and to permit persons to whom the
117f3c3d6fSHasso Tepper  * Software is furnished to do so, subject to the following conditions:
127f3c3d6fSHasso Tepper  *
137f3c3d6fSHasso Tepper  * The above copyright notice and this permission notice (including the next
147f3c3d6fSHasso Tepper  * paragraph) shall be included in all copies or substantial portions of the
157f3c3d6fSHasso Tepper  * Software.
167f3c3d6fSHasso Tepper  *
177f3c3d6fSHasso Tepper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187f3c3d6fSHasso Tepper  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197f3c3d6fSHasso Tepper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207f3c3d6fSHasso Tepper  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
217f3c3d6fSHasso Tepper  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
227f3c3d6fSHasso Tepper  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
237f3c3d6fSHasso Tepper  * OTHER DEALINGS IN THE SOFTWARE.
2479f713b0SFrançois Tigeot  *
2579f713b0SFrançois Tigeot  * Authors:
2679f713b0SFrançois Tigeot  *    Rickard E. (Rik) Faith <faith@valinux.com>
2779f713b0SFrançois Tigeot  *    Gareth Hughes <gareth@valinux.com>
2879f713b0SFrançois Tigeot  *
2979f713b0SFrançois Tigeot  * $FreeBSD: src/sys/dev/drm2/drm_auth.c,v 1.1 2012/05/22 11:07:44 kib Exp $
3079f713b0SFrançois Tigeot  */
3179f713b0SFrançois Tigeot 
3279f713b0SFrançois Tigeot /** @file drm_auth.c
3379f713b0SFrançois Tigeot  * Implementation of the get/authmagic ioctls implementing the authentication
3479f713b0SFrançois Tigeot  * scheme between the master and clients.
357f3c3d6fSHasso Tepper  */
367f3c3d6fSHasso Tepper 
3718e26a6dSFrançois Tigeot #include <drm/drmP.h>
387f3c3d6fSHasso Tepper 
397f3c3d6fSHasso Tepper /**
40*9edbd4a0SFrançois Tigeot  * Find the file with the given magic number.
41*9edbd4a0SFrançois Tigeot  *
42*9edbd4a0SFrançois Tigeot  * \param dev DRM device.
43*9edbd4a0SFrançois Tigeot  * \param magic magic number.
44*9edbd4a0SFrançois Tigeot  *
45*9edbd4a0SFrançois Tigeot  * Searches in drm_device::magiclist within all files with the same hash key
46*9edbd4a0SFrançois Tigeot  * the one with matching magic number, while holding the drm_device::struct_mutex
47*9edbd4a0SFrançois Tigeot  * lock.
487f3c3d6fSHasso Tepper  */
4979f713b0SFrançois Tigeot static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic)
5079f713b0SFrançois Tigeot {
51*9edbd4a0SFrançois Tigeot 	struct drm_file *retval = NULL;
5279f713b0SFrançois Tigeot 	drm_magic_entry_t *pt;
53*9edbd4a0SFrançois Tigeot 	struct drm_hash_item *hash;
5479f713b0SFrançois Tigeot 
55*9edbd4a0SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
56*9edbd4a0SFrançois Tigeot 	if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
57*9edbd4a0SFrançois Tigeot 		pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
58*9edbd4a0SFrançois Tigeot 		retval = pt->priv;
5979f713b0SFrançois Tigeot 	}
60*9edbd4a0SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
61*9edbd4a0SFrançois Tigeot 	return retval;
6279f713b0SFrançois Tigeot }
6379f713b0SFrançois Tigeot 
6479f713b0SFrançois Tigeot /**
6579f713b0SFrançois Tigeot  * Inserts the given magic number into the hash table of used magic number
6679f713b0SFrançois Tigeot  * lists.
6779f713b0SFrançois Tigeot  */
6879f713b0SFrançois Tigeot static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
69b3705d71SHasso Tepper 			 drm_magic_t magic)
707f3c3d6fSHasso Tepper {
7179f713b0SFrançois Tigeot 	drm_magic_entry_t *entry;
7279f713b0SFrançois Tigeot 
737f3c3d6fSHasso Tepper 	DRM_DEBUG("%d\n", magic);
747f3c3d6fSHasso Tepper 
75*9edbd4a0SFrançois Tigeot 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
76b3705d71SHasso Tepper 	if (!entry)
77*9edbd4a0SFrançois Tigeot 		return -ENOMEM;
787f3c3d6fSHasso Tepper 	entry->priv = priv;
79*9edbd4a0SFrançois Tigeot 	entry->hash_item.key = (unsigned long)magic;
80*9edbd4a0SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
81*9edbd4a0SFrançois Tigeot 	drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
82*9edbd4a0SFrançois Tigeot 	list_add_tail(&entry->head, &dev->magicfree);
83*9edbd4a0SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
847f3c3d6fSHasso Tepper 
857f3c3d6fSHasso Tepper 	return 0;
867f3c3d6fSHasso Tepper }
877f3c3d6fSHasso Tepper 
887f3c3d6fSHasso Tepper /**
8979f713b0SFrançois Tigeot  * Removes the given magic number from the hash table of used magic number
9079f713b0SFrançois Tigeot  * lists.
917f3c3d6fSHasso Tepper  */
9279f713b0SFrançois Tigeot static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic)
937f3c3d6fSHasso Tepper {
9479f713b0SFrançois Tigeot 	drm_magic_entry_t *pt;
95*9edbd4a0SFrançois Tigeot 	struct drm_hash_item *hash;
967f3c3d6fSHasso Tepper 
977f3c3d6fSHasso Tepper 	DRM_DEBUG("%d\n", magic);
987f3c3d6fSHasso Tepper 
99*9edbd4a0SFrançois Tigeot 	mutex_lock(&dev->struct_mutex);
100*9edbd4a0SFrançois Tigeot 	if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
101*9edbd4a0SFrançois Tigeot 		mutex_unlock(&dev->struct_mutex);
102*9edbd4a0SFrançois Tigeot 		return -EINVAL;
1037f3c3d6fSHasso Tepper 	}
104*9edbd4a0SFrançois Tigeot 	pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
105*9edbd4a0SFrançois Tigeot 	drm_ht_remove_item(&dev->magiclist, hash);
106*9edbd4a0SFrançois Tigeot 	list_del(&pt->head);
107*9edbd4a0SFrançois Tigeot 	mutex_unlock(&dev->struct_mutex);
108*9edbd4a0SFrançois Tigeot 
109*9edbd4a0SFrançois Tigeot 	kfree(pt);
110*9edbd4a0SFrançois Tigeot 
1117f3c3d6fSHasso Tepper 	return 0;
1127f3c3d6fSHasso Tepper }
1137f3c3d6fSHasso Tepper 
1147f3c3d6fSHasso Tepper /**
11579f713b0SFrançois Tigeot  * Called by the client, this returns a unique magic number to be authorized
11679f713b0SFrançois Tigeot  * by the master.
1177f3c3d6fSHasso Tepper  *
11879f713b0SFrançois Tigeot  * The master may use its own knowledge of the client (such as the X
11979f713b0SFrançois Tigeot  * connection that the magic is passed over) to determine if the magic number
12079f713b0SFrançois Tigeot  * should be authenticated.
1217f3c3d6fSHasso Tepper  */
122b3705d71SHasso Tepper int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
1237f3c3d6fSHasso Tepper {
1247f3c3d6fSHasso Tepper 	static drm_magic_t sequence = 0;
125b3705d71SHasso Tepper 	struct drm_auth *auth = data;
1267f3c3d6fSHasso Tepper 
1277f3c3d6fSHasso Tepper 	/* Find unique magic */
1287f3c3d6fSHasso Tepper 	if (file_priv->magic) {
1297f3c3d6fSHasso Tepper 		auth->magic = file_priv->magic;
1307f3c3d6fSHasso Tepper 	} else {
13179f713b0SFrançois Tigeot 		DRM_LOCK(dev);
1327f3c3d6fSHasso Tepper 		do {
13379f713b0SFrançois Tigeot 			int old = sequence;
13479f713b0SFrançois Tigeot 
13579f713b0SFrançois Tigeot 			auth->magic = old+1;
13679f713b0SFrançois Tigeot 
13779f713b0SFrançois Tigeot 			if (!atomic_cmpset_int(&sequence, old, auth->magic))
13879f713b0SFrançois Tigeot 				continue;
13979f713b0SFrançois Tigeot 		} while (drm_find_file(dev, auth->magic));
1407f3c3d6fSHasso Tepper 		file_priv->magic = auth->magic;
14179f713b0SFrançois Tigeot 		drm_add_magic(dev, file_priv, auth->magic);
14279f713b0SFrançois Tigeot 		DRM_UNLOCK(dev);
1437f3c3d6fSHasso Tepper 	}
1447f3c3d6fSHasso Tepper 
1457f3c3d6fSHasso Tepper 	DRM_DEBUG("%u\n", auth->magic);
1467f3c3d6fSHasso Tepper 
1477f3c3d6fSHasso Tepper 	return 0;
1487f3c3d6fSHasso Tepper }
1497f3c3d6fSHasso Tepper 
1507f3c3d6fSHasso Tepper /**
15179f713b0SFrançois Tigeot  * Marks the client associated with the given magic number as authenticated.
1527f3c3d6fSHasso Tepper  */
153b3705d71SHasso Tepper int drm_authmagic(struct drm_device *dev, void *data,
154b3705d71SHasso Tepper 		  struct drm_file *file_priv)
1557f3c3d6fSHasso Tepper {
156b3705d71SHasso Tepper 	struct drm_auth *auth = data;
15779f713b0SFrançois Tigeot 	struct drm_file *priv;
1587f3c3d6fSHasso Tepper 
1597f3c3d6fSHasso Tepper 	DRM_DEBUG("%u\n", auth->magic);
16079f713b0SFrançois Tigeot 
16179f713b0SFrançois Tigeot 	DRM_LOCK(dev);
16279f713b0SFrançois Tigeot 	priv = drm_find_file(dev, auth->magic);
16379f713b0SFrançois Tigeot 	if (priv != NULL) {
16479f713b0SFrançois Tigeot 		priv->authenticated = 1;
16579f713b0SFrançois Tigeot 		drm_remove_magic(dev, auth->magic);
16679f713b0SFrançois Tigeot 		DRM_UNLOCK(dev);
1677f3c3d6fSHasso Tepper 		return 0;
16879f713b0SFrançois Tigeot 	} else {
16979f713b0SFrançois Tigeot 		DRM_UNLOCK(dev);
17079f713b0SFrançois Tigeot 		return EINVAL;
1717f3c3d6fSHasso Tepper 	}
1727f3c3d6fSHasso Tepper }
173