17f3c3d6fSHasso Tepper /*- 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. 247f3c3d6fSHasso Tepper * 257f3c3d6fSHasso Tepper * Authors: 267f3c3d6fSHasso Tepper * Rickard E. (Rik) Faith <faith@valinux.com> 277f3c3d6fSHasso Tepper * Gareth Hughes <gareth@valinux.com> 287f3c3d6fSHasso Tepper * 297f3c3d6fSHasso Tepper */ 307f3c3d6fSHasso Tepper 317f3c3d6fSHasso Tepper /** @file drm_auth.c 327f3c3d6fSHasso Tepper * Implementation of the get/authmagic ioctls implementing the authentication 337f3c3d6fSHasso Tepper * scheme between the master and clients. 347f3c3d6fSHasso Tepper */ 357f3c3d6fSHasso Tepper 36*b3705d71SHasso Tepper #include "dev/drm/drmP.h" 377f3c3d6fSHasso Tepper 387f3c3d6fSHasso Tepper static int drm_hash_magic(drm_magic_t magic) 397f3c3d6fSHasso Tepper { 407f3c3d6fSHasso Tepper return magic & (DRM_HASH_SIZE-1); 417f3c3d6fSHasso Tepper } 427f3c3d6fSHasso Tepper 437f3c3d6fSHasso Tepper /** 447f3c3d6fSHasso Tepper * Returns the file private associated with the given magic number. 457f3c3d6fSHasso Tepper */ 46*b3705d71SHasso Tepper static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic) 477f3c3d6fSHasso Tepper { 487f3c3d6fSHasso Tepper drm_magic_entry_t *pt; 497f3c3d6fSHasso Tepper int hash = drm_hash_magic(magic); 507f3c3d6fSHasso Tepper 517f3c3d6fSHasso Tepper DRM_SPINLOCK_ASSERT(&dev->dev_lock); 527f3c3d6fSHasso Tepper 537f3c3d6fSHasso Tepper for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { 547f3c3d6fSHasso Tepper if (pt->magic == magic) { 557f3c3d6fSHasso Tepper return pt->priv; 567f3c3d6fSHasso Tepper } 577f3c3d6fSHasso Tepper } 587f3c3d6fSHasso Tepper 597f3c3d6fSHasso Tepper return NULL; 607f3c3d6fSHasso Tepper } 617f3c3d6fSHasso Tepper 627f3c3d6fSHasso Tepper /** 637f3c3d6fSHasso Tepper * Inserts the given magic number into the hash table of used magic number 647f3c3d6fSHasso Tepper * lists. 657f3c3d6fSHasso Tepper */ 66*b3705d71SHasso Tepper static int drm_add_magic(struct drm_device *dev, struct drm_file *priv, 67*b3705d71SHasso Tepper drm_magic_t magic) 687f3c3d6fSHasso Tepper { 697f3c3d6fSHasso Tepper int hash; 707f3c3d6fSHasso Tepper drm_magic_entry_t *entry; 717f3c3d6fSHasso Tepper 727f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 737f3c3d6fSHasso Tepper 747f3c3d6fSHasso Tepper DRM_SPINLOCK_ASSERT(&dev->dev_lock); 757f3c3d6fSHasso Tepper 767f3c3d6fSHasso Tepper hash = drm_hash_magic(magic); 77*b3705d71SHasso Tepper entry = malloc(sizeof(*entry), DRM_MEM_MAGIC, M_ZERO | M_NOWAIT); 78*b3705d71SHasso Tepper if (!entry) 79*b3705d71SHasso Tepper return ENOMEM; 807f3c3d6fSHasso Tepper entry->magic = magic; 817f3c3d6fSHasso Tepper entry->priv = priv; 827f3c3d6fSHasso Tepper entry->next = NULL; 837f3c3d6fSHasso Tepper 847f3c3d6fSHasso Tepper if (dev->magiclist[hash].tail) { 857f3c3d6fSHasso Tepper dev->magiclist[hash].tail->next = entry; 867f3c3d6fSHasso Tepper dev->magiclist[hash].tail = entry; 877f3c3d6fSHasso Tepper } else { 887f3c3d6fSHasso Tepper dev->magiclist[hash].head = entry; 897f3c3d6fSHasso Tepper dev->magiclist[hash].tail = entry; 907f3c3d6fSHasso Tepper } 917f3c3d6fSHasso Tepper 927f3c3d6fSHasso Tepper return 0; 937f3c3d6fSHasso Tepper } 947f3c3d6fSHasso Tepper 957f3c3d6fSHasso Tepper /** 967f3c3d6fSHasso Tepper * Removes the given magic number from the hash table of used magic number 977f3c3d6fSHasso Tepper * lists. 987f3c3d6fSHasso Tepper */ 99*b3705d71SHasso Tepper static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic) 1007f3c3d6fSHasso Tepper { 1017f3c3d6fSHasso Tepper drm_magic_entry_t *prev = NULL; 1027f3c3d6fSHasso Tepper drm_magic_entry_t *pt; 1037f3c3d6fSHasso Tepper int hash; 1047f3c3d6fSHasso Tepper 1057f3c3d6fSHasso Tepper DRM_SPINLOCK_ASSERT(&dev->dev_lock); 1067f3c3d6fSHasso Tepper 1077f3c3d6fSHasso Tepper DRM_DEBUG("%d\n", magic); 1087f3c3d6fSHasso Tepper hash = drm_hash_magic(magic); 1097f3c3d6fSHasso Tepper 1107f3c3d6fSHasso Tepper for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { 1117f3c3d6fSHasso Tepper if (pt->magic == magic) { 1127f3c3d6fSHasso Tepper if (dev->magiclist[hash].head == pt) { 1137f3c3d6fSHasso Tepper dev->magiclist[hash].head = pt->next; 1147f3c3d6fSHasso Tepper } 1157f3c3d6fSHasso Tepper if (dev->magiclist[hash].tail == pt) { 1167f3c3d6fSHasso Tepper dev->magiclist[hash].tail = prev; 1177f3c3d6fSHasso Tepper } 1187f3c3d6fSHasso Tepper if (prev) { 1197f3c3d6fSHasso Tepper prev->next = pt->next; 1207f3c3d6fSHasso Tepper } 121*b3705d71SHasso Tepper free(pt, DRM_MEM_MAGIC); 1227f3c3d6fSHasso Tepper return 0; 1237f3c3d6fSHasso Tepper } 1247f3c3d6fSHasso Tepper } 1257f3c3d6fSHasso Tepper 1267f3c3d6fSHasso Tepper return EINVAL; 1277f3c3d6fSHasso Tepper } 1287f3c3d6fSHasso Tepper 1297f3c3d6fSHasso Tepper /** 1307f3c3d6fSHasso Tepper * Called by the client, this returns a unique magic number to be authorized 1317f3c3d6fSHasso Tepper * by the master. 1327f3c3d6fSHasso Tepper * 1337f3c3d6fSHasso Tepper * The master may use its own knowledge of the client (such as the X 1347f3c3d6fSHasso Tepper * connection that the magic is passed over) to determine if the magic number 1357f3c3d6fSHasso Tepper * should be authenticated. 1367f3c3d6fSHasso Tepper */ 137*b3705d71SHasso Tepper int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) 1387f3c3d6fSHasso Tepper { 1397f3c3d6fSHasso Tepper static drm_magic_t sequence = 0; 140*b3705d71SHasso Tepper struct drm_auth *auth = data; 1417f3c3d6fSHasso Tepper 1427f3c3d6fSHasso Tepper /* Find unique magic */ 1437f3c3d6fSHasso Tepper if (file_priv->magic) { 1447f3c3d6fSHasso Tepper auth->magic = file_priv->magic; 1457f3c3d6fSHasso Tepper } else { 1467f3c3d6fSHasso Tepper DRM_LOCK(); 1477f3c3d6fSHasso Tepper do { 1487f3c3d6fSHasso Tepper int old = sequence; 1497f3c3d6fSHasso Tepper 1507f3c3d6fSHasso Tepper auth->magic = old+1; 1517f3c3d6fSHasso Tepper 1527f3c3d6fSHasso Tepper if (!atomic_cmpset_int(&sequence, old, auth->magic)) 1537f3c3d6fSHasso Tepper continue; 1547f3c3d6fSHasso Tepper } while (drm_find_file(dev, auth->magic)); 1557f3c3d6fSHasso Tepper file_priv->magic = auth->magic; 1567f3c3d6fSHasso Tepper drm_add_magic(dev, file_priv, auth->magic); 1577f3c3d6fSHasso Tepper DRM_UNLOCK(); 1587f3c3d6fSHasso Tepper } 1597f3c3d6fSHasso Tepper 1607f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 1617f3c3d6fSHasso Tepper 1627f3c3d6fSHasso Tepper return 0; 1637f3c3d6fSHasso Tepper } 1647f3c3d6fSHasso Tepper 1657f3c3d6fSHasso Tepper /** 1667f3c3d6fSHasso Tepper * Marks the client associated with the given magic number as authenticated. 1677f3c3d6fSHasso Tepper */ 168*b3705d71SHasso Tepper int drm_authmagic(struct drm_device *dev, void *data, 169*b3705d71SHasso Tepper struct drm_file *file_priv) 1707f3c3d6fSHasso Tepper { 171*b3705d71SHasso Tepper struct drm_auth *auth = data; 172*b3705d71SHasso Tepper struct drm_file *priv; 1737f3c3d6fSHasso Tepper 1747f3c3d6fSHasso Tepper DRM_DEBUG("%u\n", auth->magic); 1757f3c3d6fSHasso Tepper 1767f3c3d6fSHasso Tepper DRM_LOCK(); 1777f3c3d6fSHasso Tepper priv = drm_find_file(dev, auth->magic); 1787f3c3d6fSHasso Tepper if (priv != NULL) { 1797f3c3d6fSHasso Tepper priv->authenticated = 1; 1807f3c3d6fSHasso Tepper drm_remove_magic(dev, auth->magic); 1817f3c3d6fSHasso Tepper DRM_UNLOCK(); 1827f3c3d6fSHasso Tepper return 0; 1837f3c3d6fSHasso Tepper } else { 1847f3c3d6fSHasso Tepper DRM_UNLOCK(); 1857f3c3d6fSHasso Tepper return EINVAL; 1867f3c3d6fSHasso Tepper } 1877f3c3d6fSHasso Tepper } 188