OSDN Git Service

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