linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] overflow.h: Add arithmetic shift helper
@ 2018-08-01  0:00 Kees Cook
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01  0:00 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Kees Cook, Jason Gunthorpe, Leon Romanovsky, Bart Van Assche,
	Doug Ledford, Dan Carpenter, linux-rdma, linux-kernel

This adds the shift overflow helper, selftests, and first usage.

-Kees

Jason Gunthorpe (1):
  overflow.h: Add arithmetic shift helper

Kees Cook (1):
  test_overflow: Add shift overflow tests

Leon Romanovsky (1):
  RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq

 drivers/infiniband/hw/mlx5/qp.c |   5 +-
 include/linux/overflow.h        |  31 +++++++
 lib/test_overflow.c             | 140 +++++++++++++++++++++++++++++++-
 3 files changed, 174 insertions(+), 2 deletions(-)

-- 
2.17.1


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

* [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  0:00 [PATCH v2 0/3] overflow.h: Add arithmetic shift helper Kees Cook
@ 2018-08-01  0:00 ` Kees Cook
  2018-08-01  1:59   ` Randy Dunlap
                     ` (2 more replies)
  2018-08-01  0:00 ` [PATCH v2 2/3] test_overflow: Add shift overflow tests Kees Cook
  2018-08-01  0:00 ` [PATCH v2 3/3] RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq Kees Cook
  2 siblings, 3 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01  0:00 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Kees Cook, Jason Gunthorpe, Leon Romanovsky, Jason Gunthorpe,
	Leon Romanovsky, Bart Van Assche, Doug Ledford, Dan Carpenter,
	linux-rdma, linux-kernel

From: Jason Gunthorpe <jgg@mellanox.com>

Add shift_overflow() helper to assist driver authors in ensuring that
shift operations don't cause overflows or other odd conditions.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
[kees: tweaked comments and commit log, dropped unneeded assignment]
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/overflow.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/include/linux/overflow.h b/include/linux/overflow.h
index 8712ff70995f..69fc366ce865 100644
--- a/include/linux/overflow.h
+++ b/include/linux/overflow.h
@@ -202,6 +202,37 @@
 
 #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
 
+/** check_shift_overflow() - Calculate a left-shifted value and check overflow
+ *
+ * @a: Value to be shifted
+ * @b: How many bits left to shift
+ * @d: Pointer to where to store the result
+ *
+ * Computes *@d = (@a << @s)
+ *
+ * Returns true if '*d' cannot hold the result or when 'a << s' doesn't
+ * make sense. Example conditions:
+ * - 'a << s' causes bits to be lost when stored in *d.
+ * - 's' is garbage (e.g. negative) or so large that the result of
+ *   'a << s' is guaranteed to be 0.
+ * - 'a' is negative.
+ * - 'a << s' sets the sign bit, if any, in '*d'.
+ *
+ * '*d' will hold the results of the attempted shift, but is not
+ * considered "safe for use" if false is returned.
+ */
+#define check_shift_overflow(a, s, d) ({				\
+	typeof(a) _a = a;						\
+	typeof(s) _s = s;						\
+	typeof(d) _d = d;						\
+	u64 _a_full = _a;						\
+	unsigned int _to_shift =					\
+		_s >= 0 && _s < 8 * sizeof(*d) ? _s : 0;		\
+	*_d = (_a_full << _to_shift);					\
+	(_to_shift != _s || *_d < 0 || _a < 0 ||			\
+		(*_d >> _to_shift) != _a);				\
+})
+
 /**
  * array_size() - Calculate size of 2-dimensional array.
  *
-- 
2.17.1


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

* [PATCH v2 2/3] test_overflow: Add shift overflow tests
  2018-08-01  0:00 [PATCH v2 0/3] overflow.h: Add arithmetic shift helper Kees Cook
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
@ 2018-08-01  0:00 ` Kees Cook
  2018-08-01  2:13   ` Jason Gunthorpe
  2018-08-01  0:00 ` [PATCH v2 3/3] RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq Kees Cook
  2 siblings, 1 reply; 13+ messages in thread
From: Kees Cook @ 2018-08-01  0:00 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Kees Cook, Jason Gunthorpe, Leon Romanovsky, Bart Van Assche,
	Doug Ledford, Dan Carpenter, linux-rdma, linux-kernel

This adds overflow tests for the new check_shift_overflow() helper to
validate overflow, signedness glitches, storage glitches, etc.

Co-developed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 lib/test_overflow.c | 140 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/lib/test_overflow.c b/lib/test_overflow.c
index 2278fe05a1b0..face66e8aa37 100644
--- a/lib/test_overflow.c
+++ b/lib/test_overflow.c
@@ -252,7 +252,8 @@ static int __init test_ ## t ## _overflow(void) {			\
 	int err = 0;							\
 	unsigned i;							\
 									\
-	pr_info("%-3s: %zu tests\n", #t, ARRAY_SIZE(t ## _tests));	\
+	pr_info("%-3s: %zu arithmetic tests\n", #t,			\
+		ARRAY_SIZE(t ## _tests));				\
 	for (i = 0; i < ARRAY_SIZE(t ## _tests); ++i)			\
 		err |= do_test_ ## t(&t ## _tests[i]);			\
 	return err;							\
@@ -287,6 +288,142 @@ static int __init test_overflow_calculation(void)
 	return err;
 }
 
+static int __init test_overflow_shift(void)
+{
+	int err = 0;
+
+/* Args are: value, shift, type, expected result, overflow expected */
+#define TEST_ONE_SHIFT(a, s, t, expect, of) ({				\
+	int __failed = 0;						\
+	typeof(a) __a = (a);						\
+	typeof(s) __s = (s);						\
+	t __e = (expect);						\
+	t __d;								\
+	bool __of = check_shift_overflow(__a, __s, &__d);		\
+	if (__of != of) {						\
+		pr_warn("expected (%s)(%s << %s) to%s overflow\n",	\
+			#t, #a, #s, of ? "" : " not");			\
+		__failed = 1;						\
+	} else if (!__of && __d != __e) {				\
+		pr_warn("expected (%s)(%s << %s) == %s\n",		\
+			#t, #a, #s, #expect);				\
+		if ((t)-1 < 0)						\
+			pr_warn("got %lld\n", (s64)__d);		\
+		else							\
+			pr_warn("got %llu\n", (u64)__d);		\
+		__failed = 1;						\
+	}								\
+	if (!__failed)							\
+		pr_info("ok: (%s)(%s << %s) == %s\n", #t, #a, #s,	\
+			of ? "overflow" : #expect);			\
+	__failed;							\
+})
+
+	/* Sane shifts */
+	err |= TEST_ONE_SHIFT(1, 4, u8, 1 << 4, false);
+	err |= TEST_ONE_SHIFT(1, 7, u8, 1 << 7, false);
+	err |= TEST_ONE_SHIFT(1, 10, u16, 1 << 10, false);
+	err |= TEST_ONE_SHIFT(1, 15, u16, 1 << 15, false);
+	err |= TEST_ONE_SHIFT(1, 30, int, 1 << 30, false);
+	err |= TEST_ONE_SHIFT(1, 30, s32, 1 << 30, false);
+	err |= TEST_ONE_SHIFT(1, 20, unsigned int, 1U << 20, false);
+	err |= TEST_ONE_SHIFT(1, 31, unsigned int, 1U << 31, false);
+	err |= TEST_ONE_SHIFT(1, 20, u32, 1U << 20, false);
+	err |= TEST_ONE_SHIFT(1, 31, u32, 1U << 31, false);
+	err |= TEST_ONE_SHIFT(1, 40, u64, 1ULL << 40, false);
+	err |= TEST_ONE_SHIFT(1, 63, u64, 1ULL << 63, false);
+
+	/* Sane shift: start and end with 0, without a too-wide shift. */
+	err |= TEST_ONE_SHIFT(0, 7, u8, 0, false);
+	err |= TEST_ONE_SHIFT(0, 15, u16, 0, false);
+	err |= TEST_ONE_SHIFT(0, 31, unsigned int, 0, false);
+	err |= TEST_ONE_SHIFT(0, 31, u32, 0, false);
+	err |= TEST_ONE_SHIFT(0, 63, u64, 0, false);
+
+	/* Sane shift: start and end with 0, without reaching signed bit. */
+	err |= TEST_ONE_SHIFT(0, 6, s8, 0, false);
+	err |= TEST_ONE_SHIFT(0, 14, s16, 0, false);
+	err |= TEST_ONE_SHIFT(0, 30, int, 0, false);
+	err |= TEST_ONE_SHIFT(0, 30, s32, 0, false);
+	err |= TEST_ONE_SHIFT(0, 62, s64, 0, false);
+
+	/* Overflow: shifted the bit off the end. */
+	err |= TEST_ONE_SHIFT(1, 8, u8, 0, true);
+	err |= TEST_ONE_SHIFT(1, 16, u16, 0, true);
+	err |= TEST_ONE_SHIFT(1, 32, unsigned int, 0, true);
+	err |= TEST_ONE_SHIFT(1, 32, u32, 0, true);
+	err |= TEST_ONE_SHIFT(1, 64, u64, 0, true);
+
+	/* Overflow: high bit falls off. */
+	/* 10010110 */
+	err |= TEST_ONE_SHIFT(150, 1, u8, 0, true);
+	/* 1000100010010110 */
+	err |= TEST_ONE_SHIFT(34966, 1, u16, 0, true);
+	/* 10000100000010001000100010010110 */
+	err |= TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true);
+	err |= TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true);
+	/* 1000001000010000010000000100000010000100000010001000100010010110 */
+	err |= TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true);
+
+	/* Nonsense: negative initial value. */
+	err |= TEST_ONE_SHIFT(-1, 0, s8, 0, true);
+	err |= TEST_ONE_SHIFT(-5, 0, s16, 0, true);
+	err |= TEST_ONE_SHIFT(-10, 0, int, 0, true);
+	err |= TEST_ONE_SHIFT(-100, 0, s32, 0, true);
+	err |= TEST_ONE_SHIFT(-10000, 0, s64, 0, true);
+
+	/* Nonsense: negative shift values. */
+	err |= TEST_ONE_SHIFT(0, -5, s8, 0, true);
+	err |= TEST_ONE_SHIFT(0, -10, s16, 0, true);
+	err |= TEST_ONE_SHIFT(0, -15, int, 0, true);
+	err |= TEST_ONE_SHIFT(0, -20, s32, 0, true);
+	err |= TEST_ONE_SHIFT(0, -30, s64, 0, true);
+
+	/* Overflow: shifted at or beyond entire type's bit width. */
+	err |= TEST_ONE_SHIFT(0, 8, u8, 0, true);
+	err |= TEST_ONE_SHIFT(0, 9, u8, 0, true);
+	err |= TEST_ONE_SHIFT(0, 8, s8, 0, true);
+	err |= TEST_ONE_SHIFT(0, 9, s8, 0, true);
+	err |= TEST_ONE_SHIFT(0, 16, u16, 0, true);
+	err |= TEST_ONE_SHIFT(0, 17, u16, 0, true);
+	err |= TEST_ONE_SHIFT(0, 16, s16, 0, true);
+	err |= TEST_ONE_SHIFT(0, 17, s16, 0, true);
+	err |= TEST_ONE_SHIFT(0, 32, u32, 0, true);
+	err |= TEST_ONE_SHIFT(0, 33, u32, 0, true);
+	err |= TEST_ONE_SHIFT(0, 32, int, 0, true);
+	err |= TEST_ONE_SHIFT(0, 33, int, 0, true);
+	err |= TEST_ONE_SHIFT(0, 32, s32, 0, true);
+	err |= TEST_ONE_SHIFT(0, 33, s32, 0, true);
+	err |= TEST_ONE_SHIFT(0, 64, u64, 0, true);
+	err |= TEST_ONE_SHIFT(0, 65, u64, 0, true);
+	err |= TEST_ONE_SHIFT(0, 64, s64, 0, true);
+	err |= TEST_ONE_SHIFT(0, 65, s64, 0, true);
+
+	/* Overflow: shifted into signed bit. */
+	err |= TEST_ONE_SHIFT(1, 7, s8, 0, true);
+	err |= TEST_ONE_SHIFT(1, 15, s16, 0, true);
+	err |= TEST_ONE_SHIFT(1, 31, int, 0, true);
+	err |= TEST_ONE_SHIFT(1, 31, s32, 0, true);
+	err |= TEST_ONE_SHIFT(1, 63, s64, 0, true);
+
+	/*
+	 * Corner case: for unsigned types, we fail when we've shifted
+	 * through the entire width of bits. For signed types, we might
+	 * want to match this behavior, but that would mean noticing if
+	 * we shift through all but the signed bit, and this is not
+	 * currently detected (but we'll notice an overflow into the
+	 * signed bit). So, for now, we will test this condition but
+	 * mark it as not expected to overflow.
+	 */
+	err |= TEST_ONE_SHIFT(0, 7, s8, 0, false);
+	err |= TEST_ONE_SHIFT(0, 15, s16, 0, false);
+	err |= TEST_ONE_SHIFT(0, 31, int, 0, false);
+	err |= TEST_ONE_SHIFT(0, 31, s32, 0, false);
+	err |= TEST_ONE_SHIFT(0, 63, s64, 0, false);
+
+	return err;
+}
+
 /*
  * Deal with the various forms of allocator arguments. See comments above
  * the DEFINE_TEST_ALLOC() instances for mapping of the "bits".
@@ -397,6 +534,7 @@ static int __init test_module_init(void)
 	int err = 0;
 
 	err |= test_overflow_calculation();
+	err |= test_overflow_shift();
 	err |= test_overflow_allocation();
 
 	if (err) {
-- 
2.17.1


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

* [PATCH v2 3/3] RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq
  2018-08-01  0:00 [PATCH v2 0/3] overflow.h: Add arithmetic shift helper Kees Cook
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
  2018-08-01  0:00 ` [PATCH v2 2/3] test_overflow: Add shift overflow tests Kees Cook
@ 2018-08-01  0:00 ` Kees Cook
  2 siblings, 0 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01  0:00 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Kees Cook, Leon Romanovsky, stable, syzkaller, Jason Gunthorpe,
	Leon Romanovsky, Bart Van Assche, Doug Ledford, Dan Carpenter,
	linux-rdma, linux-kernel

From: Leon Romanovsky <leonro@mellanox.com>

[   61.182439] UBSAN: Undefined behaviour in drivers/infiniband/hw/mlx5/qp.c:5366:34
[   61.183673] shift exponent 4294967288 is too large for 32-bit type 'unsigned int'
[   61.185530] CPU: 0 PID: 639 Comm: qp Not tainted 4.18.0-rc1-00037-g4aa1d69a9c60-dirty #96
[   61.186981] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-2.fc27 04/01/2014
[   61.188315] Call Trace:
[   61.188661]  dump_stack+0xc7/0x13b
[   61.190427]  ubsan_epilogue+0x9/0x49
[   61.190899]  __ubsan_handle_shift_out_of_bounds+0x1ea/0x22f
[   61.197040]  mlx5_ib_create_wq+0x1c99/0x1d50
[   61.206632]  ib_uverbs_ex_create_wq+0x499/0x820
[   61.213892]  ib_uverbs_write+0x77e/0xae0
[   61.248018]  vfs_write+0x121/0x3b0
[   61.249831]  ksys_write+0xa1/0x120
[   61.254024]  do_syscall_64+0x7c/0x2a0
[   61.256178]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   61.259211] RIP: 0033:0x7f54bab70e99
[   61.262125] Code: 00 f3 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89
[   61.268678] RSP: 002b:00007ffe1541c318 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[   61.271076] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f54bab70e99
[   61.273795] RDX: 0000000000000070 RSI: 0000000020000240 RDI: 0000000000000003
[   61.276982] RBP: 00007ffe1541c330 R08: 00000000200078e0 R09: 0000000000000002
[   61.280035] R10: 0000000000000000 R11: 0000000000000246 R12: 00000000004005c0
[   61.283279] R13: 00007ffe1541c420 R14: 0000000000000000 R15: 0000000000000000

Cc: <stable@vger.kernel.org> # 4.7
Fixes: 79b20a6c3014 ("IB/mlx5: Add receive Work Queue verbs")
Cc: syzkaller <syzkaller@googlegroups.com>
Reported-by: Noa Osherovich <noaos@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/infiniband/hw/mlx5/qp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index a4f1f638509f..7fc156db643d 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -5365,7 +5365,10 @@ static int set_user_rq_size(struct mlx5_ib_dev *dev,
 
 	rwq->wqe_count = ucmd->rq_wqe_count;
 	rwq->wqe_shift = ucmd->rq_wqe_shift;
-	rwq->buf_size = (rwq->wqe_count << rwq->wqe_shift);
+	if (check_shift_overflow(rwq->wqe_count, rwq->wqe_shift,
+				 &rwq->buf_size))
+		return -EINVAL;
+
 	rwq->log_rq_stride = rwq->wqe_shift;
 	rwq->log_rq_size = ilog2(rwq->wqe_count);
 	return 0;
-- 
2.17.1


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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
@ 2018-08-01  1:59   ` Randy Dunlap
  2018-08-01  2:15   ` Jason Gunthorpe
  2018-08-01  7:57   ` Dan Carpenter
  2 siblings, 0 replies; 13+ messages in thread
From: Randy Dunlap @ 2018-08-01  1:59 UTC (permalink / raw)
  To: Kees Cook, Rasmus Villemoes
  Cc: Jason Gunthorpe, Leon Romanovsky, Jason Gunthorpe,
	Leon Romanovsky, Bart Van Assche, Doug Ledford, Dan Carpenter,
	linux-rdma, linux-kernel

On 07/31/2018 05:00 PM, Kees Cook wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
> 
> Add shift_overflow() helper to assist driver authors in ensuring that
> shift operations don't cause overflows or other odd conditions.
> 
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
> [kees: tweaked comments and commit log, dropped unneeded assignment]
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  include/linux/overflow.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
> index 8712ff70995f..69fc366ce865 100644
> --- a/include/linux/overflow.h
> +++ b/include/linux/overflow.h
> @@ -202,6 +202,37 @@
>  
>  #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
>  
> +/** check_shift_overflow() - Calculate a left-shifted value and check overflow
> + *
> + * @a: Value to be shifted
> + * @b: How many bits left to shift
> + * @d: Pointer to where to store the result
> + *
> + * Computes *@d = (@a << @s)

                            @b)

> + *
> + * Returns true if '*d' cannot hold the result or when 'a << s' doesn't
> + * make sense. Example conditions:
> + * - 'a << s' causes bits to be lost when stored in *d.
> + * - 's' is garbage (e.g. negative) or so large that the result of
> + *   'a << s' is guaranteed to be 0.
> + * - 'a' is negative.
> + * - 'a << s' sets the sign bit, if any, in '*d'.
> + *
> + * '*d' will hold the results of the attempted shift, but is not
> + * considered "safe for use" if false is returned.
> + */
> +#define check_shift_overflow(a, s, d) ({				\
> +	typeof(a) _a = a;						\
> +	typeof(s) _s = s;						\
> +	typeof(d) _d = d;						\
> +	u64 _a_full = _a;						\
> +	unsigned int _to_shift =					\
> +		_s >= 0 && _s < 8 * sizeof(*d) ? _s : 0;		\
> +	*_d = (_a_full << _to_shift);					\
> +	(_to_shift != _s || *_d < 0 || _a < 0 ||			\
> +		(*_d >> _to_shift) != _a);				\
> +})
> +
>  /**
>   * array_size() - Calculate size of 2-dimensional array.
>   *
> 


-- 
~Randy

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

* Re: [PATCH v2 2/3] test_overflow: Add shift overflow tests
  2018-08-01  0:00 ` [PATCH v2 2/3] test_overflow: Add shift overflow tests Kees Cook
@ 2018-08-01  2:13   ` Jason Gunthorpe
  2018-08-01  5:51     ` Kees Cook
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Gunthorpe @ 2018-08-01  2:13 UTC (permalink / raw)
  To: Kees Cook
  Cc: Rasmus Villemoes, Leon Romanovsky, Bart Van Assche, Doug Ledford,
	Dan Carpenter, linux-rdma, linux-kernel

On Tue, Jul 31, 2018 at 05:00:38PM -0700, Kees Cook wrote:
> +	/* Overflow: high bit falls off. */
> +	/* 10010110 */
> +	err |= TEST_ONE_SHIFT(150, 1, u8, 0, true);
> +	/* 1000100010010110 */
> +	err |= TEST_ONE_SHIFT(34966, 1, u16, 0, true);
> +	/* 10000100000010001000100010010110 */
> +	err |= TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true);
> +	err |= TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true);
> +	/* 1000001000010000010000000100000010000100000010001000100010010110 */
> +	err |= TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true);

