2005-04-17 02:20:36 +04:00
/**
2005-09-25 08:28:13 +04:00
* \ file drm_auth . c
2005-04-17 02:20:36 +04:00
* IOCTLs for authentication
*
* \ author Rickard E . ( Rik ) Faith < faith @ valinux . com >
* \ author Gareth Hughes < gareth @ valinux . com >
*/
/*
* Created : Tue Feb 2 08 : 37 : 54 1999 by faith @ valinux . com
*
* Copyright 1999 Precision Insight , Inc . , Cedar Park , Texas .
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
* All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* VA LINUX SYSTEMS AND / OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*/
# include "drmP.h"
/**
* Find the file with the given magic number .
*
* \ param dev DRM device .
* \ param magic magic number .
*
* Searches in drm_device : : magiclist within all files with the same hash key
2006-02-02 11:37:46 +03:00
* the one with matching magic number , while holding the drm_device : : struct_mutex
2005-04-17 02:20:36 +04:00
* lock .
*/
2007-07-11 09:53:27 +04:00
static struct drm_file * drm_find_file ( struct drm_device * dev , drm_magic_t magic )
2005-04-17 02:20:36 +04:00
{
2007-07-11 09:53:27 +04:00
struct drm_file * retval = NULL ;
2007-07-11 10:21:47 +04:00
struct drm_magic_entry * pt ;
2007-07-12 04:26:44 +04:00
struct drm_hash_item * hash ;
2005-04-17 02:20:36 +04:00
2006-02-02 11:37:46 +03:00
mutex_lock ( & dev - > struct_mutex ) ;
2006-08-07 16:22:10 +04:00
if ( ! drm_ht_find_item ( & dev - > magiclist , ( unsigned long ) magic , & hash ) ) {
2007-07-11 10:21:47 +04:00
pt = drm_hash_entry ( hash , struct drm_magic_entry , hash_item ) ;
2006-08-07 16:22:10 +04:00
retval = pt - > priv ;
2005-04-17 02:20:36 +04:00
}
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
/**
* Adds a magic number .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ param dev DRM device .
* \ param priv file private data .
* \ param magic magic number .
*
* Creates a drm_magic_entry structure and appends to the linked list
* associated the magic number hash key in drm_device : : magiclist , while holding
2006-02-02 11:37:46 +03:00
* the drm_device : : struct_mutex lock .
2005-04-17 02:20:36 +04:00
*/
2007-07-11 09:53:27 +04:00
static int drm_add_magic ( struct drm_device * dev , struct drm_file * priv ,
2005-09-25 08:28:13 +04:00
drm_magic_t magic )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:21:47 +04:00
struct drm_magic_entry * entry ;
2005-04-17 02:20:36 +04:00
DRM_DEBUG ( " %d \n " , magic ) ;
2005-09-25 08:28:13 +04:00
entry = drm_alloc ( sizeof ( * entry ) , DRM_MEM_MAGIC ) ;
if ( ! entry )
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
memset ( entry , 0 , sizeof ( * entry ) ) ;
2005-09-25 08:28:13 +04:00
entry - > priv = priv ;
2005-04-17 02:20:36 +04:00
2006-08-07 16:22:10 +04:00
entry - > hash_item . key = ( unsigned long ) magic ;
2006-02-02 11:37:46 +03:00
mutex_lock ( & dev - > struct_mutex ) ;
2006-08-07 16:22:10 +04:00
drm_ht_insert_item ( & dev - > magiclist , & entry - > hash_item ) ;
list_add_tail ( & entry - > head , & dev - > magicfree ) ;
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* Remove a magic number .
2005-09-25 08:28:13 +04:00
*
2005-04-17 02:20:36 +04:00
* \ param dev DRM device .
* \ param magic magic number .
*
* Searches and unlinks the entry in drm_device : : magiclist with the magic
2006-02-02 11:37:46 +03:00
* number hash key , while holding the drm_device : : struct_mutex lock .
2005-04-17 02:20:36 +04:00
*/
2007-07-11 09:53:27 +04:00
static int drm_remove_magic ( struct drm_device * dev , drm_magic_t magic )
2005-04-17 02:20:36 +04:00
{
2007-07-11 10:21:47 +04:00
struct drm_magic_entry * pt ;
2007-07-12 04:26:44 +04:00
struct drm_hash_item * hash ;
2005-04-17 02:20:36 +04:00
DRM_DEBUG ( " %d \n " , magic ) ;
2006-02-02 11:37:46 +03:00
mutex_lock ( & dev - > struct_mutex ) ;
2006-08-07 16:22:10 +04:00
if ( drm_ht_find_item ( & dev - > magiclist , ( unsigned long ) magic , & hash ) ) {
mutex_unlock ( & dev - > struct_mutex ) ;
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
2007-07-11 10:21:47 +04:00
pt = drm_hash_entry ( hash , struct drm_magic_entry , hash_item ) ;
2006-08-07 16:22:10 +04:00
drm_ht_remove_item ( & dev - > magiclist , hash ) ;
list_del ( & pt - > head ) ;
2006-02-02 11:37:46 +03:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-04-17 02:20:36 +04:00
drm_free ( pt , sizeof ( * pt ) , DRM_MEM_MAGIC ) ;
2006-08-08 16:17:02 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/**
* Get a unique magic number ( ioctl ) .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg pointer to a resulting drm_auth structure .
* \ return zero on success , or a negative number on failure .
*
* If there is a magic number in drm_file : : magic then use it , otherwise
* searches an unique non - zero magic number and add it associating it with \ p
2007-08-25 14:23:09 +04:00
* file_priv .
2005-04-17 02:20:36 +04:00
*/
2007-09-03 06:06:45 +04:00
int drm_getmagic ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
static drm_magic_t sequence = 0 ;
static DEFINE_SPINLOCK ( lock ) ;
2007-09-03 06:06:45 +04:00
struct drm_auth * auth = data ;
2005-04-17 02:20:36 +04:00
2005-09-25 08:28:13 +04:00
/* Find unique magic */
2007-08-25 14:23:09 +04:00
if ( file_priv - > magic ) {
2007-09-03 06:06:45 +04:00
auth - > magic = file_priv - > magic ;
2005-04-17 02:20:36 +04:00
} else {
do {
spin_lock ( & lock ) ;
2005-09-25 08:28:13 +04:00
if ( ! sequence )
+ + sequence ; /* reserve 0 */
2007-09-03 06:06:45 +04:00
auth - > magic = sequence + + ;
2005-04-17 02:20:36 +04:00
spin_unlock ( & lock ) ;
2007-09-03 06:06:45 +04:00
} while ( drm_find_file ( dev , auth - > magic ) ) ;
file_priv - > magic = auth - > magic ;
drm_add_magic ( dev , file_priv , auth - > magic ) ;
2005-04-17 02:20:36 +04:00
}
2007-09-03 06:06:45 +04:00
DRM_DEBUG ( " %u \n " , auth - > magic ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* Authenticate with a magic .
*
* \ param inode device inode .
2007-08-25 14:23:09 +04:00
* \ param file_priv DRM file private .
2005-04-17 02:20:36 +04:00
* \ param cmd command .
* \ param arg pointer to a drm_auth structure .
* \ return zero if authentication successed , or a negative number otherwise .
*
2007-08-25 14:23:09 +04:00
* Checks if \ p file_priv is associated with the magic number passed in \ arg .
2005-04-17 02:20:36 +04:00
*/
2007-09-03 06:06:45 +04:00
int drm_authmagic ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-04-17 02:20:36 +04:00
{
2007-09-03 06:06:45 +04:00
struct drm_auth * auth = data ;
2007-07-11 09:53:27 +04:00
struct drm_file * file ;
2005-04-17 02:20:36 +04:00
2007-09-03 06:06:45 +04:00
DRM_DEBUG ( " %u \n " , auth - > magic ) ;
if ( ( file = drm_find_file ( dev , auth - > magic ) ) ) {
2005-04-17 02:20:36 +04:00
file - > authenticated = 1 ;
2007-09-03 06:06:45 +04:00
drm_remove_magic ( dev , auth - > magic ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
return - EINVAL ;
}