Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Author Rickard E. (Rik) Faith <faith@valinux.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Author Gareth Hughes <gareth@valinux.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Permission is hereby granted, free of charge, to any person obtaining a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * copy of this software and associated documentation files (the "Software"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * to deal in the Software without restriction, including without limitation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * and/or sell copies of the Software, and to permit persons to whom the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * Software is furnished to do so, subject to the following conditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * The above copyright notice and this permission notice (including the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * paragraph) shall be included in all copies or substantial portions of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * Software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * OTHER DEALINGS IN THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <drm/drm_auth.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <drm/drm_drv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <drm/drm_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <drm/drm_lease.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <drm/drm_print.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include "drm_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include "drm_legacy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * DOC: master and authentication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * &struct drm_master is used to track groups of clients with open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * primary/legacy device nodes. For every &struct drm_file which has had at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * least once successfully became the device master (either through the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * SET_MASTER IOCTL, or implicitly through opening the primary device node when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * no one else is the current master that time) there exists one &drm_master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * This is noted in &drm_file.is_master. All other clients have just a pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * to the &drm_master they are associated with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * In addition only one &drm_master can be the current master for a &drm_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * It can be switched through the DROP_MASTER and SET_MASTER IOCTL, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * implicitly through closing/openeing the primary device node. See also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * drm_is_current_master().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * Clients can authenticate against the current master (if it matches their own)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * using the GETMAGIC and AUTHMAGIC IOCTLs. Together with exchanging masters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * this allows controlled access to the device for an entire group of mutually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * trusted clients.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct drm_auth *auth = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if (!file_priv->magic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		ret = idr_alloc(&file_priv->master->magic_map, file_priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 				1, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			file_priv->magic = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	auth->magic = file_priv->magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	DRM_DEBUG("%u\n", auth->magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return ret < 0 ? ret : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) int drm_authmagic(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		  struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct drm_auth *auth = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	struct drm_file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	DRM_DEBUG("%u\n", auth->magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	file = idr_find(&file_priv->master->magic_map, auth->magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		file->authenticated = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		idr_replace(&file_priv->master->magic_map, NULL, auth->magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return file ? 0 : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct drm_master *drm_master_create(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct drm_master *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	master = kzalloc(sizeof(*master), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (!master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	kref_init(&master->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	drm_master_legacy_init(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	idr_init(&master->magic_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	master->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	/* initialize the tree of output resource lessees */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	INIT_LIST_HEAD(&master->lessees);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	INIT_LIST_HEAD(&master->lessee_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	idr_init(&master->leases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	idr_init(&master->lessee_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	return master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void drm_set_master(struct drm_device *dev, struct drm_file *fpriv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			   bool new_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	dev->master = drm_master_get(fpriv->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (dev->driver->master_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		dev->driver->master_set(dev, fpriv, new_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	fpriv->was_master = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct drm_master *old_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	lockdep_assert_held_once(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	WARN_ON(fpriv->is_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	old_master = fpriv->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	fpriv->master = drm_master_create(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (!fpriv->master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		fpriv->master = old_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	fpriv->is_master = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	fpriv->authenticated = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	drm_set_master(dev, fpriv, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (old_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		drm_master_put(&old_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * In the olden days the SET/DROP_MASTER ioctls used to return EACCES when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  * CAP_SYS_ADMIN was not set. This was used to prevent rogue applications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  * from becoming master and/or failing to release it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * At the same time, the first client (for a given VT) is _always_ master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * Thus in order for the ioctls to succeed, one had to _explicitly_ run the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  * application as root or flip the setuid bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * If the CAP_SYS_ADMIN was missing, no other client could become master...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * EVER :-( Leading to a) the graphics session dying badly or b) a completely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  * locked session.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * As some point systemd-logind was introduced to orchestrate and delegate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * master as applicable. It does so by opening the fd and passing it to users
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * while in itself logind a) does the set/drop master per users' request and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * b)  * implicitly drops master on VT switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * Even though logind looks like the future, there are a few issues:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  *  - some platforms don't have equivalent (Android, CrOS, some BSDs) so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * root is required _solely_ for SET/DROP MASTER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  *  - applications may not be updated to use it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  *  - any client which fails to drop master* can DoS the application using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * logind, to a varying degree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * * Either due missing CAP_SYS_ADMIN or simply not calling DROP_MASTER.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * Here we implement the next best thing:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  *  - ensure the logind style of fd passing works unchanged, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  *  - allow a client to drop/set master, iff it is/was master at a given point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * in time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * Note: DROP_MASTER cannot be free for all, as an arbitrator user could:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  *  - DoS/crash the arbitrator - details would be implementation specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  *  - open the node, become master implicitly and cause issues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * As a result this fixes the following when using root-less build w/o logind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  * - startx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * - weston
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  * - various compositors based on wlroots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) drm_master_check_perm(struct drm_device *dev, struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (file_priv->pid == task_pid(current) && file_priv->was_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int drm_setmaster_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	ret = drm_master_check_perm(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (drm_is_current_master(file_priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	if (dev->master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (!file_priv->master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (!file_priv->is_master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		ret = drm_new_set_master(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	if (file_priv->master->lessor != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		DRM_DEBUG_LEASE("Attempt to set lessee %d as master\n", file_priv->master->lessee_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	drm_set_master(dev, file_priv, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void drm_drop_master(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			    struct drm_file *fpriv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (dev->driver->master_drop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		dev->driver->master_drop(dev, fpriv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	drm_master_put(&dev->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			 struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	ret = drm_master_check_perm(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (!drm_is_current_master(file_priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	if (!dev->master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	if (file_priv->master->lessor != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		DRM_DEBUG_LEASE("Attempt to drop lessee %d as master\n", file_priv->master->lessee_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	drm_drop_master(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int drm_master_open(struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	struct drm_device *dev = file_priv->minor->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	/* if there is no current master make this fd it, but do not create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	 * any master object for render clients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (!dev->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		ret = drm_new_set_master(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		file_priv->master = drm_master_get(dev->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) void drm_master_release(struct drm_file *file_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	struct drm_device *dev = file_priv->minor->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	struct drm_master *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	master = file_priv->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (file_priv->magic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		idr_remove(&file_priv->master->magic_map, file_priv->magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	if (!drm_is_current_master(file_priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	drm_legacy_lock_master_cleanup(dev, master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (dev->master == file_priv->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		drm_drop_master(dev, file_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (drm_core_check_feature(dev, DRIVER_MODESET) && file_priv->is_master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		/* Revoke any leases held by this or lessees, but only if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		 * this is the "real" master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		drm_lease_revoke(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	/* drop the master reference held by the file priv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (file_priv->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		drm_master_put(&file_priv->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)  * drm_is_current_master - checks whether @priv is the current master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)  * @fpriv: DRM file private
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)  * Checks whether @fpriv is current master on its device. This decides whether a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)  * client is allowed to run DRM_MASTER IOCTLs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)  * Most of the modern IOCTL which require DRM_MASTER are for kernel modesetting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)  * - the current master is assumed to own the non-shareable display hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) bool drm_is_current_master(struct drm_file *fpriv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) EXPORT_SYMBOL(drm_is_current_master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)  * drm_master_get - reference a master pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)  * @master: &struct drm_master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)  * Increments the reference count of @master and returns a pointer to @master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct drm_master *drm_master_get(struct drm_master *master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	kref_get(&master->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	return master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) EXPORT_SYMBOL(drm_master_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void drm_master_destroy(struct kref *kref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	struct drm_master *master = container_of(kref, struct drm_master, refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	struct drm_device *dev = master->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	if (drm_core_check_feature(dev, DRIVER_MODESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		drm_lease_destroy(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	drm_legacy_master_rmmaps(dev, master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	idr_destroy(&master->magic_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	idr_destroy(&master->leases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	idr_destroy(&master->lessee_idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	kfree(master->unique);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	kfree(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)  * drm_master_put - unreference and clear a master pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)  * @master: pointer to a pointer of &struct drm_master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  * This decrements the &drm_master behind @master and sets it to NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) void drm_master_put(struct drm_master **master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	kref_put(&(*master)->refcount, drm_master_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	*master = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) EXPORT_SYMBOL(drm_master_put);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Used by drm_client and drm_fb_helper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) bool drm_master_internal_acquire(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	mutex_lock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	if (dev->master) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) EXPORT_SYMBOL(drm_master_internal_acquire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Used by drm_client and drm_fb_helper */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) void drm_master_internal_release(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	mutex_unlock(&dev->master_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) EXPORT_SYMBOL(drm_master_internal_release);