This same idea should be repeated with signed outputs and check both
overflow past the end (<<2) and overflow into the signed bit (<<1)

        /* Overflow, high bit falls into the sign bit or off the end */
	/* 01001011 */
	err |= TEST_ONE_SHIFT(75, 1, s8, 0, true);
	err |= TEST_ONE_SHIFT(75, 2, s8, 0, true);

And also general type mismatch overflow:

	err |= TEST_ONE_SHIFT(0x100, 0, u8, 0, true);
	err |= TEST_ONE_SHIFT(0xFF, 0, s8, 0, true);

Thanks,
Jason

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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
  2018-08-01  1:59   ` Randy Dunlap
@ 2018-08-01  2:15   ` Jason Gunthorpe
  2018-08-01  4:22     ` Kees Cook
  2018-08-01  7:57   ` Dan Carpenter
  2 siblings, 1 reply; 13+ messages in thread
From: Jason Gunthorpe @ 2018-08-01  2:15 UTC (permalink / raw)
  To: Kees Cook
  Cc: Rasmus Villemoes, Leon Romanovsky, Leon Romanovsky,
	Bart Van Assche, Doug Ledford, Dan Carpenter, linux-rdma,
	linux-kernel

On Tue, Jul 31, 2018 at 05:00:37PM -0700, Kees Cook wrote:
> From: Jason Gunthorpe <jgg@mellanox.com>
> 
> Add shift_overflow() helper to assist driver authors in ensuring that
> shift operations don't cause overflows or other odd conditions.
> 
> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
> [kees: tweaked comments and commit log, dropped unneeded assignment]
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  include/linux/overflow.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
> index 8712ff70995f..69fc366ce865 100644
> --- a/include/linux/overflow.h
> +++ b/include/linux/overflow.h
> @@ -202,6 +202,37 @@
>  
>  #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
>  
> +/** check_shift_overflow() - Calculate a left-shifted value and check overflow
> + *
> + * @a: Value to be shifted
> + * @b: How many bits left to shift

The above @b should be @s

> +#define check_shift_overflow(a, s, d) ({				\

Should I run this series through the rdma tree?

Thanks,
Jason

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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  2:15   ` Jason Gunthorpe
@ 2018-08-01  4:22     ` Kees Cook
  0 siblings, 0 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01  4:22 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Rasmus Villemoes, Leon Romanovsky, Leon Romanovsky,
	Bart Van Assche, Doug Ledford, Dan Carpenter, linux-rdma, LKML

On Tue, Jul 31, 2018 at 7:15 PM, Jason Gunthorpe <jgg@ziepe.ca> wrote:
> On Tue, Jul 31, 2018 at 05:00:37PM -0700, Kees Cook wrote:
>> From: Jason Gunthorpe <jgg@mellanox.com>
>>
>> Add shift_overflow() helper to assist driver authors in ensuring that
>> shift operations don't cause overflows or other odd conditions.
>>
>> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
>> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
>> [kees: tweaked comments and commit log, dropped unneeded assignment]
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>> ---
>>  include/linux/overflow.h | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
>> index 8712ff70995f..69fc366ce865 100644
>> --- a/include/linux/overflow.h
>> +++ b/include/linux/overflow.h
>> @@ -202,6 +202,37 @@
>>
>>  #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
>>
>> +/** check_shift_overflow() - Calculate a left-shifted value and check overflow
>> + *
>> + * @a: Value to be shifted
>> + * @b: How many bits left to shift
>
> The above @b should be @s

Ooops, copy-paste-o. :)

>
>> +#define check_shift_overflow(a, s, d) ({                             \
>
> Should I run this series through the rdma tree?

I'd like to get Rasmus's Ack, but otherwise, yes, that'd be fine.

-Kees

-- 
Kees Cook
Pixel Security

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

* Re: [PATCH v2 2/3] test_overflow: Add shift overflow tests
  2018-08-01  2:13   ` Jason Gunthorpe
@ 2018-08-01  5:51     ` Kees Cook
  0 siblings, 0 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01  5:51 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Rasmus Villemoes, Leon Romanovsky, Bart Van Assche, Doug Ledford,
	Dan Carpenter, linux-rdma, LKML

On Tue, Jul 31, 2018 at 7:13 PM, Jason Gunthorpe <jgg@ziepe.ca> wrote:
> On Tue, Jul 31, 2018 at 05:00:38PM -0700, Kees Cook wrote:
>> +     /* Overflow: high bit falls off. */
>> +     /* 10010110 */
>> +     err |= TEST_ONE_SHIFT(150, 1, u8, 0, true);
>> +     /* 1000100010010110 */
>> +     err |= TEST_ONE_SHIFT(34966, 1, u16, 0, true);
>> +     /* 10000100000010001000100010010110 */
>> +     err |= TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true);
>> +     err |= TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true);
>> +     /* 1000001000010000010000000100000010000100000010001000100010010110 */
>> +     err |= TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true);
>
> This same idea should be repeated with signed outputs and check both
> overflow past the end (<<2) and overflow into the signed bit (<<1)
>
>         /* Overflow, high bit falls into the sign bit or off the end */
>         /* 01001011 */
>         err |= TEST_ONE_SHIFT(75, 1, s8, 0, true);
>         err |= TEST_ONE_SHIFT(75, 2, s8, 0, true);
>
> And also general type mismatch overflow:
>
>         err |= TEST_ONE_SHIFT(0x100, 0, u8, 0, true);
>         err |= TEST_ONE_SHIFT(0xFF, 0, s8, 0, true);

