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>
This commit is contained in:
parent
3d45dbd611
commit
8669cbc5e6
|
@ -105,7 +105,7 @@
|
||||||
#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
|
#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
|
||||||
also include looping detection. */
|
also include looping detection. */
|
||||||
|
|
||||||
#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
|
#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
|
||||||
#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
|
#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
|
||||||
#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
|
#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
|
||||||
#define DRM_LOOPING_LIMIT 5000000
|
#define DRM_LOOPING_LIMIT 5000000
|
||||||
|
@ -277,7 +277,8 @@ typedef struct drm_devstate {
|
||||||
} drm_devstate_t;
|
} drm_devstate_t;
|
||||||
|
|
||||||
typedef struct drm_magic_entry {
|
typedef struct drm_magic_entry {
|
||||||
drm_magic_t magic;
|
drm_hash_item_t hash_item;
|
||||||
|
struct list_head head;
|
||||||
struct drm_file *priv;
|
struct drm_file *priv;
|
||||||
struct drm_magic_entry *next;
|
struct drm_magic_entry *next;
|
||||||
} drm_magic_entry_t;
|
} drm_magic_entry_t;
|
||||||
|
@ -653,7 +654,8 @@ typedef struct drm_device {
|
||||||
/*@{ */
|
/*@{ */
|
||||||
drm_file_t *file_first; /**< file list head */
|
drm_file_t *file_first; /**< file list head */
|
||||||
drm_file_t *file_last; /**< file list tail */
|
drm_file_t *file_last; /**< file list tail */
|
||||||
drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
|
drm_open_hash_t magiclist; /**< magic hash table */
|
||||||
|
struct list_head magicfree;
|
||||||
/*@} */
|
/*@} */
|
||||||
|
|
||||||
/** \name Memory management */
|
/** \name Memory management */
|
||||||
|
|
|
@ -35,20 +35,6 @@
|
||||||
|
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a hash key from a magic.
|
|
||||||
*
|
|
||||||
* \param magic magic.
|
|
||||||
* \return hash key.
|
|
||||||
*
|
|
||||||
* The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
|
|
||||||
* a power of 2.
|
|
||||||
*/
|
|
||||||
static int drm_hash_magic(drm_magic_t magic)
|
|
||||||
{
|
|
||||||
return magic & (DRM_HASH_SIZE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the file with the given magic number.
|
* Find the file with the given magic number.
|
||||||
*
|
*
|
||||||
|
@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
|
||||||
{
|
{
|
||||||
drm_file_t *retval = NULL;
|
drm_file_t *retval = NULL;
|
||||||
drm_magic_entry_t *pt;
|
drm_magic_entry_t *pt;
|
||||||
int hash = drm_hash_magic(magic);
|
drm_hash_item_t *hash;
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
|
||||||
if (pt->magic == magic) {
|
pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
|
||||||
retval = pt->priv;
|
retval = pt->priv;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
|
||||||
static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
|
static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
|
||||||
drm_magic_t magic)
|
drm_magic_t magic)
|
||||||
{
|
{
|
||||||
int hash;
|
|
||||||
drm_magic_entry_t *entry;
|
drm_magic_entry_t *entry;
|
||||||
|
|
||||||
DRM_DEBUG("%d\n", magic);
|
DRM_DEBUG("%d\n", magic);
|
||||||
|
|
||||||
hash = drm_hash_magic(magic);
|
|
||||||
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
|
entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memset(entry, 0, sizeof(*entry));
|
memset(entry, 0, sizeof(*entry));
|
||||||
entry->magic = magic;
|
|
||||||
entry->priv = priv;
|
entry->priv = priv;
|
||||||
entry->next = NULL;
|
|
||||||
|
|
||||||
|
entry->hash_item.key = (unsigned long)magic;
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
if (dev->magiclist[hash].tail) {
|
drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
|
||||||
dev->magiclist[hash].tail->next = entry;
|
list_add_tail(&entry->head, &dev->magicfree);
|
||||||
dev->magiclist[hash].tail = entry;
|
|
||||||
} else {
|
|
||||||
dev->magiclist[hash].head = entry;
|
|
||||||
dev->magiclist[hash].tail = entry;
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -128,29 +104,19 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv,
|
||||||
*/
|
*/
|
||||||
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
|
static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
|
||||||
{
|
{
|
||||||
drm_magic_entry_t *prev = NULL;
|
|
||||||
drm_magic_entry_t *pt;
|
drm_magic_entry_t *pt;
|
||||||
int hash;
|
drm_hash_item_t *hash;
|
||||||
|
|
||||||
DRM_DEBUG("%d\n", magic);
|
DRM_DEBUG("%d\n", magic);
|
||||||
hash = drm_hash_magic(magic);
|
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
|
||||||
if (pt->magic == magic) {
|
mutex_unlock(&dev->struct_mutex);
|
||||||
if (dev->magiclist[hash].head == pt) {
|
return -EINVAL;
|
||||||
dev->magiclist[hash].head = pt->next;
|
|
||||||
}
|
|
||||||
if (dev->magiclist[hash].tail == pt) {
|
|
||||||
dev->magiclist[hash].tail = prev;
|
|
||||||
}
|
|
||||||
if (prev) {
|
|
||||||
prev->next = pt->next;
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
|
||||||
|
drm_ht_remove_item(&dev->magiclist, hash);
|
||||||
|
list_del(&pt->head);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||||
|
|
|
@ -155,12 +155,10 @@ int drm_lastclose(drm_device_t * dev)
|
||||||
del_timer(&dev->timer);
|
del_timer(&dev->timer);
|
||||||
|
|
||||||
/* Clear pid list */
|
/* Clear pid list */
|
||||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
|
||||||
for (pt = dev->magiclist[i].head; pt; pt = next) {
|
list_del(&pt->head);
|
||||||
next = pt->next;
|
drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
|
||||||
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
|
||||||
}
|
|
||||||
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear AGP information */
|
/* Clear AGP information */
|
||||||
|
|
|
@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev)
|
||||||
for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
|
for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
|
||||||
atomic_set(&dev->counts[i], 0);
|
atomic_set(&dev->counts[i], 0);
|
||||||
|
|
||||||
for (i = 0; i < DRM_HASH_SIZE; i++) {
|
drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
|
||||||
dev->magiclist[i].head = NULL;
|
INIT_LIST_HEAD(&dev->magicfree);
|
||||||
dev->magiclist[i].tail = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
|
dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
|
||||||
if (dev->ctxlist == NULL)
|
if (dev->ctxlist == NULL)
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#ifndef DRM_HASHTAB_H
|
#ifndef DRM_HASHTAB_H
|
||||||
#define DRM_HASHTAB_H
|
#define DRM_HASHTAB_H
|
||||||
|
|
||||||
#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
|
#define drm_hash_entry(_ptr, _type, _member) list_entry(_ptr, _type, _member)
|
||||||
|
|
||||||
typedef struct drm_hash_item{
|
typedef struct drm_hash_item{
|
||||||
struct hlist_node head;
|
struct hlist_node head;
|
||||||
|
|
Loading…
Reference in New Issue