Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8669cbc5 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@linux.ie>
parent 3d45dbd6
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@
#define DRM_DEBUG_CODE 2	  /**< Include debugging code if > 1, then
				     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_RESERVED_CONTEXTS 1	 /**< Change drm_resctx if changed */
#define DRM_LOOPING_LIMIT     5000000
@@ -277,7 +277,8 @@ typedef struct drm_devstate {
} drm_devstate_t;

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_magic_entry *next;
} drm_magic_entry_t;
@@ -653,7 +654,8 @@ typedef struct drm_device {
	/*@{ */
	drm_file_t *file_first;		/**< file list head */
	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 */
+14 −48
Original line number Diff line number Diff line
@@ -35,20 +35,6 @@

#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.
 *
@@ -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_magic_entry_t *pt;
	int hash = drm_hash_magic(magic);
	drm_hash_item_t *hash;

	mutex_lock(&dev->struct_mutex);
	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
		if (pt->magic == magic) {
	if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
		pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
		retval = pt->priv;
			break;
		}
	}
	mutex_unlock(&dev->struct_mutex);
	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,
			 drm_magic_t magic)
{
	int hash;
	drm_magic_entry_t *entry;

	DRM_DEBUG("%d\n", magic);

	hash = drm_hash_magic(magic);
	entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
	if (!entry)
		return -ENOMEM;
	memset(entry, 0, sizeof(*entry));
	entry->magic = magic;
	entry->priv = priv;
	entry->next = NULL;

	entry->hash_item.key = (unsigned long)magic;
	mutex_lock(&dev->struct_mutex);
	if (dev->magiclist[hash].tail) {
		dev->magiclist[hash].tail->next = entry;
		dev->magiclist[hash].tail = entry;
	} else {
		dev->magiclist[hash].head = entry;
		dev->magiclist[hash].tail = entry;
	}
	drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
	list_add_tail(&entry->head, &dev->magicfree);
	mutex_unlock(&dev->struct_mutex);

	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)
{
	drm_magic_entry_t *prev = NULL;
	drm_magic_entry_t *pt;
	int hash;
	drm_hash_item_t *hash;

	DRM_DEBUG("%d\n", magic);
	hash = drm_hash_magic(magic);

	mutex_lock(&dev->struct_mutex);
	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
		if (pt->magic == magic) {
			if (dev->magiclist[hash].head == pt) {
				dev->magiclist[hash].head = pt->next;
			}
			if (dev->magiclist[hash].tail == pt) {
				dev->magiclist[hash].tail = prev;
			}
			if (prev) {
				prev->next = pt->next;
			}
	if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
		mutex_unlock(&dev->struct_mutex);
			return 0;
		}
		return -EINVAL;
	}
	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);

	drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+4 −6
Original line number Diff line number Diff line
@@ -155,13 +155,11 @@ int drm_lastclose(drm_device_t * dev)
	del_timer(&dev->timer);

	/* Clear pid list */
	for (i = 0; i < DRM_HASH_SIZE; i++) {
		for (pt = dev->magiclist[i].head; pt; pt = next) {
			next = pt->next;
	list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
		list_del(&pt->head);
		drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
		drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
	}
		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
	}

	/* Clear AGP information */
	if (drm_core_has_AGP(dev) && dev->agp) {
+2 −4
Original line number Diff line number Diff line
@@ -72,10 +72,8 @@ static int drm_setup(drm_device_t * dev)
	for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
		atomic_set(&dev->counts[i], 0);

	for (i = 0; i < DRM_HASH_SIZE; i++) {
		dev->magiclist[i].head = NULL;
		dev->magiclist[i].tail = NULL;
	}
	drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
	INIT_LIST_HEAD(&dev->magicfree);

	dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
	if (dev->ctxlist == NULL)
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
#ifndef 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{
	struct hlist_node head;