From d72286943212fdb6d254d08d4cfccdc70603d0ca Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 8 Oct 2020 16:58:18 +1100 Subject: lib/mpi: Remove unused scalar_copied The scalar_copied variable is not as the scalar is never copied in that block. This patch removes it. Fixes: d58bb7e55a8a ("lib/mpi: Introduce ec implementation to...") Reported-by: Gustavo A. R. Silva Signed-off-by: Herbert Xu --- lib/mpi/ec.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib') diff --git a/lib/mpi/ec.c b/lib/mpi/ec.c index c21470122dfc..40f5908e57a4 100644 --- a/lib/mpi/ec.c +++ b/lib/mpi/ec.c @@ -1252,7 +1252,6 @@ void mpi_ec_mul_point(MPI_POINT result, MPI_POINT q1, q2, prd, sum; unsigned long sw; mpi_size_t rsize; - int scalar_copied = 0; /* Compute scalar point multiplication with Montgomery Ladder. * Note that we don't use Y-coordinate in the points at all. @@ -1314,8 +1313,6 @@ void mpi_ec_mul_point(MPI_POINT result, point_free(&p2); point_free(&p1_); point_free(&p2_); - if (scalar_copied) - mpi_free(scalar); return; } -- cgit v1.2.3 From 1762818f25f3f99c5083caa13d69e5e5aa2e4b6f Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Sun, 25 Oct 2020 10:31:14 -0400 Subject: crypto: lib/sha256 - Use memzero_explicit() for clearing state Without the barrier_data() inside memzero_explicit(), the compiler may optimize away the state-clearing if it can tell that the state is not used afterwards. At least in lib/crypto/sha256.c:__sha256_final(), the function can get inlined into sha256(), in which case the memset is optimized away. Signed-off-by: Arvind Sankar Reviewed-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index 2321f6cb322f..d43bc39ab05e 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -265,7 +265,7 @@ static void __sha256_final(struct sha256_state *sctx, u8 *out, int digest_words) put_unaligned_be32(sctx->state[i], &dst[i]); /* Zeroize sensitive information. */ - memset(sctx, 0, sizeof(*sctx)); + memzero_explicit(sctx, sizeof(*sctx)); } void sha256_final(struct sha256_state *sctx, u8 *out) -- cgit v1.2.3 From 7a4295f6c9d54e082474667e552a227606b4a085 Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Sun, 25 Oct 2020 10:31:16 -0400 Subject: crypto: lib/sha256 - Don't clear temporary variables The assignments to clear a through h and t1/t2 are optimized out by the compiler because they are unused after the assignments. Clearing individual scalar variables is unlikely to be useful, as they may have been assigned to registers, and even if stack spilling was required, there may be compiler-generated temporaries that are impossible to clear in any case. So drop the clearing of a through h and t1/t2. Signed-off-by: Arvind Sankar Reviewed-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index d43bc39ab05e..099cd11f83c1 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -202,7 +202,6 @@ static void sha256_transform(u32 *state, const u8 *input) state[4] += e; state[5] += f; state[6] += g; state[7] += h; /* clear any sensitive info... */ - a = b = c = d = e = f = g = h = t1 = t2 = 0; memzero_explicit(W, 64 * sizeof(u32)); } -- cgit v1.2.3 From b8399819b2dd6f29195ed7535217b66c01b1e57d Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Sun, 25 Oct 2020 10:31:17 -0400 Subject: crypto: lib/sha256 - Clear W[] in sha256_update() instead of sha256_transform() The temporary W[] array is currently zeroed out once every call to sha256_transform(), i.e. once every 64 bytes of input data. Moving it to sha256_update() instead so that it is cleared only once per update can save about 2-3% of the total time taken to compute the digest, with a reasonable memset() implementation, and considerably more (~20%) with a bad one (eg the x86 purgatory currently uses a memset() coded in C). Signed-off-by: Arvind Sankar Reviewed-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index 099cd11f83c1..c6bfeacc5b81 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -43,10 +43,9 @@ static inline void BLEND_OP(int I, u32 *W) W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; } -static void sha256_transform(u32 *state, const u8 *input) +static void sha256_transform(u32 *state, const u8 *input, u32 *W) { u32 a, b, c, d, e, f, g, h, t1, t2; - u32 W[64]; int i; /* load the input */ @@ -200,15 +199,13 @@ static void sha256_transform(u32 *state, const u8 *input) state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; - - /* clear any sensitive info... */ - memzero_explicit(W, 64 * sizeof(u32)); } void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) { unsigned int partial, done; const u8 *src; + u32 W[64]; partial = sctx->count & 0x3f; sctx->count += len; @@ -223,11 +220,13 @@ void sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len) } do { - sha256_transform(sctx->state, src); + sha256_transform(sctx->state, src, W); done += 64; src = data + done; } while (done + 63 < len); + memzero_explicit(W, sizeof(W)); + partial = 0; } memcpy(sctx->buf + partial, src, len - done); -- cgit v1.2.3 From 63642d5c141f1bcbe97f7895467a724ad2e3f346 Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Sun, 25 Oct 2020 10:31:18 -0400 Subject: crypto: lib/sha256 - Unroll SHA256 loop 8 times intead of 64 This reduces code size substantially (on x86_64 with gcc-10 the size of sha256_update() goes from 7593 bytes to 1952 bytes including the new SHA256_K array), and on x86 is slightly faster than the full unroll (tested on Broadwell Xeon). Signed-off-by: Arvind Sankar Reviewed-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 174 ++++++++++++---------------------------------------- 1 file changed, 38 insertions(+), 136 deletions(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index c6bfeacc5b81..e2e29d9b0ccd 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -18,6 +18,25 @@ #include #include +static const u32 SHA256_K[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; + static inline u32 Ch(u32 x, u32 y, u32 z) { return z ^ (x & (y ^ z)); @@ -43,9 +62,17 @@ static inline void BLEND_OP(int I, u32 *W) W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16]; } +#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) do { \ + u32 t1, t2; \ + t1 = h + e1(e) + Ch(e, f, g) + SHA256_K[i] + W[i]; \ + t2 = e0(a) + Maj(a, b, c); \ + d += t1; \ + h = t1 + t2; \ +} while (0) + static void sha256_transform(u32 *state, const u8 *input, u32 *W) { - u32 a, b, c, d, e, f, g, h, t1, t2; + u32 a, b, c, d, e, f, g, h; int i; /* load the input */ @@ -61,141 +88,16 @@ static void sha256_transform(u32 *state, const u8 *input, u32 *W) e = state[4]; f = state[5]; g = state[6]; h = state[7]; /* now iterate */ - t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; - - t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56]; - t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; - t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57]; - t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; - t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58]; - t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; - t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59]; - t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; - t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60]; - t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; - t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61]; - t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; - t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62]; - t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; - t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63]; - t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; + for (i = 0; i < 64; i += 8) { + SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h); + SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g); + SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f); + SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e); + SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d); + SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c); + SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b); + SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a); + } state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; -- cgit v1.2.3 From 18d05ca4486fe38991c3166b1f4df26b8a029665 Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Sun, 25 Oct 2020 10:31:19 -0400 Subject: crypto: lib/sha256 - Unroll LOAD and BLEND loops Unrolling the LOAD and BLEND loops improves performance by ~8% on x86_64 (tested on Broadwell Xeon) while not increasing code size too much. Signed-off-by: Arvind Sankar Reviewed-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index e2e29d9b0ccd..cdef37c05972 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -76,12 +76,28 @@ static void sha256_transform(u32 *state, const u8 *input, u32 *W) int i; /* load the input */ - for (i = 0; i < 16; i++) - LOAD_OP(i, W, input); + for (i = 0; i < 16; i += 8) { + LOAD_OP(i + 0, W, input); + LOAD_OP(i + 1, W, input); + LOAD_OP(i + 2, W, input); + LOAD_OP(i + 3, W, input); + LOAD_OP(i + 4, W, input); + LOAD_OP(i + 5, W, input); + LOAD_OP(i + 6, W, input); + LOAD_OP(i + 7, W, input); + } /* now blend */ - for (i = 16; i < 64; i++) - BLEND_OP(i, W); + for (i = 16; i < 64; i += 8) { + BLEND_OP(i + 0, W); + BLEND_OP(i + 1, W); + BLEND_OP(i + 2, W); + BLEND_OP(i + 3, W); + BLEND_OP(i + 4, W); + BLEND_OP(i + 5, W); + BLEND_OP(i + 6, W); + BLEND_OP(i + 7, W); + } /* load the state into our registers */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; -- cgit v1.2.3 From 58b999d7a22c59313e1e84832607c7a61640f4e7 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Sun, 1 Nov 2020 17:07:37 -0800 Subject: kasan: adopt KUNIT tests to SW_TAGS mode Now that we have KASAN-KUNIT tests integration, it's easy to see that some KASAN tests are not adopted to the SW_TAGS mode and are failing. Adjust the allocation size for kasan_memchr() and kasan_memcmp() by roung it up to OOB_TAG_OFF so the bad access ends up in a separate memory granule. Add a new kmalloc_uaf_16() tests that relies on UAF, and a new kasan_bitops_tags() test that is tailored to tag-based mode, as it's hard to adopt the existing kmalloc_oob_16() and kasan_bitops_generic() (renamed from kasan_bitops()) without losing the precision. Add new kmalloc_uaf_16() and kasan_bitops_uaf() tests that rely on UAFs, as it's hard to adopt the existing kmalloc_oob_16() and kasan_bitops_oob() (rename from kasan_bitops()) without losing the precision. Disable kasan_global_oob() and kasan_alloca_oob_left/right() as SW_TAGS mode doesn't instrument globals nor dynamic allocas. Signed-off-by: Andrey Konovalov Signed-off-by: Andrew Morton Tested-by: David Gow Link: https://lkml.kernel.org/r/76eee17b6531ca8b3ca92b240cb2fd23204aaff7.1603129942.git.andreyknvl@google.com Signed-off-by: Linus Torvalds --- lib/test_kasan.c | 149 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 107 insertions(+), 42 deletions(-) (limited to 'lib') diff --git a/lib/test_kasan.c b/lib/test_kasan.c index 63c26171a791..662f862702fc 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -216,6 +216,12 @@ static void kmalloc_oob_16(struct kunit *test) u64 words[2]; } *ptr1, *ptr2; + /* This test is specifically crafted for the generic mode. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_GENERIC required\n"); + return; + } + ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); @@ -227,6 +233,23 @@ static void kmalloc_oob_16(struct kunit *test) kfree(ptr2); } +static void kmalloc_uaf_16(struct kunit *test) +{ + struct { + u64 words[2]; + } *ptr1, *ptr2; + + ptr1 = kmalloc(sizeof(*ptr1), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); + + ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2); + kfree(ptr2); + + KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2); + kfree(ptr1); +} + static void kmalloc_oob_memset_2(struct kunit *test) { char *ptr; @@ -429,6 +452,12 @@ static void kasan_global_oob(struct kunit *test) volatile int i = 3; char *p = &global_array[ARRAY_SIZE(global_array) + i]; + /* Only generic mode instruments globals. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_GENERIC required"); + return; + } + KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); } @@ -467,6 +496,12 @@ static void kasan_alloca_oob_left(struct kunit *test) char alloca_array[i]; char *p = alloca_array - 1; + /* Only generic mode instruments dynamic allocas. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_GENERIC required"); + return; + } + if (!IS_ENABLED(CONFIG_KASAN_STACK)) { kunit_info(test, "CONFIG_KASAN_STACK is not enabled"); return; @@ -481,6 +516,12 @@ static void kasan_alloca_oob_right(struct kunit *test) char alloca_array[i]; char *p = alloca_array + i; + /* Only generic mode instruments dynamic allocas. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_GENERIC required"); + return; + } + if (!IS_ENABLED(CONFIG_KASAN_STACK)) { kunit_info(test, "CONFIG_KASAN_STACK is not enabled"); return; @@ -551,6 +592,9 @@ static void kasan_memchr(struct kunit *test) return; } + if (OOB_TAG_OFF) + size = round_up(size, OOB_TAG_OFF); + ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -573,6 +617,9 @@ static void kasan_memcmp(struct kunit *test) return; } + if (OOB_TAG_OFF) + size = round_up(size, OOB_TAG_OFF); + ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); memset(arr, 0, sizeof(arr)); @@ -619,13 +666,50 @@ static void kasan_strings(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = strnlen(ptr, 1)); } -static void kasan_bitops(struct kunit *test) +static void kasan_bitops_modify(struct kunit *test, int nr, void *addr) +{ + KUNIT_EXPECT_KASAN_FAIL(test, set_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __set_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, clear_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, clear_bit_unlock(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit_unlock(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, change_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __change_bit(nr, addr)); +} + +static void kasan_bitops_test_and_modify(struct kunit *test, int nr, void *addr) +{ + KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __test_and_set_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, test_and_set_bit_lock(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, test_and_clear_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __test_and_clear_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, test_and_change_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, __test_and_change_bit(nr, addr)); + KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = test_bit(nr, addr)); + +#if defined(clear_bit_unlock_is_negative_byte) + KUNIT_EXPECT_KASAN_FAIL(test, kasan_int_result = + clear_bit_unlock_is_negative_byte(nr, addr)); +#endif +} + +static void kasan_bitops_generic(struct kunit *test) { + long *bits; + + /* This test is specifically crafted for the generic mode. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_GENERIC required\n"); + return; + } + /* * Allocate 1 more byte, which causes kzalloc to round up to 16-bytes; * this way we do not actually corrupt other memory. */ - long *bits = kzalloc(sizeof(*bits) + 1, GFP_KERNEL); + bits = kzalloc(sizeof(*bits) + 1, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits); /* @@ -633,55 +717,34 @@ static void kasan_bitops(struct kunit *test) * below accesses are still out-of-bounds, since bitops are defined to * operate on the whole long the bit is in. */ - KUNIT_EXPECT_KASAN_FAIL(test, set_bit(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, __set_bit(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, clear_bit(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, clear_bit_unlock(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, __clear_bit_unlock(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, change_bit(BITS_PER_LONG, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, __change_bit(BITS_PER_LONG, bits)); + kasan_bitops_modify(test, BITS_PER_LONG, bits); /* * Below calls try to access bit beyond allocated memory. */ - KUNIT_EXPECT_KASAN_FAIL(test, - test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, - __test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); - - KUNIT_EXPECT_KASAN_FAIL(test, - test_and_set_bit_lock(BITS_PER_LONG + BITS_PER_BYTE, bits)); + kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, bits); - KUNIT_EXPECT_KASAN_FAIL(test, - test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); + kfree(bits); +} - KUNIT_EXPECT_KASAN_FAIL(test, - __test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); +static void kasan_bitops_tags(struct kunit *test) +{ + long *bits; - KUNIT_EXPECT_KASAN_FAIL(test, - test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); + /* This test is specifically crafted for the tag-based mode. */ + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) { + kunit_info(test, "CONFIG_KASAN_SW_TAGS required\n"); + return; + } - KUNIT_EXPECT_KASAN_FAIL(test, - __test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); + /* Allocation size will be rounded to up granule size, which is 16. */ + bits = kzalloc(sizeof(*bits), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bits); - KUNIT_EXPECT_KASAN_FAIL(test, - kasan_int_result = - test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits)); + /* Do the accesses past the 16 allocated bytes. */ + kasan_bitops_modify(test, BITS_PER_LONG, &bits[1]); + kasan_bitops_test_and_modify(test, BITS_PER_LONG + BITS_PER_BYTE, &bits[1]); -#if defined(clear_bit_unlock_is_negative_byte) - KUNIT_EXPECT_KASAN_FAIL(test, - kasan_int_result = clear_bit_unlock_is_negative_byte( - BITS_PER_LONG + BITS_PER_BYTE, bits)); -#endif kfree(bits); } @@ -728,6 +791,7 @@ static struct kunit_case kasan_kunit_test_cases[] = { KUNIT_CASE(kmalloc_oob_krealloc_more), KUNIT_CASE(kmalloc_oob_krealloc_less), KUNIT_CASE(kmalloc_oob_16), + KUNIT_CASE(kmalloc_uaf_16), KUNIT_CASE(kmalloc_oob_in_memset), KUNIT_CASE(kmalloc_oob_memset_2), KUNIT_CASE(kmalloc_oob_memset_4), @@ -751,7 +815,8 @@ static struct kunit_case kasan_kunit_test_cases[] = { KUNIT_CASE(kasan_memchr), KUNIT_CASE(kasan_memcmp), KUNIT_CASE(kasan_strings), - KUNIT_CASE(kasan_bitops), + KUNIT_CASE(kasan_bitops_generic), + KUNIT_CASE(kasan_bitops_tags), KUNIT_CASE(kmalloc_double_kzfree), KUNIT_CASE(vmalloc_oob), {} -- cgit v1.2.3 From aa4e460f0976351fddd2f5ac6e08b74320c277a1 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Sun, 1 Nov 2020 17:07:47 -0800 Subject: lib/crc32test: remove extra local_irq_disable/enable Commit 4d004099a668 ("lockdep: Fix lockdep recursion") uncovered the following issue in lib/crc32test reported on s390: BUG: using __this_cpu_read() in preemptible [00000000] code: swapper/0/1 caller is lockdep_hardirqs_on_prepare+0x48/0x270 CPU: 6 PID: 1 Comm: swapper/0 Not tainted 5.9.0-next-20201015-15164-g03d992bd2de6 #19 Hardware name: IBM 3906 M04 704 (LPAR) Call Trace: lockdep_hardirqs_on_prepare+0x48/0x270 trace_hardirqs_on+0x9c/0x1b8 crc32_test.isra.0+0x170/0x1c0 crc32test_init+0x1c/0x40 do_one_initcall+0x40/0x130 do_initcalls+0x126/0x150 kernel_init_freeable+0x1f6/0x230 kernel_init+0x22/0x150 ret_from_fork+0x24/0x2c no locks held by swapper/0/1. Remove extra local_irq_disable/local_irq_enable helpers calls. Fixes: 5fb7f87408f1 ("lib: add module support to crc32 tests") Signed-off-by: Vasily Gorbik Signed-off-by: Andrew Morton Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Greg Kroah-Hartman Link: https://lkml.kernel.org/r/patch.git-4369da00c06e.your-ad-here.call-01602859837-ext-1679@work.hours Signed-off-by: Linus Torvalds --- lib/crc32test.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/crc32test.c b/lib/crc32test.c index 97d6a57cefcc..61ddce2cff77 100644 --- a/lib/crc32test.c +++ b/lib/crc32test.c @@ -683,7 +683,6 @@ static int __init crc32c_test(void) /* reduce OS noise */ local_irq_save(flags); - local_irq_disable(); nsec = ktime_get_ns(); for (i = 0; i < 100; i++) { @@ -694,7 +693,6 @@ static int __init crc32c_test(void) nsec = ktime_get_ns() - nsec; local_irq_restore(flags); - local_irq_enable(); pr_info("crc32c: CRC_LE_BITS = %d\n", CRC_LE_BITS); @@ -768,7 +766,6 @@ static int __init crc32_test(void) /* reduce OS noise */ local_irq_save(flags); - local_irq_disable(); nsec = ktime_get_ns(); for (i = 0; i < 100; i++) { @@ -783,7 +780,6 @@ static int __init crc32_test(void) nsec = ktime_get_ns() - nsec; local_irq_restore(flags); - local_irq_enable(); pr_info("crc32: CRC_LE_BITS = %d, CRC_BE BITS = %d\n", CRC_LE_BITS, CRC_BE_BITS); -- cgit v1.2.3 From 6370cc3bbd8a0f9bf975b013781243ab147876c6 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Thu, 29 Oct 2020 17:36:19 +0000 Subject: net: add kcov handle to skb extensions Remote KCOV coverage collection enables coverage-guided fuzzing of the code that is not reachable during normal system call execution. It is especially helpful for fuzzing networking subsystems, where it is common to perform packet handling in separate work queues even for the packets that originated directly from the user space. Enable coverage-guided frame injection by adding kcov remote handle to skb extensions. Default initialization in __alloc_skb and __build_skb_around ensures that no socket buffer that was generated during a system call will be missed. Code that is of interest and that performs packet processing should be annotated with kcov_remote_start()/kcov_remote_stop(). An alternative approach is to determine kcov_handle solely on the basis of the device/interface that received the specific socket buffer. However, in this case it would be impossible to distinguish between packets that originated during normal background network processes or were intentionally injected from the user space. Signed-off-by: Aleksandr Nogikh Acked-by: Willem de Bruijn Signed-off-by: Jakub Kicinski --- lib/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index d7a7bc3b6098..d171a032db78 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1870,6 +1870,7 @@ config KCOV depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS select DEBUG_FS select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC + select SKB_EXTENSIONS help KCOV exposes kernel code coverage information in a form suitable for coverage-guided fuzzing (randomized testing). -- cgit v1.2.3 From 9522750c66c689b739e151fcdf895420dc81efc0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 13:32:42 -0500 Subject: Fonts: Replace discarded const qualifier Commit 6735b4632def ("Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts") introduced the following error when building rpc_defconfig (only this build appears to be affected): `acorndata_8x8' referenced in section `.text' of arch/arm/boot/compressed/ll_char_wr.o: defined in discarded section `.data' of arch/arm/boot/compressed/font.o `acorndata_8x8' referenced in section `.data.rel.ro' of arch/arm/boot/compressed/font.o: defined in discarded section `.data' of arch/arm/boot/compressed/font.o make[3]: *** [/scratch/linux/arch/arm/boot/compressed/Makefile:191: arch/arm/boot/compressed/vmlinux] Error 1 make[2]: *** [/scratch/linux/arch/arm/boot/Makefile:61: arch/arm/boot/compressed/vmlinux] Error 2 make[1]: *** [/scratch/linux/arch/arm/Makefile:317: zImage] Error 2 The .data section is discarded at link time. Reinstating acorndata_8x8 as const ensures it is still available after linking. Do the same for the other 12 built-in fonts as well, for consistency purposes. Cc: Cc: Russell King Reviewed-by: Greg Kroah-Hartman Fixes: 6735b4632def ("Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts") Signed-off-by: Lee Jones Co-developed-by: Peilin Ye Signed-off-by: Peilin Ye Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20201102183242.2031659-1-yepeilin.cs@gmail.com --- lib/fonts/font_10x18.c | 2 +- lib/fonts/font_6x10.c | 2 +- lib/fonts/font_6x11.c | 2 +- lib/fonts/font_6x8.c | 2 +- lib/fonts/font_7x14.c | 2 +- lib/fonts/font_8x16.c | 2 +- lib/fonts/font_8x8.c | 2 +- lib/fonts/font_acorn_8x8.c | 2 +- lib/fonts/font_mini_4x6.c | 2 +- lib/fonts/font_pearl_8x8.c | 2 +- lib/fonts/font_sun12x22.c | 2 +- lib/fonts/font_sun8x16.c | 2 +- lib/fonts/font_ter16x32.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/fonts/font_10x18.c b/lib/fonts/font_10x18.c index 0e2deac97da0..e02f9df24d1e 100644 --- a/lib/fonts/font_10x18.c +++ b/lib/fonts/font_10x18.c @@ -8,7 +8,7 @@ #define FONTDATAMAX 9216 -static struct font_data fontdata_10x18 = { +static const struct font_data fontdata_10x18 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, 0x00, /* 0000000000 */ diff --git a/lib/fonts/font_6x10.c b/lib/fonts/font_6x10.c index 87da8acd07db..6e3c4b7691c8 100644 --- a/lib/fonts/font_6x10.c +++ b/lib/fonts/font_6x10.c @@ -3,7 +3,7 @@ #define FONTDATAMAX 2560 -static struct font_data fontdata_6x10 = { +static const struct font_data fontdata_6x10 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ diff --git a/lib/fonts/font_6x11.c b/lib/fonts/font_6x11.c index 5e975dfa10a5..2d22a24e816f 100644 --- a/lib/fonts/font_6x11.c +++ b/lib/fonts/font_6x11.c @@ -9,7 +9,7 @@ #define FONTDATAMAX (11*256) -static struct font_data fontdata_6x11 = { +static const struct font_data fontdata_6x11 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ diff --git a/lib/fonts/font_6x8.c b/lib/fonts/font_6x8.c index 700039a9ceae..e7442a0d183d 100644 --- a/lib/fonts/font_6x8.c +++ b/lib/fonts/font_6x8.c @@ -3,7 +3,7 @@ #define FONTDATAMAX 2048 -static struct font_data fontdata_6x8 = { +static const struct font_data fontdata_6x8 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 000000 */ diff --git a/lib/fonts/font_7x14.c b/lib/fonts/font_7x14.c index 86d298f38505..9cc7ae2e03f7 100644 --- a/lib/fonts/font_7x14.c +++ b/lib/fonts/font_7x14.c @@ -8,7 +8,7 @@ #define FONTDATAMAX 3584 -static struct font_data fontdata_7x14 = { +static const struct font_data fontdata_7x14 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 0000000 */ diff --git a/lib/fonts/font_8x16.c b/lib/fonts/font_8x16.c index 37cedd36ca5e..bab25dc59e8d 100644 --- a/lib/fonts/font_8x16.c +++ b/lib/fonts/font_8x16.c @@ -10,7 +10,7 @@ #define FONTDATAMAX 4096 -static struct font_data fontdata_8x16 = { +static const struct font_data fontdata_8x16 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ diff --git a/lib/fonts/font_8x8.c b/lib/fonts/font_8x8.c index 8ab695538395..109d0572368f 100644 --- a/lib/fonts/font_8x8.c +++ b/lib/fonts/font_8x8.c @@ -9,7 +9,7 @@ #define FONTDATAMAX 2048 -static struct font_data fontdata_8x8 = { +static const struct font_data fontdata_8x8 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ diff --git a/lib/fonts/font_acorn_8x8.c b/lib/fonts/font_acorn_8x8.c index 069b3e80c434..fb395f0d4031 100644 --- a/lib/fonts/font_acorn_8x8.c +++ b/lib/fonts/font_acorn_8x8.c @@ -5,7 +5,7 @@ #define FONTDATAMAX 2048 -static struct font_data acorndata_8x8 = { +static const struct font_data acorndata_8x8 = { { 0, 0, FONTDATAMAX, 0 }, { /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ /* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */ diff --git a/lib/fonts/font_mini_4x6.c b/lib/fonts/font_mini_4x6.c index 1449876c6a27..592774a90917 100644 --- a/lib/fonts/font_mini_4x6.c +++ b/lib/fonts/font_mini_4x6.c @@ -43,7 +43,7 @@ __END__; #define FONTDATAMAX 1536 -static struct font_data fontdata_mini_4x6 = { +static const struct font_data fontdata_mini_4x6 = { { 0, 0, FONTDATAMAX, 0 }, { /*{*/ /* Char 0: ' ' */ diff --git a/lib/fonts/font_pearl_8x8.c b/lib/fonts/font_pearl_8x8.c index 32d65551e7ed..a6f95ebce950 100644 --- a/lib/fonts/font_pearl_8x8.c +++ b/lib/fonts/font_pearl_8x8.c @@ -14,7 +14,7 @@ #define FONTDATAMAX 2048 -static struct font_data fontdata_pearl8x8 = { +static const struct font_data fontdata_pearl8x8 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ diff --git a/lib/fonts/font_sun12x22.c b/lib/fonts/font_sun12x22.c index 641a6b4dca42..a5b65bd49604 100644 --- a/lib/fonts/font_sun12x22.c +++ b/lib/fonts/font_sun12x22.c @@ -3,7 +3,7 @@ #define FONTDATAMAX 11264 -static struct font_data fontdata_sun12x22 = { +static const struct font_data fontdata_sun12x22 = { { 0, 0, FONTDATAMAX, 0 }, { /* 0 0x00 '^@' */ 0x00, 0x00, /* 000000000000 */ diff --git a/lib/fonts/font_sun8x16.c b/lib/fonts/font_sun8x16.c index 193fe6d988e0..e577e76a6a7c 100644 --- a/lib/fonts/font_sun8x16.c +++ b/lib/fonts/font_sun8x16.c @@ -3,7 +3,7 @@ #define FONTDATAMAX 4096 -static struct font_data fontdata_sun8x16 = { +static const struct font_data fontdata_sun8x16 = { { 0, 0, FONTDATAMAX, 0 }, { /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, diff --git a/lib/fonts/font_ter16x32.c b/lib/fonts/font_ter16x32.c index 91b9c283bd9c..f7c3abb6b99e 100644 --- a/lib/fonts/font_ter16x32.c +++ b/lib/fonts/font_ter16x32.c @@ -4,7 +4,7 @@ #define FONTDATAMAX 16384 -static struct font_data fontdata_ter16x32 = { +static const struct font_data fontdata_ter16x32 = { { 0, 0, FONTDATAMAX, 0 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x7f, 0xfc, -- cgit v1.2.3 From a3453d923ece6760689894bad5b6d5e00c0ffe2d Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 15 Oct 2020 10:01:42 +0200 Subject: s390/kasan: remove 3-level paging support Compiling the kernel with Kasan disables automatic 3-level vs 4-level kernel space paging selection, because the shadow memory offset has to be known at compile time and there is no such offset which would be acceptable for both 3 and 4-level paging. Instead S390_4_LEVEL_PAGING option was introduced which allowed to pick how many paging levels to use under Kasan. With the introduction of protected virtualization, kernel memory layout may be affected due to ultravisor secure storage limit. This adds additional complexity into how memory layout would look like in combination with Kasan predefined shadow memory offsets. To simplify this make Kasan 4-level paging default and remove Kasan 3-level paging support. Suggested-by: Heiko Carstens Reviewed-by: Alexander Gordeev Signed-off-by: Vasily Gorbik Signed-off-by: Heiko Carstens --- lib/Kconfig.kasan | 9 --------- 1 file changed, 9 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index 542a9c18398e..8fb097057fec 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -136,15 +136,6 @@ config KASAN_STACK default 1 if KASAN_STACK_ENABLE || CC_IS_GCC default 0 -config KASAN_S390_4_LEVEL_PAGING - bool "KASan: use 4-level paging" - depends on S390 - help - Compiling the kernel with KASan disables automatic 3-level vs - 4-level paging selection. 3-level paging is used by default (up - to 3TB of RAM with KASan enabled). This options allows to force - 4-level paging instead. - config KASAN_SW_TAGS_IDENTIFY bool "Enable memory corruption identification" depends on KASAN_SW_TAGS -- cgit v1.2.3 From a8b62fd0850503cf1e557d7e5a98d3f1f5c25eef Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 21 Sep 2020 12:58:17 +0200 Subject: stop_machine: Add function and caller debug info Crashes in stop-machine are hard to connect to the calling code, add a little something to help with that. Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Valentin Schneider Reviewed-by: Daniel Bristot de Oliveira Link: https://lkml.kernel.org/r/20201023102346.116513635@infradead.org --- lib/dump_stack.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/dump_stack.c b/lib/dump_stack.c index a00ee6eedc7c..f5a33b6f773f 100644 --- a/lib/dump_stack.c +++ b/lib/dump_stack.c @@ -12,6 +12,7 @@ #include #include #include +#include static char dump_stack_arch_desc_str[128]; @@ -57,6 +58,7 @@ void dump_stack_print_info(const char *log_lvl) log_lvl, dump_stack_arch_desc_str); print_worker_info(log_lvl, current); + print_stop_info(log_lvl, current); } /** -- cgit v1.2.3 From af449901b84c98cbd84a0113223ba3bcfcb12a26 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 17 Sep 2020 10:38:30 +0200 Subject: sched: Add migrate_disable() Add the base migrate_disable() support (under protest). While migrate_disable() is (currently) required for PREEMPT_RT, it is also one of the biggest flaws in the system. Notably this is just the base implementation, it is broken vs sched_setaffinity() and hotplug, both solved in additional patches for ease of review. Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Valentin Schneider Reviewed-by: Daniel Bristot de Oliveira Link: https://lkml.kernel.org/r/20201023102346.818170844@infradead.org --- lib/smp_processor_id.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 525222e4f409..faaa927ac2c8 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -26,6 +26,11 @@ unsigned int check_preemption_disabled(const char *what1, const char *what2) if (current->nr_cpus_allowed == 1) goto out; +#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT) + if (current->migration_disabled) + goto out; +#endif + /* * It is valid to assume CPU-locality during early bootup: */ -- cgit v1.2.3 From 14e292f8d45380c519a83d9b0f37089a17eedcdf Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 1 Oct 2020 15:54:14 +0200 Subject: sched,rt: Use cpumask_any*_distribute() Replace a bunch of cpumask_any*() instances with cpumask_any*_distribute(), by injecting this little bit of random in cpu selection, we reduce the chance two competing balance operations working off the same lowest_mask pick the same CPU. Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Valentin Schneider Reviewed-by: Daniel Bristot de Oliveira Link: https://lkml.kernel.org/r/20201023102347.190759694@infradead.org --- lib/cpumask.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'lib') diff --git a/lib/cpumask.c b/lib/cpumask.c index 85da6ab4fbb5..35924025097b 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -267,3 +267,21 @@ int cpumask_any_and_distribute(const struct cpumask *src1p, return next; } EXPORT_SYMBOL(cpumask_any_and_distribute); + +int cpumask_any_distribute(const struct cpumask *srcp) +{ + int next, prev; + + /* NOTE: our first selection will skip 0. */ + prev = __this_cpu_read(distribute_cpu_mask_prev); + + next = cpumask_next(prev, srcp); + if (next >= nr_cpu_ids) + next = cpumask_first(srcp); + + if (next < nr_cpu_ids) + __this_cpu_write(distribute_cpu_mask_prev, next); + + return next; +} +EXPORT_SYMBOL(cpumask_any_distribute); -- cgit v1.2.3 From 5f9ae91f7c0dbbc4195e2a6c8eedcaeb5b9e4cbb Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Mon, 9 Nov 2020 17:19:30 -0800 Subject: kbuild: Build kernel module BTFs if BTF is enabled and pahole supports it Detect if pahole supports split BTF generation, and generate BTF for each selected kernel module, if it does. This is exposed to Makefiles and C code as CONFIG_DEBUG_INFO_BTF_MODULES flag. Kernel module BTF has to be re-generated if either vmlinux's BTF changes or module's .ko changes. To achieve that, I needed a helper similar to if_changed, but that would allow to filter out vmlinux from the list of updated dependencies for .ko building. I've put it next to the only place that uses and needs it, but it might be a better idea to just add it along the other if_changed variants into scripts/Kbuild.include. Each kernel module's BTF deduplication is pretty fast, as it does only incremental BTF deduplication on top of already deduplicated vmlinux BTF. To show the added build time, I've first ran make only just built kernel (to establish the baseline) and then forced only BTF re-generation, without regenerating .ko files. The build was performed with -j60 parallelization on 56-core machine. The final time also includes bzImage building, so it's not a pure BTF overhead. $ time make -j60 ... make -j60 27.65s user 10.96s system 782% cpu 4.933 total $ touch ~/linux-build/default/vmlinux && time make -j60 ... make -j60 123.69s user 27.85s system 1566% cpu 9.675 total So 4.6 seconds real time, with noticeable part spent in compressed vmlinux and bzImage building. To show size savings, I've built my kernel configuration with about 700 kernel modules with full BTF per each kernel module (without deduplicating against vmlinux) and with split BTF against deduplicated vmlinux (approach in this patch). Below are top 10 modules with biggest BTF sizes. And total size of BTF data across all kernel modules. It shows that split BTF "compresses" 115MB down to 5MB total. And the biggest kernel modules get a downsize from 500-570KB down to 200-300KB. FULL BTF ======== $ for f in $(find . -name '*.ko'); do size -A -d $f | grep BTF | awk '{print $2}'; done | awk '{ s += $1 } END { print s }' 115710691 $ for f in $(find . -name '*.ko'); do printf "%s %d\n" $f $(size -A -d $f | grep BTF | awk '{print $2}'); done | sort -nr -k2 | head -n10 ./drivers/gpu/drm/i915/i915.ko 570570 ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko 520240 ./drivers/gpu/drm/radeon/radeon.ko 503849 ./drivers/infiniband/hw/mlx5/mlx5_ib.ko 491777 ./fs/xfs/xfs.ko 411544 ./drivers/net/ethernet/intel/i40e/i40e.ko 403904 ./drivers/net/ethernet/broadcom/bnx2x/bnx2x.ko 398754 ./drivers/infiniband/core/ib_core.ko 397224 ./fs/cifs/cifs.ko 386249 ./fs/nfsd/nfsd.ko 379738 SPLIT BTF ========= $ for f in $(find . -name '*.ko'); do size -A -d $f | grep BTF | awk '{print $2}'; done | awk '{ s += $1 } END { print s }' 5194047 $ for f in $(find . -name '*.ko'); do printf "%s %d\n" $f $(size -A -d $f | grep BTF | awk '{print $2}'); done | sort -nr -k2 | head -n10 ./drivers/gpu/drm/i915/i915.ko 293206 ./drivers/gpu/drm/radeon/radeon.ko 282103 ./fs/xfs/xfs.ko 222150 ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko 198503 ./drivers/infiniband/hw/mlx5/mlx5_ib.ko 198356 ./drivers/net/ethernet/broadcom/bnx2x/bnx2x.ko 113444 ./fs/cifs/cifs.ko 109379 ./arch/x86/kvm/kvm.ko 100225 ./drivers/gpu/drm/drm.ko 94827 ./drivers/infiniband/core/ib_core.ko 91188 Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20201110011932.3201430-4-andrii@kernel.org --- lib/Kconfig.debug | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index d7a7bc3b6098..1e78faaf20a5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -274,6 +274,15 @@ config DEBUG_INFO_BTF Turning this on expects presence of pahole tool, which will convert DWARF type info into equivalent deduplicated BTF type info. +config PAHOLE_HAS_SPLIT_BTF + def_bool $(success, test `$(PAHOLE) --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/'` -ge "119") + +config DEBUG_INFO_BTF_MODULES + def_bool y + depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF + help + Generate compact split BTF type information for kernel modules. + config GDB_SCRIPTS bool "Provide GDB scripts for kernel debugging" help -- cgit v1.2.3 From 85ce50d337d10a6fd328fa70b0a15543bf5c0f64 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 10 Nov 2020 09:57:46 -0800 Subject: net: kcov: don't select SKB_EXTENSIONS when there is no NET Fix kconfig warning when CONFIG_NET is not set/enabled: WARNING: unmet direct dependencies detected for SKB_EXTENSIONS Depends on [n]: NET [=n] Selected by [y]: - KCOV [=y] && ARCH_HAS_KCOV [=y] && (CC_HAS_SANCOV_TRACE_PC [=y] || GCC_PLUGINS [=n]) Fixes: 6370cc3bbd8a ("net: add kcov handle to skb extensions") Signed-off-by: Randy Dunlap Cc: Aleksandr Nogikh Cc: Willem de Bruijn Link: https://lore.kernel.org/r/20201110175746.11437-1-rdunlap@infradead.org Signed-off-by: Jakub Kicinski --- lib/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index dd052a272fa7..fc6e120045b0 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1870,7 +1870,7 @@ config KCOV depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS select DEBUG_FS select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC - select SKB_EXTENSIONS + select SKB_EXTENSIONS if NET help KCOV exposes kernel code coverage information in a form suitable for coverage-guided fuzzing (randomized testing). -- cgit v1.2.3 From 4ee573086bd88ff3060dda07873bf755d332e9ba Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Thu, 12 Nov 2020 07:13:34 -0500 Subject: Fonts: Add charcount field to font_desc Subsystems are hard-coding the number of characters of our built-in fonts as 256. Include that information in our kernel font descriptor, `struct font_desc`. Signed-off-by: Peilin Ye Reviewed-by: Daniel Vetter Reviewed-by: Greg Kroah-Hartman Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/65952296d1d9486093bd955d1536f7dcd11112c6.1605169912.git.yepeilin.cs@gmail.com --- lib/fonts/font_10x18.c | 1 + lib/fonts/font_6x10.c | 1 + lib/fonts/font_6x11.c | 1 + lib/fonts/font_6x8.c | 1 + lib/fonts/font_7x14.c | 1 + lib/fonts/font_8x16.c | 1 + lib/fonts/font_8x8.c | 1 + lib/fonts/font_acorn_8x8.c | 1 + lib/fonts/font_mini_4x6.c | 1 + lib/fonts/font_pearl_8x8.c | 1 + lib/fonts/font_sun12x22.c | 1 + lib/fonts/font_sun8x16.c | 1 + lib/fonts/font_ter16x32.c | 1 + 13 files changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/fonts/font_10x18.c b/lib/fonts/font_10x18.c index e02f9df24d1e..5d940db626e7 100644 --- a/lib/fonts/font_10x18.c +++ b/lib/fonts/font_10x18.c @@ -5137,6 +5137,7 @@ const struct font_desc font_10x18 = { .name = "10x18", .width = 10, .height = 18, + .charcount = 256, .data = fontdata_10x18.data, #ifdef __sparc__ .pref = 5, diff --git a/lib/fonts/font_6x10.c b/lib/fonts/font_6x10.c index 6e3c4b7691c8..e65df019e0d2 100644 --- a/lib/fonts/font_6x10.c +++ b/lib/fonts/font_6x10.c @@ -3083,6 +3083,7 @@ const struct font_desc font_6x10 = { .name = "6x10", .width = 6, .height = 10, + .charcount = 256, .data = fontdata_6x10.data, .pref = 0, }; diff --git a/lib/fonts/font_6x11.c b/lib/fonts/font_6x11.c index 2d22a24e816f..bd76b3f6b635 100644 --- a/lib/fonts/font_6x11.c +++ b/lib/fonts/font_6x11.c @@ -3346,6 +3346,7 @@ const struct font_desc font_vga_6x11 = { .name = "ProFont6x11", .width = 6, .height = 11, + .charcount = 256, .data = fontdata_6x11.data, /* Try avoiding this font if possible unless on MAC */ .pref = -2000, diff --git a/lib/fonts/font_6x8.c b/lib/fonts/font_6x8.c index e7442a0d183d..06ace7792521 100644 --- a/lib/fonts/font_6x8.c +++ b/lib/fonts/font_6x8.c @@ -2571,6 +2571,7 @@ const struct font_desc font_6x8 = { .name = "6x8", .width = 6, .height = 8, + .charcount = 256, .data = fontdata_6x8.data, .pref = 0, }; diff --git a/lib/fonts/font_7x14.c b/lib/fonts/font_7x14.c index 9cc7ae2e03f7..a2f561c9fa04 100644 --- a/lib/fonts/font_7x14.c +++ b/lib/fonts/font_7x14.c @@ -4113,6 +4113,7 @@ const struct font_desc font_7x14 = { .name = "7x14", .width = 7, .height = 14, + .charcount = 256, .data = fontdata_7x14.data, .pref = 0, }; diff --git a/lib/fonts/font_8x16.c b/lib/fonts/font_8x16.c index bab25dc59e8d..06ae14088514 100644 --- a/lib/fonts/font_8x16.c +++ b/lib/fonts/font_8x16.c @@ -4627,6 +4627,7 @@ const struct font_desc font_vga_8x16 = { .name = "VGA8x16", .width = 8, .height = 16, + .charcount = 256, .data = fontdata_8x16.data, .pref = 0, }; diff --git a/lib/fonts/font_8x8.c b/lib/fonts/font_8x8.c index 109d0572368f..69570b8c31af 100644 --- a/lib/fonts/font_8x8.c +++ b/lib/fonts/font_8x8.c @@ -2578,6 +2578,7 @@ const struct font_desc font_vga_8x8 = { .name = "VGA8x8", .width = 8, .height = 8, + .charcount = 256, .data = fontdata_8x8.data, .pref = 0, }; diff --git a/lib/fonts/font_acorn_8x8.c b/lib/fonts/font_acorn_8x8.c index fb395f0d4031..18755c33d249 100644 --- a/lib/fonts/font_acorn_8x8.c +++ b/lib/fonts/font_acorn_8x8.c @@ -270,6 +270,7 @@ const struct font_desc font_acorn_8x8 = { .name = "Acorn8x8", .width = 8, .height = 8, + .charcount = 256, .data = acorndata_8x8.data, #ifdef CONFIG_ARCH_ACORN .pref = 20, diff --git a/lib/fonts/font_mini_4x6.c b/lib/fonts/font_mini_4x6.c index 592774a90917..8d39fd447952 100644 --- a/lib/fonts/font_mini_4x6.c +++ b/lib/fonts/font_mini_4x6.c @@ -2152,6 +2152,7 @@ const struct font_desc font_mini_4x6 = { .name = "MINI4x6", .width = 4, .height = 6, + .charcount = 256, .data = fontdata_mini_4x6.data, .pref = 3, }; diff --git a/lib/fonts/font_pearl_8x8.c b/lib/fonts/font_pearl_8x8.c index a6f95ebce950..b1678ed0017c 100644 --- a/lib/fonts/font_pearl_8x8.c +++ b/lib/fonts/font_pearl_8x8.c @@ -2582,6 +2582,7 @@ const struct font_desc font_pearl_8x8 = { .name = "PEARL8x8", .width = 8, .height = 8, + .charcount = 256, .data = fontdata_pearl8x8.data, .pref = 2, }; diff --git a/lib/fonts/font_sun12x22.c b/lib/fonts/font_sun12x22.c index a5b65bd49604..91daf5ab8b6b 100644 --- a/lib/fonts/font_sun12x22.c +++ b/lib/fonts/font_sun12x22.c @@ -6156,6 +6156,7 @@ const struct font_desc font_sun_12x22 = { .name = "SUN12x22", .width = 12, .height = 22, + .charcount = 256, .data = fontdata_sun12x22.data, #ifdef __sparc__ .pref = 5, diff --git a/lib/fonts/font_sun8x16.c b/lib/fonts/font_sun8x16.c index e577e76a6a7c..81bb4eeae04e 100644 --- a/lib/fonts/font_sun8x16.c +++ b/lib/fonts/font_sun8x16.c @@ -268,6 +268,7 @@ const struct font_desc font_sun_8x16 = { .name = "SUN8x16", .width = 8, .height = 16, + .charcount = 256, .data = fontdata_sun8x16.data, #ifdef __sparc__ .pref = 10, diff --git a/lib/fonts/font_ter16x32.c b/lib/fonts/font_ter16x32.c index f7c3abb6b99e..1955d624177c 100644 --- a/lib/fonts/font_ter16x32.c +++ b/lib/fonts/font_ter16x32.c @@ -2062,6 +2062,7 @@ const struct font_desc font_ter_16x32 = { .name = "TER16x32", .width = 16, .height = 32, + .charcount = 256, .data = fontdata_ter16x32.data, #ifdef __sparc__ .pref = 5, -- cgit v1.2.3 From 8eeb99bc81bc1cb3d5e5323d9a82d8392e3a27b4 Mon Sep 17 00:00:00 2001 From: Francis Laniel Date: Sun, 15 Nov 2020 18:08:04 +0100 Subject: Fix unefficient call to memset before memcpu in nla_strlcpy. Before this commit, nla_strlcpy first memseted dst to 0 then wrote src into it. This is inefficient because bytes whom number is less than src length are written twice. This patch solves this issue by first writing src into dst then fill dst with 0's. Note that, in the case where src length is higher than dst, only 0 is written. Otherwise there are as many 0's written to fill dst. For example, if src is "foo\0" and dst is 5 bytes long, the result will be: 1. "fooGG" after memcpy (G means garbage). 2. "foo\0\0" after memset. Signed-off-by: Francis Laniel Reviewed-by: Kees Cook Signed-off-by: Jakub Kicinski --- lib/nlattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/nlattr.c b/lib/nlattr.c index 74019c8ebf6b..07156e581997 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -731,8 +731,9 @@ size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) if (dstsize > 0) { size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; - memset(dst, 0, dstsize); memcpy(dst, src, len); + /* Zero pad end of dst. */ + memset(dst + len, 0, dstsize - len); } return srclen; -- cgit v1.2.3 From 9ca718743ad8402958637bfc196d7b62371a1b9f Mon Sep 17 00:00:00 2001 From: Francis Laniel Date: Sun, 15 Nov 2020 18:08:05 +0100 Subject: Modify return value of nla_strlcpy to match that of strscpy. nla_strlcpy now returns -E2BIG if src was truncated when written to dst. It also returns this error value if dstsize is 0 or higher than INT_MAX. For example, if src is "foo\0" and dst is 3 bytes long, the result will be: 1. "foG" after memcpy (G means garbage). 2. "fo\0" after memset. 3. -E2BIG is returned because src was not completely written into dst. The callers of nla_strlcpy were modified to take into account this modification. Signed-off-by: Francis Laniel Reviewed-by: Kees Cook Signed-off-by: Jakub Kicinski --- lib/nlattr.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/nlattr.c b/lib/nlattr.c index 07156e581997..447182543c03 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -710,33 +710,44 @@ EXPORT_SYMBOL(nla_find); /** * nla_strlcpy - Copy string attribute payload into a sized buffer - * @dst: where to copy the string to - * @nla: attribute to copy the string from - * @dstsize: size of destination buffer + * @dst: Where to copy the string to. + * @nla: Attribute to copy the string from. + * @dstsize: Size of destination buffer. * * Copies at most dstsize - 1 bytes into the destination buffer. - * The result is always a valid NUL-terminated string. Unlike - * strlcpy the destination buffer is always padded out. + * Unlike strlcpy the destination buffer is always padded out. * - * Returns the length of the source buffer. + * Return: + * * srclen - Returns @nla length (not including the trailing %NUL). + * * -E2BIG - If @dstsize is 0 or greater than U16_MAX or @nla length greater + * than @dstsize. */ -size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) +ssize_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) { size_t srclen = nla_len(nla); char *src = nla_data(nla); + ssize_t ret; + size_t len; + + if (dstsize == 0 || WARN_ON_ONCE(dstsize > U16_MAX)) + return -E2BIG; if (srclen > 0 && src[srclen - 1] == '\0') srclen--; - if (dstsize > 0) { - size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen; - - memcpy(dst, src, len); - /* Zero pad end of dst. */ - memset(dst + len, 0, dstsize - len); + if (srclen >= dstsize) { + len = dstsize - 1; + ret = -E2BIG; + } else { + len = srclen; + ret = len; } - return srclen; + memcpy(dst, src, len); + /* Zero pad end of dst. */ + memset(dst + len, 0, dstsize - len); + + return ret; } EXPORT_SYMBOL(nla_strlcpy); -- cgit v1.2.3 From 872f690341948b502c93318f806d821c56772c42 Mon Sep 17 00:00:00 2001 From: Francis Laniel Date: Sun, 15 Nov 2020 18:08:06 +0100 Subject: treewide: rename nla_strlcpy to nla_strscpy. Calls to nla_strlcpy are now replaced by calls to nla_strscpy which is the new name of this function. Signed-off-by: Francis Laniel Reviewed-by: Kees Cook Signed-off-by: Jakub Kicinski --- lib/nlattr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/nlattr.c b/lib/nlattr.c index 447182543c03..09aa181569e0 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -709,7 +709,7 @@ struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype) EXPORT_SYMBOL(nla_find); /** - * nla_strlcpy - Copy string attribute payload into a sized buffer + * nla_strscpy - Copy string attribute payload into a sized buffer * @dst: Where to copy the string to. * @nla: Attribute to copy the string from. * @dstsize: Size of destination buffer. @@ -722,7 +722,7 @@ EXPORT_SYMBOL(nla_find); * * -E2BIG - If @dstsize is 0 or greater than U16_MAX or @nla length greater * than @dstsize. */ -ssize_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) +ssize_t nla_strscpy(char *dst, const struct nlattr *nla, size_t dstsize) { size_t srclen = nla_len(nla); char *src = nla_data(nla); @@ -749,7 +749,7 @@ ssize_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) return ret; } -EXPORT_SYMBOL(nla_strlcpy); +EXPORT_SYMBOL(nla_strscpy); /** * nla_strdup - Copy string attribute payload into a newly allocated buffer -- cgit v1.2.3 From 5df38ca6afeceaf3ea911ad2f7e2101364dee48d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 3 Nov 2020 22:45:08 +0200 Subject: resource: Add test cases for new resource API Add test cases for newly added resource APIs. Signed-off-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- lib/Kconfig.debug | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c789b39ed527..64f9501a6b5c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2226,6 +2226,17 @@ config BITFIELD_KUNIT If unsure, say N. +config RESOURCE_KUNIT_TEST + tristate "KUnit test for resource API" + depends on KUNIT + help + This builds the resource API unit test. + Tests the logic of API provided by resource.c and ioport.h. + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config SYSCTL_KUNIT_TEST tristate "KUnit test for sysctl" if !KUNIT_ALL_TESTS depends on KUNIT -- cgit v1.2.3 From 4c1ca831adb1010e473a18eb01b3fbef7595f230 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Sun, 15 Nov 2020 20:35:31 -0800 Subject: Revert "lib: Revert use of fallthrough pseudo-keyword in lib/" This reverts commit 6a9dc5fd6170 ("lib: Revert use of fallthrough pseudo-keyword in lib/") Now that we can build arch/powerpc/boot/ free of -Wimplicit-fallthrough, re-enable these fixes for lib/. Signed-off-by: Nick Desaulniers Tested-by: Nathan Chancellor Reviewed-by: Nathan Chancellor Reviewed-by: Gustavo A. R. Silva Reviewed-by: Miguel Ojeda Link: https://github.com/ClangBuiltLinux/linux/issues/236 Signed-off-by: Gustavo A. R. Silva --- lib/asn1_decoder.c | 4 ++-- lib/assoc_array.c | 2 +- lib/bootconfig.c | 4 ++-- lib/cmdline.c | 10 +++++----- lib/dim/net_dim.c | 2 +- lib/dim/rdma_dim.c | 4 ++-- lib/glob.c | 2 +- lib/siphash.c | 36 ++++++++++++++++++------------------ lib/ts_fsm.c | 2 +- lib/vsprintf.c | 14 +++++++------- lib/xz/xz_dec_lzma2.c | 4 ++-- lib/xz/xz_dec_stream.c | 16 ++++++++-------- lib/zstd/bitstream.h | 10 +++++----- lib/zstd/compress.c | 2 +- lib/zstd/decompress.c | 12 ++++++------ lib/zstd/huf_compress.c | 4 ++-- 16 files changed, 64 insertions(+), 64 deletions(-) (limited to 'lib') diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 58f72b25f8e9..13da529e2e72 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -381,7 +381,7 @@ next_op: case ASN1_OP_END_SET_ACT: if (unlikely(!(flags & FLAG_MATCHED))) goto tag_mismatch; - /* fall through */ + fallthrough; case ASN1_OP_END_SEQ: case ASN1_OP_END_SET_OF: @@ -448,7 +448,7 @@ next_op: pc += asn1_op_lengths[op]; goto next_op; } - /* fall through */ + fallthrough; case ASN1_OP_ACT: ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); diff --git a/lib/assoc_array.c b/lib/assoc_array.c index 6f4bcf524554..04c98799c3ba 100644 --- a/lib/assoc_array.c +++ b/lib/assoc_array.c @@ -1113,7 +1113,7 @@ struct assoc_array_edit *assoc_array_delete(struct assoc_array *array, index_key)) goto found_leaf; } - /* fall through */ + fallthrough; case assoc_array_walk_tree_empty: case assoc_array_walk_found_wrong_shortcut: default: diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 649ed44f199c..9f8c70a98fcf 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -827,7 +827,7 @@ int __init xbc_init(char *buf, const char **emsg, int *epos) q - 2); break; } - /* fall through */ + fallthrough; case '=': ret = xbc_parse_kv(&p, q, c); break; @@ -836,7 +836,7 @@ int __init xbc_init(char *buf, const char **emsg, int *epos) break; case '#': q = skip_comment(q); - /* fall through */ + fallthrough; case ';': case '\n': ret = xbc_parse_key(&p, q); diff --git a/lib/cmdline.c b/lib/cmdline.c index fbb9981a04a4..55768b4f3f58 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -132,23 +132,23 @@ unsigned long long memparse(const char *ptr, char **retptr) case 'E': case 'e': ret <<= 10; - /* fall through */ + fallthrough; case 'P': case 'p': ret <<= 10; - /* fall through */ + fallthrough; case 'T': case 't': ret <<= 10; - /* fall through */ + fallthrough; case 'G': case 'g': ret <<= 10; - /* fall through */ + fallthrough; case 'M': case 'm': ret <<= 10; - /* fall through */ + fallthrough; case 'K': case 'k': ret <<= 10; diff --git a/lib/dim/net_dim.c b/lib/dim/net_dim.c index a4db51c21266..06811d866775 100644 --- a/lib/dim/net_dim.c +++ b/lib/dim/net_dim.c @@ -233,7 +233,7 @@ void net_dim(struct dim *dim, struct dim_sample end_sample) schedule_work(&dim->work); break; } - /* fall through */ + fallthrough; case DIM_START_MEASURE: dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr, &dim->start_sample); diff --git a/lib/dim/rdma_dim.c b/lib/dim/rdma_dim.c index f7e26c7b4749..15462d54758d 100644 --- a/lib/dim/rdma_dim.c +++ b/lib/dim/rdma_dim.c @@ -59,7 +59,7 @@ static bool rdma_dim_decision(struct dim_stats *curr_stats, struct dim *dim) break; case DIM_STATS_WORSE: dim_turn(dim); - /* fall through */ + fallthrough; case DIM_STATS_BETTER: step_res = rdma_dim_step(dim); if (step_res == DIM_ON_EDGE) @@ -94,7 +94,7 @@ void rdma_dim(struct dim *dim, u64 completions) schedule_work(&dim->work); break; } - /* fall through */ + fallthrough; case DIM_START_MEASURE: dim->state = DIM_MEASURE_IN_PROGRESS; dim_update_sample_with_comps(curr_sample->event_ctr, 0, 0, diff --git a/lib/glob.c b/lib/glob.c index 52e3ed7e4a9b..85ecbda45cd8 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -102,7 +102,7 @@ bool __pure glob_match(char const *pat, char const *str) break; case '\\': d = *pat++; - /* fall through */ + fallthrough; default: /* Literal character */ literal: if (c == d) { diff --git a/lib/siphash.c b/lib/siphash.c index c47bb6ff2149..a90112ee72a1 100644 --- a/lib/siphash.c +++ b/lib/siphash.c @@ -68,11 +68,11 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= le32_to_cpup(data); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -101,11 +101,11 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= get_unaligned_le32(end); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } @@ -268,11 +268,11 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= le32_to_cpup(data); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -301,11 +301,11 @@ u32 __hsiphash_unaligned(const void *data, size_t len, bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= get_unaligned_le32(end); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } @@ -431,7 +431,7 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) v0 ^= m; } switch (left) { - case 3: b |= ((u32)end[2]) << 16; /* fall through */ + case 3: b |= ((u32)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -454,7 +454,7 @@ u32 __hsiphash_unaligned(const void *data, size_t len, v0 ^= m; } switch (left) { - case 3: b |= ((u32)end[2]) << 16; /* fall through */ + case 3: b |= ((u32)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c index ab749ec10ab5..64fd9015ad80 100644 --- a/lib/ts_fsm.c +++ b/lib/ts_fsm.c @@ -193,7 +193,7 @@ startover: TOKEN_MISMATCH(); block_idx++; - /* fall through */ + fallthrough; case TS_FSM_ANY: if (next == NULL) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 14c9a6af1b23..d3c5c16f391c 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1265,7 +1265,7 @@ char *mac_address_string(char *buf, char *end, u8 *addr, case 'R': reversed = true; - /* fall through */ + fallthrough; default: separator = ':'; @@ -1682,7 +1682,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, switch (*(++fmt)) { case 'L': uc = true; - /* fall through */ + fallthrough; case 'l': index = guid_index; break; @@ -2219,7 +2219,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'S': case 's': ptr = dereference_symbol_descriptor(ptr); - /* fall through */ + fallthrough; case 'B': return symbol_string(buf, end, ptr, spec, fmt); case 'R': @@ -2450,7 +2450,7 @@ qualifier: case 'x': spec->flags |= SMALL; - /* fall through */ + fallthrough; case 'X': spec->base = 16; @@ -2468,7 +2468,7 @@ qualifier: * utility, treat it as any other invalid or * unsupported format specifier. */ - /* fall through */ + fallthrough; default: WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt); @@ -3411,10 +3411,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; case 'i': base = 0; - /* fall through */ + fallthrough; case 'd': is_sign = true; - /* fall through */ + fallthrough; case 'u': break; case '%': diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c index 65a1aad8c223..ca2603abee08 100644 --- a/lib/xz/xz_dec_lzma2.c +++ b/lib/xz/xz_dec_lzma2.c @@ -1043,7 +1043,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.sequence = SEQ_LZMA_PREPARE; - /* fall through */ + fallthrough; case SEQ_LZMA_PREPARE: if (s->lzma2.compressed < RC_INIT_BYTES) @@ -1055,7 +1055,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.compressed -= RC_INIT_BYTES; s->lzma2.sequence = SEQ_LZMA_RUN; - /* fall through */ + fallthrough; case SEQ_LZMA_RUN: /* diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c index 32ab2a08b7cb..fea86deaaa01 100644 --- a/lib/xz/xz_dec_stream.c +++ b/lib/xz/xz_dec_stream.c @@ -583,7 +583,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) if (ret != XZ_OK) return ret; - /* fall through */ + fallthrough; case SEQ_BLOCK_START: /* We need one byte of input to continue. */ @@ -608,7 +608,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->temp.pos = 0; s->sequence = SEQ_BLOCK_HEADER; - /* fall through */ + fallthrough; case SEQ_BLOCK_HEADER: if (!fill_temp(s, b)) @@ -620,7 +620,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_UNCOMPRESS; - /* fall through */ + fallthrough; case SEQ_BLOCK_UNCOMPRESS: ret = dec_block(s, b); @@ -629,7 +629,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_PADDING; - /* fall through */ + fallthrough; case SEQ_BLOCK_PADDING: /* @@ -651,7 +651,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_CHECK; - /* fall through */ + fallthrough; case SEQ_BLOCK_CHECK: if (s->check_type == XZ_CHECK_CRC32) { @@ -675,7 +675,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_INDEX_PADDING; - /* fall through */ + fallthrough; case SEQ_INDEX_PADDING: while ((s->index.size + (b->in_pos - s->in_start)) @@ -699,7 +699,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_INDEX_CRC32; - /* fall through */ + fallthrough; case SEQ_INDEX_CRC32: ret = crc32_validate(s, b); @@ -709,7 +709,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->temp.size = STREAM_HEADER_SIZE; s->sequence = SEQ_STREAM_FOOTER; - /* fall through */ + fallthrough; case SEQ_STREAM_FOOTER: if (!fill_temp(s, b)) diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h index 3a49784d5c61..7c65c66e41fd 100644 --- a/lib/zstd/bitstream.h +++ b/lib/zstd/bitstream.h @@ -259,15 +259,15 @@ ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, s bitD->bitContainer = *(const BYTE *)(bitD->start); switch (srcSize) { case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16); - /* fall through */ + fallthrough; case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24); - /* fall through */ + fallthrough; case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32); - /* fall through */ + fallthrough; case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24; - /* fall through */ + fallthrough; case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16; - /* fall through */ + fallthrough; case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8; default:; } diff --git a/lib/zstd/compress.c b/lib/zstd/compress.c index 5e0b67003e55..b080264ed3ad 100644 --- a/lib/zstd/compress.c +++ b/lib/zstd/compress.c @@ -3182,7 +3182,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream *zcs, void *dst, size_t * zcs->outBuffFlushedSize = 0; zcs->stage = zcss_flush; /* pass-through to flush stage */ } - /* fall through */ + fallthrough; case zcss_flush: { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c index db6761ea4deb..66cd487a326a 100644 --- a/lib/zstd/decompress.c +++ b/lib/zstd/decompress.c @@ -442,7 +442,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize case set_repeat: if (dctx->litEntropy == 0) return ERROR(dictionary_corrupted); - /* fall through */ + fallthrough; case set_compressed: if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ @@ -1768,7 +1768,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, c return 0; } dctx->expected = 0; /* not necessary to copy more */ - /* fall through */ + fallthrough; case ZSTDds_decodeFrameHeader: memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); @@ -2309,7 +2309,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB switch (zds->stage) { case zdss_init: ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ - /* fall through */ + fallthrough; case zdss_loadHeader: { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); @@ -2376,7 +2376,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB } zds->stage = zdss_read; } - /* fall through */ + fallthrough; case zdss_read: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); @@ -2405,7 +2405,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB zds->stage = zdss_load; /* pass-through */ } - /* fall through */ + fallthrough; case zdss_load: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); @@ -2438,7 +2438,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB /* pass-through */ } } - /* fall through */ + fallthrough; case zdss_flush: { size_t const toFlushSize = zds->outEnd - zds->outStart; diff --git a/lib/zstd/huf_compress.c b/lib/zstd/huf_compress.c index e727812d12aa..08b4ae80aed4 100644 --- a/lib/zstd/huf_compress.c +++ b/lib/zstd/huf_compress.c @@ -556,9 +556,9 @@ size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, si n = srcSize & ~3; /* join to mod 4 */ switch (srcSize & 3) { case 3: HUF_encodeSymbol(&bitC, ip[n + 2], CTable); HUF_FLUSHBITS_2(&bitC); - /* fall through */ + fallthrough; case 2: HUF_encodeSymbol(&bitC, ip[n + 1], CTable); HUF_FLUSHBITS_1(&bitC); - /* fall through */ + fallthrough; case 1: HUF_encodeSymbol(&bitC, ip[n + 0], CTable); HUF_FLUSHBITS(&bitC); case 0: default:; -- cgit v1.2.3 From 36f9ff9e03de89691274a6aec45aa079bd3ae405 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 19 Nov 2020 07:11:44 -0600 Subject: lib: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding multiple break statements instead of letting the code fall through to the next case, and by replacing a number of /* fall through */ comments with the new pseudo-keyword macro fallthrough. Notice that Clang doesn't recognize /* Fall through */ comments as implicit fall-through markings. Link: https://github.com/KSPP/linux/issues/115 Signed-off-by: Gustavo A. R. Silva --- lib/cmdline.c | 1 + lib/kstrtox.c | 1 + lib/nlattr.c | 2 +- lib/vsprintf.c | 1 + lib/zlib_inflate/inflate.c | 24 ++++++++++++------------ lib/zstd/bitstream.h | 1 + lib/zstd/huf_compress.c | 1 + 7 files changed, 18 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/cmdline.c b/lib/cmdline.c index 55768b4f3f58..d11fdc579170 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -153,6 +153,7 @@ unsigned long long memparse(const char *ptr, char **retptr) case 'k': ret <<= 10; endptr++; + fallthrough; default: break; } diff --git a/lib/kstrtox.c b/lib/kstrtox.c index a14ccf905055..a118b0b1e9b2 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -355,6 +355,7 @@ int kstrtobool(const char *s, bool *res) default: break; } + break; default: break; } diff --git a/lib/nlattr.c b/lib/nlattr.c index 74019c8ebf6b..19372355557a 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -432,7 +432,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype, err = -EINVAL; goto out_err; } - /* fall through */ + fallthrough; case NLA_STRING: if (attrlen < 1) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d3c5c16f391c..3b53c73580c5 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2459,6 +2459,7 @@ qualifier: case 'd': case 'i': spec->flags |= SIGN; + break; case 'u': break; diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c index 67cc9b08ae9d..ee39b5eb71f7 100644 --- a/lib/zlib_inflate/inflate.c +++ b/lib/zlib_inflate/inflate.c @@ -396,7 +396,7 @@ int zlib_inflate(z_streamp strm, int flush) strm->adler = state->check = REVERSE(hold); INITBITS(); state->mode = DICT; - /* fall through */ + fallthrough; case DICT: if (state->havedict == 0) { RESTORE(); @@ -404,10 +404,10 @@ int zlib_inflate(z_streamp strm, int flush) } strm->adler = state->check = zlib_adler32(0L, NULL, 0); state->mode = TYPE; - /* fall through */ + fallthrough; case TYPE: if (flush == Z_BLOCK) goto inf_leave; - /* fall through */ + fallthrough; case TYPEDO: INFLATE_TYPEDO_HOOK(strm, flush); if (state->last) { @@ -446,7 +446,7 @@ int zlib_inflate(z_streamp strm, int flush) state->length = (unsigned)hold & 0xffff; INITBITS(); state->mode = COPY; - /* fall through */ + fallthrough; case COPY: copy = state->length; if (copy) { @@ -480,7 +480,7 @@ int zlib_inflate(z_streamp strm, int flush) #endif state->have = 0; state->mode = LENLENS; - /* fall through */ + fallthrough; case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); @@ -501,7 +501,7 @@ int zlib_inflate(z_streamp strm, int flush) } state->have = 0; state->mode = CODELENS; - /* fall through */ + fallthrough; case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { @@ -575,7 +575,7 @@ int zlib_inflate(z_streamp strm, int flush) break; } state->mode = LEN; - /* fall through */ + fallthrough; case LEN: if (have >= 6 && left >= 258) { RESTORE(); @@ -615,7 +615,7 @@ int zlib_inflate(z_streamp strm, int flush) } state->extra = (unsigned)(this.op) & 15; state->mode = LENEXT; - /* fall through */ + fallthrough; case LENEXT: if (state->extra) { NEEDBITS(state->extra); @@ -623,7 +623,7 @@ int zlib_inflate(z_streamp strm, int flush) DROPBITS(state->extra); } state->mode = DIST; - /* fall through */ + fallthrough; case DIST: for (;;) { this = state->distcode[BITS(state->distbits)]; @@ -649,7 +649,7 @@ int zlib_inflate(z_streamp strm, int flush) state->offset = (unsigned)this.val; state->extra = (unsigned)(this.op) & 15; state->mode = DISTEXT; - /* fall through */ + fallthrough; case DISTEXT: if (state->extra) { NEEDBITS(state->extra); @@ -669,7 +669,7 @@ int zlib_inflate(z_streamp strm, int flush) break; } state->mode = MATCH; - /* fall through */ + fallthrough; case MATCH: if (left == 0) goto inf_leave; copy = out - left; @@ -720,7 +720,7 @@ int zlib_inflate(z_streamp strm, int flush) INITBITS(); } state->mode = DONE; - /* fall through */ + fallthrough; case DONE: ret = Z_STREAM_END; goto inf_leave; diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h index 7c65c66e41fd..5d6343c1a909 100644 --- a/lib/zstd/bitstream.h +++ b/lib/zstd/bitstream.h @@ -269,6 +269,7 @@ ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, s case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16; fallthrough; case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8; + fallthrough; default:; } { diff --git a/lib/zstd/huf_compress.c b/lib/zstd/huf_compress.c index 08b4ae80aed4..fd32838c185f 100644 --- a/lib/zstd/huf_compress.c +++ b/lib/zstd/huf_compress.c @@ -560,6 +560,7 @@ size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, si case 2: HUF_encodeSymbol(&bitC, ip[n + 1], CTable); HUF_FLUSHBITS_1(&bitC); fallthrough; case 1: HUF_encodeSymbol(&bitC, ip[n + 0], CTable); HUF_FLUSHBITS(&bitC); + fallthrough; case 0: default:; } -- cgit v1.2.3 From 6fa6d28051e9fcaa1570e69648ea13a353a5d218 Mon Sep 17 00:00:00 2001 From: Daniel Xu Date: Tue, 17 Nov 2020 12:05:45 -0800 Subject: lib/strncpy_from_user.c: Mask out bytes after NUL terminator. do_strncpy_from_user() may copy some extra bytes after the NUL terminator into the destination buffer. This usually does not matter for normal string operations. However, when BPF programs key BPF maps with strings, this matters a lot. A BPF program may read strings from user memory by calling the bpf_probe_read_user_str() helper which eventually calls do_strncpy_from_user(). The program can then key a map with the destination buffer. BPF map keys are fixed-width and string-agnostic, meaning that map keys are treated as a set of bytes. The issue is when do_strncpy_from_user() overcopies bytes after the NUL terminator, it can result in seemingly identical strings occupying multiple slots in a BPF map. This behavior is subtle and totally unexpected by the user. This commit masks out the bytes following the NUL while preserving long-sized stride in the fast path. Fixes: 6ae08ae3dea2 ("bpf: Add probe_read_{user, kernel} and probe_read_{user, kernel}_str helpers") Signed-off-by: Daniel Xu Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/21efc982b3e9f2f7b0379eed642294caaa0c27a7.1605642949.git.dxu@dxuuu.xyz --- lib/strncpy_from_user.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index e6d5fcc2cdf3..122d8d0e253c 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c @@ -35,17 +35,32 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, goto byte_at_a_time; while (max >= sizeof(unsigned long)) { - unsigned long c, data; + unsigned long c, data, mask; /* Fall back to byte-at-a-time if we get a page fault */ unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time); - *(unsigned long *)(dst+res) = c; + /* + * Note that we mask out the bytes following the NUL. This is + * important to do because string oblivious code may read past + * the NUL. For those routines, we don't want to give them + * potentially random bytes after the NUL in `src`. + * + * One example of such code is BPF map keys. BPF treats map keys + * as an opaque set of bytes. Without the post-NUL mask, any BPF + * maps keyed by strings returned from strncpy_from_user() may + * have multiple entries for semantically identical strings. + */ if (has_zero(c, &data, &constants)) { data = prep_zero_mask(c, data, &constants); data = create_zero_mask(data); + mask = zero_bytemask(data); + *(unsigned long *)(dst+res) = c & mask; return res + find_zero(data); } + + *(unsigned long *)(dst+res) = c; + res += sizeof(unsigned long); max -= sizeof(unsigned long); } -- cgit v1.2.3 From a24d22b225ce158651378869a6b88105c4bdb887 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 12 Nov 2020 21:20:21 -0800 Subject: crypto: sha - split sha.h into sha1.h and sha2.h Currently contains declarations for both SHA-1 and SHA-2, and contains declarations for SHA-3. This organization is inconsistent, but more importantly SHA-1 is no longer considered to be cryptographically secure. So to the extent possible, SHA-1 shouldn't be grouped together with any of the other SHA versions, and usage of it should be phased out. Therefore, split into two headers and , and make everyone explicitly specify whether they want the declarations for SHA-1, SHA-2, or both. This avoids making the SHA-1 declarations visible to files that don't want anything to do with SHA-1. It also prepares for potentially moving sha1.h into a new insecure/ or dangerous/ directory. Signed-off-by: Eric Biggers Acked-by: Ard Biesheuvel Acked-by: Jason A. Donenfeld Signed-off-by: Herbert Xu --- lib/crypto/sha256.c | 2 +- lib/digsig.c | 2 +- lib/sha1.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c index cdef37c05972..72a4b0b1df28 100644 --- a/lib/crypto/sha256.c +++ b/lib/crypto/sha256.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include static const u32 SHA256_K[] = { diff --git a/lib/digsig.c b/lib/digsig.c index e0627c3e53b2..04b5e55ed95f 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/lib/sha1.c b/lib/sha1.c index 49257a915bb6..9bd1935a1472 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* -- cgit v1.2.3 From 1201581c57925b8bc2cba8628b61add3d16d4615 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 13 Nov 2020 17:12:59 +1100 Subject: crypto: lib/curve25519 - Move selftest prototype into header file This patch moves the curve25519_selftest into curve25519.h so we don't get a warning from gcc complaining about a missing prototype. Reported-by: kernel test robot Signed-off-by: Herbert Xu --- lib/crypto/curve25519.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/crypto/curve25519.c b/lib/crypto/curve25519.c index 288a62cd29b2..fb29739e8c29 100644 --- a/lib/crypto/curve25519.c +++ b/lib/crypto/curve25519.c @@ -13,8 +13,6 @@ #include #include -bool curve25519_selftest(void); - static int __init mod_init(void) { if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) && -- cgit v1.2.3 From 74d862b682f51e45d25b95b1ecf212428a4967b0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 18 Nov 2020 20:48:42 +0100 Subject: sched: Make migrate_disable/enable() independent of RT Now that the scheduler can deal with migrate disable properly, there is no real compelling reason to make it only available for RT. There are quite some code pathes which needlessly disable preemption in order to prevent migration and some constructs like kmap_atomic() enforce it implicitly. Making it available independent of RT allows to provide a preemptible variant of kmap_atomic() and makes the code more consistent in general. Signed-off-by: Thomas Gleixner Grudgingly-Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20201118204007.269943012@linutronix.de --- lib/smp_processor_id.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index faaa927ac2c8..1c1dbd300325 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -26,7 +26,7 @@ unsigned int check_preemption_disabled(const char *what1, const char *what2) if (current->nr_cpus_allowed == 1) goto out; -#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT) +#ifdef CONFIG_SMP if (current->migration_disabled) goto out; #endif -- cgit v1.2.3 From 6e799cb69a70eedbb41561b750f7180c12cff280 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 18 Nov 2020 20:48:39 +0100 Subject: mm/highmem: Provide and use CONFIG_DEBUG_KMAP_LOCAL CONFIG_KMAP_LOCAL can be enabled by x86/32bit even if CONFIG_HIGHMEM is not enabled for temporary MMIO space mappings. Provide it as a seperate config option which depends on CONFIG_KMAP_LOCAL and let CONFIG_DEBUG_HIGHMEM select it. This won't increase the debug coverage of this significantly but it paves the way to do so. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20201118204006.869487226@linutronix.de --- lib/Kconfig.debug | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c789b39ed527..f24fa158f9db 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -849,9 +849,17 @@ config DEBUG_PER_CPU_MAPS Say N if unsure. +config DEBUG_KMAP_LOCAL + bool "Debug kmap_local temporary mappings" + depends on DEBUG_KERNEL && KMAP_LOCAL + help + This option enables additional error checking for the kmap_local + infrastructure. Disable for production use. + config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM + select DEBUG_KMAP_LOCAL help This option enables additional error checking for high memory systems. Disable for production systems. -- cgit v1.2.3 From 0e91a0c6984c837a7c6760e3f28e8e1c532abf87 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 18 Nov 2020 20:48:40 +0100 Subject: mm/highmem: Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP CONFIG_DEBUG_KMAP_LOCAL, which is selected by CONFIG_DEBUG_HIGHMEM is only providing guard pages, but does not provide a mechanism to enforce the usage of the kmap_local() infrastructure. Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP which forces the temporary mapping even for lowmem pages. This needs to be a seperate config switch because this only works on architectures which do not have cache aliasing problems. Suggested-by: Linus Torvalds Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20201118204007.028261233@linutronix.de --- lib/Kconfig.debug | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f24fa158f9db..e952f892f047 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -856,9 +856,23 @@ config DEBUG_KMAP_LOCAL This option enables additional error checking for the kmap_local infrastructure. Disable for production use. +config ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP + bool + +config DEBUG_KMAP_LOCAL_FORCE_MAP + bool "Enforce kmap_local temporary mappings" + depends on DEBUG_KERNEL && ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP + select KMAP_LOCAL + select DEBUG_KMAP_LOCAL + help + This option enforces temporary mappings through the kmap_local + mechanism for non-highmem pages and on non-highmem systems. + Disable this for production systems! + config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM + select DEBUG_KMAP_LOCAL_FORCE_MAP if ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP select DEBUG_KMAP_LOCAL help This option enables additional error checking for high memory -- cgit v1.2.3 From fa69ee5aa48b5b52e8028c2eb486906e9998d081 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Wed, 25 Nov 2020 23:48:40 +0100 Subject: net: switch to storing KCOV handle directly in sk_buff It turns out that usage of skb extensions can cause memory leaks. Ido Schimmel reported: "[...] there are instances that blindly overwrite 'skb->extensions' by invoking skb_copy_header() after __alloc_skb()." Therefore, give up on using skb extensions for KCOV handle, and instead directly store kcov_handle in sk_buff. Fixes: 6370cc3bbd8a ("net: add kcov handle to skb extensions") Fixes: 85ce50d337d1 ("net: kcov: don't select SKB_EXTENSIONS when there is no NET") Fixes: 97f53a08cba1 ("net: linux/skbuff.h: combine SKB_EXTENSIONS + KCOV handling") Link: https://lore.kernel.org/linux-wireless/20201121160941.GA485907@shredder.lan/ Reported-by: Ido Schimmel Signed-off-by: Marco Elver Link: https://lore.kernel.org/r/20201125224840.2014773-1-elver@google.com Signed-off-by: Jakub Kicinski --- lib/Kconfig.debug | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 826a205ffd1c..1d15cdaf1b89 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1879,7 +1879,6 @@ config KCOV depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS select DEBUG_FS select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC - select SKB_EXTENSIONS if NET help KCOV exposes kernel code coverage information in a form suitable for coverage-guided fuzzing (randomized testing). -- cgit v1.2.3 From fadb08e7c7501ed42949e646c6865ba4ec5dd948 Mon Sep 17 00:00:00 2001 From: Arpitha Raghunandan <98.arpi@gmail.com> Date: Mon, 16 Nov 2020 11:10:35 +0530 Subject: kunit: Support for Parameterized Testing Implementation of support for parameterized testing in KUnit. This approach requires the creation of a test case using the KUNIT_CASE_PARAM() macro that accepts a generator function as input. This generator function should return the next parameter given the previous parameter in parameterized tests. It also provides a macro to generate common-case generators based on arrays. Generators may also optionally provide a human-readable description of parameters, which is displayed where available. Note, currently the result of each parameter run is displayed in diagnostic lines, and only the overall test case output summarizes TAP-compliant success or failure of all parameter runs. In future, when supported by kunit-tool, these can be turned into subsubtest outputs. Signed-off-by: Arpitha Raghunandan <98.arpi@gmail.com> Co-developed-by: Marco Elver Signed-off-by: Marco Elver Reviewed-by: David Gow Tested-by: David Gow Signed-off-by: Shuah Khan --- lib/kunit/test.c | 59 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/kunit/test.c b/lib/kunit/test.c index 750704abe89a..ec9494e914ef 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -325,39 +325,72 @@ static void kunit_catch_run_case(void *data) * occur in a test case and reports them as failures. */ static void kunit_run_case_catch_errors(struct kunit_suite *suite, - struct kunit_case *test_case) + struct kunit_case *test_case, + struct kunit *test) { struct kunit_try_catch_context context; struct kunit_try_catch *try_catch; - struct kunit test; - kunit_init_test(&test, test_case->name, test_case->log); - try_catch = &test.try_catch; + kunit_init_test(test, test_case->name, test_case->log); + try_catch = &test->try_catch; kunit_try_catch_init(try_catch, - &test, + test, kunit_try_run_case, kunit_catch_run_case); - context.test = &test; + context.test = test; context.suite = suite; context.test_case = test_case; kunit_try_catch_run(try_catch, &context); - test_case->success = test.success; - - kunit_print_ok_not_ok(&test, true, test_case->success, - kunit_test_case_num(suite, test_case), - test_case->name); + test_case->success = test->success; } int kunit_run_tests(struct kunit_suite *suite) { + char param_desc[KUNIT_PARAM_DESC_SIZE]; struct kunit_case *test_case; kunit_print_subtest_start(suite); - kunit_suite_for_each_test_case(suite, test_case) - kunit_run_case_catch_errors(suite, test_case); + kunit_suite_for_each_test_case(suite, test_case) { + struct kunit test = { .param_value = NULL, .param_index = 0 }; + bool test_success = true; + + if (test_case->generate_params) { + /* Get initial param. */ + param_desc[0] = '\0'; + test.param_value = test_case->generate_params(NULL, param_desc); + } + + do { + kunit_run_case_catch_errors(suite, test_case, &test); + test_success &= test_case->success; + + if (test_case->generate_params) { + if (param_desc[0] == '\0') { + snprintf(param_desc, sizeof(param_desc), + "param-%d", test.param_index); + } + + kunit_log(KERN_INFO, &test, + KUNIT_SUBTEST_INDENT + "# %s: %s %d - %s", + test_case->name, + kunit_status_to_string(test.success), + test.param_index + 1, param_desc); + + /* Get next param. */ + param_desc[0] = '\0'; + test.param_value = test_case->generate_params(test.param_value, param_desc); + test.param_index++; + } + } while (test.param_value); + + kunit_print_ok_not_ok(&test, true, test_success, + kunit_test_case_num(suite, test_case), + test_case->name); + } kunit_print_subtest_end(suite); -- cgit v1.2.3 From a2e9ae58d5042b3aa4a61f676ff6975ff3bc7bc7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 30 Oct 2020 12:37:43 +0100 Subject: lockdep/selftests: Fix PROVE_RAW_LOCK_NESTING The selftest nests rwlock_t inside raw_spinlock_t, this is invalid. Reported-by: Boqun Feng Signed-off-by: Peter Zijlstra (Intel) --- lib/locking-selftest.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index a899b3f0e2e5..afa7d4bb291f 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -58,10 +58,10 @@ static struct ww_mutex o, o2, o3; * Normal standalone locks, for the circular and irq-context * dependency tests: */ -static DEFINE_RAW_SPINLOCK(lock_A); -static DEFINE_RAW_SPINLOCK(lock_B); -static DEFINE_RAW_SPINLOCK(lock_C); -static DEFINE_RAW_SPINLOCK(lock_D); +static DEFINE_SPINLOCK(lock_A); +static DEFINE_SPINLOCK(lock_B); +static DEFINE_SPINLOCK(lock_C); +static DEFINE_SPINLOCK(lock_D); static DEFINE_RWLOCK(rwlock_A); static DEFINE_RWLOCK(rwlock_B); @@ -93,12 +93,12 @@ static DEFINE_RT_MUTEX(rtmutex_D); * but X* and Y* are different classes. We do this so that * we do not trigger a real lockup: */ -static DEFINE_RAW_SPINLOCK(lock_X1); -static DEFINE_RAW_SPINLOCK(lock_X2); -static DEFINE_RAW_SPINLOCK(lock_Y1); -static DEFINE_RAW_SPINLOCK(lock_Y2); -static DEFINE_RAW_SPINLOCK(lock_Z1); -static DEFINE_RAW_SPINLOCK(lock_Z2); +static DEFINE_SPINLOCK(lock_X1); +static DEFINE_SPINLOCK(lock_X2); +static DEFINE_SPINLOCK(lock_Y1); +static DEFINE_SPINLOCK(lock_Y2); +static DEFINE_SPINLOCK(lock_Z1); +static DEFINE_SPINLOCK(lock_Z2); static DEFINE_RWLOCK(rwlock_X1); static DEFINE_RWLOCK(rwlock_X2); @@ -138,10 +138,10 @@ static DEFINE_RT_MUTEX(rtmutex_Z2); */ #define INIT_CLASS_FUNC(class) \ static noinline void \ -init_class_##class(raw_spinlock_t *lock, rwlock_t *rwlock, \ +init_class_##class(spinlock_t *lock, rwlock_t *rwlock, \ struct mutex *mutex, struct rw_semaphore *rwsem)\ { \ - raw_spin_lock_init(lock); \ + spin_lock_init(lock); \ rwlock_init(rwlock); \ mutex_init(mutex); \ init_rwsem(rwsem); \ @@ -210,10 +210,10 @@ static void init_shared_classes(void) * Shortcuts for lock/unlock API variants, to keep * the testcases compact: */ -#define L(x) raw_spin_lock(&lock_##x) -#define U(x) raw_spin_unlock(&lock_##x) +#define L(x) spin_lock(&lock_##x) +#define U(x) spin_unlock(&lock_##x) #define LU(x) L(x); U(x) -#define SI(x) raw_spin_lock_init(&lock_##x) +#define SI(x) spin_lock_init(&lock_##x) #define WL(x) write_lock(&rwlock_##x) #define WU(x) write_unlock(&rwlock_##x) @@ -1341,7 +1341,7 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion3_soft_wlock) #define I2(x) \ do { \ - raw_spin_lock_init(&lock_##x); \ + spin_lock_init(&lock_##x); \ rwlock_init(&rwlock_##x); \ mutex_init(&mutex_##x); \ init_rwsem(&rwsem_##x); \ @@ -2005,7 +2005,7 @@ static void ww_test_edeadlk_acquire_wrong_slow(void) static void ww_test_spin_nest_unlocked(void) { - raw_spin_lock_nest_lock(&lock_A, &o.base); + spin_lock_nest_lock(&lock_A, &o.base); U(A); } -- cgit v1.2.3 From e04ce676e7aa490dcf5df880592e3db5e842a9bc Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Mon, 2 Nov 2020 13:37:42 +0800 Subject: lockdep/selftest: Add spin_nest_lock test Add a self test case to test the behavior for the following case: lock(A); lock_nest_lock(C1, A); lock(B); lock_nest_lock(C2, A); This is a reproducer for a problem[1] reported by Chris Wilson, and is helpful to prevent this. [1]: https://lore.kernel.org/lkml/160390684819.31966.12048967113267928793@build.alporthouse.com/ Signed-off-by: Boqun Feng Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20201102053743.450459-2-boqun.feng@gmail.com --- lib/locking-selftest.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib') diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index afa7d4bb291f..4c24ac8a456c 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -2009,6 +2009,19 @@ static void ww_test_spin_nest_unlocked(void) U(A); } +/* This is not a deadlock, because we have X1 to serialize Y1 and Y2 */ +static void ww_test_spin_nest_lock(void) +{ + spin_lock(&lock_X1); + spin_lock_nest_lock(&lock_Y1, &lock_X1); + spin_lock(&lock_A); + spin_lock_nest_lock(&lock_Y2, &lock_X1); + spin_unlock(&lock_A); + spin_unlock(&lock_Y2); + spin_unlock(&lock_Y1); + spin_unlock(&lock_X1); +} + static void ww_test_unneeded_slow(void) { WWAI(&t); @@ -2226,6 +2239,10 @@ static void ww_tests(void) dotest(ww_test_spin_nest_unlocked, FAILURE, LOCKTYPE_WW); pr_cont("\n"); + print_testname("spinlock nest test"); + dotest(ww_test_spin_nest_lock, SUCCESS, LOCKTYPE_WW); + pr_cont("\n"); + printk(" -----------------------------------------------------\n"); printk(" |block | try |context|\n"); printk(" -----------------------------------------------------\n"); -- cgit v1.2.3 From 4f134b89a24b965991e7c345b9a4591821f7c2a6 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 30 Nov 2020 08:36:48 +0100 Subject: lib/syscall: fix syscall registers retrieval on 32-bit platforms Lilith >_> and Claudio Bozzato of Cisco Talos security team reported that collect_syscall() improperly casts the syscall registers to 64-bit values leaking the uninitialized last 24 bytes on 32-bit platforms, that are visible in /proc/self/syscall. The cause is that info->data.args are u64 while syscall_get_arguments() uses longs, as hinted by the bogus pointer cast in the function. Let's just proceed like the other call places, by retrieving the registers into an array of longs before assigning them to the caller's array. This was successfully tested on x86_64, i386 and ppc32. Reference: CVE-2020-28588, TALOS-2020-1211 Fixes: 631b7abacd02 ("ptrace: Remove maxargs from task_current_syscall()") Cc: Greg KH Reviewed-by: Kees Cook Tested-by: Michael Ellerman (ppc32) Signed-off-by: Willy Tarreau Reviewed-by: Thomas Gleixner Signed-off-by: Linus Torvalds --- lib/syscall.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/syscall.c b/lib/syscall.c index 8533d2fea2d7..ba13e924c430 100644 --- a/lib/syscall.c +++ b/lib/syscall.c @@ -7,6 +7,7 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info) { + unsigned long args[6] = { }; struct pt_regs *regs; if (!try_get_task_stack(target)) { @@ -27,8 +28,14 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info info->data.nr = syscall_get_nr(target, regs); if (info->data.nr != -1L) - syscall_get_arguments(target, regs, - (unsigned long *)&info->data.args[0]); + syscall_get_arguments(target, regs, args); + + info->data.args[0] = args[0]; + info->data.args[1] = args[1]; + info->data.args[2] = args[2]; + info->data.args[3] = args[3]; + info->data.args[4] = args[4]; + info->data.args[5] = args[5]; put_task_stack(target); return 0; -- cgit v1.2.3 From ce0d5d63e897cc7c3a8fd043c7942fc6a78ec6f4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 27 Nov 2020 16:43:18 +1100 Subject: crypto: lib/blake2s - Move selftest prototype into header file This patch fixes a missing prototype warning on blake2s_selftest. Reported-by: kernel test robot Signed-off-by: Herbert Xu --- lib/crypto/blake2s-selftest.c | 2 +- lib/crypto/blake2s.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c index 79ef404a990d..5d9ea53be973 100644 --- a/lib/crypto/blake2s-selftest.c +++ b/lib/crypto/blake2s-selftest.c @@ -3,7 +3,7 @@ * Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved. */ -#include +#include #include /* diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c index 41025a30c524..6a4b6b78d630 100644 --- a/lib/crypto/blake2s.c +++ b/lib/crypto/blake2s.c @@ -17,8 +17,6 @@ #include #include -bool blake2s_selftest(void); - void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) { const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; -- cgit v1.2.3 From 11fb479ff5d9872ddff02dd533c16d60372c86b2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 5 Dec 2020 22:14:38 -0800 Subject: zlib: export S390 symbols for zlib modules Fix build errors when ZLIB_INFLATE=m and ZLIB_DEFLATE=m and ZLIB_DFLTCC=y by exporting the 2 needed symbols in dfltcc_inflate.c. Fixes these build errors: ERROR: modpost: "dfltcc_inflate" [lib/zlib_inflate/zlib_inflate.ko] undefined! ERROR: modpost: "dfltcc_can_inflate" [lib/zlib_inflate/zlib_inflate.ko] undefined! Fixes: 126196100063 ("lib/zlib: add s390 hardware support for kernel zlib_inflate") Reported-by: kernel test robot Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Acked-by: Ilya Leoshkevich Cc: Mikhail Zaslonko Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Christian Borntraeger Link: https://lkml.kernel.org/r/20201123191712.4882-1-rdunlap@infradead.org Signed-off-by: Linus Torvalds --- lib/zlib_dfltcc/dfltcc_inflate.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/zlib_dfltcc/dfltcc_inflate.c b/lib/zlib_dfltcc/dfltcc_inflate.c index aa9ef23474df..db107016d29b 100644 --- a/lib/zlib_dfltcc/dfltcc_inflate.c +++ b/lib/zlib_dfltcc/dfltcc_inflate.c @@ -4,6 +4,7 @@ #include "dfltcc_util.h" #include "dfltcc.h" #include +#include #include /* @@ -29,6 +30,7 @@ int dfltcc_can_inflate( return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); } +EXPORT_SYMBOL(dfltcc_can_inflate); static int dfltcc_was_inflate_used( z_streamp strm @@ -147,3 +149,4 @@ dfltcc_inflate_action dfltcc_inflate( return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ? DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE; } +EXPORT_SYMBOL(dfltcc_inflate); -- cgit v1.2.3 From b78beea038a3087df63bba7adaacb476a8ca95af Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Nov 2020 15:35:45 +0000 Subject: sbitmap: optimise sbitmap_deferred_clear() Because of spinlocks and atomics sbitmap_deferred_clear() have to reload &sb->map[index] on each access even though the map address won't change. Pass in sbitmap_word instead of {sb, index}, so it's cached in a variable. It also improves code generation of sbitmap_find_bit_in_index(). Signed-off-by: Pavel Begunkov Reviewed-by: John Garry Signed-off-by: Jens Axboe --- lib/sbitmap.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 267aa7709416..c1c8a4e69325 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -12,32 +12,32 @@ /* * See if we have deferred clears that we can batch move */ -static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index) +static inline bool sbitmap_deferred_clear(struct sbitmap_word *map) { unsigned long mask, val; bool ret = false; unsigned long flags; - spin_lock_irqsave(&sb->map[index].swap_lock, flags); + spin_lock_irqsave(&map->swap_lock, flags); - if (!sb->map[index].cleared) + if (!map->cleared) goto out_unlock; /* * First get a stable cleared mask, setting the old mask to 0. */ - mask = xchg(&sb->map[index].cleared, 0); + mask = xchg(&map->cleared, 0); /* * Now clear the masked bits in our free word */ do { - val = sb->map[index].word; - } while (cmpxchg(&sb->map[index].word, val, val & ~mask) != val); + val = map->word; + } while (cmpxchg(&map->word, val, val & ~mask) != val); ret = true; out_unlock: - spin_unlock_irqrestore(&sb->map[index].swap_lock, flags); + spin_unlock_irqrestore(&map->swap_lock, flags); return ret; } @@ -92,7 +92,7 @@ void sbitmap_resize(struct sbitmap *sb, unsigned int depth) unsigned int i; for (i = 0; i < sb->map_nr; i++) - sbitmap_deferred_clear(sb, i); + sbitmap_deferred_clear(&sb->map[i]); sb->depth = depth; sb->map_nr = DIV_ROUND_UP(sb->depth, bits_per_word); @@ -139,15 +139,15 @@ static int __sbitmap_get_word(unsigned long *word, unsigned long depth, static int sbitmap_find_bit_in_index(struct sbitmap *sb, int index, unsigned int alloc_hint, bool round_robin) { + struct sbitmap_word *map = &sb->map[index]; int nr; do { - nr = __sbitmap_get_word(&sb->map[index].word, - sb->map[index].depth, alloc_hint, + nr = __sbitmap_get_word(&map->word, map->depth, alloc_hint, !round_robin); if (nr != -1) break; - if (!sbitmap_deferred_clear(sb, index)) + if (!sbitmap_deferred_clear(map)) break; } while (1); @@ -207,7 +207,7 @@ again: break; } - if (sbitmap_deferred_clear(sb, index)) + if (sbitmap_deferred_clear(&sb->map[index])) goto again; /* Jump to next index. */ -- cgit v1.2.3 From 661d4f55a79483aee4970a76e3bd9d4cdc74ac79 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Nov 2020 15:35:46 +0000 Subject: sbitmap: remove swap_lock map->swap_lock protects map->cleared from concurrent modification, however sbitmap_deferred_clear() is already atomically drains it, so it's guaranteed to not loose bits on concurrent sbitmap_deferred_clear(). A one threaded tag heavy test on top of nullbk showed ~1.5% t-put increase, and 3% -> 1% cycle reduction of sbitmap_get() according to perf. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- lib/sbitmap.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/sbitmap.c b/lib/sbitmap.c index c1c8a4e69325..4fd877048ba8 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -15,13 +15,9 @@ static inline bool sbitmap_deferred_clear(struct sbitmap_word *map) { unsigned long mask, val; - bool ret = false; - unsigned long flags; - spin_lock_irqsave(&map->swap_lock, flags); - - if (!map->cleared) - goto out_unlock; + if (!READ_ONCE(map->cleared)) + return false; /* * First get a stable cleared mask, setting the old mask to 0. @@ -35,10 +31,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap_word *map) val = map->word; } while (cmpxchg(&map->word, val, val & ~mask) != val); - ret = true; -out_unlock: - spin_unlock_irqrestore(&map->swap_lock, flags); - return ret; + return true; } int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift, @@ -80,7 +73,6 @@ int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift, for (i = 0; i < sb->map_nr; i++) { sb->map[i].depth = min(depth, bits_per_word); depth -= sb->map[i].depth; - spin_lock_init(&sb->map[i].swap_lock); } return 0; } -- cgit v1.2.3 From c3250c8d2451ffbea14ba95164c59edd943ee4be Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Nov 2020 15:35:47 +0000 Subject: sbitmap: replace CAS with atomic and sbitmap_deferred_clear() does CAS loop to propagate cleared bits, replace it with equivalent atomic bitwise and. That's slightly faster and makes wait-free instead of lock-free as before. The atomic can be relaxed (i.e. barrier-less) because following sbitmap_get*() deal with synchronisation, see comments in sbitmap_queue_clear(). It's ok to cast to atomic_long_t, that's what bitops/lock.h does. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- lib/sbitmap.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/sbitmap.c b/lib/sbitmap.c index 4fd877048ba8..c18b518a16ba 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -14,7 +14,7 @@ */ static inline bool sbitmap_deferred_clear(struct sbitmap_word *map) { - unsigned long mask, val; + unsigned long mask; if (!READ_ONCE(map->cleared)) return false; @@ -27,10 +27,8 @@ static inline bool sbitmap_deferred_clear(struct sbitmap_word *map) /* * Now clear the masked bits in our free word */ - do { - val = map->word; - } while (cmpxchg(&map->word, val, val & ~mask) != val); - + atomic_long_andnot(mask, (atomic_long_t *)&map->word); + BUILD_BUG_ON(sizeof(atomic_long_t) != sizeof(map->word)); return true; } -- cgit v1.2.3 From 0eff1f1a38a95b20fec83d0b69409c8da967fe1e Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 22 Nov 2020 15:35:48 +0000 Subject: sbitmap: simplify wrap check __sbitmap_get_word() doesn't warp if it's starting from the beginning (i.e. initial hint is 0). Instead of stashing the original hint just set @wrap accordingly. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- lib/sbitmap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/sbitmap.c b/lib/sbitmap.c index c18b518a16ba..d693d9213ceb 100644 --- a/lib/sbitmap.c +++ b/lib/sbitmap.c @@ -97,9 +97,11 @@ EXPORT_SYMBOL_GPL(sbitmap_resize); static int __sbitmap_get_word(unsigned long *word, unsigned long depth, unsigned int hint, bool wrap) { - unsigned int orig_hint = hint; int nr; + /* don't wrap if starting from 0 */ + wrap = wrap && hint; + while (1) { nr = find_next_zero_bit(word, depth, hint); if (unlikely(nr >= depth)) { @@ -108,8 +110,8 @@ static int __sbitmap_get_word(unsigned long *word, unsigned long depth, * offset to 0 in a failure case, so start from 0 to * exhaust the map. */ - if (orig_hint && hint && wrap) { - hint = orig_hint = 0; + if (hint && wrap) { + hint = 0; continue; } return -1; -- cgit v1.2.3 From 3577afb0052fca65e67efdfc8e0859bb7bac87a6 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Wed, 9 Dec 2020 11:36:25 -0700 Subject: dyndbg: fix use before null check In commit a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()"), a string is copied before checking it isn't NULL. Fix this, report a usage/interface error, and return the proper error code. Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()") Cc: stable@vger.kernel.org -- -v2 drop comment tweak, improve commit message Signed-off-by: Jim Cromie Link: https://lore.kernel.org/r/20201209183625.2432329-1-jim.cromie@gmail.com Signed-off-by: Greg Kroah-Hartman --- lib/dynamic_debug.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index bd7b3aaa93c3..c70d6347afa2 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -561,9 +561,14 @@ static int ddebug_exec_queries(char *query, const char *modname) int dynamic_debug_exec_queries(const char *query, const char *modname) { int rc; - char *qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL); + char *qry; /* writable copy of query */ - if (!query) + if (!query) { + pr_err("non-null query/command string expected\n"); + return -EINVAL; + } + qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL); + if (!qry) return -ENOMEM; rc = ddebug_exec_queries(qry, modname); -- cgit v1.2.3 From 527701eda5f196588df9b36a30651804fea7d1a7 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 9 Jul 2020 11:43:21 -0700 Subject: lib: Add a generic version of devmem_is_allowed() As part of adding support for STRICT_DEVMEM to the RISC-V port, Zong provided a devmem_is_allowed() implementation that's exactly the same as all the others I checked. Instead I'm adding a generic version, which will soon be used. Reviewed-by: Luis Chamberlain Signed-off-by: Palmer Dabbelt --- lib/Kconfig | 3 +++ lib/Kconfig.debug | 2 +- lib/Makefile | 2 ++ lib/devmem_is_allowed.c | 27 +++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 lib/devmem_is_allowed.c (limited to 'lib') diff --git a/lib/Kconfig b/lib/Kconfig index b4b98a03ff98..b26721cf51bc 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -681,6 +681,9 @@ config GENERIC_LIB_CMPDI2 config GENERIC_LIB_UCMPDI2 bool +config GENERIC_LIB_DEVMEM_IS_ALLOWED + bool + config PLDMFW bool default n diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0c781f912f9f..87410f62b501 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1626,7 +1626,7 @@ config ARCH_HAS_DEVMEM_IS_ALLOWED config STRICT_DEVMEM bool "Filter access to /dev/mem" depends on MMU && DEVMEM - depends on ARCH_HAS_DEVMEM_IS_ALLOWED + depends on ARCH_HAS_DEVMEM_IS_ALLOWED || GENERIC_LIB_DEVMEM_IS_ALLOWED default y if PPC || X86 || ARM64 help If this option is disabled, you allow userspace (root) access to all diff --git a/lib/Makefile b/lib/Makefile index a4a4c6864f51..34011a11fbb3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -348,3 +348,5 @@ obj-$(CONFIG_PLDMFW) += pldmfw/ obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o obj-$(CONFIG_BITS_TEST) += test_bits.o + +obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o diff --git a/lib/devmem_is_allowed.c b/lib/devmem_is_allowed.c new file mode 100644 index 000000000000..c0d67c541849 --- /dev/null +++ b/lib/devmem_is_allowed.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * A generic version of devmem_is_allowed. + * + * Based on arch/arm64/mm/mmap.c + * + * Copyright (C) 2020 Google, Inc. + * Copyright (C) 2012 ARM Ltd. + */ + +#include +#include + +/* + * devmem_is_allowed() checks to see if /dev/mem access to a certain address + * is valid. The argument is a physical page number. We mimic x86 here by + * disallowing access to system RAM as well as device-exclusive MMIO regions. + * This effectively disable read()/write() on /dev/mem. + */ +int devmem_is_allowed(unsigned long pfn) +{ + if (iomem_is_exclusive(pfn << PAGE_SHIFT)) + return 0; + if (!page_is_ram(pfn)) + return 1; + return 0; +} -- cgit v1.2.3 From 84edc2eff82730d45ab513ecec49cb63beb973c9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 11 Dec 2020 13:36:35 -0800 Subject: selftest/fpu: avoid clang warning With extra warnings enabled, clang complains about the redundant -mhard-float argument: clang: error: argument unused during compilation: '-mhard-float' [-Werror,-Wunused-command-line-argument] Move this into the gcc-only part of the Makefile. Link: https://lkml.kernel.org/r/20201203223652.1320700-1-arnd@kernel.org Fixes: 4185b3b92792 ("selftests/fpu: Add an FPU selftest") Signed-off-by: Arnd Bergmann Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Petteri Aimonen Cc: Borislav Petkov Cc: Arnd Bergmann Cc: Andy Shevchenko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index ce45af50983a..d415fc7067c5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -107,7 +107,7 @@ obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o # off the generation of FPU/SSE* instructions for kernel proper but FPU_FLAGS # get appended last to CFLAGS and thus override those previous compiler options. # -FPU_CFLAGS := -mhard-float -msse -msse2 +FPU_CFLAGS := -msse -msse2 ifdef CONFIG_CC_IS_GCC # Stack alignment mismatch, proceed with caution. # GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 @@ -120,6 +120,7 @@ ifdef CONFIG_CC_IS_GCC # -mpreferred-stack-boundary=3 is not between 4 and 12 # # can be triggered. Otherwise gcc doesn't complain. +FPU_CFLAGS += -mhard-float FPU_CFLAGS += $(call cc-option,-msse -mpreferred-stack-boundary=3,-mpreferred-stack-boundary=4) endif -- cgit v1.2.3 From d5037d1d82b39d70e2f5952528f24172f33f5629 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 14 Dec 2020 19:08:38 -0800 Subject: locking/selftests: add testcases for fs_reclaim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since I butchered this I figured better to make sure we have testcases for this now. Since we only have a locking context for __GFP_FS that's the only thing we're testing right now. Link: https://lkml.kernel.org/r/20201125162532.1299794-4-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter Acked-by: Peter Zijlstra (Intel) Cc: Dave Chinner Cc: Qian Cai Cc: Thomas Hellström (Intel) Cc: Jason Gunthorpe Cc: Maarten Lankhorst Cc: Christian König Cc: "Matthew Wilcox (Oracle)" Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Christoph Lameter Cc: David Rientjes Cc: Ingo Molnar Cc: Jason Gunthorpe Cc: Joonsoo Kim Cc: Mathieu Desnoyers Cc: Michel Lespinasse Cc: Paul E. McKenney Cc: Pekka Enberg Cc: Randy Dunlap Cc: Sebastian Andrzej Siewior Cc: Thomas Gleixner Cc: Vlastimil Babka Cc: Waiman Long Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/locking-selftest.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'lib') diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index a899b3f0e2e5..ad47c3358e30 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -2357,6 +2358,50 @@ static void queued_read_lock_tests(void) pr_cont("\n"); } +static void fs_reclaim_correct_nesting(void) +{ + fs_reclaim_acquire(GFP_KERNEL); + might_alloc(GFP_NOFS); + fs_reclaim_release(GFP_KERNEL); +} + +static void fs_reclaim_wrong_nesting(void) +{ + fs_reclaim_acquire(GFP_KERNEL); + might_alloc(GFP_KERNEL); + fs_reclaim_release(GFP_KERNEL); +} + +static void fs_reclaim_protected_nesting(void) +{ + unsigned int flags; + + fs_reclaim_acquire(GFP_KERNEL); + flags = memalloc_nofs_save(); + might_alloc(GFP_KERNEL); + memalloc_nofs_restore(flags); + fs_reclaim_release(GFP_KERNEL); +} + +static void fs_reclaim_tests(void) +{ + printk(" --------------------\n"); + printk(" | fs_reclaim tests |\n"); + printk(" --------------------\n"); + + print_testname("correct nesting"); + dotest(fs_reclaim_correct_nesting, SUCCESS, 0); + pr_cont("\n"); + + print_testname("wrong nesting"); + dotest(fs_reclaim_wrong_nesting, FAILURE, 0); + pr_cont("\n"); + + print_testname("protected nesting"); + dotest(fs_reclaim_protected_nesting, SUCCESS, 0); + pr_cont("\n"); +} + void locking_selftest(void) { /* @@ -2478,6 +2523,8 @@ void locking_selftest(void) if (IS_ENABLED(CONFIG_QUEUED_RWLOCKS)) queued_read_lock_tests(); + fs_reclaim_tests(); + if (unexpected_testcase_failures) { printk("-----------------------------------------------------------------\n"); debug_locks = 0; -- cgit v1.2.3 From 214c783d593bdb83cc7e3bd9df9c6fe206d82e1c Mon Sep 17 00:00:00 2001 From: Walter Wu Date: Mon, 14 Dec 2020 19:09:17 -0800 Subject: lib/test_kasan.c: add workqueue test case Adds a test to verify workqueue stack recording and print it in KASAN report. The KASAN report was as follows(cleaned up slightly): BUG: KASAN: use-after-free in kasan_workqueue_uaf Freed by task 54: kasan_save_stack+0x24/0x50 kasan_set_track+0x24/0x38 kasan_set_free_info+0x20/0x40 __kasan_slab_free+0x10c/0x170 kasan_slab_free+0x10/0x18 kfree+0x98/0x270 kasan_workqueue_work+0xc/0x18 Last potentially related work creation: kasan_save_stack+0x24/0x50 kasan_record_wq_stack+0xa8/0xb8 insert_work+0x48/0x288 __queue_work+0x3e8/0xc40 queue_work_on+0xf4/0x118 kasan_workqueue_uaf+0xfc/0x190 Link: https://lkml.kernel.org/r/20201203022748.30681-1-walter-zh.wu@mediatek.com Signed-off-by: Walter Wu Acked-by: Marco Elver Reviewed-by: Dmitry Vyukov Reviewed-by: Andrey Konovalov Cc: Andrey Ryabinin Cc: Alexander Potapenko Cc: Matthias Brugger Cc: Jonathan Corbet Cc: Lai Jiangshan Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_kasan_module.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'lib') diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c index 2d68db6ae67b..62a87854b120 100644 --- a/lib/test_kasan_module.c +++ b/lib/test_kasan_module.c @@ -91,6 +91,34 @@ static noinline void __init kasan_rcu_uaf(void) call_rcu(&global_rcu_ptr->rcu, kasan_rcu_reclaim); } +static noinline void __init kasan_workqueue_work(struct work_struct *work) +{ + kfree(work); +} + +static noinline void __init kasan_workqueue_uaf(void) +{ + struct workqueue_struct *workqueue; + struct work_struct *work; + + workqueue = create_workqueue("kasan_wq_test"); + if (!workqueue) { + pr_err("Allocation failed\n"); + return; + } + work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); + if (!work) { + pr_err("Allocation failed\n"); + return; + } + + INIT_WORK(work, kasan_workqueue_work); + queue_work(workqueue, work); + destroy_workqueue(workqueue); + + pr_info("use-after-free on workqueue\n"); + ((volatile struct work_struct *)work)->data; +} static int __init test_kasan_module_init(void) { @@ -102,6 +130,7 @@ static int __init test_kasan_module_init(void) copy_user_test(); kasan_rcu_uaf(); + kasan_workqueue_uaf(); kasan_restore_multi_shot(multishot); return -EAGAIN; -- cgit v1.2.3 From aa6159ab99a9ab5df835b4750b66cf132a5aa292 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 15 Dec 2020 20:42:48 -0800 Subject: kernel.h: split out mathematical helpers kernel.h is being used as a dump for all kinds of stuff for a long time. Here is the attempt to start cleaning it up by splitting out mathematical helpers. At the same time convert users in header and lib folder to use new header. Though for time being include new header back to kernel.h to avoid twisted indirected includes for existing users. [sfr@canb.auug.org.au: fix powerpc build] Link: https://lkml.kernel.org/r/20201029150809.13059608@canb.auug.org.au Link: https://lkml.kernel.org/r/20201028173212.41768-1-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Cc: "Paul E. McKenney" Cc: Trond Myklebust Cc: Jeff Layton Cc: Rasmus Villemoes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/errname.c | 1 + lib/errseq.c | 1 + lib/find_bit.c | 3 ++- lib/math/div64.c | 4 +++- lib/math/int_pow.c | 2 +- lib/math/int_sqrt.c | 3 ++- lib/math/reciprocal_div.c | 9 ++++++--- 7 files changed, 16 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/errname.c b/lib/errname.c index 0c4d3e66170e..05cbf731545f 100644 --- a/lib/errname.c +++ b/lib/errname.c @@ -3,6 +3,7 @@ #include #include #include +#include /* * Ensure these tables do not accidentally become gigantic if some diff --git a/lib/errseq.c b/lib/errseq.c index 81f9e33aa7e7..93e9b94358dc 100644 --- a/lib/errseq.c +++ b/lib/errseq.c @@ -3,6 +3,7 @@ #include #include #include +#include /* * An errseq_t is a way of recording errors in one place, and allowing any diff --git a/lib/find_bit.c b/lib/find_bit.c index 4a8751010d59..f67f86fd2f62 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -15,8 +15,9 @@ #include #include #include -#include +#include #include +#include #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) || \ diff --git a/lib/math/div64.c b/lib/math/div64.c index 3952a07130d8..064d68a5391a 100644 --- a/lib/math/div64.c +++ b/lib/math/div64.c @@ -18,9 +18,11 @@ * or by defining a preprocessor macro in arch/include/asm/div64.h. */ +#include #include -#include +#include #include +#include /* Not needed on 64bit architectures */ #if BITS_PER_LONG == 32 diff --git a/lib/math/int_pow.c b/lib/math/int_pow.c index 622fc1ab3c74..0cf426e69bda 100644 --- a/lib/math/int_pow.c +++ b/lib/math/int_pow.c @@ -6,7 +6,7 @@ */ #include -#include +#include #include /** diff --git a/lib/math/int_sqrt.c b/lib/math/int_sqrt.c index 30e0f9770f88..a8170bb9142f 100644 --- a/lib/math/int_sqrt.c +++ b/lib/math/int_sqrt.c @@ -6,9 +6,10 @@ * square root from Guy L. Steele. */ -#include #include #include +#include +#include /** * int_sqrt - computes the integer square root diff --git a/lib/math/reciprocal_div.c b/lib/math/reciprocal_div.c index 32436dd4171e..6cb4adbb81d2 100644 --- a/lib/math/reciprocal_div.c +++ b/lib/math/reciprocal_div.c @@ -1,10 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include -#include -#include -#include #include +#include +#include #include +#include + +#include /* * For a description of the algorithm please have a look at -- cgit v1.2.3 From 0ae446e4b91b5a713fb189cf7f23d1a303057fd9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Dec 2020 20:43:01 -0800 Subject: lib/test_free_pages.c: add basic progress indicators The test module to check that free_pages() does not leak memory does not provide any feedback whatsoever its state or progress, but may take some time on slow machines. Add the printing of messages upon starting each phase of the test, and upon completion. Link: https://lkml.kernel.org/r/20201018140445.20972-1-geert@linux-m68k.org Signed-off-by: Geert Uytterhoeven Cc: Mike Rapoport Cc: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_free_pages.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/test_free_pages.c b/lib/test_free_pages.c index 074e76bd76b2..25ae1ac2624a 100644 --- a/lib/test_free_pages.c +++ b/lib/test_free_pages.c @@ -5,6 +5,8 @@ * Author: Matthew Wilcox */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -26,8 +28,11 @@ static void test_free_pages(gfp_t gfp) static int m_in(void) { + pr_info("Testing with GFP_KERNEL\n"); test_free_pages(GFP_KERNEL); + pr_info("Testing with GFP_KERNEL | __GFP_COMP\n"); test_free_pages(GFP_KERNEL | __GFP_COMP); + pr_info("Test completed\n"); return 0; } -- cgit v1.2.3 From 3a2b67e6e3fdb14c6da4c6909454d7a1d9b24f70 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Dec 2020 20:43:04 -0800 Subject: lib/stackdepot.c: replace one-element array with flexible-array member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch series "lib/stackdepot.c: Replace one-element array with flexible-array member". This series aims to replace a one-element array with a flexible-array member. Also, make use of the struct_size(), flexible_array_size() and array_size() helpers. This patch (of 3): There is a regular need in the kernel to provide a way to declare having a dynamically sized set of trailing elements in a structure. Kernel code should always use “flexible array members”[1] for these cases. The older style of one-element or zero-length arrays should no longer be used[2]. Refactor the code according to the use of a flexible-array member in struct stack_record, instead of a one-element array, and use the struct_size() helper to calculate the size for the allocation. [1] https://en.wikipedia.org/wiki/Flexible_array_member [2] https://www.kernel.org/doc/html/v5.9-rc1/process/deprecated.html#zero-length-and-one-element-arrays Link: https://lkml.kernel.org/r/cover.1601565471.git.gustavoars@kernel.org Link: https://lore.kernel.org/lkml/5f75876b.x9zdN10esiC0qLHV%25lkp@intel.com/ Link: https://lkml.kernel.org/r/2f1e6a17aaa891ad9c58817cf0a10b8ab8894f59.1601565471.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/stackdepot.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/stackdepot.c b/lib/stackdepot.c index 2caffc64e4c8..c6106cfb7950 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -62,7 +62,7 @@ struct stack_record { u32 hash; /* Hash in the hastable */ u32 size; /* Number of frames in the stack */ union handle_parts handle; - unsigned long entries[1]; /* Variable-sized array of entries. */ + unsigned long entries[]; /* Variable-sized array of entries. */ }; static void *stack_slabs[STACK_ALLOC_MAX_SLABS]; @@ -104,9 +104,8 @@ static bool init_stack_slab(void **prealloc) static struct stack_record *depot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc, gfp_t alloc_flags) { - int required_size = offsetof(struct stack_record, entries) + - sizeof(unsigned long) * size; struct stack_record *stack; + size_t required_size = struct_size(stack, entries, size); required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN); -- cgit v1.2.3 From 47e684aaa2661b2af39474a12d05447865ce9184 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Dec 2020 20:43:07 -0800 Subject: lib/stackdepot.c: use flex_array_size() helper in memcpy() Make use of the flex_array_size() helper to calculate the size of a flexible array member within an enclosing structure. This helper offers defense-in-depth against potential integer overflows, while at the same time makes it explicitly clear that we are dealing with a flexible array member. Link: https://lkml.kernel.org/r/186e37fe07196ee41a0e562fa8a8cb7a01112ec5.1601565471.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/stackdepot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/stackdepot.c b/lib/stackdepot.c index c6106cfb7950..683b6a8ddade 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -135,7 +135,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size, stack->handle.slabindex = depot_index; stack->handle.offset = depot_offset >> STACK_ALLOC_ALIGN; stack->handle.valid = 1; - memcpy(stack->entries, entries, size * sizeof(unsigned long)); + memcpy(stack->entries, entries, flex_array_size(stack, entries, size)); depot_offset += required_size; return stack; -- cgit v1.2.3 From 180644f80a0284bf5c9acdbd33760924fef14236 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Dec 2020 20:43:10 -0800 Subject: lib/stackdepot.c: use array_size() helper in jhash2() Use array_size() helper instead of the open-coded version in jhash2(). These sorts of multiplication factors need to be wrapped in array_size(). Also, use the preferred form for passing the size of an object type. Link: https://lkml.kernel.org/r/cb8a682e4bba4dbddd2bd8aca7f8c02fea89639b.1601565471.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/stackdepot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/stackdepot.c b/lib/stackdepot.c index 683b6a8ddade..890dcc2e984e 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -154,8 +154,8 @@ static struct stack_record *stack_table[STACK_HASH_SIZE] = { static inline u32 hash_stack(unsigned long *entries, unsigned int size) { return jhash2((u32 *)entries, - size * sizeof(unsigned long) / sizeof(u32), - STACK_HASH_SEED); + array_size(size, sizeof(*entries)) / sizeof(u32), + STACK_HASH_SEED); } /* Use our own, non-instrumented version of memcmp(). -- cgit v1.2.3 From 45e3d5a2af1d53164cc5fbd22c5ceea0d163ad45 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 15 Dec 2020 20:43:13 -0800 Subject: lib/test_lockup.c: minimum fix to get it compiled on PREEMPT_RT On PREEMPT_RT the locks are quite different so they can't be tested as it is done below. The alternative is to test for the waitlock within rtmutex. This is the bare minimun to get it compiled. Problems which exist on PREEMP_RT: - none of the locks (spinlock_t, rwlock_t, mutex_t, rw_semaphore) may be acquired with disabled preemption or interrupts. If I read the code correct the it is possible to acquire a mutex_t with disabled interrupts. I don't know how to obtain a lock pointer. Technically they are not exported to userland. - memory can not be allocated with disabled preemption or interrupts even with GFP_ATOMIC. Link: https://lkml.kernel.org/r/20201028181041.xyeothhkouc3p4md@linutronix.de Signed-off-by: Sebastian Andrzej Siewior Cc: Konstantin Khlebnikov Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_lockup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'lib') diff --git a/lib/test_lockup.c b/lib/test_lockup.c index f1a020bcc763..864554e76973 100644 --- a/lib/test_lockup.c +++ b/lib/test_lockup.c @@ -480,6 +480,21 @@ static int __init test_lockup_init(void) return -EINVAL; #ifdef CONFIG_DEBUG_SPINLOCK +#ifdef CONFIG_PREEMPT_RT + if (test_magic(lock_spinlock_ptr, + offsetof(spinlock_t, lock.wait_lock.magic), + SPINLOCK_MAGIC) || + test_magic(lock_rwlock_ptr, + offsetof(rwlock_t, rtmutex.wait_lock.magic), + SPINLOCK_MAGIC) || + test_magic(lock_mutex_ptr, + offsetof(struct mutex, lock.wait_lock.magic), + SPINLOCK_MAGIC) || + test_magic(lock_rwsem_ptr, + offsetof(struct rw_semaphore, rtmutex.wait_lock.magic), + SPINLOCK_MAGIC)) + return -EINVAL; +#else if (test_magic(lock_spinlock_ptr, offsetof(spinlock_t, rlock.magic), SPINLOCK_MAGIC) || @@ -493,6 +508,7 @@ static int __init test_lockup_init(void) offsetof(struct rw_semaphore, wait_lock.magic), SPINLOCK_MAGIC)) return -EINVAL; +#endif #endif if ((wait_state != TASK_RUNNING || -- cgit v1.2.3 From e291851d65495739e4eede33b6bc387bb546a19b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 15 Dec 2020 20:43:27 -0800 Subject: lib/cmdline: fix get_option() for strings starting with hyphen When string doesn't have an integer and starts from hyphen get_option() may return interesting results. Fix it to return 0. The simple_strtoull() is used due to absence of simple_strtoul() in a boot code on some architectures. Note, the Fixes tag below is rather for anthropological curiosity. Link: https://lkml.kernel.org/r/20201112180732.75589-4-andriy.shevchenko@linux.intel.com Fixes: f68565831e72 ("Import 2.4.0-test2pre3") Signed-off-by: Andy Shevchenko Cc: Brendan Higgins Cc: David Gow Cc: Mark Brown Cc: Matti Vaittinen Cc: Shuah Khan Cc: Vitor Massaru Iha Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/cmdline.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/cmdline.c b/lib/cmdline.c index fbb9981a04a4..ca89846ee0bb 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -45,6 +45,9 @@ static int get_range(char **str, int *pint, int n) * 1 - int found, no subsequent comma * 2 - int found including a subsequent comma * 3 - hyphen found to denote a range + * + * Leading hyphen without integer is no integer case, but we consume it + * for the sake of simplification. */ int get_option(char **str, int *pint) @@ -53,7 +56,10 @@ int get_option(char **str, int *pint) if (!cur || !(*cur)) return 0; - *pint = simple_strtol(cur, str, 0); + if (*cur == '-') + *pint = -simple_strtoull(++cur, str, 0); + else + *pint = simple_strtoull(cur, str, 0); if (cur == *str) return 0; if (**str == ',') { -- cgit v1.2.3 From 6b2b6b864684848f9deacb6d0faa00626860832e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 15 Dec 2020 20:43:30 -0800 Subject: lib/cmdline: allow NULL to be an output for get_option() In the future we would like to use get_option() to only validate the string and parse it separately. To achieve this, allow NULL to be an output for get_option(). Link: https://lkml.kernel.org/r/20201112180732.75589-5-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Cc: Brendan Higgins Cc: David Gow Cc: Mark Brown Cc: Matti Vaittinen Cc: Shuah Khan Cc: Vitor Massaru Iha Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/cmdline.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/cmdline.c b/lib/cmdline.c index ca89846ee0bb..9e186234edc0 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -35,11 +35,14 @@ static int get_range(char **str, int *pint, int n) /** * get_option - Parse integer from an option string * @str: option string - * @pint: (output) integer value parsed from @str + * @pint: (optional output) integer value parsed from @str * * Read an int from an option string; if available accept a subsequent * comma as well. * + * When @pint is NULL the function can be used as a validator of + * the current option in the string. + * * Return values: * 0 - no int in string * 1 - int found, no subsequent comma @@ -53,13 +56,16 @@ static int get_range(char **str, int *pint, int n) int get_option(char **str, int *pint) { char *cur = *str; + int value; if (!cur || !(*cur)) return 0; if (*cur == '-') - *pint = -simple_strtoull(++cur, str, 0); + value = -simple_strtoull(++cur, str, 0); else - *pint = simple_strtoull(cur, str, 0); + value = simple_strtoull(cur, str, 0); + if (pint) + *pint = value; if (cur == *str) return 0; if (**str == ',') { -- cgit v1.2.3 From 7546861a8c55f1d704a6cfd699b33a9e2dd8c021 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 15 Dec 2020 20:43:34 -0800 Subject: lib/cmdline_kunit: add a new test suite for cmdline API Test get_option() for a starter which is provided by cmdline.c. [akpm@linux-foundation.org: fix warning by constifying cmdline_test_values] [andriy.shevchenko@linux.intel.com: type of expected returned values should be int] Link: https://lkml.kernel.org/r/20201116104244.15472-1-andriy.shevchenko@linux.intel.com [andriy.shevchenko@linux.intel.com: provide meaningful MODULE_LICENSE()] Link: https://lkml.kernel.org/r/20201116104257.15527-1-andriy.shevchenko@linux.intel.com Link: https://lkml.kernel.org/r/20201112180732.75589-6-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Cc: Shuah Khan Cc: Vitor Massaru Iha Cc: Mark Brown Cc: Brendan Higgins Cc: David Gow Cc: Matti Vaittinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 11 ++++++ lib/Makefile | 1 + lib/cmdline_kunit.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 lib/cmdline_kunit.c (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 7c70521d2a22..7d7097c5dc58 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2311,6 +2311,17 @@ config LINEAR_RANGES_TEST If unsure, say N. +config CMDLINE_KUNIT_TEST + tristate "KUnit test for cmdline API" + depends on KUNIT + help + This builds the cmdline API unit test. + Tests the logic of API provided by cmdline.c. + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config BITS_TEST tristate "KUnit test for bits.h" depends on KUNIT diff --git a/lib/Makefile b/lib/Makefile index d415fc7067c5..8598e8796edf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -353,3 +353,4 @@ obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o obj-$(CONFIG_BITS_TEST) += test_bits.o +obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o diff --git a/lib/cmdline_kunit.c b/lib/cmdline_kunit.c new file mode 100644 index 000000000000..550e7a47fd24 --- /dev/null +++ b/lib/cmdline_kunit.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test cases for API provided by cmdline.c + */ + +#include +#include +#include +#include + +static const char *cmdline_test_strings[] = { + "\"\"", "" , "=" , "\"-", "," , "-," , ",-" , "-" , + "+," , "--", ",,", "''" , "\"\",", "\",\"", "-\"\"", "\"", +}; + +static const int cmdline_test_values[] = { + 1, 1, 1, 1, 2, 3, 2, 3, + 1, 3, 2, 1, 1, 1, 3, 1, +}; + +static void cmdline_do_one_test(struct kunit *test, const char *in, int rc, int offset) +{ + const char *fmt = "Pattern: %s"; + const char *out = in; + int dummy; + int ret; + + ret = get_option((char **)&out, &dummy); + + KUNIT_EXPECT_EQ_MSG(test, ret, rc, fmt, in); + KUNIT_EXPECT_PTR_EQ_MSG(test, out, in + offset, fmt, in); +} + +static void cmdline_test_noint(struct kunit *test) +{ + unsigned int i = 0; + + do { + const char *str = cmdline_test_strings[i]; + int rc = 0; + int offset; + + /* Only first and leading '-' will advance the pointer */ + offset = !!(*str == '-'); + cmdline_do_one_test(test, str, rc, offset); + } while (++i < ARRAY_SIZE(cmdline_test_strings)); +} + +static void cmdline_test_lead_int(struct kunit *test) +{ + unsigned int i = 0; + char in[32]; + + do { + const char *str = cmdline_test_strings[i]; + int rc = cmdline_test_values[i]; + int offset; + + sprintf(in, "%u%s", get_random_int() % 256, str); + /* Only first '-' after the number will advance the pointer */ + offset = strlen(in) - strlen(str) + !!(rc == 2); + cmdline_do_one_test(test, in, rc, offset); + } while (++i < ARRAY_SIZE(cmdline_test_strings)); +} + +static void cmdline_test_tail_int(struct kunit *test) +{ + unsigned int i = 0; + char in[32]; + + do { + const char *str = cmdline_test_strings[i]; + /* When "" or "-" the result will be valid integer */ + int rc = strcmp(str, "") ? (strcmp(str, "-") ? 0 : 1) : 1; + int offset; + + sprintf(in, "%s%u", str, get_random_int() % 256); + /* + * Only first and leading '-' not followed by integer + * will advance the pointer. + */ + offset = rc ? strlen(in) : !!(*str == '-'); + cmdline_do_one_test(test, in, rc, offset); + } while (++i < ARRAY_SIZE(cmdline_test_strings)); +} + +static struct kunit_case cmdline_test_cases[] = { + KUNIT_CASE(cmdline_test_noint), + KUNIT_CASE(cmdline_test_lead_int), + KUNIT_CASE(cmdline_test_tail_int), + {} +}; + +static struct kunit_suite cmdline_test_suite = { + .name = "cmdline", + .test_cases = cmdline_test_cases, +}; +kunit_test_suite(cmdline_test_suite); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ff72daa371f58fbf16999f4fb3d65d4f650555aa Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 15 Dec 2020 20:43:40 -0800 Subject: lib/string: remove unnecessary #undefs A few architecture specific string.h functions used to be implemented in terms of preprocessor defines to the corresponding compiler builtins. Since this is no longer the case, remove unused #undefs. Only memcmp is still defined in terms of builtins for a few arches. Link: https://github.com/ClangBuiltLinux/linux/issues/428 Link: https://lkml.kernel.org/r/20201120041113.89382-1-ndesaulniers@google.com Fixes: 5f074f3e192f ("lib/string.c: implement a basic bcmp") Signed-off-by: Nick Desaulniers Cc: Andy Shevchenko Cc: Yury Norov Cc: Alexandru Ardelean Cc: Nathan Chancellor Cc: Masahiro Yamada Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/string.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/string.c b/lib/string.c index 4288e0158d47..7548eb715ddb 100644 --- a/lib/string.c +++ b/lib/string.c @@ -85,7 +85,6 @@ EXPORT_SYMBOL(strcasecmp); * @dest: Where to copy the string to * @src: Where to copy the string from */ -#undef strcpy char *strcpy(char *dest, const char *src) { char *tmp = dest; @@ -302,7 +301,6 @@ EXPORT_SYMBOL(stpcpy); * @dest: The string to be appended to * @src: The string to append to it */ -#undef strcat char *strcat(char *dest, const char *src) { char *tmp = dest; @@ -378,7 +376,6 @@ EXPORT_SYMBOL(strlcat); * @cs: One string * @ct: Another string */ -#undef strcmp int strcmp(const char *cs, const char *ct) { unsigned char c1, c2; @@ -958,7 +955,6 @@ EXPORT_SYMBOL(memcmp); * while this particular implementation is a simple (tail) call to memcmp, do * not rely on anything but whether the return value is zero or non-zero. */ -#undef bcmp int bcmp(const void *a, const void *b, size_t len) { return memcmp(a, b, len); -- cgit v1.2.3 From 506dfc9906e5cbf453bbcd5eb627689435583558 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 15 Dec 2020 20:44:00 -0800 Subject: lib: cleanup kstrto*() usage Use proper conversion functions. kstrto*() variants exist for all standard types. Link: https://lkml.kernel.org/r/20201122123410.GB92364@localhost.localdomain Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_firmware.c | 9 +++------ lib/test_kmod.c | 26 ++++++++++---------------- 2 files changed, 13 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/test_firmware.c b/lib/test_firmware.c index 2baa275a6ddf..b6fe89add9fe 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -364,18 +364,15 @@ static ssize_t test_dev_config_show_int(char *buf, int val) static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) { + u8 val; int ret; - long new; - ret = kstrtol(buf, 10, &new); + ret = kstrtou8(buf, 10, &val); if (ret) return ret; - if (new > U8_MAX) - return -EINVAL; - mutex_lock(&test_fw_mutex); - *(u8 *)cfg = new; + *(u8 *)cfg = val; mutex_unlock(&test_fw_mutex); /* Always return full write size even if we didn't consume all */ diff --git a/lib/test_kmod.c b/lib/test_kmod.c index eab52770070d..38c250fbace3 100644 --- a/lib/test_kmod.c +++ b/lib/test_kmod.c @@ -877,20 +877,17 @@ static int test_dev_config_update_uint_sync(struct kmod_test_device *test_dev, int (*test_sync)(struct kmod_test_device *test_dev)) { int ret; - unsigned long new; + unsigned int val; unsigned int old_val; - ret = kstrtoul(buf, 10, &new); + ret = kstrtouint(buf, 10, &val); if (ret) return ret; - if (new > UINT_MAX) - return -EINVAL; - mutex_lock(&test_dev->config_mutex); old_val = *config; - *(unsigned int *)config = new; + *(unsigned int *)config = val; ret = test_sync(test_dev); if (ret) { @@ -914,18 +911,18 @@ static int test_dev_config_update_uint_range(struct kmod_test_device *test_dev, unsigned int min, unsigned int max) { + unsigned int val; int ret; - unsigned long new; - ret = kstrtoul(buf, 10, &new); + ret = kstrtouint(buf, 10, &val); if (ret) return ret; - if (new < min || new > max) + if (val < min || val > max) return -EINVAL; mutex_lock(&test_dev->config_mutex); - *config = new; + *config = val; mutex_unlock(&test_dev->config_mutex); /* Always return full write size even if we didn't consume all */ @@ -936,18 +933,15 @@ static int test_dev_config_update_int(struct kmod_test_device *test_dev, const char *buf, size_t size, int *config) { + int val; int ret; - long new; - ret = kstrtol(buf, 10, &new); + ret = kstrtoint(buf, 10, &val); if (ret) return ret; - if (new < INT_MIN || new > INT_MAX) - return -EINVAL; - mutex_lock(&test_dev->config_mutex); - *config = new; + *config = val; mutex_unlock(&test_dev->config_mutex); /* Always return full write size even if we didn't consume all */ return size; -- cgit v1.2.3 From 89b158635ad79574bde8e94d45dad33f8cf09549 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 15 Dec 2020 20:44:03 -0800 Subject: lib/lz4: explicitly support in-place decompression LZ4 final literal copy could be overlapped when doing in-place decompression, so it's unsafe to just use memcpy() on an optimized memcpy approach but memmove() instead. Upstream LZ4 has updated this years ago [1] (and the impact is non-sensible [2] plus only a few bytes remain), this commit just synchronizes LZ4 upstream code to the kernel side as well. It can be observed as EROFS in-place decompression failure on specific files when X86_FEATURE_ERMS is unsupported, memcpy() optimization of commit 59daa706fbec ("x86, mem: Optimize memcpy by avoiding memory false dependece") will be enabled then. Currently most modern x86-CPUs support ERMS, these CPUs just use "rep movsb" approach so no problem at all. However, it can still be verified with forcely disabling ERMS feature... arch/x86/lib/memcpy_64.S: ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \ - "jmp memcpy_erms", X86_FEATURE_ERMS + "jmp memcpy_orig", X86_FEATURE_ERMS We didn't observe any strange on arm64/arm/x86 platform before since most memcpy() would behave in an increasing address order ("copy upwards" [3]) and it's the correct order of in-place decompression but it really needs an update to memmove() for sure considering it's an undefined behavior according to the standard and some unique optimization already exists in the kernel. [1] https://github.com/lz4/lz4/commit/33cb8518ac385835cc17be9a770b27b40cd0e15b [2] https://github.com/lz4/lz4/pull/717#issuecomment-497818921 [3] https://sourceware.org/bugzilla/show_bug.cgi?id=12518 Link: https://lkml.kernel.org/r/20201122030749.2698994-1-hsiangkao@redhat.com Signed-off-by: Gao Xiang Reviewed-by: Nick Terrell Cc: Yann Collet Cc: Miao Xie Cc: Chao Yu Cc: Li Guifu Cc: Guo Xuenan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/lz4/lz4_decompress.c | 6 +++++- lib/lz4/lz4defs.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c index 00cb0d0b73e1..8a7724a6ce2f 100644 --- a/lib/lz4/lz4_decompress.c +++ b/lib/lz4/lz4_decompress.c @@ -263,7 +263,11 @@ static FORCE_INLINE int LZ4_decompress_generic( } } - LZ4_memcpy(op, ip, length); + /* + * supports overlapping memory regions; only matters + * for in-place decompression scenarios + */ + LZ4_memmove(op, ip, length); ip += length; op += length; diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index c91dd96ef629..673bd206aa98 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -146,6 +146,7 @@ static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value) * environments. This is needed when decompressing the Linux Kernel, for example. */ #define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) +#define LZ4_memmove(dst, src, size) __builtin_memmove(dst, src, size) static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) { -- cgit v1.2.3 From d8a7f62b6eec198e85b8602e062c00e199f5c328 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:20 -0800 Subject: ubsan: remove redundant -Wno-maybe-uninitialized Patch series "Clean up UBSAN Makefile", v2. This series attempts to address the issues seen with UBSAN's object-size sanitizer causing problems under GCC. In the process, the Kconfig and Makefile are refactored to do all the cc-option calls in the Kconfig. Additionally start to detangle -Wno-maybe-uninitialized, disable UBSAN_TRAP under COMPILE_TEST for wider build coverage, and expand the libusan tests. This patch (of 7): In commit 78a5255ffb6a ("Stop the ad-hoc games with -Wno-maybe-initialized") -Wmaybe-uninitialized was disabled globally, so keeping the disabling logic here too doesn't make sense. Link: https://lkml.kernel.org/r/20201203004437.389959-1-keescook@chromium.org Link: https://lkml.kernel.org/r/20201203004437.389959-2-keescook@chromium.org Signed-off-by: Kees Cook Cc: Linus Torvalds Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Masahiro Yamada Cc: Michal Marek Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Marco Elver Cc: Randy Dunlap Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Peter Oberparleiter Cc: Andrey Ryabinin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 58f8d03d037b..d8d4d6557b80 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -72,10 +72,6 @@ config UBSAN_MISC config UBSAN_SANITIZE_ALL bool "Enable instrumentation for the entire kernel" depends on ARCH_HAS_UBSAN_SANITIZE_ALL - - # We build with -Wno-maybe-uninitilzed, but we still want to - # use -Wmaybe-uninitilized in allmodconfig builds. - # So dependsy bellow used to disable this option in allmodconfig depends on !COMPILE_TEST default y help -- cgit v1.2.3 From cdf8a76fda4ae3b53c5a09e5a8c79e27b7b65d68 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:24 -0800 Subject: ubsan: move cc-option tests into Kconfig Instead of doing if/endif blocks with cc-option calls in the UBSAN Makefile, move all the tests into Kconfig and use the Makefile to collect the results. Link: https://lkml.kernel.org/r/20201203004437.389959-3-keescook@chromium.org Link: https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/ Signed-off-by: Kees Cook Suggested-by: Linus Torvalds Reviewed-by: Nathan Chancellor Tested-by: Nathan Chancellor Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index d8d4d6557b80..05147112b355 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -36,10 +36,17 @@ config UBSAN_KCOV_BROKEN See https://bugs.llvm.org/show_bug.cgi?id=45831 for the status in newer releases. +config CC_HAS_UBSAN_BOUNDS + def_bool $(cc-option,-fsanitize=bounds) + +config CC_HAS_UBSAN_ARRAY_BOUNDS + def_bool $(cc-option,-fsanitize=array-bounds) + config UBSAN_BOUNDS bool "Perform array index bounds checking" default UBSAN depends on !UBSAN_KCOV_BROKEN + depends on CC_HAS_UBSAN_ARRAY_BOUNDS || CC_HAS_UBSAN_BOUNDS help This option enables detection of directly indexed out of bounds array accesses, where the array size is known at compile time. @@ -47,15 +54,30 @@ config UBSAN_BOUNDS to the {str,mem}*cpy() family of functions (that is addressed by CONFIG_FORTIFY_SOURCE). +config UBSAN_ONLY_BOUNDS + def_bool CC_HAS_UBSAN_BOUNDS && !CC_HAS_UBSAN_ARRAY_BOUNDS + depends on UBSAN_BOUNDS + help + This is a weird case: Clang's -fsanitize=bounds includes + -fsanitize=local-bounds, but it's trapping-only, so for + Clang, we must use -fsanitize=array-bounds when we want + traditional array bounds checking enabled. For GCC, we + want -fsanitize=bounds. + +config UBSAN_ARRAY_BOUNDS + def_bool CC_HAS_UBSAN_ARRAY_BOUNDS + depends on UBSAN_BOUNDS + config UBSAN_LOCAL_BOUNDS bool "Perform array local bounds checking" depends on UBSAN_TRAP - depends on CC_IS_CLANG depends on !UBSAN_KCOV_BROKEN + depends on $(cc-option,-fsanitize=local-bounds) help This option enables -fsanitize=local-bounds which traps when an - exception/error is detected. Therefore, it should be enabled only - if trapping is expected. + exception/error is detected. Therefore, it may only be enabled + with CONFIG_UBSAN_TRAP. + Enabling this option detects errors due to accesses through a pointer that is derived from an object of a statically-known size, where an added offset (which may not be known statically) is @@ -69,6 +91,38 @@ config UBSAN_MISC own Kconfig options. Disable this if you only want to have individually selected checks. +config UBSAN_SHIFT + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=shift) + +config UBSAN_DIV_ZERO + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=integer-divide-by-zero) + +config UBSAN_UNREACHABLE + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=unreachable) + +config UBSAN_SIGNED_OVERFLOW + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=signed-integer-overflow) + +config UBSAN_UNSIGNED_OVERFLOW + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=unsigned-integer-overflow) + +config UBSAN_OBJECT_SIZE + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=object-size) + +config UBSAN_BOOL + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=bool) + +config UBSAN_ENUM + def_bool UBSAN_MISC + depends on $(cc-option,-fsanitize=enum) + config UBSAN_SANITIZE_ALL bool "Enable instrumentation for the entire kernel" depends on ARCH_HAS_UBSAN_SANITIZE_ALL @@ -85,6 +139,7 @@ config UBSAN_ALIGNMENT bool "Enable checks for pointers alignment" default !HAVE_EFFICIENT_UNALIGNED_ACCESS depends on !UBSAN_TRAP + depends on $(cc-option,-fsanitize=alignment) help This option enables the check of unaligned memory accesses. Enabling this option on architectures that support unaligned -- cgit v1.2.3 From 61e0349f703d1576a12f88c15f25e0a56fd277af Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:28 -0800 Subject: ubsan: disable object-size sanitizer under GCC GCC's -fsanitize=object-size (as part of CONFIG_UBSAN_MISC) greatly increases stack utilization. Do not allow this under GCC. Link: https://lkml.kernel.org/r/20201203004437.389959-4-keescook@chromium.org Link: https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/ Signed-off-by: Kees Cook Reviewed-by: Nathan Chancellor Suggested-by: Linus Torvalds Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 05147112b355..4190a99b1eaa 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -113,6 +113,9 @@ config UBSAN_UNSIGNED_OVERFLOW config UBSAN_OBJECT_SIZE def_bool UBSAN_MISC + # gcc hugely expands stack usage with -fsanitize=object-size + # https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/ + depends on !CC_IS_GCC depends on $(cc-option,-fsanitize=object-size) config UBSAN_BOOL -- cgit v1.2.3 From 79791378a1bc9e218462211742e48e375371e8c5 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:31 -0800 Subject: ubsan: disable UBSAN_TRAP for all*config Doing all*config builds attempts to build as much as possible. UBSAN_TRAP effectively short-circuits lib/usban.c, so it should be disabled for COMPILE_TEST so that the lib/ubsan.c code gets built. Link: https://lkml.kernel.org/r/20201203004437.389959-5-keescook@chromium.org Signed-off-by: Kees Cook Reviewed-by: Nathan Chancellor Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Linus Torvalds Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 4190a99b1eaa..6e8b67d4b0d9 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -14,6 +14,7 @@ if UBSAN config UBSAN_TRAP bool "On Sanitizer warnings, abort the running kernel code" + depends on !COMPILE_TEST depends on $(cc-option, -fsanitize-undefined-trap-on-error) help Building kernels with Sanitizer features enabled tends to grow -- cgit v1.2.3 From d0a3ac549f389c1511a4df0d7638536305205d20 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:35 -0800 Subject: ubsan: enable for all*config builds With UBSAN_OBJECT_SIZE disabled for GCC, only UBSAN_ALIGNMENT remained a noisy UBSAN option. Disable it for COMPILE_TEST so the rest of UBSAN can be used for full all*config builds or other large combinations. [sfr@canb.auug.org.au: add .data..Lubsan_data*/.data..Lubsan_type* sections explicitly] Link: https://lkml.kernel.org/r/20201208230157.42c42789@canb.auug.org.au Link: https://lore.kernel.org/lkml/CAHk-=wgXW=YLxGN0QVpp-1w5GDd2pf1W-FqY15poKzoVfik2qA@mail.gmail.com/ Link: https://lkml.kernel.org/r/20201203004437.389959-6-keescook@chromium.org Signed-off-by: Kees Cook Signed-off-by: Stephen Rothwell Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Linus Torvalds Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 6e8b67d4b0d9..fa78f0f3c1dc 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -130,7 +130,6 @@ config UBSAN_ENUM config UBSAN_SANITIZE_ALL bool "Enable instrumentation for the entire kernel" depends on ARCH_HAS_UBSAN_SANITIZE_ALL - depends on !COMPILE_TEST default y help This option activates instrumentation for the entire kernel. @@ -142,7 +141,7 @@ config UBSAN_SANITIZE_ALL config UBSAN_ALIGNMENT bool "Enable checks for pointers alignment" default !HAVE_EFFICIENT_UNALIGNED_ACCESS - depends on !UBSAN_TRAP + depends on !UBSAN_TRAP && !COMPILE_TEST depends on $(cc-option,-fsanitize=alignment) help This option enables the check of unaligned memory accesses. -- cgit v1.2.3 From c637693b20da8706b7f48d96882c9c80ae935151 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:39 -0800 Subject: ubsan: remove UBSAN_MISC in favor of individual options Make each UBSAN option individually selectable and remove UBSAN_MISC which no longer has any purpose. Add help text for each Kconfig, and include a reference to the Clang sanitizer documentation. Disable unsigned overflow by default (not available with GCC and makes x86 unbootable with Clang). Disable unreachable when objtool is in use (redundant and confuses things: instrumentation appears at unreachable locations). Link: https://lkml.kernel.org/r/20201203004437.389959-7-keescook@chromium.org Signed-off-by: Kees Cook Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Linus Torvalds Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 82 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index fa78f0f3c1dc..8b635fd75fe4 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -84,48 +84,88 @@ config UBSAN_LOCAL_BOUNDS where an added offset (which may not be known statically) is out-of-bounds. -config UBSAN_MISC - bool "Enable all other Undefined Behavior sanity checks" - default UBSAN - help - This option enables all sanity checks that don't have their - own Kconfig options. Disable this if you only want to have - individually selected checks. - config UBSAN_SHIFT - def_bool UBSAN_MISC + bool "Perform checking for bit-shift overflows" + default UBSAN depends on $(cc-option,-fsanitize=shift) + help + This option enables -fsanitize=shift which checks for bit-shift + operations that overflow to the left or go switch to negative + for signed types. config UBSAN_DIV_ZERO - def_bool UBSAN_MISC + bool "Perform checking for integer divide-by-zero" depends on $(cc-option,-fsanitize=integer-divide-by-zero) + help + This option enables -fsanitize=integer-divide-by-zero which checks + for integer division by zero. This is effectively redundant with the + kernel's existing exception handling, though it can provide greater + debugging information under CONFIG_UBSAN_REPORT_FULL. config UBSAN_UNREACHABLE - def_bool UBSAN_MISC + bool "Perform checking for unreachable code" + # objtool already handles unreachable checking and gets angry about + # seeing UBSan instrumentation located in unreachable places. + depends on !STACK_VALIDATION depends on $(cc-option,-fsanitize=unreachable) + help + This option enables -fsanitize=unreachable which checks for control + flow reaching an expected-to-be-unreachable position. config UBSAN_SIGNED_OVERFLOW - def_bool UBSAN_MISC + bool "Perform checking for signed arithmetic overflow" + default UBSAN depends on $(cc-option,-fsanitize=signed-integer-overflow) + help + This option enables -fsanitize=signed-integer-overflow which checks + for overflow of any arithmetic operations with signed integers. config UBSAN_UNSIGNED_OVERFLOW - def_bool UBSAN_MISC + bool "Perform checking for unsigned arithmetic overflow" depends on $(cc-option,-fsanitize=unsigned-integer-overflow) + help + This option enables -fsanitize=unsigned-integer-overflow which checks + for overflow of any arithmetic operations with unsigned integers. This + currently causes x86 to fail to boot. config UBSAN_OBJECT_SIZE - def_bool UBSAN_MISC + bool "Perform checking for accesses beyond the end of objects" + default UBSAN # gcc hugely expands stack usage with -fsanitize=object-size # https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/ depends on !CC_IS_GCC depends on $(cc-option,-fsanitize=object-size) + help + This option enables -fsanitize=object-size which checks for accesses + beyond the end of objects where the optimizer can determine both the + object being operated on and its size, usually seen with bad downcasts, + or access to struct members from NULL pointers. config UBSAN_BOOL - def_bool UBSAN_MISC + bool "Perform checking for non-boolean values used as boolean" + default UBSAN depends on $(cc-option,-fsanitize=bool) + help + This option enables -fsanitize=bool which checks for boolean values being + loaded that are neither 0 nor 1. config UBSAN_ENUM - def_bool UBSAN_MISC + bool "Perform checking for out of bounds enum values" + default UBSAN depends on $(cc-option,-fsanitize=enum) + help + This option enables -fsanitize=enum which checks for values being loaded + into an enum that are outside the range of given values for the given enum. + +config UBSAN_ALIGNMENT + bool "Perform checking for misaligned pointer usage" + default !HAVE_EFFICIENT_UNALIGNED_ACCESS + depends on !UBSAN_TRAP && !COMPILE_TEST + depends on $(cc-option,-fsanitize=alignment) + help + This option enables the check of unaligned memory accesses. + Enabling this option on architectures that support unaligned + accesses may produce a lot of false positives. config UBSAN_SANITIZE_ALL bool "Enable instrumentation for the entire kernel" @@ -138,16 +178,6 @@ config UBSAN_SANITIZE_ALL Enabling this option will get kernel image size increased significantly. -config UBSAN_ALIGNMENT - bool "Enable checks for pointers alignment" - default !HAVE_EFFICIENT_UNALIGNED_ACCESS - depends on !UBSAN_TRAP && !COMPILE_TEST - depends on $(cc-option,-fsanitize=alignment) - help - This option enables the check of unaligned memory accesses. - Enabling this option on architectures that support unaligned - accesses may produce a lot of false positives. - config TEST_UBSAN tristate "Module for testing for undefined behavior detection" depends on m -- cgit v1.2.3 From 4a26f49b7b3dbe998d9b2561f9f256a1c3fdb74a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Dec 2020 20:46:43 -0800 Subject: ubsan: expand tests and reporting Expand the UBSAN tests to include some additional UB cases. Notably the out-of-bounds enum loading appears not to work. Also include per-test reporting, including the relevant CONFIG_UBSAN... Kconfigs. Link: https://lkml.kernel.org/r/20201203004437.389959-8-keescook@chromium.org Signed-off-by: Kees Cook Cc: Andrey Ryabinin Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Dmitry Vyukov Cc: George Popescu Cc: Herbert Xu Cc: Linus Torvalds Cc: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Peter Oberparleiter Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_ubsan.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c index 9ea10adf7a66..5e5d9355ef49 100644 --- a/lib/test_ubsan.c +++ b/lib/test_ubsan.c @@ -5,32 +5,54 @@ typedef void(*test_ubsan_fp)(void); +#define UBSAN_TEST(config, ...) do { \ + pr_info("%s " __VA_ARGS__ "%s(%s=%s)\n", __func__, \ + sizeof(" " __VA_ARGS__) > 2 ? " " : "", \ + #config, IS_ENABLED(config) ? "y" : "n"); \ + } while (0) + static void test_ubsan_add_overflow(void) { volatile int val = INT_MAX; + volatile unsigned int uval = UINT_MAX; + UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW); val += 2; + + UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW); + uval += 2; } static void test_ubsan_sub_overflow(void) { volatile int val = INT_MIN; + volatile unsigned int uval = 0; volatile int val2 = 2; + UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW); val -= val2; + + UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW); + uval -= val2; } static void test_ubsan_mul_overflow(void) { volatile int val = INT_MAX / 2; + volatile unsigned int uval = UINT_MAX / 2; + UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW); val *= 3; + + UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW); + uval *= 3; } static void test_ubsan_negate_overflow(void) { volatile int val = INT_MIN; + UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW); val = -val; } @@ -39,37 +61,67 @@ static void test_ubsan_divrem_overflow(void) volatile int val = 16; volatile int val2 = 0; + UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO); val /= val2; } static void test_ubsan_shift_out_of_bounds(void) { - volatile int val = -1; - int val2 = 10; + volatile int neg = -1, wrap = 4; + int val1 = 10; + int val2 = INT_MAX; + + UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent"); + val1 <<= neg; - val2 <<= val; + UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow"); + val2 <<= wrap; } static void test_ubsan_out_of_bounds(void) { - volatile int i = 4, j = 5; + volatile int i = 4, j = 5, k = -1; + volatile char above[4] = { }; /* Protect surrounding memory. */ volatile int arr[4]; + volatile char below[4] = { }; /* Protect surrounding memory. */ + above[0] = below[0]; + + UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above"); arr[j] = i; + + UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below"); + arr[k] = i; } +enum ubsan_test_enum { + UBSAN_TEST_ZERO = 0, + UBSAN_TEST_ONE, + UBSAN_TEST_MAX, +}; + static void test_ubsan_load_invalid_value(void) { volatile char *dst, *src; bool val, val2, *ptr; - char c = 4; + enum ubsan_test_enum eval, eval2, *eptr; + unsigned char c = 0xff; + UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool"); dst = (char *)&val; src = &c; *dst = *src; ptr = &val2; val2 = val; + + UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum"); + dst = (char *)&eval; + src = &c; + *dst = *src; + + eptr = &eval2; + eval2 = eval; } static void test_ubsan_null_ptr_deref(void) @@ -77,6 +129,7 @@ static void test_ubsan_null_ptr_deref(void) volatile int *ptr = NULL; int val; + UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE); val = *ptr; } @@ -85,6 +138,7 @@ static void test_ubsan_misaligned_access(void) volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5}; volatile int *ptr, val = 6; + UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT); ptr = (int *)(arr + 1); *ptr = val; } @@ -95,6 +149,7 @@ static void test_ubsan_object_size_mismatch(void) volatile int val __aligned(8) = 4; volatile long long *ptr, val2; + UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE); ptr = (long long *)&val; val2 = *ptr; } @@ -104,15 +159,19 @@ static const test_ubsan_fp test_ubsan_array[] = { test_ubsan_sub_overflow, test_ubsan_mul_overflow, test_ubsan_negate_overflow, - test_ubsan_divrem_overflow, test_ubsan_shift_out_of_bounds, test_ubsan_out_of_bounds, test_ubsan_load_invalid_value, - //test_ubsan_null_ptr_deref, /* exclude it because there is a crash */ test_ubsan_misaligned_access, test_ubsan_object_size_mismatch, }; +/* Excluded because they Oops the module. */ +static const test_ubsan_fp skip_ubsan_array[] = { + test_ubsan_divrem_overflow, + test_ubsan_null_ptr_deref, +}; + static int __init test_ubsan_init(void) { unsigned int i; @@ -120,7 +179,6 @@ static int __init test_ubsan_init(void) for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++) test_ubsan_array[i](); - (void)test_ubsan_null_ptr_deref; /* to avoid unsed-function warning */ return 0; } module_init(test_ubsan_init); -- cgit v1.2.3 From d3c227978a130ee18716d3496cf82621d8cda28c Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Tue, 15 Dec 2020 20:46:50 -0800 Subject: lib/ubsan.c: mark type_check_kinds with static keyword Fix the following sparse warning: lib/ubsan.c:20:12: warning: symbol 'type_check_kinds' was not declared. Should it be static? [akpm@linux-foundation.org: make it `static const char * const' while we're in there] Link: https://lkml.kernel.org/r/1607602638-79584-1-git-send-email-zou_wei@huawei.com Signed-off-by: Zou Wei Reviewed-by: Andrew Morton Reviewed-by: Kees Cook Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/ubsan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ubsan.c b/lib/ubsan.c index cb9af3f6b77e..3e3352f3d0da 100644 --- a/lib/ubsan.c +++ b/lib/ubsan.c @@ -17,7 +17,7 @@ #include "ubsan.h" -const char *type_check_kinds[] = { +static const char * const type_check_kinds[] = { "load of", "store to", "reference binding to", -- cgit v1.2.3 From 537cd89484ab57ca38ae25d9557361c0815977d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Tue, 15 Dec 2020 20:47:10 -0800 Subject: fault-injection: handle EI_ETYPE_TRUE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit af3b854492f351d1 ("mm/page_alloc.c: allow error injection") introduced EI_ETYPE_TRUE, but did not extend * lib/error-inject.c:error_type_string(), and * kernel/fail_function.c:adjust_error_retval() to accommodate for this change. Handle EI_ETYPE_TRUE in both functions appropriately by * returning "TRUE" in error_type_string(), * adjusting the return value to true (1) in adjust_error_retval(). Furthermore, simplify the logic of handling EI_ETYPE_NULL in adjust_error_retval(). Link: https://lkml.kernel.org/r/njB1czX0ZgWPR9h61euHIBb5bEyePw9D4D2m3i5lc9Cl96P8Q1308dTcmsEZW7Vtz3Ifz4do-rOtSfuFTyGoEDYokkK2aUqBePVptzZEWfU=@protonmail.com Signed-off-by: Barnabás Pőcze Acked-by: Masami Hiramatsu Reviewed-by: Akinobu Mita Cc: "Naveen N. Rao" Cc: Anil S Keshavamurthy Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/error-inject.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/error-inject.c b/lib/error-inject.c index aa63751c916f..c73651b15b76 100644 --- a/lib/error-inject.c +++ b/lib/error-inject.c @@ -180,6 +180,8 @@ static const char *error_type_string(int etype) return "ERRNO"; case EI_ETYPE_ERRNO_NULL: return "ERRNO_NULL"; + case EI_ETYPE_TRUE: + return "TRUE"; default: return "(unknown)"; } -- cgit v1.2.3 From 33fb626be08f3877b92e3c1782eac1a9a1575ea5 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Tue, 15 Dec 2020 20:47:13 -0800 Subject: lib/lzo/lzo1x_compress.c: make lzogeneric1x_1_compress() static Fix the following sparse warning: lib/lzo/lzo1x_compress.c:304:5: warning: symbol 'lzogeneric1x_1_compress' was not declared. Should it be static? Link: https://lkml.kernel.org/r/20201020031415.136874-1-yanaijie@huawei.com Signed-off-by: Jason Yan Cc: Dave Rodgman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/lzo/lzo1x_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c index 8ad5ba2b86e2..76758e9296ba 100644 --- a/lib/lzo/lzo1x_compress.c +++ b/lib/lzo/lzo1x_compress.c @@ -301,7 +301,7 @@ finished_writing_instruction: return in_end - (ii - ti); } -int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, +static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out, size_t *out_len, void *wrkmem, const unsigned char bitstream_version) { -- cgit v1.2.3 From 71f6af6d52ceb96be522819a1b0806325bc690d8 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 22 Dec 2020 12:00:10 -0800 Subject: kasan: KASAN_VMALLOC depends on KASAN_GENERIC Currently only generic KASAN mode supports vmalloc, reflect that in the config. Link: https://lkml.kernel.org/r/0c493d3a065ad95b04313d00244e884a7e2498ff.1606161801.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Signed-off-by: Vincenzo Frascino Reviewed-by: Marco Elver Reviewed-by: Alexander Potapenko Tested-by: Vincenzo Frascino Cc: Andrey Ryabinin Cc: Branislav Rankov Cc: Catalin Marinas Cc: Dmitry Vyukov Cc: Evgenii Stepanov Cc: Kevin Brodsky Cc: Vasily Gorbik Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.kasan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index 8fb097057fec..58dd3b86ef84 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -146,7 +146,7 @@ config KASAN_SW_TAGS_IDENTIFY config KASAN_VMALLOC bool "Back mappings in vmalloc space with real shadow memory" - depends on HAVE_ARCH_KASAN_VMALLOC + depends on KASAN_GENERIC && HAVE_ARCH_KASAN_VMALLOC help By default, the shadow region for vmalloc space is the read-only zero page. This means that KASAN cannot detect errors involving -- cgit v1.2.3 From 1f600626b3a9b77001b3ef90a79bf68c9f7e4cda Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 22 Dec 2020 12:00:24 -0800 Subject: kasan: rename KASAN_SHADOW_* to KASAN_GRANULE_* This is a preparatory commit for the upcoming addition of a new hardware tag-based (MTE-based) KASAN mode. The new mode won't be using shadow memory, but will still use the concept of memory granules. Each memory granule maps to a single metadata entry: 8 bytes per one shadow byte for generic mode, 16 bytes per one shadow byte for software tag-based mode, and 16 bytes per one allocation tag for hardware tag-based mode. Rename KASAN_SHADOW_SCALE_SIZE to KASAN_GRANULE_SIZE, and KASAN_SHADOW_MASK to KASAN_GRANULE_MASK. Also use MASK when used as a mask, otherwise use SIZE. No functional changes. Link: https://lkml.kernel.org/r/939b5754e47f528a6e6a6f28ffc5815d8d128033.1606161801.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Signed-off-by: Vincenzo Frascino Reviewed-by: Marco Elver Reviewed-by: Alexander Potapenko Tested-by: Vincenzo Frascino Cc: Andrey Ryabinin Cc: Branislav Rankov Cc: Catalin Marinas Cc: Dmitry Vyukov Cc: Evgenii Stepanov Cc: Kevin Brodsky Cc: Vasily Gorbik Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_kasan.c | 2 +- lib/test_kasan_module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/test_kasan.c b/lib/test_kasan.c index 662f862702fc..2947274cc2d3 100644 --- a/lib/test_kasan.c +++ b/lib/test_kasan.c @@ -25,7 +25,7 @@ #include "../mm/kasan/kasan.h" -#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_SHADOW_SCALE_SIZE) +#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE) /* * We assign some test results to these globals to make sure the tests diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c index 62a87854b120..3b4cc77992d2 100644 --- a/lib/test_kasan_module.c +++ b/lib/test_kasan_module.c @@ -15,7 +15,7 @@ #include "../mm/kasan/kasan.h" -#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_SHADOW_SCALE_SIZE) +#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE) static noinline void __init copy_user_test(void) { -- cgit v1.2.3 From ffcc5cea46c0c3dde4eeb101fdf3a37da43863de Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 22 Dec 2020 12:00:42 -0800 Subject: kasan: don't duplicate config dependencies Both KASAN_GENERIC and KASAN_SW_TAGS have common dependencies, move those to KASAN. Link: https://lkml.kernel.org/r/c1cc0d562608a318c607afe22db5ec2a7af72e47.1606161801.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Signed-off-by: Vincenzo Frascino Reviewed-by: Marco Elver Reviewed-by: Alexander Potapenko Tested-by: Vincenzo Frascino Cc: Andrey Ryabinin Cc: Branislav Rankov Cc: Catalin Marinas Cc: Dmitry Vyukov Cc: Evgenii Stepanov Cc: Kevin Brodsky Cc: Vasily Gorbik Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.kasan | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index 58dd3b86ef84..c0e9e7874122 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -24,6 +24,8 @@ menuconfig KASAN (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS) depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB) depends on CC_HAS_WORKING_NOSANITIZE_ADDRESS + select CONSTRUCTORS + select STACKDEPOT help Enables KASAN (KernelAddressSANitizer) - runtime memory debugger, designed to find out-of-bounds accesses and use-after-free bugs. @@ -46,10 +48,7 @@ choice config KASAN_GENERIC bool "Generic mode" depends on HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC - depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB) select SLUB_DEBUG if SLUB - select CONSTRUCTORS - select STACKDEPOT help Enables generic KASAN mode. @@ -70,10 +69,7 @@ config KASAN_GENERIC config KASAN_SW_TAGS bool "Software tag-based mode" depends on HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS - depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB) select SLUB_DEBUG if SLUB - select CONSTRUCTORS - select STACKDEPOT help Enables software tag-based KASAN mode. -- cgit v1.2.3 From 6a63a63ff1ac2959706dba218d5e17f9ec721c0c Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Tue, 22 Dec 2020 12:01:20 -0800 Subject: kasan: introduce CONFIG_KASAN_HW_TAGS This patch adds a configuration option for a new KASAN mode called hardware tag-based KASAN. This mode uses the memory tagging approach like the software tag-based mode, but relies on arm64 Memory Tagging Extension feature for tag management and access checking. Link: https://lkml.kernel.org/r/44906a209d3a44f9c6f5a21841e90988e365601e.1606161801.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Co-developed-by: Vincenzo Frascino Signed-off-by: Vincenzo Frascino Reviewed-by: Marco Elver Reviewed-by: Alexander Potapenko Tested-by: Vincenzo Frascino Cc: Andrey Ryabinin Cc: Branislav Rankov Cc: Catalin Marinas Cc: Dmitry Vyukov Cc: Evgenii Stepanov Cc: Kevin Brodsky Cc: Vasily Gorbik Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.kasan | 61 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index c0e9e7874122..f5fa4ba126bf 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -6,7 +6,10 @@ config HAVE_ARCH_KASAN config HAVE_ARCH_KASAN_SW_TAGS bool -config HAVE_ARCH_KASAN_VMALLOC +config HAVE_ARCH_KASAN_HW_TAGS + bool + +config HAVE_ARCH_KASAN_VMALLOC bool config CC_HAS_KASAN_GENERIC @@ -15,16 +18,19 @@ config CC_HAS_KASAN_GENERIC config CC_HAS_KASAN_SW_TAGS def_bool $(cc-option, -fsanitize=kernel-hwaddress) +# This option is only required for software KASAN modes. +# Old GCC versions don't have proper support for no_sanitize_address. +# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89124 for details. config CC_HAS_WORKING_NOSANITIZE_ADDRESS def_bool !CC_IS_GCC || GCC_VERSION >= 80300 menuconfig KASAN bool "KASAN: runtime memory debugger" - depends on (HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \ - (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS) + depends on (((HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC) || \ + (HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS)) && \ + CC_HAS_WORKING_NOSANITIZE_ADDRESS) || \ + HAVE_ARCH_KASAN_HW_TAGS depends on (SLUB && SYSFS) || (SLAB && !DEBUG_SLAB) - depends on CC_HAS_WORKING_NOSANITIZE_ADDRESS - select CONSTRUCTORS select STACKDEPOT help Enables KASAN (KernelAddressSANitizer) - runtime memory debugger, @@ -37,18 +43,24 @@ choice prompt "KASAN mode" default KASAN_GENERIC help - KASAN has two modes: generic KASAN (similar to userspace ASan, - x86_64/arm64/xtensa, enabled with CONFIG_KASAN_GENERIC) and - software tag-based KASAN (a version based on software memory - tagging, arm64 only, similar to userspace HWASan, enabled with - CONFIG_KASAN_SW_TAGS). + KASAN has three modes: + 1. generic KASAN (similar to userspace ASan, + x86_64/arm64/xtensa, enabled with CONFIG_KASAN_GENERIC), + 2. software tag-based KASAN (arm64 only, based on software + memory tagging (similar to userspace HWASan), enabled with + CONFIG_KASAN_SW_TAGS), and + 3. hardware tag-based KASAN (arm64 only, based on hardware + memory tagging, enabled with CONFIG_KASAN_HW_TAGS). + + All KASAN modes are strictly debugging features. - Both generic and tag-based KASAN are strictly debugging features. + For better error reports enable CONFIG_STACKTRACE. config KASAN_GENERIC bool "Generic mode" depends on HAVE_ARCH_KASAN && CC_HAS_KASAN_GENERIC select SLUB_DEBUG if SLUB + select CONSTRUCTORS help Enables generic KASAN mode. @@ -61,8 +73,6 @@ config KASAN_GENERIC and introduces an overhead of ~x1.5 for the rest of the allocations. The performance slowdown is ~x3. - For better error detection enable CONFIG_STACKTRACE. - Currently CONFIG_KASAN_GENERIC doesn't work with CONFIG_DEBUG_SLAB (the resulting kernel does not boot). @@ -70,11 +80,15 @@ config KASAN_SW_TAGS bool "Software tag-based mode" depends on HAVE_ARCH_KASAN_SW_TAGS && CC_HAS_KASAN_SW_TAGS select SLUB_DEBUG if SLUB + select CONSTRUCTORS help Enables software tag-based KASAN mode. - This mode requires Top Byte Ignore support by the CPU and therefore - is only supported for arm64. This mode requires Clang. + This mode require software memory tagging support in the form of + HWASan-like compiler instrumentation. + + Currently this mode is only implemented for arm64 CPUs and relies on + Top Byte Ignore. This mode requires Clang. This mode consumes about 1/16th of available memory at kernel start and introduces an overhead of ~20% for the rest of the allocations. @@ -82,15 +96,27 @@ config KASAN_SW_TAGS casting and comparison, as it embeds tags into the top byte of each pointer. - For better error detection enable CONFIG_STACKTRACE. - Currently CONFIG_KASAN_SW_TAGS doesn't work with CONFIG_DEBUG_SLAB (the resulting kernel does not boot). +config KASAN_HW_TAGS + bool "Hardware tag-based mode" + depends on HAVE_ARCH_KASAN_HW_TAGS + depends on SLUB + help + Enables hardware tag-based KASAN mode. + + This mode requires hardware memory tagging support, and can be used + by any architecture that provides it. + + Currently this mode is only implemented for arm64 CPUs starting from + ARMv8.5 and relies on Memory Tagging Extension and Top Byte Ignore. + endchoice choice prompt "Instrumentation type" + depends on KASAN_GENERIC || KASAN_SW_TAGS default KASAN_OUTLINE config KASAN_OUTLINE @@ -114,6 +140,7 @@ endchoice config KASAN_STACK_ENABLE bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && !COMPILE_TEST + depends on KASAN_GENERIC || KASAN_SW_TAGS help The LLVM stack address sanitizer has a know problem that causes excessive stack usage in a lot of functions, see -- cgit v1.2.3