All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation
@ 2022-07-05 12:24 ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

This patch series fixes integer overflow or integer truncation issues in
page lookups, ttm place configuration and scatterlist creation, etc.
We need to check that we avoid integer overflows when looking up a page,
and so fix all the instances where we have mistakenly used a plain integer
instead of a more suitable long.
And there is an impedance mismatch between the scatterlist API using
unsigned int and our memory/page accounting in unsigned long. That is we
may try to create a scatterlist for a large object that overflows returning
a small table into which we try to fit very many pages. As the object size
is under the control of userspace, we have to be prudent and catch the
conversion errors. To catch the implicit truncation as we switch from
unsigned long into the scatterlist's unsigned int, we use our overflows_type
check and report E2BIG prior to the operation. This is already used in
our create ioctls to indicate if the uABI request is simply too large for
the backing store. 
And ttm place also has the same problem with scatterlist creation,
and we fix the integer truncation problem with the way approached by
scatterlist creation.
And It corrects the error code to return -E2BIG when creating gem objects
using ttm or shmem, if the size is too large in each case.
In order to provide a common macro, it moves and adds a few utility macros into drm util header

Testcase: igt@gem_create@create-massive
Testcase: igt@gem_userptr_blits@input-checking
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5411
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Nirmoy Das <nirmoy.das@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>

Chris Wilson (3):
  drm/i915/gem: Typecheck page lookups
  drm/i915: Check for integer truncation on scatterlist creation
  drm/i915: Remove truncation warning for large objects

Gwan-gyeong Mun (4):
  drm: Move and add a few utility macros into drm util header
  drm/i915: Check for integer truncation on the configuration of ttm
    place
  drm/i915: Check if the size is too big while creating shmem file
  drm/i915: Use error code as -E2BIG when the size of gem ttm object is
    too large

 drivers/gpu/drm/i915/gem/i915_gem_internal.c  |  6 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 77 +++++++++++--------
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 +++---
 drivers/gpu/drm/i915/gem/i915_gem_phys.c      |  4 +
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c     | 14 +++-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 29 ++++++-
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c   |  5 +-
 .../drm/i915/gem/selftests/i915_gem_context.c | 12 +--
 .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +-
 .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +-
 drivers/gpu/drm/i915/gvt/dmabuf.c             |  9 ++-
 drivers/gpu/drm/i915/i915_gem.c               | 18 ++++-
 drivers/gpu/drm/i915/i915_scatterlist.h       |  8 ++
 drivers/gpu/drm/i915/i915_utils.h             |  5 +-
 drivers/gpu/drm/i915/i915_vma.c               |  8 +-
 drivers/gpu/drm/i915/intel_region_ttm.c       | 16 +++-
 include/drm/drm_util.h                        | 54 +++++++++++++
 18 files changed, 226 insertions(+), 87 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 0/7] Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation
@ 2022-07-05 12:24 ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

This patch series fixes integer overflow or integer truncation issues in
page lookups, ttm place configuration and scatterlist creation, etc.
We need to check that we avoid integer overflows when looking up a page,
and so fix all the instances where we have mistakenly used a plain integer
instead of a more suitable long.
And there is an impedance mismatch between the scatterlist API using
unsigned int and our memory/page accounting in unsigned long. That is we
may try to create a scatterlist for a large object that overflows returning
a small table into which we try to fit very many pages. As the object size
is under the control of userspace, we have to be prudent and catch the
conversion errors. To catch the implicit truncation as we switch from
unsigned long into the scatterlist's unsigned int, we use our overflows_type
check and report E2BIG prior to the operation. This is already used in
our create ioctls to indicate if the uABI request is simply too large for
the backing store. 
And ttm place also has the same problem with scatterlist creation,
and we fix the integer truncation problem with the way approached by
scatterlist creation.
And It corrects the error code to return -E2BIG when creating gem objects
using ttm or shmem, if the size is too large in each case.
In order to provide a common macro, it moves and adds a few utility macros into drm util header

Testcase: igt@gem_create@create-massive
Testcase: igt@gem_userptr_blits@input-checking
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5411
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Nirmoy Das <nirmoy.das@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>

Chris Wilson (3):
  drm/i915/gem: Typecheck page lookups
  drm/i915: Check for integer truncation on scatterlist creation
  drm/i915: Remove truncation warning for large objects

Gwan-gyeong Mun (4):
  drm: Move and add a few utility macros into drm util header
  drm/i915: Check for integer truncation on the configuration of ttm
    place
  drm/i915: Check if the size is too big while creating shmem file
  drm/i915: Use error code as -E2BIG when the size of gem ttm object is
    too large

 drivers/gpu/drm/i915/gem/i915_gem_internal.c  |  6 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 77 +++++++++++--------
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 +++---
 drivers/gpu/drm/i915/gem/i915_gem_phys.c      |  4 +
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c     | 14 +++-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 29 ++++++-
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c   |  5 +-
 .../drm/i915/gem/selftests/i915_gem_context.c | 12 +--
 .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +-
 .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +-
 drivers/gpu/drm/i915/gvt/dmabuf.c             |  9 ++-
 drivers/gpu/drm/i915/i915_gem.c               | 18 ++++-
 drivers/gpu/drm/i915/i915_scatterlist.h       |  8 ++
 drivers/gpu/drm/i915/i915_utils.h             |  5 +-
 drivers/gpu/drm/i915/i915_vma.c               |  8 +-
 drivers/gpu/drm/i915/intel_region_ttm.c       | 16 +++-
 include/drm/drm_util.h                        | 54 +++++++++++++
 18 files changed, 226 insertions(+), 87 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

It moves overflows_type utility macro into drm util header from i915_utils
header. The overflows_type can be used to catch the truncation between data
types. And it adds safe_conversion() macro which performs a type conversion
(cast) of an source value into a new variable, checking that the
destination is large enough to hold the source value.
And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
while compiling.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Nirmoy Das <nirmoy.das@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_utils.h |  5 +--
 include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index c10d68cdc3ca..345e5b2dc1cd 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/sched/clock.h>
+#include <drm/drm_util.h>
 
 #ifdef CONFIG_X86
 #include <asm/hypervisor.h>
@@ -111,10 +112,6 @@ bool i915_error_injected(void);
 #define range_overflows_end_t(type, start, size, max) \
 	range_overflows_end((type)(start), (type)(size), (type)(max))
 
-/* Note we don't consider signbits :| */
-#define overflows_type(x, T) \
-	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
-
 #define ptr_mask_bits(ptr, n) ({					\
 	unsigned long __v = (unsigned long)(ptr);			\
 	(typeof(ptr))(__v & -BIT(n));					\
diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
index 79952d8c4bba..c56230e39e37 100644
--- a/include/drm/drm_util.h
+++ b/include/drm/drm_util.h
@@ -62,6 +62,60 @@
  */
 #define for_each_if(condition) if (!(condition)) {} else
 
+/**
+ * overflows_type - helper for checking the truncation between data types
+ * @x: Source for overflow type comparison
+ * @T: Destination for overflow type comparison
+ *
+ * It compares the values and size of each data type between the first and
+ * second argument to check whether truncation can occur when assigning the
+ * first argument to the variable of the second argument.
+ * It does't consider signbits.
+ *
+ * Returns:
+ * True if truncation can occur, false otherwise.
+ */
+#define overflows_type(x, T) \
+	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
+
+/**
+ * exact_type - break compile if source type and destination value's type are
+ * not the same
+ * @T: Source type
+ * @n: Destination value
+ *
+ * It is a helper macro for a poor man's -Wconversion: only allow variables of
+ * an exact type. It determines whether the source type and destination value's
+ * type are the same while compiling, and it breaks compile if two types are
+ * not the same
+ */
+#define exact_type(T, n) \
+	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
+
+/**
+ * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
+ * @n: value to compare pgoff_t type
+ *
+ * It breaks compile if the argument value's type is not pgoff_t type.
+ */
+#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
+
+/*
+ * safe_conversion - perform a type conversion (cast) of an source value into
+ * a new variable, checking that the destination is large enough to hold the
+ * source value.
+ * @ptr: Destination pointer address
+ * @value: Source value
+ *
+ * Returns:
+ * If the value would overflow the destination, it returns false.
+ */
+#define safe_conversion(ptr, value) ({ \
+	typeof(value) __v = (value); \
+	typeof(ptr) __ptr = (ptr); \
+	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
+})
+
 /**
  * drm_can_sleep - returns true if currently okay to sleep
  *
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

It moves overflows_type utility macro into drm util header from i915_utils
header. The overflows_type can be used to catch the truncation between data
types. And it adds safe_conversion() macro which performs a type conversion
(cast) of an source value into a new variable, checking that the
destination is large enough to hold the source value.
And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
while compiling.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Nirmoy Das <nirmoy.das@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_utils.h |  5 +--
 include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index c10d68cdc3ca..345e5b2dc1cd 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/sched/clock.h>
+#include <drm/drm_util.h>
 
 #ifdef CONFIG_X86
 #include <asm/hypervisor.h>
@@ -111,10 +112,6 @@ bool i915_error_injected(void);
 #define range_overflows_end_t(type, start, size, max) \
 	range_overflows_end((type)(start), (type)(size), (type)(max))
 
-/* Note we don't consider signbits :| */
-#define overflows_type(x, T) \
-	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
-
 #define ptr_mask_bits(ptr, n) ({					\
 	unsigned long __v = (unsigned long)(ptr);			\
 	(typeof(ptr))(__v & -BIT(n));					\
diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
index 79952d8c4bba..c56230e39e37 100644
--- a/include/drm/drm_util.h
+++ b/include/drm/drm_util.h
@@ -62,6 +62,60 @@
  */
 #define for_each_if(condition) if (!(condition)) {} else
 
+/**
+ * overflows_type - helper for checking the truncation between data types
+ * @x: Source for overflow type comparison
+ * @T: Destination for overflow type comparison
+ *
+ * It compares the values and size of each data type between the first and
+ * second argument to check whether truncation can occur when assigning the
+ * first argument to the variable of the second argument.
+ * It does't consider signbits.
+ *
+ * Returns:
+ * True if truncation can occur, false otherwise.
+ */
+#define overflows_type(x, T) \
+	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
+
+/**
+ * exact_type - break compile if source type and destination value's type are
+ * not the same
+ * @T: Source type
+ * @n: Destination value
+ *
+ * It is a helper macro for a poor man's -Wconversion: only allow variables of
+ * an exact type. It determines whether the source type and destination value's
+ * type are the same while compiling, and it breaks compile if two types are
+ * not the same
+ */
+#define exact_type(T, n) \
+	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
+
+/**
+ * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
+ * @n: value to compare pgoff_t type
+ *
+ * It breaks compile if the argument value's type is not pgoff_t type.
+ */
+#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
+
+/*
+ * safe_conversion - perform a type conversion (cast) of an source value into
+ * a new variable, checking that the destination is large enough to hold the
+ * source value.
+ * @ptr: Destination pointer address
+ * @value: Source value
+ *
+ * Returns:
+ * If the value would overflow the destination, it returns false.
+ */
+#define safe_conversion(ptr, value) ({ \
+	typeof(value) __v = (value); \
+	typeof(ptr) __ptr = (ptr); \
+	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
+})
+
 /**
  * drm_can_sleep - returns true if currently okay to sleep
  *
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

We need to check that we avoid integer overflows when looking up a page,
and so fix all the instances where we have mistakenly used a plain
integer instead of a more suitable long. Be pedantic and add integer
typechecking to the lookup so that we can be sure that we are safe.
And it also uses pgoff_t as our page lookups must remain compatible with
the page cache, pgoff_t is currently exactly unsigned long.

v2: Move added i915_utils's macro into drm_util header (Jani N)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
 .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
 .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
 .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
 drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
 drivers/gpu/drm/i915/i915_vma.c               |  8 +--
 9 files changed, 100 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index ccec4055fde3..90996fe8ad45 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
 static void
 i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	pgoff_t idx = offset >> PAGE_SHIFT;
 	void *src_map;
 	void *src_ptr;
 
-	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
+	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
 
 	src_ptr = src_map + offset_in_page(offset);
 	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
@@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
 static void
 i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	pgoff_t idx = offset >> PAGE_SHIFT;
+	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
 	void __iomem *src_map;
 	void __iomem *src_ptr;
-	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
 
 	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
 				    dma - obj->mm.region->region.start,
@@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
  */
 int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
 	GEM_BUG_ON(offset >= obj->base.size);
 	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
 	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 6f0a3ce35567..a60c6f4517d5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -27,8 +27,10 @@ enum intel_region_id;
  * 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
+ * - sg_table embeds unsigned int for nents
+ *
+ * We can check for invalidly typed locals with typecheck(), see for example
+ * i915_gem_object_get_sg().
  */
 #define GEM_CHECK_SIZE_OVERFLOW(sz) \
 	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
@@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
 struct scatterlist *
 __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 			 struct i915_gem_object_page_iter *iter,
-			 unsigned int n,
-			 unsigned int *offset, bool dma);
+			 pgoff_t  n,
+			 unsigned int *offset);
+
+#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(__i915_gem_object_get_sg)(obj, it, n, offset); \
+})
 
 static inline struct scatterlist *
-i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
-		       unsigned int n,
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
 		       unsigned int *offset)
 {
-	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
+	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
 }
 
+#define i915_gem_object_get_sg(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg)(obj, n, offset); \
+})
+
 static inline struct scatterlist *
-i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
-			   unsigned int n,
+i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
 			   unsigned int *offset)
 {
-	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
+	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
 }
 
+#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg_dma)(obj, n, offset); \
+})
+
 struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj,
-			 unsigned int n);
+i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_page)(obj, n); \
+})
 
 struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
-			       unsigned int n);
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_dirty_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dirty_page)(obj, n); \
+})
 
 dma_addr_t
-i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
-				    unsigned long n,
+i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
 				    unsigned int *len);
 
+#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address_len)(obj, n, len); \
+})
+
 dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
-				unsigned long n);
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_dma_address(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address)(obj, n); \
+})
 
 void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 				 struct sg_table *pages,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 97c820eee115..1d1edcb3514b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
 }
 
 struct scatterlist *
-__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
 			 struct i915_gem_object_page_iter *iter,
-			 unsigned int n,
-			 unsigned int *offset,
-			 bool dma)
+			 pgoff_t n,
+			 unsigned int *offset)
+
 {
-	struct scatterlist *sg;
+	const bool dma = iter == &obj->mm.get_dma_page ||
+			 iter == &obj->ttm.get_io_page;
 	unsigned int idx, count;
+	struct scatterlist *sg;
 
 	might_sleep();
 	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
@@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 }
 
 struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
+(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	struct scatterlist *sg;
 	unsigned int offset;
@@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
 
 /* Like i915_gem_object_get_page(), but mark the returned page dirty */
 struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
-			       unsigned int n)
+(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	struct page *page;
 
@@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
 }
 
 dma_addr_t
-i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
-				    unsigned long n,
-				    unsigned int *len)
+(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
+				      pgoff_t n, unsigned int *len)
 {
 	struct scatterlist *sg;
 	unsigned int offset;
@@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
 }
 
 dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
-				unsigned long n)
+(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	return i915_gem_object_get_dma_address_len(obj, n, NULL);
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 7e1f8b83077f..50a02d850139 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
 	GEM_WARN_ON(bo->ttm);
 
 	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
-	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
+	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
 
 	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
 }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index c6ad67b90e8a..a18a890e681f 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
 static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 {
 	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
-	unsigned int n, m, need_flush;
+	unsigned int need_flush;
+	unsigned long n, m;
 	int err;
 
 	i915_gem_object_lock(obj, NULL);
@@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 static noinline int cpu_check(struct drm_i915_gem_object *obj,
 			      unsigned int idx, unsigned int max)
 {
-	unsigned int n, m, needs_flush;
+	unsigned int needs_flush;
+	unsigned long n;
 	int err;
 
 	i915_gem_object_lock(obj, NULL);
@@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 		goto out_unlock;
 
 	for (n = 0; n < real_page_count(obj); n++) {
-		u32 *map;
+		u32 *map, m;
 
 		map = kmap_atomic(i915_gem_object_get_page(obj, n));
 		if (needs_flush & CLFLUSH_BEFORE)
@@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 
 		for (m = 0; m < max; m++) {
 			if (map[m] != m) {
-				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
+				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
 				       __builtin_return_address(0), idx,
 				       n, real_page_count(obj), m, max,
 				       map[m], m);
@@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 
 		for (; m < DW_PER_PAGE; m++) {
 			if (map[m] != STACK_MAGIC) {
-				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
+				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
 				       __builtin_return_address(0), idx, n, m,
 				       map[m], STACK_MAGIC);
 				err = -EINVAL;
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 3ced9948a331..86e435d42546 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt_view view;
 	struct i915_vma *vma;
+	unsigned long offset;
 	unsigned long page;
 	u32 __iomem *io;
 	struct page *p;
 	unsigned int n;
-	u64 offset;
 	u32 *cpu;
 	int err;
 
@@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	cpu = kmap(p) + offset_in_page(offset);
 	drm_clflush_virt_range(cpu, sizeof(*cpu));
 	if (*cpu != (u32)page) {
-		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
+		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
 		       page, n,
 		       view.partial.offset,
 		       view.partial.size,
@@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
 	for_each_prime_number_from(page, 1, npages) {
 		struct i915_ggtt_view view =
 			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
+		unsigned long offset;
 		u32 __iomem *io;
 		struct page *p;
 		unsigned int n;
-		u64 offset;
 		u32 *cpu;
 
 		GEM_BUG_ON(view.partial.size > nreal);
@@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
 		cpu = kmap(p) + offset_in_page(offset);
 		drm_clflush_virt_range(cpu, sizeof(*cpu));
 		if (*cpu != (u32)page) {
-			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
+			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
 			       page, n,
 			       view.partial.offset,
 			       view.partial.size,
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
index fe0a890775e2..bf30763ee6bc 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
@@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
 
 static int igt_gem_huge(void *arg)
 {
-	const unsigned int nreal = 509; /* just to be awkward */
+	const unsigned long nreal = 509; /* just to be awkward */
 	struct drm_i915_private *i915 = arg;
 	struct drm_i915_gem_object *obj;
-	unsigned int n;
+	unsigned long n;
 	int err;
 
 	/* Basic sanitycheck of our huge fake object allocation */
@@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
 
 	err = i915_gem_object_pin_pages_unlocked(obj);
 	if (err) {
-		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
+		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
 		       nreal, obj->base.size / PAGE_SIZE, err);
 		goto out;
 	}
@@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
 	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
 		if (i915_gem_object_get_page(obj, n) !=
 		    i915_gem_object_get_page(obj, n % nreal)) {
-			pr_err("Page lookup mismatch at index %u [%u]\n",
+			pr_err("Page lookup mismatch at index %lu [%lu]\n",
 			       n, n % nreal);
 			err = -EINVAL;
 			goto out_unpin;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 702e5b89be22..dba58a3c3238 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
 		     struct drm_i915_gem_pread *args)
 {
 	unsigned int needs_clflush;
-	unsigned int idx, offset;
 	char __user *user_data;
+	unsigned long offset;
+	pgoff_t idx;
 	u64 remain;
 	int ret;
 
@@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+	unsigned long remain, offset;
 	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	void __user *user_data;
 	struct i915_vma *vma;
-	u64 remain, offset;
 	int ret = 0;
 
+	if (overflows_type(args->size, remain) ||
+	    overflows_type(args->offset, offset))
+		return -EINVAL;
+
 	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 
 	vma = i915_gem_gtt_prepare(obj, &node, false);
@@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
 	struct intel_runtime_pm *rpm = &i915->runtime_pm;
+	unsigned long remain, offset;
 	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	struct i915_vma *vma;
-	u64 remain, offset;
 	void __user *user_data;
 	int ret = 0;
 
+	if (overflows_type(args->size, remain) ||
+	    overflows_type(args->offset, offset))
+		return -EINVAL;
+
 	if (i915_gem_object_has_struct_page(obj)) {
 		/*
 		 * Avoid waking the device up if we can fallback, as
@@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 {
 	unsigned int partial_cacheline_write;
 	unsigned int needs_clflush;
-	unsigned int offset, idx;
 	void __user *user_data;
+	unsigned long offset;
+	pgoff_t idx;
 	u64 remain;
 	int ret;
 
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index ef3b04c7e153..28443c77b45a 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
 	     struct sg_table *st, struct scatterlist *sg)
 {
 	unsigned int column, row;
-	unsigned int src_idx;
+	pgoff_t src_idx;
 
 	for (column = 0; column < width; column++) {
 		unsigned int left;
@@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
 
 static struct scatterlist *
 remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
-			      unsigned int offset, unsigned int alignment_pad,
+			      unsigned long offset, unsigned int alignment_pad,
 			      unsigned int width, unsigned int height,
 			      unsigned int src_stride, unsigned int dst_stride,
 			      struct sg_table *st, struct scatterlist *sg,
@@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
 
 static struct scatterlist *
 remap_contiguous_pages(struct drm_i915_gem_object *obj,
-		       unsigned int obj_offset,
+		       pgoff_t obj_offset,
 		       unsigned int count,
 		       struct sg_table *st, struct scatterlist *sg)
 {
@@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
 
 static struct scatterlist *
 remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
-			       unsigned int obj_offset, unsigned int alignment_pad,
+			       pgoff_t obj_offset, unsigned int alignment_pad,
 			       unsigned int size,
 			       struct sg_table *st, struct scatterlist *sg,
 			       unsigned int *gtt_offset)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

We need to check that we avoid integer overflows when looking up a page,
and so fix all the instances where we have mistakenly used a plain
integer instead of a more suitable long. Be pedantic and add integer
typechecking to the lookup so that we can be sure that we are safe.
And it also uses pgoff_t as our page lookups must remain compatible with
the page cache, pgoff_t is currently exactly unsigned long.

v2: Move added i915_utils's macro into drm_util header (Jani N)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
 drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
 drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
 .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
 .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
 .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
 drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
 drivers/gpu/drm/i915/i915_vma.c               |  8 +--
 9 files changed, 100 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index ccec4055fde3..90996fe8ad45 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
 static void
 i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	pgoff_t idx = offset >> PAGE_SHIFT;
 	void *src_map;
 	void *src_ptr;
 
-	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
+	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
 
 	src_ptr = src_map + offset_in_page(offset);
 	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
@@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
 static void
 i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	pgoff_t idx = offset >> PAGE_SHIFT;
+	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
 	void __iomem *src_map;
 	void __iomem *src_ptr;
-	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
 
 	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
 				    dma - obj->mm.region->region.start,
@@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
  */
 int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
 {
+	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
 	GEM_BUG_ON(offset >= obj->base.size);
 	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
 	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 6f0a3ce35567..a60c6f4517d5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -27,8 +27,10 @@ enum intel_region_id;
  * 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
+ * - sg_table embeds unsigned int for nents
+ *
+ * We can check for invalidly typed locals with typecheck(), see for example
+ * i915_gem_object_get_sg().
  */
 #define GEM_CHECK_SIZE_OVERFLOW(sz) \
 	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
@@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
 struct scatterlist *
 __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 			 struct i915_gem_object_page_iter *iter,
-			 unsigned int n,
-			 unsigned int *offset, bool dma);
+			 pgoff_t  n,
+			 unsigned int *offset);
+
+#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(__i915_gem_object_get_sg)(obj, it, n, offset); \
+})
 
 static inline struct scatterlist *
-i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
-		       unsigned int n,
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
 		       unsigned int *offset)
 {
-	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
+	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
 }
 
+#define i915_gem_object_get_sg(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg)(obj, n, offset); \
+})
+
 static inline struct scatterlist *
-i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
-			   unsigned int n,
+i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
 			   unsigned int *offset)
 {
-	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
+	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
 }
 
+#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg_dma)(obj, n, offset); \
+})
+
 struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj,
-			 unsigned int n);
+i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_page)(obj, n); \
+})
 
 struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
-			       unsigned int n);
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_dirty_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dirty_page)(obj, n); \
+})
 
 dma_addr_t
-i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
-				    unsigned long n,
+i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
 				    unsigned int *len);
 
+#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address_len)(obj, n, len); \
+})
+
 dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
-				unsigned long n);
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
+
+#define i915_gem_object_get_dma_address(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address)(obj, n); \
+})
 
 void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 				 struct sg_table *pages,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 97c820eee115..1d1edcb3514b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
 }
 
 struct scatterlist *
-__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
 			 struct i915_gem_object_page_iter *iter,
-			 unsigned int n,
-			 unsigned int *offset,
-			 bool dma)
+			 pgoff_t n,
+			 unsigned int *offset)
+
 {
-	struct scatterlist *sg;
+	const bool dma = iter == &obj->mm.get_dma_page ||
+			 iter == &obj->ttm.get_io_page;
 	unsigned int idx, count;
+	struct scatterlist *sg;
 
 	might_sleep();
 	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
@@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
 }
 
 struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
+(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	struct scatterlist *sg;
 	unsigned int offset;
@@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
 
 /* Like i915_gem_object_get_page(), but mark the returned page dirty */
 struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
-			       unsigned int n)
+(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	struct page *page;
 
@@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
 }
 
 dma_addr_t
-i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
-				    unsigned long n,
-				    unsigned int *len)
+(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
+				      pgoff_t n, unsigned int *len)
 {
 	struct scatterlist *sg;
 	unsigned int offset;
@@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
 }
 
 dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
