diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-08-07 08:22:10 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-09-21 15:32:31 -0400 |
commit | 8669cbc5e651bf4effa20e8c244a5a7d67da6fe9 (patch) | |
tree | a97ac359c8041bc39efc0f32cac26772a43a0736 | |
parent | 3d45dbd611d1441d667b06acced9fbad3c8fcb1b (diff) |
drm: move drm authentication to new generic hash table.
Fix drm_remove_magic potential memory leak / corruption. Move drm
authentication token hashing to new generic hash table implementation.
Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r-- | drivers/char/drm/drmP.h | 8 | ||||
-rw-r--r-- | drivers/char/drm/drm_auth.c | 62 | ||||
-rw-r--r-- | drivers/char/drm/drm_drv.c | 10 | ||||
-rw-r--r-- | drivers/char/drm/drm_fops.c | 6 | ||||
-rw-r--r-- | drivers/char/drm/drm_hashtab.h | 2 |
5 files changed, 26 insertions, 62 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index c93985bb91a2..fedaf013f848 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -105,7 +105,7 @@ | |||
105 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then | 105 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then |
106 | also include looping detection. */ | 106 | also include looping detection. */ |
107 | 107 | ||
108 | #define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */ | 108 | #define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */ |
109 | #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ | 109 | #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ |
110 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ | 110 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ |
111 | #define DRM_LOOPING_LIMIT 5000000 | 111 | #define DRM_LOOPING_LIMIT 5000000 |
@@ -277,7 +277,8 @@ typedef struct drm_devstate { | |||
277 | } drm_devstate_t; | 277 | } drm_devstate_t; |
278 | 278 | ||
279 | typedef struct drm_magic_entry { | 279 | typedef struct drm_magic_entry { |
280 | drm_magic_t magic; | 280 | drm_hash_item_t hash_item; |
281 | struct list_head head; | ||
281 | struct drm_file *priv; | 282 | struct drm_file *priv; |
282 | struct drm_magic_entry *next; | 283 | struct drm_magic_entry *next; |
283 | } drm_magic_entry_t; | 284 | } drm_magic_entry_t; |
@@ -653,7 +654,8 @@ typedef struct drm_device { | |||
653 | /*@{ */ | 654 | /*@{ */ |
654 | drm_file_t *file_first; /**< file list head */ | 655 | drm_file_t *file_first; /**< file list head */ |
655 | drm_file_t *file_last; /**< file list tail */ | 656 | drm_file_t *file_last; /**< file list tail */ |
656 | drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */ | 657 | drm_open_hash_t magiclist; /**< magic hash table */ |
658 | struct list_head magicfree; | ||
657 | /*@} */ | 659 | /*@} */ |
658 | 660 | ||
659 | /** \name Memory management */ | 661 | /** \name Memory management */ |
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c index 2a37586a7ee8..40cd262ca9e1 100644 --- a/drivers/char/drm/drm_auth.c +++ b/drivers/char/drm/drm_auth.c | |||
@@ -36,20 +36,6 @@ | |||
36 | #include "drmP.h" | 36 | #include "drmP.h" |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Generate a hash key from a magic. | ||
40 | * | ||
41 | * \param magic magic. | ||
42 | * \return hash key. | ||
43 | * | ||
44 | * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be | ||
45 | * a power of 2. | ||
46 | */ | ||
47 | static int drm_hash_magic(drm_magic_t magic) | ||
48 | { | ||
49 | return magic & (DRM_HASH_SIZE - 1); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Find the file with the given magic number. | 39 | * Find the file with the given magic number. |
54 | * | 40 | * |
55 | * \param dev DRM device. | 41 | * \param dev DRM device. |
@@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
63 | { | 49 | { |
64 | drm_file_t *retval = NULL; | 50 | drm_file_t *retval = NULL; |
65 | drm_magic_entry_t *pt; | 51 | drm_magic_entry_t *pt; |
66 | int hash = drm_hash_magic(magic); | 52 | drm_hash_item_t *hash; |
67 | 53 | ||
68 | mutex_lock(&dev->struct_mutex); | 54 | mutex_lock(&dev->struct_mutex); |
69 | for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { | 55 | if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { |
70 | if (pt->magic == magic) { | 56 | pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); |
71 | retval = pt->priv; | 57 | retval = pt->priv; |
72 | break; | ||
73 | } | ||
74 | } | 58 | } |
75 | mutex_unlock(&dev->struct_mutex); | 59 | mutex_unlock(&dev->struct_mutex); |
76 | return retval; | 60 | return retval; |
@@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
90 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | 74 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, |
91 | drm_magic_t magic) | 75 | drm_magic_t magic) |
92 | { | 76 | { |
93 | int hash; | ||
94 | drm_magic_entry_t *entry; | 77 | drm_magic_entry_t *entry; |
95 | 78 | ||
96 | DRM_DEBUG("%d\n", magic); | 79 | DRM_DEBUG("%d\n", magic); |
97 | 80 | ||
98 | hash = drm_hash_magic(magic); | ||
99 | entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); | 81 | entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); |
100 | if (!entry) | 82 | if (!entry) |
101 | return -ENOMEM; | 83 | return -ENOMEM; |
102 | memset(entry, 0, sizeof(*entry)); | 84 | memset(entry, 0, sizeof(*entry)); |
103 | entry->magic = magic; | ||
104 | entry->priv = priv; | 85 | entry->priv = priv; |
105 | entry->next = NULL; | ||
106 | 86 | ||
87 | entry->hash_item.key = (unsigned long)magic; | ||
107 | mutex_lock(&dev->struct_mutex); | 88 | mutex_lock(&dev->struct_mutex); |
108 | if (dev->magiclist[hash].tail) { | 89 | drm_ht_insert_item(&dev->magiclist, &entry->hash_item); |
109 | dev->magiclist[hash].tail->next = entry; | 90 | list_add_tail(&entry->head, &dev->magicfree); |
110 | dev->magiclist[hash].tail = entry; | ||
111 | } else { | ||
112 | dev->magiclist[hash].head = entry; | ||
113 | dev->magiclist[hash].tail = entry; | ||
114 | } | ||
115 | mutex_unlock(&dev->struct_mutex); | 91 | mutex_unlock(&dev->struct_mutex); |
116 | 92 | ||
117 | return 0; | 93 | return 0; |
@@ -128,29 +104,19 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | |||
128 | */ | 104 | */ |
129 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) | 105 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) |
130 | { | 106 | { |
131 | drm_magic_entry_t *prev = NULL; | ||
132 | drm_magic_entry_t *pt; | 107 | drm_magic_entry_t *pt; |
133 | int hash; | 108 | drm_hash_item_t *hash; |
134 | 109 | ||
135 | DRM_DEBUG("%d\n", magic); | 110 | DRM_DEBUG("%d\n", magic); |
136 | hash = drm_hash_magic(magic); | ||
137 | 111 | ||
138 | mutex_lock(&dev->struct_mutex); | 112 | mutex_lock(&dev->struct_mutex); |
139 | for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { | 113 | if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { |
140 | if (pt->magic == magic) { | 114 | mutex_unlock(&dev->struct_mutex); |
141 | if (dev->magiclist[hash].head == pt) { | 115 | return -EINVAL; |
142 | dev->magiclist[hash].head = pt->next; | ||
143 | } | ||
144 | if (dev->magiclist[hash].tail == pt) { | ||
145 | dev->magiclist[hash].tail = prev; | ||
146 | } | ||
147 | if (prev) { | ||
148 | prev->next = pt->next; | ||
149 | } | ||
150 | mutex_unlock(&dev->struct_mutex); | ||
151 | return 0; | ||
152 | } | ||
153 | } | 116 | } |
117 | pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); | ||
118 | drm_ht_remove_item(&dev->magiclist, hash); | ||
119 | list_del(&pt->head); | ||
154 | mutex_unlock(&dev->struct_mutex); | 120 | mutex_unlock(&dev->struct_mutex); |
155 | 121 | ||
156 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 122 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 3da72f7364f0..f9ecc8414b8a 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -155,12 +155,10 @@ int drm_lastclose(drm_device_t * dev) | |||
155 | del_timer(&dev->timer); | 155 | del_timer(&dev->timer); |
156 | 156 | ||
157 | /* Clear pid list */ | 157 | /* Clear pid list */ |
158 | for (i = 0; i < DRM_HASH_SIZE; i++) { | 158 | list_for_each_entry_safe(pt, next, &dev->magicfree, head) { |
159 | for (pt = dev->magiclist[i].head; pt; pt = next) { | 159 | list_del(&pt->head); |
160 | next = pt->next; | 160 | drm_ht_remove_item(&dev->magiclist, &pt->hash_item); |
161 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 161 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
162 | } | ||
163 | dev->magiclist[i].head = dev->magiclist[i].tail = NULL; | ||
164 | } | 162 | } |
165 | 163 | ||
166 | /* Clear AGP information */ | 164 | /* Clear AGP information */ |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 51ccc82bf612..2bbf45d85c35 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev) | |||
72 | for (i = 0; i < ARRAY_SIZE(dev->counts); i++) | 72 | for (i = 0; i < ARRAY_SIZE(dev->counts); i++) |
73 | atomic_set(&dev->counts[i], 0); | 73 | atomic_set(&dev->counts[i], 0); |
74 | 74 | ||
75 | for (i = 0; i < DRM_HASH_SIZE; i++) { | 75 | drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER); |
76 | dev->magiclist[i].head = NULL; | 76 | INIT_LIST_HEAD(&dev->magicfree); |
77 | dev->magiclist[i].tail = NULL; | ||
78 | } | ||
79 | 77 | ||
80 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); | 78 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); |
81 | if (dev->ctxlist == NULL) | 79 | if (dev->ctxlist == NULL) |
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h index 40afec05bff8..9e19ef1814ba 100644 --- a/drivers/char/drm/drm_hashtab.h +++ b/drivers/char/drm/drm_hashtab.h | |||
@@ -35,7 +35,7 @@ | |||
35 | #ifndef DRM_HASHTAB_H | 35 | #ifndef DRM_HASHTAB_H |
36 | #define DRM_HASHTAB_H | 36 | #define DRM_HASHTAB_H |
37 | 37 | ||
38 | #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) | 38 | #define drm_hash_entry(_ptr, _type, _member) list_entry(_ptr, _type, _member) |
39 | 39 | ||
40 | typedef struct drm_hash_item{ | 40 | typedef struct drm_hash_item{ |
41 | struct hlist_node head; | 41 | struct hlist_node head; |