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