xref: /titanic_44/usr/src/uts/common/io/drm/drm_auth.c (revision 9dd0f810214fdc8e1af881a9a5c4b6927629ff9e)
1 /*
2  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
8  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
9  */
10 /*
11  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
12  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
13  * All Rights Reserved.
14  *
15  * Permission is hereby granted, free of charge, to any person obtaining a
16  * copy of this software and associated documentation files (the "Software"),
17  * to deal in the Software without restriction, including without limitation
18  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19  * and/or sell copies of the Software, and to permit persons to whom the
20  * Software is furnished to do so, subject to the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the next
23  * paragraph) shall be included in all copies or substantial portions of the
24  * Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
29  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
30  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
31  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32  * OTHER DEALINGS IN THE SOFTWARE.
33  *
34  * Authors:
35  *    Rickard E. (Rik) Faith <faith@valinux.com>
36  *    Gareth Hughes <gareth@valinux.com>
37  *
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 #include "drmP.h"
43 
44 static int
45 drm_hash_magic(drm_magic_t magic)
46 {
47 	return (magic & (DRM_HASH_SIZE-1));
48 }
49 
50 drm_file_t *
51 drm_find_file(drm_device_t *dev, drm_magic_t magic)
52 {
53 	drm_file_t	  *retval = NULL;
54 	drm_magic_entry_t *pt;
55 	int		  hash;
56 
57 	hash = drm_hash_magic(magic);
58 
59 	DRM_LOCK();
60 	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
61 		if (pt->magic == magic) {
62 			retval = pt->priv;
63 			break;
64 		}
65 	}
66 	DRM_UNLOCK();
67 	return (retval);
68 }
69 
70 static int
71 drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
72 {
73 	int		  hash;
74 	drm_magic_entry_t *entry;
75 
76 	DRM_DEBUG("drm_add_magic: %d", magic);
77 
78 	hash = drm_hash_magic(magic);
79 	entry = drm_alloc(sizeof (*entry), DRM_MEM_MAGIC);
80 	if (!entry)
81 		return (DRM_ERR(ENOMEM));
82 	entry->magic = magic;
83 	entry->priv  = priv;
84 	entry->next  = NULL;
85 
86 	DRM_LOCK();
87 	if (dev->magiclist[hash].tail) {
88 		dev->magiclist[hash].tail->next = entry;
89 		dev->magiclist[hash].tail	= entry;
90 	} else {
91 		dev->magiclist[hash].head	= entry;
92 		dev->magiclist[hash].tail	= entry;
93 	}
94 	DRM_UNLOCK();
95 
96 	return (0);
97 }
98 
99 int
100 drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
101 {
102 	drm_magic_entry_t *prev = NULL;
103 	drm_magic_entry_t *pt;
104 	int		  hash;
105 
106 	DRM_DEBUG("drm_remove_magic : %d", magic);
107 	hash = drm_hash_magic(magic);
108 
109 	DRM_LOCK();
110 	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
111 		if (pt->magic == magic) {
112 			if (dev->magiclist[hash].head == pt) {
113 				dev->magiclist[hash].head = pt->next;
114 			}
115 			if (dev->magiclist[hash].tail == pt) {
116 				dev->magiclist[hash].tail = prev;
117 			}
118 			if (prev) {
119 				prev->next = pt->next;
120 			}
121 			DRM_UNLOCK();
122 			drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC);
123 			return (0);
124 		}
125 	}
126 	DRM_UNLOCK();
127 
128 	return (DRM_ERR(EINVAL));
129 }
130 
131 /*ARGSUSED*/
132 int
133 drm_getmagic(DRM_IOCTL_ARGS)
134 {
135 	DRM_DEVICE;
136 	static drm_magic_t sequence = 0;
137 	drm_auth_t auth;
138 	drm_file_t *priv;
139 
140 	DRM_LOCK();
141 	priv = drm_find_file_by_proc(dev, credp);
142 	DRM_UNLOCK();
143 	if (priv == NULL) {
144 		DRM_ERROR("drm_getmagic: can't find authenticator");
145 		return (DRM_ERR(EINVAL));
146 	}
147 
148 	/* Find unique magic */
149 	if (priv->magic) {
150 		auth.magic = priv->magic;
151 	} else {
152 		do {
153 			int old = sequence;
154 			auth.magic = old+1;
155 			if (!atomic_cmpset_int(&sequence, old, auth.magic))
156 				continue;
157 		} while (drm_find_file(dev, auth.magic));
158 		priv->magic = auth.magic;
159 		(void) drm_add_magic(dev, priv, auth.magic);
160 	}
161 
162 	DRM_DEBUG("drm_getmagic: %u", auth.magic);
163 
164 	DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof (auth));
165 
166 	return (0);
167 }
168 
169 /*ARGSUSED*/
170 int
171 drm_authmagic(DRM_IOCTL_ARGS)
172 {
173 	drm_auth_t	   auth;
174 	drm_file_t	   *file;
175 	DRM_DEVICE;
176 
177 	DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof (auth));
178 
179 	DRM_DEBUG("drm_authmagic %u", auth.magic);
180 
181 	if ((file = drm_find_file(dev, auth.magic))) {
182 		file->authenticated = 1;
183 		(void) drm_remove_magic(dev, auth.magic);
184 		return (0);
185 	}
186 	return (DRM_ERR(EINVAL));
187 }
188