diff mbox series

[2/2] drm/i915: consolidate 2big error checking for object sizes

Message ID 20210122173546.531842-2-matthew.auld@intel.com (mailing list archive)
State New, archived
Headers show
Series [1/2] drm/i915/dmabuf: don't trust the dma_buf->size | expand

Commit Message

Matthew Auld Jan. 22, 2021, 5:35 p.m. UTC
Throw it into a simple helper, and throw a warning if we encounter an
object which has been initialised with an object size that exceeds our
limit of INT_MAX pages.

Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c  |  9 +------
 drivers/gpu/drm/i915/gem/i915_gem_object.c  |  2 ++
 drivers/gpu/drm/i915/gem/i915_gem_object.h  | 26 +++++++++++++++++++++
 drivers/gpu/drm/i915/gem/i915_gem_region.c  | 12 +---------
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 16 +------------
 5 files changed, 31 insertions(+), 34 deletions(-)

Comments

Chris Wilson Jan. 22, 2021, 5:43 p.m. UTC | #1
Quoting Matthew Auld (2021-01-22 17:35:46)
> Throw it into a simple helper, and throw a warning if we encounter an
> object which has been initialised with an object size that exceeds our
> limit of INT_MAX pages.
> 
> Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c  |  9 +------
>  drivers/gpu/drm/i915/gem/i915_gem_object.c  |  2 ++
>  drivers/gpu/drm/i915/gem/i915_gem_object.h  | 26 +++++++++++++++++++++
>  drivers/gpu/drm/i915/gem/i915_gem_region.c  | 12 +---------
>  drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 16 +------------
>  5 files changed, 31 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> index dc11497f830b..5cc8a0b2387f 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> @@ -244,14 +244,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
>                 }
>         }
>  
> -       /*
> -        * XXX: There is a prevalence of the assumption that we fit the
> -        * object's page count inside a 32bit _signed_ variable. Let's document
> -        * this and catch if we ever need to fix it. In the meantime, if you do
> -        * spot such a local variable, please consider fixing!
> -        */
> -
> -       if (dma_buf->size >> PAGE_SHIFT > INT_MAX)
> +       if (i915_gem_object_size_2big(dma_buf->size))
>                 return ERR_PTR(-E2BIG);
>  
>         /* need to attach */
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index 70f798405f7f..d3702ea8c6aa 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -62,6 +62,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
>                           const struct drm_i915_gem_object_ops *ops,
>                           struct lock_class_key *key)
>  {
> +       GEM_CHECK_SIZE_OVERFLOW(obj->base.size);
> +
>         __mutex_init(&obj->mm.lock, ops->name ?: "obj->mm.lock", key);
>  
>         spin_lock_init(&obj->vma.lock);
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index d0ae834d787a..d9cef56533ca 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -16,6 +16,32 @@
>  #include "i915_gem_gtt.h"
>  #include "i915_vma_types.h"
>  
> +/*
> + * XXX: There is a prevalence of the assumption that we fit the
> + * object's page count inside a 32bit _signed_ variable. Let's document
> + * this and catch if we ever need to fix it. In the meantime, if you do
> + * spot such a local variable, please consider fixing!
> + *
> + * Aside from our own locals (for which we have no excuse!):
> + * - sg_table embeds unsigned int for num_pages
> + * - get_user_pages*() mixed ints with longs
> + */
> +#define GEM_CHECK_SIZE_OVERFLOW(sz) \
> +       GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> +
> +static inline bool i915_gem_object_size_2big(u64 size)
> +{
> +       struct drm_i915_gem_object *obj;
> +
> +       if (size >> PAGE_SHIFT > INT_MAX)
> +               return true;

Macro here^

Make it easy to grep, everybody gets a warning as a reminder to fix it.
And a prize to whoever does manage to trigger the warning.

> +
> +       if (overflows_type(size, obj->base.size))
> +               return true;
> +
> +       return false;
> +}
Matthew Auld Jan. 22, 2021, 5:54 p.m. UTC | #2
On Fri, 22 Jan 2021 at 17:43, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>
> Quoting Matthew Auld (2021-01-22 17:35:46)
> > Throw it into a simple helper, and throw a warning if we encounter an
> > object which has been initialised with an object size that exceeds our
> > limit of INT_MAX pages.
> >
> > Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > ---
> >  drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c  |  9 +------
> >  drivers/gpu/drm/i915/gem/i915_gem_object.c  |  2 ++
> >  drivers/gpu/drm/i915/gem/i915_gem_object.h  | 26 +++++++++++++++++++++
> >  drivers/gpu/drm/i915/gem/i915_gem_region.c  | 12 +---------
> >  drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 16 +------------
> >  5 files changed, 31 insertions(+), 34 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > index dc11497f830b..5cc8a0b2387f 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > @@ -244,14 +244,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
> >                 }
> >         }
> >
> > -       /*
> > -        * XXX: There is a prevalence of the assumption that we fit the
> > -        * object's page count inside a 32bit _signed_ variable. Let's document
> > -        * this and catch if we ever need to fix it. In the meantime, if you do
> > -        * spot such a local variable, please consider fixing!
> > -        */
> > -
> > -       if (dma_buf->size >> PAGE_SHIFT > INT_MAX)
> > +       if (i915_gem_object_size_2big(dma_buf->size))
> >                 return ERR_PTR(-E2BIG);
> >
> >         /* need to attach */
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > index 70f798405f7f..d3702ea8c6aa 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > @@ -62,6 +62,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
> >                           const struct drm_i915_gem_object_ops *ops,
> >                           struct lock_class_key *key)
> >  {
> > +       GEM_CHECK_SIZE_OVERFLOW(obj->base.size);
> > +
> >         __mutex_init(&obj->mm.lock, ops->name ?: "obj->mm.lock", key);
> >
> >         spin_lock_init(&obj->vma.lock);
> > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > index d0ae834d787a..d9cef56533ca 100644
> > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > @@ -16,6 +16,32 @@
> >  #include "i915_gem_gtt.h"
> >  #include "i915_vma_types.h"
> >
> > +/*
> > + * XXX: There is a prevalence of the assumption that we fit the
> > + * object's page count inside a 32bit _signed_ variable. Let's document
> > + * this and catch if we ever need to fix it. In the meantime, if you do
> > + * spot such a local variable, please consider fixing!
> > + *
> > + * Aside from our own locals (for which we have no excuse!):
> > + * - sg_table embeds unsigned int for num_pages
> > + * - get_user_pages*() mixed ints with longs
> > + */
> > +#define GEM_CHECK_SIZE_OVERFLOW(sz) \
> > +       GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> > +
> > +static inline bool i915_gem_object_size_2big(u64 size)
> > +{
> > +       struct drm_i915_gem_object *obj;
> > +
> > +       if (size >> PAGE_SHIFT > INT_MAX)
> > +               return true;
>
> Macro here^
>
> Make it easy to grep, everybody gets a warning as a reminder to fix it.
> And a prize to whoever does manage to trigger the warning.

But this code is user triggable, like with igt("create-massive")? What
am I missing?


>
> > +
> > +       if (overflows_type(size, obj->base.size))
> > +               return true;
> > +
> > +       return false;
> > +}
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Chris Wilson Jan. 22, 2021, 5:59 p.m. UTC | #3
Quoting Matthew Auld (2021-01-22 17:54:16)
> On Fri, 22 Jan 2021 at 17:43, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> >
> > Quoting Matthew Auld (2021-01-22 17:35:46)
> > > Throw it into a simple helper, and throw a warning if we encounter an
> > > object which has been initialised with an object size that exceeds our
> > > limit of INT_MAX pages.
> > >
> > > Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> > > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c  |  9 +------
> > >  drivers/gpu/drm/i915/gem/i915_gem_object.c  |  2 ++
> > >  drivers/gpu/drm/i915/gem/i915_gem_object.h  | 26 +++++++++++++++++++++
> > >  drivers/gpu/drm/i915/gem/i915_gem_region.c  | 12 +---------
> > >  drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 16 +------------
> > >  5 files changed, 31 insertions(+), 34 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > > index dc11497f830b..5cc8a0b2387f 100644
> > > --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
> > > @@ -244,14 +244,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
> > >                 }
> > >         }
> > >
> > > -       /*
> > > -        * XXX: There is a prevalence of the assumption that we fit the
> > > -        * object's page count inside a 32bit _signed_ variable. Let's document
> > > -        * this and catch if we ever need to fix it. In the meantime, if you do
> > > -        * spot such a local variable, please consider fixing!
> > > -        */
> > > -
> > > -       if (dma_buf->size >> PAGE_SHIFT > INT_MAX)
> > > +       if (i915_gem_object_size_2big(dma_buf->size))
> > >                 return ERR_PTR(-E2BIG);
> > >
> > >         /* need to attach */
> > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > > index 70f798405f7f..d3702ea8c6aa 100644
> > > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> > > @@ -62,6 +62,8 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
> > >                           const struct drm_i915_gem_object_ops *ops,
> > >                           struct lock_class_key *key)
> > >  {
> > > +       GEM_CHECK_SIZE_OVERFLOW(obj->base.size);
> > > +
> > >         __mutex_init(&obj->mm.lock, ops->name ?: "obj->mm.lock", key);
> > >
> > >         spin_lock_init(&obj->vma.lock);
> > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > > index d0ae834d787a..d9cef56533ca 100644
> > > --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> > > @@ -16,6 +16,32 @@
> > >  #include "i915_gem_gtt.h"
> > >  #include "i915_vma_types.h"
> > >
> > > +/*
> > > + * XXX: There is a prevalence of the assumption that we fit the
> > > + * object's page count inside a 32bit _signed_ variable. Let's document
> > > + * this and catch if we ever need to fix it. In the meantime, if you do
> > > + * spot such a local variable, please consider fixing!
> > > + *
> > > + * Aside from our own locals (for which we have no excuse!):
> > > + * - sg_table embeds unsigned int for num_pages
> > > + * - get_user_pages*() mixed ints with longs
> > > + */
> > > +#define GEM_CHECK_SIZE_OVERFLOW(sz) \
> > > +       GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> > > +
> > > +static inline bool i915_gem_object_size_2big(u64 size)
> > > +{
> > > +       struct drm_i915_gem_object *obj;
> > > +
> > > +       if (size >> PAGE_SHIFT > INT_MAX)
> > > +               return true;
> >
> > Macro here^
> >
> > Make it easy to grep, everybody gets a warning as a reminder to fix it.
> > And a prize to whoever does manage to trigger the warning.
> 
> But this code is user triggable, like with igt("create-massive")? What
> am I missing?

GEM_WARN_ON() only emits a warning in debug builds, and we try very hard
not to let that be enabled in production.
-Chris
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index dc11497f830b..5cc8a0b2387f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -244,14 +244,7 @@  struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
 		}
 	}
 
