]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Jul 2018 10:05:43 +0000 (12:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Jul 2018 10:05:43 +0000 (12:05 +0200)
added patches:
keys-dns-fix-parsing-multiple-options.patch
net-nfc-avoid-stalls-when-nfc_alloc_send_skb-returned-null.patch
netfilter-ebtables-reject-non-bridge-targets.patch
netfilter-ipv6-nf_defrag-drop-skb-dst-before-queueing.patch
rds-avoid-unenecessary-cong_update-in-loop-transport.patch
reiserfs-fix-buffer-overflow-with-long-warning-messages.patch

queue-4.9/keys-dns-fix-parsing-multiple-options.patch [new file with mode: 0644]
queue-4.9/net-nfc-avoid-stalls-when-nfc_alloc_send_skb-returned-null.patch [new file with mode: 0644]
queue-4.9/netfilter-ebtables-reject-non-bridge-targets.patch [new file with mode: 0644]
queue-4.9/netfilter-ipv6-nf_defrag-drop-skb-dst-before-queueing.patch [new file with mode: 0644]
queue-4.9/rds-avoid-unenecessary-cong_update-in-loop-transport.patch [new file with mode: 0644]
queue-4.9/reiserfs-fix-buffer-overflow-with-long-warning-messages.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/keys-dns-fix-parsing-multiple-options.patch b/queue-4.9/keys-dns-fix-parsing-multiple-options.patch
new file mode 100644 (file)
index 0000000..b3fd1f4
--- /dev/null
@@ -0,0 +1,107 @@
+From c604cb767049b78b3075497b80ebb8fd530ea2cc Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Wed, 11 Jul 2018 10:46:29 -0700
+Subject: KEYS: DNS: fix parsing multiple options
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit c604cb767049b78b3075497b80ebb8fd530ea2cc upstream.
+
+My recent fix for dns_resolver_preparse() printing very long strings was
+incomplete, as shown by syzbot which still managed to hit the
+WARN_ONCE() in set_precision() by adding a crafted "dns_resolver" key:
+
+    precision 50001 too large
+    WARNING: CPU: 7 PID: 864 at lib/vsprintf.c:2164 vsnprintf+0x48a/0x5a0
+
+The bug this time isn't just a printing bug, but also a logical error
+when multiple options ("#"-separated strings) are given in the key
+payload.  Specifically, when separating an option string into name and
+value, if there is no value then the name is incorrectly considered to
+end at the end of the key payload, rather than the end of the current
+option.  This bypasses validation of the option length, and also means
+that specifying multiple options is broken -- which presumably has gone
+unnoticed as there is currently only one valid option anyway.
+
+A similar problem also applied to option values, as the kstrtoul() when
+parsing the "dnserror" option will read past the end of the current
+option and into the next option.
+
+Fix these bugs by correctly computing the length of the option name and
+by copying the option value, null-terminated, into a temporary buffer.
+
+Reproducer for the WARN_ONCE() that syzbot hit:
+
+    perl -e 'print "#A#", "\0" x 50000' | keyctl padd dns_resolver desc @s
+
+Reproducer for "dnserror" option being parsed incorrectly (expected
+behavior is to fail when seeing the unknown option "foo", actual
+behavior was to read the dnserror value as "1#foo" and fail there):
+
+    perl -e 'print "#dnserror=1#foo\0"' | keyctl padd dns_resolver desc @s
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Fixes: 4a2d789267e0 ("DNS: If the DNS server returns an error, allow that to be cached [ver #2]")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/dns_resolver/dns_key.c |   30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+--- a/net/dns_resolver/dns_key.c
++++ b/net/dns_resolver/dns_key.c
+@@ -87,35 +87,39 @@ dns_resolver_preparse(struct key_prepars
+               opt++;
+               kdebug("options: '%s'", opt);
+               do {
++                      int opt_len, opt_nlen;
+                       const char *eq;
+-                      int opt_len, opt_nlen, opt_vlen, tmp;
++                      char optval[128];
+                       next_opt = memchr(opt, '#', end - opt) ?: end;
+                       opt_len = next_opt - opt;
+-                      if (opt_len <= 0 || opt_len > 128) {
++                      if (opt_len <= 0 || opt_len > sizeof(optval)) {
+                               pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n",
+                                                   opt_len);
+                               return -EINVAL;
+                       }
+-                      eq = memchr(opt, '=', opt_len) ?: end;
+-                      opt_nlen = eq - opt;
+-                      eq++;
+-                      opt_vlen = next_opt - eq; /* will be -1 if no value */
+-
+-                      tmp = opt_vlen >= 0 ? opt_vlen : 0;
+-                      kdebug("option '%*.*s' val '%*.*s'",
+-                             opt_nlen, opt_nlen, opt, tmp, tmp, eq);
++                      eq = memchr(opt, '=', opt_len);
++                      if (eq) {
++                              opt_nlen = eq - opt;
++                              eq++;
++                              memcpy(optval, eq, next_opt - eq);
++                              optval[next_opt - eq] = '\0';
++                      } else {
++                              opt_nlen = opt_len;
++                              optval[0] = '\0';
++                      }
++
++                      kdebug("option '%*.*s' val '%s'",
++                             opt_nlen, opt_nlen, opt, optval);
+                       /* see if it's an error number representing a DNS error
+                        * that's to be recorded as the result in this key */
+                       if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 &&
+                           memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) {
+                               kdebug("dns error number option");
+-                              if (opt_vlen <= 0)
+-                                      goto bad_option_value;
+-                              ret = kstrtoul(eq, 10, &derrno);
++                              ret = kstrtoul(optval, 10, &derrno);
+                               if (ret < 0)
+                                       goto bad_option_value;
diff --git a/queue-4.9/net-nfc-avoid-stalls-when-nfc_alloc_send_skb-returned-null.patch b/queue-4.9/net-nfc-avoid-stalls-when-nfc_alloc_send_skb-returned-null.patch
new file mode 100644 (file)
index 0000000..27b911c
--- /dev/null
@@ -0,0 +1,49 @@
+From 3bc53be9db21040b5d2de4d455f023c8c494aa68 Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Date: Wed, 18 Jul 2018 18:57:27 +0900
+Subject: net/nfc: Avoid stalls when nfc_alloc_send_skb() returned NULL.
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+commit 3bc53be9db21040b5d2de4d455f023c8c494aa68 upstream.
+
+syzbot is reporting stalls at nfc_llcp_send_ui_frame() [1]. This is
+because nfc_llcp_send_ui_frame() is retrying the loop without any delay
+when nonblocking nfc_alloc_send_skb() returned NULL.
+
+Since there is no need to use MSG_DONTWAIT if we retry until
+sock_alloc_send_pskb() succeeds, let's use blocking call.
+Also, in case an unexpected error occurred, let's break the loop
+if blocking nfc_alloc_send_skb() failed.
+
+[1] https://syzkaller.appspot.com/bug?id=4a131cc571c3733e0eff6bc673f4e36ae48f19c6
+
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Reported-by: syzbot <syzbot+d29d18215e477cfbfbdd@syzkaller.appspotmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/nfc/llcp_commands.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/net/nfc/llcp_commands.c
++++ b/net/nfc/llcp_commands.c
+@@ -753,11 +753,14 @@ int nfc_llcp_send_ui_frame(struct nfc_ll
+               pr_debug("Fragment %zd bytes remaining %zd",
+                        frag_len, remaining_len);
+-              pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
++              pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0,
+                                        frag_len + LLCP_HEADER_SIZE, &err);
+               if (pdu == NULL) {
+-                      pr_err("Could not allocate PDU\n");
+-                      continue;
++                      pr_err("Could not allocate PDU (error=%d)\n", err);
++                      len -= remaining_len;
++                      if (len == 0)
++                              len = err;
++                      break;
+               }
+               pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
diff --git a/queue-4.9/netfilter-ebtables-reject-non-bridge-targets.patch b/queue-4.9/netfilter-ebtables-reject-non-bridge-targets.patch
new file mode 100644 (file)
index 0000000..8de4753
--- /dev/null
@@ -0,0 +1,64 @@
+From 11ff7288beb2b7da889a014aff0a7b80bf8efcf3 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Wed, 6 Jun 2018 12:14:56 +0200
+Subject: netfilter: ebtables: reject non-bridge targets
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 11ff7288beb2b7da889a014aff0a7b80bf8efcf3 upstream.
+
+the ebtables evaluation loop expects targets to return
+positive values (jumps), or negative values (absolute verdicts).
+
+This is completely different from what xtables does.
+In xtables, targets are expected to return the standard netfilter
+verdicts, i.e. NF_DROP, NF_ACCEPT, etc.
+
+ebtables will consider these as jumps.
+
+Therefore reject any target found due to unspec fallback.
+v2: also reject watchers.  ebtables ignores their return value, so
+a target that assumes skb ownership (and returns NF_STOLEN) causes
+use-after-free.
+
+The only watchers in the 'ebtables' front-end are log and nflog;
+both have AF_BRIDGE specific wrappers on kernel side.
+
+Reported-by: syzbot+2b43f681169a2a0d306a@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/bridge/netfilter/ebtables.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -406,6 +406,12 @@ ebt_check_watcher(struct ebt_entry_watch
+       watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0);
+       if (IS_ERR(watcher))
+               return PTR_ERR(watcher);
++
++      if (watcher->family != NFPROTO_BRIDGE) {
++              module_put(watcher->me);
++              return -ENOENT;
++      }
++
+       w->u.watcher = watcher;
+       par->target   = watcher;
+@@ -727,6 +733,13 @@ ebt_check_entry(struct ebt_entry *e, str
+               goto cleanup_watchers;
+       }
++      /* Reject UNSPEC, xtables verdicts/return values are incompatible */
++      if (target->family != NFPROTO_BRIDGE) {
++              module_put(target->me);
++              ret = -ENOENT;
++              goto cleanup_watchers;
++      }
++
+       t->u.target = target;
+       if (t->u.target == &ebt_standard_target) {
+               if (gap < sizeof(struct ebt_standard_target)) {
diff --git a/queue-4.9/netfilter-ipv6-nf_defrag-drop-skb-dst-before-queueing.patch b/queue-4.9/netfilter-ipv6-nf_defrag-drop-skb-dst-before-queueing.patch
new file mode 100644 (file)
index 0000000..1827d39
--- /dev/null
@@ -0,0 +1,52 @@
+From 84379c9afe011020e797e3f50a662b08a6355dcf Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Mon, 9 Jul 2018 13:43:38 +0200
+Subject: netfilter: ipv6: nf_defrag: drop skb dst before queueing
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 84379c9afe011020e797e3f50a662b08a6355dcf upstream.
+
+Eric Dumazet reports:
+ Here is a reproducer of an annoying bug detected by syzkaller on our production kernel
+ [..]
+ ./b78305423 enable_conntrack
+ Then :
+ sleep 60
+ dmesg | tail -10
+ [  171.599093] unregister_netdevice: waiting for lo to become free. Usage count = 2
+ [  181.631024] unregister_netdevice: waiting for lo to become free. Usage count = 2
+ [  191.687076] unregister_netdevice: waiting for lo to become free. Usage count = 2
+ [  201.703037] unregister_netdevice: waiting for lo to become free. Usage count = 2
+ [  211.711072] unregister_netdevice: waiting for lo to become free. Usage count = 2
+ [  221.959070] unregister_netdevice: waiting for lo to become free. Usage count = 2
+
+Reproducer sends ipv6 fragment that hits nfct defrag via LOCAL_OUT hook.
+skb gets queued until frag timer expiry -- 1 minute.
+
+Normally nf_conntrack_reasm gets called during prerouting, so skb has
+no dst yet which might explain why this wasn't spotted earlier.
+
+Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
+Reported-by: John Sperbeck <jsperbeck@google.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Tested-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv6/netfilter/nf_conntrack_reasm.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -618,6 +618,8 @@ int nf_ct_frag6_gather(struct net *net,
+           fq->q.meat == fq->q.len &&
+           nf_ct_frag6_reasm(fq, skb, dev))
+               ret = 0;
++      else
++              skb_dst_drop(skb);
+ out_unlock:
+       spin_unlock_bh(&fq->q.lock);
diff --git a/queue-4.9/rds-avoid-unenecessary-cong_update-in-loop-transport.patch b/queue-4.9/rds-avoid-unenecessary-cong_update-in-loop-transport.patch
new file mode 100644 (file)
index 0000000..b0ec6ef
--- /dev/null
@@ -0,0 +1,61 @@
+From f1693c63ab133d16994cc50f773982b5905af264 Mon Sep 17 00:00:00 2001
+From: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+Date: Thu, 14 Jun 2018 11:52:34 -0700
+Subject: rds: avoid unenecessary cong_update in loop transport
+
+From: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+
+commit f1693c63ab133d16994cc50f773982b5905af264 upstream.
+
+Loop transport which is self loopback, remote port congestion
+update isn't relevant. Infact the xmit path already ignores it.
+Receive path needs to do the same.
+
+Reported-by: syzbot+4c20b3866171ce8441d2@syzkaller.appspotmail.com
+Reviewed-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
+Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/rds/loop.c |    1 +
+ net/rds/rds.h  |    5 +++++
+ net/rds/recv.c |    5 +++++
+ 3 files changed, 11 insertions(+)
+
+--- a/net/rds/loop.c
++++ b/net/rds/loop.c
+@@ -193,4 +193,5 @@ struct rds_transport rds_loop_transport
+       .inc_copy_to_user       = rds_message_inc_copy_to_user,
+       .inc_free               = rds_loop_inc_free,
+       .t_name                 = "loopback",
++      .t_type                 = RDS_TRANS_LOOP,
+ };
+--- a/net/rds/rds.h
++++ b/net/rds/rds.h
+@@ -440,6 +440,11 @@ struct rds_notifier {
+       int                     n_status;
+ };
++/* Available as part of RDS core, so doesn't need to participate
++ * in get_preferred transport etc
++ */
++#define       RDS_TRANS_LOOP  3
++
+ /**
+  * struct rds_transport -  transport specific behavioural hooks
+  *
+--- a/net/rds/recv.c
++++ b/net/rds/recv.c
+@@ -94,6 +94,11 @@ static void rds_recv_rcvbuf_delta(struct
+               return;
+       rs->rs_rcv_bytes += delta;
++
++      /* loop transport doesn't send/recv congestion updates */
++      if (rs->rs_transport->t_type == RDS_TRANS_LOOP)
++              return;
++
+       now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs);
+       rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d "
diff --git a/queue-4.9/reiserfs-fix-buffer-overflow-with-long-warning-messages.patch b/queue-4.9/reiserfs-fix-buffer-overflow-with-long-warning-messages.patch
new file mode 100644 (file)
index 0000000..e2cd195
--- /dev/null
@@ -0,0 +1,252 @@
+From fe10e398e860955bac4d28ec031b701d358465e4 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Fri, 13 Jul 2018 16:59:27 -0700
+Subject: reiserfs: fix buffer overflow with long warning messages
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit fe10e398e860955bac4d28ec031b701d358465e4 upstream.
+
+ReiserFS prepares log messages into a 1024-byte buffer with no bounds
+checks.  Long messages, such as the "unknown mount option" warning when
+userspace passes a crafted mount options string, overflow this buffer.
+This causes KASAN to report a global-out-of-bounds write.
+
+Fix it by truncating messages to the buffer size.
+
+Link: http://lkml.kernel.org/r/20180707203621.30922-1-ebiggers3@gmail.com
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: syzbot+b890b3335a4d8c608963@syzkaller.appspotmail.com
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
+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>
+
+---
+ fs/reiserfs/prints.c |  141 +++++++++++++++++++++++++++++----------------------
+ 1 file changed, 81 insertions(+), 60 deletions(-)
+
+--- a/fs/reiserfs/prints.c
++++ b/fs/reiserfs/prints.c
+@@ -76,83 +76,99 @@ static char *le_type(struct reiserfs_key
+ }
+ /* %k */
+-static void sprintf_le_key(char *buf, struct reiserfs_key *key)
++static int scnprintf_le_key(char *buf, size_t size, struct reiserfs_key *key)
+ {
+       if (key)
+-              sprintf(buf, "[%d %d %s %s]", le32_to_cpu(key->k_dir_id),
+-                      le32_to_cpu(key->k_objectid), le_offset(key),
+-                      le_type(key));
++              return scnprintf(buf, size, "[%d %d %s %s]",
++                               le32_to_cpu(key->k_dir_id),
++                               le32_to_cpu(key->k_objectid), le_offset(key),
++                               le_type(key));
+       else
+-              sprintf(buf, "[NULL]");
++              return scnprintf(buf, size, "[NULL]");
+ }
+ /* %K */
+-static void sprintf_cpu_key(char *buf, struct cpu_key *key)
++static int scnprintf_cpu_key(char *buf, size_t size, struct cpu_key *key)
+ {
+       if (key)
+-              sprintf(buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id,
+-                      key->on_disk_key.k_objectid, reiserfs_cpu_offset(key),
+-                      cpu_type(key));
++              return scnprintf(buf, size, "[%d %d %s %s]",
++                               key->on_disk_key.k_dir_id,
++                               key->on_disk_key.k_objectid,
++                               reiserfs_cpu_offset(key), cpu_type(key));
+       else
+-              sprintf(buf, "[NULL]");
++              return scnprintf(buf, size, "[NULL]");
+ }
+-static void sprintf_de_head(char *buf, struct reiserfs_de_head *deh)
++static int scnprintf_de_head(char *buf, size_t size,
++                           struct reiserfs_de_head *deh)
+ {
+       if (deh)
+-              sprintf(buf,
+-                      "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]",
+-                      deh_offset(deh), deh_dir_id(deh), deh_objectid(deh),
+-                      deh_location(deh), deh_state(deh));
++              return scnprintf(buf, size,
++                               "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]",
++                               deh_offset(deh), deh_dir_id(deh),
++                               deh_objectid(deh), deh_location(deh),
++                               deh_state(deh));
+       else
+-              sprintf(buf, "[NULL]");
++              return scnprintf(buf, size, "[NULL]");
+ }
+-static void sprintf_item_head(char *buf, struct item_head *ih)
++static int scnprintf_item_head(char *buf, size_t size, struct item_head *ih)
+ {
+       if (ih) {
+-              strcpy(buf,
+-                     (ih_version(ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*");
+-              sprintf_le_key(buf + strlen(buf), &(ih->ih_key));
+-              sprintf(buf + strlen(buf), ", item_len %d, item_location %d, "
+-                      "free_space(entry_count) %d",
+-                      ih_item_len(ih), ih_location(ih), ih_free_space(ih));
++              char *p = buf;
++              char * const end = buf + size;
++
++              p += scnprintf(p, end - p, "%s",
++                             (ih_version(ih) == KEY_FORMAT_3_6) ?
++                             "*3.6* " : "*3.5*");
++
++              p += scnprintf_le_key(p, end - p, &ih->ih_key);
++
++              p += scnprintf(p, end - p,
++                             ", item_len %d, item_location %d, free_space(entry_count) %d",
++                             ih_item_len(ih), ih_location(ih),
++                             ih_free_space(ih));
++              return p - buf;
+       } else
+-              sprintf(buf, "[NULL]");
++              return scnprintf(buf, size, "[NULL]");
+ }
+-static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de)
++static int scnprintf_direntry(char *buf, size_t size,
++                            struct reiserfs_dir_entry *de)
+ {
+       char name[20];
+       memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen);
+       name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0;
+-      sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid);
++      return scnprintf(buf, size, "\"%s\"==>[%d %d]",
++                       name, de->de_dir_id, de->de_objectid);
+ }
+-static void sprintf_block_head(char *buf, struct buffer_head *bh)
++static int scnprintf_block_head(char *buf, size_t size, struct buffer_head *bh)
+ {
+-      sprintf(buf, "level=%d, nr_items=%d, free_space=%d rdkey ",
+-              B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh));
++      return scnprintf(buf, size,
++                       "level=%d, nr_items=%d, free_space=%d rdkey ",
++                       B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh));
+ }
+-static void sprintf_buffer_head(char *buf, struct buffer_head *bh)
++static int scnprintf_buffer_head(char *buf, size_t size, struct buffer_head *bh)
+ {
+-      sprintf(buf,
+-              "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
+-              bh->b_bdev, bh->b_size,
+-              (unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)),
+-              bh->b_state, bh->b_page,
+-              buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE",
+-              buffer_dirty(bh) ? "DIRTY" : "CLEAN",
+-              buffer_locked(bh) ? "LOCKED" : "UNLOCKED");
++      return scnprintf(buf, size,
++                       "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
++                       bh->b_bdev, bh->b_size,
++                       (unsigned long long)bh->b_blocknr,
++                       atomic_read(&(bh->b_count)),
++                       bh->b_state, bh->b_page,
++                       buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE",
++                       buffer_dirty(bh) ? "DIRTY" : "CLEAN",
++                       buffer_locked(bh) ? "LOCKED" : "UNLOCKED");
+ }
+-static void sprintf_disk_child(char *buf, struct disk_child *dc)
++static int scnprintf_disk_child(char *buf, size_t size, struct disk_child *dc)
+ {
+-      sprintf(buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc),
+-              dc_size(dc));
++      return scnprintf(buf, size, "[dc_number=%d, dc_size=%u]",
++                       dc_block_number(dc), dc_size(dc));
+ }
+ static char *is_there_reiserfs_struct(char *fmt, int *what)
+@@ -189,55 +205,60 @@ static void prepare_error_buf(const char
+       char *fmt1 = fmt_buf;
+       char *k;
+       char *p = error_buf;
++      char * const end = &error_buf[sizeof(error_buf)];
+       int what;
+       spin_lock(&error_lock);
+-      strcpy(fmt1, fmt);
++      if (WARN_ON(strscpy(fmt_buf, fmt, sizeof(fmt_buf)) < 0)) {
++              strscpy(error_buf, "format string too long", end - error_buf);
++              goto out_unlock;
++      }
+       while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) {
+               *k = 0;
+-              p += vsprintf(p, fmt1, args);
++              p += vscnprintf(p, end - p, fmt1, args);
+               switch (what) {
+               case 'k':
+-                      sprintf_le_key(p, va_arg(args, struct reiserfs_key *));
++                      p += scnprintf_le_key(p, end - p,
++                                            va_arg(args, struct reiserfs_key *));
+                       break;
+               case 'K':
+-                      sprintf_cpu_key(p, va_arg(args, struct cpu_key *));
++                      p += scnprintf_cpu_key(p, end - p,
++                                             va_arg(args, struct cpu_key *));
+                       break;
+               case 'h':
+-                      sprintf_item_head(p, va_arg(args, struct item_head *));
++                      p += scnprintf_item_head(p, end - p,
++                                               va_arg(args, struct item_head *));
+                       break;
+               case 't':
+-                      sprintf_direntry(p,
+-                                       va_arg(args,
+-                                              struct reiserfs_dir_entry *));
++                      p += scnprintf_direntry(p, end - p,
++                                              va_arg(args, struct reiserfs_dir_entry *));
+                       break;
+               case 'y':
+-                      sprintf_disk_child(p,
+-                                         va_arg(args, struct disk_child *));
++                      p += scnprintf_disk_child(p, end - p,
++                                                va_arg(args, struct disk_child *));
+                       break;
+               case 'z':
+-                      sprintf_block_head(p,
+-                                         va_arg(args, struct buffer_head *));
++                      p += scnprintf_block_head(p, end - p,
++                                                va_arg(args, struct buffer_head *));
+                       break;
+               case 'b':
+-                      sprintf_buffer_head(p,
+-                                          va_arg(args, struct buffer_head *));
++                      p += scnprintf_buffer_head(p, end - p,
++                                                 va_arg(args, struct buffer_head *));
+                       break;
+               case 'a':
+-                      sprintf_de_head(p,
+-                                      va_arg(args,
+-                                             struct reiserfs_de_head *));
++                      p += scnprintf_de_head(p, end - p,
++                                             va_arg(args, struct reiserfs_de_head *));
+                       break;
+               }
+-              p += strlen(p);
+               fmt1 = k + 2;
+       }
+-      vsprintf(p, fmt1, args);
++      p += vscnprintf(p, end - p, fmt1, args);
++out_unlock:
+       spin_unlock(&error_lock);
+ }
index 1aa6c08e3b5c55c15e3d931f919d714fe282de36..c6a8584deffb6b37f54c02ca9ffd8d4c8ea32794 100644 (file)
@@ -34,3 +34,9 @@ net-mlx5-fix-command-interface-race-in-polling-mode.patch
 net-cxgb3_main-fix-potential-spectre-v1.patch
 rtlwifi-rtl8821ae-fix-firmware-is-not-ready-to-run.patch
 net-lan78xx-fix-race-in-tx-pending-skb-size-calculation.patch
+netfilter-ebtables-reject-non-bridge-targets.patch
+reiserfs-fix-buffer-overflow-with-long-warning-messages.patch
+keys-dns-fix-parsing-multiple-options.patch
+netfilter-ipv6-nf_defrag-drop-skb-dst-before-queueing.patch
+rds-avoid-unenecessary-cong_update-in-loop-transport.patch
+net-nfc-avoid-stalls-when-nfc_alloc_send_skb-returned-null.patch