-				unsigned long n)
+(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)
 {
 	return i915_gem_object_get_dma_address_len(obj, n, NULL);
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 7e1f8b83077f..50a02d850139 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
 	GEM_WARN_ON(bo->ttm);
 
 	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
-	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
+	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
 
 	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
 }
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index c6ad67b90e8a..a18a890e681f 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
 static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 {
 	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
-	unsigned int n, m, need_flush;
+	unsigned int need_flush;
+	unsigned long n, m;
 	int err;
 
 	i915_gem_object_lock(obj, NULL);
@@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
 static noinline int cpu_check(struct drm_i915_gem_object *obj,
 			      unsigned int idx, unsigned int max)
 {
-	unsigned int n, m, needs_flush;
+	unsigned int needs_flush;
+	unsigned long n;
 	int err;
 
 	i915_gem_object_lock(obj, NULL);
@@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 		goto out_unlock;
 
 	for (n = 0; n < real_page_count(obj); n++) {
-		u32 *map;
+		u32 *map, m;
 
 		map = kmap_atomic(i915_gem_object_get_page(obj, n));
 		if (needs_flush & CLFLUSH_BEFORE)
@@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 
 		for (m = 0; m < max; m++) {
 			if (map[m] != m) {
-				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
+				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
 				       __builtin_return_address(0), idx,
 				       n, real_page_count(obj), m, max,
 				       map[m], m);
@@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
 
 		for (; m < DW_PER_PAGE; m++) {
 			if (map[m] != STACK_MAGIC) {
-				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
+				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
 				       __builtin_return_address(0), idx, n, m,
 				       map[m], STACK_MAGIC);
 				err = -EINVAL;
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 3ced9948a331..86e435d42546 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt_view view;
 	struct i915_vma *vma;
+	unsigned long offset;
 	unsigned long page;
 	u32 __iomem *io;
 	struct page *p;
 	unsigned int n;
-	u64 offset;
 	u32 *cpu;
 	int err;
 
@@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
 	cpu = kmap(p) + offset_in_page(offset);
 	drm_clflush_virt_range(cpu, sizeof(*cpu));
 	if (*cpu != (u32)page) {
-		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
+		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
 		       page, n,
 		       view.partial.offset,
 		       view.partial.size,
@@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
 	for_each_prime_number_from(page, 1, npages) {
 		struct i915_ggtt_view view =
 			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
+		unsigned long offset;
 		u32 __iomem *io;
 		struct page *p;
 		unsigned int n;
-		u64 offset;
 		u32 *cpu;
 
 		GEM_BUG_ON(view.partial.size > nreal);
@@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
 		cpu = kmap(p) + offset_in_page(offset);
 		drm_clflush_virt_range(cpu, sizeof(*cpu));
 		if (*cpu != (u32)page) {
-			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
+			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
 			       page, n,
 			       view.partial.offset,
 			       view.partial.size,
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
index fe0a890775e2..bf30763ee6bc 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
@@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
 
 static int igt_gem_huge(void *arg)
 {
-	const unsigned int nreal = 509; /* just to be awkward */
+	const unsigned long nreal = 509; /* just to be awkward */
 	struct drm_i915_private *i915 = arg;
 	struct drm_i915_gem_object *obj;
-	unsigned int n;
+	unsigned long n;
 	int err;
 
 	/* Basic sanitycheck of our huge fake object allocation */
@@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
 
 	err = i915_gem_object_pin_pages_unlocked(obj);
 	if (err) {
-		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
+		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
 		       nreal, obj->base.size / PAGE_SIZE, err);
 		goto out;
 	}
@@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
 	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
 		if (i915_gem_object_get_page(obj, n) !=
 		    i915_gem_object_get_page(obj, n % nreal)) {
-			pr_err("Page lookup mismatch at index %u [%u]\n",
+			pr_err("Page lookup mismatch at index %lu [%lu]\n",
 			       n, n % nreal);
 			err = -EINVAL;
 			goto out_unpin;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 702e5b89be22..dba58a3c3238 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
 		     struct drm_i915_gem_pread *args)
 {
 	unsigned int needs_clflush;
-	unsigned int idx, offset;
 	char __user *user_data;
+	unsigned long offset;
+	pgoff_t idx;
 	u64 remain;
 	int ret;
 
@@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+	unsigned long remain, offset;
 	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	void __user *user_data;
 	struct i915_vma *vma;
-	u64 remain, offset;
 	int ret = 0;
 
+	if (overflows_type(args->size, remain) ||
+	    overflows_type(args->offset, offset))
+		return -EINVAL;
+
 	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 
 	vma = i915_gem_gtt_prepare(obj, &node, false);
@@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
 	struct intel_runtime_pm *rpm = &i915->runtime_pm;
+	unsigned long remain, offset;
 	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	struct i915_vma *vma;
-	u64 remain, offset;
 	void __user *user_data;
 	int ret = 0;
 
+	if (overflows_type(args->size, remain) ||
+	    overflows_type(args->offset, offset))
+		return -EINVAL;
+
 	if (i915_gem_object_has_struct_page(obj)) {
 		/*
 		 * Avoid waking the device up if we can fallback, as
@@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 {
 	unsigned int partial_cacheline_write;
 	unsigned int needs_clflush;
-	unsigned int offset, idx;
 	void __user *user_data;
+	unsigned long offset;
+	pgoff_t idx;
 	u64 remain;
 	int ret;
 
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index ef3b04c7e153..28443c77b45a 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
 	     struct sg_table *st, struct scatterlist *sg)
 {
 	unsigned int column, row;
-	unsigned int src_idx;
+	pgoff_t src_idx;
 
 	for (column = 0; column < width; column++) {
 		unsigned int left;
@@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
 
 static struct scatterlist *
 remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
-			      unsigned int offset, unsigned int alignment_pad,
+			      unsigned long offset, unsigned int alignment_pad,
 			      unsigned int width, unsigned int height,
 			      unsigned int src_stride, unsigned int dst_stride,
 			      struct sg_table *st, struct scatterlist *sg,
@@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
 
 static struct scatterlist *
 remap_contiguous_pages(struct drm_i915_gem_object *obj,
-		       unsigned int obj_offset,
+		       pgoff_t obj_offset,
 		       unsigned int count,
 		       struct sg_table *st, struct scatterlist *sg)
 {
@@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
 
 static struct scatterlist *
 remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
-			       unsigned int obj_offset, unsigned int alignment_pad,
+			       pgoff_t obj_offset, unsigned int alignment_pad,
 			       unsigned int size,
 			       struct sg_table *st, struct scatterlist *sg,
 			       unsigned int *gtt_offset)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 3/7] drm/i915: Check for integer truncation on scatterlist creation
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

There is an impedance mismatch between the scatterlist API using unsigned
int and our memory/page accounting in unsigned long. That is we may try
to create a scatterlist for a large object that overflows returning a
small table into which we try to fit very many pages. As the object size
is under control of userspace, we have to be prudent and catch the
conversion errors.

To catch the implicit truncation as we switch from unsigned long into the
scatterlist's unsigned int, we use overflows_type check and report
E2BIG prior to the operation. This is already used in our create ioctls to
indicate if the uABI request is simply too large for the backing store.
Failing that type check, we have a second check at sg_alloc_table time
to make sure the values we are passing into the scatterlist API are not
truncated.

It uses pgoff_t for locals that are dealing with page indices, in this
case, the page count is the limit of the page index.
And it uses safe_conversion() macro which performs a type conversion (cast)
of an integer value into a new variable, checking that the destination is
large enough to hold the source value.

v2: Move added i915_utils's macro into drm_util header (Jani N)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Brian Welty <brian.welty@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_internal.c | 6 ++++--
 drivers/gpu/drm/i915/gem/i915_gem_object.h   | 3 ---
 drivers/gpu/drm/i915/gem/i915_gem_phys.c     | 4 ++++
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c    | 5 ++++-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c      | 4 ++++
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c  | 5 ++++-
 drivers/gpu/drm/i915/gvt/dmabuf.c            | 9 +++++----
 drivers/gpu/drm/i915/i915_scatterlist.h      | 8 ++++++++
 8 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
index c698f95af15f..ff2e6e780631 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
@@ -37,10 +37,13 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	struct sg_table *st;
 	struct scatterlist *sg;
 	unsigned int sg_page_sizes;
-	unsigned int npages;
+	pgoff_t npages; /* restricted by sg_alloc_table */
 	int max_order;
 	gfp_t gfp;
 
+	if (!safe_conversion(&npages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	max_order = MAX_ORDER;
 #ifdef CONFIG_SWIOTLB
 	if (is_swiotlb_active(obj->base.dev->dev)) {
@@ -67,7 +70,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	if (!st)
 		return -ENOMEM;
 
-	npages = obj->base.size / PAGE_SIZE;
 	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
 		kfree(st);
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index a60c6f4517d5..31bb09dccf2f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -26,9 +26,6 @@ enum intel_region_id;
  * 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 nents
- *
  * We can check for invalidly typed locals with typecheck(), see for example
  * i915_gem_object_get_sg().
  */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index 0d0e46dae559..88ba7266a3a5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -28,6 +28,10 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	void *dst;
 	int i;
 
+	/* Contiguous chunk, with a single scatterlist element */
+	if (overflows_type(obj->base.size, sg->length))
+		return -E2BIG;
+
 	if (GEM_WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 4eed3dd90ba8..604e8829e8ea 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -193,13 +193,16 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct intel_memory_region *mem = obj->mm.region;
 	struct address_space *mapping = obj->base.filp->f_mapping;
-	const unsigned long page_count = obj->base.size / PAGE_SIZE;
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
 	struct sgt_iter sgt_iter;
+	pgoff_t page_count;
 	struct page *page;
 	int ret;
 
+	if (!safe_conversion(&page_count, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	/*
 	 * Assert that the object is not currently in any GPU domain. As it
 	 * wasn't in the GTT, there shouldn't be any way it could have been in
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 50a02d850139..cdcb3ee0c433 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -815,6 +815,10 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 {
 	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
 	struct ttm_placement placement;
+	pgoff_t num_pages;
+
+	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
 
 	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index 094f06b4ce33..25785c3a0083 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -128,13 +128,16 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
 
 static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
-	const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
 	unsigned int sg_page_sizes;
 	struct page **pvec;
+	pgoff_t num_pages; /* limited by sg_alloc_table_from_pages_segment */
 	int ret;
 
+	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 01e54b45c5c1..795270cb4ec2 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -42,8 +42,7 @@
 
 #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
 
-static int vgpu_gem_get_pages(
-		struct drm_i915_gem_object *obj)
+static int vgpu_gem_get_pages(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 	struct intel_vgpu *vgpu;
@@ -52,7 +51,10 @@ static int vgpu_gem_get_pages(
 	int i, j, ret;
 	gen8_pte_t __iomem *gtt_entries;
 	struct intel_vgpu_fb_info *fb_info;
-	u32 page_num;
+	pgoff_t page_num;
+
+	if (!safe_conversion(&page_num, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
 
 	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
 	if (drm_WARN_ON(&dev_priv->drm, !fb_info))
@@ -66,7 +68,6 @@ static int vgpu_gem_get_pages(
 	if (unlikely(!st))
 		return -ENOMEM;
 
-	page_num = obj->base.size >> PAGE_SHIFT;
 	ret = sg_alloc_table(st, page_num, GFP_KERNEL);
 	if (ret) {
 		kfree(st);
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
index 12c6a1684081..c4d4d3c84cff 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.h
+++ b/drivers/gpu/drm/i915/i915_scatterlist.h
@@ -218,4 +218,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
 struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
 						     u64 region_start);
 
+/* Wrap scatterlist.h to sanity check for integer truncation */
+typedef unsigned int __sg_size_t; /* see linux/scatterlist.h */
+#define sg_alloc_table(sgt, nents, gfp) \
+	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)
+
+#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
+	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 3/7] drm/i915: Check for integer truncation on scatterlist creation
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

There is an impedance mismatch between the scatterlist API using unsigned
int and our memory/page accounting in unsigned long. That is we may try
to create a scatterlist for a large object that overflows returning a
small table into which we try to fit very many pages. As the object size
is under control of userspace, we have to be prudent and catch the
conversion errors.

To catch the implicit truncation as we switch from unsigned long into the
scatterlist's unsigned int, we use overflows_type check and report
E2BIG prior to the operation. This is already used in our create ioctls to
indicate if the uABI request is simply too large for the backing store.
Failing that type check, we have a second check at sg_alloc_table time
to make sure the values we are passing into the scatterlist API are not
truncated.

It uses pgoff_t for locals that are dealing with page indices, in this
case, the page count is the limit of the page index.
And it uses safe_conversion() macro which performs a type conversion (cast)
of an integer value into a new variable, checking that the destination is
large enough to hold the source value.

v2: Move added i915_utils's macro into drm_util header (Jani N)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Brian Welty <brian.welty@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_internal.c | 6 ++++--
 drivers/gpu/drm/i915/gem/i915_gem_object.h   | 3 ---
 drivers/gpu/drm/i915/gem/i915_gem_phys.c     | 4 ++++
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c    | 5 ++++-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c      | 4 ++++
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c  | 5 ++++-
 drivers/gpu/drm/i915/gvt/dmabuf.c            | 9 +++++----
 drivers/gpu/drm/i915/i915_scatterlist.h      | 8 ++++++++
 8 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
index c698f95af15f..ff2e6e780631 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
@@ -37,10 +37,13 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	struct sg_table *st;
 	struct scatterlist *sg;
 	unsigned int sg_page_sizes;
-	unsigned int npages;
+	pgoff_t npages; /* restricted by sg_alloc_table */
 	int max_order;
 	gfp_t gfp;
 
+	if (!safe_conversion(&npages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	max_order = MAX_ORDER;
 #ifdef CONFIG_SWIOTLB
 	if (is_swiotlb_active(obj->base.dev->dev)) {
@@ -67,7 +70,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	if (!st)
 		return -ENOMEM;
 
-	npages = obj->base.size / PAGE_SIZE;
 	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
 		kfree(st);
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index a60c6f4517d5..31bb09dccf2f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -26,9 +26,6 @@ enum intel_region_id;
  * 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 nents
- *
  * We can check for invalidly typed locals with typecheck(), see for example
  * i915_gem_object_get_sg().
  */
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index 0d0e46dae559..88ba7266a3a5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -28,6 +28,10 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	void *dst;
 	int i;
 
+	/* Contiguous chunk, with a single scatterlist element */
+	if (overflows_type(obj->base.size, sg->length))
+		return -E2BIG;
+
 	if (GEM_WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 4eed3dd90ba8..604e8829e8ea 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -193,13 +193,16 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct intel_memory_region *mem = obj->mm.region;
 	struct address_space *mapping = obj->base.filp->f_mapping;
-	const unsigned long page_count = obj->base.size / PAGE_SIZE;
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
 	struct sgt_iter sgt_iter;
+	pgoff_t page_count;
 	struct page *page;
 	int ret;
 
+	if (!safe_conversion(&page_count, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	/*
 	 * Assert that the object is not currently in any GPU domain. As it
 	 * wasn't in the GTT, there shouldn't be any way it could have been in
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 50a02d850139..cdcb3ee0c433 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -815,6 +815,10 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
 {
 	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
 	struct ttm_placement placement;
+	pgoff_t num_pages;
+
+	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
 
 	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index 094f06b4ce33..25785c3a0083 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -128,13 +128,16 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
 
 static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
-	const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
 	unsigned int sg_page_sizes;
 	struct page **pvec;
+	pgoff_t num_pages; /* limited by sg_alloc_table_from_pages_segment */
 	int ret;
 
+	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
+
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 01e54b45c5c1..795270cb4ec2 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -42,8 +42,7 @@
 
 #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
 
-static int vgpu_gem_get_pages(
-		struct drm_i915_gem_object *obj)
+static int vgpu_gem_get_pages(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 	struct intel_vgpu *vgpu;
@@ -52,7 +51,10 @@ static int vgpu_gem_get_pages(
 	int i, j, ret;
 	gen8_pte_t __iomem *gtt_entries;
 	struct intel_vgpu_fb_info *fb_info;
-	u32 page_num;
+	pgoff_t page_num;
+
+	if (!safe_conversion(&page_num, obj->base.size >> PAGE_SHIFT))
+		return -E2BIG;
 
 	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
 	if (drm_WARN_ON(&dev_priv->drm, !fb_info))
@@ -66,7 +68,6 @@ static int vgpu_gem_get_pages(
 	if (unlikely(!st))
 		return -ENOMEM;
 
-	page_num = obj->base.size >> PAGE_SHIFT;
 	ret = sg_alloc_table(st, page_num, GFP_KERNEL);
 	if (ret) {
 		kfree(st);
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
index 12c6a1684081..c4d4d3c84cff 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.h
+++ b/drivers/gpu/drm/i915/i915_scatterlist.h
@@ -218,4 +218,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
 struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
 						     u64 region_start);
 
+/* Wrap scatterlist.h to sanity check for integer truncation */
+typedef unsigned int __sg_size_t; /* see linux/scatterlist.h */
+#define sg_alloc_table(sgt, nents, gfp) \
+	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)
+
+#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
+	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)
+
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 4/7] drm/i915: Check for integer truncation on the configuration of ttm place
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

There is an impedance mismatch between the first/last valid page
frame number of ttm place in unsigned and our memory/page accounting in
unsigned long.
As the object size is under the control of userspace, we have to be prudent
and catch the conversion errors.
To catch the implicit truncation as we switch from unsigned long to
unsigned, we use overflows_type check and report E2BIG or overflow_type
prior to the operation.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 12 +++++++++---
 drivers/gpu/drm/i915/intel_region_ttm.c | 16 +++++++++++++---
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index cdcb3ee0c433..d579524663b3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -137,19 +137,25 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
 	if (mr->type == INTEL_MEMORY_SYSTEM)
 		return;
 
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+	} \
+})
 	if (flags & I915_BO_ALLOC_CONTIGUOUS)
 		place->flags |= TTM_PL_FLAG_CONTIGUOUS;
 	if (offset != I915_BO_INVALID_OFFSET) {
-		place->fpfn = offset >> PAGE_SHIFT;
-		place->lpfn = place->fpfn + (size >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place->fpfn, offset >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place->lpfn, place->fpfn + (size >> PAGE_SHIFT));
 	} else if (mr->io_size && mr->io_size < mr->total) {
 		if (flags & I915_BO_ALLOC_GPU_ONLY) {
 			place->flags |= TTM_PL_FLAG_TOPDOWN;
 		} else {
 			place->fpfn = 0;
-			place->lpfn = mr->io_size >> PAGE_SHIFT;
+			SAFE_CONVERSION(&place->lpfn, mr->io_size >> PAGE_SHIFT);
 		}
 	}
+#undef SAFE_CONVERSION
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 62ff77445b01..8fcb8654b978 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -202,24 +202,34 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
 	struct ttm_resource *res;
 	int ret;
 
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+		ret = -E2BIG; \
+		goto out; \
+	} \
+})
 	if (flags & I915_BO_ALLOC_CONTIGUOUS)
 		place.flags |= TTM_PL_FLAG_CONTIGUOUS;
 	if (offset != I915_BO_INVALID_OFFSET) {
-		place.fpfn = offset >> PAGE_SHIFT;
-		place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place.fpfn, offset >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place.lpfn, place.fpfn + (size >> PAGE_SHIFT));
 	} else if (mem->io_size && mem->io_size < mem->total) {
 		if (flags & I915_BO_ALLOC_GPU_ONLY) {
 			place.flags |= TTM_PL_FLAG_TOPDOWN;
 		} else {
 			place.fpfn = 0;
-			place.lpfn = mem->io_size >> PAGE_SHIFT;
+			SAFE_CONVERSION(&place.lpfn, mem->io_size >> PAGE_SHIFT);
 		}
 	}
+#undef SAFE_CONVERSION
 
 	mock_bo.base.size = size;
 	mock_bo.bdev = &mem->i915->bdev;
 
 	ret = man->func->alloc(man, &mock_bo, &place, &res);
+
+out:
 	if (ret == -ENOSPC)
 		ret = -ENXIO;
 	if (!ret)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 4/7] drm/i915: Check for integer truncation on the configuration of ttm place
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

There is an impedance mismatch between the first/last valid page
frame number of ttm place in unsigned and our memory/page accounting in
unsigned long.
As the object size is under the control of userspace, we have to be prudent
and catch the conversion errors.
To catch the implicit truncation as we switch from unsigned long to
unsigned, we use overflows_type check and report E2BIG or overflow_type
prior to the operation.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 12 +++++++++---
 drivers/gpu/drm/i915/intel_region_ttm.c | 16 +++++++++++++---
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index cdcb3ee0c433..d579524663b3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -137,19 +137,25 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
 	if (mr->type == INTEL_MEMORY_SYSTEM)
 		return;
 
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+	} \
+})
 	if (flags & I915_BO_ALLOC_CONTIGUOUS)
 		place->flags |= TTM_PL_FLAG_CONTIGUOUS;
 	if (offset != I915_BO_INVALID_OFFSET) {
-		place->fpfn = offset >> PAGE_SHIFT;
-		place->lpfn = place->fpfn + (size >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place->fpfn, offset >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place->lpfn, place->fpfn + (size >> PAGE_SHIFT));
 	} else if (mr->io_size && mr->io_size < mr->total) {
 		if (flags & I915_BO_ALLOC_GPU_ONLY) {
 			place->flags |= TTM_PL_FLAG_TOPDOWN;
 		} else {
 			place->fpfn = 0;
-			place->lpfn = mr->io_size >> PAGE_SHIFT;
+			SAFE_CONVERSION(&place->lpfn, mr->io_size >> PAGE_SHIFT);
 		}
 	}
+#undef SAFE_CONVERSION
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 62ff77445b01..8fcb8654b978 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -202,24 +202,34 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
 	struct ttm_resource *res;
 	int ret;
 
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+		ret = -E2BIG; \
+		goto out; \
+	} \
+})
 	if (flags & I915_BO_ALLOC_CONTIGUOUS)
 		place.flags |= TTM_PL_FLAG_CONTIGUOUS;
 	if (offset != I915_BO_INVALID_OFFSET) {
-		place.fpfn = offset >> PAGE_SHIFT;
-		place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place.fpfn, offset >> PAGE_SHIFT);
+		SAFE_CONVERSION(&place.lpfn, place.fpfn + (size >> PAGE_SHIFT));
 	} else if (mem->io_size && mem->io_size < mem->total) {
 		if (flags & I915_BO_ALLOC_GPU_ONLY) {
 			place.flags |= TTM_PL_FLAG_TOPDOWN;
 		} else {
 			place.fpfn = 0;
-			place.lpfn = mem->io_size >> PAGE_SHIFT;
+			SAFE_CONVERSION(&place.lpfn, mem->io_size >> PAGE_SHIFT);
 		}
 	}
+#undef SAFE_CONVERSION
 
 	mock_bo.base.size = size;
 	mock_bo.bdev = &mem->i915->bdev;
 
 	ret = man->func->alloc(man, &mock_bo, &place, &res);
+
+out:
 	if (ret == -ENOSPC)
 		ret = -ENXIO;
 	if (!ret)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 5/7] drm/i915: Check if the size is too big while creating shmem file
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

The __shmem_file_setup() function returns -EINVAL if size is greater than
MAX_LFS_FILESIZE. To handle the same error as other code that returns
-E2BIG when the size is too large, it add a code that returns -E2BIG when
the size is larger than the size that can be handled.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 604e8829e8ea..8495e87432f6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -541,6 +541,15 @@ static int __create_shmem(struct drm_i915_private *i915,
 
 	drm_gem_private_object_init(&i915->drm, obj, size);
 
+	/* XXX: The __shmem_file_setup() function returns -EINVAL if size is
+	 * greater than MAX_LFS_FILESIZE.
+	 * To handle the same error as other code that returns -E2BIG when
+	 * the size is too large, we add a code that returns -E2BIG when the
+	 * size is larger than the size that can be handled.
+	 */
+	if (size > MAX_LFS_FILESIZE)
+		return -E2BIG;
+
 	if (i915->mm.gemfs)
 		filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
 						 flags);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 5/7] drm/i915: Check if the size is too big while creating shmem file
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

The __shmem_file_setup() function returns -EINVAL if size is greater than
MAX_LFS_FILESIZE. To handle the same error as other code that returns
-E2BIG when the size is too large, it add a code that returns -E2BIG when
the size is larger than the size that can be handled.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 604e8829e8ea..8495e87432f6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -541,6 +541,15 @@ static int __create_shmem(struct drm_i915_private *i915,
 
 	drm_gem_private_object_init(&i915->drm, obj, size);
 
+	/* XXX: The __shmem_file_setup() function returns -EINVAL if size is
+	 * greater than MAX_LFS_FILESIZE.
+	 * To handle the same error as other code that returns -E2BIG when
+	 * the size is too large, we add a code that returns -E2BIG when the
+	 * size is larger than the size that can be handled.
+	 */
+	if (size > MAX_LFS_FILESIZE)
+		return -E2BIG;
+
 	if (i915->mm.gemfs)
 		filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
 						 flags);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 6/7] drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

The ttm_bo_init_reserved() functions returns -ENOSPC if the size is too big
to add vma. The direct function that returns -ENOSPC is drm_mm_insert_node_in_range().
To handle the same error as other code returning -E2BIG when the size is
too large, it converts return value to -E2BIG.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index d579524663b3..271f64b7e4f1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1249,6 +1249,17 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
 				   bo_type, &i915_sys_placement,
 				   page_size >> PAGE_SHIFT,
 				   &ctx, NULL, NULL, i915_ttm_bo_destroy);
+
+	/*
+	 * XXX: The ttm_bo_init_reserved() functions returns -ENOSPC if the size
+	 * is too big to add vma. The direct function that returns -ENOSPC is
+	 * drm_mm_insert_node_in_range(). To handle the same error as other code
+	 * that returns -E2BIG when the size is too large, it converts -ENOSPC to
+	 * -E2BIG.
+	 */
+	if (size >> PAGE_SHIFT > INT_MAX && ret == -ENOSPC)
+		ret = -E2BIG;
+
 	if (ret)
 		return i915_ttm_err_to_gem(ret);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 6/7] drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

The ttm_bo_init_reserved() functions returns -ENOSPC if the size is too big
to add vma. The direct function that returns -ENOSPC is drm_mm_insert_node_in_range().
To handle the same error as other code returning -E2BIG when the size is
too large, it converts return value to -E2BIG.

Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index d579524663b3..271f64b7e4f1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1249,6 +1249,17 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
 				   bo_type, &i915_sys_placement,
 				   page_size >> PAGE_SHIFT,
 				   &ctx, NULL, NULL, i915_ttm_bo_destroy);
+
+	/*
+	 * XXX: The ttm_bo_init_reserved() functions returns -ENOSPC if the size
+	 * is too big to add vma. The direct function that returns -ENOSPC is
+	 * drm_mm_insert_node_in_range(). To handle the same error as other code
+	 * that returns -E2BIG when the size is too large, it converts -ENOSPC to
+	 * -E2BIG.
+	 */
+	if (size >> PAGE_SHIFT > INT_MAX && ret == -ENOSPC)
+		ret = -E2BIG;
+
 	if (ret)
 		return i915_ttm_err_to_gem(ret);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 7/7] drm/i915: Remove truncation warning for large objects
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

Having addressed the issues surrounding incorrect types for local
variables and potential integer truncation in using the scatterlist API,
we have closed all the loop holes we had previously identified with
dangerously large object creation. As such, we can eliminate the warning
put in place to remind us to complete the review.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Brian Welty <brian.welty@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Testcase: igt@gem_create@create-massive
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.h | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 31bb09dccf2f..4d614e4c1c4e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -20,25 +20,10 @@
 
 enum intel_region_id;
 
-/*
- * 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!
- *
- * We can check for invalidly typed locals with typecheck(), see for example
- * i915_gem_object_get_sg().
- */
-#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 (GEM_CHECK_SIZE_OVERFLOW(size))
-		return true;
-
 	if (overflows_type(size, obj->base.size))
 		return true;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Intel-gfx] [PATCH v2 7/7] drm/i915: Remove truncation warning for large objects
@ 2022-07-05 12:24   ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-05 12:24 UTC (permalink / raw)
  To: intel-gfx
  Cc: thomas.hellstrom, jani.nikula, dri-devel, chris, airlied,
	matthew.auld, nirmoy.das

From: Chris Wilson <chris@chris-wilson.co.uk>

Having addressed the issues surrounding incorrect types for local
variables and potential integer truncation in using the scatterlist API,
we have closed all the loop holes we had previously identified with
dangerously large object creation. As such, we can eliminate the warning
put in place to remind us to complete the review.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Brian Welty <brian.welty@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Testcase: igt@gem_create@create-massive
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.h | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 31bb09dccf2f..4d614e4c1c4e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -20,25 +20,10 @@
 
 enum intel_region_id;
 
-/*
- * 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!
- *
- * We can check for invalidly typed locals with typecheck(), see for example
- * i915_gem_object_get_sg().
- */
-#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 (GEM_CHECK_SIZE_OVERFLOW(size))
-		return true;
-
 	if (overflows_type(size, obj->base.size))
 		return true;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:23     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:23 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:49 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> It moves overflows_type utility macro into drm util header from i915_utils
> header. The overflows_type can be used to catch the truncation between data
> types. And it adds safe_conversion() macro which performs a type conversion
> (cast) of an source value into a new variable, checking that the
> destination is large enough to hold the source value.
> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
> while compiling.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Nirmoy Das <nirmoy.das@intel.com>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_utils.h |  5 +--
>  include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
> index c10d68cdc3ca..345e5b2dc1cd 100644
> --- a/drivers/gpu/drm/i915/i915_utils.h
> +++ b/drivers/gpu/drm/i915/i915_utils.h
> @@ -32,6 +32,7 @@
>  #include <linux/types.h>
>  #include <linux/workqueue.h>
>  #include <linux/sched/clock.h>
> +#include <drm/drm_util.h>
>  
>  #ifdef CONFIG_X86
>  #include <asm/hypervisor.h>
> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>  #define range_overflows_end_t(type, start, size, max) \
>  	range_overflows_end((type)(start), (type)(size), (type)(max))
>  
> -/* Note we don't consider signbits :| */
> -#define overflows_type(x, T) \
> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> -
>  #define ptr_mask_bits(ptr, n) ({					\
>  	unsigned long __v = (unsigned long)(ptr);			\
>  	(typeof(ptr))(__v & -BIT(n));					\
> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
> index 79952d8c4bba..c56230e39e37 100644
> --- a/include/drm/drm_util.h
> +++ b/include/drm/drm_util.h
> @@ -62,6 +62,60 @@
>   */
>  #define for_each_if(condition) if (!(condition)) {} else
>  
> +/**
> + * overflows_type - helper for checking the truncation between data types
> + * @x: Source for overflow type comparison
> + * @T: Destination for overflow type comparison
> + *
> + * It compares the values and size of each data type between the first and
> + * second argument to check whether truncation can occur when assigning the
> + * first argument to the variable of the second argument.
> + * It does't consider signbits.
> + *
> + * Returns:
> + * True if truncation can occur, false otherwise.
> + */
> +#define overflows_type(x, T) \
> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))

As pointed on its description, this macro only works if both types
are either signed or unsigned. However, the macro itself doesn't check
it.

It probably worth adding something there to ensure that both types are 
either signed or unsigned. I would add this ancillary macro probably on
on a generic kernel header - as this can be useful outside drm:

	#define sign_matches(x, y) \
	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))

And then include use it at overflows_type:

	BUILD_BUG_ON(!sign_matches(x, T))

> +
> +/**
> + * exact_type - break compile if source type and destination value's type are
> + * not the same
> + * @T: Source type
> + * @n: Destination value
> + *
> + * It is a helper macro for a poor man's -Wconversion: only allow variables of
> + * an exact type. It determines whether the source type and destination value's
> + * type are the same while compiling, and it breaks compile if two types are
> + * not the same
> + */
> +#define exact_type(T, n) \
> +	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
> +
> +/**
> + * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
> + * @n: value to compare pgoff_t type
> + *
> + * It breaks compile if the argument value's type is not pgoff_t type.
> + */
> +#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
> +
> +/*
> + * safe_conversion - perform a type conversion (cast) of an source value into
> + * a new variable, checking that the destination is large enough to hold the
> + * source value.
> + * @ptr: Destination pointer address
> + * @value: Source value
> + *
> + * Returns:
> + * If the value would overflow the destination, it returns false.
> + */
> +#define safe_conversion(ptr, value) ({ \
> +	typeof(value) __v = (value); \
> +	typeof(ptr) __ptr = (ptr); \
> +	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
> +})
> +
>  /**
>   * drm_can_sleep - returns true if currently okay to sleep
>   *

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
@ 2022-07-05 14:23     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:23 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:49 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> It moves overflows_type utility macro into drm util header from i915_utils
> header. The overflows_type can be used to catch the truncation between data
> types. And it adds safe_conversion() macro which performs a type conversion
> (cast) of an source value into a new variable, checking that the
> destination is large enough to hold the source value.
> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
> while compiling.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Nirmoy Das <nirmoy.das@intel.com>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_utils.h |  5 +--
>  include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
> index c10d68cdc3ca..345e5b2dc1cd 100644
> --- a/drivers/gpu/drm/i915/i915_utils.h
> +++ b/drivers/gpu/drm/i915/i915_utils.h
> @@ -32,6 +32,7 @@
>  #include <linux/types.h>
>  #include <linux/workqueue.h>
>  #include <linux/sched/clock.h>
> +#include <drm/drm_util.h>
>  
>  #ifdef CONFIG_X86
>  #include <asm/hypervisor.h>
> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>  #define range_overflows_end_t(type, start, size, max) \
>  	range_overflows_end((type)(start), (type)(size), (type)(max))
>  
> -/* Note we don't consider signbits :| */
> -#define overflows_type(x, T) \
> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> -
>  #define ptr_mask_bits(ptr, n) ({					\
>  	unsigned long __v = (unsigned long)(ptr);			\
>  	(typeof(ptr))(__v & -BIT(n));					\
> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
> index 79952d8c4bba..c56230e39e37 100644
> --- a/include/drm/drm_util.h
> +++ b/include/drm/drm_util.h
> @@ -62,6 +62,60 @@
>   */
>  #define for_each_if(condition) if (!(condition)) {} else
>  
> +/**
> + * overflows_type - helper for checking the truncation between data types
> + * @x: Source for overflow type comparison
> + * @T: Destination for overflow type comparison
> + *
> + * It compares the values and size of each data type between the first and
> + * second argument to check whether truncation can occur when assigning the
> + * first argument to the variable of the second argument.
> + * It does't consider signbits.
> + *
> + * Returns:
> + * True if truncation can occur, false otherwise.
> + */
> +#define overflows_type(x, T) \
> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))

As pointed on its description, this macro only works if both types
are either signed or unsigned. However, the macro itself doesn't check
it.

It probably worth adding something there to ensure that both types are 
either signed or unsigned. I would add this ancillary macro probably on
on a generic kernel header - as this can be useful outside drm:

	#define sign_matches(x, y) \
	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))

And then include use it at overflows_type:

	BUILD_BUG_ON(!sign_matches(x, T))

> +
> +/**
> + * exact_type - break compile if source type and destination value's type are
> + * not the same
> + * @T: Source type
> + * @n: Destination value
> + *
> + * It is a helper macro for a poor man's -Wconversion: only allow variables of
> + * an exact type. It determines whether the source type and destination value's
> + * type are the same while compiling, and it breaks compile if two types are
> + * not the same
> + */
> +#define exact_type(T, n) \
> +	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
> +
> +/**
> + * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
> + * @n: value to compare pgoff_t type
> + *
> + * It breaks compile if the argument value's type is not pgoff_t type.
> + */
> +#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
> +
> +/*
> + * safe_conversion - perform a type conversion (cast) of an source value into
> + * a new variable, checking that the destination is large enough to hold the
> + * source value.
> + * @ptr: Destination pointer address
> + * @value: Source value
> + *
> + * Returns:
> + * If the value would overflow the destination, it returns false.
> + */
> +#define safe_conversion(ptr, value) ({ \
> +	typeof(value) __v = (value); \
> +	typeof(ptr) __ptr = (ptr); \
> +	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
> +})
> +
>  /**
>   * drm_can_sleep - returns true if currently okay to sleep
>   *

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:35     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:35 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:50 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> We need to check that we avoid integer overflows when looking up a page,
> and so fix all the instances where we have mistakenly used a plain
> integer instead of a more suitable long. Be pedantic and add integer
> typechecking to the lookup so that we can be sure that we are safe.
> And it also uses pgoff_t as our page lookups must remain compatible with
> the page cache, pgoff_t is currently exactly unsigned long.
> 
> v2: Move added i915_utils's macro into drm_util header (Jani N)
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>  drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>  drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>  .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>  .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>  .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>  drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>  drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>  9 files changed, 100 insertions(+), 55 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index ccec4055fde3..90996fe8ad45 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>  static void
>  i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	pgoff_t idx = offset >> PAGE_SHIFT;
>  	void *src_map;
>  	void *src_ptr;
>  
> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>  
>  	src_ptr = src_map + offset_in_page(offset);
>  	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>  static void
>  i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	pgoff_t idx = offset >> PAGE_SHIFT;
> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>  	void __iomem *src_map;
>  	void __iomem *src_ptr;
> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>  
>  	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>  				    dma - obj->mm.region->region.start,
> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>   */
>  int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>  	GEM_BUG_ON(offset >= obj->base.size);
>  	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>  	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index 6f0a3ce35567..a60c6f4517d5 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -27,8 +27,10 @@ enum intel_region_id;
>   * 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
> + * - sg_table embeds unsigned int for nents
> + *
> + * We can check for invalidly typed locals with typecheck(), see for example
> + * i915_gem_object_get_sg().
>   */
>  #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>  	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>  struct scatterlist *
>  __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>  			 struct i915_gem_object_page_iter *iter,
> -			 unsigned int n,
> -			 unsigned int *offset, bool dma);
> +			 pgoff_t  n,
> +			 unsigned int *offset);
> +
> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
> +})
>  
>  static inline struct scatterlist *
> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> -		       unsigned int n,
> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>  		       unsigned int *offset)
>  {
> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>  }
>  
> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_sg)(obj, n, offset); \
> +})
> +
>  static inline struct scatterlist *
> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
> -			   unsigned int n,
> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>  			   unsigned int *offset)
>  {
> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>  }
>  
> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
> +})
> +
>  struct page *
> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
> -			 unsigned int n);
> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_page(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_page)(obj, n); \
> +})
>  
>  struct page *
> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> -			       unsigned int n);
> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dirty_page)(obj, n); \
> +})
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> -				    unsigned long n,
> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>  				    unsigned int *len);
>  
> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
> +})
> +
>  dma_addr_t
> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> -				unsigned long n);
> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_dma_address(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dma_address)(obj, n); \
> +})
>  
>  void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>  				 struct sg_table *pages,
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> index 97c820eee115..1d1edcb3514b 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>  }
>  
>  struct scatterlist *
> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>  			 struct i915_gem_object_page_iter *iter,
> -			 unsigned int n,
> -			 unsigned int *offset,
> -			 bool dma)
> +			 pgoff_t n,
> +			 unsigned int *offset)
> +

Nitpick: no need to place the function name in parenthesis.

>  {
> -	struct scatterlist *sg;
> +	const bool dma = iter == &obj->mm.get_dma_page ||
> +			 iter == &obj->ttm.get_io_page;
>  	unsigned int idx, count;
> +	struct scatterlist *sg;
>  
>  	might_sleep();
>  	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>  }
>  
>  struct page *
> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above: why are you placing parenthesis at the function name here?
Just use:
	
	struct page *
	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)

>  {
>  	struct scatterlist *sg;
>  	unsigned int offset;
> @@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>  
>  /* Like i915_gem_object_get_page(), but mark the returned page dirty */
>  struct page *
> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> -			       unsigned int n)
> +(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above.

>  {
>  	struct page *page;
>  
> @@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>  }
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> -				    unsigned long n,
> -				    unsigned int *len)
> +(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
> +				      pgoff_t n, unsigned int *len)

Same as above.

