]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/include-linux-bitops.h-sanitize-rotate-primitives.patch
Linux 4.9.181
[thirdparty/kernel/stable-queue.git] / queue-4.4 / include-linux-bitops.h-sanitize-rotate-primitives.patch
1 From ef4d6f6b275c498f8e5626c99dbeefdc5027f843 Mon Sep 17 00:00:00 2001
2 From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
3 Date: Tue, 14 May 2019 15:43:27 -0700
4 Subject: include/linux/bitops.h: sanitize rotate primitives
5
6 From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
7
8 commit ef4d6f6b275c498f8e5626c99dbeefdc5027f843 upstream.
9
10 The ror32 implementation (word >> shift) | (word << (32 - shift) has
11 undefined behaviour if shift is outside the [1, 31] range. Similarly
12 for the 64 bit variants. Most callers pass a compile-time constant
13 (naturally in that range), but there's an UBSAN report that these may
14 actually be called with a shift count of 0.
15
16 Instead of special-casing that, we can make them DTRT for all values of
17 shift while also avoiding UB. For some reason, this was already partly
18 done for rol32 (which was well-defined for [0, 31]). gcc 8 recognizes
19 these patterns as rotates, so for example
20
21 __u32 rol32(__u32 word, unsigned int shift)
22 {
23 return (word << (shift & 31)) | (word >> ((-shift) & 31));
24 }
25
26 compiles to
27
28 0000000000000020 <rol32>:
29 20: 89 f8 mov %edi,%eax
30 22: 89 f1 mov %esi,%ecx
31 24: d3 c0 rol %cl,%eax
32 26: c3 retq
33
34 Older compilers unfortunately do not do as well, but this only affects
35 the small minority of users that don't pass constants.
36
37 Due to integer promotions, ro[lr]8 were already well-defined for shifts
38 in [0, 8], and ro[lr]16 were mostly well-defined for shifts in [0, 16]
39 (only mostly - u16 gets promoted to _signed_ int, so if bit 15 is set,
40 word << 16 is undefined). For consistency, update those as well.
41
42 Link: http://lkml.kernel.org/r/20190410211906.2190-1-linux@rasmusvillemoes.dk
43 Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
44 Reported-by: Ido Schimmel <idosch@mellanox.com>
45 Tested-by: Ido Schimmel <idosch@mellanox.com>
46 Reviewed-by: Will Deacon <will.deacon@arm.com>
47 Cc: Vadim Pasternak <vadimp@mellanox.com>
48 Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
49 Cc: Jacek Anaszewski <jacek.anaszewski@gmail.com>
50 Cc: Pavel Machek <pavel@ucw.cz>
51 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
52 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
53 Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
54 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
55
56 ---
57 include/linux/bitops.h | 16 ++++++++--------
58 1 file changed, 8 insertions(+), 8 deletions(-)
59
60 --- a/include/linux/bitops.h
61 +++ b/include/linux/bitops.h
62 @@ -68,7 +68,7 @@ static __always_inline unsigned long hwe
63 */
64 static inline __u64 rol64(__u64 word, unsigned int shift)
65 {
66 - return (word << shift) | (word >> (64 - shift));
67 + return (word << (shift & 63)) | (word >> ((-shift) & 63));
68 }
69
70 /**
71 @@ -78,7 +78,7 @@ static inline __u64 rol64(__u64 word, un
72 */
73 static inline __u64 ror64(__u64 word, unsigned int shift)
74 {
75 - return (word >> shift) | (word << (64 - shift));
76 + return (word >> (shift & 63)) | (word << ((-shift) & 63));
77 }
78
79 /**
80 @@ -88,7 +88,7 @@ static inline __u64 ror64(__u64 word, un
81 */
82 static inline __u32 rol32(__u32 word, unsigned int shift)
83 {
84 - return (word << shift) | (word >> ((-shift) & 31));
85 + return (word << (shift & 31)) | (word >> ((-shift) & 31));
86 }
87
88 /**
89 @@ -98,7 +98,7 @@ static inline __u32 rol32(__u32 word, un
90 */
91 static inline __u32 ror32(__u32 word, unsigned int shift)
92 {
93 - return (word >> shift) | (word << (32 - shift));
94 + return (word >> (shift & 31)) | (word << ((-shift) & 31));
95 }
96
97 /**
98 @@ -108,7 +108,7 @@ static inline __u32 ror32(__u32 word, un
99 */
100 static inline __u16 rol16(__u16 word, unsigned int shift)
101 {
102 - return (word << shift) | (word >> (16 - shift));
103 + return (word << (shift & 15)) | (word >> ((-shift) & 15));
104 }
105
106 /**
107 @@ -118,7 +118,7 @@ static inline __u16 rol16(__u16 word, un
108 */
109 static inline __u16 ror16(__u16 word, unsigned int shift)
110 {
111 - return (word >> shift) | (word << (16 - shift));
112 + return (word >> (shift & 15)) | (word << ((-shift) & 15));
113 }
114
115 /**
116 @@ -128,7 +128,7 @@ static inline __u16 ror16(__u16 word, un
117 */
118 static inline __u8 rol8(__u8 word, unsigned int shift)
119 {
120 - return (word << shift) | (word >> (8 - shift));
121 + return (word << (shift & 7)) | (word >> ((-shift) & 7));
122 }
123
124 /**
125 @@ -138,7 +138,7 @@ static inline __u8 rol8(__u8 word, unsig
126 */
127 static inline __u8 ror8(__u8 word, unsigned int shift)
128 {
129 - return (word >> shift) | (word << (8 - shift));
130 + return (word >> (shift & 7)) | (word << ((-shift) & 7));
131 }
132
133 /**