This is a note to let you know that I've just added the patch titled
md: free unused memory after bitmap resize
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
md-free-unused-memory-after-bitmap-resize.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From foo@baz Tue Dec 12 13:26:17 CET 2017
From: Zdenek Kabelac <zkabelac(a)redhat.com>
Date: Wed, 8 Nov 2017 13:44:56 +0100
Subject: md: free unused memory after bitmap resize
From: Zdenek Kabelac <zkabelac(a)redhat.com>
[ Upstream commit 0868b99c214a3d55486c700de7c3f770b7243e7c ]
When bitmap is resized, the old kalloced chunks just are not released
once the resized bitmap starts to use new space.
This fixes in particular kmemleak reports like this one:
unreferenced object 0xffff8f4311e9c000 (size 4096):
comm "lvm", pid 19333, jiffies 4295263268 (age 528.265s)
hex dump (first 32 bytes):
02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 ................
02 80 02 80 02 80 02 80 02 80 02 80 02 80 02 80 ................
backtrace:
[<ffffffffa69471ca>] kmemleak_alloc+0x4a/0xa0
[<ffffffffa628c10e>] kmem_cache_alloc_trace+0x14e/0x2e0
[<ffffffffa676cfec>] bitmap_checkpage+0x7c/0x110
[<ffffffffa676d0c5>] bitmap_get_counter+0x45/0xd0
[<ffffffffa676d6b3>] bitmap_set_memory_bits+0x43/0xe0
[<ffffffffa676e41c>] bitmap_init_from_disk+0x23c/0x530
[<ffffffffa676f1ae>] bitmap_load+0xbe/0x160
[<ffffffffc04c47d3>] raid_preresume+0x203/0x2f0 [dm_raid]
[<ffffffffa677762f>] dm_table_resume_targets+0x4f/0xe0
[<ffffffffa6774b52>] dm_resume+0x122/0x140
[<ffffffffa6779b9f>] dev_suspend+0x18f/0x290
[<ffffffffa677a3a7>] ctl_ioctl+0x287/0x560
[<ffffffffa677a693>] dm_ctl_ioctl+0x13/0x20
[<ffffffffa62d6b46>] do_vfs_ioctl+0xa6/0x750
[<ffffffffa62d7269>] SyS_ioctl+0x79/0x90
[<ffffffffa6956d41>] entry_SYSCALL_64_fastpath+0x1f/0xc2
Signed-off-by: Zdenek Kabelac <zkabelac(a)redhat.com>
Signed-off-by: Shaohua Li <shli(a)fb.com>
Signed-off-by: Sasha Levin <alexander.levin(a)verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/md/bitmap.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -2084,6 +2084,7 @@ int bitmap_resize(struct bitmap *bitmap,
for (k = 0; k < page; k++) {
kfree(new_bp[k].map);
}
+ kfree(new_bp);
/* restore some fields from old_counts */
bitmap->counts.bp = old_counts.bp;
@@ -2134,6 +2135,14 @@ int bitmap_resize(struct bitmap *bitmap,
block += old_blocks;
}
+ if (bitmap->counts.bp != old_counts.bp) {
+ unsigned long k;
+ for (k = 0; k < old_counts.pages; k++)
+ if (!old_counts.bp[k].hijacked)
+ kfree(old_counts.bp[k].map);
+ kfree(old_counts.bp);
+ }
+
if (!init) {
int i;
while (block < (chunks << chunkshift)) {
Patches currently in stable-queue which might be from zkabelac(a)redhat.com are
queue-4.9/md-free-unused-memory-after-bitmap-resize.patch
This is a note to let you know that I've just added the patch titled
kbuild: do not call cc-option before KBUILD_CFLAGS initialization
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
kbuild-do-not-call-cc-option-before-kbuild_cflags-initialization.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From foo@baz Tue Dec 12 13:26:17 CET 2017
From: Masahiro Yamada <yamada.masahiro(a)socionext.com>
Date: Thu, 12 Oct 2017 18:22:25 +0900
Subject: kbuild: do not call cc-option before KBUILD_CFLAGS initialization
From: Masahiro Yamada <yamada.masahiro(a)socionext.com>
[ Upstream commit 433dc2ebe7d17dd21cba7ad5c362d37323592236 ]
Some $(call cc-option,...) are invoked very early, even before
KBUILD_CFLAGS, etc. are initialized.
The returned string from $(call cc-option,...) depends on
KBUILD_CPPFLAGS, KBUILD_CFLAGS, and GCC_PLUGINS_CFLAGS.
Since they are exported, they are not empty when the top Makefile
is recursively invoked.
The recursion occurs in several places. For example, the top
Makefile invokes itself for silentoldconfig. "make tinyconfig",
"make rpm-pkg" are the cases, too.
In those cases, the second call of cc-option from the same line
runs a different shell command due to non-pristine KBUILD_CFLAGS.
To get the same result all the time, KBUILD_* and GCC_PLUGINS_CFLAGS
must be initialized before any call of cc-option. This avoids
garbage data in the .cache.mk file.
Move all calls of cc-option below the config targets because target
compiler flags are unnecessary for Kconfig.
Signed-off-by: Masahiro Yamada <yamada.masahiro(a)socionext.com>
Reviewed-by: Douglas Anderson <dianders(a)chromium.org>
Signed-off-by: Sasha Levin <alexander.levin(a)verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
Makefile | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -370,9 +370,6 @@ LDFLAGS_MODULE =
CFLAGS_KERNEL =
AFLAGS_KERNEL =
LDFLAGS_vmlinux =
-CFLAGS_GCOV := -fprofile-arcs -ftest-coverage -fno-tree-loop-im $(call cc-disable-warning,maybe-uninitialized,)
-CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
-
# Use USERINCLUDE when you must reference the UAPI directories only.
USERINCLUDE := \
@@ -393,21 +390,19 @@ LINUXINCLUDE := \
LINUXINCLUDE += $(filter-out $(LINUXINCLUDE),$(USERINCLUDE))
-KBUILD_CPPFLAGS := -D__KERNEL__
-
+KBUILD_AFLAGS := -D__ASSEMBLY__
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
- -std=gnu89 $(call cc-option,-fno-PIE)
-
-
+ -std=gnu89
+KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
-KBUILD_AFLAGS := -D__ASSEMBLY__ $(call cc-option,-fno-PIE)
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
+GCC_PLUGINS_CFLAGS :=
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
@@ -420,7 +415,7 @@ export MAKE AWK GENKSYMS INSTALLKERNEL P
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KCOV CFLAGS_KASAN CFLAGS_UBSAN
+export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_KASAN CFLAGS_UBSAN
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
@@ -620,6 +615,12 @@ endif
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
+KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
+KBUILD_AFLAGS += $(call cc-option,-fno-PIE)
+CFLAGS_GCOV := -fprofile-arcs -ftest-coverage -fno-tree-loop-im $(call cc-disable-warning,maybe-uninitialized,)
+CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
+export CFLAGS_GCOV CFLAGS_KCOV
+
# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
# values of the respective KBUILD_* variables
ARCH_CPPFLAGS :=
Patches currently in stable-queue which might be from yamada.masahiro(a)socionext.com are
queue-4.9/kbuild-do-not-call-cc-option-before-kbuild_cflags-initialization.patch
This is a note to let you know that I've just added the patch titled
ipvlan: fix ipv6 outbound device
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
ipvlan-fix-ipv6-outbound-device.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From foo@baz Tue Dec 12 13:26:17 CET 2017
From: Keefe Liu <liuqifa(a)huawei.com>
Date: Thu, 9 Nov 2017 20:09:31 +0800
Subject: ipvlan: fix ipv6 outbound device
From: Keefe Liu <liuqifa(a)huawei.com>
[ Upstream commit ca29fd7cce5a6444d57fb86517589a1a31c759e1 ]
When process the outbound packet of ipv6, we should assign the master
device to output device other than input device.
Signed-off-by: Keefe Liu <liuqifa(a)huawei.com>
Acked-by: Mahesh Bandewar <maheshb(a)google.com>
Signed-off-by: David S. Miller <davem(a)davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin(a)verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/net/ipvlan/ipvlan_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -404,7 +404,7 @@ static int ipvlan_process_v6_outbound(st
struct dst_entry *dst;
int err, ret = NET_XMIT_DROP;
struct flowi6 fl6 = {
- .flowi6_iif = dev->ifindex,
+ .flowi6_oif = dev->ifindex,
.daddr = ip6h->daddr,
.saddr = ip6h->saddr,
.flowi6_flags = FLOWI_FLAG_ANYSRC,
Patches currently in stable-queue which might be from liuqifa(a)huawei.com are
queue-4.9/ipvlan-fix-ipv6-outbound-device.patch
This is a note to let you know that I've just added the patch titled
audit: ensure that 'audit=1' actually enables audit for PID 1
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
audit-ensure-that-audit-1-actually-enables-audit-for-pid-1.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From foo@baz Tue Dec 12 13:26:17 CET 2017
From: Paul Moore <paul(a)paul-moore.com>
Date: Fri, 1 Sep 2017 09:44:34 -0400
Subject: audit: ensure that 'audit=1' actually enables audit for PID 1
From: Paul Moore <paul(a)paul-moore.com>
[ Upstream commit 173743dd99a49c956b124a74c8aacb0384739a4c ]
Prior to this patch we enabled audit in audit_init(), which is too
late for PID 1 as the standard initcalls are run after the PID 1 task
is forked. This means that we never allocate an audit_context (see
audit_alloc()) for PID 1 and therefore miss a lot of audit events
generated by PID 1.
This patch enables audit as early as possible to help ensure that when
PID 1 is forked it can allocate an audit_context if required.
Reviewed-by: Richard Guy Briggs <rgb(a)redhat.com>
Signed-off-by: Paul Moore <paul(a)paul-moore.com>
Signed-off-by: Sasha Levin <alexander.levin(a)verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
kernel/audit.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -79,13 +79,13 @@ static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
#define AUDIT_LOCKED 2
-u32 audit_enabled;
-u32 audit_ever_enabled;
+u32 audit_enabled = AUDIT_OFF;
+u32 audit_ever_enabled = !!AUDIT_OFF;
EXPORT_SYMBOL_GPL(audit_enabled);
/* Default state when kernel boots without any parameters. */
-static u32 audit_default;
+static u32 audit_default = AUDIT_OFF;
/* If auditing cannot proceed, audit_failure selects what happens. */
static u32 audit_failure = AUDIT_FAIL_PRINTK;
@@ -1199,8 +1199,6 @@ static int __init audit_init(void)
skb_queue_head_init(&audit_skb_queue);
skb_queue_head_init(&audit_skb_hold_queue);
audit_initialized = AUDIT_INITIALIZED;
- audit_enabled = audit_default;
- audit_ever_enabled |= !!audit_default;
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
@@ -1217,6 +1215,8 @@ static int __init audit_enable(char *str
audit_default = !!simple_strtol(str, NULL, 0);
if (!audit_default)
audit_initialized = AUDIT_DISABLED;
+ audit_enabled = audit_default;
+ audit_ever_enabled = !!audit_enabled;
pr_info("%s\n", audit_default ?
"enabled (after initialization)" : "disabled (until reboot)");
Patches currently in stable-queue which might be from paul(a)paul-moore.com are
queue-4.9/audit-ensure-that-audit-1-actually-enables-audit-for-pid-1.patch
From: Len Brown <len.brown(a)intel.com>
Linux-4.10 added X86_FEATURE_TSC_KNOWN_FREQ.
commit 4ca4df0b7eb0
("x86/tsc: Mark TSC frequency determined by CPUID as known")
When it is set, run-time refined TSC calibration is disabled.
But native_calibrate_tsc() sets it on all systems with CPUID.15,
even if crystal_khz can not be discovered via CPUID.15 or via
built-in table. eg. When a new Intel processor comes out
that does not return CPUID.15.crystal_khz, and does not have
its model# and crystal_khz listed in native_calibate_tsc().
This results in (tsc_khz = cpu_khz) and TSC refined calibration
disabled. But for machines with the TSC and CPU in different clock
domains (and those support CPUID.15), almost all such configurations
will experience measurable negative timeofday clock drift.
Signed-off-by: Len Brown <len.brown(a)intel.com>
Cc: Bin Gao <bin.gao(a)intel.com>
Cc: <stable(a)vger.kernel.org> # v4.10+
---
arch/x86/kernel/tsc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 8ea117f8142e..49d772672367 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -609,6 +609,8 @@ unsigned long native_calibrate_tsc(void)
case INTEL_FAM6_ATOM_GOLDMONT:
crystal_khz = 19200; /* 19.2 MHz */
break;
+ default:
+ return 0; /* no X86_FEATURE_TSC_KNOWN_FREQ */
}
}
--
2.14.0-rc0
From: Michal Hocko <mhocko(a)suse.com>
Subject: mm, oom_reaper: fix memory corruption
David Rientjes has reported the following memory corruption while the oom
reaper tries to unmap the victims address space
BUG: Bad page map in process oom_reaper pte:6353826300000000 pmd:00000000
addr:00007f50cab1d000 vm_flags:08100073 anon_vma:ffff9eea335603f0 mapping: (null) index:7f50cab1d
file: (null) fault: (null) mmap: (null) readpage: (null)
CPU: 2 PID: 1001 Comm: oom_reaper
Call Trace:
[<ffffffffa4bd967d>] dump_stack+0x4d/0x70
[<ffffffffa4a03558>] unmap_page_range+0x1068/0x1130
[<ffffffffa4a2e07f>] __oom_reap_task_mm+0xd5/0x16b
[<ffffffffa4a2e226>] oom_reaper+0xff/0x14c
[<ffffffffa48d6ad1>] kthread+0xc1/0xe0
Tetsuo Handa has noticed that the synchronization inside exit_mmap is
insufficient. We only synchronize with the oom reaper if
tsk_is_oom_victim which is not true if the final __mmput is called from a
different context than the oom victim exit path. This can trivially
happen from context of any task which has grabbed mm reference (e.g. to
read /proc/<pid>/ file which requires mm etc.). The race would look like
this
oom_reaper oom_victim task
mmget_not_zero
do_exit
mmput
__oom_reap_task_mm mmput
__mmput
exit_mmap
remove_vma
unmap_page_range
Fix this issue by providing a new mm_is_oom_victim() helper which operates
on the mm struct rather than a task. Any context which operates on a
remote mm struct should use this helper in place of tsk_is_oom_victim.
The flag is set in mark_oom_victim and never cleared so it is stable in
the exit_mmap path.
Debugged by Tetsuo Handa.
Link: http://lkml.kernel.org/r/20171210095130.17110-1-mhocko@kernel.org
Fixes: 212925802454 ("mm: oom: let oom_reap_task and exit_mmap run concurrently")
Signed-off-by: Michal Hocko <mhocko(a)suse.com>
Reported-by: David Rientjes <rientjes(a)google.com>
Acked-by: David Rientjes <rientjes(a)google.com>
Cc: Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp>
Cc: Andrea Argangeli <andrea(a)kernel.org>
Cc: <stable(a)vger.kernel.org> [4.14]
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
---
include/linux/oom.h | 9 +++++++++
include/linux/sched/coredump.h | 1 +
mm/mmap.c | 10 +++++-----
mm/oom_kill.c | 4 +++-
4 files changed, 18 insertions(+), 6 deletions(-)
diff -puN include/linux/oom.h~mm-oom_reaper-fix-memory-corruption include/linux/oom.h
--- a/include/linux/oom.h~mm-oom_reaper-fix-memory-corruption
+++ a/include/linux/oom.h
@@ -67,6 +67,15 @@ static inline bool tsk_is_oom_victim(str
}
/*
+ * Use this helper if tsk->mm != mm and the victim mm needs a special
+ * handling. This is guaranteed to stay true after once set.
+ */
+static inline bool mm_is_oom_victim(struct mm_struct *mm)
+{
+ return test_bit(MMF_OOM_VICTIM, &mm->flags);
+}
+
+/*
* Checks whether a page fault on the given mm is still reliable.
* This is no longer true if the oom reaper started to reap the
* address space which is reflected by MMF_UNSTABLE flag set in
diff -puN include/linux/sched/coredump.h~mm-oom_reaper-fix-memory-corruption include/linux/sched/coredump.h
--- a/include/linux/sched/coredump.h~mm-oom_reaper-fix-memory-corruption
+++ a/include/linux/sched/coredump.h
@@ -70,6 +70,7 @@ static inline int get_dumpable(struct mm
#define MMF_UNSTABLE 22 /* mm is unstable for copy_from_user */
#define MMF_HUGE_ZERO_PAGE 23 /* mm has ever used the global huge zero page */
#define MMF_DISABLE_THP 24 /* disable THP for all VMAs */
+#define MMF_OOM_VICTIM 25 /* mm is the oom victim */
#define MMF_DISABLE_THP_MASK (1 << MMF_DISABLE_THP)
#define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
diff -puN mm/mmap.c~mm-oom_reaper-fix-memory-corruption mm/mmap.c
--- a/mm/mmap.c~mm-oom_reaper-fix-memory-corruption
+++ a/mm/mmap.c
@@ -3019,20 +3019,20 @@ void exit_mmap(struct mm_struct *mm)
/* Use -1 here to ensure all VMAs in the mm are unmapped */
unmap_vmas(&tlb, vma, 0, -1);
- set_bit(MMF_OOM_SKIP, &mm->flags);
- if (unlikely(tsk_is_oom_victim(current))) {
+ if (unlikely(mm_is_oom_victim(mm))) {
/*
* Wait for oom_reap_task() to stop working on this
* mm. Because MMF_OOM_SKIP is already set before
* calling down_read(), oom_reap_task() will not run
* on this "mm" post up_write().
*
- * tsk_is_oom_victim() cannot be set from under us
- * either because current->mm is already set to NULL
+ * mm_is_oom_victim() cannot be set from under us
+ * either because victim->mm is already set to NULL
* under task_lock before calling mmput and oom_mm is
- * set not NULL by the OOM killer only if current->mm
+ * set not NULL by the OOM killer only if victim->mm
* is found not NULL while holding the task_lock.
*/
+ set_bit(MMF_OOM_SKIP, &mm->flags);
down_write(&mm->mmap_sem);
up_write(&mm->mmap_sem);
}
diff -puN mm/oom_kill.c~mm-oom_reaper-fix-memory-corruption mm/oom_kill.c
--- a/mm/oom_kill.c~mm-oom_reaper-fix-memory-corruption
+++ a/mm/oom_kill.c
@@ -683,8 +683,10 @@ static void mark_oom_victim(struct task_
return;
/* oom_mm is bound to the signal struct life time. */
- if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm))
+ if (!cmpxchg(&tsk->signal->oom_mm, NULL, mm)) {
mmgrab(tsk->signal->oom_mm);
+ set_bit(MMF_OOM_VICTIM, &mm->flags);
+ }
/*
* Make sure that the task is woken up from uninterruptible sleep
_
From: Arnd Bergmann <arnd(a)arndb.de>
Subject: string.h: workaround for increased stack usage
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(a)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(a)arndb.de>
Cc: Kees Cook <keescook(a)chromium.org>
Cc: Mauro Carvalho Chehab <mchehab(a)kernel.org>
Cc: Dmitry Vyukov <dvyukov(a)google.com>
Cc: Alexander Potapenko <glider(a)google.com>
Cc: Andrey Ryabinin <aryabinin(a)virtuozzo.com>
Cc: Daniel Micay <danielmicay(a)gmail.com>
Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Cc: Martin Wilck <mwilck(a)suse.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Cc: <stable(a)vger.kernel.org>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
---
include/linux/string.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff -puN include/linux/string.h~stringh-work-around-for-increased-stack-usage include/linux/string.h
--- a/include/linux/string.h~stringh-work-around-for-increased-stack-usage
+++ a/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)
_