>  {
>  	struct scatterlist *sg;
>  	unsigned int offset;
> @@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>  }
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> -				unsigned long n)
> +(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above.

>  {
>  	return i915_gem_object_get_dma_address_len(obj, n, NULL);
>  }
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index 7e1f8b83077f..50a02d850139 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
>  	GEM_WARN_ON(bo->ttm);
>  
>  	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
> -	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
> +	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
>  
>  	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
>  }
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> index c6ad67b90e8a..a18a890e681f 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> @@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
>  static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>  {
>  	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
> -	unsigned int n, m, need_flush;
> +	unsigned int need_flush;
> +	unsigned long n, m;
>  	int err;
>  
>  	i915_gem_object_lock(obj, NULL);
> @@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>  static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  			      unsigned int idx, unsigned int max)
>  {
> -	unsigned int n, m, needs_flush;
> +	unsigned int needs_flush;
> +	unsigned long n;
>  	int err;
>  
>  	i915_gem_object_lock(obj, NULL);
> @@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  		goto out_unlock;
>  
>  	for (n = 0; n < real_page_count(obj); n++) {
> -		u32 *map;
> +		u32 *map, m;
>  
>  		map = kmap_atomic(i915_gem_object_get_page(obj, n));
>  		if (needs_flush & CLFLUSH_BEFORE)
> @@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  
>  		for (m = 0; m < max; m++) {
>  			if (map[m] != m) {
> -				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
> +				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
>  				       __builtin_return_address(0), idx,
>  				       n, real_page_count(obj), m, max,
>  				       map[m], m);
> @@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  
>  		for (; m < DW_PER_PAGE; m++) {
>  			if (map[m] != STACK_MAGIC) {
> -				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
> +				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
>  				       __builtin_return_address(0), idx, n, m,
>  				       map[m], STACK_MAGIC);
>  				err = -EINVAL;
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> index 3ced9948a331..86e435d42546 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> @@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt_view view;
>  	struct i915_vma *vma;
> +	unsigned long offset;
>  	unsigned long page;
>  	u32 __iomem *io;
>  	struct page *p;
>  	unsigned int n;
> -	u64 offset;
>  	u32 *cpu;
>  	int err;
>  
> @@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>  	cpu = kmap(p) + offset_in_page(offset);
>  	drm_clflush_virt_range(cpu, sizeof(*cpu));
>  	if (*cpu != (u32)page) {
> -		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
> +		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>  		       page, n,
>  		       view.partial.offset,
>  		       view.partial.size,
> @@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>  	for_each_prime_number_from(page, 1, npages) {
>  		struct i915_ggtt_view view =
>  			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
> +		unsigned long offset;
>  		u32 __iomem *io;
>  		struct page *p;
>  		unsigned int n;
> -		u64 offset;
>  		u32 *cpu;
>  
>  		GEM_BUG_ON(view.partial.size > nreal);
> @@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>  		cpu = kmap(p) + offset_in_page(offset);
>  		drm_clflush_virt_range(cpu, sizeof(*cpu));
>  		if (*cpu != (u32)page) {
> -			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
> +			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>  			       page, n,
>  			       view.partial.offset,
>  			       view.partial.size,
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> index fe0a890775e2..bf30763ee6bc 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> @@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
>  
>  static int igt_gem_huge(void *arg)
>  {
> -	const unsigned int nreal = 509; /* just to be awkward */
> +	const unsigned long nreal = 509; /* just to be awkward */
>  	struct drm_i915_private *i915 = arg;
>  	struct drm_i915_gem_object *obj;
> -	unsigned int n;
> +	unsigned long n;
>  	int err;
>  
>  	/* Basic sanitycheck of our huge fake object allocation */
> @@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
>  
>  	err = i915_gem_object_pin_pages_unlocked(obj);
>  	if (err) {
> -		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
> +		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
>  		       nreal, obj->base.size / PAGE_SIZE, err);
>  		goto out;
>  	}
> @@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
>  	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
>  		if (i915_gem_object_get_page(obj, n) !=
>  		    i915_gem_object_get_page(obj, n % nreal)) {
> -			pr_err("Page lookup mismatch at index %u [%u]\n",
> +			pr_err("Page lookup mismatch at index %lu [%lu]\n",
>  			       n, n % nreal);
>  			err = -EINVAL;
>  			goto out_unpin;
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 702e5b89be22..dba58a3c3238 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
>  		     struct drm_i915_gem_pread *args)
>  {
>  	unsigned int needs_clflush;
> -	unsigned int idx, offset;
>  	char __user *user_data;
> +	unsigned long offset;
> +	pgoff_t idx;
>  	u64 remain;
>  	int ret;
>  
> @@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
>  {
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
> +	unsigned long remain, offset;
>  	intel_wakeref_t wakeref;
>  	struct drm_mm_node node;
>  	void __user *user_data;
>  	struct i915_vma *vma;
> -	u64 remain, offset;
>  	int ret = 0;
>  
> +	if (overflows_type(args->size, remain) ||
> +	    overflows_type(args->offset, offset))
> +		return -EINVAL;
> +
>  	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>  
>  	vma = i915_gem_gtt_prepare(obj, &node, false);
> @@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>  	struct intel_runtime_pm *rpm = &i915->runtime_pm;
> +	unsigned long remain, offset;
>  	intel_wakeref_t wakeref;
>  	struct drm_mm_node node;
>  	struct i915_vma *vma;
> -	u64 remain, offset;
>  	void __user *user_data;
>  	int ret = 0;
>  
> +	if (overflows_type(args->size, remain) ||
> +	    overflows_type(args->offset, offset))
> +		return -EINVAL;
> +
>  	if (i915_gem_object_has_struct_page(obj)) {
>  		/*
>  		 * Avoid waking the device up if we can fallback, as
> @@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
>  {
>  	unsigned int partial_cacheline_write;
>  	unsigned int needs_clflush;
> -	unsigned int offset, idx;
>  	void __user *user_data;
> +	unsigned long offset;
> +	pgoff_t idx;
>  	u64 remain;
>  	int ret;
>  
> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> index ef3b04c7e153..28443c77b45a 100644
> --- a/drivers/gpu/drm/i915/i915_vma.c
> +++ b/drivers/gpu/drm/i915/i915_vma.c
> @@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
>  	     struct sg_table *st, struct scatterlist *sg)
>  {
>  	unsigned int column, row;
> -	unsigned int src_idx;
> +	pgoff_t src_idx;
>  
>  	for (column = 0; column < width; column++) {
>  		unsigned int left;
> @@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
>  
>  static struct scatterlist *
>  remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
> -			      unsigned int offset, unsigned int alignment_pad,
> +			      unsigned long offset, unsigned int alignment_pad,
>  			      unsigned int width, unsigned int height,
>  			      unsigned int src_stride, unsigned int dst_stride,
>  			      struct sg_table *st, struct scatterlist *sg,
> @@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>  
>  static struct scatterlist *
>  remap_contiguous_pages(struct drm_i915_gem_object *obj,
> -		       unsigned int obj_offset,
> +		       pgoff_t obj_offset,
>  		       unsigned int count,
>  		       struct sg_table *st, struct scatterlist *sg)
>  {
> @@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
>  
>  static struct scatterlist *
>  remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
> -			       unsigned int obj_offset, unsigned int alignment_pad,
> +			       pgoff_t obj_offset, unsigned int alignment_pad,
>  			       unsigned int size,
>  			       struct sg_table *st, struct scatterlist *sg,
>  			       unsigned int *gtt_offset)

Once fixed the above nitpicks, feel free to add:

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
@ 2022-07-05 14:35     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:35 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:50 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> We need to check that we avoid integer overflows when looking up a page,
> and so fix all the instances where we have mistakenly used a plain
> integer instead of a more suitable long. Be pedantic and add integer
> typechecking to the lookup so that we can be sure that we are safe.
> And it also uses pgoff_t as our page lookups must remain compatible with
> the page cache, pgoff_t is currently exactly unsigned long.
> 
> v2: Move added i915_utils's macro into drm_util header (Jani N)
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>  drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>  drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>  .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>  .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>  .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>  drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>  drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>  9 files changed, 100 insertions(+), 55 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> index ccec4055fde3..90996fe8ad45 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>  static void
>  i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	pgoff_t idx = offset >> PAGE_SHIFT;
>  	void *src_map;
>  	void *src_ptr;
>  
> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>  
>  	src_ptr = src_map + offset_in_page(offset);
>  	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>  static void
>  i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	pgoff_t idx = offset >> PAGE_SHIFT;
> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>  	void __iomem *src_map;
>  	void __iomem *src_ptr;
> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>  
>  	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>  				    dma - obj->mm.region->region.start,
> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>   */
>  int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>  {
> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>  	GEM_BUG_ON(offset >= obj->base.size);
>  	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>  	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index 6f0a3ce35567..a60c6f4517d5 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -27,8 +27,10 @@ enum intel_region_id;
>   * 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
> + * - sg_table embeds unsigned int for nents
> + *
> + * We can check for invalidly typed locals with typecheck(), see for example
> + * i915_gem_object_get_sg().
>   */
>  #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>  	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>  struct scatterlist *
>  __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>  			 struct i915_gem_object_page_iter *iter,
> -			 unsigned int n,
> -			 unsigned int *offset, bool dma);
> +			 pgoff_t  n,
> +			 unsigned int *offset);
> +
> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
> +})
>  
>  static inline struct scatterlist *
> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> -		       unsigned int n,
> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>  		       unsigned int *offset)
>  {
> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>  }
>  
> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_sg)(obj, n, offset); \
> +})
> +
>  static inline struct scatterlist *
> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
> -			   unsigned int n,
> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>  			   unsigned int *offset)
>  {
> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>  }
>  
> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
> +})
> +
>  struct page *
> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
> -			 unsigned int n);
> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_page(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_page)(obj, n); \
> +})
>  
>  struct page *
> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> -			       unsigned int n);
> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dirty_page)(obj, n); \
> +})
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> -				    unsigned long n,
> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>  				    unsigned int *len);
>  
> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
> +})
> +
>  dma_addr_t
> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> -				unsigned long n);
> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
> +
> +#define i915_gem_object_get_dma_address(obj, n) ({ \
> +	exactly_pgoff_t(n); \
> +	(i915_gem_object_get_dma_address)(obj, n); \
> +})
>  
>  void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>  				 struct sg_table *pages,
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> index 97c820eee115..1d1edcb3514b 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>  }
>  
>  struct scatterlist *
> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>  			 struct i915_gem_object_page_iter *iter,
> -			 unsigned int n,
> -			 unsigned int *offset,
> -			 bool dma)
> +			 pgoff_t n,
> +			 unsigned int *offset)
> +

Nitpick: no need to place the function name in parenthesis.

>  {
> -	struct scatterlist *sg;
> +	const bool dma = iter == &obj->mm.get_dma_page ||
> +			 iter == &obj->ttm.get_io_page;
>  	unsigned int idx, count;
> +	struct scatterlist *sg;
>  
>  	might_sleep();
>  	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>  }
>  
>  struct page *
> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above: why are you placing parenthesis at the function name here?
Just use:
	
	struct page *
	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)

>  {
>  	struct scatterlist *sg;
>  	unsigned int offset;
> @@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>  
>  /* Like i915_gem_object_get_page(), but mark the returned page dirty */
>  struct page *
> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> -			       unsigned int n)
> +(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above.

>  {
>  	struct page *page;
>  
> @@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>  }
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> -				    unsigned long n,
> -				    unsigned int *len)
> +(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
> +				      pgoff_t n, unsigned int *len)

Same as above.

>  {
>  	struct scatterlist *sg;
>  	unsigned int offset;
> @@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>  }
>  
>  dma_addr_t
> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> -				unsigned long n)
> +(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)

Same as above.

>  {
>  	return i915_gem_object_get_dma_address_len(obj, n, NULL);
>  }
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index 7e1f8b83077f..50a02d850139 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
>  	GEM_WARN_ON(bo->ttm);
>  
>  	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
> -	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
> +	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
>  
>  	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
>  }
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> index c6ad67b90e8a..a18a890e681f 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
> @@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
>  static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>  {
>  	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
> -	unsigned int n, m, need_flush;
> +	unsigned int need_flush;
> +	unsigned long n, m;
>  	int err;
>  
>  	i915_gem_object_lock(obj, NULL);
> @@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>  static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  			      unsigned int idx, unsigned int max)
>  {
> -	unsigned int n, m, needs_flush;
> +	unsigned int needs_flush;
> +	unsigned long n;
>  	int err;
>  
>  	i915_gem_object_lock(obj, NULL);
> @@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  		goto out_unlock;
>  
>  	for (n = 0; n < real_page_count(obj); n++) {
> -		u32 *map;
> +		u32 *map, m;
>  
>  		map = kmap_atomic(i915_gem_object_get_page(obj, n));
>  		if (needs_flush & CLFLUSH_BEFORE)
> @@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  
>  		for (m = 0; m < max; m++) {
>  			if (map[m] != m) {
> -				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
> +				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
>  				       __builtin_return_address(0), idx,
>  				       n, real_page_count(obj), m, max,
>  				       map[m], m);
> @@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>  
>  		for (; m < DW_PER_PAGE; m++) {
>  			if (map[m] != STACK_MAGIC) {
> -				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
> +				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
>  				       __builtin_return_address(0), idx, n, m,
>  				       map[m], STACK_MAGIC);
>  				err = -EINVAL;
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> index 3ced9948a331..86e435d42546 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
> @@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt_view view;
>  	struct i915_vma *vma;
> +	unsigned long offset;
>  	unsigned long page;
>  	u32 __iomem *io;
>  	struct page *p;
>  	unsigned int n;
> -	u64 offset;
>  	u32 *cpu;
>  	int err;
>  
> @@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>  	cpu = kmap(p) + offset_in_page(offset);
>  	drm_clflush_virt_range(cpu, sizeof(*cpu));
>  	if (*cpu != (u32)page) {
> -		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
> +		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>  		       page, n,
>  		       view.partial.offset,
>  		       view.partial.size,
> @@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>  	for_each_prime_number_from(page, 1, npages) {
>  		struct i915_ggtt_view view =
>  			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
> +		unsigned long offset;
>  		u32 __iomem *io;
>  		struct page *p;
>  		unsigned int n;
> -		u64 offset;
>  		u32 *cpu;
>  
>  		GEM_BUG_ON(view.partial.size > nreal);
> @@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>  		cpu = kmap(p) + offset_in_page(offset);
>  		drm_clflush_virt_range(cpu, sizeof(*cpu));
>  		if (*cpu != (u32)page) {
> -			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
> +			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>  			       page, n,
>  			       view.partial.offset,
>  			       view.partial.size,
> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> index fe0a890775e2..bf30763ee6bc 100644
> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
> @@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
>  
>  static int igt_gem_huge(void *arg)
>  {
> -	const unsigned int nreal = 509; /* just to be awkward */
> +	const unsigned long nreal = 509; /* just to be awkward */
>  	struct drm_i915_private *i915 = arg;
>  	struct drm_i915_gem_object *obj;
> -	unsigned int n;
> +	unsigned long n;
>  	int err;
>  
>  	/* Basic sanitycheck of our huge fake object allocation */
> @@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
>  
>  	err = i915_gem_object_pin_pages_unlocked(obj);
>  	if (err) {
> -		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
> +		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
>  		       nreal, obj->base.size / PAGE_SIZE, err);
>  		goto out;
>  	}
> @@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
>  	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
>  		if (i915_gem_object_get_page(obj, n) !=
>  		    i915_gem_object_get_page(obj, n % nreal)) {
> -			pr_err("Page lookup mismatch at index %u [%u]\n",
> +			pr_err("Page lookup mismatch at index %lu [%lu]\n",
>  			       n, n % nreal);
>  			err = -EINVAL;
>  			goto out_unpin;
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 702e5b89be22..dba58a3c3238 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
>  		     struct drm_i915_gem_pread *args)
>  {
>  	unsigned int needs_clflush;
> -	unsigned int idx, offset;
>  	char __user *user_data;
> +	unsigned long offset;
> +	pgoff_t idx;
>  	u64 remain;
>  	int ret;
>  
> @@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
>  {
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
> +	unsigned long remain, offset;
>  	intel_wakeref_t wakeref;
>  	struct drm_mm_node node;
>  	void __user *user_data;
>  	struct i915_vma *vma;
> -	u64 remain, offset;
>  	int ret = 0;
>  
> +	if (overflows_type(args->size, remain) ||
> +	    overflows_type(args->offset, offset))
> +		return -EINVAL;
> +
>  	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>  
>  	vma = i915_gem_gtt_prepare(obj, &node, false);
> @@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>  	struct intel_runtime_pm *rpm = &i915->runtime_pm;
> +	unsigned long remain, offset;
>  	intel_wakeref_t wakeref;
>  	struct drm_mm_node node;
>  	struct i915_vma *vma;
> -	u64 remain, offset;
>  	void __user *user_data;
>  	int ret = 0;
>  
> +	if (overflows_type(args->size, remain) ||
> +	    overflows_type(args->offset, offset))
> +		return -EINVAL;
> +
>  	if (i915_gem_object_has_struct_page(obj)) {
>  		/*
>  		 * Avoid waking the device up if we can fallback, as
> @@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
>  {
>  	unsigned int partial_cacheline_write;
>  	unsigned int needs_clflush;
> -	unsigned int offset, idx;
>  	void __user *user_data;
> +	unsigned long offset;
> +	pgoff_t idx;
>  	u64 remain;
>  	int ret;
>  
> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> index ef3b04c7e153..28443c77b45a 100644
> --- a/drivers/gpu/drm/i915/i915_vma.c
> +++ b/drivers/gpu/drm/i915/i915_vma.c
> @@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
>  	     struct sg_table *st, struct scatterlist *sg)
>  {
>  	unsigned int column, row;
> -	unsigned int src_idx;
> +	pgoff_t src_idx;
>  
>  	for (column = 0; column < width; column++) {
>  		unsigned int left;
> @@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
>  
>  static struct scatterlist *
>  remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
> -			      unsigned int offset, unsigned int alignment_pad,
> +			      unsigned long offset, unsigned int alignment_pad,
>  			      unsigned int width, unsigned int height,
>  			      unsigned int src_stride, unsigned int dst_stride,
>  			      struct sg_table *st, struct scatterlist *sg,
> @@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>  
>  static struct scatterlist *
>  remap_contiguous_pages(struct drm_i915_gem_object *obj,
> -		       unsigned int obj_offset,
> +		       pgoff_t obj_offset,
>  		       unsigned int count,
>  		       struct sg_table *st, struct scatterlist *sg)
>  {
> @@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
>  
>  static struct scatterlist *
>  remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
> -			       unsigned int obj_offset, unsigned int alignment_pad,
> +			       pgoff_t obj_offset, unsigned int alignment_pad,
>  			       unsigned int size,
>  			       struct sg_table *st, struct scatterlist *sg,
>  			       unsigned int *gtt_offset)

Once fixed the above nitpicks, feel free to add:

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 4/7] drm/i915: Check for integer truncation on the configuration of ttm place
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:44     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:44 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:52 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> There is an impedance mismatch between the first/last valid page
> frame number of ttm place in unsigned and our memory/page accounting in
> unsigned long.
> As the object size is under the control of userspace, we have to be prudent
> and catch the conversion errors.
> To catch the implicit truncation as we switch from unsigned long to
> unsigned, we use overflows_type check and report E2BIG or overflow_type
> prior to the operation.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 12 +++++++++---
>  drivers/gpu/drm/i915/intel_region_ttm.c | 16 +++++++++++++---
>  2 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index cdcb3ee0c433..d579524663b3 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -137,19 +137,25 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
>  	if (mr->type == INTEL_MEMORY_SYSTEM)
>  		return;
>  
> +#define SAFE_CONVERSION(ptr, value) ({ \
> +	if (!safe_conversion(ptr, value)) { \
> +		GEM_BUG_ON(overflows_type(value, *ptr)); \
> +	} \
> +})
>  	if (flags & I915_BO_ALLOC_CONTIGUOUS)
>  		place->flags |= TTM_PL_FLAG_CONTIGUOUS;
>  	if (offset != I915_BO_INVALID_OFFSET) {
> -		place->fpfn = offset >> PAGE_SHIFT;
> -		place->lpfn = place->fpfn + (size >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place->fpfn, offset >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place->lpfn, place->fpfn + (size >> PAGE_SHIFT));
>  	} else if (mr->io_size && mr->io_size < mr->total) {
>  		if (flags & I915_BO_ALLOC_GPU_ONLY) {
>  			place->flags |= TTM_PL_FLAG_TOPDOWN;
>  		} else {
>  			place->fpfn = 0;
> -			place->lpfn = mr->io_size >> PAGE_SHIFT;
> +			SAFE_CONVERSION(&place->lpfn, mr->io_size >> PAGE_SHIFT);
>  		}
>  	}

> +#undef SAFE_CONVERSION
Why?

>  }
>  
>  static void
> diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
> index 62ff77445b01..8fcb8654b978 100644
> --- a/drivers/gpu/drm/i915/intel_region_ttm.c
> +++ b/drivers/gpu/drm/i915/intel_region_ttm.c
> @@ -202,24 +202,34 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
>  	struct ttm_resource *res;
>  	int ret;
>  
> +#define SAFE_CONVERSION(ptr, value) ({ \
> +	if (!safe_conversion(ptr, value)) { \
> +		GEM_BUG_ON(overflows_type(value, *ptr)); \
> +		ret = -E2BIG; \
> +		goto out; \
> +	} \
> +})

It is a bad practice to change execution inside a macro.
See "12) Macros, Enums and RTL" at Documentation/process/coding-style.rst.

>  	if (flags & I915_BO_ALLOC_CONTIGUOUS)
>  		place.flags |= TTM_PL_FLAG_CONTIGUOUS;
>  	if (offset != I915_BO_INVALID_OFFSET) {
> -		place.fpfn = offset >> PAGE_SHIFT;
> -		place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place.fpfn, offset >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place.lpfn, place.fpfn + (size >> PAGE_SHIFT));
>  	} else if (mem->io_size && mem->io_size < mem->total) {
>  		if (flags & I915_BO_ALLOC_GPU_ONLY) {
>  			place.flags |= TTM_PL_FLAG_TOPDOWN;
>  		} else {
>  			place.fpfn = 0;
> -			place.lpfn = mem->io_size >> PAGE_SHIFT;
> +			SAFE_CONVERSION(&place.lpfn, mem->io_size >> PAGE_SHIFT);
>  		}
>  	}

> +#undef SAFE_CONVERSION
Why?

>  
>  	mock_bo.base.size = size;
>  	mock_bo.bdev = &mem->i915->bdev;
>  
>  	ret = man->func->alloc(man, &mock_bo, &place, &res);
> +
> +out:
>  	if (ret == -ENOSPC)
>  		ret = -ENXIO;
>  	if (!ret)

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 4/7] drm/i915: Check for integer truncation on the configuration of ttm place
@ 2022-07-05 14:44     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:44 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:52 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> There is an impedance mismatch between the first/last valid page
> frame number of ttm place in unsigned and our memory/page accounting in
> unsigned long.
> As the object size is under the control of userspace, we have to be prudent
> and catch the conversion errors.
> To catch the implicit truncation as we switch from unsigned long to
> unsigned, we use overflows_type check and report E2BIG or overflow_type
> prior to the operation.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 12 +++++++++---
>  drivers/gpu/drm/i915/intel_region_ttm.c | 16 +++++++++++++---
>  2 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index cdcb3ee0c433..d579524663b3 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -137,19 +137,25 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
>  	if (mr->type == INTEL_MEMORY_SYSTEM)
>  		return;
>  
> +#define SAFE_CONVERSION(ptr, value) ({ \
> +	if (!safe_conversion(ptr, value)) { \
> +		GEM_BUG_ON(overflows_type(value, *ptr)); \
> +	} \
> +})
>  	if (flags & I915_BO_ALLOC_CONTIGUOUS)
>  		place->flags |= TTM_PL_FLAG_CONTIGUOUS;
>  	if (offset != I915_BO_INVALID_OFFSET) {
> -		place->fpfn = offset >> PAGE_SHIFT;
> -		place->lpfn = place->fpfn + (size >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place->fpfn, offset >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place->lpfn, place->fpfn + (size >> PAGE_SHIFT));
>  	} else if (mr->io_size && mr->io_size < mr->total) {
>  		if (flags & I915_BO_ALLOC_GPU_ONLY) {
>  			place->flags |= TTM_PL_FLAG_TOPDOWN;
>  		} else {
>  			place->fpfn = 0;
> -			place->lpfn = mr->io_size >> PAGE_SHIFT;
> +			SAFE_CONVERSION(&place->lpfn, mr->io_size >> PAGE_SHIFT);
>  		}
>  	}

> +#undef SAFE_CONVERSION
Why?

>  }
>  
>  static void
> diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
> index 62ff77445b01..8fcb8654b978 100644
> --- a/drivers/gpu/drm/i915/intel_region_ttm.c
> +++ b/drivers/gpu/drm/i915/intel_region_ttm.c
> @@ -202,24 +202,34 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
>  	struct ttm_resource *res;
>  	int ret;
>  
> +#define SAFE_CONVERSION(ptr, value) ({ \
> +	if (!safe_conversion(ptr, value)) { \
> +		GEM_BUG_ON(overflows_type(value, *ptr)); \
> +		ret = -E2BIG; \
> +		goto out; \
> +	} \
> +})

It is a bad practice to change execution inside a macro.
See "12) Macros, Enums and RTL" at Documentation/process/coding-style.rst.

>  	if (flags & I915_BO_ALLOC_CONTIGUOUS)
>  		place.flags |= TTM_PL_FLAG_CONTIGUOUS;
>  	if (offset != I915_BO_INVALID_OFFSET) {
> -		place.fpfn = offset >> PAGE_SHIFT;
> -		place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place.fpfn, offset >> PAGE_SHIFT);
> +		SAFE_CONVERSION(&place.lpfn, place.fpfn + (size >> PAGE_SHIFT));
>  	} else if (mem->io_size && mem->io_size < mem->total) {
>  		if (flags & I915_BO_ALLOC_GPU_ONLY) {
>  			place.flags |= TTM_PL_FLAG_TOPDOWN;
>  		} else {
>  			place.fpfn = 0;
> -			place.lpfn = mem->io_size >> PAGE_SHIFT;
> +			SAFE_CONVERSION(&place.lpfn, mem->io_size >> PAGE_SHIFT);
>  		}
>  	}

> +#undef SAFE_CONVERSION
Why?

>  
>  	mock_bo.base.size = size;
>  	mock_bo.bdev = &mem->i915->bdev;
>  
>  	ret = man->func->alloc(man, &mock_bo, &place, &res);
> +
> +out:
>  	if (ret == -ENOSPC)
>  		ret = -ENXIO;
>  	if (!ret)

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 3/7] drm/i915: Check for integer truncation on scatterlist creation
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:48     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:48 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:51 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> There is an impedance mismatch between the scatterlist API using unsigned
> int and our memory/page accounting in unsigned long. That is we may try
> to create a scatterlist for a large object that overflows returning a
> small table into which we try to fit very many pages. As the object size
> is under control of userspace, we have to be prudent and catch the
> conversion errors.
> 
> To catch the implicit truncation as we switch from unsigned long into the
> scatterlist's unsigned int, we use overflows_type check and report
> E2BIG prior to the operation. This is already used in our create ioctls to
> indicate if the uABI request is simply too large for the backing store.
> Failing that type check, we have a second check at sg_alloc_table time
> to make sure the values we are passing into the scatterlist API are not
> truncated.
> 
> It uses pgoff_t for locals that are dealing with page indices, in this
> case, the page count is the limit of the page index.
> And it uses safe_conversion() macro which performs a type conversion (cast)
> of an integer value into a new variable, checking that the destination is
> large enough to hold the source value.
> 
> v2: Move added i915_utils's macro into drm_util header (Jani N)
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Brian Welty <brian.welty@intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_internal.c | 6 ++++--
>  drivers/gpu/drm/i915/gem/i915_gem_object.h   | 3 ---
>  drivers/gpu/drm/i915/gem/i915_gem_phys.c     | 4 ++++
>  drivers/gpu/drm/i915/gem/i915_gem_shmem.c    | 5 ++++-
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c      | 4 ++++
>  drivers/gpu/drm/i915/gem/i915_gem_userptr.c  | 5 ++++-
>  drivers/gpu/drm/i915/gvt/dmabuf.c            | 9 +++++----
>  drivers/gpu/drm/i915/i915_scatterlist.h      | 8 ++++++++
>  8 files changed, 33 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> index c698f95af15f..ff2e6e780631 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> @@ -37,10 +37,13 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
>  	struct sg_table *st;
>  	struct scatterlist *sg;
>  	unsigned int sg_page_sizes;
> -	unsigned int npages;
> +	pgoff_t npages; /* restricted by sg_alloc_table */
>  	int max_order;
>  	gfp_t gfp;
>  
> +	if (!safe_conversion(&npages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	max_order = MAX_ORDER;
>  #ifdef CONFIG_SWIOTLB
>  	if (is_swiotlb_active(obj->base.dev->dev)) {
> @@ -67,7 +70,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
>  	if (!st)
>  		return -ENOMEM;
>  
> -	npages = obj->base.size / PAGE_SIZE;
>  	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
>  		kfree(st);
>  		return -ENOMEM;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index a60c6f4517d5..31bb09dccf2f 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -26,9 +26,6 @@ enum intel_region_id;
>   * 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 nents
> - *
>   * We can check for invalidly typed locals with typecheck(), see for example
>   * i915_gem_object_get_sg().
>   */
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> index 0d0e46dae559..88ba7266a3a5 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> @@ -28,6 +28,10 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
>  	void *dst;
>  	int i;
>  
> +	/* Contiguous chunk, with a single scatterlist element */
> +	if (overflows_type(obj->base.size, sg->length))
> +		return -E2BIG;
> +
>  	if (GEM_WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
>  		return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> index 4eed3dd90ba8..604e8829e8ea 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> @@ -193,13 +193,16 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct intel_memory_region *mem = obj->mm.region;
>  	struct address_space *mapping = obj->base.filp->f_mapping;
> -	const unsigned long page_count = obj->base.size / PAGE_SIZE;
>  	unsigned int max_segment = i915_sg_segment_size();
>  	struct sg_table *st;
>  	struct sgt_iter sgt_iter;
> +	pgoff_t page_count;
>  	struct page *page;
>  	int ret;
>  
> +	if (!safe_conversion(&page_count, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	/*
>  	 * Assert that the object is not currently in any GPU domain. As it
>  	 * wasn't in the GTT, there shouldn't be any way it could have been in
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index 50a02d850139..cdcb3ee0c433 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -815,6 +815,10 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  {
>  	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>  	struct ttm_placement placement;
> +	pgoff_t num_pages;
> +
> +	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
>  
>  	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>  
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index 094f06b4ce33..25785c3a0083 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -128,13 +128,16 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
>  
>  static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
>  {
> -	const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
>  	unsigned int max_segment = i915_sg_segment_size();
>  	struct sg_table *st;
>  	unsigned int sg_page_sizes;
>  	struct page **pvec;
> +	pgoff_t num_pages; /* limited by sg_alloc_table_from_pages_segment */
>  	int ret;
>  
> +	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	st = kmalloc(sizeof(*st), GFP_KERNEL);
>  	if (!st)
>  		return -ENOMEM;
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> index 01e54b45c5c1..795270cb4ec2 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -42,8 +42,7 @@
>  
>  #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
>  
> -static int vgpu_gem_get_pages(
> -		struct drm_i915_gem_object *obj)
> +static int vgpu_gem_get_pages(struct drm_i915_gem_object *obj)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
>  	struct intel_vgpu *vgpu;
> @@ -52,7 +51,10 @@ static int vgpu_gem_get_pages(
>  	int i, j, ret;
>  	gen8_pte_t __iomem *gtt_entries;
>  	struct intel_vgpu_fb_info *fb_info;
> -	u32 page_num;
> +	pgoff_t page_num;
> +
> +	if (!safe_conversion(&page_num, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
>  
>  	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
>  	if (drm_WARN_ON(&dev_priv->drm, !fb_info))
> @@ -66,7 +68,6 @@ static int vgpu_gem_get_pages(
>  	if (unlikely(!st))
>  		return -ENOMEM;
>  
> -	page_num = obj->base.size >> PAGE_SHIFT;
>  	ret = sg_alloc_table(st, page_num, GFP_KERNEL);
>  	if (ret) {
>  		kfree(st);
> diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
> index 12c6a1684081..c4d4d3c84cff 100644
> --- a/drivers/gpu/drm/i915/i915_scatterlist.h
> +++ b/drivers/gpu/drm/i915/i915_scatterlist.h
> @@ -218,4 +218,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
>  struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
>  						     u64 region_start);
>  
> +/* Wrap scatterlist.h to sanity check for integer truncation */
> +typedef unsigned int __sg_size_t; /* see linux/scatterlist.h */
> +#define sg_alloc_table(sgt, nents, gfp) \
> +	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)
> +
> +#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
> +	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)
> +
>  #endif

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 3/7] drm/i915: Check for integer truncation on scatterlist creation
@ 2022-07-05 14:48     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:48 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:51 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> There is an impedance mismatch between the scatterlist API using unsigned
> int and our memory/page accounting in unsigned long. That is we may try
> to create a scatterlist for a large object that overflows returning a
> small table into which we try to fit very many pages. As the object size
> is under control of userspace, we have to be prudent and catch the
> conversion errors.
> 
> To catch the implicit truncation as we switch from unsigned long into the
> scatterlist's unsigned int, we use overflows_type check and report
> E2BIG prior to the operation. This is already used in our create ioctls to
> indicate if the uABI request is simply too large for the backing store.
> Failing that type check, we have a second check at sg_alloc_table time
> to make sure the values we are passing into the scatterlist API are not
> truncated.
> 
> It uses pgoff_t for locals that are dealing with page indices, in this
> case, the page count is the limit of the page index.
> And it uses safe_conversion() macro which performs a type conversion (cast)
> of an integer value into a new variable, checking that the destination is
> large enough to hold the source value.
> 
> v2: Move added i915_utils's macro into drm_util header (Jani N)
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Brian Welty <brian.welty@intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_internal.c | 6 ++++--
>  drivers/gpu/drm/i915/gem/i915_gem_object.h   | 3 ---
>  drivers/gpu/drm/i915/gem/i915_gem_phys.c     | 4 ++++
>  drivers/gpu/drm/i915/gem/i915_gem_shmem.c    | 5 ++++-
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c      | 4 ++++
>  drivers/gpu/drm/i915/gem/i915_gem_userptr.c  | 5 ++++-
>  drivers/gpu/drm/i915/gvt/dmabuf.c            | 9 +++++----
>  drivers/gpu/drm/i915/i915_scatterlist.h      | 8 ++++++++
>  8 files changed, 33 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> index c698f95af15f..ff2e6e780631 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
> @@ -37,10 +37,13 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
>  	struct sg_table *st;
>  	struct scatterlist *sg;
>  	unsigned int sg_page_sizes;
> -	unsigned int npages;
> +	pgoff_t npages; /* restricted by sg_alloc_table */
>  	int max_order;
>  	gfp_t gfp;
>  
> +	if (!safe_conversion(&npages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	max_order = MAX_ORDER;
>  #ifdef CONFIG_SWIOTLB
>  	if (is_swiotlb_active(obj->base.dev->dev)) {
> @@ -67,7 +70,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
>  	if (!st)
>  		return -ENOMEM;
>  
> -	npages = obj->base.size / PAGE_SIZE;
>  	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
>  		kfree(st);
>  		return -ENOMEM;
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index a60c6f4517d5..31bb09dccf2f 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -26,9 +26,6 @@ enum intel_region_id;
>   * 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 nents
> - *
>   * We can check for invalidly typed locals with typecheck(), see for example
>   * i915_gem_object_get_sg().
>   */
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> index 0d0e46dae559..88ba7266a3a5 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
> @@ -28,6 +28,10 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
>  	void *dst;
>  	int i;
>  
> +	/* Contiguous chunk, with a single scatterlist element */
> +	if (overflows_type(obj->base.size, sg->length))
> +		return -E2BIG;
> +
>  	if (GEM_WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
>  		return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> index 4eed3dd90ba8..604e8829e8ea 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> @@ -193,13 +193,16 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
>  	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>  	struct intel_memory_region *mem = obj->mm.region;
>  	struct address_space *mapping = obj->base.filp->f_mapping;
> -	const unsigned long page_count = obj->base.size / PAGE_SIZE;
>  	unsigned int max_segment = i915_sg_segment_size();
>  	struct sg_table *st;
>  	struct sgt_iter sgt_iter;
> +	pgoff_t page_count;
>  	struct page *page;
>  	int ret;
>  
> +	if (!safe_conversion(&page_count, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	/*
>  	 * Assert that the object is not currently in any GPU domain. As it
>  	 * wasn't in the GTT, there shouldn't be any way it could have been in
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index 50a02d850139..cdcb3ee0c433 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -815,6 +815,10 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
>  {
>  	struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
>  	struct ttm_placement placement;
> +	pgoff_t num_pages;
> +
> +	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
>  
>  	GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
>  
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index 094f06b4ce33..25785c3a0083 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -128,13 +128,16 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
>  
>  static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
>  {
> -	const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
>  	unsigned int max_segment = i915_sg_segment_size();
>  	struct sg_table *st;
>  	unsigned int sg_page_sizes;
>  	struct page **pvec;
> +	pgoff_t num_pages; /* limited by sg_alloc_table_from_pages_segment */
>  	int ret;
>  
> +	if (!safe_conversion(&num_pages, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
> +
>  	st = kmalloc(sizeof(*st), GFP_KERNEL);
>  	if (!st)
>  		return -ENOMEM;
> diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
> index 01e54b45c5c1..795270cb4ec2 100644
> --- a/drivers/gpu/drm/i915/gvt/dmabuf.c
> +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
> @@ -42,8 +42,7 @@
>  
>  #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
>  
> -static int vgpu_gem_get_pages(
> -		struct drm_i915_gem_object *obj)
> +static int vgpu_gem_get_pages(struct drm_i915_gem_object *obj)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
>  	struct intel_vgpu *vgpu;
> @@ -52,7 +51,10 @@ static int vgpu_gem_get_pages(
>  	int i, j, ret;
>  	gen8_pte_t __iomem *gtt_entries;
>  	struct intel_vgpu_fb_info *fb_info;
> -	u32 page_num;
> +	pgoff_t page_num;
> +
> +	if (!safe_conversion(&page_num, obj->base.size >> PAGE_SHIFT))
> +		return -E2BIG;
>  
>  	fb_info = (struct intel_vgpu_fb_info *)obj->gvt_info;
>  	if (drm_WARN_ON(&dev_priv->drm, !fb_info))
> @@ -66,7 +68,6 @@ static int vgpu_gem_get_pages(
>  	if (unlikely(!st))
>  		return -ENOMEM;
>  
> -	page_num = obj->base.size >> PAGE_SHIFT;
>  	ret = sg_alloc_table(st, page_num, GFP_KERNEL);
>  	if (ret) {
>  		kfree(st);
> diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
> index 12c6a1684081..c4d4d3c84cff 100644
> --- a/drivers/gpu/drm/i915/i915_scatterlist.h
> +++ b/drivers/gpu/drm/i915/i915_scatterlist.h
> @@ -218,4 +218,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node,
>  struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
>  						     u64 region_start);
>  
> +/* Wrap scatterlist.h to sanity check for integer truncation */
> +typedef unsigned int __sg_size_t; /* see linux/scatterlist.h */
> +#define sg_alloc_table(sgt, nents, gfp) \
> +	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)
> +
> +#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
> +	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)
> +
>  #endif

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 5/7] drm/i915: Check if the size is too big while creating shmem file
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:50     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:50 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:53 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> The __shmem_file_setup() function returns -EINVAL if size is greater than
> MAX_LFS_FILESIZE. To handle the same error as other code that returns
> -E2BIG when the size is too large, it add a code that returns -E2BIG when
> the size is larger than the size that can be handled.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> index 604e8829e8ea..8495e87432f6 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> @@ -541,6 +541,15 @@ static int __create_shmem(struct drm_i915_private *i915,
>  
>  	drm_gem_private_object_init(&i915->drm, obj, size);
>  
> +	/* XXX: The __shmem_file_setup() function returns -EINVAL if size is
> +	 * greater than MAX_LFS_FILESIZE.
> +	 * To handle the same error as other code that returns -E2BIG when
> +	 * the size is too large, we add a code that returns -E2BIG when the
> +	 * size is larger than the size that can be handled.
> +	 */
> +	if (size > MAX_LFS_FILESIZE)
> +		return -E2BIG;
> +
>  	if (i915->mm.gemfs)
>  		filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
>  						 flags);
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 5/7] drm/i915: Check if the size is too big while creating shmem file
@ 2022-07-05 14:50     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:50 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:53 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> The __shmem_file_setup() function returns -EINVAL if size is greater than
> MAX_LFS_FILESIZE. To handle the same error as other code that returns
> -E2BIG when the size is too large, it add a code that returns -E2BIG when
> the size is larger than the size that can be handled.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> index 604e8829e8ea..8495e87432f6 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> @@ -541,6 +541,15 @@ static int __create_shmem(struct drm_i915_private *i915,
>  
>  	drm_gem_private_object_init(&i915->drm, obj, size);
>  
> +	/* XXX: The __shmem_file_setup() function returns -EINVAL if size is
> +	 * greater than MAX_LFS_FILESIZE.
> +	 * To handle the same error as other code that returns -E2BIG when
> +	 * the size is too large, we add a code that returns -E2BIG when the
> +	 * size is larger than the size that can be handled.
> +	 */
> +	if (size > MAX_LFS_FILESIZE)
> +		return -E2BIG;
> +
>  	if (i915->mm.gemfs)
>  		filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
>  						 flags);
 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 6/7] drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:50     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:50 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:54 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> The ttm_bo_init_reserved() functions returns -ENOSPC if the size is too big
> to add vma. The direct function that returns -ENOSPC is drm_mm_insert_node_in_range().
> To handle the same error as other code returning -E2BIG when the size is
> too large, it converts return value to -E2BIG.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index d579524663b3..271f64b7e4f1 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -1249,6 +1249,17 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
>  				   bo_type, &i915_sys_placement,
>  				   page_size >> PAGE_SHIFT,
>  				   &ctx, NULL, NULL, i915_ttm_bo_destroy);
> +
> +	/*
> +	 * XXX: The ttm_bo_init_reserved() functions returns -ENOSPC if the size
> +	 * is too big to add vma. The direct function that returns -ENOSPC is
> +	 * drm_mm_insert_node_in_range(). To handle the same error as other code
> +	 * that returns -E2BIG when the size is too large, it converts -ENOSPC to
> +	 * -E2BIG.
> +	 */
> +	if (size >> PAGE_SHIFT > INT_MAX && ret == -ENOSPC)
> +		ret = -E2BIG;
> +
>  	if (ret)
>  		return i915_ttm_err_to_gem(ret);
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 6/7] drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
@ 2022-07-05 14:50     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:50 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:54 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> The ttm_bo_init_reserved() functions returns -ENOSPC if the size is too big
> to add vma. The direct function that returns -ENOSPC is drm_mm_insert_node_in_range().
> To handle the same error as other code returning -E2BIG when the size is
> too large, it converts return value to -E2BIG.
> 
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> index d579524663b3..271f64b7e4f1 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
> @@ -1249,6 +1249,17 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
>  				   bo_type, &i915_sys_placement,
>  				   page_size >> PAGE_SHIFT,
>  				   &ctx, NULL, NULL, i915_ttm_bo_destroy);
> +
> +	/*
> +	 * XXX: The ttm_bo_init_reserved() functions returns -ENOSPC if the size
> +	 * is too big to add vma. The direct function that returns -ENOSPC is
> +	 * drm_mm_insert_node_in_range(). To handle the same error as other code
> +	 * that returns -E2BIG when the size is too large, it converts -ENOSPC to
> +	 * -E2BIG.
> +	 */
> +	if (size >> PAGE_SHIFT > INT_MAX && ret == -ENOSPC)
> +		ret = -E2BIG;
> +
>  	if (ret)
>  		return i915_ttm_err_to_gem(ret);
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 7/7] drm/i915: Remove truncation warning for large objects
  2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-05 14:51     ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:51 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:55 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> Having addressed the issues surrounding incorrect types for local
> variables and potential integer truncation in using the scatterlist API,
> we have closed all the loop holes we had previously identified with
> dangerously large object creation. As such, we can eliminate the warning
> put in place to remind us to complete the review.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Brian Welty <brian.welty@intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Testcase: igt@gem_create@create-massive
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.h | 15 ---------------
>  1 file changed, 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index 31bb09dccf2f..4d614e4c1c4e 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -20,25 +20,10 @@
>  
>  enum intel_region_id;
>  
> -/*
> - * 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!
> - *
> - * We can check for invalidly typed locals with typecheck(), see for example
> - * i915_gem_object_get_sg().
> - */
> -#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 (GEM_CHECK_SIZE_OVERFLOW(size))
> -		return true;
> -
>  	if (overflows_type(size, obj->base.size))
>  		return true;
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 7/7] drm/i915: Remove truncation warning for large objects
@ 2022-07-05 14:51     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-05 14:51 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Tue,  5 Jul 2022 15:24:55 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> From: Chris Wilson <chris@chris-wilson.co.uk>
> 
> Having addressed the issues surrounding incorrect types for local
> variables and potential integer truncation in using the scatterlist API,
> we have closed all the loop holes we had previously identified with
> dangerously large object creation. As such, we can eliminate the warning
> put in place to remind us to complete the review.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Brian Welty <brian.welty@intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Testcase: igt@gem_create@create-massive
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4991
> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>

Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>

> ---
>  drivers/gpu/drm/i915/gem/i915_gem_object.h | 15 ---------------
>  1 file changed, 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> index 31bb09dccf2f..4d614e4c1c4e 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> @@ -20,25 +20,10 @@
>  
>  enum intel_region_id;
>  
> -/*
> - * 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!
> - *
> - * We can check for invalidly typed locals with typecheck(), see for example
> - * i915_gem_object_get_sg().
> - */
> -#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 (GEM_CHECK_SIZE_OVERFLOW(size))
> -		return true;
> -
>  	if (overflows_type(size, obj->base.size))
>  		return true;
>  

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
                   ` (7 preceding siblings ...)
  (?)
@ 2022-07-05 14:54 ` Patchwork
  -1 siblings, 0 replies; 45+ messages in thread
From: Patchwork @ 2022-07-05 14:54 UTC (permalink / raw)
  To: Gwan-gyeong Mun; +Cc: intel-gfx

== Series Details ==

Series: Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
URL   : https://patchwork.freedesktop.org/series/104704/
State : warning

== Summary ==

Error: dim checkpatch failed
a9f2e87eee8d drm: Move and add a few utility macros into drm util header
6d3ba3e26e48 drm/i915/gem: Typecheck page lookups
-:89: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#89: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:374:
+#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(__i915_gem_object_get_sg)(obj, it, n, offset); \
+})

-:104: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#104: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:386:
+#define i915_gem_object_get_sg(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg)(obj, n, offset); \
+})

-:119: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#119: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:398:
+#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_sg_dma)(obj, n, offset); \
+})

-:129: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#129: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:406:
+#define i915_gem_object_get_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_page)(obj, n); \
+})

-:139: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#139: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:414:
+#define i915_gem_object_get_dirty_page(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dirty_page)(obj, n); \
+})

-:150: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#150: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:423:
+#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address_len)(obj, n, len); \
+})

-:160: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'n' - possible side-effects?
#160: FILE: drivers/gpu/drm/i915/gem/i915_gem_object.h:431:
+#define i915_gem_object_get_dma_address(obj, n) ({ \
+	exactly_pgoff_t(n); \
+	(i915_gem_object_get_dma_address)(obj, n); \
+})

total: 0 errors, 0 warnings, 7 checks, 391 lines checked
26cca639bed5 drm/i915: Check for integer truncation on scatterlist creation
-:199: WARNING:NEW_TYPEDEFS: do not add new typedefs
#199: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:222:
+typedef unsigned int __sg_size_t; /* see linux/scatterlist.h */

-:200: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#200: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:223:
+#define sg_alloc_table(sgt, nents, gfp) \
+	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)

-:200: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'nents' - possible side-effects?
#200: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:223:
+#define sg_alloc_table(sgt, nents, gfp) \
+	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)

-:201: WARNING:LONG_LINE: line length of 102 exceeds 100 columns
#201: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:224:
+	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, (__sg_size_t)(nents), gfp)

-:203: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#203: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:226:
+#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
+	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)