Ah yes, thanks. I've added these for the next version now.

-Kees

-- 
Kees Cook
Pixel Security

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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
  2018-08-01  1:59   ` Randy Dunlap
  2018-08-01  2:15   ` Jason Gunthorpe
@ 2018-08-01  7:57   ` Dan Carpenter
  2018-08-01  8:07     ` Dan Carpenter
  2 siblings, 1 reply; 13+ messages in thread
From: Dan Carpenter @ 2018-08-01  7:57 UTC (permalink / raw)
  To: Kees Cook
  Cc: Rasmus Villemoes, Jason Gunthorpe, Leon Romanovsky,
	Jason Gunthorpe, Leon Romanovsky, Bart Van Assche, Doug Ledford,
	linux-rdma, linux-kernel

The idea is nice, but I don't like the API.  The "_overflow" feels too
specific because maybe we could check for other things in the future.
Normally boolean macros should say they are boolean in the name and I
would prefer if it returned zero on failure.

	if (!checked_shift(dest, mask, shift)) {
	if (!shift_ok(dest, mask, shift)) {
	if (!safe_shift(dest, mask, shift)) {

regards,
dan carpenter


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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  7:57   ` Dan Carpenter
@ 2018-08-01  8:07     ` Dan Carpenter
  2018-08-01 15:38       ` Kees Cook
  2018-08-01 15:48       ` Jason Gunthorpe
  0 siblings, 2 replies; 13+ messages in thread
From: Dan Carpenter @ 2018-08-01  8:07 UTC (permalink / raw)
  To: Kees Cook
  Cc: Rasmus Villemoes, Jason Gunthorpe, Leon Romanovsky,
	Jason Gunthorpe, Leon Romanovsky, Bart Van Assche, Doug Ledford,
	linux-rdma, linux-kernel

On Wed, Aug 01, 2018 at 10:57:44AM +0300, Dan Carpenter wrote:
> The idea is nice, but I don't like the API.  The "_overflow" feels too
> specific because maybe we could check for other things in the future.
> Normally boolean macros should say they are boolean in the name and I
> would prefer if it returned zero on failure.
> 
> 	if (!checked_shift(dest, mask, shift)) {
> 	if (!shift_ok(dest, mask, shift)) {
> 	if (!safe_shift(dest, mask, shift)) {

Huh...  It turns out I put the argument order different as well.

If we wanted to keep it returning 1 on failure then some other names
are:

	if (shift_failed(dest, mask, shift)) {
	if (shift_error(dest, mask, shift)) {
	if (shift_overflow(dest, mask, shift)) {

regards,
dan carpenter


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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  8:07     ` Dan Carpenter
@ 2018-08-01 15:38       ` Kees Cook
  2018-08-01 15:48       ` Jason Gunthorpe
  1 sibling, 0 replies; 13+ messages in thread
From: Kees Cook @ 2018-08-01 15:38 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Rasmus Villemoes, Jason Gunthorpe, Leon Romanovsky,
	Jason Gunthorpe, Leon Romanovsky, Bart Van Assche, Doug Ledford,
	linux-rdma, LKML

On Wed, Aug 1, 2018 at 1:07 AM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
> On Wed, Aug 01, 2018 at 10:57:44AM +0300, Dan Carpenter wrote:
>> The idea is nice, but I don't like the API.  The "_overflow" feels too
>> specific because maybe we could check for other things in the future.
>> Normally boolean macros should say they are boolean in the name and I
>> would prefer if it returned zero on failure.
>>
>>       if (!checked_shift(dest, mask, shift)) {
>>       if (!shift_ok(dest, mask, shift)) {
>>       if (!safe_shift(dest, mask, shift)) {
>
> Huh...  It turns out I put the argument order different as well.
>
> If we wanted to keep it returning 1 on failure then some other names
> are:
>
>         if (shift_failed(dest, mask, shift)) {
>         if (shift_error(dest, mask, shift)) {
>         if (shift_overflow(dest, mask, shift)) {

This is following the existing check_{add,mul}_overflow() helpers,
which are based on the gcc helpers. I'd like to keep things
consistent.

-Kees

-- 
Kees Cook
Pixel Security

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

* Re: [PATCH v2 1/3] overflow.h: Add arithmetic shift helper
  2018-08-01  8:07     ` Dan Carpenter
  2018-08-01 15:38       ` Kees Cook
@ 2018-08-01 15:48       ` Jason Gunthorpe
  1 sibling, 0 replies; 13+ messages in thread
From: Jason Gunthorpe @ 2018-08-01 15:48 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Kees Cook, Rasmus Villemoes, Leon Romanovsky, Leon Romanovsky,
	Bart Van Assche, Doug Ledford, linux-rdma, linux-kernel

On Wed, Aug 01, 2018 at 11:07:24AM +0300, Dan Carpenter wrote:
> On Wed, Aug 01, 2018 at 10:57:44AM +0300, Dan Carpenter wrote:
> > The idea is nice, but I don't like the API.  The "_overflow" feels too
> > specific because maybe we could check for other things in the future.
> > Normally boolean macros should say they are boolean in the name and I
> > would prefer if it returned zero on failure.
> > 
> > 	if (!checked_shift(dest, mask, shift)) {
> > 	if (!shift_ok(dest, mask, shift)) {
> > 	if (!safe_shift(dest, mask, shift)) {
> 
> Huh...  It turns out I put the argument order different as well.
> 
> If we wanted to keep it returning 1 on failure then some other names
> are:
> 
> 	if (shift_failed(dest, mask, shift)) {
> 	if (shift_error(dest, mask, shift)) {
> 	if (shift_overflow(dest, mask, shift)) {

I think this ship has sailed, the convention for these tests is
already established in overflow.h. ie:

check_add_overflow
check_sub_overflow
check_mul_overflow

Jason

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

end of thread, other threads:[~2018-08-01 15:48 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-01  0:00 [PATCH v2 0/3] overflow.h: Add arithmetic shift helper Kees Cook
2018-08-01  0:00 ` [PATCH v2 1/3] " Kees Cook
2018-08-01  1:59   ` Randy Dunlap
2018-08-01  2:15   ` Jason Gunthorpe
2018-08-01  4:22     ` Kees Cook
2018-08-01  7:57   ` Dan Carpenter
2018-08-01  8:07     ` Dan Carpenter
2018-08-01 15:38       ` Kees Cook
2018-08-01 15:48       ` Jason Gunthorpe
2018-08-01  0:00 ` [PATCH v2 2/3] test_overflow: Add shift overflow tests Kees Cook
2018-08-01  2:13   ` Jason Gunthorpe
2018-08-01  5:51     ` Kees Cook
2018-08-01  0:00 ` [PATCH v2 3/3] RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).