1*2c9916cdSFrançois Tigeot /** 2*2c9916cdSFrançois Tigeot * \file drm_auth.c 3*2c9916cdSFrançois Tigeot * IOCTLs for authentication 4*2c9916cdSFrançois Tigeot * 5*2c9916cdSFrançois Tigeot * \author Rickard E. (Rik) Faith <faith@valinux.com> 6*2c9916cdSFrançois Tigeot * \author Gareth Hughes <gareth@valinux.com> 7*2c9916cdSFrançois Tigeot */ 8*2c9916cdSFrançois Tigeot 9*2c9916cdSFrançois Tigeot /* 10*2c9916cdSFrançois Tigeot * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com 11*2c9916cdSFrançois Tigeot * 127f3c3d6fSHasso Tepper * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 137f3c3d6fSHasso Tepper * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 147f3c3d6fSHasso Tepper * All Rights Reserved. 157f3c3d6fSHasso Tepper * 167f3c3d6fSHasso Tepper * Permission is hereby granted, free of charge, to any person obtaining a 177f3c3d6fSHasso Tepper * copy of this software and associated documentation files (the "Software"), 187f3c3d6fSHasso Tepper * to deal in the Software without restriction, including without limitation 197f3c3d6fSHasso Tepper * the rights to use, copy, modify, merge, publish, distribute, sublicense, 207f3c3d6fSHasso Tepper * and/or sell copies of the Software, and to permit persons to whom the 217f3c3d6fSHasso Tepper * Software is furnished to do so, subject to the following conditions: 227f3c3d6fSHasso Tepper * 237f3c3d6fSHasso Tepper * The above copyright notice and this permission notice (including the next 247f3c3d6fSHasso Tepper * paragraph) shall be included in all copies or substantial portions of the 257f3c3d6fSHasso Tepper * Software. 267f3c3d6fSHasso Tepper * 277f3c3d6fSHasso Tepper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 287f3c3d6fSHasso Tepper * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 297f3c3d6fSHasso Tepper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 307f3c3d6fSHasso Tepper * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 317f3c3d6fSHasso Tepper * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 327f3c3d6fSHasso Tepper * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 337f3c3d6fSHasso Tepper * OTHER DEALINGS IN THE SOFTWARE. 347f3c3d6fSHasso Tepper */ 357f3c3d6fSHasso Tepper 3618e26a6dSFrançois Tigeot #include <drm/drmP.h> 37*2c9916cdSFrançois Tigeot #include "drm_internal.h" 387f3c3d6fSHasso Tepper 397f3c3d6fSHasso Tepper /** 409edbd4a0SFrançois Tigeot * Find the file with the given magic number. 419edbd4a0SFrançois Tigeot * 429edbd4a0SFrançois Tigeot * \param dev DRM device. 439edbd4a0SFrançois Tigeot * \param magic magic number. 449edbd4a0SFrançois Tigeot * 459edbd4a0SFrançois Tigeot * Searches in drm_device::magiclist within all files with the same hash key 469edbd4a0SFrançois Tigeot * the one with matching magic number, while holding the drm_device::struct_mutex 479edbd4a0SFrançois Tigeot * lock. 487f3c3d6fSHasso Tepper */ 4979f713b0SFrançois Tigeot static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic) 5079f713b0SFrançois Tigeot { 519edbd4a0SFrançois Tigeot struct drm_file *retval = NULL; 521b13d190SFrançois Tigeot struct drm_magic_entry *pt; 539edbd4a0SFrançois Tigeot struct drm_hash_item *hash; 5479f713b0SFrançois Tigeot 559edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 569edbd4a0SFrançois Tigeot if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { 571b13d190SFrançois Tigeot pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); 589edbd4a0SFrançois Tigeot retval = pt->priv; 5979f713b0SFrançois Tigeot } 609edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 619edbd4a0SFrançois Tigeot return retval; 6279f713b0SFrançois Tigeot } 6379f713b0SFrançois Tigeot 6479f713b0SFrançois Tigeot /** 6579f713b0SFrançois Tigeot * Inserts the given magic number into the hash table of used magic number 6679f713b0SFrançois Tigeot * lists. 6779f713b0SFrançois Tigeot */ 6879f713b0SFrançois Tigeot static int drm_add_magic(struct drm_device *dev, struct drm_file *priv, 69b3705d71SHasso Tepper drm_magic_t magic) 707f3c3d6fSHasso Tepper { 711b13d190SFrançois Tigeot struct drm_magic_entry *entry; 7279f713b0SFrançois Tigeot 737f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 747f3c3d6fSHasso Tepper 759edbd4a0SFrançois Tigeot entry = kzalloc(sizeof(*entry), GFP_KERNEL); 76b3705d71SHasso Tepper if (!entry) 779edbd4a0SFrançois Tigeot return -ENOMEM; 787f3c3d6fSHasso Tepper entry->priv = priv; 799edbd4a0SFrançois Tigeot entry->hash_item.key = (unsigned long)magic; 809edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 819edbd4a0SFrançois Tigeot drm_ht_insert_item(&dev->magiclist, &entry->hash_item); 829edbd4a0SFrançois Tigeot list_add_tail(&entry->head, &dev->magicfree); 839edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 847f3c3d6fSHasso Tepper 857f3c3d6fSHasso Tepper return 0; 867f3c3d6fSHasso Tepper } 877f3c3d6fSHasso Tepper 887f3c3d6fSHasso Tepper /** 8979f713b0SFrançois Tigeot * Removes the given magic number from the hash table of used magic number 9079f713b0SFrançois Tigeot * lists. 917f3c3d6fSHasso Tepper */ 92*2c9916cdSFrançois Tigeot int drm_remove_magic(struct drm_device *dev, drm_magic_t magic) 937f3c3d6fSHasso Tepper { 941b13d190SFrançois Tigeot struct drm_magic_entry *pt; 959edbd4a0SFrançois Tigeot struct drm_hash_item *hash; 967f3c3d6fSHasso Tepper 977f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 987f3c3d6fSHasso Tepper 999edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 1009edbd4a0SFrançois Tigeot if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { 1019edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 1029edbd4a0SFrançois Tigeot return -EINVAL; 1037f3c3d6fSHasso Tepper } 1041b13d190SFrançois Tigeot pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); 1059edbd4a0SFrançois Tigeot drm_ht_remove_item(&dev->magiclist, hash); 1069edbd4a0SFrançois Tigeot list_del(&pt->head); 1079edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 1089edbd4a0SFrançois Tigeot 1099edbd4a0SFrançois Tigeot kfree(pt); 1109edbd4a0SFrançois Tigeot 1117f3c3d6fSHasso Tepper return 0; 1127f3c3d6fSHasso Tepper } 1137f3c3d6fSHasso Tepper 1147f3c3d6fSHasso Tepper /** 115ba55f2f5SFrançois Tigeot * Get a unique magic number (ioctl). 1167f3c3d6fSHasso Tepper * 117ba55f2f5SFrançois Tigeot * \param inode device inode. 118ba55f2f5SFrançois Tigeot * \param file_priv DRM file private. 119ba55f2f5SFrançois Tigeot * \param cmd command. 120ba55f2f5SFrançois Tigeot * \param arg pointer to a resulting drm_auth structure. 121ba55f2f5SFrançois Tigeot * \return zero on success, or a negative number on failure. 122ba55f2f5SFrançois Tigeot * 123ba55f2f5SFrançois Tigeot * If there is a magic number in drm_file::magic then use it, otherwise 124ba55f2f5SFrançois Tigeot * searches an unique non-zero magic number and add it associating it with \p 125ba55f2f5SFrançois Tigeot * file_priv. 126ba55f2f5SFrançois Tigeot * This ioctl needs protection by the drm_global_mutex, which protects 127ba55f2f5SFrançois Tigeot * struct drm_file::magic and struct drm_magic_entry::priv. 1287f3c3d6fSHasso Tepper */ 129b3705d71SHasso Tepper int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) 1307f3c3d6fSHasso Tepper { 1317f3c3d6fSHasso Tepper static drm_magic_t sequence = 0; 132ba55f2f5SFrançois Tigeot static struct spinlock lock = SPINLOCK_INITIALIZER(&lock, "drm_gm"); 133b3705d71SHasso Tepper struct drm_auth *auth = data; 1347f3c3d6fSHasso Tepper 1357f3c3d6fSHasso Tepper /* Find unique magic */ 1367f3c3d6fSHasso Tepper if (file_priv->magic) { 1377f3c3d6fSHasso Tepper auth->magic = file_priv->magic; 1387f3c3d6fSHasso Tepper } else { 1397f3c3d6fSHasso Tepper do { 140ba55f2f5SFrançois Tigeot spin_lock(&lock); 141ba55f2f5SFrançois Tigeot if (!sequence) 142ba55f2f5SFrançois Tigeot ++sequence; /* reserve 0 */ 143ba55f2f5SFrançois Tigeot auth->magic = sequence++; 144ba55f2f5SFrançois Tigeot spin_unlock(&lock); 14579f713b0SFrançois Tigeot } while (drm_find_file(dev, auth->magic)); 1467f3c3d6fSHasso Tepper file_priv->magic = auth->magic; 14779f713b0SFrançois Tigeot drm_add_magic(dev, file_priv, auth->magic); 1487f3c3d6fSHasso Tepper } 1497f3c3d6fSHasso Tepper 1507f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 1517f3c3d6fSHasso Tepper 1527f3c3d6fSHasso Tepper return 0; 1537f3c3d6fSHasso Tepper } 1547f3c3d6fSHasso Tepper 1557f3c3d6fSHasso Tepper /** 156ba55f2f5SFrançois Tigeot * Authenticate with a magic. 157ba55f2f5SFrançois Tigeot * 158ba55f2f5SFrançois Tigeot * \param inode device inode. 159ba55f2f5SFrançois Tigeot * \param file_priv DRM file private. 160ba55f2f5SFrançois Tigeot * \param cmd command. 161ba55f2f5SFrançois Tigeot * \param arg pointer to a drm_auth structure. 162ba55f2f5SFrançois Tigeot * \return zero if authentication successed, or a negative number otherwise. 163ba55f2f5SFrançois Tigeot * 164ba55f2f5SFrançois Tigeot * Checks if \p file_priv is associated with the magic number passed in \arg. 165ba55f2f5SFrançois Tigeot * This ioctl needs protection by the drm_global_mutex, which protects 166ba55f2f5SFrançois Tigeot * struct drm_file::magic and struct drm_magic_entry::priv. 1677f3c3d6fSHasso Tepper */ 168b3705d71SHasso Tepper int drm_authmagic(struct drm_device *dev, void *data, 169b3705d71SHasso Tepper struct drm_file *file_priv) 1707f3c3d6fSHasso Tepper { 171b3705d71SHasso Tepper struct drm_auth *auth = data; 172ba55f2f5SFrançois Tigeot struct drm_file *file; 1737f3c3d6fSHasso Tepper 1747f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 175ba55f2f5SFrançois Tigeot if ((file = drm_find_file(dev, auth->magic))) { 176ba55f2f5SFrançois Tigeot file->authenticated = 1; 17779f713b0SFrançois Tigeot drm_remove_magic(dev, auth->magic); 1787f3c3d6fSHasso Tepper return 0; 1797f3c3d6fSHasso Tepper } 180ba55f2f5SFrançois Tigeot return -EINVAL; 1817f3c3d6fSHasso Tepper } 182