-	/*
-	 * XXX: There is a prevalence of the assumption that we fit the
-	 * object's page count inside a 32bit _signed_ variable. Let's document
-	 * this and catch if we ever need to fix it. In the meantime, if you do
-	 * spot such a local variable, please consider fixing!
-	 */
-
-	if (dma_buf->size >> PAGE_SHIFT > INT_MAX)
+	if (i915_gem_object_size_2big(dma_buf->size))
 		return ERR_PTR(-E2BIG);
 
 	/* need to attach */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 70f798405f7f..d3702ea8c6aa 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -62,6 +62,8 @@  void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			  const struct drm_i915_gem_object_ops *ops,
 			  struct lock_class_key *key)
 {
+	GEM_CHECK_SIZE_OVERFLOW(obj->base.size);
+
 	__mutex_init(&obj->mm.lock, ops->name ?: "obj->mm.lock", key);
 
 	spin_lock_init(&obj->vma.lock);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index d0ae834d787a..d9cef56533ca 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -16,6 +16,32 @@ 
 #include "i915_gem_gtt.h"
 #include "i915_vma_types.h"
 
+/*
+ * XXX: There is a prevalence of the assumption that we fit the
+ * object's page count inside a 32bit _signed_ variable. Let's document
+ * this and catch if we ever need to fix it. In the meantime, if you do
+ * spot such a local variable, please consider fixing!
+ *
+ * Aside from our own locals (for which we have no excuse!):
+ * - sg_table embeds unsigned int for num_pages
+ * - get_user_pages*() mixed ints with longs
+ */
+#define GEM_CHECK_SIZE_OVERFLOW(sz) \
+	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
+
+static inline bool i915_gem_object_size_2big(u64 size)
+{
+	struct drm_i915_gem_object *obj;
+
+	if (size >> PAGE_SHIFT > INT_MAX)
+		return true;
+
+	if (overflows_type(size, obj->base.size))
+		return true;
+
+	return false;
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915);
 
 struct drm_i915_gem_object *i915_gem_object_alloc(void);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c
index 3e3dad22a683..77dfa908f156 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
@@ -161,17 +161,7 @@  i915_gem_object_create_region(struct intel_memory_region *mem,
 	GEM_BUG_ON(!size);
 	GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT));
 