-:203: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'npages' - possible side-effects?
#203: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:226:
+#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, size, max_segment, gfp) \
+	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)

-:204: WARNING:LONG_LINE: line length of 157 exceeds 100 columns
#204: FILE: drivers/gpu/drm/i915/i915_scatterlist.h:227:
+	overflows_type(npages, __sg_size_t) ? -E2BIG : (sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), offset, size, max_segment, gfp)

total: 2 errors, 3 warnings, 2 checks, 123 lines checked
97ac44a48866 drm/i915: Check for integer truncation on the configuration of ttm place
-:33: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'ptr' - possible side-effects?
#33: FILE: drivers/gpu/drm/i915/gem/i915_gem_ttm.c:140:
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+	} \
+})

-:33: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'value' - possible side-effects?
#33: FILE: drivers/gpu/drm/i915/gem/i915_gem_ttm.c:140:
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+	} \
+})

-:66: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'ptr' - possible side-effects?
#66: FILE: drivers/gpu/drm/i915/intel_region_ttm.c:205:
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+		ret = -E2BIG; \
+		goto out; \
+	} \
+})

-:66: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'value' - possible side-effects?
#66: FILE: drivers/gpu/drm/i915/intel_region_ttm.c:205:
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+		ret = -E2BIG; \
+		goto out; \
+	} \
+})

-:66: WARNING:MACRO_WITH_FLOW_CONTROL: Macros with flow control statements should be avoided
#66: FILE: drivers/gpu/drm/i915/intel_region_ttm.c:205:
+#define SAFE_CONVERSION(ptr, value) ({ \
+	if (!safe_conversion(ptr, value)) { \
+		GEM_BUG_ON(overflows_type(value, *ptr)); \
+		ret = -E2BIG; \
+		goto out; \
+	} \
+})

total: 0 errors, 1 warnings, 4 checks, 65 lines checked
312aff1f2799 drm/i915: Check if the size is too big while creating shmem file
af0e92722339 drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
-:11: WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#11: 
to add vma. The direct function that returns -ENOSPC is drm_mm_insert_node_in_range().

total: 0 errors, 1 warnings, 0 checks, 17 lines checked
9ed7d10f87ba drm/i915: Remove truncation warning for large objects



^ permalink raw reply	[flat|nested] 45+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
                   ` (8 preceding siblings ...)
  (?)
@ 2022-07-05 15:13 ` Patchwork
  -1 siblings, 0 replies; 45+ messages in thread
From: Patchwork @ 2022-07-05 15:13 UTC (permalink / raw)
  To: Gwan-gyeong Mun; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 7376 bytes --]

== Series Details ==

Series: Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
URL   : https://patchwork.freedesktop.org/series/104704/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11849 -> Patchwork_104704v3
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/index.html

Participating hosts (43 -> 35)
------------------------------

  Additional (2): fi-kbl-x1275 fi-bxt-dsi 
  Missing    (10): fi-bdw-5557u fi-tgl-u2 bat-dg1-5 bat-dg2-8 bat-dg2-9 fi-apl-guc bat-adlp-4 bat-adln-1 bat-jsl-3 bat-jsl-1 

