Commit 598781d7 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

drm: Fix authentication kernel crash

If the master tries to authenticate a client using drm_authmagic and
that client has already closed its drm file descriptor,
either wilfully or because it was terminated, the
call to drm_authmagic will dereference a stale pointer into kmalloc'ed memory
and corrupt it.

Typically this results in a hard system hang.

This patch fixes that problem by removing any authentication tokens
(struct drm_magic_entry) open for a file descriptor when that file
descriptor is closed.
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 15b63d35
...@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv, ...@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
* Searches and unlinks the entry in drm_device::magiclist with the magic * Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock. * number hash key, while holding the drm_device::struct_mutex lock.
*/ */
static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{ {
struct drm_magic_entry *pt; struct drm_magic_entry *pt;
struct drm_hash_item *hash; struct drm_hash_item *hash;
...@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) ...@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
* If there is a magic number in drm_file::magic then use it, otherwise * 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 * searches an unique non-zero magic number and add it associating it with \p
* file_priv. * file_priv.
* This ioctl needs protection by the drm_global_mutex, which protects
* struct drm_file::magic and struct drm_magic_entry::priv.
*/ */
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{ {
...@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
* \return zero if authentication successed, or a negative number otherwise. * \return zero if authentication successed, or a negative number otherwise.
* *
* Checks if \p file_priv is associated with the magic number passed in \arg. * Checks if \p file_priv is associated with the magic number passed in \arg.
* This ioctl needs protection by the drm_global_mutex, which protects
* struct drm_file::magic and struct drm_magic_entry::priv.
*/ */
int drm_authmagic(struct drm_device *dev, void *data, int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
......
...@@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp)
(long)old_encode_dev(file_priv->minor->device), (long)old_encode_dev(file_priv->minor->device),
dev->open_count); dev->open_count);
/* Release any auth tokens that might point to this file_priv,
(do that under the drm_global_mutex) */
if (file_priv->magic)
(void) drm_remove_magic(file_priv->master, file_priv->magic);
/* if the master has gone away we can't do anything with the lock */ /* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master) if (file_priv->minor->master)
drm_master_release(dev, filp); drm_master_release(dev, filp);
......
...@@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data, ...@@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_authmagic(struct drm_device *dev, void *data, extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
/* Cache management (drm_cache.c) */ /* Cache management (drm_cache.c) */
void drm_clflush_pages(struct page *pages[], unsigned long num_pages); void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment