--- /dev/null
+From a821df3f1af72aa6a0d573eea94a7dd2613e9f4e Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Tue, 21 Nov 2017 09:36:33 +1100
+Subject: cifs: fix NULL deref in SMB2_read
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit a821df3f1af72aa6a0d573eea94a7dd2613e9f4e upstream.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -2678,27 +2678,27 @@ SMB2_read(const unsigned int xid, struct
+ cifs_small_buf_release(req);
+
+ rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
+- shdr = get_sync_hdr(rsp);
+
+- if (shdr->Status == STATUS_END_OF_FILE) {
++ if (rc) {
++ if (rc != -ENODATA) {
++ cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
++ cifs_dbg(VFS, "Send error in read = %d\n", rc);
++ }
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+- return 0;
++ return rc == -ENODATA ? 0 : rc;
+ }
+
+- if (rc) {
+- cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
+- cifs_dbg(VFS, "Send error in read = %d\n", rc);
+- } else {
+- *nbytes = le32_to_cpu(rsp->DataLength);
+- if ((*nbytes > CIFS_MAX_MSGSIZE) ||
+- (*nbytes > io_parms->length)) {
+- cifs_dbg(FYI, "bad length %d for count %d\n",
+- *nbytes, io_parms->length);
+- rc = -EIO;
+- *nbytes = 0;
+- }
++ *nbytes = le32_to_cpu(rsp->DataLength);
++ if ((*nbytes > CIFS_MAX_MSGSIZE) ||
++ (*nbytes > io_parms->length)) {
++ cifs_dbg(FYI, "bad length %d for count %d\n",
++ *nbytes, io_parms->length);
++ rc = -EIO;
++ *nbytes = 0;
+ }
+
++ shdr = get_sync_hdr(rsp);
++
+ if (*buf) {
+ memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
--- /dev/null
+From 887207ed9e5812ed9239b6d07185a2d35dda91db Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 28 Nov 2017 00:46:24 -0800
+Subject: crypto: af_alg - fix NULL pointer dereference in
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 887207ed9e5812ed9239b6d07185a2d35dda91db upstream.
+
+ af_alg_free_areq_sgls()
+
+If allocating the ->tsgl member of 'struct af_alg_async_req' failed,
+during cleanup we dereferenced the NULL ->tsgl pointer in
+af_alg_free_areq_sgls(), because ->tsgl_entries was nonzero.
+
+Fix it by only freeing the ->tsgl list if it is non-NULL.
+
+This affected both algif_skcipher and algif_aead.
+
+Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
+Fixes: d887c52d6ae4 ("crypto: algif_aead - overhaul memory management")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/af_alg.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -699,14 +699,15 @@ void af_alg_free_areq_sgls(struct af_alg
+ }
+
+ tsgl = areq->tsgl;
+- for_each_sg(tsgl, sg, areq->tsgl_entries, i) {
+- if (!sg_page(sg))
+- continue;
+- put_page(sg_page(sg));
+- }
++ if (tsgl) {
++ for_each_sg(tsgl, sg, areq->tsgl_entries, i) {
++ if (!sg_page(sg))
++ continue;
++ put_page(sg_page(sg));
++ }
+
+- if (areq->tsgl && areq->tsgl_entries)
+ sock_kfree_s(sk, tsgl, areq->tsgl_entries * sizeof(*tsgl));
++ }
+ }
+ EXPORT_SYMBOL_GPL(af_alg_free_areq_sgls);
+
--- /dev/null
+From b32a7dc8aef1882fbf983eb354837488cc9d54dc Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 27 Nov 2017 23:23:05 -0800
+Subject: crypto: algif_aead - fix reference counting of null skcipher
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit b32a7dc8aef1882fbf983eb354837488cc9d54dc upstream.
+
+In the AEAD interface for AF_ALG, the reference to the "null skcipher"
+held by each tfm was being dropped in the wrong place -- when each
+af_alg_ctx was freed instead of when the aead_tfm was freed. As
+discovered by syzkaller, a specially crafted program could use this to
+cause the null skcipher to be freed while it is still in use.
+
+Fix it by dropping the reference in the right place.
+
+Fixes: 72548b093ee3 ("crypto: algif_aead - copy AAD from src to dst")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_aead.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/crypto/algif_aead.c
++++ b/crypto/algif_aead.c
+@@ -503,6 +503,7 @@ static void aead_release(void *private)
+ struct aead_tfm *tfm = private;
+
+ crypto_free_aead(tfm->aead);
++ crypto_put_default_null_skcipher2();
+ kfree(tfm);
+ }
+
+@@ -535,7 +536,6 @@ static void aead_sock_destruct(struct so
+ unsigned int ivlen = crypto_aead_ivsize(tfm);
+
+ af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
+- crypto_put_default_null_skcipher2();
+ sock_kzfree_s(sk, ctx->iv, ivlen);
+ sock_kfree_s(sk, ctx, ctx->len);
+ af_alg_release_parent(sk);
--- /dev/null
+From af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 28 Nov 2017 18:01:38 -0800
+Subject: crypto: hmac - require that the underlying hash algorithm is unkeyed
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1 upstream.
+
+Because the HMAC template didn't check that its underlying hash
+algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))"
+through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC
+being used without having been keyed, resulting in sha3_update() being
+called without sha3_init(), causing a stack buffer overflow.
+
+This is a very old bug, but it seems to have only started causing real
+problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3)
+because the innermost hash's state is ->import()ed from a zeroed buffer,
+and it just so happens that other hash algorithms are fine with that,
+but SHA-3 is not. However, there could be arch or hardware-dependent
+hash algorithms also affected; I couldn't test everything.
+
+Fix the bug by introducing a function crypto_shash_alg_has_setkey()
+which tests whether a shash algorithm is keyed. Then update the HMAC
+template to require that its underlying hash algorithm is unkeyed.
+
+Here is a reproducer:
+
+ #include <linux/if_alg.h>
+ #include <sys/socket.h>
+
+ int main()
+ {
+ int algfd;
+ struct sockaddr_alg addr = {
+ .salg_type = "hash",
+ .salg_name = "hmac(hmac(sha3-512-generic))",
+ };
+ char key[4096] = { 0 };
+
+ algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ bind(algfd, (const struct sockaddr *)&addr, sizeof(addr));
+ setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
+ }
+
+Here was the KASAN report from syzbot:
+
+ BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline]
+ BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
+ Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044
+
+ CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+ Call Trace:
+ __dump_stack lib/dump_stack.c:17 [inline]
+ dump_stack+0x194/0x257 lib/dump_stack.c:53
+ print_address_description+0x73/0x250 mm/kasan/report.c:252
+ kasan_report_error mm/kasan/report.c:351 [inline]
+ kasan_report+0x25b/0x340 mm/kasan/report.c:409
+ check_memory_region_inline mm/kasan/kasan.c:260 [inline]
+ check_memory_region+0x137/0x190 mm/kasan/kasan.c:267
+ memcpy+0x37/0x50 mm/kasan/kasan.c:303
+ memcpy include/linux/string.h:341 [inline]
+ sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161
+ crypto_shash_update+0xcb/0x220 crypto/shash.c:109
+ shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151
+ crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
+ hmac_finup+0x182/0x330 crypto/hmac.c:152
+ crypto_shash_finup+0xc4/0x120 crypto/shash.c:165
+ shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172
+ crypto_shash_digest+0xc4/0x120 crypto/shash.c:186
+ hmac_setkey+0x36a/0x690 crypto/hmac.c:66
+ crypto_shash_setkey+0xad/0x190 crypto/shash.c:64
+ shash_async_setkey+0x47/0x60 crypto/shash.c:207
+ crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200
+ hash_setkey+0x40/0x90 crypto/algif_hash.c:446
+ alg_setkey crypto/af_alg.c:221 [inline]
+ alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254
+ SYSC_setsockopt net/socket.c:1851 [inline]
+ SyS_setsockopt+0x189/0x360 net/socket.c:1830
+ entry_SYSCALL_64_fastpath+0x1f/0x96
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/hmac.c | 6 +++++-
+ crypto/shash.c | 5 +++--
+ include/crypto/internal/hash.h | 8 ++++++++
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+--- a/crypto/hmac.c
++++ b/crypto/hmac.c
+@@ -195,11 +195,15 @@ static int hmac_create(struct crypto_tem
+ salg = shash_attr_alg(tb[1], 0, 0);
+ if (IS_ERR(salg))
+ return PTR_ERR(salg);
++ alg = &salg->base;
+
++ /* The underlying hash algorithm must be unkeyed */
+ err = -EINVAL;
++ if (crypto_shash_alg_has_setkey(salg))
++ goto out_put_alg;
++
+ ds = salg->digestsize;
+ ss = salg->statesize;
+- alg = &salg->base;
+ if (ds > alg->cra_blocksize ||
+ ss < alg->cra_blocksize)
+ goto out_put_alg;
+--- a/crypto/shash.c
++++ b/crypto/shash.c
+@@ -25,11 +25,12 @@
+
+ static const struct crypto_type crypto_shash_type;
+
+-static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
+- unsigned int keylen)
++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
++ unsigned int keylen)
+ {
+ return -ENOSYS;
+ }
++EXPORT_SYMBOL_GPL(shash_no_setkey);
+
+ static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
+ unsigned int keylen)
+--- a/include/crypto/internal/hash.h
++++ b/include/crypto/internal/hash.h
+@@ -82,6 +82,14 @@ int ahash_register_instance(struct crypt
+ struct ahash_instance *inst);
+ void ahash_free_instance(struct crypto_instance *inst);
+
++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
++ unsigned int keylen);
++
++static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
++{
++ return alg->setkey != shash_no_setkey;
++}
++
+ int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
+ struct hash_alg_common *alg,
+ struct crypto_instance *inst);
--- /dev/null
+From d2890c3778b164fde587bc16583f3a1c87233ec5 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Sun, 26 Nov 2017 23:16:49 -0800
+Subject: crypto: rsa - fix buffer overread when stripping leading zeroes
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit d2890c3778b164fde587bc16583f3a1c87233ec5 upstream.
+
+In rsa_get_n(), if the buffer contained all 0's and "FIPS mode" is
+enabled, we would read one byte past the end of the buffer while
+scanning the leading zeroes. Fix it by checking 'n_sz' before '!*ptr'.
+
+This bug was reachable by adding a specially crafted key of type
+"asymmetric" (requires CONFIG_RSA and CONFIG_X509_CERTIFICATE_PARSER).
+
+KASAN report:
+
+ BUG: KASAN: slab-out-of-bounds in rsa_get_n+0x19e/0x1d0 crypto/rsa_helper.c:33
+ Read of size 1 at addr ffff88003501a708 by task keyctl/196
+
+ CPU: 1 PID: 196 Comm: keyctl Not tainted 4.14.0-09238-g1d3b78bbc6e9 #26
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-20171110_100015-anatol 04/01/2014
+ Call Trace:
+ rsa_get_n+0x19e/0x1d0 crypto/rsa_helper.c:33
+ asn1_ber_decoder+0x82a/0x1fd0 lib/asn1_decoder.c:328
+ rsa_set_pub_key+0xd3/0x320 crypto/rsa.c:278
+ crypto_akcipher_set_pub_key ./include/crypto/akcipher.h:364 [inline]
+ pkcs1pad_set_pub_key+0xae/0x200 crypto/rsa-pkcs1pad.c:117
+ crypto_akcipher_set_pub_key ./include/crypto/akcipher.h:364 [inline]
+ public_key_verify_signature+0x270/0x9d0 crypto/asymmetric_keys/public_key.c:106
+ x509_check_for_self_signed+0x2ea/0x480 crypto/asymmetric_keys/x509_public_key.c:141
+ x509_cert_parse+0x46a/0x620 crypto/asymmetric_keys/x509_cert_parser.c:129
+ x509_key_preparse+0x61/0x750 crypto/asymmetric_keys/x509_public_key.c:174
+ asymmetric_key_preparse+0xa4/0x150 crypto/asymmetric_keys/asymmetric_type.c:388
+ key_create_or_update+0x4d4/0x10a0 security/keys/key.c:850
+ SYSC_add_key security/keys/keyctl.c:122 [inline]
+ SyS_add_key+0xe8/0x290 security/keys/keyctl.c:62
+ entry_SYSCALL_64_fastpath+0x1f/0x96
+
+ Allocated by task 196:
+ __do_kmalloc mm/slab.c:3711 [inline]
+ __kmalloc_track_caller+0x118/0x2e0 mm/slab.c:3726
+ kmemdup+0x17/0x40 mm/util.c:118
+ kmemdup ./include/linux/string.h:414 [inline]
+ x509_cert_parse+0x2cb/0x620 crypto/asymmetric_keys/x509_cert_parser.c:106
+ x509_key_preparse+0x61/0x750 crypto/asymmetric_keys/x509_public_key.c:174
+ asymmetric_key_preparse+0xa4/0x150 crypto/asymmetric_keys/asymmetric_type.c:388
+ key_create_or_update+0x4d4/0x10a0 security/keys/key.c:850
+ SYSC_add_key security/keys/keyctl.c:122 [inline]
+ SyS_add_key+0xe8/0x290 security/keys/keyctl.c:62
+ entry_SYSCALL_64_fastpath+0x1f/0x96
+
+Fixes: 5a7de97309f5 ("crypto: rsa - return raw integers for the ASN.1 parser")
+Cc: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: James Morris <james.l.morris@oracle.com>
+Reviewed-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/rsa_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/crypto/rsa_helper.c
++++ b/crypto/rsa_helper.c
+@@ -30,7 +30,7 @@ int rsa_get_n(void *context, size_t hdrl
+ return -EINVAL;
+
+ if (fips_enabled) {
+- while (!*ptr && n_sz) {
++ while (n_sz && !*ptr) {
+ ptr++;
+ n_sz--;
+ }
--- /dev/null
+From ecaaab5649781c5a0effdaf298a925063020500e Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 28 Nov 2017 20:56:59 -0800
+Subject: crypto: salsa20 - fix blkcipher_walk API usage
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit ecaaab5649781c5a0effdaf298a925063020500e upstream.
+
+When asked to encrypt or decrypt 0 bytes, both the generic and x86
+implementations of Salsa20 crash in blkcipher_walk_done(), either when
+doing 'kfree(walk->buffer)' or 'free_page((unsigned long)walk->page)',
+because walk->buffer and walk->page have not been initialized.
+
+The bug is that Salsa20 is calling blkcipher_walk_done() even when
+nothing is in 'walk.nbytes'. But blkcipher_walk_done() is only meant to
+be called when a nonzero number of bytes have been provided.
+
+The broken code is part of an optimization that tries to make only one
+call to salsa20_encrypt_bytes() to process inputs that are not evenly
+divisible by 64 bytes. To fix the bug, just remove this "optimization"
+and use the blkcipher_walk API the same way all the other users do.
+
+Reproducer:
+
+ #include <linux/if_alg.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+
+ int main()
+ {
+ int algfd, reqfd;
+ struct sockaddr_alg addr = {
+ .salg_type = "skcipher",
+ .salg_name = "salsa20",
+ };
+ char key[16] = { 0 };
+
+ algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ bind(algfd, (void *)&addr, sizeof(addr));
+ reqfd = accept(algfd, 0, 0);
+ setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key));
+ read(reqfd, key, sizeof(key));
+ }
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Fixes: eb6f13eb9f81 ("[CRYPTO] salsa20_generic: Fix multi-page processing")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/crypto/salsa20_glue.c | 7 -------
+ crypto/salsa20_generic.c | 7 -------
+ 2 files changed, 14 deletions(-)
+
+--- a/arch/x86/crypto/salsa20_glue.c
++++ b/arch/x86/crypto/salsa20_glue.c
+@@ -59,13 +59,6 @@ static int encrypt(struct blkcipher_desc
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+- if (likely(walk.nbytes == nbytes))
+- {
+- salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+- walk.dst.virt.addr, nbytes);
+- return blkcipher_walk_done(desc, &walk, 0);
+- }
+-
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.src.virt.addr,
+ walk.dst.virt.addr,
+--- a/crypto/salsa20_generic.c
++++ b/crypto/salsa20_generic.c
+@@ -188,13 +188,6 @@ static int encrypt(struct blkcipher_desc
+
+ salsa20_ivsetup(ctx, walk.iv);
+
+- if (likely(walk.nbytes == nbytes))
+- {
+- salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+- walk.src.virt.addr, nbytes);
+- return blkcipher_walk_done(desc, &walk, 0);
+- }
+-
+ while (walk.nbytes >= 64) {
+ salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
+ walk.src.virt.addr,
mfd-fsl-imx25-clean-up-irq-settings-during-removal.patch
+crypto-algif_aead-fix-reference-counting-of-null-skcipher.patch
+crypto-rsa-fix-buffer-overread-when-stripping-leading-zeroes.patch
+crypto-hmac-require-that-the-underlying-hash-algorithm-is-unkeyed.patch
+crypto-salsa20-fix-blkcipher_walk-api-usage.patch
+crypto-af_alg-fix-null-pointer-dereference-in.patch
+cifs-fix-null-deref-in-smb2_read.patch
+string.h-workaround-for-increased-stack-usage.patch
--- /dev/null
+From 146734b091430c80d80bb96b1139a96fb4bc830e Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 14 Dec 2017 15:32:34 -0800
+Subject: string.h: workaround for increased stack usage
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit 146734b091430c80d80bb96b1139a96fb4bc830e upstream.
+
+The hardened strlen() function causes rather large stack usage in at
+least one file in the kernel, in particular when CONFIG_KASAN is
+enabled:
+
+ drivers/media/usb/em28xx/em28xx-dvb.c: In function 'em28xx_dvb_init':
+ drivers/media/usb/em28xx/em28xx-dvb.c:2062:1: error: the frame size of 3256 bytes is larger than 204 bytes [-Werror=frame-larger-than=]
+
+Analyzing this problem led to the discovery that gcc fails to merge the
+stack slots for the i2c_board_info[] structures after we strlcpy() into
+them, due to the 'noreturn' attribute on the source string length check.
+
+I reported this as a gcc bug, but it is unlikely to get fixed for gcc-8,
+since it is relatively easy to work around, and it gets triggered
+rarely. An earlier workaround I did added an empty inline assembly
+statement before the call to fortify_panic(), which works surprisingly
+well, but is really ugly and unintuitive.
+
+This is a new approach to the same problem, this time addressing it by
+not calling the 'extern __real_strnlen()' function for string constants
+where __builtin_strlen() is a compile-time constant and therefore known
+to be safe.
+
+We do this by checking if the last character in the string is a
+compile-time constant '\0'. If it is, we can assume that strlen() of
+the string is also constant.
+
+As a side-effect, this should also improve the object code output for
+any other call of strlen() on a string constant.
+
+[akpm@linux-foundation.org: add comment]
+Link: http://lkml.kernel.org/r/20171205215143.3085755-1-arnd@arndb.de
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365
+Link: https://patchwork.kernel.org/patch/9980413/
+Link: https://patchwork.kernel.org/patch/9974047/
+Fixes: 6974f0c4555 ("include/linux/string.h: add the option of fortified string.h functions")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
+Cc: Daniel Micay <danielmicay@gmail.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Martin Wilck <mwilck@suse.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/string.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/include/linux/string.h
++++ b/include/linux/string.h
+@@ -259,7 +259,10 @@ __FORTIFY_INLINE __kernel_size_t strlen(
+ {
+ __kernel_size_t ret;
+ size_t p_size = __builtin_object_size(p, 0);
+- if (p_size == (size_t)-1)
++
++ /* Work around gcc excess stack consumption issue */
++ if (p_size == (size_t)-1 ||
++ (__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
+ return __builtin_strlen(p);
+ ret = strnlen(p, p_size);
+ if (p_size <= ret)