Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: simplify authentication management

The magic auth tokens we have are a simple map from cyclic IDs to drm_file
objects. Remove all the old bulk of code and replace it with a simple,
direct IDR.

The previous behavior is kept. Especially calling authmagic multiple times
on the same magic results in EINVAL except on the first call. The only
difference in behavior is that we never allocate IDs multiple times as
long as a client has its FD open.

v2:
- Fix return code of GetMagic()
- Use non-cyclic IDR allocator
- fix off-by-one in "magic > INT_MAX" sanity check

v3:
- drop redundant "magic > INT_MAX" check

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

authored by

David Herrmann and committed by
Daniel Vetter
32e7b94a acab18b5

+42 -157
+35 -140
drivers/gpu/drm/drm_auth.c
··· 1 - /** 2 - * \file drm_auth.c 3 - * IOCTLs for authentication 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 1 /* 10 2 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com 11 3 * 12 4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 6 * All Rights Reserved. 7 + * 8 + * Author Rickard E. (Rik) Faith <faith@valinux.com> 9 + * Author Gareth Hughes <gareth@valinux.com> 15 10 * 16 11 * Permission is hereby granted, free of charge, to any person obtaining a 17 12 * copy of this software and associated documentation files (the "Software"), ··· 31 36 #include <drm/drmP.h> 32 37 #include "drm_internal.h" 33 38 34 - struct drm_magic_entry { 35 - struct drm_hash_item hash_item; 36 - struct drm_file *priv; 37 - }; 38 - 39 39 /** 40 - * Find the file with the given magic number. 40 + * drm_getmagic - Get unique magic of a client 41 + * @dev: DRM device to operate on 42 + * @data: ioctl data containing the drm_auth object 43 + * @file_priv: DRM file that performs the operation 41 44 * 42 - * \param dev DRM device. 43 - * \param magic magic number. 45 + * This looks up the unique magic of the passed client and returns it. If the 46 + * client did not have a magic assigned, yet, a new one is registered. The magic 47 + * is stored in the passed drm_auth object. 44 48 * 45 - * Searches in drm_device::magiclist within all files with the same hash key 46 - * the one with matching magic number, while holding the drm_device::struct_mutex 47 - * lock. 48 - */ 49 - static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic) 50 - { 51 - struct drm_file *retval = NULL; 52 - struct drm_magic_entry *pt; 53 - struct drm_hash_item *hash; 54 - struct drm_device *dev = master->minor->dev; 55 - 56 - mutex_lock(&dev->struct_mutex); 57 - if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { 58 - pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); 59 - retval = pt->priv; 60 - } 61 - mutex_unlock(&dev->struct_mutex); 62 - return retval; 63 - } 64 - 65 - /** 66 - * Adds a magic number. 67 - * 68 - * \param dev DRM device. 69 - * \param priv file private data. 70 - * \param magic magic number. 71 - * 72 - * Creates a drm_magic_entry structure and appends to the linked list 73 - * associated the magic number hash key in drm_device::magiclist, while holding 74 - * the drm_device::struct_mutex lock. 75 - */ 76 - static int drm_add_magic(struct drm_master *master, struct drm_file *priv, 77 - drm_magic_t magic) 78 - { 79 - struct drm_magic_entry *entry; 80 - struct drm_device *dev = master->minor->dev; 81 - DRM_DEBUG("%d\n", magic); 82 - 83 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 84 - if (!entry) 85 - return -ENOMEM; 86 - entry->priv = priv; 87 - entry->hash_item.key = (unsigned long)magic; 88 - mutex_lock(&dev->struct_mutex); 89 - drm_ht_insert_item(&master->magiclist, &entry->hash_item); 90 - mutex_unlock(&dev->struct_mutex); 91 - 92 - return 0; 93 - } 94 - 95 - /** 96 - * Remove a magic number. 97 - * 98 - * \param dev DRM device. 99 - * \param magic magic number. 100 - * 101 - * Searches and unlinks the entry in drm_device::magiclist with the magic 102 - * number hash key, while holding the drm_device::struct_mutex lock. 103 - */ 104 - int drm_remove_magic(struct drm_master *master, drm_magic_t magic) 105 - { 106 - struct drm_magic_entry *pt; 107 - struct drm_hash_item *hash; 108 - struct drm_device *dev = master->minor->dev; 109 - 110 - DRM_DEBUG("%d\n", magic); 111 - 112 - mutex_lock(&dev->struct_mutex); 113 - if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { 114 - mutex_unlock(&dev->struct_mutex); 115 - return -EINVAL; 116 - } 117 - pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); 118 - drm_ht_remove_item(&master->magiclist, hash); 119 - mutex_unlock(&dev->struct_mutex); 120 - 121 - kfree(pt); 122 - 123 - return 0; 124 - } 125 - 126 - /** 127 - * Get a unique magic number (ioctl). 128 - * 129 - * \param inode device inode. 130 - * \param file_priv DRM file private. 131 - * \param cmd command. 132 - * \param arg pointer to a resulting drm_auth structure. 133 - * \return zero on success, or a negative number on failure. 134 - * 135 - * If there is a magic number in drm_file::magic then use it, otherwise 136 - * searches an unique non-zero magic number and add it associating it with \p 137 - * file_priv. 138 - * This ioctl needs protection by the drm_global_mutex, which protects 139 - * struct drm_file::magic and struct drm_magic_entry::priv. 49 + * Returns: 0 on success, negative error code on failure. 140 50 */ 141 51 int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) 142 52 { 143 - static drm_magic_t sequence = 0; 144 - static DEFINE_SPINLOCK(lock); 145 53 struct drm_auth *auth = data; 54 + int ret = 0; 146 55 147 - /* Find unique magic */ 148 - if (file_priv->magic) { 149 - auth->magic = file_priv->magic; 150 - } else { 151 - do { 152 - spin_lock(&lock); 153 - if (!sequence) 154 - ++sequence; /* reserve 0 */ 155 - auth->magic = sequence++; 156 - spin_unlock(&lock); 157 - } while (drm_find_file(file_priv->master, auth->magic)); 158 - file_priv->magic = auth->magic; 159 - drm_add_magic(file_priv->master, file_priv, auth->magic); 56 + mutex_lock(&dev->struct_mutex); 57 + if (!file_priv->magic) { 58 + ret = idr_alloc(&file_priv->master->magic_map, file_priv, 59 + 1, 0, GFP_KERNEL); 60 + if (ret >= 0) 61 + file_priv->magic = ret; 160 62 } 63 + auth->magic = file_priv->magic; 64 + mutex_unlock(&dev->struct_mutex); 161 65 162 66 DRM_DEBUG("%u\n", auth->magic); 163 67 164 - return 0; 68 + return ret < 0 ? ret : 0; 165 69 } 166 70 167 71 /** 168 - * Authenticate with a magic. 72 + * drm_authmagic - Authenticate client with a magic 73 + * @dev: DRM device to operate on 74 + * @data: ioctl data containing the drm_auth object 75 + * @file_priv: DRM file that performs the operation 169 76 * 170 - * \param inode device inode. 171 - * \param file_priv DRM file private. 172 - * \param cmd command. 173 - * \param arg pointer to a drm_auth structure. 174 - * \return zero if authentication successed, or a negative number otherwise. 77 + * This looks up a DRM client by the passed magic and authenticates it. 175 78 * 176 - * Checks if \p file_priv is associated with the magic number passed in \arg. 177 - * This ioctl needs protection by the drm_global_mutex, which protects 178 - * struct drm_file::magic and struct drm_magic_entry::priv. 79 + * Returns: 0 on success, negative error code on failure. 179 80 */ 180 81 int drm_authmagic(struct drm_device *dev, void *data, 181 82 struct drm_file *file_priv) ··· 80 189 struct drm_file *file; 81 190 82 191 DRM_DEBUG("%u\n", auth->magic); 83 - if ((file = drm_find_file(file_priv->master, auth->magic))) { 192 + 193 + mutex_lock(&dev->struct_mutex); 194 + file = idr_find(&file_priv->master->magic_map, auth->magic); 195 + if (file) { 84 196 file->authenticated = 1; 85 - drm_remove_magic(file_priv->master, auth->magic); 86 - return 0; 197 + idr_replace(&file_priv->master->magic_map, NULL, auth->magic); 87 198 } 88 - return -EINVAL; 199 + mutex_unlock(&dev->struct_mutex); 200 + 201 + return file ? 0 : -EINVAL; 89 202 }
+3 -9
drivers/gpu/drm/drm_drv.c
··· 92 92 } 93 93 EXPORT_SYMBOL(drm_ut_debug_printk); 94 94 95 - #define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */ 96 - 97 95 struct drm_master *drm_master_create(struct drm_minor *minor) 98 96 { 99 97 struct drm_master *master; ··· 103 105 kref_init(&master->refcount); 104 106 spin_lock_init(&master->lock.spinlock); 105 107 init_waitqueue_head(&master->lock.lock_queue); 106 - if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) { 107 - kfree(master); 108 - return NULL; 109 - } 108 + idr_init(&master->magic_map); 110 109 master->minor = minor; 111 110 112 111 return master; ··· 138 143 master->unique = NULL; 139 144 master->unique_len = 0; 140 145 } 141 - 142 - drm_ht_remove(&master->magiclist); 143 - 144 146 mutex_unlock(&dev->struct_mutex); 147 + 148 + idr_destroy(&master->magic_map); 145 149 kfree(master); 146 150 } 147 151
+2 -5
drivers/gpu/drm/drm_fops.c
··· 380 380 381 381 mutex_lock(&dev->struct_mutex); 382 382 list_del(&file_priv->lhead); 383 + if (file_priv->magic) 384 + idr_remove(&file_priv->master->magic_map, file_priv->magic); 383 385 mutex_unlock(&dev->struct_mutex); 384 386 385 387 if (dev->driver->preclose) ··· 395 393 task_pid_nr(current), 396 394 (long)old_encode_dev(file_priv->minor->kdev->devt), 397 395 dev->open_count); 398 - 399 - /* Release any auth tokens that might point to this file_priv, 400 - (do that under the drm_global_mutex) */ 401 - if (file_priv->magic) 402 - (void) drm_remove_magic(file_priv->master, file_priv->magic); 403 396 404 397 /* if the master has gone away we can't do anything with the lock */ 405 398 if (file_priv->minor->master)
-1
drivers/gpu/drm/drm_internal.h
··· 69 69 struct drm_file *file_priv); 70 70 int drm_authmagic(struct drm_device *dev, void *data, 71 71 struct drm_file *file_priv); 72 - int drm_remove_magic(struct drm_master *master, drm_magic_t magic); 73 72 74 73 /* drm_sysfs.c */ 75 74 extern struct class *drm_class;
+2 -2
include/drm/drmP.h
··· 355 355 * @minor: Link back to minor char device we are master for. Immutable. 356 356 * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex. 357 357 * @unique_len: Length of unique field. Protected by drm_global_mutex. 358 - * @magiclist: Hash of used authentication tokens. Protected by struct_mutex. 358 + * @magic_map: Map of used authentication tokens. Protected by struct_mutex. 359 359 * @lock: DRI lock information. 360 360 * @driver_priv: Pointer to driver-private information. 361 361 */ ··· 364 364 struct drm_minor *minor; 365 365 char *unique; 366 366 int unique_len; 367 - struct drm_open_hash magiclist; 367 + struct idr magic_map; 368 368 struct drm_lock_data lock; 369 369 void *driver_priv; 370 370 };