Known issues
------------

  Here are the changes found in Patchwork_104704v3 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_huc_copy@huc-copy:
    - fi-bxt-dsi:         NOTRUN -> [SKIP][1] ([fdo#109271] / [i915#2190])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-bxt-dsi/igt@gem_huc_copy@huc-copy.html
    - fi-kbl-x1275:       NOTRUN -> [SKIP][2] ([fdo#109271] / [i915#2190])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-kbl-x1275/igt@gem_huc_copy@huc-copy.html

  * igt@gem_lmem_swapping@verify-random:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][3] ([fdo#109271] / [i915#4613]) +3 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-kbl-x1275/igt@gem_lmem_swapping@verify-random.html
    - fi-bxt-dsi:         NOTRUN -> [SKIP][4] ([fdo#109271] / [i915#4613]) +3 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-bxt-dsi/igt@gem_lmem_swapping@verify-random.html

  * igt@gem_tiled_blits@basic:
    - fi-bxt-dsi:         NOTRUN -> [SKIP][5] ([fdo#109271]) +12 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-bxt-dsi/igt@gem_tiled_blits@basic.html

  * igt@i915_selftest@live@gt_lrc:
    - fi-rkl-guc:         [PASS][6] -> [INCOMPLETE][7] ([i915#4983])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/fi-rkl-guc/igt@i915_selftest@live@gt_lrc.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-rkl-guc/igt@i915_selftest@live@gt_lrc.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [PASS][8] -> [INCOMPLETE][9] ([i915#4785])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@i915_suspend@basic-s3-without-i915:
    - fi-rkl-11600:       [PASS][10] -> [INCOMPLETE][11] ([i915#5982])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/fi-rkl-11600/igt@i915_suspend@basic-s3-without-i915.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-rkl-11600/igt@i915_suspend@basic-s3-without-i915.html

  * igt@kms_chamelium@common-hpd-after-suspend:
    - fi-snb-2600:        NOTRUN -> [SKIP][12] ([fdo#109271] / [fdo#111827])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-snb-2600/igt@kms_chamelium@common-hpd-after-suspend.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][13] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-kbl-x1275/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_chamelium@hdmi-edid-read:
    - fi-bxt-dsi:         NOTRUN -> [SKIP][14] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-bxt-dsi/igt@kms_chamelium@hdmi-edid-read.html

  * igt@prime_vgem@basic-userptr:
    - fi-kbl-x1275:       NOTRUN -> [SKIP][15] ([fdo#109271]) +11 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-kbl-x1275/igt@prime_vgem@basic-userptr.html

  * igt@runner@aborted:
    - fi-hsw-4770:        NOTRUN -> [FAIL][16] ([fdo#109271] / [i915#4312] / [i915#5594] / [i915#6246])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-hsw-4770/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-cfl-8109u:       [DMESG-FAIL][17] ([i915#5334]) -> [PASS][18]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/fi-cfl-8109u/igt@i915_selftest@live@gt_heartbeat.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-cfl-8109u/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@hangcheck:
    - fi-snb-2600:        [INCOMPLETE][19] ([i915#3921]) -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/fi-snb-2600/igt@i915_selftest@live@hangcheck.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/fi-snb-2600/igt@i915_selftest@live@hangcheck.html

  * igt@kms_busy@basic@flip:
    - {bat-adlp-6}:       [DMESG-WARN][21] ([i915#3576]) -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/bat-adlp-6/igt@kms_busy@basic@flip.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/bat-adlp-6/igt@kms_busy@basic@flip.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5334]: https://gitlab.freedesktop.org/drm/intel/issues/5334
  [i915#5594]: https://gitlab.freedesktop.org/drm/intel/issues/5594
  [i915#5982]: https://gitlab.freedesktop.org/drm/intel/issues/5982
  [i915#6246]: https://gitlab.freedesktop.org/drm/intel/issues/6246


Build changes
-------------

  * Linux: CI_DRM_11849 -> Patchwork_104704v3

  CI-20190529: 20190529
  CI_DRM_11849: 66197f3ca0b462799e265b002dc5cf8dcec1c62d @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6555: 1a3ffecd400b8f82c35745fa2e07992f6bdeede2 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_104704v3: 66197f3ca0b462799e265b002dc5cf8dcec1c62d @ git://anongit.freedesktop.org/gfx-ci/linux


### Linux commits

911cb519dbe2 drm/i915: Remove truncation warning for large objects
81100ce8b42a drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large
9424b3caef75 drm/i915: Check if the size is too big while creating shmem file
fd2a411180fd drm/i915: Check for integer truncation on the configuration of ttm place
3df0351edf5a drm/i915: Check for integer truncation on scatterlist creation
a180f4d31d1e drm/i915/gem: Typecheck page lookups
8575f0ebc7cc drm: Move and add a few utility macros into drm util header

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/index.html

[-- Attachment #2: Type: text/html, Size: 9266 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
  2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
                   ` (9 preceding siblings ...)
  (?)
@ 2022-07-05 18:44 ` Patchwork
  -1 siblings, 0 replies; 45+ messages in thread
From: Patchwork @ 2022-07-05 18:44 UTC (permalink / raw)
  To: Gwan-gyeong Mun; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 58499 bytes --]

== Series Details ==

Series: Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3)
URL   : https://patchwork.freedesktop.org/series/104704/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11849_full -> Patchwork_104704v3_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (12 -> 12)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_104704v3_full:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling:
    - {shard-rkl}:        NOTRUN -> [SKIP][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile-downscaling.html

  
Known issues
------------

  Here are the changes found in Patchwork_104704v3_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@preservation-s3@vecs0:
    - shard-kbl:          [PASS][2] -> [DMESG-WARN][3] ([i915#180]) +3 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@gem_ctx_isolation@preservation-s3@vecs0.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@gem_ctx_isolation@preservation-s3@vecs0.html

  * igt@gem_ctx_persistence@hostile:
    - shard-snb:          NOTRUN -> [SKIP][4] ([fdo#109271] / [i915#1099])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb6/igt@gem_ctx_persistence@hostile.html

  * igt@gem_eio@unwedge-stress:
    - shard-iclb:         [PASS][5] -> [TIMEOUT][6] ([i915#3070])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb6/igt@gem_eio@unwedge-stress.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb5/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_balancer@parallel-out-fence:
    - shard-iclb:         [PASS][7] -> [SKIP][8] ([i915#4525])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb1/igt@gem_exec_balancer@parallel-out-fence.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb6/igt@gem_exec_balancer@parallel-out-fence.html

  * igt@gem_exec_fair@basic-none-share@rcs0:
    - shard-tglb:         [PASS][9] -> [FAIL][10] ([i915#2842]) +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglb2/igt@gem_exec_fair@basic-none-share@rcs0.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@gem_exec_fair@basic-none-share@rcs0.html

  * igt@gem_exec_fair@basic-none@vcs1:
    - shard-iclb:         NOTRUN -> [FAIL][11] ([i915#2842])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@gem_exec_fair@basic-none@vcs1.html

  * igt@gem_exec_fair@basic-pace@vcs1:
    - shard-kbl:          [PASS][12] -> [FAIL][13] ([i915#2842])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@gem_exec_fair@basic-pace@vcs1.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@gem_exec_fair@basic-pace@vcs1.html

  * igt@gem_exec_whisper@basic-queues:
    - shard-snb:          NOTRUN -> [SKIP][14] ([fdo#109271]) +48 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb6/igt@gem_exec_whisper@basic-queues.html

  * igt@gem_lmem_swapping@basic:
    - shard-apl:          NOTRUN -> [SKIP][15] ([fdo#109271] / [i915#4613]) +1 similar issue
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@gem_lmem_swapping@basic.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - shard-kbl:          NOTRUN -> [SKIP][16] ([fdo#109271] / [i915#4613])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_lmem_swapping@verify-random-ccs:
    - shard-skl:          NOTRUN -> [SKIP][17] ([fdo#109271] / [i915#4613]) +2 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@gem_lmem_swapping@verify-random-ccs.html

  * igt@gem_pxp@display-protected-crc:
    - shard-tglb:         NOTRUN -> [SKIP][18] ([i915#4270])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@gem_pxp@display-protected-crc.html
    - shard-iclb:         NOTRUN -> [SKIP][19] ([i915#4270])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@gem_pxp@display-protected-crc.html

  * igt@gem_softpin@evict-single-offset:
    - shard-apl:          NOTRUN -> [FAIL][20] ([i915#4171])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@gem_softpin@evict-single-offset.html

  * igt@gem_userptr_blits@unsync-overlap:
    - shard-iclb:         NOTRUN -> [SKIP][21] ([i915#3297])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@gem_userptr_blits@unsync-overlap.html
    - shard-tglb:         NOTRUN -> [SKIP][22] ([i915#3297])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@gem_userptr_blits@unsync-overlap.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-skl:          [PASS][23] -> [INCOMPLETE][24] ([i915#4939] / [i915#5129])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl10/igt@gem_workarounds@suspend-resume-context.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl10/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-skl:          [PASS][25] -> [DMESG-WARN][26] ([i915#5566] / [i915#716])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl4/igt@gen9_exec_parse@allowed-single.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl6/igt@gen9_exec_parse@allowed-single.html

  * igt@gen9_exec_parse@secure-batches:
    - shard-iclb:         NOTRUN -> [SKIP][27] ([i915#2856])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@gen9_exec_parse@secure-batches.html
    - shard-tglb:         NOTRUN -> [SKIP][28] ([i915#2527] / [i915#2856])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@gen9_exec_parse@secure-batches.html

  * igt@i915_pm_rpm@dpms-lpsp:
    - shard-kbl:          NOTRUN -> [SKIP][29] ([fdo#109271]) +85 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@i915_pm_rpm@dpms-lpsp.html

  * igt@kms_big_fb@4-tiled-8bpp-rotate-180:
    - shard-tglb:         NOTRUN -> [SKIP][30] ([i915#5286])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_big_fb@4-tiled-8bpp-rotate-180.html
    - shard-iclb:         NOTRUN -> [SKIP][31] ([i915#5286])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_big_fb@4-tiled-8bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-32bpp-rotate-270:
    - shard-tglb:         NOTRUN -> [SKIP][32] ([fdo#111615]) +1 similar issue
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_big_fb@yf-tiled-32bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip:
    - shard-skl:          NOTRUN -> [FAIL][33] ([i915#3743]) +1 similar issue
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-async-flip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0:
    - shard-iclb:         NOTRUN -> [SKIP][34] ([fdo#110723])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0.html

  * igt@kms_ccs@pipe-a-crc-primary-basic-y_tiled_gen12_rc_ccs_cc:
    - shard-kbl:          NOTRUN -> [SKIP][35] ([fdo#109271] / [i915#3886])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@kms_ccs@pipe-a-crc-primary-basic-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-b-missing-ccs-buffer-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][36] ([fdo#109271] / [i915#3886]) +3 similar issues
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@kms_ccs@pipe-b-missing-ccs-buffer-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-c-crc-primary-basic-4_tiled_dg2_rc_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][37] ([i915#6095])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb7/igt@kms_ccs@pipe-c-crc-primary-basic-4_tiled_dg2_rc_ccs.html

  * igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs:
    - shard-iclb:         NOTRUN -> [SKIP][38] ([fdo#109278] / [i915#3886])
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html
    - shard-skl:          NOTRUN -> [SKIP][39] ([fdo#109271] / [i915#3886])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl3/igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html
    - shard-tglb:         NOTRUN -> [SKIP][40] ([i915#3689] / [i915#3886])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html
    - shard-glk:          NOTRUN -> [SKIP][41] ([fdo#109271] / [i915#3886])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk5/igt@kms_ccs@pipe-c-crc-primary-rotation-180-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-d-random-ccs-data-y_tiled_gen12_mc_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][42] ([i915#3689])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_ccs@pipe-d-random-ccs-data-y_tiled_gen12_mc_ccs.html

  * igt@kms_chamelium@hdmi-crc-multiple:
    - shard-skl:          NOTRUN -> [SKIP][43] ([fdo#109271] / [fdo#111827]) +7 similar issues
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl7/igt@kms_chamelium@hdmi-crc-multiple.html

  * igt@kms_chamelium@hdmi-hpd-storm:
    - shard-apl:          NOTRUN -> [SKIP][44] ([fdo#109271] / [fdo#111827]) +5 similar issues
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@kms_chamelium@hdmi-hpd-storm.html

  * igt@kms_color_chamelium@pipe-a-ctm-limited-range:
    - shard-tglb:         NOTRUN -> [SKIP][45] ([fdo#109284] / [fdo#111827])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_color_chamelium@pipe-a-ctm-limited-range.html
    - shard-glk:          NOTRUN -> [SKIP][46] ([fdo#109271] / [fdo#111827])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk5/igt@kms_color_chamelium@pipe-a-ctm-limited-range.html
    - shard-iclb:         NOTRUN -> [SKIP][47] ([fdo#109284] / [fdo#111827])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_color_chamelium@pipe-a-ctm-limited-range.html
    - shard-snb:          NOTRUN -> [SKIP][48] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb6/igt@kms_color_chamelium@pipe-a-ctm-limited-range.html

  * igt@kms_color_chamelium@pipe-c-ctm-blue-to-red:
    - shard-kbl:          NOTRUN -> [SKIP][49] ([fdo#109271] / [fdo#111827]) +5 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@kms_color_chamelium@pipe-c-ctm-blue-to-red.html

  * igt@kms_cursor_crc@cursor-suspend@pipe-a-dp-1:
    - shard-kbl:          NOTRUN -> [DMESG-WARN][50] ([i915#180]) +2 similar issues
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@kms_cursor_crc@cursor-suspend@pipe-a-dp-1.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor:
    - shard-tglb:         NOTRUN -> [SKIP][51] ([i915#4103])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor.html
    - shard-iclb:         NOTRUN -> [SKIP][52] ([i915#4103])
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_cursor_legacy@basic-busy-flip-before-cursor.html

  * igt@kms_cursor_legacy@cursor-vs-flip@toggle:
    - shard-iclb:         [PASS][53] -> [FAIL][54] ([i915#5072]) +1 similar issue
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb2/igt@kms_cursor_legacy@cursor-vs-flip@toggle.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb7/igt@kms_cursor_legacy@cursor-vs-flip@toggle.html

  * igt@kms_cursor_legacy@flip-vs-cursor@atomic-transitions-varying-size:
    - shard-glk:          [PASS][55] -> [FAIL][56] ([i915#2346])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk6/igt@kms_cursor_legacy@flip-vs-cursor@atomic-transitions-varying-size.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk3/igt@kms_cursor_legacy@flip-vs-cursor@atomic-transitions-varying-size.html

  * igt@kms_draw_crc@draw-method-rgb565-pwrite-4tiled:
    - shard-tglb:         NOTRUN -> [SKIP][57] ([i915#5287])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_draw_crc@draw-method-rgb565-pwrite-4tiled.html
    - shard-iclb:         NOTRUN -> [SKIP][58] ([i915#5287])
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_draw_crc@draw-method-rgb565-pwrite-4tiled.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-skl:          [PASS][59] -> [FAIL][60] ([i915#4767])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl6/igt@kms_fbcon_fbt@psr-suspend.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl9/igt@kms_fbcon_fbt@psr-suspend.html

  * igt@kms_flip@2x-wf_vblank-ts-check:
    - shard-iclb:         NOTRUN -> [SKIP][61] ([fdo#109274])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_flip@2x-wf_vblank-ts-check.html
    - shard-tglb:         NOTRUN -> [SKIP][62] ([fdo#109274] / [fdo#111825] / [i915#3637])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_flip@2x-wf_vblank-ts-check.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@c-edp1:
    - shard-skl:          [PASS][63] -> [FAIL][64] ([i915#2122]) +1 similar issue
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl7/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-edp1.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@kms_flip@flip-vs-expired-vblank-interruptible@c-edp1.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-upscaling@pipe-a-valid-mode:
    - shard-iclb:         NOTRUN -> [SKIP][65] ([i915#2672]) +6 similar issues
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb4/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-32bpp-4tile-upscaling@pipe-a-valid-mode.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-cpu:
    - shard-tglb:         NOTRUN -> [SKIP][66] ([fdo#109280] / [fdo#111825]) +4 similar issues
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-cpu.html
    - shard-iclb:         NOTRUN -> [SKIP][67] ([fdo#109280]) +4 similar issues
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-apl:          [PASS][68] -> [DMESG-WARN][69] ([i915#180])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl7/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl6/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-gtt:
    - shard-glk:          NOTRUN -> [SKIP][70] ([fdo#109271]) +28 similar issues
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk5/igt@kms_frontbuffer_tracking@fbcpsr-1p-offscren-pri-indfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-render:
    - shard-apl:          NOTRUN -> [SKIP][71] ([fdo#109271]) +130 similar issues
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl8/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-render.html

  * igt@kms_hdr@bpc-switch-suspend:
    - shard-tglb:         NOTRUN -> [SKIP][72] ([i915#3555]) +1 similar issue
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_hdr@bpc-switch-suspend.html

  * igt@kms_hdr@bpc-switch-suspend@pipe-a-dp-1:
    - shard-kbl:          NOTRUN -> [DMESG-FAIL][73] ([i915#180])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@kms_hdr@bpc-switch-suspend@pipe-a-dp-1.html

  * igt@kms_hdr@static-toggle-suspend:
    - shard-iclb:         NOTRUN -> [SKIP][74] ([i915#3555]) +1 similar issue
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_hdr@static-toggle-suspend.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-max:
    - shard-apl:          NOTRUN -> [FAIL][75] ([fdo#108145] / [i915#265]) +1 similar issue
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl8/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-max.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb:
    - shard-apl:          NOTRUN -> [FAIL][76] ([i915#265])
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl8/igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb.html

  * igt@kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-5@pipe-a-edp-1:
    - shard-iclb:         [PASS][77] -> [SKIP][78] ([i915#5176]) +2 similar issues
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-5@pipe-a-edp-1.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_plane_scaling@plane-downscale-with-pixel-format-factor-0-5@pipe-a-edp-1.html

  * igt@kms_prime@basic-crc@first-to-second:
    - shard-tglb:         NOTRUN -> [SKIP][79] ([i915#1836])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_prime@basic-crc@first-to-second.html
    - shard-iclb:         NOTRUN -> [SKIP][80] ([i915#1836])
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_prime@basic-crc@first-to-second.html

  * igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area:
    - shard-apl:          NOTRUN -> [SKIP][81] ([fdo#109271] / [i915#658])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@kms_psr2_sf@overlay-plane-update-sf-dmg-area.html

  * igt@kms_psr2_sf@primary-plane-update-sf-dmg-area:
    - shard-skl:          NOTRUN -> [SKIP][82] ([fdo#109271] / [i915#658])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area.html

  * igt@kms_psr2_su@frontbuffer-xrgb8888:
    - shard-kbl:          NOTRUN -> [SKIP][83] ([fdo#109271] / [i915#658]) +1 similar issue
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@kms_psr2_su@frontbuffer-xrgb8888.html

  * igt@kms_psr@psr2_cursor_mmap_gtt:
    - shard-tglb:         NOTRUN -> [FAIL][84] ([i915#132] / [i915#3467])
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_psr@psr2_cursor_mmap_gtt.html
    - shard-iclb:         NOTRUN -> [SKIP][85] ([fdo#109441])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_psr@psr2_cursor_mmap_gtt.html

  * igt@kms_psr@psr2_no_drrs:
    - shard-iclb:         [PASS][86] -> [SKIP][87] ([fdo#109441])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb2/igt@kms_psr@psr2_no_drrs.html
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb7/igt@kms_psr@psr2_no_drrs.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-tglb:         [PASS][88] -> [SKIP][89] ([i915#5519])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglb2/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_scaling_modes@scaling-mode-none@edp-1-pipe-a:
    - shard-iclb:         NOTRUN -> [SKIP][90] ([i915#5030]) +2 similar issues
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_scaling_modes@scaling-mode-none@edp-1-pipe-a.html

  * igt@kms_scaling_modes@scaling-mode-none@edp-1-pipe-d:
    - shard-tglb:         NOTRUN -> [SKIP][91] ([i915#5030]) +3 similar issues
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb7/igt@kms_scaling_modes@scaling-mode-none@edp-1-pipe-d.html

  * igt@kms_vblank@pipe-d-wait-forked:
    - shard-iclb:         NOTRUN -> [SKIP][92] ([fdo#109278]) +3 similar issues
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_vblank@pipe-d-wait-forked.html

  * igt@kms_vrr@flipline:
    - shard-skl:          NOTRUN -> [SKIP][93] ([fdo#109271]) +97 similar issues
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@kms_vrr@flipline.html

  * igt@kms_writeback@writeback-pixel-formats:
    - shard-apl:          NOTRUN -> [SKIP][94] ([fdo#109271] / [i915#2437])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl8/igt@kms_writeback@writeback-pixel-formats.html

  * igt@prime_nv_api@i915_self_import_to_different_fd:
    - shard-tglb:         NOTRUN -> [SKIP][95] ([fdo#109291])
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@prime_nv_api@i915_self_import_to_different_fd.html
    - shard-iclb:         NOTRUN -> [SKIP][96] ([fdo#109291])
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@prime_nv_api@i915_self_import_to_different_fd.html

  * igt@sw_sync@sync_multi_timeline_wait:
    - shard-apl:          NOTRUN -> [FAIL][97] ([i915#6140])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@sw_sync@sync_multi_timeline_wait.html

  * igt@sysfs_clients@fair-1:
    - shard-skl:          NOTRUN -> [SKIP][98] ([fdo#109271] / [i915#2994]) +1 similar issue
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl1/igt@sysfs_clients@fair-1.html

  * igt@sysfs_clients@recycle:
    - shard-apl:          NOTRUN -> [SKIP][99] ([fdo#109271] / [i915#2994]) +2 similar issues
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl4/igt@sysfs_clients@recycle.html
    - shard-tglb:         NOTRUN -> [SKIP][100] ([i915#2994])
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@sysfs_clients@recycle.html
    - shard-glk:          NOTRUN -> [SKIP][101] ([fdo#109271] / [i915#2994])
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk5/igt@sysfs_clients@recycle.html
    - shard-iclb:         NOTRUN -> [SKIP][102] ([i915#2994])
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@sysfs_clients@recycle.html
    - shard-kbl:          NOTRUN -> [SKIP][103] ([fdo#109271] / [i915#2994]) +1 similar issue
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@sysfs_clients@recycle.html

  * igt@sysfs_heartbeat_interval@mixed@bcs0:
    - shard-skl:          [PASS][104] -> [FAIL][105] ([i915#1731])
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl3/igt@sysfs_heartbeat_interval@mixed@bcs0.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl3/igt@sysfs_heartbeat_interval@mixed@bcs0.html

  
#### Possible fixes ####

  * igt@drm_buddy@all@buddy_alloc_smoke:
    - shard-skl:          [INCOMPLETE][106] ([i915#5800]) -> [PASS][107]
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl7/igt@drm_buddy@all@buddy_alloc_smoke.html
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl6/igt@drm_buddy@all@buddy_alloc_smoke.html

  * igt@fbdev@read:
    - {shard-rkl}:        [SKIP][108] ([i915#2582]) -> [PASS][109]
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@fbdev@read.html
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@fbdev@read.html

  * igt@gem_create@create-massive:
    - shard-apl:          [DMESG-WARN][110] ([i915#4991]) -> [PASS][111] +1 similar issue
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl1/igt@gem_create@create-massive.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl4/igt@gem_create@create-massive.html
    - shard-tglb:         [DMESG-WARN][112] ([i915#4991]) -> [PASS][113] +1 similar issue
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglb2/igt@gem_create@create-massive.html
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglb2/igt@gem_create@create-massive.html
    - shard-glk:          [DMESG-WARN][114] ([i915#4991]) -> [PASS][115] +1 similar issue
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk1/igt@gem_create@create-massive.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk5/igt@gem_create@create-massive.html
    - shard-kbl:          [DMESG-WARN][116] ([i915#4991]) -> [PASS][117]
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@gem_create@create-massive.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@gem_create@create-massive.html
    - {shard-rkl}:        [DMESG-WARN][118] ([i915#4991]) -> [PASS][119]
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@gem_create@create-massive.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-1/igt@gem_create@create-massive.html
    - shard-skl:          [DMESG-WARN][120] ([i915#4991]) -> [PASS][121]
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl4/igt@gem_create@create-massive.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl3/igt@gem_create@create-massive.html

  * igt@gem_ctx_exec@basic-nohangcheck:
    - {shard-tglu}:       [FAIL][122] ([i915#6268]) -> [PASS][123]
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglu-8/igt@gem_ctx_exec@basic-nohangcheck.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglu-6/igt@gem_ctx_exec@basic-nohangcheck.html

  * igt@gem_exec_balancer@parallel-balancer:
    - shard-iclb:         [SKIP][124] ([i915#4525]) -> [PASS][125]
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@gem_exec_balancer@parallel-balancer.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb1/igt@gem_exec_balancer@parallel-balancer.html

  * igt@gem_exec_fair@basic-flow@rcs0:
    - {shard-rkl}:        [FAIL][126] ([i915#2842]) -> [PASS][127] +1 similar issue
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@gem_exec_fair@basic-flow@rcs0.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-none@vecs0:
    - shard-apl:          [FAIL][128] ([i915#2842]) -> [PASS][129]
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl6/igt@gem_exec_fair@basic-none@vecs0.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl7/igt@gem_exec_fair@basic-none@vecs0.html

  * igt@gem_exec_fair@basic-pace-share@rcs0:
    - shard-glk:          [FAIL][130] ([i915#2842]) -> [PASS][131] +1 similar issue
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk9/igt@gem_exec_fair@basic-pace-share@rcs0.html
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk2/igt@gem_exec_fair@basic-pace-share@rcs0.html
    - {shard-tglu}:       [FAIL][132] ([i915#2842]) -> [PASS][133]
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglu-5/igt@gem_exec_fair@basic-pace-share@rcs0.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglu-1/igt@gem_exec_fair@basic-pace-share@rcs0.html

  * igt@gem_exec_fair@basic-pace@rcs0:
    - shard-kbl:          [FAIL][134] ([i915#2842]) -> [PASS][135]
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@gem_exec_fair@basic-pace@rcs0.html
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@gem_exec_fair@basic-pace@rcs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-iclb:         [FAIL][136] ([i915#2842]) -> [PASS][137]
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@gem_exec_fair@basic-throttle@rcs0.html
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb1/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_exec_reloc@basic-gtt-wc-noreloc:
    - {shard-rkl}:        [SKIP][138] ([i915#3281]) -> [PASS][139] +15 similar issues
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@gem_exec_reloc@basic-gtt-wc-noreloc.html
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gem_exec_reloc@basic-gtt-wc-noreloc.html

  * igt@gem_exec_schedule@semaphore-power:
    - {shard-rkl}:        [SKIP][140] ([fdo#110254]) -> [PASS][141]
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@gem_exec_schedule@semaphore-power.html
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gem_exec_schedule@semaphore-power.html

  * igt@gem_exec_whisper@basic-fds-priority-all:
    - shard-glk:          [DMESG-WARN][142] ([i915#118]) -> [PASS][143] +1 similar issue
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk9/igt@gem_exec_whisper@basic-fds-priority-all.html
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk2/igt@gem_exec_whisper@basic-fds-priority-all.html

  * igt@gem_mmap_gtt@coherency:
    - {shard-rkl}:        [SKIP][144] ([fdo#111656]) -> [PASS][145]
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-6/igt@gem_mmap_gtt@coherency.html
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gem_mmap_gtt@coherency.html

  * igt@gem_partial_pwrite_pread@writes-after-reads-uncached:
    - {shard-rkl}:        [SKIP][146] ([i915#3282]) -> [PASS][147] +6 similar issues
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gem_partial_pwrite_pread@writes-after-reads-uncached.html

  * igt@gem_userptr_blits@input-checking:
    - shard-iclb:         [DMESG-WARN][148] ([i915#4991]) -> [PASS][149] +1 similar issue
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb5/igt@gem_userptr_blits@input-checking.html
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@gem_userptr_blits@input-checking.html
    - shard-snb:          [DMESG-WARN][150] ([i915#4991]) -> [PASS][151] +1 similar issue
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-snb5/igt@gem_userptr_blits@input-checking.html
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb2/igt@gem_userptr_blits@input-checking.html

  * igt@gem_workarounds@suspend-resume:
    - shard-apl:          [DMESG-WARN][152] ([i915#180]) -> [PASS][153] +2 similar issues
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl6/igt@gem_workarounds@suspend-resume.html
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl6/igt@gem_workarounds@suspend-resume.html

  * igt@gem_workarounds@suspend-resume-fd:
    - shard-kbl:          [DMESG-WARN][154] ([i915#180]) -> [PASS][155] +3 similar issues
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl7/igt@gem_workarounds@suspend-resume-fd.html
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@gem_workarounds@suspend-resume-fd.html

  * igt@gen9_exec_parse@bb-start-param:
    - {shard-rkl}:        [SKIP][156] ([i915#2527]) -> [PASS][157] +5 similar issues
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@gen9_exec_parse@bb-start-param.html
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@gen9_exec_parse@bb-start-param.html

  * igt@i915_module_load@reload-with-fault-injection:
    - shard-snb:          [DMESG-WARN][158] ([i915#6201]) -> [PASS][159]
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-snb6/igt@i915_module_load@reload-with-fault-injection.html
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb2/igt@i915_module_load@reload-with-fault-injection.html

  * igt@i915_pm_dc@dc6-dpms:
    - {shard-tglu}:       [FAIL][160] ([i915#3989] / [i915#454]) -> [PASS][161]
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-tglu-1/igt@i915_pm_dc@dc6-dpms.html
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-tglu-2/igt@i915_pm_dc@dc6-dpms.html

  * igt@kms_big_fb@x-tiled-32bpp-rotate-0:
    - {shard-rkl}:        [SKIP][162] ([i915#1845] / [i915#4098]) -> [PASS][163] +19 similar issues
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_big_fb@x-tiled-32bpp-rotate-0.html

  * igt@kms_cursor_legacy@flip-vs-cursor@toggle:
    - shard-iclb:         [FAIL][164] ([i915#2346]) -> [PASS][165] +2 similar issues
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor@toggle.html
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_cursor_legacy@flip-vs-cursor@toggle.html

  * igt@kms_cursor_legacy@flip-vs-cursor@varying-size:
    - shard-iclb:         [FAIL][166] -> [PASS][167]
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor@varying-size.html
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_cursor_legacy@flip-vs-cursor@varying-size.html

  * igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled:
    - {shard-rkl}:        [SKIP][168] ([fdo#111314] / [i915#4098] / [i915#4369]) -> [PASS][169] +2 similar issues
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled.html
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_draw_crc@draw-method-xrgb8888-pwrite-untiled.html

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2:
    - shard-glk:          [FAIL][170] ([i915#79]) -> [PASS][171]
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk8/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk1/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1:
    - shard-skl:          [FAIL][172] ([i915#2122]) -> [PASS][173]
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl6/igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1.html
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl5/igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1.html

  * igt@kms_frontbuffer_tracking@psr-suspend:
    - {shard-rkl}:        [SKIP][174] ([i915#1849] / [i915#4098]) -> [PASS][175] +18 similar issues
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@kms_frontbuffer_tracking@psr-suspend.html
   [175]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_frontbuffer_tracking@psr-suspend.html

  * igt@kms_invalid_mode@bad-vtotal:
    - {shard-rkl}:        [SKIP][176] ([i915#4278]) -> [PASS][177]
   [176]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@kms_invalid_mode@bad-vtotal.html
   [177]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_invalid_mode@bad-vtotal.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb:
    - {shard-rkl}:        [SKIP][178] ([i915#1849] / [i915#4070] / [i915#4098]) -> [PASS][179]
   [178]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb.html
   [179]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_plane_alpha_blend@pipe-a-alpha-transparent-fb.html

  * igt@kms_psr@psr2_cursor_plane_move:
    - shard-iclb:         [SKIP][180] ([fdo#109441]) -> [PASS][181] +2 similar issues
   [180]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@kms_psr@psr2_cursor_plane_move.html
   [181]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_psr@psr2_cursor_plane_move.html

  * igt@kms_psr@sprite_blt:
    - {shard-rkl}:        [SKIP][182] ([i915#1072]) -> [PASS][183] +1 similar issue
   [182]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@kms_psr@sprite_blt.html
   [183]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_psr@sprite_blt.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-iclb:         [SKIP][184] ([i915#5519]) -> [PASS][185]
   [184]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb8/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html
   [185]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb6/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_universal_plane@universal-plane-gen9-features-pipe-a:
    - {shard-rkl}:        [SKIP][186] ([i915#1845] / [i915#4070] / [i915#4098]) -> [PASS][187]
   [186]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-2/igt@kms_universal_plane@universal-plane-gen9-features-pipe-a.html
   [187]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-6/igt@kms_universal_plane@universal-plane-gen9-features-pipe-a.html

  * igt@perf@polling-parameterized:
    - shard-skl:          [FAIL][188] ([i915#5639]) -> [PASS][189]
   [188]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl3/igt@perf@polling-parameterized.html
   [189]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl7/igt@perf@polling-parameterized.html
    - shard-apl:          [FAIL][190] ([i915#5639]) -> [PASS][191]
   [190]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl8/igt@perf@polling-parameterized.html
   [191]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl8/igt@perf@polling-parameterized.html
    - shard-glk:          [FAIL][192] ([i915#5639]) -> [PASS][193]
   [192]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-glk2/igt@perf@polling-parameterized.html
   [193]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-glk7/igt@perf@polling-parameterized.html

  * igt@prime_vgem@basic-write:
    - {shard-rkl}:        [SKIP][194] ([fdo#109295] / [i915#3291] / [i915#3708]) -> [PASS][195]
   [194]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-6/igt@prime_vgem@basic-write.html
   [195]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@prime_vgem@basic-write.html

  * igt@prime_vgem@coherency-gtt:
    - {shard-rkl}:        [SKIP][196] ([fdo#109295] / [fdo#111656] / [i915#3708]) -> [PASS][197]
   [196]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-rkl-1/igt@prime_vgem@coherency-gtt.html
   [197]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-rkl-5/igt@prime_vgem@coherency-gtt.html

  
#### Warnings ####

  * igt@gem_exec_fair@basic-none-rrul@rcs0:
    - shard-iclb:         [FAIL][198] ([i915#2842]) -> [FAIL][199] ([i915#2852])
   [198]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb8/igt@gem_exec_fair@basic-none-rrul@rcs0.html
   [199]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb5/igt@gem_exec_fair@basic-none-rrul@rcs0.html

  * igt@kms_ccs@pipe-b-bad-rotation-90-4_tiled_dg2_rc_ccs_cc:
    - shard-skl:          [SKIP][200] ([fdo#109271]) -> [SKIP][201] ([fdo#109271] / [i915#1888]) +1 similar issue
   [200]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl6/igt@kms_ccs@pipe-b-bad-rotation-90-4_tiled_dg2_rc_ccs_cc.html
   [201]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl5/igt@kms_ccs@pipe-b-bad-rotation-90-4_tiled_dg2_rc_ccs_cc.html

  * igt@kms_chamelium@hdmi-audio:
    - shard-skl:          [SKIP][202] ([fdo#109271] / [fdo#111827] / [i915#1888]) -> [SKIP][203] ([fdo#109271] / [fdo#111827])
   [202]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl6/igt@kms_chamelium@hdmi-audio.html
   [203]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl5/igt@kms_chamelium@hdmi-audio.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render:
    - shard-skl:          [INCOMPLETE][204] -> [SKIP][205] ([fdo#109271])
   [204]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl3/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html
   [205]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl7/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html

  * igt@kms_psr2_sf@cursor-plane-update-sf:
    - shard-iclb:         [SKIP][206] ([i915#2920]) -> [SKIP][207] ([fdo#111068] / [i915#658])
   [206]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb2/igt@kms_psr2_sf@cursor-plane-update-sf.html
   [207]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb7/igt@kms_psr2_sf@cursor-plane-update-sf.html

  * igt@kms_psr2_sf@overlay-plane-move-continuous-sf:
    - shard-iclb:         [SKIP][208] ([i915#658]) -> [SKIP][209] ([i915#2920]) +1 similar issue
   [208]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb7/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html
   [209]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb2/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_su@page_flip-nv12:
    - shard-iclb:         [FAIL][210] ([i915#5939]) -> [SKIP][211] ([fdo#109642] / [fdo#111068] / [i915#658]) +1 similar issue
   [210]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-iclb2/igt@kms_psr2_su@page_flip-nv12.html
   [211]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-iclb8/igt@kms_psr2_su@page_flip-nv12.html

  * igt@runner@aborted:
    - shard-snb:          ([FAIL][212], [FAIL][213], [FAIL][214]) ([i915#3002] / [i915#4312]) -> [FAIL][215] ([i915#4312])
   [212]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-snb5/igt@runner@aborted.html
   [213]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-snb6/igt@runner@aborted.html
   [214]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-snb6/igt@runner@aborted.html
   [215]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-snb6/igt@runner@aborted.html
    - shard-skl:          ([FAIL][216], [FAIL][217]) ([i915#2029] / [i915#3002] / [i915#4312] / [i915#5257]) -> ([FAIL][218], [FAIL][219], [FAIL][220], [FAIL][221]) ([i915#2029] / [i915#4312] / [i915#5257])
   [216]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl4/igt@runner@aborted.html
   [217]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-skl3/igt@runner@aborted.html
   [218]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl5/igt@runner@aborted.html
   [219]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl5/igt@runner@aborted.html
   [220]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl2/igt@runner@aborted.html
   [221]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-skl6/igt@runner@aborted.html
    - shard-apl:          ([FAIL][222], [FAIL][223], [FAIL][224], [FAIL][225], [FAIL][226]) ([fdo#109271] / [i915#180] / [i915#3002] / [i915#4312] / [i915#5257]) -> [FAIL][227] ([fdo#109271] / [i915#4312] / [i915#5257])
   [222]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl4/igt@runner@aborted.html
   [223]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl8/igt@runner@aborted.html
   [224]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl1/igt@runner@aborted.html
   [225]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl6/igt@runner@aborted.html
   [226]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-apl3/igt@runner@aborted.html
   [227]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-apl6/igt@runner@aborted.html
    - shard-kbl:          ([FAIL][228], [FAIL][229], [FAIL][230], [FAIL][231], [FAIL][232], [FAIL][233], [FAIL][234], [FAIL][235], [FAIL][236], [FAIL][237], [FAIL][238], [FAIL][239], [FAIL][240], [FAIL][241]) ([fdo#109271] / [i915#180] / [i915#3002] / [i915#4312] / [i915#5257]) -> ([FAIL][242], [FAIL][243], [FAIL][244], [FAIL][245], [FAIL][246], [FAIL][247], [FAIL][248], [FAIL][249], [FAIL][250], [FAIL][251], [FAIL][252], [FAIL][253], [FAIL][254], [FAIL][255]) ([fdo#109271] / [i915#180] / [i915#4312] / [i915#5257])
   [228]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@runner@aborted.html
   [229]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl4/igt@runner@aborted.html
   [230]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl4/igt@runner@aborted.html
   [231]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@runner@aborted.html
   [232]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@runner@aborted.html
   [233]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl4/igt@runner@aborted.html
   [234]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@runner@aborted.html
   [235]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl1/igt@runner@aborted.html
   [236]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl4/igt@runner@aborted.html
   [237]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl4/igt@runner@aborted.html
   [238]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl7/igt@runner@aborted.html
   [239]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl7/igt@runner@aborted.html
   [240]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl7/igt@runner@aborted.html
   [241]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11849/shard-kbl7/igt@runner@aborted.html
   [242]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@runner@aborted.html
   [243]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@runner@aborted.html
   [244]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@runner@aborted.html
   [245]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@runner@aborted.html
   [246]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl7/igt@runner@aborted.html
   [247]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@runner@aborted.html
   [248]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@runner@aborted.html
   [249]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@runner@aborted.html
   [250]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@runner@aborted.html
   [251]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl1/igt@runner@aborted.html
   [252]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl4/igt@runner@aborted.html
   [253]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl7/igt@runner@aborted.html
   [254]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl7/igt@runner@aborted.html
   [255]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/shard-kbl7/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109284]: https://bugs.freedesktop.org/show_bug.cgi?id=109284
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109291]: https://bugs.freedesktop.org/show_bug.cgi?id=109291
  [fdo#109295]: https://bugs.freedesktop.org/show_bug.cgi?id=109295
  [fdo#109300]: https://bugs.freedesktop.org/show_bug.cgi?id=109300
  [fdo#109308]: https://bugs.freedesktop.org/show_bug.cgi?id=109308
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#109642]: https://bugs.freedesktop.org/show_bug.cgi?id=109642
  [fdo#110254]: https://bugs.freedesktop.org/show_bug.cgi?id=110254
  [fdo#110723]: https://bugs.freedesktop.org/show_bug.cgi?id=110723
  [fdo#111068]: https://bugs.freedesktop.org/show_bug.cgi?id=111068
  [fdo#111314]: https://bugs.freedesktop.org/show_bug.cgi?id=111314
  [fdo#111614]: https://bugs.freedesktop.org/show_bug.cgi?id=111614
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111656]: https://bugs.freedesktop.org/show_bug.cgi?id=111656
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1099]: https://gitlab.freedesktop.org/drm/intel/issues/1099
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1257]: https://gitlab.freedesktop.org/drm/intel/issues/1257
  [i915#132]: https://gitlab.freedesktop.org/drm/intel/issues/132
  [i915#1397]: https://gitlab.freedesktop.org/drm/intel/issues/1397
  [i915#1731]: https://gitlab.freedesktop.org/drm/intel/issues/1731
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1825]: https://gitlab.freedesktop.org/drm/intel/issues/1825
  [i915#1836]: https://gitlab.freedesktop.org/drm/intel/issues/1836
  [i915#1839]: https://gitlab.freedesktop.org/drm/intel/issues/1839
  [i915#1845]: https://gitlab.freedesktop.org/drm/intel/issues/1845
  [i915#1849]: https://gitlab.freedesktop.org/drm/intel/issues/1849
  [i915#1888]: https://gitlab.freedesktop.org/drm/intel/issues/1888
  [i915#2029]: https://gitlab.freedesktop.org/drm/intel/issues/2029
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2410]: https://gitlab.freedesktop.org/drm/intel/issues/2410
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2527]: https://gitlab.freedesktop.org/drm/intel/issues/2527
  [i915#2530]: https://gitlab.freedesktop.org/drm/intel/issues/2530
  [i915#2532]: https://gitlab.freedesktop.org/drm/intel/issues/2532
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2852]: https://gitlab.freedesktop.org/drm/intel/issues/2852
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#2994]: https://gitlab.freedesktop.org/drm/intel/issues/2994
  [i915#3002]: https://gitlab.freedesktop.org/drm/intel/issues/3002
  [i915#3012]: https://gitlab.freedesktop.org/drm/intel/issues/3012
  [i915#3070]: https://gitlab.freedesktop.org/drm/intel/issues/3070
  [i915#3116]: https://gitlab.freedesktop.org/drm/intel/issues/3116
  [i915#3281]: https://gitlab.freedesktop.org/drm/intel/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/intel/issues/3297
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3361]: https://gitlab.freedesktop.org/drm/intel/issues/3361
  [i915#3467]: https://gitlab.freedesktop.org/drm/intel/issues/3467
  [i915#3536]: https://gitlab.freedesktop.org/drm/intel/issues/3536
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3558]: https://gitlab.freedesktop.org/drm/intel/issues/3558
  [i915#3637]: https://gitlab.freedesktop.org/drm/intel/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/intel/issues/3638
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3734]: https://gitlab.freedesktop.org/drm/intel/issues/3734
  [i915#3743]: https://gitlab.freedesktop.org/drm/intel/issues/3743
  [i915#3778]: https://gitlab.freedesktop.org/drm/intel/issues/3778
  [i915#3825]: https://gitlab.freedesktop.org/drm/intel/issues/3825
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#3989]: https://gitlab.freedesktop.org/drm/intel/issues/3989
  [i915#4070]: https://gitlab.freedesktop.org/drm/intel/issues/4070
  [i915#4098]: https://gitlab.freedesktop.org/drm/intel/issues/4098
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4171]: https://gitlab.freedesktop.org/drm/intel/issues/4171
  [i915#4270]: https://gitlab.freedesktop.org/drm/intel/issues/4270
  [i915#4278]: https://gitlab.freedesktop.org/drm/intel/issues/4278
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4369]: https://gitlab.freedesktop.org/drm/intel/issues/4369
  [i915#4462]: https://gitlab.freedesktop.org/drm/intel/issues/4462
  [i915#4525]: https://gitlab.freedesktop.org/drm/intel/issues/4525
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4767]: https://gitlab.freedesktop.org/drm/intel/issues/4767
  [i915#4893]: https://gitlab.freedesktop.org/drm/intel/issues/4893
  [i915#4939]: https://gitlab.freedesktop.org/drm/intel/issues/4939
  [i915#4991]: https://gitlab.freedesktop.org/drm/intel/issues/4991
  [i915#5030]: https://gitlab.freedesktop.org/drm/intel/issues/5030
  [i915#5072]: https://gitlab.freedesktop.org/drm/intel/issues/5072
  [i915#5129]: https://gitlab.freedesktop.org/drm/intel/issues/5129
  [i915#5176]: https://gitlab.freedesktop.org/drm/intel/issues/5176
  [i915#5182]: https://gitlab.freedesktop.org/drm/intel/issues/5182
  [i915#5235]: https://gitlab.freedesktop.org/drm/intel/issues/5235
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5286]: https://gitlab.freedesktop.org/drm/intel/issues/5286
  [i915#5287]: https://gitlab.freedesktop.org/drm/intel/issues/5287
  [i915#5288]: https://gitlab.freedesktop.org/drm/intel/issues/5288
  [i915#5325]: https://gitlab.freedesktop.org/drm/intel/issues/5325
  [i915#5327]: https://gitlab.freedesktop.org/drm/intel/issues/5327
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#5519]: https://gitlab.freedesktop.org/drm/intel/issues/5519
  [i915#5566]: https://gitlab.freedesktop.org/drm/intel/issues/5566
  [i915#5639]: https://gitlab.freedesktop.org/drm/intel/issues/5639
  [i915#5800]: https://gitlab.freedesktop.org/drm/intel/issues/5800
  [i915#5939]: https://gitlab.freedesktop.org/drm/intel/issues/5939
  [i915#6095]: https://gitlab.freedesktop.org/drm/intel/issues/6095
  [i915#6140]: https://gitlab.freedesktop.org/drm/intel/issues/6140
  [i915#6201]: https://gitlab.freedesktop.org/drm/intel/issues/6201
  [i915#6248]: https://gitlab.freedesktop.org/drm/intel/issues/6248
  [i915#6268]: https://gitlab.freedesktop.org/drm/intel/issues/6268
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#716]: https://gitlab.freedesktop.org/drm/intel/issues/716
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79


Build changes
-------------

  * Linux: CI_DRM_11849 -> Patchwork_104704v3

  CI-20190529: 20190529
  CI_DRM_11849: 66197f3ca0b462799e265b002dc5cf8dcec1c62d @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6555: 1a3ffecd400b8f82c35745fa2e07992f6bdeede2 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_104704v3: 66197f3ca0b462799e265b002dc5cf8dcec1c62d @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_104704v3/index.html

[-- Attachment #2: Type: text/html, Size: 69992 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
  2022-07-05 14:23     ` Mauro Carvalho Chehab
@ 2022-07-06 15:04       ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-06 15:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
> On Tue,  5 Jul 2022 15:24:49 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> It moves overflows_type utility macro into drm util header from i915_utils
>> header. The overflows_type can be used to catch the truncation between data
>> types. And it adds safe_conversion() macro which performs a type conversion
>> (cast) of an source value into a new variable, checking that the
>> destination is large enough to hold the source value.
>> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
>> while compiling.
>>
>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Cc: Matthew Auld <matthew.auld@intel.com>
>> Cc: Nirmoy Das <nirmoy.das@intel.com>
>> Cc: Jani Nikula <jani.nikula@intel.com>
>> ---
>>   drivers/gpu/drm/i915/i915_utils.h |  5 +--
>>   include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>>   2 files changed, 55 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
>> index c10d68cdc3ca..345e5b2dc1cd 100644
>> --- a/drivers/gpu/drm/i915/i915_utils.h
>> +++ b/drivers/gpu/drm/i915/i915_utils.h
>> @@ -32,6 +32,7 @@
>>   #include <linux/types.h>
>>   #include <linux/workqueue.h>
>>   #include <linux/sched/clock.h>
>> +#include <drm/drm_util.h>
>>   
>>   #ifdef CONFIG_X86
>>   #include <asm/hypervisor.h>
>> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>>   #define range_overflows_end_t(type, start, size, max) \
>>   	range_overflows_end((type)(start), (type)(size), (type)(max))
>>   
>> -/* Note we don't consider signbits :| */
>> -#define overflows_type(x, T) \
>> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>> -
>>   #define ptr_mask_bits(ptr, n) ({					\
>>   	unsigned long __v = (unsigned long)(ptr);			\
>>   	(typeof(ptr))(__v & -BIT(n));					\
>> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
>> index 79952d8c4bba..c56230e39e37 100644
>> --- a/include/drm/drm_util.h
>> +++ b/include/drm/drm_util.h
>> @@ -62,6 +62,60 @@
>>    */
>>   #define for_each_if(condition) if (!(condition)) {} else
>>   
>> +/**
>> + * overflows_type - helper for checking the truncation between data types
>> + * @x: Source for overflow type comparison
>> + * @T: Destination for overflow type comparison
>> + *
>> + * It compares the values and size of each data type between the first and
>> + * second argument to check whether truncation can occur when assigning the
>> + * first argument to the variable of the second argument.
>> + * It does't consider signbits.
>> + *
>> + * Returns:
>> + * True if truncation can occur, false otherwise.
>> + */
>> +#define overflows_type(x, T) \
>> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> 
> As pointed on its description, this macro only works if both types
> are either signed or unsigned. However, the macro itself doesn't check
> it.
> 
> It probably worth adding something there to ensure that both types are
> either signed or unsigned. I would add this ancillary macro probably on
> on a generic kernel header - as this can be useful outside drm:
> 
> 	#define sign_matches(x, y) \
> 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> 
> And then include use it at overflows_type:
> 
> 	BUILD_BUG_ON(!sign_matches(x, T))
> 
Hi Mauro, thanks for checking it.

What you commented here (sign_matches macro) is to check whether the 
sign bits of two types are the same,  but the purpose of the 
overflows_type() macro checks overflows while assigning a variable with 
a large data size (BITS_PER_TYPE is large) to a variable with a small 
data size (BITS_PER_TYPE is small).

we can check the additional sign bit by adding sign_matches() to the 
overflows_type() macro, but in the current scenario, it is used only 
when the sign bit is the same.
Should the macro be extended even for cases where the sign bit is 
different in the current state? (If yes, I'll updated it as v3)

In addition, the place where this macro is currently used is only in the 
i915 driver, so it has been moved to the header of the drm subsystem.
IMHO, moving the macro location so that it can be used by multiple 
subsystems of linux would be a good idea when there is a use case for 
this macro. What do you think?

G.G.
>> +
>> +/**
>> + * exact_type - break compile if source type and destination value's type are
>> + * not the same
>> + * @T: Source type
>> + * @n: Destination value
>> + *
>> + * It is a helper macro for a poor man's -Wconversion: only allow variables of
>> + * an exact type. It determines whether the source type and destination value's
>> + * type are the same while compiling, and it breaks compile if two types are
>> + * not the same
>> + */
>> +#define exact_type(T, n) \
>> +	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
>> +
>> +/**
>> + * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
>> + * @n: value to compare pgoff_t type
>> + *
>> + * It breaks compile if the argument value's type is not pgoff_t type.
>> + */
>> +#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
>> +
>> +/*
>> + * safe_conversion - perform a type conversion (cast) of an source value into
>> + * a new variable, checking that the destination is large enough to hold the
>> + * source value.
>> + * @ptr: Destination pointer address
>> + * @value: Source value
>> + *
>> + * Returns:
>> + * If the value would overflow the destination, it returns false.
>> + */
>> +#define safe_conversion(ptr, value) ({ \
>> +	typeof(value) __v = (value); \
>> +	typeof(ptr) __ptr = (ptr); \
>> +	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
>> +})
>> +
>>   /**
>>    * drm_can_sleep - returns true if currently okay to sleep
>>    *

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
@ 2022-07-06 15:04       ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-06 15:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
> On Tue,  5 Jul 2022 15:24:49 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> It moves overflows_type utility macro into drm util header from i915_utils
>> header. The overflows_type can be used to catch the truncation between data
>> types. And it adds safe_conversion() macro which performs a type conversion
>> (cast) of an source value into a new variable, checking that the
>> destination is large enough to hold the source value.
>> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
>> while compiling.
>>
>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Cc: Matthew Auld <matthew.auld@intel.com>
>> Cc: Nirmoy Das <nirmoy.das@intel.com>
>> Cc: Jani Nikula <jani.nikula@intel.com>
>> ---
>>   drivers/gpu/drm/i915/i915_utils.h |  5 +--
>>   include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>>   2 files changed, 55 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
>> index c10d68cdc3ca..345e5b2dc1cd 100644
>> --- a/drivers/gpu/drm/i915/i915_utils.h
>> +++ b/drivers/gpu/drm/i915/i915_utils.h
>> @@ -32,6 +32,7 @@
>>   #include <linux/types.h>
>>   #include <linux/workqueue.h>
>>   #include <linux/sched/clock.h>
>> +#include <drm/drm_util.h>
>>   
>>   #ifdef CONFIG_X86
>>   #include <asm/hypervisor.h>
>> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>>   #define range_overflows_end_t(type, start, size, max) \
>>   	range_overflows_end((type)(start), (type)(size), (type)(max))
>>   
>> -/* Note we don't consider signbits :| */
>> -#define overflows_type(x, T) \
>> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>> -
>>   #define ptr_mask_bits(ptr, n) ({					\
>>   	unsigned long __v = (unsigned long)(ptr);			\
>>   	(typeof(ptr))(__v & -BIT(n));					\
>> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
>> index 79952d8c4bba..c56230e39e37 100644
>> --- a/include/drm/drm_util.h
>> +++ b/include/drm/drm_util.h
>> @@ -62,6 +62,60 @@
>>    */
>>   #define for_each_if(condition) if (!(condition)) {} else
>>   
>> +/**
>> + * overflows_type - helper for checking the truncation between data types
>> + * @x: Source for overflow type comparison
>> + * @T: Destination for overflow type comparison
>> + *
>> + * It compares the values and size of each data type between the first and
>> + * second argument to check whether truncation can occur when assigning the
>> + * first argument to the variable of the second argument.
>> + * It does't consider signbits.
>> + *
>> + * Returns:
>> + * True if truncation can occur, false otherwise.
>> + */
>> +#define overflows_type(x, T) \
>> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> 
> As pointed on its description, this macro only works if both types
> are either signed or unsigned. However, the macro itself doesn't check
> it.
> 
> It probably worth adding something there to ensure that both types are
> either signed or unsigned. I would add this ancillary macro probably on
> on a generic kernel header - as this can be useful outside drm:
> 
> 	#define sign_matches(x, y) \
> 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> 
> And then include use it at overflows_type:
> 
> 	BUILD_BUG_ON(!sign_matches(x, T))
> 
Hi Mauro, thanks for checking it.

What you commented here (sign_matches macro) is to check whether the 
sign bits of two types are the same,  but the purpose of the 
overflows_type() macro checks overflows while assigning a variable with 
a large data size (BITS_PER_TYPE is large) to a variable with a small 
data size (BITS_PER_TYPE is small).

we can check the additional sign bit by adding sign_matches() to the 
overflows_type() macro, but in the current scenario, it is used only 
when the sign bit is the same.
Should the macro be extended even for cases where the sign bit is 
different in the current state? (If yes, I'll updated it as v3)

In addition, the place where this macro is currently used is only in the 
i915 driver, so it has been moved to the header of the drm subsystem.
IMHO, moving the macro location so that it can be used by multiple 
subsystems of linux would be a good idea when there is a use case for 
this macro. What do you think?

G.G.
>> +
>> +/**
>> + * exact_type - break compile if source type and destination value's type are
>> + * not the same
>> + * @T: Source type
>> + * @n: Destination value
>> + *
>> + * It is a helper macro for a poor man's -Wconversion: only allow variables of
>> + * an exact type. It determines whether the source type and destination value's
>> + * type are the same while compiling, and it breaks compile if two types are
>> + * not the same
>> + */
>> +#define exact_type(T, n) \
>> +	BUILD_BUG_ON(!__builtin_constant_p(n) && !__builtin_types_compatible_p(T, typeof(n)))
>> +
>> +/**
>> + * exactly_pgoff_t - helper to check if the type of a value is pgoff_t
>> + * @n: value to compare pgoff_t type
>> + *
>> + * It breaks compile if the argument value's type is not pgoff_t type.
>> + */
>> +#define exactly_pgoff_t(n) exact_type(pgoff_t, n)
>> +
>> +/*
>> + * safe_conversion - perform a type conversion (cast) of an source value into
>> + * a new variable, checking that the destination is large enough to hold the
>> + * source value.
>> + * @ptr: Destination pointer address
>> + * @value: Source value
>> + *
>> + * Returns:
>> + * If the value would overflow the destination, it returns false.
>> + */
>> +#define safe_conversion(ptr, value) ({ \
>> +	typeof(value) __v = (value); \
>> +	typeof(ptr) __ptr = (ptr); \
>> +	overflows_type(__v, *__ptr) ? 0 : (*__ptr = (typeof(*__ptr))__v), 1; \
>> +})
>> +
>>   /**
>>    * drm_can_sleep - returns true if currently okay to sleep
>>    *

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
  2022-07-05 14:35     ` Mauro Carvalho Chehab
@ 2022-07-06 16:33       ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-06 16:33 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
> On Tue,  5 Jul 2022 15:24:50 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> From: Chris Wilson <chris@chris-wilson.co.uk>
>>
>> We need to check that we avoid integer overflows when looking up a page,
>> and so fix all the instances where we have mistakenly used a plain
>> integer instead of a more suitable long. Be pedantic and add integer
>> typechecking to the lookup so that we can be sure that we are safe.
>> And it also uses pgoff_t as our page lookups must remain compatible with
>> the page cache, pgoff_t is currently exactly unsigned long.
>>
>> v2: Move added i915_utils's macro into drm_util header (Jani N)
>>
>> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>> Cc: Matthew Auld <matthew.auld@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>>   drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>>   .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>>   .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>>   .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>>   drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>>   drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>>   9 files changed, 100 insertions(+), 55 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index ccec4055fde3..90996fe8ad45 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>>   static void
>>   i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>   	void *src_map;
>>   	void *src_ptr;
>>   
>> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
>> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>>   
>>   	src_ptr = src_map + offset_in_page(offset);
>>   	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
>> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>>   static void
>>   i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>>   	void __iomem *src_map;
>>   	void __iomem *src_ptr;
>> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>>   
>>   	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>>   				    dma - obj->mm.region->region.start,
>> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>>    */
>>   int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>>   	GEM_BUG_ON(offset >= obj->base.size);
>>   	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>>   	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index 6f0a3ce35567..a60c6f4517d5 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -27,8 +27,10 @@ enum intel_region_id;
>>    * 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
>> + * - sg_table embeds unsigned int for nents
>> + *
>> + * We can check for invalidly typed locals with typecheck(), see for example
>> + * i915_gem_object_get_sg().
>>    */
>>   #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>>   	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
>> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>>   struct scatterlist *
>>   __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>   			 struct i915_gem_object_page_iter *iter,
>> -			 unsigned int n,
>> -			 unsigned int *offset, bool dma);
>> +			 pgoff_t  n,
>> +			 unsigned int *offset);
>> +
>> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
>> +})
>>   
>>   static inline struct scatterlist *
>> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>> -		       unsigned int n,
>> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>>   		       unsigned int *offset)
>>   {
>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>>   }
>>   
>> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_sg)(obj, n, offset); \
>> +})
>> +
>>   static inline struct scatterlist *
>> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
>> -			   unsigned int n,
>> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>>   			   unsigned int *offset)
>>   {
>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>>   }
>>   
>> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
>> +})
>> +
>>   struct page *
>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
>> -			 unsigned int n);
>> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_page(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_page)(obj, n); \
>> +})
>>   
>>   struct page *
>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>> -			       unsigned int n);
>> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dirty_page)(obj, n); \
>> +})
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>> -				    unsigned long n,
>> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>>   				    unsigned int *len);
>>   
>> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
>> +})
>> +
>>   dma_addr_t
>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>> -				unsigned long n);
>> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_dma_address(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dma_address)(obj, n); \
>> +})
>>   
>>   void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>>   				 struct sg_table *pages,
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> index 97c820eee115..1d1edcb3514b 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>>   }
>>   
>>   struct scatterlist *
>> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>>   			 struct i915_gem_object_page_iter *iter,
>> -			 unsigned int n,
>> -			 unsigned int *offset,
>> -			 bool dma)
>> +			 pgoff_t n,
>> +			 unsigned int *offset)
>> +
> 
> Nitpick: no need to place the function name in parenthesis.
> 
>>   {
>> -	struct scatterlist *sg;
>> +	const bool dma = iter == &obj->mm.get_dma_page ||
>> +			 iter == &obj->ttm.get_io_page;
>>   	unsigned int idx, count;
>> +	struct scatterlist *sg;
>>   
>>   	might_sleep();
>>   	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
>> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   struct page *
>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above: why are you placing parenthesis at the function name here?
> Just use:
> 	
> 	struct page *
> 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
>
In this case, the macro and function have the same name. If parenthesis 
is not used, the following compile error occurs as the macro is applied 
to the c code.

./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected 
identifier or ‘(’ before ‘{’ token
   356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
       |                                                       ^
drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of 
macro ‘__i915_gem_object_get_sg’
   506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
       | ^~~~~~~~~~~~~~~~~~~~~~~~

And all of the parts you leave comments below are cases where the names 
of macros and functions are the same.

G.G.


>>   {
>>   	struct scatterlist *sg;
>>   	unsigned int offset;
>> @@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>>   
>>   /* Like i915_gem_object_get_page(), but mark the returned page dirty */
>>   struct page *
>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>> -			       unsigned int n)
>> +(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above.
> 
>>   {
>>   	struct page *page;
>>   
>> @@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>> -				    unsigned long n,
>> -				    unsigned int *len)
>> +(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
>> +				      pgoff_t n, unsigned int *len)
> 
> Same as above.
> 
>>   {
>>   	struct scatterlist *sg;
>>   	unsigned int offset;
>> @@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>> -				unsigned long n)
>> +(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above.
> 
>>   {
>>   	return i915_gem_object_get_dma_address_len(obj, n, NULL);
>>   }
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index 7e1f8b83077f..50a02d850139 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
>>   	GEM_WARN_ON(bo->ttm);
>>   
>>   	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
>> -	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
>> +	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
>>   
>>   	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
>>   }
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> index c6ad67b90e8a..a18a890e681f 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> @@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
>>   static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>>   {
>>   	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
>> -	unsigned int n, m, need_flush;
>> +	unsigned int need_flush;
>> +	unsigned long n, m;
>>   	int err;
>>   
>>   	i915_gem_object_lock(obj, NULL);
>> @@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>>   static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   			      unsigned int idx, unsigned int max)
>>   {
>> -	unsigned int n, m, needs_flush;
>> +	unsigned int needs_flush;
>> +	unsigned long n;
>>   	int err;
>>   
>>   	i915_gem_object_lock(obj, NULL);
>> @@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   		goto out_unlock;
>>   
>>   	for (n = 0; n < real_page_count(obj); n++) {
>> -		u32 *map;
>> +		u32 *map, m;
>>   
>>   		map = kmap_atomic(i915_gem_object_get_page(obj, n));
>>   		if (needs_flush & CLFLUSH_BEFORE)
>> @@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   
>>   		for (m = 0; m < max; m++) {
>>   			if (map[m] != m) {
>> -				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
>> +				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
>>   				       __builtin_return_address(0), idx,
>>   				       n, real_page_count(obj), m, max,
>>   				       map[m], m);
>> @@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   
>>   		for (; m < DW_PER_PAGE; m++) {
>>   			if (map[m] != STACK_MAGIC) {
>> -				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
>> +				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
>>   				       __builtin_return_address(0), idx, n, m,
>>   				       map[m], STACK_MAGIC);
>>   				err = -EINVAL;
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> index 3ced9948a331..86e435d42546 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> @@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt_view view;
>>   	struct i915_vma *vma;
>> +	unsigned long offset;
>>   	unsigned long page;
>>   	u32 __iomem *io;
>>   	struct page *p;
>>   	unsigned int n;
>> -	u64 offset;
>>   	u32 *cpu;
>>   	int err;
>>   
>> @@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>>   	cpu = kmap(p) + offset_in_page(offset);
>>   	drm_clflush_virt_range(cpu, sizeof(*cpu));
>>   	if (*cpu != (u32)page) {
>> -		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
>> +		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>>   		       page, n,
>>   		       view.partial.offset,
>>   		       view.partial.size,
>> @@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>>   	for_each_prime_number_from(page, 1, npages) {
>>   		struct i915_ggtt_view view =
>>   			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
>> +		unsigned long offset;
>>   		u32 __iomem *io;
>>   		struct page *p;
>>   		unsigned int n;
>> -		u64 offset;
>>   		u32 *cpu;
>>   
>>   		GEM_BUG_ON(view.partial.size > nreal);
>> @@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>>   		cpu = kmap(p) + offset_in_page(offset);
>>   		drm_clflush_virt_range(cpu, sizeof(*cpu));
>>   		if (*cpu != (u32)page) {
>> -			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
>> +			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>>   			       page, n,
>>   			       view.partial.offset,
>>   			       view.partial.size,
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> index fe0a890775e2..bf30763ee6bc 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> @@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
>>   
>>   static int igt_gem_huge(void *arg)
>>   {
>> -	const unsigned int nreal = 509; /* just to be awkward */
>> +	const unsigned long nreal = 509; /* just to be awkward */
>>   	struct drm_i915_private *i915 = arg;
>>   	struct drm_i915_gem_object *obj;
>> -	unsigned int n;
>> +	unsigned long n;
>>   	int err;
>>   
>>   	/* Basic sanitycheck of our huge fake object allocation */
>> @@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
>>   
>>   	err = i915_gem_object_pin_pages_unlocked(obj);
>>   	if (err) {
>> -		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
>> +		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
>>   		       nreal, obj->base.size / PAGE_SIZE, err);
>>   		goto out;
>>   	}
>> @@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
>>   	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
>>   		if (i915_gem_object_get_page(obj, n) !=
>>   		    i915_gem_object_get_page(obj, n % nreal)) {
>> -			pr_err("Page lookup mismatch at index %u [%u]\n",
>> +			pr_err("Page lookup mismatch at index %lu [%lu]\n",
>>   			       n, n % nreal);
>>   			err = -EINVAL;
>>   			goto out_unpin;
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 702e5b89be22..dba58a3c3238 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
>>   		     struct drm_i915_gem_pread *args)
>>   {
>>   	unsigned int needs_clflush;
>> -	unsigned int idx, offset;
>>   	char __user *user_data;
>> +	unsigned long offset;
>> +	pgoff_t idx;
>>   	u64 remain;
>>   	int ret;
>>   
>> @@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
>>   {
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>> +	unsigned long remain, offset;
>>   	intel_wakeref_t wakeref;
>>   	struct drm_mm_node node;
>>   	void __user *user_data;
>>   	struct i915_vma *vma;
>> -	u64 remain, offset;
>>   	int ret = 0;
>>   
>> +	if (overflows_type(args->size, remain) ||
>> +	    overflows_type(args->offset, offset))
>> +		return -EINVAL;
>> +
>>   	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>>   
>>   	vma = i915_gem_gtt_prepare(obj, &node, false);
>> @@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>>   	struct intel_runtime_pm *rpm = &i915->runtime_pm;
>> +	unsigned long remain, offset;
>>   	intel_wakeref_t wakeref;
>>   	struct drm_mm_node node;
>>   	struct i915_vma *vma;
>> -	u64 remain, offset;
>>   	void __user *user_data;
>>   	int ret = 0;
>>   
>> +	if (overflows_type(args->size, remain) ||
>> +	    overflows_type(args->offset, offset))
>> +		return -EINVAL;
>> +
>>   	if (i915_gem_object_has_struct_page(obj)) {
>>   		/*
>>   		 * Avoid waking the device up if we can fallback, as
>> @@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
>>   {
>>   	unsigned int partial_cacheline_write;
>>   	unsigned int needs_clflush;
>> -	unsigned int offset, idx;
>>   	void __user *user_data;
>> +	unsigned long offset;
>> +	pgoff_t idx;
>>   	u64 remain;
>>   	int ret;
>>   
>> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
>> index ef3b04c7e153..28443c77b45a 100644
>> --- a/drivers/gpu/drm/i915/i915_vma.c
>> +++ b/drivers/gpu/drm/i915/i915_vma.c
>> @@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
>>   	     struct sg_table *st, struct scatterlist *sg)
>>   {
>>   	unsigned int column, row;
>> -	unsigned int src_idx;
>> +	pgoff_t src_idx;
>>   
>>   	for (column = 0; column < width; column++) {
>>   		unsigned int left;
>> @@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
>>   
>>   static struct scatterlist *
>>   remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>> -			      unsigned int offset, unsigned int alignment_pad,
>> +			      unsigned long offset, unsigned int alignment_pad,
>>   			      unsigned int width, unsigned int height,
>>   			      unsigned int src_stride, unsigned int dst_stride,
>>   			      struct sg_table *st, struct scatterlist *sg,
>> @@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>>   
>>   static struct scatterlist *
>>   remap_contiguous_pages(struct drm_i915_gem_object *obj,
>> -		       unsigned int obj_offset,
>> +		       pgoff_t obj_offset,
>>   		       unsigned int count,
>>   		       struct sg_table *st, struct scatterlist *sg)
>>   {
>> @@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
>>   
>>   static struct scatterlist *
>>   remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
>> -			       unsigned int obj_offset, unsigned int alignment_pad,
>> +			       pgoff_t obj_offset, unsigned int alignment_pad,
>>   			       unsigned int size,
>>   			       struct sg_table *st, struct scatterlist *sg,
>>   			       unsigned int *gtt_offset)
> 
> Once fixed the above nitpicks, feel free to add:
> 
> Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
@ 2022-07-06 16:33       ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-06 16:33 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
> On Tue,  5 Jul 2022 15:24:50 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> From: Chris Wilson <chris@chris-wilson.co.uk>
>>
>> We need to check that we avoid integer overflows when looking up a page,
>> and so fix all the instances where we have mistakenly used a plain
>> integer instead of a more suitable long. Be pedantic and add integer
>> typechecking to the lookup so that we can be sure that we are safe.
>> And it also uses pgoff_t as our page lookups must remain compatible with
>> the page cache, pgoff_t is currently exactly unsigned long.
>>
>> v2: Move added i915_utils's macro into drm_util header (Jani N)
>>
>> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>> Cc: Matthew Auld <matthew.auld@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
>> ---
>>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>>   drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>>   .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>>   .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>>   .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>>   drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>>   drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>>   9 files changed, 100 insertions(+), 55 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> index ccec4055fde3..90996fe8ad45 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>>   static void
>>   i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>   	void *src_map;
>>   	void *src_ptr;
>>   
>> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
>> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>>   
>>   	src_ptr = src_map + offset_in_page(offset);
>>   	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
>> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>>   static void
>>   i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>>   	void __iomem *src_map;
>>   	void __iomem *src_ptr;
>> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>>   
>>   	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>>   				    dma - obj->mm.region->region.start,
>> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>>    */
>>   int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>   {
>> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>>   	GEM_BUG_ON(offset >= obj->base.size);
>>   	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>>   	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index 6f0a3ce35567..a60c6f4517d5 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -27,8 +27,10 @@ enum intel_region_id;
>>    * 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
>> + * - sg_table embeds unsigned int for nents
>> + *
>> + * We can check for invalidly typed locals with typecheck(), see for example
>> + * i915_gem_object_get_sg().
>>    */
>>   #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>>   	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
>> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>>   struct scatterlist *
>>   __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>   			 struct i915_gem_object_page_iter *iter,
>> -			 unsigned int n,
>> -			 unsigned int *offset, bool dma);
>> +			 pgoff_t  n,
>> +			 unsigned int *offset);
>> +
>> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
>> +})
>>   
>>   static inline struct scatterlist *
>> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>> -		       unsigned int n,
>> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>>   		       unsigned int *offset)
>>   {
>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>>   }
>>   
>> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_sg)(obj, n, offset); \
>> +})
>> +
>>   static inline struct scatterlist *
>> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
>> -			   unsigned int n,
>> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>>   			   unsigned int *offset)
>>   {
>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>>   }
>>   
>> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
>> +})
>> +
>>   struct page *
>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
>> -			 unsigned int n);
>> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_page(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_page)(obj, n); \
>> +})
>>   
>>   struct page *
>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>> -			       unsigned int n);
>> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dirty_page)(obj, n); \
>> +})
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>> -				    unsigned long n,
>> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>>   				    unsigned int *len);
>>   
>> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
>> +})
>> +
>>   dma_addr_t
>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>> -				unsigned long n);
>> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
>> +
>> +#define i915_gem_object_get_dma_address(obj, n) ({ \
>> +	exactly_pgoff_t(n); \
>> +	(i915_gem_object_get_dma_address)(obj, n); \
>> +})
>>   
>>   void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>>   				 struct sg_table *pages,
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> index 97c820eee115..1d1edcb3514b 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>>   }
>>   
>>   struct scatterlist *
>> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>>   			 struct i915_gem_object_page_iter *iter,
>> -			 unsigned int n,
>> -			 unsigned int *offset,
>> -			 bool dma)
>> +			 pgoff_t n,
>> +			 unsigned int *offset)
>> +
> 
> Nitpick: no need to place the function name in parenthesis.
> 
>>   {
>> -	struct scatterlist *sg;
>> +	const bool dma = iter == &obj->mm.get_dma_page ||
>> +			 iter == &obj->ttm.get_io_page;
>>   	unsigned int idx, count;
>> +	struct scatterlist *sg;
>>   
>>   	might_sleep();
>>   	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
>> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   struct page *
>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above: why are you placing parenthesis at the function name here?
> Just use:
> 	
> 	struct page *
> 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
>
In this case, the macro and function have the same name. If parenthesis 
is not used, the following compile error occurs as the macro is applied 
to the c code.

./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected 
identifier or ‘(’ before ‘{’ token
   356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
       |                                                       ^
drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of 
macro ‘__i915_gem_object_get_sg’
   506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
       | ^~~~~~~~~~~~~~~~~~~~~~~~

And all of the parts you leave comments below are cases where the names 
of macros and functions are the same.

G.G.


>>   {
>>   	struct scatterlist *sg;
>>   	unsigned int offset;
>> @@ -631,8 +633,7 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>>   
>>   /* Like i915_gem_object_get_page(), but mark the returned page dirty */
>>   struct page *
>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>> -			       unsigned int n)
>> +(i915_gem_object_get_dirty_page)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above.
> 
>>   {
>>   	struct page *page;
>>   
>> @@ -644,9 +645,8 @@ i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>> -				    unsigned long n,
>> -				    unsigned int *len)
>> +(i915_gem_object_get_dma_address_len)(struct drm_i915_gem_object *obj,
>> +				      pgoff_t n, unsigned int *len)
> 
> Same as above.
> 
>>   {
>>   	struct scatterlist *sg;
>>   	unsigned int offset;
>> @@ -660,8 +660,7 @@ i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>>   }
>>   
>>   dma_addr_t
>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>> -				unsigned long n)
>> +(i915_gem_object_get_dma_address)(struct drm_i915_gem_object *obj, pgoff_t n)
> 
> Same as above.
> 
>>   {
>>   	return i915_gem_object_get_dma_address_len(obj, n, NULL);
>>   }
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index 7e1f8b83077f..50a02d850139 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -717,7 +717,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
>>   	GEM_WARN_ON(bo->ttm);
>>   
>>   	base = obj->mm.region->iomap.base - obj->mm.region->region.start;
>> -	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs, true);
>> +	sg = __i915_gem_object_get_sg(obj, &obj->ttm.get_io_page, page_offset, &ofs);
>>   
>>   	return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
>>   }
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> index c6ad67b90e8a..a18a890e681f 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
>> @@ -455,7 +455,8 @@ static int gpu_fill(struct intel_context *ce,
>>   static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>>   {
>>   	const bool has_llc = HAS_LLC(to_i915(obj->base.dev));
>> -	unsigned int n, m, need_flush;
>> +	unsigned int need_flush;
>> +	unsigned long n, m;
>>   	int err;
>>   
>>   	i915_gem_object_lock(obj, NULL);
>> @@ -485,7 +486,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value)
>>   static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   			      unsigned int idx, unsigned int max)
>>   {
>> -	unsigned int n, m, needs_flush;
>> +	unsigned int needs_flush;
>> +	unsigned long n;
>>   	int err;
>>   
>>   	i915_gem_object_lock(obj, NULL);
>> @@ -494,7 +496,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   		goto out_unlock;
>>   
>>   	for (n = 0; n < real_page_count(obj); n++) {
>> -		u32 *map;
>> +		u32 *map, m;
>>   
>>   		map = kmap_atomic(i915_gem_object_get_page(obj, n));
>>   		if (needs_flush & CLFLUSH_BEFORE)
>> @@ -502,7 +504,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   
>>   		for (m = 0; m < max; m++) {
>>   			if (map[m] != m) {
>> -				pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n",
>> +				pr_err("%pS: Invalid value at object %d page %ld/%ld, offset %d/%d: found %x expected %x\n",
>>   				       __builtin_return_address(0), idx,
>>   				       n, real_page_count(obj), m, max,
>>   				       map[m], m);
>> @@ -513,7 +515,7 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj,
>>   
>>   		for (; m < DW_PER_PAGE; m++) {
>>   			if (map[m] != STACK_MAGIC) {
>> -				pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n",
>> +				pr_err("%pS: Invalid value at object %d page %ld, offset %d: found %x expected %x (uninitialised)\n",
>>   				       __builtin_return_address(0), idx, n, m,
>>   				       map[m], STACK_MAGIC);
>>   				err = -EINVAL;
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> index 3ced9948a331..86e435d42546 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
>> @@ -95,11 +95,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt_view view;
>>   	struct i915_vma *vma;
>> +	unsigned long offset;
>>   	unsigned long page;
>>   	u32 __iomem *io;
>>   	struct page *p;
>>   	unsigned int n;
>> -	u64 offset;
>>   	u32 *cpu;
>>   	int err;
>>   
>> @@ -156,7 +156,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj,
>>   	cpu = kmap(p) + offset_in_page(offset);
>>   	drm_clflush_virt_range(cpu, sizeof(*cpu));
>>   	if (*cpu != (u32)page) {
>> -		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
>> +		pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>>   		       page, n,
>>   		       view.partial.offset,
>>   		       view.partial.size,
>> @@ -212,10 +212,10 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>>   	for_each_prime_number_from(page, 1, npages) {
>>   		struct i915_ggtt_view view =
>>   			compute_partial_view(obj, page, MIN_CHUNK_PAGES);
>> +		unsigned long offset;
>>   		u32 __iomem *io;
>>   		struct page *p;
>>   		unsigned int n;
>> -		u64 offset;
>>   		u32 *cpu;
>>   
>>   		GEM_BUG_ON(view.partial.size > nreal);
>> @@ -252,7 +252,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj,
>>   		cpu = kmap(p) + offset_in_page(offset);
>>   		drm_clflush_virt_range(cpu, sizeof(*cpu));
>>   		if (*cpu != (u32)page) {
>> -			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%llu + %u [0x%llx]) of 0x%x, found 0x%x\n",
>> +			pr_err("Partial view for %lu [%u] (offset=%llu, size=%u [%llu, row size %u], fence=%d, tiling=%d, stride=%d) misalignment, expected write to page (%lu + %u [0x%lx]) of 0x%x, found 0x%x\n",
>>   			       page, n,
>>   			       view.partial.offset,
>>   			       view.partial.size,
>> diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> index fe0a890775e2..bf30763ee6bc 100644
>> --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c
>> @@ -33,10 +33,10 @@ static int igt_gem_object(void *arg)
>>   
>>   static int igt_gem_huge(void *arg)
>>   {
>> -	const unsigned int nreal = 509; /* just to be awkward */
>> +	const unsigned long nreal = 509; /* just to be awkward */
>>   	struct drm_i915_private *i915 = arg;
>>   	struct drm_i915_gem_object *obj;
>> -	unsigned int n;
>> +	unsigned long n;
>>   	int err;
>>   
>>   	/* Basic sanitycheck of our huge fake object allocation */
>> @@ -49,7 +49,7 @@ static int igt_gem_huge(void *arg)
>>   
>>   	err = i915_gem_object_pin_pages_unlocked(obj);
>>   	if (err) {
>> -		pr_err("Failed to allocate %u pages (%lu total), err=%d\n",
>> +		pr_err("Failed to allocate %lu pages (%lu total), err=%d\n",
>>   		       nreal, obj->base.size / PAGE_SIZE, err);
>>   		goto out;
>>   	}
>> @@ -57,7 +57,7 @@ static int igt_gem_huge(void *arg)
>>   	for (n = 0; n < obj->base.size / PAGE_SIZE; n++) {
>>   		if (i915_gem_object_get_page(obj, n) !=
>>   		    i915_gem_object_get_page(obj, n % nreal)) {
>> -			pr_err("Page lookup mismatch at index %u [%u]\n",
>> +			pr_err("Page lookup mismatch at index %lu [%lu]\n",
>>   			       n, n % nreal);
>>   			err = -EINVAL;
>>   			goto out_unpin;
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 702e5b89be22..dba58a3c3238 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -229,8 +229,9 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
>>   		     struct drm_i915_gem_pread *args)
>>   {
>>   	unsigned int needs_clflush;
>> -	unsigned int idx, offset;
>>   	char __user *user_data;
>> +	unsigned long offset;
>> +	pgoff_t idx;
>>   	u64 remain;
>>   	int ret;
>>   
>> @@ -383,13 +384,17 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
>>   {
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>> +	unsigned long remain, offset;
>>   	intel_wakeref_t wakeref;
>>   	struct drm_mm_node node;
>>   	void __user *user_data;
>>   	struct i915_vma *vma;
>> -	u64 remain, offset;
>>   	int ret = 0;
>>   
>> +	if (overflows_type(args->size, remain) ||
>> +	    overflows_type(args->offset, offset))
>> +		return -EINVAL;
>> +
>>   	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>>   
>>   	vma = i915_gem_gtt_prepare(obj, &node, false);
>> @@ -540,13 +545,17 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
>>   	struct drm_i915_private *i915 = to_i915(obj->base.dev);
>>   	struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
>>   	struct intel_runtime_pm *rpm = &i915->runtime_pm;
>> +	unsigned long remain, offset;
>>   	intel_wakeref_t wakeref;
>>   	struct drm_mm_node node;
>>   	struct i915_vma *vma;
>> -	u64 remain, offset;
>>   	void __user *user_data;
>>   	int ret = 0;
>>   
>> +	if (overflows_type(args->size, remain) ||
>> +	    overflows_type(args->offset, offset))
>> +		return -EINVAL;
>> +
>>   	if (i915_gem_object_has_struct_page(obj)) {
>>   		/*
>>   		 * Avoid waking the device up if we can fallback, as
>> @@ -654,8 +663,9 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
>>   {
>>   	unsigned int partial_cacheline_write;
>>   	unsigned int needs_clflush;
>> -	unsigned int offset, idx;
>>   	void __user *user_data;
>> +	unsigned long offset;
>> +	pgoff_t idx;
>>   	u64 remain;
>>   	int ret;
>>   
>> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
>> index ef3b04c7e153..28443c77b45a 100644
>> --- a/drivers/gpu/drm/i915/i915_vma.c
>> +++ b/drivers/gpu/drm/i915/i915_vma.c
>> @@ -911,7 +911,7 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
>>   	     struct sg_table *st, struct scatterlist *sg)
>>   {
>>   	unsigned int column, row;
>> -	unsigned int src_idx;
>> +	pgoff_t src_idx;
>>   
>>   	for (column = 0; column < width; column++) {
>>   		unsigned int left;
>> @@ -1017,7 +1017,7 @@ add_padding_pages(unsigned int count,
>>   
>>   static struct scatterlist *
>>   remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>> -			      unsigned int offset, unsigned int alignment_pad,
>> +			      unsigned long offset, unsigned int alignment_pad,
>>   			      unsigned int width, unsigned int height,
>>   			      unsigned int src_stride, unsigned int dst_stride,
>>   			      struct sg_table *st, struct scatterlist *sg,
>> @@ -1076,7 +1076,7 @@ remap_tiled_color_plane_pages(struct drm_i915_gem_object *obj,
>>   
>>   static struct scatterlist *
>>   remap_contiguous_pages(struct drm_i915_gem_object *obj,
>> -		       unsigned int obj_offset,
>> +		       pgoff_t obj_offset,
>>   		       unsigned int count,
>>   		       struct sg_table *st, struct scatterlist *sg)
>>   {
>> @@ -1109,7 +1109,7 @@ remap_contiguous_pages(struct drm_i915_gem_object *obj,
>>   
>>   static struct scatterlist *
>>   remap_linear_color_plane_pages(struct drm_i915_gem_object *obj,
>> -			       unsigned int obj_offset, unsigned int alignment_pad,
>> +			       pgoff_t obj_offset, unsigned int alignment_pad,
>>   			       unsigned int size,
>>   			       struct sg_table *st, struct scatterlist *sg,
>>   			       unsigned int *gtt_offset)
> 
> Once fixed the above nitpicks, feel free to add:
> 
> Reviewed-by: Mauro Carvalho Chehab <mchehab@kernel.org>
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
  2022-07-06 15:04       ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-06 17:05         ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-06 17:05 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Wed, 6 Jul 2022 18:04:20 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
> > On Tue,  5 Jul 2022 15:24:49 +0300
> > Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> >   
> >> It moves overflows_type utility macro into drm util header from i915_utils
> >> header. The overflows_type can be used to catch the truncation between data
> >> types. And it adds safe_conversion() macro which performs a type conversion
> >> (cast) of an source value into a new variable, checking that the
> >> destination is large enough to hold the source value.
> >> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
> >> while compiling.
> >>
> >> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> >> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >> Cc: Matthew Auld <matthew.auld@intel.com>
> >> Cc: Nirmoy Das <nirmoy.das@intel.com>
> >> Cc: Jani Nikula <jani.nikula@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/i915_utils.h |  5 +--
> >>   include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
> >>   2 files changed, 55 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
> >> index c10d68cdc3ca..345e5b2dc1cd 100644
> >> --- a/drivers/gpu/drm/i915/i915_utils.h
> >> +++ b/drivers/gpu/drm/i915/i915_utils.h
> >> @@ -32,6 +32,7 @@
> >>   #include <linux/types.h>
> >>   #include <linux/workqueue.h>
> >>   #include <linux/sched/clock.h>
> >> +#include <drm/drm_util.h>
> >>   
> >>   #ifdef CONFIG_X86
> >>   #include <asm/hypervisor.h>
> >> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
> >>   #define range_overflows_end_t(type, start, size, max) \
> >>   	range_overflows_end((type)(start), (type)(size), (type)(max))
> >>   
> >> -/* Note we don't consider signbits :| */
> >> -#define overflows_type(x, T) \
> >> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> >> -
> >>   #define ptr_mask_bits(ptr, n) ({					\
> >>   	unsigned long __v = (unsigned long)(ptr);			\
> >>   	(typeof(ptr))(__v & -BIT(n));					\
> >> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
> >> index 79952d8c4bba..c56230e39e37 100644
> >> --- a/include/drm/drm_util.h
> >> +++ b/include/drm/drm_util.h
> >> @@ -62,6 +62,60 @@
> >>    */
> >>   #define for_each_if(condition) if (!(condition)) {} else
> >>   
> >> +/**
> >> + * overflows_type - helper for checking the truncation between data types
> >> + * @x: Source for overflow type comparison
> >> + * @T: Destination for overflow type comparison
> >> + *
> >> + * It compares the values and size of each data type between the first and
> >> + * second argument to check whether truncation can occur when assigning the
> >> + * first argument to the variable of the second argument.
> >> + * It does't consider signbits.
> >> + *
> >> + * Returns:
> >> + * True if truncation can occur, false otherwise.
> >> + */
> >> +#define overflows_type(x, T) \
> >> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) 
> > 
> > As pointed on its description, this macro only works if both types
> > are either signed or unsigned. However, the macro itself doesn't check
> > it.
> > 
> > It probably worth adding something there to ensure that both types are
> > either signed or unsigned. I would add this ancillary macro probably on
> > on a generic kernel header - as this can be useful outside drm:
> > 
> > 	#define sign_matches(x, y) \
> > 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> > 
> > And then include use it at overflows_type:
> > 
> > 	BUILD_BUG_ON(!sign_matches(x, T))
> >   
> Hi Mauro, thanks for checking it.
> 
> What you commented here (sign_matches macro) is to check whether the 
> sign bits of two types are the same,  but the purpose of the 
> overflows_type() macro checks overflows while assigning a variable with 
> a large data size (BITS_PER_TYPE is large) to a variable with a small 
> data size (BITS_PER_TYPE is small).

True, but the problem is that such macro just assumes that either both
are signed or unsigned without actually checking it.

Basically, if one tries to store for instance a s32 value on an u64 var,
the value won't be stored correctly, due to an underflow. As the hole
idea of this macro is to exactly detect if the "container" variable
is big enough to properly represent the measure, it sounds incomplete
to not handle the integer signal.

Btw, after reviewing all patches, using BUILD_BUG_ON() is not needed
here, as such macro (or similar) is already used at the callers code.

So, I would just return false if the signals are incompatible, e. g. 
if the type of the source value is signed and the type of the 
destination value is unsigned.

So:

#define overflows_type(x, T) \
	(!signal_matches(x,T) || (sizeof(x) > sizeof(T)))

Should do the trick[1]. 

[1] using BITS_PER_TYPE() macro is not really needed, as this is
    defined as:

	#define BITS_PER_BYTE              8
	#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)

    So, checking if sizeof(x) > sizeof(T) is enough. Btw, the check
    there seems to be inverted, making the macro to always return zero!

Yet, strictly speaking, it is possible to store an unsigned value on a 
signed type, if the signed type is bigger than the size of unsigned
(so, a s64 int can store u32, but a s32 can't store u32).

Adding a check that would consider this should be like:

	#define is_type_unsigned(x) ((typeof(x))-1 >= 0) 
	#define is_type_signed(x) (!is_type_unsigned(x)) 
	#define overflows_type(x, T)							 \
	(										 \
		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
		(sizeof(x) > sizeof(T))							 \
	) 	

This should be generic enough to be used anywhere.

> we can check the additional sign bit by adding sign_matches() to the 
> overflows_type() macro, but in the current scenario, it is used only 
> when the sign bit is the same.

Yeah, but "current scenarios" can easily be extended to something
else, quickly going sideways specially on a subsystem-wide macro. 
Also, getting this right is particularly tricky when comparing typedef
integers. So, I would be more comfortable if the logic will also
check the signal at the destination variable.

> Should the macro be extended even for cases where the sign bit is 
> different in the current state? (If yes, I'll updated it as v3)
> 
> In addition, the place where this macro is currently used is only in the 
> i915 driver, so it has been moved to the header of the drm subsystem.
> IMHO, moving the macro location so that it can be used by multiple 
> subsystems of linux would be a good idea when there is a use case for 
> this macro. What do you think?

Good point. Yeah, it can stay there while not needed outside drm.

Btw, in order to get it right, I suggest double-checking in userspace
how each macros are evaluated, like using the code below.

It helps to check if the logic is doing what's expected or not.

----

#include <stdio.h>
#include <stdint.h>

// Kernel definitions from bits.h and bitops.h
#define BITS_PER_BYTE              8
#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)

#define sign_matches(x, y) \
	(!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))

#define is_type_unsigned(x) ((typeof(x))-1 >= 0)
#define is_type_signed(x) (!is_type_unsigned(x))

#define overflows_type(x, T)								 \
	(										 \
		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
		(sizeof(x) > sizeof(T))							 \
	) ? "OVERFLOW" : "don't overflow"

int main(void)
{
	uint32_t	u32_1 = 0, u32_2 = 0;
	int32_t		s32_1 = 0, s32_2 = 0;
	uint64_t	u64_1 = 0, u64_2 = 0;
	int64_t		s64_1 = 0, s64_2 = 0;

	printf("u32 stored into u32: %s\n", overflows_type(u32_1, u32_2));
	printf("u64 stored into u32: %s\n", overflows_type(u64_1, u32_2));
	printf("s32 stored into u32: %s\n", overflows_type(s32_1, u32_2));
	printf("s64 stored into u32: %s\n", overflows_type(s64_1, u32_2));

	printf("u32 stored into s32: %s\n", overflows_type(u32_1, s32_2));
	printf("u64 stored into s32: %s\n", overflows_type(u64_1, s32_2));
	printf("s32 stored into s32: %s\n", overflows_type(s32_1, s32_2));
	printf("s64 stored into s32: %s\n", overflows_type(s64_1, s32_2));

	printf("u32 stored into u64: %s\n", overflows_type(u32_1, u64_2));
	printf("u64 stored into u64: %s\n", overflows_type(u64_1, u64_2));
	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));

	printf("u32 stored into s64: %s\n", overflows_type(u32_1, s64_2));
	printf("u64 stored into s64: %s\n", overflows_type(u64_1, s64_2));
	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));

	// Shutup warnings
	s64_1 = u32_1 + u32_2 + s64_2 + s32_1 + s32_2 + u64_1 + u64_2;

	return 0;
}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
@ 2022-07-06 17:05         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-06 17:05 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Wed, 6 Jul 2022 18:04:20 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
> > On Tue,  5 Jul 2022 15:24:49 +0300
> > Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> >   
> >> It moves overflows_type utility macro into drm util header from i915_utils
> >> header. The overflows_type can be used to catch the truncation between data
> >> types. And it adds safe_conversion() macro which performs a type conversion
> >> (cast) of an source value into a new variable, checking that the
> >> destination is large enough to hold the source value.
> >> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
> >> while compiling.
> >>
> >> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> >> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >> Cc: Matthew Auld <matthew.auld@intel.com>
> >> Cc: Nirmoy Das <nirmoy.das@intel.com>
> >> Cc: Jani Nikula <jani.nikula@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/i915_utils.h |  5 +--
> >>   include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
> >>   2 files changed, 55 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
> >> index c10d68cdc3ca..345e5b2dc1cd 100644
> >> --- a/drivers/gpu/drm/i915/i915_utils.h
> >> +++ b/drivers/gpu/drm/i915/i915_utils.h
> >> @@ -32,6 +32,7 @@
> >>   #include <linux/types.h>
> >>   #include <linux/workqueue.h>
> >>   #include <linux/sched/clock.h>
> >> +#include <drm/drm_util.h>
> >>   
> >>   #ifdef CONFIG_X86
> >>   #include <asm/hypervisor.h>
> >> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
> >>   #define range_overflows_end_t(type, start, size, max) \
> >>   	range_overflows_end((type)(start), (type)(size), (type)(max))
> >>   
> >> -/* Note we don't consider signbits :| */
> >> -#define overflows_type(x, T) \
> >> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
> >> -
> >>   #define ptr_mask_bits(ptr, n) ({					\
> >>   	unsigned long __v = (unsigned long)(ptr);			\
> >>   	(typeof(ptr))(__v & -BIT(n));					\
> >> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
> >> index 79952d8c4bba..c56230e39e37 100644
> >> --- a/include/drm/drm_util.h
> >> +++ b/include/drm/drm_util.h
> >> @@ -62,6 +62,60 @@
> >>    */
> >>   #define for_each_if(condition) if (!(condition)) {} else
> >>   
> >> +/**
> >> + * overflows_type - helper for checking the truncation between data types
> >> + * @x: Source for overflow type comparison
> >> + * @T: Destination for overflow type comparison
> >> + *
> >> + * It compares the values and size of each data type between the first and
> >> + * second argument to check whether truncation can occur when assigning the
> >> + * first argument to the variable of the second argument.
> >> + * It does't consider signbits.
> >> + *
> >> + * Returns:
> >> + * True if truncation can occur, false otherwise.
> >> + */
> >> +#define overflows_type(x, T) \
> >> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) 
> > 
> > As pointed on its description, this macro only works if both types
> > are either signed or unsigned. However, the macro itself doesn't check
> > it.
> > 
> > It probably worth adding something there to ensure that both types are
> > either signed or unsigned. I would add this ancillary macro probably on
> > on a generic kernel header - as this can be useful outside drm:
> > 
> > 	#define sign_matches(x, y) \
> > 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> > 
> > And then include use it at overflows_type:
> > 
> > 	BUILD_BUG_ON(!sign_matches(x, T))
> >   
> Hi Mauro, thanks for checking it.
> 
> What you commented here (sign_matches macro) is to check whether the 
> sign bits of two types are the same,  but the purpose of the 
> overflows_type() macro checks overflows while assigning a variable with 
> a large data size (BITS_PER_TYPE is large) to a variable with a small 
> data size (BITS_PER_TYPE is small).

True, but the problem is that such macro just assumes that either both
are signed or unsigned without actually checking it.

Basically, if one tries to store for instance a s32 value on an u64 var,
the value won't be stored correctly, due to an underflow. As the hole
idea of this macro is to exactly detect if the "container" variable
is big enough to properly represent the measure, it sounds incomplete
to not handle the integer signal.

Btw, after reviewing all patches, using BUILD_BUG_ON() is not needed
here, as such macro (or similar) is already used at the callers code.

So, I would just return false if the signals are incompatible, e. g. 
if the type of the source value is signed and the type of the 
destination value is unsigned.

So:

#define overflows_type(x, T) \
	(!signal_matches(x,T) || (sizeof(x) > sizeof(T)))

Should do the trick[1]. 

[1] using BITS_PER_TYPE() macro is not really needed, as this is
    defined as:

	#define BITS_PER_BYTE              8
	#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)

    So, checking if sizeof(x) > sizeof(T) is enough. Btw, the check
    there seems to be inverted, making the macro to always return zero!

Yet, strictly speaking, it is possible to store an unsigned value on a 
signed type, if the signed type is bigger than the size of unsigned
(so, a s64 int can store u32, but a s32 can't store u32).

Adding a check that would consider this should be like:

	#define is_type_unsigned(x) ((typeof(x))-1 >= 0) 
	#define is_type_signed(x) (!is_type_unsigned(x)) 
	#define overflows_type(x, T)							 \
	(										 \
		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
		(sizeof(x) > sizeof(T))							 \
	) 	

This should be generic enough to be used anywhere.

> we can check the additional sign bit by adding sign_matches() to the 
> overflows_type() macro, but in the current scenario, it is used only 
> when the sign bit is the same.

Yeah, but "current scenarios" can easily be extended to something
else, quickly going sideways specially on a subsystem-wide macro. 
Also, getting this right is particularly tricky when comparing typedef
integers. So, I would be more comfortable if the logic will also
check the signal at the destination variable.

> Should the macro be extended even for cases where the sign bit is 
> different in the current state? (If yes, I'll updated it as v3)
> 
> In addition, the place where this macro is currently used is only in the 
> i915 driver, so it has been moved to the header of the drm subsystem.
> IMHO, moving the macro location so that it can be used by multiple 
> subsystems of linux would be a good idea when there is a use case for 
> this macro. What do you think?

Good point. Yeah, it can stay there while not needed outside drm.

Btw, in order to get it right, I suggest double-checking in userspace
how each macros are evaluated, like using the code below.

It helps to check if the logic is doing what's expected or not.

----

#include <stdio.h>
#include <stdint.h>

// Kernel definitions from bits.h and bitops.h
#define BITS_PER_BYTE              8
#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)

#define sign_matches(x, y) \
	(!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))

#define is_type_unsigned(x) ((typeof(x))-1 >= 0)
#define is_type_signed(x) (!is_type_unsigned(x))

#define overflows_type(x, T)								 \
	(										 \
		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
		(sizeof(x) > sizeof(T))							 \
	) ? "OVERFLOW" : "don't overflow"

int main(void)
{
	uint32_t	u32_1 = 0, u32_2 = 0;
	int32_t		s32_1 = 0, s32_2 = 0;
	uint64_t	u64_1 = 0, u64_2 = 0;
	int64_t		s64_1 = 0, s64_2 = 0;

	printf("u32 stored into u32: %s\n", overflows_type(u32_1, u32_2));
	printf("u64 stored into u32: %s\n", overflows_type(u64_1, u32_2));
	printf("s32 stored into u32: %s\n", overflows_type(s32_1, u32_2));
	printf("s64 stored into u32: %s\n", overflows_type(s64_1, u32_2));

	printf("u32 stored into s32: %s\n", overflows_type(u32_1, s32_2));
	printf("u64 stored into s32: %s\n", overflows_type(u64_1, s32_2));
	printf("s32 stored into s32: %s\n", overflows_type(s32_1, s32_2));
	printf("s64 stored into s32: %s\n", overflows_type(s64_1, s32_2));

	printf("u32 stored into u64: %s\n", overflows_type(u32_1, u64_2));
	printf("u64 stored into u64: %s\n", overflows_type(u64_1, u64_2));
	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));

	printf("u32 stored into s64: %s\n", overflows_type(u32_1, s64_2));
	printf("u64 stored into s64: %s\n", overflows_type(u64_1, s64_2));
	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));

	// Shutup warnings
	s64_1 = u32_1 + u32_2 + s64_2 + s32_1 + s32_2 + u64_1 + u64_2;

	return 0;
}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
  2022-07-06 16:33       ` [Intel-gfx] " Gwan-gyeong Mun
@ 2022-07-06 17:10         ` Mauro Carvalho Chehab
  -1 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-06 17:10 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Wed, 6 Jul 2022 19:33:22 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
> > On Tue,  5 Jul 2022 15:24:50 +0300
> > Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> >   
> >> From: Chris Wilson <chris@chris-wilson.co.uk>
> >>
> >> We need to check that we avoid integer overflows when looking up a page,
> >> and so fix all the instances where we have mistakenly used a plain
> >> integer instead of a more suitable long. Be pedantic and add integer
> >> typechecking to the lookup so that we can be sure that we are safe.
> >> And it also uses pgoff_t as our page lookups must remain compatible with
> >> the page cache, pgoff_t is currently exactly unsigned long.
> >>
> >> v2: Move added i915_utils's macro into drm_util header (Jani N)
> >>
> >> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> >> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> >> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> >> Cc: Matthew Auld <matthew.auld@intel.com>
> >> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
> >>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
> >>   drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
> >>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
> >>   .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
> >>   .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
> >>   .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
> >>   drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
> >>   drivers/gpu/drm/i915/i915_vma.c               |  8 +--
> >>   9 files changed, 100 insertions(+), 55 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> index ccec4055fde3..90996fe8ad45 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
> >>   static void
> >>   i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	pgoff_t idx = offset >> PAGE_SHIFT;
> >>   	void *src_map;
> >>   	void *src_ptr;
> >>   
> >> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
> >> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
> >>   
> >>   	src_ptr = src_map + offset_in_page(offset);
> >>   	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
> >> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
> >>   static void
> >>   i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	pgoff_t idx = offset >> PAGE_SHIFT;
> >> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
> >>   	void __iomem *src_map;
> >>   	void __iomem *src_ptr;
> >> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
> >>   
> >>   	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
> >>   				    dma - obj->mm.region->region.start,
> >> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
> >>    */
> >>   int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
> >>   	GEM_BUG_ON(offset >= obj->base.size);
> >>   	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
> >>   	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> index 6f0a3ce35567..a60c6f4517d5 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> @@ -27,8 +27,10 @@ enum intel_region_id;
> >>    * 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
> >> + * - sg_table embeds unsigned int for nents
> >> + *
> >> + * We can check for invalidly typed locals with typecheck(), see for example
> >> + * i915_gem_object_get_sg().
> >>    */
> >>   #define GEM_CHECK_SIZE_OVERFLOW(sz) \
> >>   	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> >> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
> >>   struct scatterlist *
> >>   __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >>   			 struct i915_gem_object_page_iter *iter,
> >> -			 unsigned int n,
> >> -			 unsigned int *offset, bool dma);
> >> +			 pgoff_t  n,
> >> +			 unsigned int *offset);
> >> +
> >> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
> >> +})
> >>   
> >>   static inline struct scatterlist *
> >> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >> -		       unsigned int n,
> >> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   		       unsigned int *offset)
> >>   {
> >> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
> >> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
> >>   }
> >>   
> >> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_sg)(obj, n, offset); \
> >> +})
> >> +
> >>   static inline struct scatterlist *
> >> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
> >> -			   unsigned int n,
> >> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   			   unsigned int *offset)
> >>   {
> >> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
> >> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
> >>   }
> >>   
> >> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
> >> +})
> >> +
> >>   struct page *
> >> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
> >> -			 unsigned int n);
> >> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_page(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_page)(obj, n); \
> >> +})
> >>   
> >>   struct page *
> >> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> >> -			       unsigned int n);
> >> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dirty_page)(obj, n); \
> >> +})
> >>   
> >>   dma_addr_t
> >> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> >> -				    unsigned long n,
> >> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   				    unsigned int *len);
> >>   
> >> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
> >> +})
> >> +
> >>   dma_addr_t
> >> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> >> -				unsigned long n);
> >> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_dma_address(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dma_address)(obj, n); \
> >> +})
> >>   
> >>   void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
> >>   				 struct sg_table *pages,
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> index 97c820eee115..1d1edcb3514b 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
> >>   }
> >>   
> >>   struct scatterlist *
> >> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
> >>   			 struct i915_gem_object_page_iter *iter,
> >> -			 unsigned int n,
> >> -			 unsigned int *offset,
> >> -			 bool dma)
> >> +			 pgoff_t n,
> >> +			 unsigned int *offset)
> >> +  
> > 
> > Nitpick: no need to place the function name in parenthesis.
> >   
> >>   {
> >> -	struct scatterlist *sg;
> >> +	const bool dma = iter == &obj->mm.get_dma_page ||
> >> +			 iter == &obj->ttm.get_io_page;
> >>   	unsigned int idx, count;
> >> +	struct scatterlist *sg;
> >>   
> >>   	might_sleep();
> >>   	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
> >> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >>   }
> >>   
> >>   struct page *
> >> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
> >> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)  
> > 
> > Same as above: why are you placing parenthesis at the function name here?
> > Just use:
> > 	
> > 	struct page *
> > 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
> >  
> In this case, the macro and function have the same name. If parenthesis 
> is not used, the following compile error occurs as the macro is applied 
> to the c code.
> 
> ./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected 
> identifier or ‘(’ before ‘{’ token
>    356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>        |                                                       ^
> drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of 
> macro ‘__i915_gem_object_get_sg’
>    506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>        | ^~~~~~~~~~~~~~~~~~~~~~~~
> 
> And all of the parts you leave comments below are cases where the names 
> of macros and functions are the same.

Don't use the same macro name on a function. This is very confusing
and will prevent ever adding documentation for it, as, for kernel-doc,
macros and functions are handled at the same namespace. So, no
duplication is allowed.

Probably the best here would be to replace the macros by inlined
functions.

Regards,
Mauro


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
@ 2022-07-06 17:10         ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 45+ messages in thread
From: Mauro Carvalho Chehab @ 2022-07-06 17:10 UTC (permalink / raw)
  To: Gwan-gyeong Mun
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das

On Wed, 6 Jul 2022 19:33:22 +0300
Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:

> On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
> > On Tue,  5 Jul 2022 15:24:50 +0300
> > Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> >   
> >> From: Chris Wilson <chris@chris-wilson.co.uk>
> >>
> >> We need to check that we avoid integer overflows when looking up a page,
> >> and so fix all the instances where we have mistakenly used a plain
> >> integer instead of a more suitable long. Be pedantic and add integer
> >> typechecking to the lookup so that we can be sure that we are safe.
> >> And it also uses pgoff_t as our page lookups must remain compatible with
> >> the page cache, pgoff_t is currently exactly unsigned long.
> >>
> >> v2: Move added i915_utils's macro into drm_util header (Jani N)
> >>
> >> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> >> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> >> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> >> Cc: Matthew Auld <matthew.auld@intel.com>
> >> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> >> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
> >>   drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
> >>   drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
> >>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
> >>   .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
> >>   .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
> >>   .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
> >>   drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
> >>   drivers/gpu/drm/i915/i915_vma.c               |  8 +--
> >>   9 files changed, 100 insertions(+), 55 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> index ccec4055fde3..90996fe8ad45 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
> >> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
> >>   static void
> >>   i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	pgoff_t idx = offset >> PAGE_SHIFT;
> >>   	void *src_map;
> >>   	void *src_ptr;
> >>   
> >> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
> >> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
> >>   
> >>   	src_ptr = src_map + offset_in_page(offset);
> >>   	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
> >> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
> >>   static void
> >>   i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	pgoff_t idx = offset >> PAGE_SHIFT;
> >> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
> >>   	void __iomem *src_map;
> >>   	void __iomem *src_ptr;
> >> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
> >>   
> >>   	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
> >>   				    dma - obj->mm.region->region.start,
> >> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
> >>    */
> >>   int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
> >>   {
> >> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
> >>   	GEM_BUG_ON(offset >= obj->base.size);
> >>   	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
> >>   	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> index 6f0a3ce35567..a60c6f4517d5 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
> >> @@ -27,8 +27,10 @@ enum intel_region_id;
> >>    * 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
> >> + * - sg_table embeds unsigned int for nents
> >> + *
> >> + * We can check for invalidly typed locals with typecheck(), see for example
> >> + * i915_gem_object_get_sg().
> >>    */
> >>   #define GEM_CHECK_SIZE_OVERFLOW(sz) \
> >>   	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
> >> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
> >>   struct scatterlist *
> >>   __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >>   			 struct i915_gem_object_page_iter *iter,
> >> -			 unsigned int n,
> >> -			 unsigned int *offset, bool dma);
> >> +			 pgoff_t  n,
> >> +			 unsigned int *offset);
> >> +
> >> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
> >> +})
> >>   
> >>   static inline struct scatterlist *
> >> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >> -		       unsigned int n,
> >> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   		       unsigned int *offset)
> >>   {
> >> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
> >> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
> >>   }
> >>   
> >> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_sg)(obj, n, offset); \
> >> +})
> >> +
> >>   static inline struct scatterlist *
> >> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
> >> -			   unsigned int n,
> >> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   			   unsigned int *offset)
> >>   {
> >> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
> >> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
> >>   }
> >>   
> >> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
> >> +})
> >> +
> >>   struct page *
> >> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
> >> -			 unsigned int n);
> >> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_page(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_page)(obj, n); \
> >> +})
> >>   
> >>   struct page *
> >> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
> >> -			       unsigned int n);
> >> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dirty_page)(obj, n); \
> >> +})
> >>   
> >>   dma_addr_t
> >> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
> >> -				    unsigned long n,
> >> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
> >>   				    unsigned int *len);
> >>   
> >> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
> >> +})
> >> +
> >>   dma_addr_t
> >> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
> >> -				unsigned long n);
> >> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
> >> +
> >> +#define i915_gem_object_get_dma_address(obj, n) ({ \
> >> +	exactly_pgoff_t(n); \
> >> +	(i915_gem_object_get_dma_address)(obj, n); \
> >> +})
> >>   
> >>   void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
> >>   				 struct sg_table *pages,
> >> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> index 97c820eee115..1d1edcb3514b 100644
> >> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
> >> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
> >>   }
> >>   
> >>   struct scatterlist *
> >> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
> >>   			 struct i915_gem_object_page_iter *iter,
> >> -			 unsigned int n,
> >> -			 unsigned int *offset,
> >> -			 bool dma)
> >> +			 pgoff_t n,
> >> +			 unsigned int *offset)
> >> +  
> > 
> > Nitpick: no need to place the function name in parenthesis.
> >   
> >>   {
> >> -	struct scatterlist *sg;
> >> +	const bool dma = iter == &obj->mm.get_dma_page ||
> >> +			 iter == &obj->ttm.get_io_page;
> >>   	unsigned int idx, count;
> >> +	struct scatterlist *sg;
> >>   
> >>   	might_sleep();
> >>   	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
> >> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
> >>   }
> >>   
> >>   struct page *
> >> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
> >> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)  
> > 
> > Same as above: why are you placing parenthesis at the function name here?
> > Just use:
> > 	
> > 	struct page *
> > 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
> >  
> In this case, the macro and function have the same name. If parenthesis 
> is not used, the following compile error occurs as the macro is applied 
> to the c code.
> 
> ./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected 
> identifier or ‘(’ before ‘{’ token
>    356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>        |                                                       ^
> drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of 
> macro ‘__i915_gem_object_get_sg’
>    506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>        | ^~~~~~~~~~~~~~~~~~~~~~~~
> 
> And all of the parts you leave comments below are cases where the names 
> of macros and functions are the same.

Don't use the same macro name on a function. This is very confusing
and will prevent ever adding documentation for it, as, for kernel-doc,
macros and functions are handled at the same namespace. So, no
duplication is allowed.

Probably the best here would be to replace the macros by inlined
functions.

Regards,
Mauro


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
  2022-07-06 17:10         ` [Intel-gfx] " Mauro Carvalho Chehab
@ 2022-07-12 10:29           ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-12 10:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/6/22 8:10 PM, Mauro Carvalho Chehab wrote:
> On Wed, 6 Jul 2022 19:33:22 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
>>> On Tue,  5 Jul 2022 15:24:50 +0300
>>> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
>>>    
>>>> From: Chris Wilson <chris@chris-wilson.co.uk>
>>>>
>>>> We need to check that we avoid integer overflows when looking up a page,
>>>> and so fix all the instances where we have mistakenly used a plain
>>>> integer instead of a more suitable long. Be pedantic and add integer
>>>> typechecking to the lookup so that we can be sure that we are safe.
>>>> And it also uses pgoff_t as our page lookups must remain compatible with
>>>> the page cache, pgoff_t is currently exactly unsigned long.
>>>>
>>>> v2: Move added i915_utils's macro into drm_util header (Jani N)
>>>>
>>>> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>>>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>>>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>>>> Cc: Matthew Auld <matthew.auld@intel.com>
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>>>>    drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>>>>    drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>>>>    drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>>>>    .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>>>>    .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>>>>    .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>>>>    drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>>>>    drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>>>>    9 files changed, 100 insertions(+), 55 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index ccec4055fde3..90996fe8ad45 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>>>>    static void
>>>>    i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>>>    	void *src_map;
>>>>    	void *src_ptr;
>>>>    
>>>> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
>>>> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>>>>    
>>>>    	src_ptr = src_map + offset_in_page(offset);
>>>>    	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
>>>> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>>>>    static void
>>>>    i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>>> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>>>>    	void __iomem *src_map;
>>>>    	void __iomem *src_ptr;
>>>> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>>>>    
>>>>    	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>>>>    				    dma - obj->mm.region->region.start,
>>>> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>>>>     */
>>>>    int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>>>>    	GEM_BUG_ON(offset >= obj->base.size);
>>>>    	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>>>>    	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> index 6f0a3ce35567..a60c6f4517d5 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> @@ -27,8 +27,10 @@ enum intel_region_id;
>>>>     * 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
>>>> + * - sg_table embeds unsigned int for nents
>>>> + *
>>>> + * We can check for invalidly typed locals with typecheck(), see for example
>>>> + * i915_gem_object_get_sg().
>>>>     */
>>>>    #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>>>>    	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
>>>> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>>>>    struct scatterlist *
>>>>    __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>>    			 struct i915_gem_object_page_iter *iter,
>>>> -			 unsigned int n,
>>>> -			 unsigned int *offset, bool dma);
>>>> +			 pgoff_t  n,
>>>> +			 unsigned int *offset);
>>>> +
>>>> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
>>>> +})
>>>>    
>>>>    static inline struct scatterlist *
>>>> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>> -		       unsigned int n,
>>>> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    		       unsigned int *offset)
>>>>    {
>>>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
>>>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>>>>    }
>>>>    
>>>> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_sg)(obj, n, offset); \
>>>> +})
>>>> +
>>>>    static inline struct scatterlist *
>>>> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
>>>> -			   unsigned int n,
>>>> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    			   unsigned int *offset)
>>>>    {
>>>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
>>>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>>>>    }
>>>>    
>>>> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
>>>> +})
>>>> +
>>>>    struct page *
>>>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
>>>> -			 unsigned int n);
>>>> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_page(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_page)(obj, n); \
>>>> +})
>>>>    
>>>>    struct page *
>>>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>>>> -			       unsigned int n);
>>>> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dirty_page)(obj, n); \
>>>> +})
>>>>    
>>>>    dma_addr_t
>>>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>>>> -				    unsigned long n,
>>>> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    				    unsigned int *len);
>>>>    
>>>> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
>>>> +})
>>>> +
>>>>    dma_addr_t
>>>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>>>> -				unsigned long n);
>>>> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_dma_address(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dma_address)(obj, n); \
>>>> +})
>>>>    
>>>>    void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>>>>    				 struct sg_table *pages,
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> index 97c820eee115..1d1edcb3514b 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>>>>    }
>>>>    
>>>>    struct scatterlist *
>>>> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>>>>    			 struct i915_gem_object_page_iter *iter,
>>>> -			 unsigned int n,
>>>> -			 unsigned int *offset,
>>>> -			 bool dma)
>>>> +			 pgoff_t n,
>>>> +			 unsigned int *offset)
>>>> +
>>>
>>> Nitpick: no need to place the function name in parenthesis.
>>>    
>>>>    {
>>>> -	struct scatterlist *sg;
>>>> +	const bool dma = iter == &obj->mm.get_dma_page ||
>>>> +			 iter == &obj->ttm.get_io_page;
>>>>    	unsigned int idx, count;
>>>> +	struct scatterlist *sg;
>>>>    
>>>>    	might_sleep();
>>>>    	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
>>>> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>>    }
>>>>    
>>>>    struct page *
>>>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>>>> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
>>>
>>> Same as above: why are you placing parenthesis at the function name here?
>>> Just use:
>>> 	
>>> 	struct page *
>>> 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
>>>   
>> In this case, the macro and function have the same name. If parenthesis
>> is not used, the following compile error occurs as the macro is applied
>> to the c code.
>>
>> ./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected
>> identifier or ‘(’ before ‘{’ token
>>     356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>>         |                                                       ^
>> drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of
>> macro ‘__i915_gem_object_get_sg’
>>     506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>         | ^~~~~~~~~~~~~~~~~~~~~~~~
>>
>> And all of the parts you leave comments below are cases where the names
>> of macros and functions are the same.
> 
> Don't use the same macro name on a function. This is very confusing
> and will prevent ever adding documentation for it, as, for kernel-doc,
> macros and functions are handled at the same namespace. So, no
> duplication is allowed.
> 
> Probably the best here would be to replace the macros by inlined
> functions.
> 
When using an inline function, the function can check the types after 
typecasting its arguments.
It is more efficient to use the above macro style to check input 
argument's type in the compilation stage.
This way is also used in the macro below among the existing i915 codes.

#define sg_alloc_table(sgt, nents, gfp) \
	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, 
(__sg_size_t)(nents), gfp)

#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, 
size, max_segment, gfp) \
	overflows_type(npages, __sg_size_t) ? -E2BIG : 
(sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), 
offset, size, max_segment, gfp)


This method has the advantage of being able to check the type of a 
variable passed as a function argument before it is typecast.

However, the kernel-doc's issues is something I didn't think consider 
before. To fix the naming problem in the documentation, I will change 
the macro name and the function name differently and send it as a new 
version.

Br,
G.G.
> Regards,
> Mauro
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups
@ 2022-07-12 10:29           ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-12 10:29 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/6/22 8:10 PM, Mauro Carvalho Chehab wrote:
> On Wed, 6 Jul 2022 19:33:22 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> On 7/5/22 5:35 PM, Mauro Carvalho Chehab wrote:
>>> On Tue,  5 Jul 2022 15:24:50 +0300
>>> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
>>>    
>>>> From: Chris Wilson <chris@chris-wilson.co.uk>
>>>>
>>>> We need to check that we avoid integer overflows when looking up a page,
>>>> and so fix all the instances where we have mistakenly used a plain
>>>> integer instead of a more suitable long. Be pedantic and add integer
>>>> typechecking to the lookup so that we can be sure that we are safe.
>>>> And it also uses pgoff_t as our page lookups must remain compatible with
>>>> the page cache, pgoff_t is currently exactly unsigned long.
>>>>
>>>> v2: Move added i915_utils's macro into drm_util header (Jani N)
>>>>
>>>> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>>>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>>>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>>>> Cc: Matthew Auld <matthew.auld@intel.com>
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/gem/i915_gem_object.c    |  7 +-
>>>>    drivers/gpu/drm/i915/gem/i915_gem_object.h    | 67 ++++++++++++++-----
>>>>    drivers/gpu/drm/i915/gem/i915_gem_pages.c     | 25 ++++---
>>>>    drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  2 +-
>>>>    .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++--
>>>>    .../drm/i915/gem/selftests/i915_gem_mman.c    |  8 +--
>>>>    .../drm/i915/gem/selftests/i915_gem_object.c  |  8 +--
>>>>    drivers/gpu/drm/i915/i915_gem.c               | 18 +++--
>>>>    drivers/gpu/drm/i915/i915_vma.c               |  8 +--
>>>>    9 files changed, 100 insertions(+), 55 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> index ccec4055fde3..90996fe8ad45 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
>>>> @@ -421,10 +421,11 @@ void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
>>>>    static void
>>>>    i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>>>    	void *src_map;
>>>>    	void *src_ptr;
>>>>    
>>>> -	src_map = kmap_atomic(i915_gem_object_get_page(obj, offset >> PAGE_SHIFT));
>>>> +	src_map = kmap_atomic(i915_gem_object_get_page(obj, idx));
>>>>    
>>>>    	src_ptr = src_map + offset_in_page(offset);
>>>>    	if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
>>>> @@ -437,9 +438,10 @@ i915_gem_object_read_from_page_kmap(struct drm_i915_gem_object *obj, u64 offset,
>>>>    static void
>>>>    i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	pgoff_t idx = offset >> PAGE_SHIFT;
>>>> +	dma_addr_t dma = i915_gem_object_get_dma_address(obj, idx);
>>>>    	void __iomem *src_map;
>>>>    	void __iomem *src_ptr;
>>>> -	dma_addr_t dma = i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT);
>>>>    
>>>>    	src_map = io_mapping_map_wc(&obj->mm.region->iomap,
>>>>    				    dma - obj->mm.region->region.start,
>>>> @@ -468,6 +470,7 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
>>>>     */
>>>>    int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset, void *dst, int size)
>>>>    {
>>>> +	GEM_BUG_ON(overflows_type(offset >> PAGE_SHIFT, pgoff_t));
>>>>    	GEM_BUG_ON(offset >= obj->base.size);
>>>>    	GEM_BUG_ON(offset_in_page(offset) > PAGE_SIZE - size);
>>>>    	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> index 6f0a3ce35567..a60c6f4517d5 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>>>> @@ -27,8 +27,10 @@ enum intel_region_id;
>>>>     * 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
>>>> + * - sg_table embeds unsigned int for nents
>>>> + *
>>>> + * We can check for invalidly typed locals with typecheck(), see for example
>>>> + * i915_gem_object_get_sg().
>>>>     */
>>>>    #define GEM_CHECK_SIZE_OVERFLOW(sz) \
>>>>    	GEM_WARN_ON((sz) >> PAGE_SHIFT > INT_MAX)
>>>> @@ -366,41 +368,70 @@ int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
>>>>    struct scatterlist *
>>>>    __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>>    			 struct i915_gem_object_page_iter *iter,
>>>> -			 unsigned int n,
>>>> -			 unsigned int *offset, bool dma);
>>>> +			 pgoff_t  n,
>>>> +			 unsigned int *offset);
>>>> +
>>>> +#define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(__i915_gem_object_get_sg)(obj, it, n, offset); \
>>>> +})
>>>>    
>>>>    static inline struct scatterlist *
>>>> -i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>> -		       unsigned int n,
>>>> +i915_gem_object_get_sg(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    		       unsigned int *offset)
>>>>    {
>>>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, false);
>>>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset);
>>>>    }
>>>>    
>>>> +#define i915_gem_object_get_sg(obj, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_sg)(obj, n, offset); \
>>>> +})
>>>> +
>>>>    static inline struct scatterlist *
>>>> -i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
>>>> -			   unsigned int n,
>>>> +i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    			   unsigned int *offset)
>>>>    {
>>>> -	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, true);
>>>> +	return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset);
>>>>    }
>>>>    
>>>> +#define i915_gem_object_get_sg_dma(obj, n, offset) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_sg_dma)(obj, n, offset); \
>>>> +})
>>>> +
>>>>    struct page *
>>>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj,
>>>> -			 unsigned int n);
>>>> +i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_page(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_page)(obj, n); \
>>>> +})
>>>>    
>>>>    struct page *
>>>> -i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
>>>> -			       unsigned int n);
>>>> +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_dirty_page(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dirty_page)(obj, n); \
>>>> +})
>>>>    
>>>>    dma_addr_t
>>>> -i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
>>>> -				    unsigned long n,
>>>> +i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, pgoff_t n,
>>>>    				    unsigned int *len);
>>>>    
>>>> +#define i915_gem_object_get_dma_address_len(obj, n, len) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dma_address_len)(obj, n, len); \
>>>> +})
>>>> +
>>>>    dma_addr_t
>>>> -i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
>>>> -				unsigned long n);
>>>> +i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, pgoff_t n);
>>>> +
>>>> +#define i915_gem_object_get_dma_address(obj, n) ({ \
>>>> +	exactly_pgoff_t(n); \
>>>> +	(i915_gem_object_get_dma_address)(obj, n); \
>>>> +})
>>>>    
>>>>    void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
>>>>    				 struct sg_table *pages,
>>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> index 97c820eee115..1d1edcb3514b 100644
>>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>>>> @@ -503,14 +503,16 @@ void __i915_gem_object_release_map(struct drm_i915_gem_object *obj)
>>>>    }
>>>>    
>>>>    struct scatterlist *
>>>> -__i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>> +(__i915_gem_object_get_sg)(struct drm_i915_gem_object *obj,
>>>>    			 struct i915_gem_object_page_iter *iter,
>>>> -			 unsigned int n,
>>>> -			 unsigned int *offset,
>>>> -			 bool dma)
>>>> +			 pgoff_t n,
>>>> +			 unsigned int *offset)
>>>> +
>>>
>>> Nitpick: no need to place the function name in parenthesis.
>>>    
>>>>    {
>>>> -	struct scatterlist *sg;
>>>> +	const bool dma = iter == &obj->mm.get_dma_page ||
>>>> +			 iter == &obj->ttm.get_io_page;
>>>>    	unsigned int idx, count;
>>>> +	struct scatterlist *sg;
>>>>    
>>>>    	might_sleep();
>>>>    	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
>>>> @@ -618,7 +620,7 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>>>    }
>>>>    
>>>>    struct page *
>>>> -i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
>>>> +(i915_gem_object_get_page)(struct drm_i915_gem_object *obj, pgoff_t n)
>>>
>>> Same as above: why are you placing parenthesis at the function name here?
>>> Just use:
>>> 	
>>> 	struct page *
>>> 	i915_gem_object_get_page(struct drm_i915_gem_object *obj, pgoff_t n)
>>>   
>> In this case, the macro and function have the same name. If parenthesis
>> is not used, the following compile error occurs as the macro is applied
>> to the c code.
>>
>> ./drivers/gpu/drm/i915/gem/i915_gem_object.h:356:55: error: expected
>> identifier or ‘(’ before ‘{’ token
>>     356 | #define __i915_gem_object_get_sg(obj, it, n, offset) ({ \
>>         |                                                       ^
>> drivers/gpu/drm/i915/gem/i915_gem_pages.c:506:1: note: in expansion of
>> macro ‘__i915_gem_object_get_sg’
>>     506 | __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>         | ^~~~~~~~~~~~~~~~~~~~~~~~
>>
>> And all of the parts you leave comments below are cases where the names
>> of macros and functions are the same.
> 
> Don't use the same macro name on a function. This is very confusing
> and will prevent ever adding documentation for it, as, for kernel-doc,
> macros and functions are handled at the same namespace. So, no
> duplication is allowed.
> 
> Probably the best here would be to replace the macros by inlined
> functions.
> 
When using an inline function, the function can check the types after 
typecasting its arguments.
It is more efficient to use the above macro style to check input 
argument's type in the compilation stage.
This way is also used in the macro below among the existing i915 codes.

#define sg_alloc_table(sgt, nents, gfp) \
	overflows_type(nents, __sg_size_t) ? -E2BIG : (sg_alloc_table)(sgt, 
(__sg_size_t)(nents), gfp)

#define sg_alloc_table_from_pages_segment(sgt, pages, npages, offset, 
size, max_segment, gfp) \
	overflows_type(npages, __sg_size_t) ? -E2BIG : 
(sg_alloc_table_from_pages_segment)(sgt, pages, (__sg_size_t)(npages), 
offset, size, max_segment, gfp)


This method has the advantage of being able to check the type of a 
variable passed as a function argument before it is typecast.

However, the kernel-doc's issues is something I didn't think consider 
before. To fix the naming problem in the documentation, I will change 
the macro name and the function name differently and send it as a new 
version.

Br,
G.G.
> Regards,
> Mauro
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
  2022-07-06 17:05         ` Mauro Carvalho Chehab
@ 2022-07-12 10:50           ` Gwan-gyeong Mun
  -1 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-12 10:50 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/6/22 8:05 PM, Mauro Carvalho Chehab wrote:
> On Wed, 6 Jul 2022 18:04:20 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
>>> On Tue,  5 Jul 2022 15:24:49 +0300
>>> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
>>>    
>>>> It moves overflows_type utility macro into drm util header from i915_utils
>>>> header. The overflows_type can be used to catch the truncation between data
>>>> types. And it adds safe_conversion() macro which performs a type conversion
>>>> (cast) of an source value into a new variable, checking that the
>>>> destination is large enough to hold the source value.
>>>> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
>>>> while compiling.
>>>>
>>>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Cc: Matthew Auld <matthew.auld@intel.com>
>>>> Cc: Nirmoy Das <nirmoy.das@intel.com>
>>>> Cc: Jani Nikula <jani.nikula@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/i915_utils.h |  5 +--
>>>>    include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>>>>    2 files changed, 55 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
>>>> index c10d68cdc3ca..345e5b2dc1cd 100644
>>>> --- a/drivers/gpu/drm/i915/i915_utils.h
>>>> +++ b/drivers/gpu/drm/i915/i915_utils.h
>>>> @@ -32,6 +32,7 @@
>>>>    #include <linux/types.h>
>>>>    #include <linux/workqueue.h>
>>>>    #include <linux/sched/clock.h>
>>>> +#include <drm/drm_util.h>
>>>>    
>>>>    #ifdef CONFIG_X86
>>>>    #include <asm/hypervisor.h>
>>>> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>>>>    #define range_overflows_end_t(type, start, size, max) \
>>>>    	range_overflows_end((type)(start), (type)(size), (type)(max))
>>>>    
>>>> -/* Note we don't consider signbits :| */
>>>> -#define overflows_type(x, T) \
>>>> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>>>> -
>>>>    #define ptr_mask_bits(ptr, n) ({					\
>>>>    	unsigned long __v = (unsigned long)(ptr);			\
>>>>    	(typeof(ptr))(__v & -BIT(n));					\
>>>> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
>>>> index 79952d8c4bba..c56230e39e37 100644
>>>> --- a/include/drm/drm_util.h
>>>> +++ b/include/drm/drm_util.h
>>>> @@ -62,6 +62,60 @@
>>>>     */
>>>>    #define for_each_if(condition) if (!(condition)) {} else
>>>>    
>>>> +/**
>>>> + * overflows_type - helper for checking the truncation between data types
>>>> + * @x: Source for overflow type comparison
>>>> + * @T: Destination for overflow type comparison
>>>> + *
>>>> + * It compares the values and size of each data type between the first and
>>>> + * second argument to check whether truncation can occur when assigning the
>>>> + * first argument to the variable of the second argument.
>>>> + * It does't consider signbits.
>>>> + *
>>>> + * Returns:
>>>> + * True if truncation can occur, false otherwise.
>>>> + */
>>>> +#define overflows_type(x, T) \
>>>> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>>>
>>> As pointed on its description, this macro only works if both types
>>> are either signed or unsigned. However, the macro itself doesn't check
>>> it.
>>>
>>> It probably worth adding something there to ensure that both types are
>>> either signed or unsigned. I would add this ancillary macro probably on
>>> on a generic kernel header - as this can be useful outside drm:
>>>
>>> 	#define sign_matches(x, y) \
>>> 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
>>>
>>> And then include use it at overflows_type:
>>>
>>> 	BUILD_BUG_ON(!sign_matches(x, T))
>>>    
>> Hi Mauro, thanks for checking it.
>>
>> What you commented here (sign_matches macro) is to check whether the
>> sign bits of two types are the same,  but the purpose of the
>> overflows_type() macro checks overflows while assigning a variable with
>> a large data size (BITS_PER_TYPE is large) to a variable with a small
>> data size (BITS_PER_TYPE is small).
> 
> True, but the problem is that such macro just assumes that either both
> are signed or unsigned without actually checking it.
> 
> Basically, if one tries to store for instance a s32 value on an u64 var,
> the value won't be stored correctly, due to an underflow. As the hole
> idea of this macro is to exactly detect if the "container" variable
> is big enough to properly represent the measure, it sounds incomplete
> to not handle the integer signal.
> 
> Btw, after reviewing all patches, using BUILD_BUG_ON() is not needed
> here, as such macro (or similar) is already used at the callers code.
> 
> So, I would just return false if the signals are incompatible, e. g.
> if the type of the source value is signed and the type of the
> destination value is unsigned.
> 
> So:
> 
> #define overflows_type(x, T) \
> 	(!signal_matches(x,T) || (sizeof(x) > sizeof(T)))
> 
> Should do the trick[1].
> 
> [1] using BITS_PER_TYPE() macro is not really needed, as this is
>      defined as:
> 
> 	#define BITS_PER_BYTE              8
> 	#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)
> 
>      So, checking if sizeof(x) > sizeof(T) is enough. Btw, the check
>      there seems to be inverted, making the macro to always return zero!
> 
> Yet, strictly speaking, it is possible to store an unsigned value on a
> signed type, if the signed type is bigger than the size of unsigned
> (so, a s64 int can store u32, but a s32 can't store u32).
> 
> Adding a check that would consider this should be like:
> 
> 	#define is_type_unsigned(x) ((typeof(x))-1 >= 0)
> 	#define is_type_signed(x) (!is_type_unsigned(x))
> 	#define overflows_type(x, T)							 \
> 	(										 \
> 		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
> 		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
> 		(sizeof(x) > sizeof(T))							 \
> 	) 	
> 
> This should be generic enough to be used anywhere.
> 
>> we can check the additional sign bit by adding sign_matches() to the
>> overflows_type() macro, but in the current scenario, it is used only
>> when the sign bit is the same.
> 
> Yeah, but "current scenarios" can easily be extended to something
> else, quickly going sideways specially on a subsystem-wide macro.
> Also, getting this right is particularly tricky when comparing typedef
> integers. So, I would be more comfortable if the logic will also
> check the signal at the destination variable.
> 
>> Should the macro be extended even for cases where the sign bit is
>> different in the current state? (If yes, I'll updated it as v3)
>>
>> In addition, the place where this macro is currently used is only in the
>> i915 driver, so it has been moved to the header of the drm subsystem.
>> IMHO, moving the macro location so that it can be used by multiple
>> subsystems of linux would be a good idea when there is a use case for
>> this macro. What do you think?
> 
> Good point. Yeah, it can stay there while not needed outside drm.
> 
> Btw, in order to get it right, I suggest double-checking in userspace
> how each macros are evaluated, like using the code below.
> 
> It helps to check if the logic is doing what's expected or not.
> 
Thanks for sharing your nice comments and ideas.
The currently used oveflows_type() macro has a requirement to check not 
only the overflow check using the size of the container, but also the 
overflow that may occur when an actual variable is assigned.
In relation to this, I wrote a macro based on the logic below and tested 
all scenarios that can be used in c code.

#define BITS_PER_BYTE           8
#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)

#define is_type_unsigned(x) ((typeof(x))-1 >= 0)

bool overflows = false;
if (is_type_unsigned(x)) {
   if (is_type_unsigned(T)) { // x: unsigned, T: unsigned
     if (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
       overflows = true;
   } else { // x: unsigned, T: signed
     if (sizeof(x) >= sizeof(T) && (x) >> BITS_PER_TYPE(T) - 1)
       overflows = true;
   }
} else {
   if (is_type_unsigned(T)) {  // x: signed, T: unsigned
     if ((x) < 0)  // sign bit is negative, negative value
       overflows = true;
     else { // sign bit is positive, positive value
       if (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
         overflows = true;
     }
   } else {  // x: signed, T: signed
     if (sizeof(x) > sizeof(T)) {
       if ((x) < 0) { // sign bit is negative, negative value
         if (((x) * -1) >> BITS_PER_TYPE(T)) {
             /* Since signed numbers treat negative numbers as
                2's complement, convert them to positive numbers,
                perform bitshift operations, and perform overflow checking.
             */
           overflows = true;
         }
       }
       else { // positive value.
         if ((x) >> BITS_PER_TYPE(T))
           overflows = true;
       }
     }
   }
}


Here is the code that was actually tested:
The patch applied with is_type_unsigned() / oveflows_type() used in the 
code below will be sent back as a new version.

#include <stdio.h>
#include <limits.h>
#include <assert.h>

#define BITS_PER_BYTE           8
#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)

#define is_type_unsigned(x) ((typeof(x))-1 >= (typeof(x))0)

#define overflows_type(x, T) \
	(is_type_unsigned(x) ? \
		is_type_unsigned(T) ? \
			(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) ? 1 : 0 \
			: (sizeof(x) >= sizeof(T) && (x) >> (BITS_PER_TYPE(T) - 1)) ? 1 : 0 \
	: is_type_unsigned(T) ? \
		((x) < 0) ? 1 : (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) ? 1 
: 0 \
		: (sizeof(x) > sizeof(T)) ? \
			((x) < 0) ? (((x) * -1) >> BITS_PER_TYPE(T)) ? 1 : 0\
				: ((x) >> BITS_PER_TYPE(T)) ? 1 : 0 \
			: 0)

typedef char s8;
typedef unsigned char u8;
typedef short s16;
typedef unsigned short u16;
typedef int s32;
typedef unsigned int u32;
typedef long long s64;
typedef unsigned long long u64;

int main(void) {
	/* test variable, test type */
	/* 1.  overflows_type(x, T) x: unsigned, T: unsigned */
	{
		u32 x = UINT_MAX;
		u16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = USHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u16));
	}
	{
		u64 x = ULLONG_MAX;
		u8 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u8));

		x = UCHAR_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u8));
	}
	{
		u8 x = UCHAR_MAX;
		u64 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u64));
	}

	/* 2.  overflows_type(x, T) x: unsigned, T: signed */
	{
		u32 x = UINT_MAX;
		s16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));

		x = SHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));

		x = SHRT_MAX + 1;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));
	}
	{
		u64 x = ULLONG_MAX;
		s8 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s8));

		x = SCHAR_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s8));
	}
	{
		u8 x = UCHAR_MAX;
		s32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));
	}

	/* 3.  overflows_type(x, T) x: signed, T: unsigned */
	{
		s32 x = INT_MAX;
		u16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = INT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = USHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u16));
	}
	{
		s16 x = SHRT_MAX;
		u32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u32));

		x = SHRT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u32));
	}
	{
		s32 x = INT_MAX;
		u32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u32));

		x = INT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u32));
	}

	/* 4.  overflows_type(x, T) x: signed, T: signed */
	{
		s32 x = INT_MAX;
		s16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));

		x = INT_MIN;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));


		x = SHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));

		x = SHRT_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));
	}
	{
		s16 x = SHRT_MAX;
		s32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));

		x = SHRT_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));
	}
	{
		s64 x = LLONG_MAX;
		s64 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s64));

		x = LLONG_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s64));
	}

	{
		u64 x = 123456;
		int *T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, int *));
	}
	return 0;
}



> ----
> 
> #include <stdio.h>
> #include <stdint.h>
> 
> // Kernel definitions from bits.h and bitops.h
> #define BITS_PER_BYTE              8
> #define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)
> 
> #define sign_matches(x, y) \
> 	(!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> 
> #define is_type_unsigned(x) ((typeof(x))-1 >= 0)
> #define is_type_signed(x) (!is_type_unsigned(x))
> 
> #define overflows_type(x, T)								 \
> 	(										 \
> 		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
> 		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
> 		(sizeof(x) > sizeof(T))							 \
> 	) ? "OVERFLOW" : "don't overflow"
> 
> int main(void)
> {
> 	uint32_t	u32_1 = 0, u32_2 = 0;
> 	int32_t		s32_1 = 0, s32_2 = 0;
> 	uint64_t	u64_1 = 0, u64_2 = 0;
> 	int64_t		s64_1 = 0, s64_2 = 0;
> 
> 	printf("u32 stored into u32: %s\n", overflows_type(u32_1, u32_2));
> 	printf("u64 stored into u32: %s\n", overflows_type(u64_1, u32_2));
> 	printf("s32 stored into u32: %s\n", overflows_type(s32_1, u32_2));
> 	printf("s64 stored into u32: %s\n", overflows_type(s64_1, u32_2));
> 
> 	printf("u32 stored into s32: %s\n", overflows_type(u32_1, s32_2));
> 	printf("u64 stored into s32: %s\n", overflows_type(u64_1, s32_2));
> 	printf("s32 stored into s32: %s\n", overflows_type(s32_1, s32_2));
> 	printf("s64 stored into s32: %s\n", overflows_type(s64_1, s32_2));
> 
> 	printf("u32 stored into u64: %s\n", overflows_type(u32_1, u64_2));
> 	printf("u64 stored into u64: %s\n", overflows_type(u64_1, u64_2));
> 	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
> 	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));
> 
> 	printf("u32 stored into s64: %s\n", overflows_type(u32_1, s64_2));
> 	printf("u64 stored into s64: %s\n", overflows_type(u64_1, s64_2));
> 	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
> 	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));
> 
> 	// Shutup warnings
> 	s64_1 = u32_1 + u32_2 + s64_2 + s32_1 + s32_2 + u64_1 + u64_2;
> 
> 	return 0;
> }
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Intel-gfx] [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header
@ 2022-07-12 10:50           ` Gwan-gyeong Mun
  0 siblings, 0 replies; 45+ messages in thread
From: Gwan-gyeong Mun @ 2022-07-12 10:50 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: thomas.hellstrom, jani.nikula, intel-gfx, dri-devel, chris,
	airlied, matthew.auld, nirmoy.das



On 7/6/22 8:05 PM, Mauro Carvalho Chehab wrote:
> On Wed, 6 Jul 2022 18:04:20 +0300
> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
> 
>> On 7/5/22 5:23 PM, Mauro Carvalho Chehab wrote:
>>> On Tue,  5 Jul 2022 15:24:49 +0300
>>> Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> wrote:
>>>    
>>>> It moves overflows_type utility macro into drm util header from i915_utils
>>>> header. The overflows_type can be used to catch the truncation between data
>>>> types. And it adds safe_conversion() macro which performs a type conversion
>>>> (cast) of an source value into a new variable, checking that the
>>>> destination is large enough to hold the source value.
>>>> And it adds exact_type and exactly_pgoff_t macro to catch type mis-match
>>>> while compiling.
>>>>
>>>> Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> Cc: Matthew Auld <matthew.auld@intel.com>
>>>> Cc: Nirmoy Das <nirmoy.das@intel.com>
>>>> Cc: Jani Nikula <jani.nikula@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/i915_utils.h |  5 +--
>>>>    include/drm/drm_util.h            | 54 +++++++++++++++++++++++++++++++
>>>>    2 files changed, 55 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
>>>> index c10d68cdc3ca..345e5b2dc1cd 100644
>>>> --- a/drivers/gpu/drm/i915/i915_utils.h
>>>> +++ b/drivers/gpu/drm/i915/i915_utils.h
>>>> @@ -32,6 +32,7 @@
>>>>    #include <linux/types.h>
>>>>    #include <linux/workqueue.h>
>>>>    #include <linux/sched/clock.h>
>>>> +#include <drm/drm_util.h>
>>>>    
>>>>    #ifdef CONFIG_X86
>>>>    #include <asm/hypervisor.h>
>>>> @@ -111,10 +112,6 @@ bool i915_error_injected(void);
>>>>    #define range_overflows_end_t(type, start, size, max) \
>>>>    	range_overflows_end((type)(start), (type)(size), (type)(max))
>>>>    
>>>> -/* Note we don't consider signbits :| */
>>>> -#define overflows_type(x, T) \
>>>> -	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>>>> -
>>>>    #define ptr_mask_bits(ptr, n) ({					\
>>>>    	unsigned long __v = (unsigned long)(ptr);			\
>>>>    	(typeof(ptr))(__v & -BIT(n));					\
>>>> diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h
>>>> index 79952d8c4bba..c56230e39e37 100644
>>>> --- a/include/drm/drm_util.h
>>>> +++ b/include/drm/drm_util.h
>>>> @@ -62,6 +62,60 @@
>>>>     */
>>>>    #define for_each_if(condition) if (!(condition)) {} else
>>>>    
>>>> +/**
>>>> + * overflows_type - helper for checking the truncation between data types
>>>> + * @x: Source for overflow type comparison
>>>> + * @T: Destination for overflow type comparison
>>>> + *
>>>> + * It compares the values and size of each data type between the first and
>>>> + * second argument to check whether truncation can occur when assigning the
>>>> + * first argument to the variable of the second argument.
>>>> + * It does't consider signbits.
>>>> + *
>>>> + * Returns:
>>>> + * True if truncation can occur, false otherwise.
>>>> + */
>>>> +#define overflows_type(x, T) \
>>>> +	(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
>>>
>>> As pointed on its description, this macro only works if both types
>>> are either signed or unsigned. However, the macro itself doesn't check
>>> it.
>>>
>>> It probably worth adding something there to ensure that both types are
>>> either signed or unsigned. I would add this ancillary macro probably on
>>> on a generic kernel header - as this can be useful outside drm:
>>>
>>> 	#define sign_matches(x, y) \
>>> 	        (!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
>>>
>>> And then include use it at overflows_type:
>>>
>>> 	BUILD_BUG_ON(!sign_matches(x, T))
>>>    
>> Hi Mauro, thanks for checking it.
>>
>> What you commented here (sign_matches macro) is to check whether the
>> sign bits of two types are the same,  but the purpose of the
>> overflows_type() macro checks overflows while assigning a variable with
>> a large data size (BITS_PER_TYPE is large) to a variable with a small
>> data size (BITS_PER_TYPE is small).
> 
> True, but the problem is that such macro just assumes that either both
> are signed or unsigned without actually checking it.
> 
> Basically, if one tries to store for instance a s32 value on an u64 var,
> the value won't be stored correctly, due to an underflow. As the hole
> idea of this macro is to exactly detect if the "container" variable
> is big enough to properly represent the measure, it sounds incomplete
> to not handle the integer signal.
> 
> Btw, after reviewing all patches, using BUILD_BUG_ON() is not needed
> here, as such macro (or similar) is already used at the callers code.
> 
> So, I would just return false if the signals are incompatible, e. g.
> if the type of the source value is signed and the type of the
> destination value is unsigned.
> 
> So:
> 
> #define overflows_type(x, T) \
> 	(!signal_matches(x,T) || (sizeof(x) > sizeof(T)))
> 
> Should do the trick[1].
> 
> [1] using BITS_PER_TYPE() macro is not really needed, as this is
>      defined as:
> 
> 	#define BITS_PER_BYTE              8
> 	#define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)
> 
>      So, checking if sizeof(x) > sizeof(T) is enough. Btw, the check
>      there seems to be inverted, making the macro to always return zero!
> 
> Yet, strictly speaking, it is possible to store an unsigned value on a
> signed type, if the signed type is bigger than the size of unsigned
> (so, a s64 int can store u32, but a s32 can't store u32).
> 
> Adding a check that would consider this should be like:
> 
> 	#define is_type_unsigned(x) ((typeof(x))-1 >= 0)
> 	#define is_type_signed(x) (!is_type_unsigned(x))
> 	#define overflows_type(x, T)							 \
> 	(										 \
> 		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
> 		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
> 		(sizeof(x) > sizeof(T))							 \
> 	) 	
> 
> This should be generic enough to be used anywhere.
> 
>> we can check the additional sign bit by adding sign_matches() to the
>> overflows_type() macro, but in the current scenario, it is used only
>> when the sign bit is the same.
> 
> Yeah, but "current scenarios" can easily be extended to something
> else, quickly going sideways specially on a subsystem-wide macro.
> Also, getting this right is particularly tricky when comparing typedef
> integers. So, I would be more comfortable if the logic will also
> check the signal at the destination variable.
> 
>> Should the macro be extended even for cases where the sign bit is
>> different in the current state? (If yes, I'll updated it as v3)
>>
>> In addition, the place where this macro is currently used is only in the
>> i915 driver, so it has been moved to the header of the drm subsystem.
>> IMHO, moving the macro location so that it can be used by multiple
>> subsystems of linux would be a good idea when there is a use case for
>> this macro. What do you think?
> 
> Good point. Yeah, it can stay there while not needed outside drm.
> 
> Btw, in order to get it right, I suggest double-checking in userspace
> how each macros are evaluated, like using the code below.
> 
> It helps to check if the logic is doing what's expected or not.
> 
Thanks for sharing your nice comments and ideas.
The currently used oveflows_type() macro has a requirement to check not 
only the overflow check using the size of the container, but also the 
overflow that may occur when an actual variable is assigned.
In relation to this, I wrote a macro based on the logic below and tested 
all scenarios that can be used in c code.

#define BITS_PER_BYTE           8
#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)

#define is_type_unsigned(x) ((typeof(x))-1 >= 0)

bool overflows = false;
if (is_type_unsigned(x)) {
   if (is_type_unsigned(T)) { // x: unsigned, T: unsigned
     if (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
       overflows = true;
   } else { // x: unsigned, T: signed
     if (sizeof(x) >= sizeof(T) && (x) >> BITS_PER_TYPE(T) - 1)
       overflows = true;
   }
} else {
   if (is_type_unsigned(T)) {  // x: signed, T: unsigned
     if ((x) < 0)  // sign bit is negative, negative value
       overflows = true;
     else { // sign bit is positive, positive value
       if (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))
         overflows = true;
     }
   } else {  // x: signed, T: signed
     if (sizeof(x) > sizeof(T)) {
       if ((x) < 0) { // sign bit is negative, negative value
         if (((x) * -1) >> BITS_PER_TYPE(T)) {
             /* Since signed numbers treat negative numbers as
                2's complement, convert them to positive numbers,
                perform bitshift operations, and perform overflow checking.
             */
           overflows = true;
         }
       }
       else { // positive value.
         if ((x) >> BITS_PER_TYPE(T))
           overflows = true;
       }
     }
   }
}


Here is the code that was actually tested:
The patch applied with is_type_unsigned() / oveflows_type() used in the 
code below will be sent back as a new version.

#include <stdio.h>
#include <limits.h>
#include <assert.h>

#define BITS_PER_BYTE           8
#define BITS_PER_TYPE(type)	(sizeof(type) * BITS_PER_BYTE)

#define is_type_unsigned(x) ((typeof(x))-1 >= (typeof(x))0)

#define overflows_type(x, T) \
	(is_type_unsigned(x) ? \
		is_type_unsigned(T) ? \
			(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) ? 1 : 0 \
			: (sizeof(x) >= sizeof(T) && (x) >> (BITS_PER_TYPE(T) - 1)) ? 1 : 0 \
	: is_type_unsigned(T) ? \
		((x) < 0) ? 1 : (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) ? 1 
: 0 \
		: (sizeof(x) > sizeof(T)) ? \
			((x) < 0) ? (((x) * -1) >> BITS_PER_TYPE(T)) ? 1 : 0\
				: ((x) >> BITS_PER_TYPE(T)) ? 1 : 0 \
			: 0)

typedef char s8;
typedef unsigned char u8;
typedef short s16;
typedef unsigned short u16;
typedef int s32;
typedef unsigned int u32;
typedef long long s64;
typedef unsigned long long u64;

int main(void) {
	/* test variable, test type */
	/* 1.  overflows_type(x, T) x: unsigned, T: unsigned */
	{
		u32 x = UINT_MAX;
		u16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = USHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u16));
	}
	{
		u64 x = ULLONG_MAX;
		u8 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u8));

		x = UCHAR_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u8));
	}
	{
		u8 x = UCHAR_MAX;
		u64 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u64));
	}

	/* 2.  overflows_type(x, T) x: unsigned, T: signed */
	{
		u32 x = UINT_MAX;
		s16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));

		x = SHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));

		x = SHRT_MAX + 1;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));
	}
	{
		u64 x = ULLONG_MAX;
		s8 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s8));

		x = SCHAR_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s8));
	}
	{
		u8 x = UCHAR_MAX;
		s32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));
	}

	/* 3.  overflows_type(x, T) x: signed, T: unsigned */
	{
		s32 x = INT_MAX;
		u16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = INT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u16));

		x = USHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u16));
	}
	{
		s16 x = SHRT_MAX;
		u32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u32));

		x = SHRT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u32));
	}
	{
		s32 x = INT_MAX;
		u32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, u32));

		x = INT_MIN;
		/* expected underflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, u32));
	}

	/* 4.  overflows_type(x, T) x: signed, T: signed */
	{
		s32 x = INT_MAX;
		s16 T;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));

		x = INT_MIN;
		/* expected overflow */
		assert(overflows_type(x, T));
		assert(overflows_type(x, s16));


		x = SHRT_MAX;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));

		x = SHRT_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s16));
	}
	{
		s16 x = SHRT_MAX;
		s32 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));

		x = SHRT_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s32));
	}
	{
		s64 x = LLONG_MAX;
		s64 T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s64));

		x = LLONG_MIN;
		/* expected not underflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, s64));
	}

	{
		u64 x = 123456;
		int *T;
		/* expected not overflow */
		assert(!overflows_type(x, T));
		assert(!overflows_type(x, int *));
	}
	return 0;
}



> ----
> 
> #include <stdio.h>
> #include <stdint.h>
> 
> // Kernel definitions from bits.h and bitops.h
> #define BITS_PER_BYTE              8
> #define BITS_PER_TYPE(type)      (sizeof(type) * BITS_PER_BYTE)
> 
> #define sign_matches(x, y) \
> 	(!((typeof(x))-1 >= 0) ^ ((typeof(y))-1 >= 0))
> 
> #define is_type_unsigned(x) ((typeof(x))-1 >= 0)
> #define is_type_signed(x) (!is_type_unsigned(x))
> 
> #define overflows_type(x, T)								 \
> 	(										 \
> 		(is_type_signed(x) && is_type_unsigned(T)) ||				 \
> 		(is_type_unsigned(x) && is_type_signed(T) && (sizeof(x) == sizeof(T))) ||\
> 		(sizeof(x) > sizeof(T))							 \
> 	) ? "OVERFLOW" : "don't overflow"
> 
> int main(void)
> {
> 	uint32_t	u32_1 = 0, u32_2 = 0;
> 	int32_t		s32_1 = 0, s32_2 = 0;
> 	uint64_t	u64_1 = 0, u64_2 = 0;
> 	int64_t		s64_1 = 0, s64_2 = 0;
> 
> 	printf("u32 stored into u32: %s\n", overflows_type(u32_1, u32_2));
> 	printf("u64 stored into u32: %s\n", overflows_type(u64_1, u32_2));
> 	printf("s32 stored into u32: %s\n", overflows_type(s32_1, u32_2));
> 	printf("s64 stored into u32: %s\n", overflows_type(s64_1, u32_2));
> 
> 	printf("u32 stored into s32: %s\n", overflows_type(u32_1, s32_2));
> 	printf("u64 stored into s32: %s\n", overflows_type(u64_1, s32_2));
> 	printf("s32 stored into s32: %s\n", overflows_type(s32_1, s32_2));
> 	printf("s64 stored into s32: %s\n", overflows_type(s64_1, s32_2));
> 
> 	printf("u32 stored into u64: %s\n", overflows_type(u32_1, u64_2));
> 	printf("u64 stored into u64: %s\n", overflows_type(u64_1, u64_2));
> 	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
> 	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));
> 
> 	printf("u32 stored into s64: %s\n", overflows_type(u32_1, s64_2));
> 	printf("u64 stored into s64: %s\n", overflows_type(u64_1, s64_2));
> 	printf("s32 stored into u64: %s\n", overflows_type(s32_1, u64_2));
> 	printf("s64 stored into u64: %s\n", overflows_type(s64_1, u64_2));
> 
> 	// Shutup warnings
> 	s64_1 = u32_1 + u32_2 + s64_2 + s32_1 + s32_2 + u64_1 + u64_2;
> 
> 	return 0;
> }
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2022-07-12 10:50 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-05 12:24 [PATCH v2 0/7] Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation Gwan-gyeong Mun
2022-07-05 12:24 ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 12:24 ` [PATCH v2 1/7] drm: Move and add a few utility macros into drm util header Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:23   ` Mauro Carvalho Chehab
2022-07-05 14:23     ` Mauro Carvalho Chehab
2022-07-06 15:04     ` Gwan-gyeong Mun
2022-07-06 15:04       ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-06 17:05       ` Mauro Carvalho Chehab
2022-07-06 17:05         ` Mauro Carvalho Chehab
2022-07-12 10:50         ` Gwan-gyeong Mun
2022-07-12 10:50           ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 12:24 ` [PATCH v2 2/7] drm/i915/gem: Typecheck page lookups Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:35   ` Mauro Carvalho Chehab
2022-07-05 14:35     ` Mauro Carvalho Chehab
2022-07-06 16:33     ` Gwan-gyeong Mun
2022-07-06 16:33       ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-06 17:10       ` Mauro Carvalho Chehab
2022-07-06 17:10         ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-12 10:29         ` Gwan-gyeong Mun
2022-07-12 10:29           ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 12:24 ` [PATCH v2 3/7] drm/i915: Check for integer truncation on scatterlist creation Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:48   ` Mauro Carvalho Chehab
2022-07-05 14:48     ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-05 12:24 ` [PATCH v2 4/7] drm/i915: Check for integer truncation on the configuration of ttm place Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:44   ` Mauro Carvalho Chehab
2022-07-05 14:44     ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-05 12:24 ` [PATCH v2 5/7] drm/i915: Check if the size is too big while creating shmem file Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:50   ` Mauro Carvalho Chehab
2022-07-05 14:50     ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-05 12:24 ` [PATCH v2 6/7] drm/i915: Use error code as -E2BIG when the size of gem ttm object is too large Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:50   ` Mauro Carvalho Chehab
2022-07-05 14:50     ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-05 12:24 ` [PATCH v2 7/7] drm/i915: Remove truncation warning for large objects Gwan-gyeong Mun
2022-07-05 12:24   ` [Intel-gfx] " Gwan-gyeong Mun
2022-07-05 14:51   ` Mauro Carvalho Chehab
2022-07-05 14:51     ` [Intel-gfx] " Mauro Carvalho Chehab
2022-07-05 14:54 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Fixes integer overflow or integer truncation issues in page lookups, ttm place configuration and scatterlist creation (rev3) Patchwork
2022-07-05 15:13 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-07-05 18:44 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.