/**1* \file drm_auth.c2* IOCTLs for authentication3*4* \author Rickard E. (Rik) Faith <[email protected]>5* \author Gareth Hughes <[email protected]>6*/78/*9* Created: Tue Feb 2 08:37:54 1999 by [email protected]10*11* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.12* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.13* All Rights Reserved.14*15* Permission is hereby granted, free of charge, to any person obtaining a16* copy of this software and associated documentation files (the "Software"),17* to deal in the Software without restriction, including without limitation18* the rights to use, copy, modify, merge, publish, distribute, sublicense,19* and/or sell copies of the Software, and to permit persons to whom the20* Software is furnished to do so, subject to the following conditions:21*22* The above copyright notice and this permission notice (including the next23* paragraph) shall be included in all copies or substantial portions of the24* Software.25*26* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR27* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,28* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL29* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR30* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,31* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR32* OTHER DEALINGS IN THE SOFTWARE.33*/3435#include "drmP.h"3637/**38* Find the file with the given magic number.39*40* \param dev DRM device.41* \param magic magic number.42*43* Searches in drm_device::magiclist within all files with the same hash key44* the one with matching magic number, while holding the drm_device::struct_mutex45* lock.46*/47static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)48{49struct drm_file *retval = NULL;50struct drm_magic_entry *pt;51struct drm_hash_item *hash;52struct drm_device *dev = master->minor->dev;5354mutex_lock(&dev->struct_mutex);55if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {56pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);57retval = pt->priv;58}59mutex_unlock(&dev->struct_mutex);60return retval;61}6263/**64* Adds a magic number.65*66* \param dev DRM device.67* \param priv file private data.68* \param magic magic number.69*70* Creates a drm_magic_entry structure and appends to the linked list71* associated the magic number hash key in drm_device::magiclist, while holding72* the drm_device::struct_mutex lock.73*/74static int drm_add_magic(struct drm_master *master, struct drm_file *priv,75drm_magic_t magic)76{77struct drm_magic_entry *entry;78struct drm_device *dev = master->minor->dev;79DRM_DEBUG("%d\n", magic);8081entry = kzalloc(sizeof(*entry), GFP_KERNEL);82if (!entry)83return -ENOMEM;84entry->priv = priv;85entry->hash_item.key = (unsigned long)magic;86mutex_lock(&dev->struct_mutex);87drm_ht_insert_item(&master->magiclist, &entry->hash_item);88list_add_tail(&entry->head, &master->magicfree);89mutex_unlock(&dev->struct_mutex);9091return 0;92}9394/**95* Remove a magic number.96*97* \param dev DRM device.98* \param magic magic number.99*100* Searches and unlinks the entry in drm_device::magiclist with the magic101* number hash key, while holding the drm_device::struct_mutex lock.102*/103static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)104{105struct drm_magic_entry *pt;106struct drm_hash_item *hash;107struct drm_device *dev = master->minor->dev;108109DRM_DEBUG("%d\n", magic);110111mutex_lock(&dev->struct_mutex);112if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {113mutex_unlock(&dev->struct_mutex);114return -EINVAL;115}116pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);117drm_ht_remove_item(&master->magiclist, hash);118list_del(&pt->head);119mutex_unlock(&dev->struct_mutex);120121kfree(pt);122123return 0;124}125126/**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, otherwise136* searches an unique non-zero magic number and add it associating it with \p137* file_priv.138*/139int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)140{141static drm_magic_t sequence = 0;142static DEFINE_SPINLOCK(lock);143struct drm_auth *auth = data;144145/* Find unique magic */146if (file_priv->magic) {147auth->magic = file_priv->magic;148} else {149do {150spin_lock(&lock);151if (!sequence)152++sequence; /* reserve 0 */153auth->magic = sequence++;154spin_unlock(&lock);155} while (drm_find_file(file_priv->master, auth->magic));156file_priv->magic = auth->magic;157drm_add_magic(file_priv->master, file_priv, auth->magic);158}159160DRM_DEBUG("%u\n", auth->magic);161162return 0;163}164165/**166* Authenticate with a magic.167*168* \param inode device inode.169* \param file_priv DRM file private.170* \param cmd command.171* \param arg pointer to a drm_auth structure.172* \return zero if authentication successed, or a negative number otherwise.173*174* Checks if \p file_priv is associated with the magic number passed in \arg.175*/176int drm_authmagic(struct drm_device *dev, void *data,177struct drm_file *file_priv)178{179struct drm_auth *auth = data;180struct drm_file *file;181182DRM_DEBUG("%u\n", auth->magic);183if ((file = drm_find_file(file_priv->master, auth->magic))) {184file->authenticated = 1;185drm_remove_magic(file_priv->master, auth->magic);186return 0;187}188return -EINVAL;189}190191192