aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2012-01-24 12:54:21 -0500
committerHerton Ronaldo Krzesinski <herton.krzesinski@canonical.com>2012-02-13 15:15:01 -0500
commitee728aa6aeba82d58e34c9569b200a82546eef58 (patch)
tree15418574b15893ca8f562c6e676828b7f98b55c4
parent86580cdc4d82039c2210799f10f6adfb21127724 (diff)
drm: Fix authentication kernel crash
BugLink: http://bugs.launchpad.net/bugs/926309 commit 598781d71119827b454fd75d46f84755bca6f0c6 upstream. 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: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
-rw-r--r--drivers/gpu/drm/drm_auth.c6
-rw-r--r--drivers/gpu/drm/drm_fops.c5
-rw-r--r--include/drm/drmP.h1
3 files changed, 11 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 3f46772f0cb..ba23790450e 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
101 * Searches and unlinks the entry in drm_device::magiclist with the magic 101 * Searches and unlinks the entry in drm_device::magiclist with the magic
102 * number hash key, while holding the drm_device::struct_mutex lock. 102 * number hash key, while holding the drm_device::struct_mutex lock.
103 */ 103 */
104static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) 104int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
105{ 105{
106 struct drm_magic_entry *pt; 106 struct drm_magic_entry *pt;
107 struct drm_hash_item *hash; 107 struct drm_hash_item *hash;
@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
136 * If there is a magic number in drm_file::magic then use it, otherwise 136 * If there is a magic number in drm_file::magic then use it, otherwise
137 * searches an unique non-zero magic number and add it associating it with \p 137 * searches an unique non-zero magic number and add it associating it with \p
138 * file_priv. 138 * file_priv.
139 * This ioctl needs protection by the drm_global_mutex, which protects
140 * struct drm_file::magic and struct drm_magic_entry::priv.
139 */ 141 */
140int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) 142int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
141{ 143{
@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
173 * \return zero if authentication successed, or a negative number otherwise. 175 * \return zero if authentication successed, or a negative number otherwise.
174 * 176 *
175 * Checks if \p file_priv is associated with the magic number passed in \arg. 177 * Checks if \p file_priv is associated with the magic number passed in \arg.
178 * This ioctl needs protection by the drm_global_mutex, which protects
179 * struct drm_file::magic and struct drm_magic_entry::priv.
176 */ 180 */
177int drm_authmagic(struct drm_device *dev, void *data, 181int drm_authmagic(struct drm_device *dev, void *data,
178 struct drm_file *file_priv) 182 struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index fbd640dbf7e..c282f85c1c8 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -490,6 +490,11 @@ int drm_release(struct inode *inode, struct file *filp)
490 (long)old_encode_dev(file_priv->minor->device), 490 (long)old_encode_dev(file_priv->minor->device),
491 dev->open_count); 491 dev->open_count);
492 492
493 /* Release any auth tokens that might point to this file_priv,
494 (do that under the drm_global_mutex) */
495 if (file_priv->magic)
496 (void) drm_remove_magic(file_priv->master, file_priv->magic);
497
493 /* if the master has gone away we can't do anything with the lock */ 498 /* if the master has gone away we can't do anything with the lock */
494 if (file_priv->minor->master) 499 if (file_priv->minor->master)
495 drm_master_release(dev, filp); 500 drm_master_release(dev, filp);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 738b3a5faa1..40aaebf50af 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1323,6 +1323,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
1323 struct drm_file *file_priv); 1323 struct drm_file *file_priv);
1324extern int drm_authmagic(struct drm_device *dev, void *data, 1324extern int drm_authmagic(struct drm_device *dev, void *data,
1325 struct drm_file *file_priv); 1325 struct drm_file *file_priv);
1326extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
1326 1327
1327/* Cache management (drm_cache.c) */ 1328/* Cache management (drm_cache.c) */
1328void drm_clflush_pages(struct page *pages[], unsigned long num_pages); 1329void drm_clflush_pages(struct page *pages[], unsigned long num_pages);