-	/*
-	 * XXX: There is a prevalence of the assumption that we fit the
-	 * object's page count inside a 32bit _signed_ variable. Let's document
-	 * this and catch if we ever need to fix it. In the meantime, if you do
-	 * spot such a local variable, please consider fixing!
-	 */
-
-	if (size >> PAGE_SHIFT > INT_MAX)
-		return ERR_PTR(-E2BIG);
-
-	if (overflows_type(size, obj->base.size))
+	if (i915_gem_object_size_2big(size))
 		return ERR_PTR(-E2BIG);
 
 	obj = i915_gem_object_alloc();
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index f2eaed6aca3d..3e4785c2dfa2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -770,21 +770,7 @@  i915_gem_userptr_ioctl(struct drm_device *dev,
 			    I915_USERPTR_UNSYNCHRONIZED))
 		return -EINVAL;
 
-	/*
-	 * XXX: There is a prevalence of the assumption that we fit the
-	 * object's page count inside a 32bit _signed_ variable. Let's document
-	 * this and catch if we ever need to fix it. In the meantime, if you do
-	 * spot such a local variable, please consider fixing!
-	 *
-	 * Aside from our own locals (for which we have no excuse!):
-	 * - sg_table embeds unsigned int for num_pages
-	 * - get_user_pages*() mixed ints with longs
-	 */
-
-	if (args->user_size >> PAGE_SHIFT > INT_MAX)
-		return -E2BIG;
-
-	if (overflows_type(args->user_size, obj->base.size))
+	if (i915_gem_object_size_2big(args->user_size))
 		return -E2BIG;
 
 	if (!args->user_size)