179f713b0SFrançois Tigeot /*- 27f3c3d6fSHasso Tepper * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 37f3c3d6fSHasso Tepper * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 47f3c3d6fSHasso Tepper * All Rights Reserved. 57f3c3d6fSHasso Tepper * 67f3c3d6fSHasso Tepper * Permission is hereby granted, free of charge, to any person obtaining a 77f3c3d6fSHasso Tepper * copy of this software and associated documentation files (the "Software"), 87f3c3d6fSHasso Tepper * to deal in the Software without restriction, including without limitation 97f3c3d6fSHasso Tepper * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107f3c3d6fSHasso Tepper * and/or sell copies of the Software, and to permit persons to whom the 117f3c3d6fSHasso Tepper * Software is furnished to do so, subject to the following conditions: 127f3c3d6fSHasso Tepper * 137f3c3d6fSHasso Tepper * The above copyright notice and this permission notice (including the next 147f3c3d6fSHasso Tepper * paragraph) shall be included in all copies or substantial portions of the 157f3c3d6fSHasso Tepper * Software. 167f3c3d6fSHasso Tepper * 177f3c3d6fSHasso Tepper * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 187f3c3d6fSHasso Tepper * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197f3c3d6fSHasso Tepper * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207f3c3d6fSHasso Tepper * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 217f3c3d6fSHasso Tepper * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 227f3c3d6fSHasso Tepper * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 237f3c3d6fSHasso Tepper * OTHER DEALINGS IN THE SOFTWARE. 2479f713b0SFrançois Tigeot * 2579f713b0SFrançois Tigeot * Authors: 2679f713b0SFrançois Tigeot * Rickard E. (Rik) Faith <faith@valinux.com> 2779f713b0SFrançois Tigeot * Gareth Hughes <gareth@valinux.com> 2879f713b0SFrançois Tigeot * 2979f713b0SFrançois Tigeot * $FreeBSD: src/sys/dev/drm2/drm_auth.c,v 1.1 2012/05/22 11:07:44 kib Exp $ 3079f713b0SFrançois Tigeot */ 3179f713b0SFrançois Tigeot 3279f713b0SFrançois Tigeot /** @file drm_auth.c 3379f713b0SFrançois Tigeot * Implementation of the get/authmagic ioctls implementing the authentication 3479f713b0SFrançois Tigeot * scheme between the master and clients. 357f3c3d6fSHasso Tepper */ 367f3c3d6fSHasso Tepper 3718e26a6dSFrançois Tigeot #include <drm/drmP.h> 387f3c3d6fSHasso Tepper 397f3c3d6fSHasso Tepper /** 40*9edbd4a0SFrançois Tigeot * Find the file with the given magic number. 41*9edbd4a0SFrançois Tigeot * 42*9edbd4a0SFrançois Tigeot * \param dev DRM device. 43*9edbd4a0SFrançois Tigeot * \param magic magic number. 44*9edbd4a0SFrançois Tigeot * 45*9edbd4a0SFrançois Tigeot * Searches in drm_device::magiclist within all files with the same hash key 46*9edbd4a0SFrançois Tigeot * the one with matching magic number, while holding the drm_device::struct_mutex 47*9edbd4a0SFranç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 { 51*9edbd4a0SFrançois Tigeot struct drm_file *retval = NULL; 5279f713b0SFrançois Tigeot drm_magic_entry_t *pt; 53*9edbd4a0SFrançois Tigeot struct drm_hash_item *hash; 5479f713b0SFrançois Tigeot 55*9edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 56*9edbd4a0SFrançois Tigeot if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { 57*9edbd4a0SFrançois Tigeot pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); 58*9edbd4a0SFrançois Tigeot retval = pt->priv; 5979f713b0SFrançois Tigeot } 60*9edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 61*9edbd4a0SFranç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 { 7179f713b0SFrançois Tigeot drm_magic_entry_t *entry; 7279f713b0SFrançois Tigeot 737f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 747f3c3d6fSHasso Tepper 75*9edbd4a0SFrançois Tigeot entry = kzalloc(sizeof(*entry), GFP_KERNEL); 76b3705d71SHasso Tepper if (!entry) 77*9edbd4a0SFrançois Tigeot return -ENOMEM; 787f3c3d6fSHasso Tepper entry->priv = priv; 79*9edbd4a0SFrançois Tigeot entry->hash_item.key = (unsigned long)magic; 80*9edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 81*9edbd4a0SFrançois Tigeot drm_ht_insert_item(&dev->magiclist, &entry->hash_item); 82*9edbd4a0SFrançois Tigeot list_add_tail(&entry->head, &dev->magicfree); 83*9edbd4a0SFranç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 */ 9279f713b0SFrançois Tigeot static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic) 937f3c3d6fSHasso Tepper { 9479f713b0SFrançois Tigeot drm_magic_entry_t *pt; 95*9edbd4a0SFrançois Tigeot struct drm_hash_item *hash; 967f3c3d6fSHasso Tepper 977f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 987f3c3d6fSHasso Tepper 99*9edbd4a0SFrançois Tigeot mutex_lock(&dev->struct_mutex); 100*9edbd4a0SFrançois Tigeot if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { 101*9edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 102*9edbd4a0SFrançois Tigeot return -EINVAL; 1037f3c3d6fSHasso Tepper } 104*9edbd4a0SFrançois Tigeot pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); 105*9edbd4a0SFrançois Tigeot drm_ht_remove_item(&dev->magiclist, hash); 106*9edbd4a0SFrançois Tigeot list_del(&pt->head); 107*9edbd4a0SFrançois Tigeot mutex_unlock(&dev->struct_mutex); 108*9edbd4a0SFrançois Tigeot 109*9edbd4a0SFrançois Tigeot kfree(pt); 110*9edbd4a0SFrançois Tigeot 1117f3c3d6fSHasso Tepper return 0; 1127f3c3d6fSHasso Tepper } 1137f3c3d6fSHasso Tepper 1147f3c3d6fSHasso Tepper /** 11579f713b0SFrançois Tigeot * Called by the client, this returns a unique magic number to be authorized 11679f713b0SFrançois Tigeot * by the master. 1177f3c3d6fSHasso Tepper * 11879f713b0SFrançois Tigeot * The master may use its own knowledge of the client (such as the X 11979f713b0SFrançois Tigeot * connection that the magic is passed over) to determine if the magic number 12079f713b0SFrançois Tigeot * should be authenticated. 1217f3c3d6fSHasso Tepper */ 122b3705d71SHasso Tepper int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) 1237f3c3d6fSHasso Tepper { 1247f3c3d6fSHasso Tepper static drm_magic_t sequence = 0; 125b3705d71SHasso Tepper struct drm_auth *auth = data; 1267f3c3d6fSHasso Tepper 1277f3c3d6fSHasso Tepper /* Find unique magic */ 1287f3c3d6fSHasso Tepper if (file_priv->magic) { 1297f3c3d6fSHasso Tepper auth->magic = file_priv->magic; 1307f3c3d6fSHasso Tepper } else { 13179f713b0SFrançois Tigeot DRM_LOCK(dev); 1327f3c3d6fSHasso Tepper do { 13379f713b0SFrançois Tigeot int old = sequence; 13479f713b0SFrançois Tigeot 13579f713b0SFrançois Tigeot auth->magic = old+1; 13679f713b0SFrançois Tigeot 13779f713b0SFrançois Tigeot if (!atomic_cmpset_int(&sequence, old, auth->magic)) 13879f713b0SFrançois Tigeot continue; 13979f713b0SFrançois Tigeot } while (drm_find_file(dev, auth->magic)); 1407f3c3d6fSHasso Tepper file_priv->magic = auth->magic; 14179f713b0SFrançois Tigeot drm_add_magic(dev, file_priv, auth->magic); 14279f713b0SFrançois Tigeot DRM_UNLOCK(dev); 1437f3c3d6fSHasso Tepper } 1447f3c3d6fSHasso Tepper 1457f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 1467f3c3d6fSHasso Tepper 1477f3c3d6fSHasso Tepper return 0; 1487f3c3d6fSHasso Tepper } 1497f3c3d6fSHasso Tepper 1507f3c3d6fSHasso Tepper /** 15179f713b0SFrançois Tigeot * Marks the client associated with the given magic number as authenticated. 1527f3c3d6fSHasso Tepper */ 153b3705d71SHasso Tepper int drm_authmagic(struct drm_device *dev, void *data, 154b3705d71SHasso Tepper struct drm_file *file_priv) 1557f3c3d6fSHasso Tepper { 156b3705d71SHasso Tepper struct drm_auth *auth = data; 15779f713b0SFrançois Tigeot struct drm_file *priv; 1587f3c3d6fSHasso Tepper 1597f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 16079f713b0SFrançois Tigeot 16179f713b0SFrançois Tigeot DRM_LOCK(dev); 16279f713b0SFrançois Tigeot priv = drm_find_file(dev, auth->magic); 16379f713b0SFrançois Tigeot if (priv != NULL) { 16479f713b0SFrançois Tigeot priv->authenticated = 1; 16579f713b0SFrançois Tigeot drm_remove_magic(dev, auth->magic); 16679f713b0SFrançois Tigeot DRM_UNLOCK(dev); 1677f3c3d6fSHasso Tepper return 0; 16879f713b0SFrançois Tigeot } else { 16979f713b0SFrançois Tigeot DRM_UNLOCK(dev); 17079f713b0SFrançois Tigeot return EINVAL; 1717f3c3d6fSHasso Tepper } 1727f3c3d6fSHasso Tepper } 173