Showing error 1623

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/gpu/drm/drm_gem.c
Line in file: 97
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-10 07:54:05 UTC


Source:

  1/*
  2 * Copyright �� 2008 Intel Corporation
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21 * IN THE SOFTWARE.
 22 *
 23 * Authors:
 24 *    Eric Anholt <eric@anholt.net>
 25 *
 26 */
 27
 28#include <linux/types.h>
 29#include <linux/slab.h>
 30#include <linux/mm.h>
 31#include <linux/uaccess.h>
 32#include <linux/fs.h>
 33#include <linux/file.h>
 34#include <linux/module.h>
 35#include <linux/mman.h>
 36#include <linux/pagemap.h>
 37#include "drmP.h"
 38
 39/** @file drm_gem.c
 40 *
 41 * This file provides some of the base ioctls and library routines for
 42 * the graphics memory manager implemented by each device driver.
 43 *
 44 * Because various devices have different requirements in terms of
 45 * synchronization and migration strategies, implementing that is left up to
 46 * the driver, and all that the general API provides should be generic --
 47 * allocating objects, reading/writing data with the cpu, freeing objects.
 48 * Even there, platform-dependent optimizations for reading/writing data with
 49 * the CPU mean we'll likely hook those out to driver-specific calls.  However,
 50 * the DRI2 implementation wants to have at least allocate/mmap be generic.
 51 *
 52 * The goal was to have swap-backed object allocation managed through
 53 * struct file.  However, file descriptors as handles to a struct file have
 54 * two major failings:
 55 * - Process limits prevent more than 1024 or so being used at a time by
 56 *   default.
 57 * - Inability to allocate high fds will aggravate the X Server's select()
 58 *   handling, and likely that of many GL client applications as well.
 59 *
 60 * This led to a plan of using our own integer IDs (called handles, following
 61 * DRM terminology) to mimic fds, and implement the fd syscalls we need as
 62 * ioctls.  The objects themselves will still include the struct file so
 63 * that we can transition to fds if the required kernel infrastructure shows
 64 * up at a later date, and as our interface with shmfs for memory allocation.
 65 */
 66
 67/**
 68 * Initialize the GEM device fields
 69 */
 70
 71int
 72drm_gem_init(struct drm_device *dev)
 73{
 74        spin_lock_init(&dev->object_name_lock);
 75        idr_init(&dev->object_name_idr);
 76        atomic_set(&dev->object_count, 0);
 77        atomic_set(&dev->object_memory, 0);
 78        atomic_set(&dev->pin_count, 0);
 79        atomic_set(&dev->pin_memory, 0);
 80        atomic_set(&dev->gtt_count, 0);
 81        atomic_set(&dev->gtt_memory, 0);
 82        return 0;
 83}
 84
 85/**
 86 * Allocate a GEM object of the specified size with shmfs backing store
 87 */
 88struct drm_gem_object *
 89drm_gem_object_alloc(struct drm_device *dev, size_t size)
 90{
 91        struct drm_gem_object *obj;
 92
 93        BUG_ON((size & (PAGE_SIZE - 1)) != 0);
 94
 95        obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
 96
 97        obj->dev = dev;
 98        obj->filp = shmem_file_setup("drm mm object", size, 0);
 99        if (IS_ERR(obj->filp)) {
100                kfree(obj);
101                return NULL;
102        }
103
104        kref_init(&obj->refcount);
105        kref_init(&obj->handlecount);
106        obj->size = size;
107        if (dev->driver->gem_init_object != NULL &&
108            dev->driver->gem_init_object(obj) != 0) {
109                fput(obj->filp);
110                kfree(obj);
111                return NULL;
112        }
113        atomic_inc(&dev->object_count);
114        atomic_add(obj->size, &dev->object_memory);
115        return obj;
116}
117EXPORT_SYMBOL(drm_gem_object_alloc);
118
119/**
120 * Removes the mapping from handle to filp for this object.
121 */
122static int
123drm_gem_handle_delete(struct drm_file *filp, int handle)
124{
125        struct drm_device *dev;
126        struct drm_gem_object *obj;
127
128        /* This is gross. The idr system doesn't let us try a delete and
129         * return an error code.  It just spews if you fail at deleting.
130         * So, we have to grab a lock around finding the object and then
131         * doing the delete on it and dropping the refcount, or the user
132         * could race us to double-decrement the refcount and cause a
133         * use-after-free later.  Given the frequency of our handle lookups,
134         * we may want to use ida for number allocation and a hash table
135         * for the pointers, anyway.
136         */
137        spin_lock(&filp->table_lock);
138
139        /* Check if we currently have a reference on the object */
140        obj = idr_find(&filp->object_idr, handle);
141        if (obj == NULL) {
142                spin_unlock(&filp->table_lock);
143                return -EINVAL;
144        }
145        dev = obj->dev;
146
147        /* Release reference and decrement refcount. */
148        idr_remove(&filp->object_idr, handle);
149        spin_unlock(&filp->table_lock);
150
151        mutex_lock(&dev->struct_mutex);
152        drm_gem_object_handle_unreference(obj);
153        mutex_unlock(&dev->struct_mutex);
154
155        return 0;
156}
157
158/**
159 * Create a handle for this object. This adds a handle reference
160 * to the object, which includes a regular reference count. Callers
161 * will likely want to dereference the object afterwards.
162 */
163int
164drm_gem_handle_create(struct drm_file *file_priv,
165                       struct drm_gem_object *obj,
166                       int *handlep)
167{
168        int        ret;
169
170        /*
171         * Get the user-visible handle using idr.
172         */
173again:
174        /* ensure there is space available to allocate a handle */
175        if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
176                return -ENOMEM;
177
178        /* do the allocation under our spinlock */
179        spin_lock(&file_priv->table_lock);
180        ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
181        spin_unlock(&file_priv->table_lock);
182        if (ret == -EAGAIN)
183                goto again;
184
185        if (ret != 0)
186                return ret;
187
188        drm_gem_object_handle_reference(obj);
189        return 0;
190}
191EXPORT_SYMBOL(drm_gem_handle_create);
192
193/** Returns a reference to the object named by the handle. */
194struct drm_gem_object *
195drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
196                      int handle)
197{
198        struct drm_gem_object *obj;
199
200        spin_lock(&filp->table_lock);
201
202        /* Check if we currently have a reference on the object */
203        obj = idr_find(&filp->object_idr, handle);
204        if (obj == NULL) {
205                spin_unlock(&filp->table_lock);
206                return NULL;
207        }
208
209        drm_gem_object_reference(obj);
210
211        spin_unlock(&filp->table_lock);
212
213        return obj;
214}
215EXPORT_SYMBOL(drm_gem_object_lookup);
216
217/**
218 * Releases the handle to an mm object.
219 */
220int
221drm_gem_close_ioctl(struct drm_device *dev, void *data,
222                    struct drm_file *file_priv)
223{
224        struct drm_gem_close *args = data;
225        int ret;
226
227        if (!(dev->driver->driver_features & DRIVER_GEM))
228                return -ENODEV;
229
230        ret = drm_gem_handle_delete(file_priv, args->handle);
231
232        return ret;
233}
234
235/**
236 * Create a global name for an object, returning the name.
237 *
238 * Note that the name does not hold a reference; when the object
239 * is freed, the name goes away.
240 */
241int
242drm_gem_flink_ioctl(struct drm_device *dev, void *data,
243                    struct drm_file *file_priv)
244{
245        struct drm_gem_flink *args = data;
246        struct drm_gem_object *obj;
247        int ret;
248
249        if (!(dev->driver->driver_features & DRIVER_GEM))
250                return -ENODEV;
251
252        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
253        if (obj == NULL)
254                return -EBADF;
255
256again:
257        if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
258                return -ENOMEM;
259
260        spin_lock(&dev->object_name_lock);
261        if (obj->name) {
262                args->name = obj->name;
263                spin_unlock(&dev->object_name_lock);
264                return 0;
265        }
266        ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
267                                 &obj->name);
268        spin_unlock(&dev->object_name_lock);
269        if (ret == -EAGAIN)
270                goto again;
271
272        if (ret != 0) {
273                mutex_lock(&dev->struct_mutex);
274                drm_gem_object_unreference(obj);
275                mutex_unlock(&dev->struct_mutex);
276                return ret;
277        }
278
279        /*
280         * Leave the reference from the lookup around as the
281         * name table now holds one
282         */
283        args->name = (uint64_t) obj->name;
284
285        return 0;
286}
287
288/**
289 * Open an object using the global name, returning a handle and the size.
290 *
291 * This handle (of course) holds a reference to the object, so the object
292 * will not go away until the handle is deleted.
293 */
294int
295drm_gem_open_ioctl(struct drm_device *dev, void *data,
296                   struct drm_file *file_priv)
297{
298        struct drm_gem_open *args = data;
299        struct drm_gem_object *obj;
300        int ret;
301        int handle;
302
303        if (!(dev->driver->driver_features & DRIVER_GEM))
304                return -ENODEV;
305
306        spin_lock(&dev->object_name_lock);
307        obj = idr_find(&dev->object_name_idr, (int) args->name);
308        if (obj)
309                drm_gem_object_reference(obj);
310        spin_unlock(&dev->object_name_lock);
311        if (!obj)
312                return -ENOENT;
313
314        ret = drm_gem_handle_create(file_priv, obj, &handle);
315        mutex_lock(&dev->struct_mutex);
316        drm_gem_object_unreference(obj);
317        mutex_unlock(&dev->struct_mutex);
318        if (ret)
319                return ret;
320
321        args->handle = handle;
322        args->size = obj->size;
323
324        return 0;
325}
326
327/**
328 * Called at device open time, sets up the structure for handling refcounting
329 * of mm objects.
330 */
331void
332drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
333{
334        idr_init(&file_private->object_idr);
335        spin_lock_init(&file_private->table_lock);
336}
337
338/**
339 * Called at device close to release the file's
340 * handle references on objects.
341 */
342static int
343drm_gem_object_release_handle(int id, void *ptr, void *data)
344{
345        struct drm_gem_object *obj = ptr;
346
347        drm_gem_object_handle_unreference(obj);
348
349        return 0;
350}
351
352/**
353 * Called at close time when the filp is going away.
354 *
355 * Releases any remaining references on objects by this filp.
356 */
357void
358drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
359{
360        mutex_lock(&dev->struct_mutex);
361        idr_for_each(&file_private->object_idr,
362                     &drm_gem_object_release_handle, NULL);
363
364        idr_destroy(&file_private->object_idr);
365        mutex_unlock(&dev->struct_mutex);
366}
367
368/**
369 * Called after the last reference to the object has been lost.
370 *
371 * Frees the object
372 */
373void
374drm_gem_object_free(struct kref *kref)
375{
376        struct drm_gem_object *obj = (struct drm_gem_object *) kref;
377        struct drm_device *dev = obj->dev;
378
379        BUG_ON(!mutex_is_locked(&dev->struct_mutex));
380
381        if (dev->driver->gem_free_object != NULL)
382                dev->driver->gem_free_object(obj);
383
384        fput(obj->filp);
385        atomic_dec(&dev->object_count);
386        atomic_sub(obj->size, &dev->object_memory);
387        kfree(obj);
388}
389EXPORT_SYMBOL(drm_gem_object_free);
390
391/**
392 * Called after the last handle to the object has been closed
393 *
394 * Removes any name for the object. Note that this must be
395 * called before drm_gem_object_free or we'll be touching
396 * freed memory
397 */
398void
399drm_gem_object_handle_free(struct kref *kref)
400{
401        struct drm_gem_object *obj = container_of(kref,
402                                                  struct drm_gem_object,
403                                                  handlecount);
404        struct drm_device *dev = obj->dev;
405
406        /* Remove any name for this object */
407        spin_lock(&dev->object_name_lock);
408        if (obj->name) {
409                idr_remove(&dev->object_name_idr, obj->name);
410                spin_unlock(&dev->object_name_lock);
411                /*
412                 * The object name held a reference to this object, drop
413                 * that now.
414                 */
415                drm_gem_object_unreference(obj);
416        } else
417                spin_unlock(&dev->object_name_lock);
418
419}
420EXPORT_SYMBOL(drm_gem_object_handle_free);
421