Merge branch 'akpm' (patches from Andrew)

Merge misc updates from Andrew Morton:

 - kasan updates

 - procfs

 - lib/bitmap updates

 - other lib/ updates

 - checkpatch tweaks

 - rapidio

 - ubsan

 - pipe fixes and cleanups

 - lots of other misc bits

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (114 commits)
  Documentation/sysctl/user.txt: fix typo
  MAINTAINERS: update ARM/QUALCOMM SUPPORT patterns
  MAINTAINERS: update various PALM patterns
  MAINTAINERS: update "ARM/OXNAS platform support" patterns
  MAINTAINERS: update Cortina/Gemini patterns
  MAINTAINERS: remove ARM/CLKDEV SUPPORT file pattern
  MAINTAINERS: remove ANDROID ION pattern
  mm: docs: add blank lines to silence sphinx "Unexpected indentation" errors
  mm: docs: fix parameter names mismatch
  mm: docs: fixup punctuation
  pipe: read buffer limits atomically
  pipe: simplify round_pipe_size()
  pipe: reject F_SETPIPE_SZ with size over UINT_MAX
  pipe: fix off-by-one error when checking buffer limits
  pipe: actually allow root to exceed the pipe buffer limits
  pipe, sysctl: remove pipe_proc_fn()
  pipe, sysctl: drop 'min' parameter from pipe-max-size converter
  kasan: rework Kconfig settings
  crash_dump: is_kdump_kernel can be boolean
  kernel/mutex: mutex_is_locked can be boolean
  ...
This commit is contained in:
Linus Torvalds 2018-02-06 22:15:42 -08:00
commit a2e5790d84
134 changed files with 1425 additions and 1078 deletions

View File

@ -3,7 +3,7 @@ Documentation for /proc/sys/user/* kernel version 4.9.0
============================================================== ==============================================================
This file contains the documetation for the sysctl files in This file contains the documentation for the sysctl files in
/proc/sys/user. /proc/sys/user.
The files in this directory can be used to override the default The files in this directory can be used to override the default

View File

@ -903,7 +903,6 @@ L: devel@driverdev.osuosl.org
S: Supported S: Supported
F: drivers/staging/android/ion F: drivers/staging/android/ion
F: drivers/staging/android/uapi/ion.h F: drivers/staging/android/uapi/ion.h
F: drivers/staging/android/uapi/ion_test.h
AOA (Apple Onboard Audio) ALSA DRIVER AOA (Apple Onboard Audio) ALSA DRIVER
M: Johannes Berg <johannes@sipsolutions.net> M: Johannes Berg <johannes@sipsolutions.net>
@ -1308,7 +1307,6 @@ M: Russell King <linux@armlinux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
T: git git://git.armlinux.org.uk/~rmk/linux-arm.git clkdev T: git git://git.armlinux.org.uk/~rmk/linux-arm.git clkdev
F: arch/arm/include/asm/clkdev.h
F: drivers/clk/clkdev.c F: drivers/clk/clkdev.c
ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT
@ -1360,7 +1358,7 @@ F: Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt
F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt
F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.txt F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.txt
F: arch/arm/mach-gemini/ F: arch/arm/mach-gemini/
F: drivers/net/ethernet/cortina/gemini/* F: drivers/net/ethernet/cortina/
F: drivers/pinctrl/pinctrl-gemini.c F: drivers/pinctrl/pinctrl-gemini.c
F: drivers/rtc/rtc-ftrtc010.c F: drivers/rtc/rtc-ftrtc010.c
@ -1737,9 +1735,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-oxnas@lists.tuxfamily.org (moderated for non-subscribers) L: linux-oxnas@lists.tuxfamily.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-oxnas/ F: arch/arm/mach-oxnas/
F: arch/arm/boot/dts/ox8*.dtsi F: arch/arm/boot/dts/ox8*.dts*
F: arch/arm/boot/dts/wd-mbwe.dts
F: arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts
N: oxnas N: oxnas
ARM/PALM TREO SUPPORT ARM/PALM TREO SUPPORT
@ -1747,8 +1743,7 @@ M: Tomas Cech <sleep_walker@suse.com>
L: linux-arm-kernel@lists.infradead.org L: linux-arm-kernel@lists.infradead.org
W: http://hackndev.com W: http://hackndev.com
S: Maintained S: Maintained
F: arch/arm/mach-pxa/include/mach/palmtreo.h F: arch/arm/mach-pxa/palmtreo.*
F: arch/arm/mach-pxa/palmtreo.c
ARM/PALMTX,PALMT5,PALMLD,PALMTE2,PALMTC SUPPORT ARM/PALMTX,PALMT5,PALMLD,PALMTE2,PALMTC SUPPORT
M: Marek Vasut <marek.vasut@gmail.com> M: Marek Vasut <marek.vasut@gmail.com>
@ -1757,12 +1752,10 @@ W: http://hackndev.com
S: Maintained S: Maintained
F: arch/arm/mach-pxa/include/mach/palmtx.h F: arch/arm/mach-pxa/include/mach/palmtx.h
F: arch/arm/mach-pxa/palmtx.c F: arch/arm/mach-pxa/palmtx.c
F: arch/arm/mach-pxa/include/mach/palmt5.h F: arch/arm/mach-pxa/palmt5.*
F: arch/arm/mach-pxa/palmt5.c
F: arch/arm/mach-pxa/include/mach/palmld.h F: arch/arm/mach-pxa/include/mach/palmld.h
F: arch/arm/mach-pxa/palmld.c F: arch/arm/mach-pxa/palmld.c
F: arch/arm/mach-pxa/include/mach/palmte2.h F: arch/arm/mach-pxa/palmte2.*
F: arch/arm/mach-pxa/palmte2.c
F: arch/arm/mach-pxa/include/mach/palmtc.h F: arch/arm/mach-pxa/include/mach/palmtc.h
F: arch/arm/mach-pxa/palmtc.c F: arch/arm/mach-pxa/palmtc.c
@ -1771,8 +1764,7 @@ M: Sergey Lapin <slapin@ossfans.org>
L: linux-arm-kernel@lists.infradead.org L: linux-arm-kernel@lists.infradead.org
W: http://hackndev.com W: http://hackndev.com
S: Maintained S: Maintained
F: arch/arm/mach-pxa/include/mach/palmz72.h F: arch/arm/mach-pxa/palmz72.*
F: arch/arm/mach-pxa/palmz72.c
ARM/PLEB SUPPORT ARM/PLEB SUPPORT
M: Peter Chubb <pleb@gelato.unsw.edu.au> M: Peter Chubb <pleb@gelato.unsw.edu.au>
@ -1801,7 +1793,6 @@ F: drivers/clk/qcom/
F: drivers/dma/qcom/ F: drivers/dma/qcom/
F: drivers/soc/qcom/ F: drivers/soc/qcom/
F: drivers/spi/spi-qup.c F: drivers/spi/spi-qup.c
F: drivers/tty/serial/msm_serial.h
F: drivers/tty/serial/msm_serial.c F: drivers/tty/serial/msm_serial.c
F: drivers/*/pm8???-* F: drivers/*/pm8???-*
F: drivers/mfd/ssbi.c F: drivers/mfd/ssbi.c
@ -3567,7 +3558,7 @@ F: drivers/media/platform/coda/
COMMON CLK FRAMEWORK COMMON CLK FRAMEWORK
M: Michael Turquette <mturquette@baylibre.com> M: Michael Turquette <mturquette@baylibre.com>
M: Stephen Boyd <sboyd@codeaurora.org> M: Stephen Boyd <sboyd@kernel.org>
L: linux-clk@vger.kernel.org L: linux-clk@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-clk/list/ Q: http://patchwork.kernel.org/project/linux-clk/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
@ -10284,7 +10275,7 @@ F: include/uapi/linux/openvswitch.h
OPERATING PERFORMANCE POINTS (OPP) OPERATING PERFORMANCE POINTS (OPP)
M: Viresh Kumar <vireshk@kernel.org> M: Viresh Kumar <vireshk@kernel.org>
M: Nishanth Menon <nm@ti.com> M: Nishanth Menon <nm@ti.com>
M: Stephen Boyd <sboyd@codeaurora.org> M: Stephen Boyd <sboyd@kernel.org>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git
@ -13020,7 +13011,7 @@ F: Documentation/networking/spider_net.txt
F: drivers/net/ethernet/toshiba/spider_net* F: drivers/net/ethernet/toshiba/spider_net*
SPMI SUBSYSTEM SPMI SUBSYSTEM
R: Stephen Boyd <sboyd@codeaurora.org> R: Stephen Boyd <sboyd@kernel.org>
L: linux-arm-msm@vger.kernel.org L: linux-arm-msm@vger.kernel.org
F: Documentation/devicetree/bindings/spmi/ F: Documentation/devicetree/bindings/spmi/
F: drivers/spmi/ F: drivers/spmi/
@ -13905,7 +13896,7 @@ F: include/linux/usb/tilegx.h
TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
M: John Stultz <john.stultz@linaro.org> M: John Stultz <john.stultz@linaro.org>
M: Thomas Gleixner <tglx@linutronix.de> M: Thomas Gleixner <tglx@linutronix.de>
R: Stephen Boyd <sboyd@codeaurora.org> R: Stephen Boyd <sboyd@kernel.org>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
S: Supported S: Supported

View File

@ -434,7 +434,8 @@ export MAKE LEX YACC AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_KASAN CFLAGS_UBSAN export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE CFLAGS_UBSAN
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
@ -679,6 +680,10 @@ endif
# This selects the stack protector compiler flag. Testing it is delayed # This selects the stack protector compiler flag. Testing it is delayed
# until after .config has been reprocessed, in the prepare-compiler-check # until after .config has been reprocessed, in the prepare-compiler-check
# target. # target.
ifdef CONFIG_CC_STACKPROTECTOR_AUTO
stackp-flag := $(call cc-option,-fstack-protector-strong,$(call cc-option,-fstack-protector))
stackp-name := AUTO
else
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
stackp-flag := -fstack-protector stackp-flag := -fstack-protector
stackp-name := REGULAR stackp-name := REGULAR
@ -687,16 +692,40 @@ ifdef CONFIG_CC_STACKPROTECTOR_STRONG
stackp-flag := -fstack-protector-strong stackp-flag := -fstack-protector-strong
stackp-name := STRONG stackp-name := STRONG
else else
# If either there is no stack protector for this architecture or
# CONFIG_CC_STACKPROTECTOR_NONE is selected, we're done, and $(stackp-name)
# is empty, skipping all remaining stack protector tests.
#
# Force off for distro compilers that enable stack protector by default. # Force off for distro compilers that enable stack protector by default.
stackp-flag := $(call cc-option, -fno-stack-protector) KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
endif
endif endif
endif endif
# Find arch-specific stack protector compiler sanity-checking script. # Find arch-specific stack protector compiler sanity-checking script.
ifdef CONFIG_CC_STACKPROTECTOR ifdef stackp-name
ifneq ($(stackp-flag),)
stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh
stackp-check := $(wildcard $(stackp-path)) stackp-check := $(wildcard $(stackp-path))
# If the wildcard test matches a test script, run it to check functionality.
ifdef stackp-check
ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
stackp-broken := y
endif
endif
ifndef stackp-broken
# If the stack protector is functional, enable code that depends on it.
KBUILD_CPPFLAGS += -DCONFIG_CC_STACKPROTECTOR
# Either we've already detected the flag (for AUTO) or we'll fail the
# build in the prepare-compiler-check rule (for specific flag).
KBUILD_CFLAGS += $(stackp-flag)
else
# We have to make sure stack protector is unconditionally disabled if
# the compiler is broken (in case we're going to continue the build in
# AUTO mode).
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
endif
endif
endif endif
KBUILD_CFLAGS += $(stackp-flag)
ifeq ($(cc-name),clang) ifeq ($(cc-name),clang)
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
@ -1091,14 +1120,25 @@ PHONY += prepare-compiler-check
prepare-compiler-check: FORCE prepare-compiler-check: FORCE
# Make sure compiler supports requested stack protector flag. # Make sure compiler supports requested stack protector flag.
ifdef stackp-name ifdef stackp-name
# Warn about CONFIG_CC_STACKPROTECTOR_AUTO having found no option.
ifeq ($(stackp-flag),)
@echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
Compiler does not support any known stack-protector >&2
else
# Fail if specifically requested stack protector is missing.
ifeq ($(call cc-option, $(stackp-flag)),) ifeq ($(call cc-option, $(stackp-flag)),)
@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \ @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
$(stackp-flag) not supported by compiler >&2 && exit 1 $(stackp-flag) not supported by compiler >&2 && exit 1
endif endif
endif
endif endif
# Make sure compiler does not have buggy stack-protector support. # Make sure compiler does not have buggy stack-protector support. If a
ifdef stackp-check # specific stack-protector was requested, fail the build, otherwise warn.
ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y) ifdef stackp-broken
ifeq ($(stackp-name),AUTO)
@echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
$(stackp-flag) available but compiler is broken: disabling >&2
else
@echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \ @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
$(stackp-flag) available but compiler is broken >&2 && exit 1 $(stackp-flag) available but compiler is broken >&2 && exit 1
endif endif

View File

@ -538,16 +538,10 @@ config HAVE_CC_STACKPROTECTOR
- its compiler supports the -fstack-protector option - its compiler supports the -fstack-protector option
- it has implemented a stack canary (e.g. __stack_chk_guard) - it has implemented a stack canary (e.g. __stack_chk_guard)
config CC_STACKPROTECTOR
def_bool n
help
Set when a stack-protector mode is enabled, so that the build
can enable kernel-side support for the GCC feature.
choice choice
prompt "Stack Protector buffer overflow detection" prompt "Stack Protector buffer overflow detection"
depends on HAVE_CC_STACKPROTECTOR depends on HAVE_CC_STACKPROTECTOR
default CC_STACKPROTECTOR_NONE default CC_STACKPROTECTOR_AUTO
help help
This option turns on the "stack-protector" GCC feature. This This option turns on the "stack-protector" GCC feature. This
feature puts, at the beginning of functions, a canary value on feature puts, at the beginning of functions, a canary value on
@ -564,7 +558,6 @@ config CC_STACKPROTECTOR_NONE
config CC_STACKPROTECTOR_REGULAR config CC_STACKPROTECTOR_REGULAR
bool "Regular" bool "Regular"
select CC_STACKPROTECTOR
help help
Functions will have the stack-protector canary logic added if they Functions will have the stack-protector canary logic added if they
have an 8-byte or larger character array on the stack. have an 8-byte or larger character array on the stack.
@ -578,7 +571,6 @@ config CC_STACKPROTECTOR_REGULAR
config CC_STACKPROTECTOR_STRONG config CC_STACKPROTECTOR_STRONG
bool "Strong" bool "Strong"
select CC_STACKPROTECTOR
help help
Functions will have the stack-protector canary logic added in any Functions will have the stack-protector canary logic added in any
of the following conditions: of the following conditions:
@ -596,6 +588,12 @@ config CC_STACKPROTECTOR_STRONG
about 20% of all kernel functions, which increases the kernel code about 20% of all kernel functions, which increases the kernel code
size by about 2%. size by about 2%.
config CC_STACKPROTECTOR_AUTO
bool "Automatic"
help
If the compiler supports it, the best available stack-protector
option will be chosen.
endchoice endchoice
config THIN_ARCHIVES config THIN_ARCHIVES

View File

@ -338,6 +338,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset)
#endif #endif
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/le.h> #include <asm-generic/bitops/le.h>
/* /*

View File

@ -12,7 +12,8 @@
/* /*
* KASAN_SHADOW_START: beginning of the kernel virtual addresses. * KASAN_SHADOW_START: beginning of the kernel virtual addresses.
* KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses. * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/N of kernel virtual addresses,
* where N = (1 << KASAN_SHADOW_SCALE_SHIFT).
*/ */
#define KASAN_SHADOW_START (VA_START) #define KASAN_SHADOW_START (VA_START)
#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE) #define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
@ -20,14 +21,16 @@
/* /*
* This value is used to map an address to the corresponding shadow * This value is used to map an address to the corresponding shadow
* address by the following formula: * address by the following formula:
* shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET; * shadow_addr = (address >> KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET
* *
* (1 << 61) shadow addresses - [KASAN_SHADOW_OFFSET,KASAN_SHADOW_END] * (1 << (64 - KASAN_SHADOW_SCALE_SHIFT)) shadow addresses that lie in range
* cover all 64-bits of virtual addresses. So KASAN_SHADOW_OFFSET * [KASAN_SHADOW_OFFSET, KASAN_SHADOW_END) cover all 64-bits of virtual
* should satisfy the following equation: * addresses. So KASAN_SHADOW_OFFSET should satisfy the following equation:
* KASAN_SHADOW_OFFSET = KASAN_SHADOW_END - (1ULL << 61) * KASAN_SHADOW_OFFSET = KASAN_SHADOW_END -
* (1ULL << (64 - KASAN_SHADOW_SCALE_SHIFT))
*/ */
#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << (64 - 3))) #define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << \
(64 - KASAN_SHADOW_SCALE_SHIFT)))
void kasan_init(void); void kasan_init(void);
void kasan_copy_shadow(pgd_t *pgdir); void kasan_copy_shadow(pgd_t *pgdir);

View File

@ -85,7 +85,8 @@
* stack size when KASAN is in use. * stack size when KASAN is in use.
*/ */
#ifdef CONFIG_KASAN #ifdef CONFIG_KASAN
#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - 3)) #define KASAN_SHADOW_SCALE_SHIFT 3
#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT))
#define KASAN_THREAD_SHIFT 1 #define KASAN_THREAD_SHIFT 1
#else #else
#define KASAN_SHADOW_SIZE (0) #define KASAN_SHADOW_SIZE (0)

View File

@ -925,9 +925,8 @@ static void __armv8pmu_probe_pmu(void *info)
pmceid[0] = read_sysreg(pmceid0_el0); pmceid[0] = read_sysreg(pmceid0_el0);
pmceid[1] = read_sysreg(pmceid1_el0); pmceid[1] = read_sysreg(pmceid1_el0);
bitmap_from_u32array(cpu_pmu->pmceid_bitmap, bitmap_from_arr32(cpu_pmu->pmceid_bitmap,
ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid, pmceid, ARMV8_PMUV3_MAX_COMMON_EVENTS);
ARRAY_SIZE(pmceid));
} }
static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu) static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)

View File

@ -135,7 +135,8 @@ static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
/* The early shadow maps everything to a single page of zeroes */ /* The early shadow maps everything to a single page of zeroes */
asmlinkage void __init kasan_early_init(void) asmlinkage void __init kasan_early_init(void)
{ {
BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_END - (1UL << 61)); BUILD_BUG_ON(KASAN_SHADOW_OFFSET !=
KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT)));
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE));
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE));
kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE, kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE,

View File

@ -2610,17 +2610,10 @@ pfm_get_task(pfm_context_t *ctx, pid_t pid, struct task_struct **task)
if (pid < 2) return -EPERM; if (pid < 2) return -EPERM;
if (pid != task_pid_vnr(current)) { if (pid != task_pid_vnr(current)) {
read_lock(&tasklist_lock);
p = find_task_by_vpid(pid);
/* make sure task cannot go away while we operate on it */ /* make sure task cannot go away while we operate on it */
if (p) get_task_struct(p); p = find_get_task_by_vpid(pid);
if (!p)
read_unlock(&tasklist_lock); return -ESRCH;
if (p == NULL) return -ESRCH;
} }
ret = pfm_task_incompatible(ctx, p); ret = pfm_task_incompatible(ctx, p);

View File

@ -311,7 +311,6 @@ static inline int bfchg_mem_test_and_change_bit(int nr,
* functions. * functions.
*/ */
#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) #if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffz.h> #include <asm-generic/bitops/ffz.h>
#else #else
@ -441,6 +440,8 @@ static inline unsigned long ffz(unsigned long word)
#endif #endif
#include <asm-generic/bitops/find.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) #if defined(CONFIG_CPU_HAS_NO_BITFIELDS)

View File

@ -124,9 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
{ {
unsigned long n = (unsigned long) v - 1; unsigned long n = (unsigned long) v - 1;
seq_printf(m, "processor\t\t: %ld\n", n); seq_printf(m, "processor\t\t: %ld\n\n", n);
seq_printf(m, "\n");
return 0; return 0;
} }

View File

@ -44,4 +44,6 @@ static inline int fls(int x)
#define find_first_bit find_first_bit #define find_first_bit find_first_bit
#define find_first_zero_bit find_first_zero_bit #define find_first_zero_bit find_first_zero_bit
#include <asm-generic/bitops/find.h>
#endif /* __UNICORE_BITOPS_H__ */ #endif /* __UNICORE_BITOPS_H__ */

View File

@ -324,7 +324,7 @@ config X86_64_SMP
config X86_32_LAZY_GS config X86_32_LAZY_GS
def_bool y def_bool y
depends on X86_32 && !CC_STACKPROTECTOR depends on X86_32 && CC_STACKPROTECTOR_NONE
config ARCH_SUPPORTS_UPROBES config ARCH_SUPPORTS_UPROBES
def_bool y def_bool y

View File

@ -4,6 +4,7 @@
#include <linux/const.h> #include <linux/const.h>
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL) #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
#define KASAN_SHADOW_SCALE_SHIFT 3
/* /*
* Compiler uses shadow offset assuming that addresses start * Compiler uses shadow offset assuming that addresses start
@ -12,12 +13,15 @@
* 'kernel address space start' >> KASAN_SHADOW_SCALE_SHIFT * 'kernel address space start' >> KASAN_SHADOW_SCALE_SHIFT
*/ */
#define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET + \ #define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET + \
((-1UL << __VIRTUAL_MASK_SHIFT) >> 3)) ((-1UL << __VIRTUAL_MASK_SHIFT) >> \
KASAN_SHADOW_SCALE_SHIFT))
/* /*
* 47 bits for kernel address -> (47 - 3) bits for shadow * 47 bits for kernel address -> (47 - KASAN_SHADOW_SCALE_SHIFT) bits for shadow
* 56 bits for kernel address -> (56 - 3) bits for shadow * 56 bits for kernel address -> (56 - KASAN_SHADOW_SCALE_SHIFT) bits for shadow
*/ */
#define KASAN_SHADOW_END (KASAN_SHADOW_START + (1ULL << (__VIRTUAL_MASK_SHIFT - 3))) #define KASAN_SHADOW_END (KASAN_SHADOW_START + \
(1ULL << (__VIRTUAL_MASK_SHIFT - \
KASAN_SHADOW_SCALE_SHIFT)))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__

View File

@ -658,10 +658,8 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
return; return;
cpmceid[0] = __dsu_pmu_read_pmceid(0); cpmceid[0] = __dsu_pmu_read_pmceid(0);
cpmceid[1] = __dsu_pmu_read_pmceid(1); cpmceid[1] = __dsu_pmu_read_pmceid(1);
bitmap_from_u32array(dsu_pmu->cpmceid_bitmap, bitmap_from_arr32(dsu_pmu->cpmceid_bitmap, cpmceid,
DSU_PMU_MAX_COMMON_EVENTS, DSU_PMU_MAX_COMMON_EVENTS);
cpmceid,
ARRAY_SIZE(cpmceid));
} }
static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu) static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu)

View File

@ -70,7 +70,7 @@ static long hrtimer_error = SAFETY_INTERVAL;
/* the kernel hrtimer event */ /* the kernel hrtimer event */
static enum hrtimer_restart hrtimer_event(struct hrtimer *timer) static enum hrtimer_restart hrtimer_event(struct hrtimer *timer)
{ {
struct timespec expire_time, ts1, ts2, ts3, dts; struct timespec64 expire_time, ts1, ts2, ts3, dts;
struct pps_generator_pp *dev; struct pps_generator_pp *dev;
struct parport *port; struct parport *port;
long lim, delta; long lim, delta;
@ -78,7 +78,7 @@ static enum hrtimer_restart hrtimer_event(struct hrtimer *timer)
/* We have to disable interrupts here. The idea is to prevent /* We have to disable interrupts here. The idea is to prevent
* other interrupts on the same processor to introduce random * other interrupts on the same processor to introduce random
* lags while polling the clock. getnstimeofday() takes <1us on * lags while polling the clock. ktime_get_real_ts64() takes <1us on
* most machines while other interrupt handlers can take much * most machines while other interrupt handlers can take much
* more potentially. * more potentially.
* *
@ -88,22 +88,22 @@ static enum hrtimer_restart hrtimer_event(struct hrtimer *timer)
local_irq_save(flags); local_irq_save(flags);
/* first of all we get the time stamp... */ /* first of all we get the time stamp... */
getnstimeofday(&ts1); ktime_get_real_ts64(&ts1);
expire_time = ktime_to_timespec(hrtimer_get_softexpires(timer)); expire_time = ktime_to_timespec64(hrtimer_get_softexpires(timer));
dev = container_of(timer, struct pps_generator_pp, timer); dev = container_of(timer, struct pps_generator_pp, timer);
lim = NSEC_PER_SEC - send_delay - dev->port_write_time; lim = NSEC_PER_SEC - send_delay - dev->port_write_time;
/* check if we are late */ /* check if we are late */
if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) { if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) {
local_irq_restore(flags); local_irq_restore(flags);
pr_err("we are late this time %ld.%09ld\n", pr_err("we are late this time %lld.%09ld\n",
ts1.tv_sec, ts1.tv_nsec); (s64)ts1.tv_sec, ts1.tv_nsec);
goto done; goto done;
} }
/* busy loop until the time is right for an assert edge */ /* busy loop until the time is right for an assert edge */
do { do {
getnstimeofday(&ts2); ktime_get_real_ts64(&ts2);
} while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim);
/* set the signal */ /* set the signal */
@ -113,25 +113,25 @@ static enum hrtimer_restart hrtimer_event(struct hrtimer *timer)
/* busy loop until the time is right for a clear edge */ /* busy loop until the time is right for a clear edge */
lim = NSEC_PER_SEC - dev->port_write_time; lim = NSEC_PER_SEC - dev->port_write_time;
do { do {
getnstimeofday(&ts2); ktime_get_real_ts64(&ts2);
} while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim);
/* unset the signal */ /* unset the signal */
port->ops->write_control(port, NO_SIGNAL); port->ops->write_control(port, NO_SIGNAL);
getnstimeofday(&ts3); ktime_get_real_ts64(&ts3);
local_irq_restore(flags); local_irq_restore(flags);
/* update calibrated port write time */ /* update calibrated port write time */
dts = timespec_sub(ts3, ts2); dts = timespec64_sub(ts3, ts2);
dev->port_write_time = dev->port_write_time =
(dev->port_write_time + timespec_to_ns(&dts)) >> 1; (dev->port_write_time + timespec64_to_ns(&dts)) >> 1;
done: done:
/* update calibrated hrtimer error */ /* update calibrated hrtimer error */
dts = timespec_sub(ts1, expire_time); dts = timespec64_sub(ts1, expire_time);
delta = timespec_to_ns(&dts); delta = timespec64_to_ns(&dts);
/* If the new error value is bigger then the old, use the new /* If the new error value is bigger then the old, use the new
* value, if not then slowly move towards the new value. This * value, if not then slowly move towards the new value. This
* way it should be safe in bad conditions and efficient in * way it should be safe in bad conditions and efficient in
@ -161,17 +161,17 @@ static void calibrate_port(struct pps_generator_pp *dev)
long acc = 0; long acc = 0;
for (i = 0; i < (1 << PORT_NTESTS_SHIFT); i++) { for (i = 0; i < (1 << PORT_NTESTS_SHIFT); i++) {
struct timespec a, b; struct timespec64 a, b;
unsigned long irq_flags; unsigned long irq_flags;
local_irq_save(irq_flags); local_irq_save(irq_flags);
getnstimeofday(&a); ktime_get_real_ts64(&a);
port->ops->write_control(port, NO_SIGNAL); port->ops->write_control(port, NO_SIGNAL);
getnstimeofday(&b); ktime_get_real_ts64(&b);
local_irq_restore(irq_flags); local_irq_restore(irq_flags);
b = timespec_sub(b, a); b = timespec64_sub(b, a);
acc += timespec_to_ns(&b); acc += timespec64_to_ns(&b);
} }
dev->port_write_time = acc >> PORT_NTESTS_SHIFT; dev->port_write_time = acc >> PORT_NTESTS_SHIFT;
@ -180,9 +180,9 @@ static void calibrate_port(struct pps_generator_pp *dev)
static inline ktime_t next_intr_time(struct pps_generator_pp *dev) static inline ktime_t next_intr_time(struct pps_generator_pp *dev)
{ {
struct timespec ts; struct timespec64 ts;
getnstimeofday(&ts); ktime_get_real_ts64(&ts);
return ktime_set(ts.tv_sec + return ktime_set(ts.tv_sec +
((ts.tv_nsec > 990 * NSEC_PER_MSEC) ? 1 : 0), ((ts.tv_nsec > 990 * NSEC_PER_MSEC) ? 1 : 0),

View File

@ -222,7 +222,7 @@ static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan)
struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device); struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
#endif #endif
if (bdma_chan->bd_base == NULL) if (!bdma_chan->bd_base)
return 0; return 0;
/* Check if DMA channel still running */ /* Check if DMA channel still running */
@ -346,7 +346,7 @@ tsi721_desc_fill_init(struct tsi721_tx_desc *desc,
{ {
u64 rio_addr; u64 rio_addr;
if (bd_ptr == NULL) if (!bd_ptr)
return -EINVAL; return -EINVAL;
/* Initialize DMA descriptor */ /* Initialize DMA descriptor */
@ -370,7 +370,7 @@ tsi721_desc_fill_init(struct tsi721_tx_desc *desc,
static int static int
tsi721_desc_fill_end(struct tsi721_dma_desc *bd_ptr, u32 bcount, bool interrupt) tsi721_desc_fill_end(struct tsi721_dma_desc *bd_ptr, u32 bcount, bool interrupt)
{ {
if (bd_ptr == NULL) if (!bd_ptr)
return -EINVAL; return -EINVAL;
/* Update DMA descriptor */ /* Update DMA descriptor */
@ -555,9 +555,7 @@ static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan,
* If there is no data transfer in progress, fetch new descriptor from * If there is no data transfer in progress, fetch new descriptor from
* the pending queue. * the pending queue.
*/ */
if (!desc && !bdma_chan->active_tx && !list_empty(&bdma_chan->queue)) {
if (desc == NULL && bdma_chan->active_tx == NULL &&
!list_empty(&bdma_chan->queue)) {
desc = list_first_entry(&bdma_chan->queue, desc = list_first_entry(&bdma_chan->queue,
struct tsi721_tx_desc, desc_node); struct tsi721_tx_desc, desc_node);
list_del_init((&desc->desc_node)); list_del_init((&desc->desc_node));
@ -735,7 +733,7 @@ static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd)
static int tsi721_alloc_chan_resources(struct dma_chan *dchan) static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
{ {
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
struct tsi721_tx_desc *desc = NULL; struct tsi721_tx_desc *desc;
int i; int i;
tsi_debug(DMA, &dchan->dev->device, "DMAC%d", bdma_chan->id); tsi_debug(DMA, &dchan->dev->device, "DMAC%d", bdma_chan->id);
@ -754,9 +752,6 @@ static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
desc = kcalloc(dma_txqueue_sz, sizeof(struct tsi721_tx_desc), desc = kcalloc(dma_txqueue_sz, sizeof(struct tsi721_tx_desc),
GFP_ATOMIC); GFP_ATOMIC);
if (!desc) { if (!desc) {
tsi_err(&dchan->dev->device,
"DMAC%d Failed to allocate logical descriptors",
bdma_chan->id);
tsi721_bdma_ch_free(bdma_chan); tsi721_bdma_ch_free(bdma_chan);
return -ENOMEM; return -ENOMEM;
} }
@ -799,7 +794,7 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan)
tsi_debug(DMA, &dchan->dev->device, "DMAC%d", bdma_chan->id); tsi_debug(DMA, &dchan->dev->device, "DMAC%d", bdma_chan->id);
if (bdma_chan->bd_base == NULL) if (!bdma_chan->bd_base)
return; return;
tsi721_bdma_interrupt_enable(bdma_chan, 0); tsi721_bdma_interrupt_enable(bdma_chan, 0);

View File

@ -81,6 +81,7 @@ u16 rio_local_get_device_id(struct rio_mport *port)
return (RIO_GET_DID(port->sys_size, result)); return (RIO_GET_DID(port->sys_size, result));
} }
EXPORT_SYMBOL_GPL(rio_local_get_device_id);
/** /**
* rio_query_mport - Query mport device attributes * rio_query_mport - Query mport device attributes
@ -110,9 +111,8 @@ EXPORT_SYMBOL(rio_query_mport);
*/ */
struct rio_net *rio_alloc_net(struct rio_mport *mport) struct rio_net *rio_alloc_net(struct rio_mport *mport)
{ {
struct rio_net *net; struct rio_net *net = kzalloc(sizeof(*net), GFP_KERNEL);
net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
if (net) { if (net) {
INIT_LIST_HEAD(&net->node); INIT_LIST_HEAD(&net->node);
INIT_LIST_HEAD(&net->devices); INIT_LIST_HEAD(&net->devices);
@ -243,18 +243,17 @@ int rio_request_inb_mbox(struct rio_mport *mport,
int rc = -ENOSYS; int rc = -ENOSYS;
struct resource *res; struct resource *res;
if (mport->ops->open_inb_mbox == NULL) if (!mport->ops->open_inb_mbox)
goto out; goto out;
res = kzalloc(sizeof(struct resource), GFP_KERNEL); res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) { if (res) {
rio_init_mbox_res(res, mbox, mbox); rio_init_mbox_res(res, mbox, mbox);
/* Make sure this mailbox isn't in use */ /* Make sure this mailbox isn't in use */
if ((rc = rc = request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE],
request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE], res);
res)) < 0) { if (rc < 0) {
kfree(res); kfree(res);
goto out; goto out;
} }
@ -277,6 +276,7 @@ int rio_request_inb_mbox(struct rio_mport *mport,
out: out:
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
/** /**
* rio_release_inb_mbox - release inbound mailbox message service * rio_release_inb_mbox - release inbound mailbox message service
@ -305,6 +305,7 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
/** /**
* rio_request_outb_mbox - request outbound mailbox service * rio_request_outb_mbox - request outbound mailbox service
@ -326,18 +327,17 @@ int rio_request_outb_mbox(struct rio_mport *mport,
int rc = -ENOSYS; int rc = -ENOSYS;
struct resource *res; struct resource *res;
if (mport->ops->open_outb_mbox == NULL) if (!mport->ops->open_outb_mbox)
goto out; goto out;
res = kzalloc(sizeof(struct resource), GFP_KERNEL); res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) { if (res) {
rio_init_mbox_res(res, mbox, mbox); rio_init_mbox_res(res, mbox, mbox);
/* Make sure this outbound mailbox isn't in use */ /* Make sure this outbound mailbox isn't in use */
if ((rc = rc = request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE],
request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE], res);
res)) < 0) { if (rc < 0) {
kfree(res); kfree(res);
goto out; goto out;
} }
@ -360,6 +360,7 @@ int rio_request_outb_mbox(struct rio_mport *mport,
out: out:
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
/** /**
* rio_release_outb_mbox - release outbound mailbox message service * rio_release_outb_mbox - release outbound mailbox message service
@ -388,6 +389,7 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
/** /**
* rio_setup_inb_dbell - bind inbound doorbell callback * rio_setup_inb_dbell - bind inbound doorbell callback
@ -405,13 +407,10 @@ rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res,
void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst,
u16 info)) u16 info))
{ {
int rc = 0; struct rio_dbell *dbell = kmalloc(sizeof(*dbell), GFP_KERNEL);
struct rio_dbell *dbell;
if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) { if (!dbell)
rc = -ENOMEM; return -ENOMEM;
goto out;
}
dbell->res = res; dbell->res = res;
dbell->dinb = dinb; dbell->dinb = dinb;
@ -420,9 +419,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res,
mutex_lock(&mport->lock); mutex_lock(&mport->lock);
list_add_tail(&dbell->node, &mport->dbells); list_add_tail(&dbell->node, &mport->dbells);
mutex_unlock(&mport->lock); mutex_unlock(&mport->lock);
return 0;
out:
return rc;
} }
/** /**
@ -444,17 +441,16 @@ int rio_request_inb_dbell(struct rio_mport *mport,
void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src,
u16 dst, u16 info)) u16 dst, u16 info))
{ {
int rc = 0; int rc;
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res) { if (res) {
rio_init_dbell_res(res, start, end); rio_init_dbell_res(res, start, end);
/* Make sure these doorbells aren't in use */ /* Make sure these doorbells aren't in use */
if ((rc = rc = request_resource(&mport->riores[RIO_DOORBELL_RESOURCE],
request_resource(&mport->riores[RIO_DOORBELL_RESOURCE], res);
res)) < 0) { if (rc < 0) {
kfree(res); kfree(res);
goto out; goto out;
} }
@ -467,6 +463,7 @@ int rio_request_inb_dbell(struct rio_mport *mport,
out: out:
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
/** /**
* rio_release_inb_dbell - release inbound doorbell message service * rio_release_inb_dbell - release inbound doorbell message service
@ -508,6 +505,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
out: out:
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
/** /**
* rio_request_outb_dbell - request outbound doorbell message range * rio_request_outb_dbell - request outbound doorbell message range
@ -536,6 +534,7 @@ struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
return res; return res;
} }
EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
/** /**
* rio_release_outb_dbell - release outbound doorbell message range * rio_release_outb_dbell - release outbound doorbell message range
@ -553,6 +552,7 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
/** /**
* rio_add_mport_pw_handler - add port-write message handler into the list * rio_add_mport_pw_handler - add port-write message handler into the list
@ -567,22 +567,17 @@ int rio_add_mport_pw_handler(struct rio_mport *mport, void *context,
int (*pwcback)(struct rio_mport *mport, int (*pwcback)(struct rio_mport *mport,
void *context, union rio_pw_msg *msg, int step)) void *context, union rio_pw_msg *msg, int step))
{ {
int rc = 0; struct rio_pwrite *pwrite = kzalloc(sizeof(*pwrite), GFP_KERNEL);
struct rio_pwrite *pwrite;
pwrite = kzalloc(sizeof(struct rio_pwrite), GFP_KERNEL); if (!pwrite)
if (!pwrite) { return -ENOMEM;
rc = -ENOMEM;
goto out;
}
pwrite->pwcback = pwcback; pwrite->pwcback = pwcback;
pwrite->context = context; pwrite->context = context;
mutex_lock(&mport->lock); mutex_lock(&mport->lock);
list_add_tail(&pwrite->node, &mport->pwrites); list_add_tail(&pwrite->node, &mport->pwrites);
mutex_unlock(&mport->lock); mutex_unlock(&mport->lock);
out: return 0;
return rc;
} }
EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler); EXPORT_SYMBOL_GPL(rio_add_mport_pw_handler);
@ -632,7 +627,7 @@ int rio_request_inb_pwrite(struct rio_dev *rdev,
int rc = 0; int rc = 0;
spin_lock(&rio_global_list_lock); spin_lock(&rio_global_list_lock);
if (rdev->pwcback != NULL) if (rdev->pwcback)
rc = -ENOMEM; rc = -ENOMEM;
else else
rdev->pwcback = pwcback; rdev->pwcback = pwcback;
@ -698,7 +693,7 @@ EXPORT_SYMBOL_GPL(rio_pw_enable);
int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local,
u64 rbase, u32 size, u32 rflags) u64 rbase, u32 size, u32 rflags)
{ {
int rc = 0; int rc;
unsigned long flags; unsigned long flags;
if (!mport->ops->map_inb) if (!mport->ops->map_inb)
@ -742,7 +737,7 @@ EXPORT_SYMBOL_GPL(rio_unmap_inb_region);
int rio_map_outb_region(struct rio_mport *mport, u16 destid, u64 rbase, int rio_map_outb_region(struct rio_mport *mport, u16 destid, u64 rbase,
u32 size, u32 rflags, dma_addr_t *local) u32 size, u32 rflags, dma_addr_t *local)
{ {
int rc = 0; int rc;
unsigned long flags; unsigned long flags;
if (!mport->ops->map_outb) if (!mport->ops->map_outb)
@ -975,7 +970,7 @@ rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
rdev = rdev->prev; rdev = rdev->prev;
} }
if (prev == NULL) if (!prev)
goto err_out; goto err_out;
p_port = prev->rswitch->route_table[rdev->destid]; p_port = prev->rswitch->route_table[rdev->destid];
@ -1054,7 +1049,7 @@ rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp)
RIO_MNT_REQ_CMD_IS); RIO_MNT_REQ_CMD_IS);
/* Exit if the response is not expected */ /* Exit if the response is not expected */
if (lnkresp == NULL) if (!lnkresp)
return 0; return 0;
checkcount = 3; checkcount = 3;
@ -1411,7 +1406,9 @@ rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
ext_ftr_ptr, &ftr_header); ext_ftr_ptr, &ftr_header);
if (RIO_GET_BLOCK_ID(ftr_header) == ftr) if (RIO_GET_BLOCK_ID(ftr_header) == ftr)
return ext_ftr_ptr; return ext_ftr_ptr;
if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header)))
ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header);
if (!ext_ftr_ptr)
break; break;
} }
@ -1462,6 +1459,7 @@ struct rio_dev *rio_get_asm(u16 vid, u16 did,
spin_unlock(&rio_global_list_lock); spin_unlock(&rio_global_list_lock);
return rdev; return rdev;
} }
EXPORT_SYMBOL_GPL(rio_get_asm);
/** /**
* rio_get_device - Begin or continue searching for a RIO device by vid/did * rio_get_device - Begin or continue searching for a RIO device by vid/did
@ -1481,6 +1479,7 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
{ {
return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
} }
EXPORT_SYMBOL_GPL(rio_get_device);
/** /**
* rio_std_route_add_entry - Add switch route table entry using standard * rio_std_route_add_entry - Add switch route table entry using standard
@ -1696,7 +1695,7 @@ int rio_route_add_entry(struct rio_dev *rdev,
spin_lock(&rdev->rswitch->lock); spin_lock(&rdev->rswitch->lock);
if (ops == NULL || ops->add_entry == NULL) { if (!ops || !ops->add_entry) {
rc = rio_std_route_add_entry(rdev->net->hport, rdev->destid, rc = rio_std_route_add_entry(rdev->net->hport, rdev->destid,
rdev->hopcount, table, rdev->hopcount, table,
route_destid, route_port); route_destid, route_port);
@ -1749,7 +1748,7 @@ int rio_route_get_entry(struct rio_dev *rdev, u16 table,
spin_lock(&rdev->rswitch->lock); spin_lock(&rdev->rswitch->lock);
if (ops == NULL || ops->get_entry == NULL) { if (!ops || !ops->get_entry) {
rc = rio_std_route_get_entry(rdev->net->hport, rdev->destid, rc = rio_std_route_get_entry(rdev->net->hport, rdev->destid,
rdev->hopcount, table, rdev->hopcount, table,
route_destid, route_port); route_destid, route_port);
@ -1797,7 +1796,7 @@ int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock)
spin_lock(&rdev->rswitch->lock); spin_lock(&rdev->rswitch->lock);
if (ops == NULL || ops->clr_table == NULL) { if (!ops || !ops->clr_table) {
rc = rio_std_route_clr_table(rdev->net->hport, rdev->destid, rc = rio_std_route_clr_table(rdev->net->hport, rdev->destid,
rdev->hopcount, table); rdev->hopcount, table);
} else if (try_module_get(ops->owner)) { } else if (try_module_get(ops->owner)) {
@ -1889,7 +1888,7 @@ struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan,
{ {
struct rio_dma_ext rio_ext; struct rio_dma_ext rio_ext;
if (dchan->device->device_prep_slave_sg == NULL) { if (!dchan->device->device_prep_slave_sg) {
pr_err("%s: prep_rio_sg == NULL\n", __func__); pr_err("%s: prep_rio_sg == NULL\n", __func__);
return NULL; return NULL;
} }
@ -2189,7 +2188,6 @@ int rio_init_mports(void)
work = kcalloc(n, sizeof *work, GFP_KERNEL); work = kcalloc(n, sizeof *work, GFP_KERNEL);
if (!work) { if (!work) {
pr_err("RIO: no memory for work struct\n");
destroy_workqueue(rio_wq); destroy_workqueue(rio_wq);
goto no_disc; goto no_disc;
} }
@ -2216,6 +2214,7 @@ int rio_init_mports(void)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rio_init_mports);
static int rio_get_hdid(int index) static int rio_get_hdid(int index)
{ {
@ -2330,16 +2329,3 @@ int rio_unregister_mport(struct rio_mport *port)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(rio_unregister_mport); EXPORT_SYMBOL_GPL(rio_unregister_mport);
EXPORT_SYMBOL_GPL(rio_local_get_device_id);
EXPORT_SYMBOL_GPL(rio_get_device);
EXPORT_SYMBOL_GPL(rio_get_asm);
EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
EXPORT_SYMBOL_GPL(rio_init_mports);

View File

@ -1599,6 +1599,8 @@ static int fill_files_note(struct memelfnote *note)
/* *Estimated* file count and total data size needed */ /* *Estimated* file count and total data size needed */
count = current->mm->map_count; count = current->mm->map_count;
if (count > UINT_MAX / 64)
return -EINVAL;
size = count * 64; size = count * 64;
names_ofs = (2 + 3 * count) * sizeof(data[0]); names_ofs = (2 + 3 * count) * sizeof(data[0]);

View File

@ -444,7 +444,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
int res = -ENOMEM; int res = -ENOMEM;
mutex_lock(&sbi->vh_mutex); mutex_lock(&sbi->vh_mutex);
inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); inode = hfsplus_new_inode(dir->i_sb, dir, S_IFLNK | S_IRWXUGO);
if (!inode) if (!inode)
goto out; goto out;
@ -486,7 +486,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
int res = -ENOMEM; int res = -ENOMEM;
mutex_lock(&sbi->vh_mutex); mutex_lock(&sbi->vh_mutex);
inode = hfsplus_new_inode(dir->i_sb, mode); inode = hfsplus_new_inode(dir->i_sb, dir, mode);
if (!inode) if (!inode)
goto out; goto out;

View File

@ -478,7 +478,8 @@ extern const struct address_space_operations hfsplus_aops;
extern const struct address_space_operations hfsplus_btree_aops; extern const struct address_space_operations hfsplus_btree_aops;
extern const struct dentry_operations hfsplus_dentry_operations; extern const struct dentry_operations hfsplus_dentry_operations;
struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode); struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
umode_t mode);
void hfsplus_delete_inode(struct inode *inode); void hfsplus_delete_inode(struct inode *inode);
void hfsplus_inode_read_fork(struct inode *inode, void hfsplus_inode_read_fork(struct inode *inode,
struct hfsplus_fork_raw *fork); struct hfsplus_fork_raw *fork);

View File

@ -354,7 +354,8 @@ static const struct file_operations hfsplus_file_operations = {
.unlocked_ioctl = hfsplus_ioctl, .unlocked_ioctl = hfsplus_ioctl,
}; };
struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode) struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
umode_t mode)
{ {
struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
struct inode *inode = new_inode(sb); struct inode *inode = new_inode(sb);
@ -364,9 +365,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
return NULL; return NULL;
inode->i_ino = sbi->next_cnid++; inode->i_ino = sbi->next_cnid++;
inode->i_mode = mode; inode_init_owner(inode, dir, mode);
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
set_nlink(inode, 1); set_nlink(inode, 1);
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);

View File

@ -549,7 +549,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
if (!sbi->hidden_dir) { if (!sbi->hidden_dir) {
mutex_lock(&sbi->vh_mutex); mutex_lock(&sbi->vh_mutex);
sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); sbi->hidden_dir = hfsplus_new_inode(sb, root, S_IFDIR);
if (!sbi->hidden_dir) { if (!sbi->hidden_dir) {
mutex_unlock(&sbi->vh_mutex); mutex_unlock(&sbi->vh_mutex);
err = -ENOMEM; err = -ENOMEM;

View File

@ -498,7 +498,6 @@ EXPORT_SYMBOL(__remove_inode_hash);
void clear_inode(struct inode *inode) void clear_inode(struct inode *inode)
{ {
might_sleep();
/* /*
* We have to cycle tree_lock here because reclaim can be still in the * We have to cycle tree_lock here because reclaim can be still in the
* process of removing the last page (in __delete_from_page_cache()) * process of removing the last page (in __delete_from_page_cache())

View File

@ -130,7 +130,7 @@ int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *segbuf,
} }
int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned int flags, int nilfs_segbuf_reset(struct nilfs_segment_buffer *segbuf, unsigned int flags,
time_t ctime, __u64 cno) time64_t ctime, __u64 cno)
{ {
int err; int err;

View File

@ -46,7 +46,7 @@ struct nilfs_segsum_info {
unsigned long nfileblk; unsigned long nfileblk;
u64 seg_seq; u64 seg_seq;
__u64 cno; __u64 cno;
time_t ctime; time64_t ctime;
sector_t next; sector_t next;
}; };
@ -120,7 +120,7 @@ void nilfs_segbuf_map_cont(struct nilfs_segment_buffer *segbuf,
struct nilfs_segment_buffer *prev); struct nilfs_segment_buffer *prev);
void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64, void nilfs_segbuf_set_next_segnum(struct nilfs_segment_buffer *, __u64,
struct the_nilfs *); struct the_nilfs *);
int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned int, time_t, int nilfs_segbuf_reset(struct nilfs_segment_buffer *, unsigned int, time64_t,
__u64); __u64);
int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *); int nilfs_segbuf_extend_segsum(struct nilfs_segment_buffer *);
int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *,

View File

@ -2040,7 +2040,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
goto out; goto out;
/* Update time stamp */ /* Update time stamp */
sci->sc_seg_ctime = get_seconds(); sci->sc_seg_ctime = ktime_get_real_seconds();
err = nilfs_segctor_collect(sci, nilfs, mode); err = nilfs_segctor_collect(sci, nilfs, mode);
if (unlikely(err)) if (unlikely(err))

View File

@ -157,7 +157,7 @@ struct nilfs_sc_info {
unsigned long sc_blk_cnt; unsigned long sc_blk_cnt;
unsigned long sc_datablk_cnt; unsigned long sc_datablk_cnt;
unsigned long sc_nblk_this_inc; unsigned long sc_nblk_this_inc;
time_t sc_seg_ctime; time64_t sc_seg_ctime;
__u64 sc_cno; __u64 sc_cno;
unsigned long sc_flags; unsigned long sc_flags;

View File

@ -526,7 +526,7 @@ int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum)
* @modtime: modification time (option) * @modtime: modification time (option)
*/ */
int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
unsigned long nblocks, time_t modtime) unsigned long nblocks, time64_t modtime)
{ {
struct buffer_head *bh; struct buffer_head *bh;
struct nilfs_segment_usage *su; struct nilfs_segment_usage *su;

View File

@ -35,7 +35,7 @@ int nilfs_sufile_set_alloc_range(struct inode *sufile, __u64 start, __u64 end);
int nilfs_sufile_alloc(struct inode *, __u64 *); int nilfs_sufile_alloc(struct inode *, __u64 *);
int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum); int nilfs_sufile_mark_dirty(struct inode *sufile, __u64 segnum);
int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum, int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
unsigned long nblocks, time_t modtime); unsigned long nblocks, time64_t modtime);
int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *); int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned int, ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned int,
size_t); size_t);

View File

@ -283,10 +283,10 @@ int nilfs_commit_super(struct super_block *sb, int flag)
{ {
struct the_nilfs *nilfs = sb->s_fs_info; struct the_nilfs *nilfs = sb->s_fs_info;
struct nilfs_super_block **sbp = nilfs->ns_sbp; struct nilfs_super_block **sbp = nilfs->ns_sbp;
time_t t; time64_t t;
/* nilfs->ns_sem must be locked by the caller. */ /* nilfs->ns_sem must be locked by the caller. */
t = get_seconds(); t = ktime_get_real_seconds();
nilfs->ns_sbwtime = t; nilfs->ns_sbwtime = t;
sbp[0]->s_wtime = cpu_to_le64(t); sbp[0]->s_wtime = cpu_to_le64(t);
sbp[0]->s_sum = 0; sbp[0]->s_sum = 0;

View File

@ -31,7 +31,7 @@ static struct kset *nilfs_kset;
#define NILFS_SHOW_TIME(time_t_val, buf) ({ \ #define NILFS_SHOW_TIME(time_t_val, buf) ({ \
struct tm res; \ struct tm res; \
int count = 0; \ int count = 0; \
time_to_tm(time_t_val, 0, &res); \ time64_to_tm(time_t_val, 0, &res); \
res.tm_year += 1900; \ res.tm_year += 1900; \
res.tm_mon += 1; \ res.tm_mon += 1; \
count = scnprintf(buf, PAGE_SIZE, \ count = scnprintf(buf, PAGE_SIZE, \
@ -579,7 +579,7 @@ nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t ctime; time64_t ctime;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
ctime = nilfs->ns_ctime; ctime = nilfs->ns_ctime;
@ -593,13 +593,13 @@ nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t ctime; time64_t ctime;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
ctime = nilfs->ns_ctime; ctime = nilfs->ns_ctime;
up_read(&nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)ctime); return snprintf(buf, PAGE_SIZE, "%llu\n", ctime);
} }
static ssize_t static ssize_t
@ -607,7 +607,7 @@ nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t nongc_ctime; time64_t nongc_ctime;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
nongc_ctime = nilfs->ns_nongc_ctime; nongc_ctime = nilfs->ns_nongc_ctime;
@ -621,14 +621,13 @@ nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t nongc_ctime; time64_t nongc_ctime;
down_read(&nilfs->ns_segctor_sem); down_read(&nilfs->ns_segctor_sem);
nongc_ctime = nilfs->ns_nongc_ctime; nongc_ctime = nilfs->ns_nongc_ctime;
up_read(&nilfs->ns_segctor_sem); up_read(&nilfs->ns_segctor_sem);
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n", nongc_ctime);
(unsigned long long)nongc_ctime);
} }
static ssize_t static ssize_t
@ -728,7 +727,7 @@ nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t sbwtime; time64_t sbwtime;
down_read(&nilfs->ns_sem); down_read(&nilfs->ns_sem);
sbwtime = nilfs->ns_sbwtime; sbwtime = nilfs->ns_sbwtime;
@ -742,13 +741,13 @@ nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr,
struct the_nilfs *nilfs, struct the_nilfs *nilfs,
char *buf) char *buf)
{ {
time_t sbwtime; time64_t sbwtime;
down_read(&nilfs->ns_sem); down_read(&nilfs->ns_sem);
sbwtime = nilfs->ns_sbwtime; sbwtime = nilfs->ns_sbwtime;
up_read(&nilfs->ns_sem); up_read(&nilfs->ns_sem);
return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)sbwtime); return snprintf(buf, PAGE_SIZE, "%llu\n", sbwtime);
} }
static ssize_t static ssize_t

View File

@ -116,7 +116,7 @@ struct the_nilfs {
*/ */
struct buffer_head *ns_sbh[2]; struct buffer_head *ns_sbh[2];
struct nilfs_super_block *ns_sbp[2]; struct nilfs_super_block *ns_sbp[2];
time_t ns_sbwtime; time64_t ns_sbwtime;
unsigned int ns_sbwcount; unsigned int ns_sbwcount;
unsigned int ns_sbsize; unsigned int ns_sbsize;
unsigned int ns_mount_state; unsigned int ns_mount_state;
@ -131,8 +131,8 @@ struct the_nilfs {
__u64 ns_nextnum; __u64 ns_nextnum;
unsigned long ns_pseg_offset; unsigned long ns_pseg_offset;
__u64 ns_cno; __u64 ns_cno;
time_t ns_ctime; time64_t ns_ctime;
time_t ns_nongc_ctime; time64_t ns_nongc_ctime;
atomic_t ns_ndirtyblks; atomic_t ns_ndirtyblks;
/* /*
@ -267,7 +267,7 @@ struct nilfs_root {
static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) static inline int nilfs_sb_need_update(struct the_nilfs *nilfs)
{ {
u64 t = get_seconds(); u64 t = ktime_get_real_seconds();
return t < nilfs->ns_sbwtime || return t < nilfs->ns_sbwtime ||
t > nilfs->ns_sbwtime + nilfs->ns_sb_update_freq; t > nilfs->ns_sbwtime + nilfs->ns_sb_update_freq;

View File

@ -35,11 +35,6 @@
*/ */
unsigned int pipe_max_size = 1048576; unsigned int pipe_max_size = 1048576;
/*
* Minimum pipe size, as required by POSIX
*/
unsigned int pipe_min_size = PAGE_SIZE;
/* Maximum allocatable pages per user. Hard limit is unset by default, soft /* Maximum allocatable pages per user. Hard limit is unset by default, soft
* matches default values. * matches default values.
*/ */
@ -610,12 +605,21 @@ static unsigned long account_pipe_buffers(struct user_struct *user,
static bool too_many_pipe_buffers_soft(unsigned long user_bufs) static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
{ {
return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft; unsigned long soft_limit = READ_ONCE(pipe_user_pages_soft);
return soft_limit && user_bufs > soft_limit;
} }
static bool too_many_pipe_buffers_hard(unsigned long user_bufs) static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
{ {
return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard; unsigned long hard_limit = READ_ONCE(pipe_user_pages_hard);
return hard_limit && user_bufs > hard_limit;
}
static bool is_unprivileged_user(void)
{
return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
} }
struct pipe_inode_info *alloc_pipe_info(void) struct pipe_inode_info *alloc_pipe_info(void)
@ -624,22 +628,23 @@ struct pipe_inode_info *alloc_pipe_info(void)
unsigned long pipe_bufs = PIPE_DEF_BUFFERS; unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
struct user_struct *user = get_current_user(); struct user_struct *user = get_current_user();
unsigned long user_bufs; unsigned long user_bufs;
unsigned int max_size = READ_ONCE(pipe_max_size);
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT); pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
if (pipe == NULL) if (pipe == NULL)
goto out_free_uid; goto out_free_uid;
if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE)) if (pipe_bufs * PAGE_SIZE > max_size && !capable(CAP_SYS_RESOURCE))
pipe_bufs = pipe_max_size >> PAGE_SHIFT; pipe_bufs = max_size >> PAGE_SHIFT;
user_bufs = account_pipe_buffers(user, 0, pipe_bufs); user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
if (too_many_pipe_buffers_soft(user_bufs)) { if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) {
user_bufs = account_pipe_buffers(user, pipe_bufs, 1); user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
pipe_bufs = 1; pipe_bufs = 1;
} }
if (too_many_pipe_buffers_hard(user_bufs)) if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user())
goto out_revert_acct; goto out_revert_acct;
pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
@ -1020,18 +1025,16 @@ const struct file_operations pipefifo_fops = {
* Currently we rely on the pipe array holding a power-of-2 number * Currently we rely on the pipe array holding a power-of-2 number
* of pages. Returns 0 on error. * of pages. Returns 0 on error.
*/ */
unsigned int round_pipe_size(unsigned int size) unsigned int round_pipe_size(unsigned long size)
{ {
unsigned long nr_pages; if (size > (1U << 31))
if (size < pipe_min_size)
size = pipe_min_size;
nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (nr_pages == 0)
return 0; return 0;
return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; /* Minimum pipe size, as required by POSIX */
if (size < PAGE_SIZE)
return PAGE_SIZE;
return roundup_pow_of_two(size);
} }
/* /*
@ -1046,8 +1049,6 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
long ret = 0; long ret = 0;
size = round_pipe_size(arg); size = round_pipe_size(arg);
if (size == 0)
return -EINVAL;
nr_pages = size >> PAGE_SHIFT; nr_pages = size >> PAGE_SHIFT;
if (!nr_pages) if (!nr_pages)
@ -1069,7 +1070,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
if (nr_pages > pipe->buffers && if (nr_pages > pipe->buffers &&
(too_many_pipe_buffers_hard(user_bufs) || (too_many_pipe_buffers_hard(user_bufs) ||
too_many_pipe_buffers_soft(user_bufs)) && too_many_pipe_buffers_soft(user_bufs)) &&
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { is_unprivileged_user()) {
ret = -EPERM; ret = -EPERM;
goto out_revert_acct; goto out_revert_acct;
} }
@ -1124,16 +1125,6 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
return ret; return ret;
} }
/*
* This should work even if CONFIG_PROC_FS isn't set, as proc_dopipe_max_size
* will return an error.
*/
int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
size_t *lenp, loff_t *ppos)
{
return proc_dopipe_max_size(table, write, buf, lenp, ppos);
}
/* /*
* After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
* location, so checking ->i_pipe is not enough to verify that this is a * location, so checking ->i_pipe is not enough to verify that this is a

View File

@ -736,16 +736,10 @@ static int children_seq_open(struct inode *inode, struct file *file)
return ret; return ret;
} }
int children_seq_release(struct inode *inode, struct file *file)
{
seq_release(inode, file);
return 0;
}
const struct file_operations proc_tid_children_operations = { const struct file_operations proc_tid_children_operations = {
.open = children_seq_open, .open = children_seq_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = children_seq_release, .release = seq_release,
}; };
#endif /* CONFIG_PROC_CHILDREN */ #endif /* CONFIG_PROC_CHILDREN */

View File

@ -75,6 +75,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/tracehook.h> #include <linux/tracehook.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/cache.h>
#include <linux/cgroup.h> #include <linux/cgroup.h>
#include <linux/cpuset.h> #include <linux/cpuset.h>
#include <linux/audit.h> #include <linux/audit.h>
@ -100,6 +101,8 @@
#include "internal.h" #include "internal.h"
#include "fd.h" #include "fd.h"
#include "../../lib/kstrtox.h"
/* NOTE: /* NOTE:
* Implementing inode permission operations in /proc is almost * Implementing inode permission operations in /proc is almost
* certainly an error. Permission checks need to happen during * certainly an error. Permission checks need to happen during
@ -110,8 +113,8 @@
* in /proc for a task before it execs a suid executable. * in /proc for a task before it execs a suid executable.
*/ */
static u8 nlink_tid; static u8 nlink_tid __ro_after_init;
static u8 nlink_tgid; static u8 nlink_tgid __ro_after_init;
struct pid_entry { struct pid_entry {
const char *name; const char *name;
@ -1370,7 +1373,7 @@ static ssize_t proc_fail_nth_write(struct file *file, const char __user *buf,
task = get_proc_task(file_inode(file)); task = get_proc_task(file_inode(file));
if (!task) if (!task)
return -ESRCH; return -ESRCH;
WRITE_ONCE(task->fail_nth, n); task->fail_nth = n;
put_task_struct(task); put_task_struct(task);
return count; return count;
@ -1386,8 +1389,7 @@ static ssize_t proc_fail_nth_read(struct file *file, char __user *buf,
task = get_proc_task(file_inode(file)); task = get_proc_task(file_inode(file));
if (!task) if (!task)
return -ESRCH; return -ESRCH;
len = snprintf(numbuf, sizeof(numbuf), "%u\n", len = snprintf(numbuf, sizeof(numbuf), "%u\n", task->fail_nth);
READ_ONCE(task->fail_nth));
len = simple_read_from_buffer(buf, count, ppos, numbuf, len); len = simple_read_from_buffer(buf, count, ppos, numbuf, len);
put_task_struct(task); put_task_struct(task);
@ -1907,8 +1909,33 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
static int dname_to_vma_addr(struct dentry *dentry, static int dname_to_vma_addr(struct dentry *dentry,
unsigned long *start, unsigned long *end) unsigned long *start, unsigned long *end)
{ {
if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2) const char *str = dentry->d_name.name;
unsigned long long sval, eval;
unsigned int len;
len = _parse_integer(str, 16, &sval);
if (len & KSTRTOX_OVERFLOW)
return -EINVAL; return -EINVAL;
if (sval != (unsigned long)sval)
return -EINVAL;
str += len;
if (*str != '-')
return -EINVAL;
str++;
len = _parse_integer(str, 16, &eval);
if (len & KSTRTOX_OVERFLOW)
return -EINVAL;
if (eval != (unsigned long)eval)
return -EINVAL;
str += len;
if (*str != '\0')
return -EINVAL;
*start = sval;
*end = eval;
return 0; return 0;
} }
@ -2000,9 +2027,9 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
} }
struct map_files_info { struct map_files_info {
unsigned long start;
unsigned long end;
fmode_t mode; fmode_t mode;
unsigned int len;
unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
}; };
/* /*
@ -2172,10 +2199,9 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
if (++pos <= ctx->pos) if (++pos <= ctx->pos)
continue; continue;
info.start = vma->vm_start;
info.end = vma->vm_end;
info.mode = vma->vm_file->f_mode; info.mode = vma->vm_file->f_mode;
info.len = snprintf(info.name,
sizeof(info.name), "%lx-%lx",
vma->vm_start, vma->vm_end);
if (flex_array_put(fa, i++, &info, GFP_KERNEL)) if (flex_array_put(fa, i++, &info, GFP_KERNEL))
BUG(); BUG();
} }
@ -2183,9 +2209,13 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
for (i = 0; i < nr_files; i++) { for (i = 0; i < nr_files; i++) {
char buf[4 * sizeof(long) + 2]; /* max: %lx-%lx\0 */
unsigned int len;
p = flex_array_get(fa, i); p = flex_array_get(fa, i);
len = snprintf(buf, sizeof(buf), "%lx-%lx", p->start, p->end);
if (!proc_fill_cache(file, ctx, if (!proc_fill_cache(file, ctx,
p->name, p->len, buf, len,
proc_map_files_instantiate, proc_map_files_instantiate,
task, task,
(void *)(unsigned long)p->mode)) (void *)(unsigned long)p->mode))
@ -3018,11 +3048,11 @@ static const struct inode_operations proc_tgid_base_inode_operations = {
static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
{ {
struct dentry *dentry, *leader, *dir; struct dentry *dentry, *leader, *dir;
char buf[PROC_NUMBUF]; char buf[10 + 1];
struct qstr name; struct qstr name;
name.name = buf; name.name = buf;
name.len = snprintf(buf, sizeof(buf), "%d", pid); name.len = snprintf(buf, sizeof(buf), "%u", pid);
/* no ->d_hash() rejects on procfs */ /* no ->d_hash() rejects on procfs */
dentry = d_hash_and_lookup(mnt->mnt_root, &name); dentry = d_hash_and_lookup(mnt->mnt_root, &name);
if (dentry) { if (dentry) {
@ -3034,7 +3064,7 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
return; return;
name.name = buf; name.name = buf;
name.len = snprintf(buf, sizeof(buf), "%d", tgid); name.len = snprintf(buf, sizeof(buf), "%u", tgid);
leader = d_hash_and_lookup(mnt->mnt_root, &name); leader = d_hash_and_lookup(mnt->mnt_root, &name);
if (!leader) if (!leader)
goto out; goto out;
@ -3046,7 +3076,7 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
goto out_put_leader; goto out_put_leader;
name.name = buf; name.name = buf;
name.len = snprintf(buf, sizeof(buf), "%d", pid); name.len = snprintf(buf, sizeof(buf), "%u", pid);
dentry = d_hash_and_lookup(dir, &name); dentry = d_hash_and_lookup(dir, &name);
if (dentry) { if (dentry) {
d_invalidate(dentry); d_invalidate(dentry);
@ -3225,14 +3255,14 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
for (iter = next_tgid(ns, iter); for (iter = next_tgid(ns, iter);
iter.task; iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) { iter.tgid += 1, iter = next_tgid(ns, iter)) {
char name[PROC_NUMBUF]; char name[10 + 1];
int len; int len;
cond_resched(); cond_resched();
if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE)) if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE))
continue; continue;
len = snprintf(name, sizeof(name), "%d", iter.tgid); len = snprintf(name, sizeof(name), "%u", iter.tgid);
ctx->pos = iter.tgid + TGID_OFFSET; ctx->pos = iter.tgid + TGID_OFFSET;
if (!proc_fill_cache(file, ctx, name, len, if (!proc_fill_cache(file, ctx, name, len,
proc_pid_instantiate, iter.task, NULL)) { proc_pid_instantiate, iter.task, NULL)) {
@ -3560,10 +3590,10 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns);
task; task;
task = next_tid(task), ctx->pos++) { task = next_tid(task), ctx->pos++) {
char name[PROC_NUMBUF]; char name[10 + 1];
int len; int len;
tid = task_pid_nr_ns(task, ns); tid = task_pid_nr_ns(task, ns);
len = snprintf(name, sizeof(name), "%d", tid); len = snprintf(name, sizeof(name), "%u", tid);
if (!proc_fill_cache(file, ctx, name, len, if (!proc_fill_cache(file, ctx, name, len,
proc_task_instantiate, task, NULL)) { proc_task_instantiate, task, NULL)) {
/* returning this tgid failed, save it as the first /* returning this tgid failed, save it as the first

View File

@ -55,8 +55,7 @@ static int show_console_dev(struct seq_file *m, void *v)
if (dev) if (dev)
seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev)); seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev));
seq_printf(m, "\n"); seq_putc(m, '\n');
return 0; return 0;
} }

View File

@ -236,7 +236,7 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
for (fd = ctx->pos - 2; for (fd = ctx->pos - 2;
fd < files_fdtable(files)->max_fds; fd < files_fdtable(files)->max_fds;
fd++, ctx->pos++) { fd++, ctx->pos++) {
char name[PROC_NUMBUF]; char name[10 + 1];
int len; int len;
if (!fcheck_files(files, fd)) if (!fcheck_files(files, fd))

View File

@ -28,7 +28,7 @@
static DEFINE_RWLOCK(proc_subdir_lock); static DEFINE_RWLOCK(proc_subdir_lock);
static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)
{ {
if (len < de->namelen) if (len < de->namelen)
return -1; return -1;
@ -60,7 +60,7 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
struct proc_dir_entry *de = rb_entry(node, struct proc_dir_entry *de = rb_entry(node,
struct proc_dir_entry, struct proc_dir_entry,
subdir_node); subdir_node);
int result = proc_match(len, name, de); int result = proc_match(name, de, len);
if (result < 0) if (result < 0)
node = node->rb_left; node = node->rb_left;
@ -84,7 +84,7 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir,
struct proc_dir_entry *this = rb_entry(*new, struct proc_dir_entry *this = rb_entry(*new,
struct proc_dir_entry, struct proc_dir_entry,
subdir_node); subdir_node);
int result = proc_match(de->namelen, de->name, this); int result = proc_match(de->name, this, de->namelen);
parent = *new; parent = *new;
if (result < 0) if (result < 0)
@ -211,8 +211,8 @@ void proc_free_inum(unsigned int inum)
* Don't create negative dentries here, return -ENOENT by hand * Don't create negative dentries here, return -ENOENT by hand
* instead. * instead.
*/ */
struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
struct dentry *dentry) struct proc_dir_entry *de)
{ {
struct inode *inode; struct inode *inode;
@ -235,7 +235,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags) unsigned int flags)
{ {
return proc_lookup_de(PDE(dir), dir, dentry); return proc_lookup_de(dir, dentry, PDE(dir));
} }
/* /*
@ -247,8 +247,8 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
* value of the readdir() call, as long as it's non-negative * value of the readdir() call, as long as it's non-negative
* for success.. * for success..
*/ */
int proc_readdir_de(struct proc_dir_entry *de, struct file *file, int proc_readdir_de(struct file *file, struct dir_context *ctx,
struct dir_context *ctx) struct proc_dir_entry *de)
{ {
int i; int i;
@ -292,7 +292,7 @@ int proc_readdir(struct file *file, struct dir_context *ctx)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
return proc_readdir_de(PDE(inode), file, ctx); return proc_readdir_de(file, ctx, PDE(inode));
} }
/* /*

View File

@ -5,6 +5,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
*/ */
#include <linux/cache.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -52,7 +53,7 @@ static void proc_evict_inode(struct inode *inode)
} }
} }
static struct kmem_cache * proc_inode_cachep; static struct kmem_cache *proc_inode_cachep __ro_after_init;
static struct inode *proc_alloc_inode(struct super_block *sb) static struct inode *proc_alloc_inode(struct super_block *sb)
{ {
@ -128,12 +129,12 @@ enum {BIAS = -1U<<31};
static inline int use_pde(struct proc_dir_entry *pde) static inline int use_pde(struct proc_dir_entry *pde)
{ {
return atomic_inc_unless_negative(&pde->in_use); return likely(atomic_inc_unless_negative(&pde->in_use));
} }
static void unuse_pde(struct proc_dir_entry *pde) static void unuse_pde(struct proc_dir_entry *pde)
{ {
if (atomic_dec_return(&pde->in_use) == BIAS) if (unlikely(atomic_dec_return(&pde->in_use) == BIAS))
complete(pde->pde_unload_completion); complete(pde->pde_unload_completion);
} }
@ -166,7 +167,7 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
spin_lock(&pde->pde_unload_lock); spin_lock(&pde->pde_unload_lock);
/* After ->release. */ /* After ->release. */
list_del(&pdeo->lh); list_del(&pdeo->lh);
if (pdeo->c) if (unlikely(pdeo->c))
complete(pdeo->c); complete(pdeo->c);
kfree(pdeo); kfree(pdeo);
} }
@ -420,7 +421,7 @@ static const char *proc_get_link(struct dentry *dentry,
struct delayed_call *done) struct delayed_call *done)
{ {
struct proc_dir_entry *pde = PDE(inode); struct proc_dir_entry *pde = PDE(inode);
if (unlikely(!use_pde(pde))) if (!use_pde(pde))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
set_delayed_call(done, proc_put_link, pde); set_delayed_call(done, proc_put_link, pde);
return pde->data; return pde->data;

View File

@ -31,24 +31,28 @@ struct mempolicy;
* subdir_node is used to build the rb tree "subdir" of the parent. * subdir_node is used to build the rb tree "subdir" of the parent.
*/ */
struct proc_dir_entry { struct proc_dir_entry {
/*
* number of callers into module in progress;
* negative -> it's going away RSN
*/
atomic_t in_use;
atomic_t count; /* use count */
struct list_head pde_openers; /* who did ->open, but not ->release */
/* protects ->pde_openers and all struct pde_opener instances */
spinlock_t pde_unload_lock;
struct completion *pde_unload_completion;
const struct inode_operations *proc_iops;
const struct file_operations *proc_fops;
void *data;
unsigned int low_ino; unsigned int low_ino;
umode_t mode;
nlink_t nlink; nlink_t nlink;
kuid_t uid; kuid_t uid;
kgid_t gid; kgid_t gid;
loff_t size; loff_t size;
const struct inode_operations *proc_iops;
const struct file_operations *proc_fops;
struct proc_dir_entry *parent; struct proc_dir_entry *parent;
struct rb_root_cached subdir; struct rb_root_cached subdir;
struct rb_node subdir_node; struct rb_node subdir_node;
void *data; umode_t mode;
atomic_t count; /* use count */
atomic_t in_use; /* number of callers into module in progress; */
/* negative -> it's going away RSN */
struct completion *pde_unload_completion;
struct list_head pde_openers; /* who did ->open, but not ->release */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
u8 namelen; u8 namelen;
char name[]; char name[];
} __randomize_layout; } __randomize_layout;
@ -149,10 +153,9 @@ extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, i
* generic.c * generic.c
*/ */
extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, struct dentry *proc_lookup_de(struct inode *, struct dentry *, struct proc_dir_entry *);
struct dentry *);
extern int proc_readdir(struct file *, struct dir_context *); extern int proc_readdir(struct file *, struct dir_context *);
extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); int proc_readdir_de(struct file *, struct dir_context *, struct proc_dir_entry *);
static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
{ {

View File

@ -512,23 +512,15 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
return -EFAULT; return -EFAULT;
} else { } else {
if (kern_addr_valid(start)) { if (kern_addr_valid(start)) {
unsigned long n;
/* /*
* Using bounce buffer to bypass the * Using bounce buffer to bypass the
* hardened user copy kernel text checks. * hardened user copy kernel text checks.
*/ */
memcpy(buf, (char *) start, tsz); if (probe_kernel_read(buf, (void *) start, tsz)) {
n = copy_to_user(buffer, buf, tsz); if (clear_user(buffer, tsz))
/* return -EFAULT;
* We cannot distinguish between fault on source } else {
* and fault on destination. When this happens if (copy_to_user(buffer, buf, tsz))
* we clear too and hope it will trigger the
* EFAULT again.
*/
if (n) {
if (clear_user(buffer + tsz - n,
n))
return -EFAULT; return -EFAULT;
} }
} else { } else {

View File

@ -135,7 +135,7 @@ static struct dentry *proc_tgid_net_lookup(struct inode *dir,
de = ERR_PTR(-ENOENT); de = ERR_PTR(-ENOENT);
net = get_proc_task_net(dir); net = get_proc_task_net(dir);
if (net != NULL) { if (net != NULL) {
de = proc_lookup_de(net->proc_net, dir, dentry); de = proc_lookup_de(dir, dentry, net->proc_net);
put_net(net); put_net(net);
} }
return de; return de;
@ -172,7 +172,7 @@ static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)
ret = -EINVAL; ret = -EINVAL;
net = get_proc_task_net(file_inode(file)); net = get_proc_task_net(file_inode(file));
if (net != NULL) { if (net != NULL) {
ret = proc_readdir_de(net->proc_net, file, ctx); ret = proc_readdir_de(file, ctx, net->proc_net);
put_net(net); put_net(net);
} }
return ret; return ret;

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/cache.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pid_namespace.h> #include <linux/pid_namespace.h>
@ -17,11 +18,11 @@ static const char *proc_self_get_link(struct dentry *dentry,
if (!tgid) if (!tgid)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
/* 11 for max length of signed int in decimal + NULL term */ /* max length of unsigned int in decimal + NULL term */
name = kmalloc(12, dentry ? GFP_KERNEL : GFP_ATOMIC); name = kmalloc(10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);
if (unlikely(!name)) if (unlikely(!name))
return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);
sprintf(name, "%d", tgid); sprintf(name, "%u", tgid);
set_delayed_call(done, kfree_link, name); set_delayed_call(done, kfree_link, name);
return name; return name;
} }
@ -30,7 +31,7 @@ static const struct inode_operations proc_self_inode_operations = {
.get_link = proc_self_get_link, .get_link = proc_self_get_link,
}; };
static unsigned self_inum; static unsigned self_inum __ro_after_init;
int proc_setup_self(struct super_block *s) int proc_setup_self(struct super_block *s)
{ {

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/cache.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pid_namespace.h> #include <linux/pid_namespace.h>
@ -18,11 +19,10 @@ static const char *proc_thread_self_get_link(struct dentry *dentry,
if (!pid) if (!pid)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
name = kmalloc(PROC_NUMBUF + 6 + PROC_NUMBUF, name = kmalloc(10 + 6 + 10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);
dentry ? GFP_KERNEL : GFP_ATOMIC);
if (unlikely(!name)) if (unlikely(!name))
return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);
sprintf(name, "%d/task/%d", tgid, pid); sprintf(name, "%u/task/%u", tgid, pid);
set_delayed_call(done, kfree_link, name); set_delayed_call(done, kfree_link, name);
return name; return name;
} }
@ -31,7 +31,7 @@ static const struct inode_operations proc_thread_self_inode_operations = {
.get_link = proc_thread_self_get_link, .get_link = proc_thread_self_get_link,
}; };
static unsigned thread_self_inum; static unsigned thread_self_inum __ro_after_init;
int proc_setup_thread_self(struct super_block *s) int proc_setup_thread_self(struct super_block *s)
{ {

View File

@ -1178,18 +1178,16 @@ fs_initcall(vmcore_init);
/* Cleanup function for vmcore module. */ /* Cleanup function for vmcore module. */
void vmcore_cleanup(void) void vmcore_cleanup(void)
{ {
struct list_head *pos, *next;
if (proc_vmcore) { if (proc_vmcore) {
proc_remove(proc_vmcore); proc_remove(proc_vmcore);
proc_vmcore = NULL; proc_vmcore = NULL;
} }
/* clear the vmcore list. */ /* clear the vmcore list. */
list_for_each_safe(pos, next, &vmcore_list) { while (!list_empty(&vmcore_list)) {
struct vmcore *m; struct vmcore *m;
m = list_entry(pos, struct vmcore, list); m = list_first_entry(&vmcore_list, struct vmcore, list);
list_del(&m->list); list_del(&m->list);
kfree(m); kfree(m);
} }

View File

@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
size, unsigned long offset); size, unsigned long offset);
#endif #endif
#ifndef find_next_and_bit
/**
* find_next_and_bit - find the next set bit in both memory regions
* @addr1: The first address to base the search on
* @addr2: The second address to base the search on
* @offset: The bitnumber to start searching at
* @size: The bitmap size in bits
*
* Returns the bit number for the next set bit
* If no bits are set, returns @size.
*/
extern unsigned long find_next_and_bit(const unsigned long *addr1,
const unsigned long *addr2, unsigned long size,
unsigned long offset);
#endif
#ifndef find_next_zero_bit #ifndef find_next_zero_bit
/** /**
* find_next_zero_bit - find the next cleared bit in a memory region * find_next_zero_bit - find the next cleared bit in a memory region
@ -55,8 +71,12 @@ extern unsigned long find_first_zero_bit(const unsigned long *addr,
unsigned long size); unsigned long size);
#else /* CONFIG_GENERIC_FIND_FIRST_BIT */ #else /* CONFIG_GENERIC_FIND_FIRST_BIT */
#ifndef find_first_bit
#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) #define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
#endif
#ifndef find_first_zero_bit
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
#endif
#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */

View File

@ -64,9 +64,14 @@
* bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region * bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region
* bitmap_release_region(bitmap, pos, order) Free specified bit region * bitmap_release_region(bitmap, pos, order) Free specified bit region
* bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region
* bitmap_from_u32array(dst, nbits, buf, nwords) *dst = *buf (nwords 32b words) * bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst
* bitmap_to_u32array(buf, nwords, src, nbits) *buf = *dst (nwords 32b words) * bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst
* *
* Note, bitmap_zero() and bitmap_fill() operate over the region of
* unsigned longs, that is, bits behind bitmap till the unsigned long
* boundary will be zeroed or filled as well. Consider to use
* bitmap_clear() or bitmap_set() to make explicit zeroing or filling
* respectively.
*/ */
/** /**
@ -83,8 +88,12 @@
* test_and_change_bit(bit, addr) Change bit and return old value * test_and_change_bit(bit, addr) Change bit and return old value
* find_first_zero_bit(addr, nbits) Position first zero bit in *addr * find_first_zero_bit(addr, nbits) Position first zero bit in *addr
* find_first_bit(addr, nbits) Position first set bit in *addr * find_first_bit(addr, nbits) Position first set bit in *addr
* find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit * find_next_zero_bit(addr, nbits, bit)
* Position next zero bit in *addr >= bit
* find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
* find_next_and_bit(addr1, addr2, nbits, bit)
* Same as find_next_bit, but in
* (*addr1 & *addr2)
* *
*/ */
@ -174,14 +183,7 @@ extern void bitmap_fold(unsigned long *dst, const unsigned long *orig,
extern int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order); extern int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order);
extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order); extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order);
extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order); extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order);
extern unsigned int bitmap_from_u32array(unsigned long *bitmap,
unsigned int nbits,
const u32 *buf,
unsigned int nwords);
extern unsigned int bitmap_to_u32array(u32 *buf,
unsigned int nwords,
const unsigned long *bitmap,
unsigned int nbits);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
extern void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits); extern void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits);
#else #else
@ -209,12 +211,12 @@ static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
static inline void bitmap_fill(unsigned long *dst, unsigned int nbits) static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
{ {
unsigned int nlongs = BITS_TO_LONGS(nbits); if (small_const_nbits(nbits))
if (!small_const_nbits(nbits)) { *dst = ~0UL;
unsigned int len = (nlongs - 1) * sizeof(unsigned long); else {
memset(dst, 0xff, len); unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, 0xff, len);
} }
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
} }
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
@ -228,6 +230,35 @@ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
} }
} }
/*
* Copy bitmap and clear tail bits in last word.
*/
static inline void bitmap_copy_clear_tail(unsigned long *dst,
const unsigned long *src, unsigned int nbits)
{
bitmap_copy(dst, src, nbits);
if (nbits % BITS_PER_LONG)
dst[nbits / BITS_PER_LONG] &= BITMAP_LAST_WORD_MASK(nbits);
}
/*
* On 32-bit systems bitmaps are represented as u32 arrays internally, and
* therefore conversion is not needed when copying data from/to arrays of u32.
*/
#if BITS_PER_LONG == 64
extern void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
unsigned int nbits);
extern void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap,
unsigned int nbits);
#else
#define bitmap_from_arr32(bitmap, buf, nbits) \
bitmap_copy_clear_tail((unsigned long *) (bitmap), \
(const unsigned long *) (buf), (nbits))
#define bitmap_to_arr32(buf, bitmap, nbits) \
bitmap_copy_clear_tail((unsigned long *) (buf), \
(const unsigned long *) (bitmap), (nbits))
#endif
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, unsigned int nbits) const unsigned long *src2, unsigned int nbits)
{ {

View File

@ -8,7 +8,6 @@
#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) (0) #define __BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
#define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0) #define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0)
#define BUILD_BUG_ON_ZERO(e) (0) #define BUILD_BUG_ON_ZERO(e) (0)
#define BUILD_BUG_ON_NULL(e) ((void *)0)
#define BUILD_BUG_ON_INVALID(e) (0) #define BUILD_BUG_ON_INVALID(e) (0)
#define BUILD_BUG_ON_MSG(cond, msg) (0) #define BUILD_BUG_ON_MSG(cond, msg) (0)
#define BUILD_BUG_ON(condition) (0) #define BUILD_BUG_ON(condition) (0)
@ -28,7 +27,6 @@
* aren't permitted). * aren't permitted).
*/ */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:(-!!(e)); }))
/* /*
* BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the * BUILD_BUG_ON_INVALID() permits the compiler to check the validity of the

View File

@ -19,3 +19,11 @@
#define randomized_struct_fields_start struct { #define randomized_struct_fields_start struct {
#define randomized_struct_fields_end }; #define randomized_struct_fields_end };
/* all clang versions usable with the kernel support KASAN ABI version 5 */
#define KASAN_ABI_VERSION 5
/* emulate gcc's __SANITIZE_ADDRESS__ flag */
#if __has_feature(address_sanitizer)
#define __SANITIZE_ADDRESS__
#endif

View File

@ -640,7 +640,7 @@ static inline int cpulist_parse(const char *buf, struct cpumask *dstp)
/** /**
* cpumask_size - size to allocate for a 'struct cpumask' in bytes * cpumask_size - size to allocate for a 'struct cpumask' in bytes
*/ */
static inline size_t cpumask_size(void) static inline unsigned int cpumask_size(void)
{ {
return BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long); return BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long);
} }

View File

@ -112,7 +112,7 @@ static inline int cpuset_do_slab_mem_spread(void)
return task_spread_slab(current); return task_spread_slab(current);
} }
extern int current_cpuset_is_being_rebound(void); extern bool current_cpuset_is_being_rebound(void);
extern void rebuild_sched_domains(void); extern void rebuild_sched_domains(void);
@ -247,9 +247,9 @@ static inline int cpuset_do_slab_mem_spread(void)
return 0; return 0;
} }
static inline int current_cpuset_is_being_rebound(void) static inline bool current_cpuset_is_being_rebound(void)
{ {
return 0; return false;
} }
static inline void rebuild_sched_domains(void) static inline void rebuild_sched_domains(void)

View File

@ -2,13 +2,13 @@
#ifndef LINUX_CRASH_DUMP_H #ifndef LINUX_CRASH_DUMP_H
#define LINUX_CRASH_DUMP_H #define LINUX_CRASH_DUMP_H
#ifdef CONFIG_CRASH_DUMP
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <asm/pgtable.h> /* for pgprot_t */ #include <asm/pgtable.h> /* for pgprot_t */
#ifdef CONFIG_CRASH_DUMP
#define ELFCORE_ADDR_MAX (-1ULL) #define ELFCORE_ADDR_MAX (-1ULL)
#define ELFCORE_ADDR_ERR (-2ULL) #define ELFCORE_ADDR_ERR (-2ULL)
@ -52,13 +52,13 @@ void vmcore_cleanup(void);
* has passed the elf core header address on command line. * has passed the elf core header address on command line.
* *
* This is not just a test if CONFIG_CRASH_DUMP is enabled or not. It will * This is not just a test if CONFIG_CRASH_DUMP is enabled or not. It will
* return 1 if CONFIG_CRASH_DUMP=y and if kernel is booting after a panic of * return true if CONFIG_CRASH_DUMP=y and if kernel is booting after a panic
* previous kernel. * of previous kernel.
*/ */
static inline int is_kdump_kernel(void) static inline bool is_kdump_kernel(void)
{ {
return (elfcorehdr_addr != ELFCORE_ADDR_MAX) ? 1 : 0; return elfcorehdr_addr != ELFCORE_ADDR_MAX;
} }
/* is_vmcore_usable() checks if the kernel is booting after a panic and /* is_vmcore_usable() checks if the kernel is booting after a panic and
@ -89,7 +89,7 @@ extern int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn));
extern void unregister_oldmem_pfn_is_ram(void); extern void unregister_oldmem_pfn_is_ram(void);
#else /* !CONFIG_CRASH_DUMP */ #else /* !CONFIG_CRASH_DUMP */
static inline int is_kdump_kernel(void) { return 0; } static inline bool is_kdump_kernel(void) { return 0; }
#endif /* CONFIG_CRASH_DUMP */ #endif /* CONFIG_CRASH_DUMP */
extern unsigned long saved_max_pfn; extern unsigned long saved_max_pfn;

View File

@ -2,6 +2,7 @@
#ifndef GENL_MAGIC_FUNC_H #ifndef GENL_MAGIC_FUNC_H
#define GENL_MAGIC_FUNC_H #define GENL_MAGIC_FUNC_H
#include <linux/build_bug.h>
#include <linux/genl_magic_struct.h> #include <linux/genl_magic_struct.h>
/* /*
@ -132,17 +133,6 @@ static void dprint_array(const char *dir, int nla_type,
* use one static buffer for parsing of nested attributes */ * use one static buffer for parsing of nested attributes */
static struct nlattr *nested_attr_tb[128]; static struct nlattr *nested_attr_tb[128];
#ifndef BUILD_BUG_ON
/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
#endif
#undef GENL_struct #undef GENL_struct
#define GENL_struct(tag_name, tag_number, s_name, s_fields) \ #define GENL_struct(tag_name, tag_number, s_name, s_fields) \
/* *_from_attrs functions are static, but potentially unused */ \ /* *_from_attrs functions are static, but potentially unused */ \

View File

@ -265,7 +265,7 @@ extern struct resource * __devm_request_region(struct device *dev,
extern void __devm_release_region(struct device *dev, struct resource *parent, extern void __devm_release_region(struct device *dev, struct resource *parent,
resource_size_t start, resource_size_t n); resource_size_t start, resource_size_t n);
extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
extern int iomem_is_exclusive(u64 addr); extern bool iomem_is_exclusive(u64 addr);
extern int extern int
walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,

View File

@ -167,7 +167,7 @@ static inline int kallsyms_show_value(void)
static inline void print_ip_sym(unsigned long ip) static inline void print_ip_sym(unsigned long ip)
{ {
printk("[<%p>] %pS\n", (void *) ip, (void *) ip); printk("[<%px>] %pS\n", (void *) ip, (void *) ip);
} }
#endif /*_LINUX_KALLSYMS_H*/ #endif /*_LINUX_KALLSYMS_H*/

View File

@ -11,8 +11,6 @@ struct task_struct;
#ifdef CONFIG_KASAN #ifdef CONFIG_KASAN
#define KASAN_SHADOW_SCALE_SHIFT 3
#include <asm/kasan.h> #include <asm/kasan.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
@ -56,14 +54,14 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object);
void kasan_init_slab_obj(struct kmem_cache *cache, const void *object); void kasan_init_slab_obj(struct kmem_cache *cache, const void *object);
void kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags); void kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags);
void kasan_kfree_large(const void *ptr); void kasan_kfree_large(void *ptr, unsigned long ip);
void kasan_poison_kfree(void *ptr); void kasan_poison_kfree(void *ptr, unsigned long ip);
void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size, void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size,
gfp_t flags); gfp_t flags);
void kasan_krealloc(const void *object, size_t new_size, gfp_t flags); void kasan_krealloc(const void *object, size_t new_size, gfp_t flags);
void kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags); void kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags);
bool kasan_slab_free(struct kmem_cache *s, void *object); bool kasan_slab_free(struct kmem_cache *s, void *object, unsigned long ip);
struct kasan_cache { struct kasan_cache {
int alloc_meta_offset; int alloc_meta_offset;
@ -108,8 +106,8 @@ static inline void kasan_init_slab_obj(struct kmem_cache *cache,
const void *object) {} const void *object) {}
static inline void kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) {} static inline void kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) {}
static inline void kasan_kfree_large(const void *ptr) {} static inline void kasan_kfree_large(void *ptr, unsigned long ip) {}
static inline void kasan_poison_kfree(void *ptr) {} static inline void kasan_poison_kfree(void *ptr, unsigned long ip) {}
static inline void kasan_kmalloc(struct kmem_cache *s, const void *object, static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
size_t size, gfp_t flags) {} size_t size, gfp_t flags) {}
static inline void kasan_krealloc(const void *object, size_t new_size, static inline void kasan_krealloc(const void *object, size_t new_size,
@ -117,7 +115,8 @@ static inline void kasan_krealloc(const void *object, size_t new_size,
static inline void kasan_slab_alloc(struct kmem_cache *s, void *object, static inline void kasan_slab_alloc(struct kmem_cache *s, void *object,
gfp_t flags) {} gfp_t flags) {}
static inline bool kasan_slab_free(struct kmem_cache *s, void *object) static inline bool kasan_slab_free(struct kmem_cache *s, void *object,
unsigned long ip)
{ {
return false; return false;
} }

View File

@ -44,7 +44,7 @@ extern void lockref_mark_dead(struct lockref *);
extern int lockref_get_not_dead(struct lockref *); extern int lockref_get_not_dead(struct lockref *);
/* Must be called under spinlock for reliable results */ /* Must be called under spinlock for reliable results */
static inline int __lockref_is_dead(const struct lockref *l) static inline bool __lockref_is_dead(const struct lockref *l)
{ {
return ((int)l->count < 0); return ((int)l->count < 0);
} }

View File

@ -332,8 +332,8 @@ void memblock_enforce_memory_limit(phys_addr_t memory_limit);
void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size); void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
void memblock_mem_limit_remove_map(phys_addr_t limit); void memblock_mem_limit_remove_map(phys_addr_t limit);
bool memblock_is_memory(phys_addr_t addr); bool memblock_is_memory(phys_addr_t addr);
int memblock_is_map_memory(phys_addr_t addr); bool memblock_is_map_memory(phys_addr_t addr);
int memblock_is_region_memory(phys_addr_t base, phys_addr_t size); bool memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
bool memblock_is_reserved(phys_addr_t addr); bool memblock_is_reserved(phys_addr_t addr);
bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size); bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);

View File

@ -491,7 +491,7 @@ extern struct mutex module_mutex;
/* FIXME: It'd be nice to isolate modules during init, too, so they /* FIXME: It'd be nice to isolate modules during init, too, so they
aren't used before they (may) fail. But presently too much code aren't used before they (may) fail. But presently too much code
(IDE & SCSI) require entry into the module during init.*/ (IDE & SCSI) require entry into the module during init.*/
static inline int module_is_live(struct module *mod) static inline bool module_is_live(struct module *mod)
{ {
return mod->state != MODULE_STATE_GOING; return mod->state != MODULE_STATE_GOING;
} }

View File

@ -138,9 +138,9 @@ extern void __mutex_init(struct mutex *lock, const char *name,
* mutex_is_locked - is the mutex locked * mutex_is_locked - is the mutex locked
* @lock: the mutex to be queried * @lock: the mutex to be queried
* *
* Returns 1 if the mutex is locked, 0 if unlocked. * Returns true if the mutex is locked, false if unlocked.
*/ */
static inline int mutex_is_locked(struct mutex *lock) static inline bool mutex_is_locked(struct mutex *lock)
{ {
/* /*
* XXX think about spin_is_locked * XXX think about spin_is_locked

View File

@ -167,10 +167,9 @@ void pipe_lock(struct pipe_inode_info *);
void pipe_unlock(struct pipe_inode_info *); void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
extern unsigned int pipe_max_size, pipe_min_size; extern unsigned int pipe_max_size;
extern unsigned long pipe_user_pages_hard; extern unsigned long pipe_user_pages_hard;
extern unsigned long pipe_user_pages_soft; extern unsigned long pipe_user_pages_soft;
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
/* Drop the inode semaphore and wait for a pipe event, atomically */ /* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe); void pipe_wait(struct pipe_inode_info *pipe);
@ -191,6 +190,6 @@ long pipe_fcntl(struct file *, unsigned int, unsigned long arg);
struct pipe_inode_info *get_pipe_info(struct file *file); struct pipe_inode_info *get_pipe_info(struct file *file);
int create_pipe_files(struct file **, int); int create_pipe_files(struct file **, int);
unsigned int round_pipe_size(unsigned int size); unsigned int round_pipe_size(unsigned long size);
#endif #endif

View File

@ -1497,6 +1497,11 @@ static inline struct thread_info *task_thread_info(struct task_struct *task)
extern struct task_struct *find_task_by_vpid(pid_t nr); extern struct task_struct *find_task_by_vpid(pid_t nr);
extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns); extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns);
/*
* find a task by its virtual pid and get the task struct
*/
extern struct task_struct *find_get_task_by_vpid(pid_t nr);
extern int wake_up_state(struct task_struct *tsk, unsigned int state); extern int wake_up_state(struct task_struct *tsk, unsigned int state);
extern int wake_up_process(struct task_struct *tsk); extern int wake_up_process(struct task_struct *tsk);
extern void wake_up_new_task(struct task_struct *tsk); extern void wake_up_new_task(struct task_struct *tsk);

View File

@ -51,9 +51,6 @@ extern int proc_dointvec_minmax(struct ctl_table *, int,
extern int proc_douintvec_minmax(struct ctl_table *table, int write, extern int proc_douintvec_minmax(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, void __user *buffer, size_t *lenp,
loff_t *ppos); loff_t *ppos);
extern int proc_dopipe_max_size(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos);
extern int proc_dointvec_jiffies(struct ctl_table *, int, extern int proc_dointvec_jiffies(struct ctl_table *, int,
void __user *, size_t *, loff_t *); void __user *, size_t *, loff_t *);
extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int, extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int,

View File

@ -17,6 +17,7 @@
#define _LINUX_UUID_H_ #define _LINUX_UUID_H_
#include <uapi/linux/uuid.h> #include <uapi/linux/uuid.h>
#include <linux/string.h>
#define UUID_SIZE 16 #define UUID_SIZE 16

View File

@ -280,8 +280,8 @@ typedef struct siginfo {
#define NSIGTRAP 4 #define NSIGTRAP 4
/* /*
* There are an additional set of SIGTRAP si_codes used by ptrace * There is an additional set of SIGTRAP si_codes used by ptrace
* that of the form: ((PTRACE_EVENT_XXX << 8) | SIGTRAP) * that are of the form: ((PTRACE_EVENT_XXX << 8) | SIGTRAP)
*/ */
/* /*

View File

@ -19,7 +19,6 @@
#define _UAPI_LINUX_UUID_H_ #define _UAPI_LINUX_UUID_H_
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h>
typedef struct { typedef struct {
__u8 b[16]; __u8 b[16];

View File

@ -596,7 +596,7 @@ static void wq_add(struct mqueue_inode_info *info, int sr,
ewp->task = current; ewp->task = current;
list_for_each_entry(walk, &info->e_wait_q[sr].list, list) { list_for_each_entry(walk, &info->e_wait_q[sr].list, list) {
if (walk->task->static_prio <= current->static_prio) { if (walk->task->prio <= current->prio) {
list_add_tail(&ewp->list, &walk->list); list_add_tail(&ewp->list, &walk->list);
return; return;
} }

View File

@ -476,9 +476,9 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,
static int msgctl_stat(struct ipc_namespace *ns, int msqid, static int msgctl_stat(struct ipc_namespace *ns, int msqid,
int cmd, struct msqid64_ds *p) int cmd, struct msqid64_ds *p)
{ {
int err;
struct msg_queue *msq; struct msg_queue *msq;
int success_return; int id = 0;
int err;
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
@ -489,14 +489,13 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
err = PTR_ERR(msq); err = PTR_ERR(msq);
goto out_unlock; goto out_unlock;
} }
success_return = msq->q_perm.id; id = msq->q_perm.id;
} else { } else {
msq = msq_obtain_object_check(ns, msqid); msq = msq_obtain_object_check(ns, msqid);
if (IS_ERR(msq)) { if (IS_ERR(msq)) {
err = PTR_ERR(msq); err = PTR_ERR(msq);
goto out_unlock; goto out_unlock;
} }
success_return = 0;
} }
err = -EACCES; err = -EACCES;
@ -507,6 +506,14 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
if (err) if (err)
goto out_unlock; goto out_unlock;
ipc_lock_object(&msq->q_perm);
if (!ipc_valid_object(&msq->q_perm)) {
ipc_unlock_object(&msq->q_perm);
err = -EIDRM;
goto out_unlock;
}
kernel_to_ipc64_perm(&msq->q_perm, &p->msg_perm); kernel_to_ipc64_perm(&msq->q_perm, &p->msg_perm);
p->msg_stime = msq->q_stime; p->msg_stime = msq->q_stime;
p->msg_rtime = msq->q_rtime; p->msg_rtime = msq->q_rtime;
@ -516,9 +523,10 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
p->msg_qbytes = msq->q_qbytes; p->msg_qbytes = msq->q_qbytes;
p->msg_lspid = msq->q_lspid; p->msg_lspid = msq->q_lspid;
p->msg_lrpid = msq->q_lrpid; p->msg_lrpid = msq->q_lrpid;
rcu_read_unlock();
return success_return; ipc_unlock_object(&msq->q_perm);
rcu_read_unlock();
return id;
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();

View File

@ -1213,10 +1213,20 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
if (err) if (err)
goto out_unlock; goto out_unlock;
ipc_lock_object(&sma->sem_perm);
if (!ipc_valid_object(&sma->sem_perm)) {
ipc_unlock_object(&sma->sem_perm);
err = -EIDRM;
goto out_unlock;
}
kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm); kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
semid64->sem_otime = get_semotime(sma); semid64->sem_otime = get_semotime(sma);
semid64->sem_ctime = sma->sem_ctime; semid64->sem_ctime = sma->sem_ctime;
semid64->sem_nsems = sma->sem_nsems; semid64->sem_nsems = sma->sem_nsems;
ipc_unlock_object(&sma->sem_perm);
rcu_read_unlock(); rcu_read_unlock();
return id; return id;

View File

@ -909,9 +909,11 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
int cmd, struct shmid64_ds *tbuf) int cmd, struct shmid64_ds *tbuf)
{ {
struct shmid_kernel *shp; struct shmid_kernel *shp;
int result; int id = 0;
int err; int err;
memset(tbuf, 0, sizeof(*tbuf));
rcu_read_lock(); rcu_read_lock();
if (cmd == SHM_STAT) { if (cmd == SHM_STAT) {
shp = shm_obtain_object(ns, shmid); shp = shm_obtain_object(ns, shmid);
@ -919,14 +921,13 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
err = PTR_ERR(shp); err = PTR_ERR(shp);
goto out_unlock; goto out_unlock;
} }
result = shp->shm_perm.id; id = shp->shm_perm.id;
} else { } else {
shp = shm_obtain_object_check(ns, shmid); shp = shm_obtain_object_check(ns, shmid);
if (IS_ERR(shp)) { if (IS_ERR(shp)) {
err = PTR_ERR(shp); err = PTR_ERR(shp);
goto out_unlock; goto out_unlock;
} }
result = 0;
} }
err = -EACCES; err = -EACCES;
@ -937,7 +938,14 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
if (err) if (err)
goto out_unlock; goto out_unlock;
memset(tbuf, 0, sizeof(*tbuf)); ipc_lock_object(&shp->shm_perm);
if (!ipc_valid_object(&shp->shm_perm)) {
ipc_unlock_object(&shp->shm_perm);
err = -EIDRM;
goto out_unlock;
}
kernel_to_ipc64_perm(&shp->shm_perm, &tbuf->shm_perm); kernel_to_ipc64_perm(&shp->shm_perm, &tbuf->shm_perm);
tbuf->shm_segsz = shp->shm_segsz; tbuf->shm_segsz = shp->shm_segsz;
tbuf->shm_atime = shp->shm_atim; tbuf->shm_atime = shp->shm_atim;
@ -946,8 +954,10 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
tbuf->shm_cpid = shp->shm_cprid; tbuf->shm_cpid = shp->shm_cprid;
tbuf->shm_lpid = shp->shm_lprid; tbuf->shm_lpid = shp->shm_lprid;
tbuf->shm_nattch = shp->shm_nattch; tbuf->shm_nattch = shp->shm_nattch;
ipc_unlock_object(&shp->shm_perm);
rcu_read_unlock(); rcu_read_unlock();
return result; return id;
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();

View File

@ -23,9 +23,12 @@
* tree. * tree.
* - perform initial checks (capabilities, auditing and permission, * - perform initial checks (capabilities, auditing and permission,
* etc). * etc).
* - perform read-only operations, such as STAT, INFO commands. * - perform read-only operations, such as INFO command, that
* do not demand atomicity
* acquire the ipc lock (kern_ipc_perm.lock) through * acquire the ipc lock (kern_ipc_perm.lock) through
* ipc_lock_object() * ipc_lock_object()
* - perform read-only operations that demand atomicity,
* such as STAT command.
* - perform data updates, such as SET, RMID commands and * - perform data updates, such as SET, RMID commands and
* mechanism-specific operations (semop/semtimedop, * mechanism-specific operations (semop/semtimedop,
* msgsnd/msgrcv, shmat/shmdt). * msgsnd/msgrcv, shmat/shmdt).

View File

@ -84,20 +84,24 @@ static atomic_t entry_count;
static async_cookie_t lowest_in_progress(struct async_domain *domain) static async_cookie_t lowest_in_progress(struct async_domain *domain)
{ {
struct list_head *pending; struct async_entry *first = NULL;
async_cookie_t ret = ASYNC_COOKIE_MAX; async_cookie_t ret = ASYNC_COOKIE_MAX;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&async_lock, flags); spin_lock_irqsave(&async_lock, flags);
if (domain) if (domain) {
pending = &domain->pending; if (!list_empty(&domain->pending))
else first = list_first_entry(&domain->pending,
pending = &async_global_pending; struct async_entry, domain_list);
} else {
if (!list_empty(&async_global_pending))
first = list_first_entry(&async_global_pending,
struct async_entry, global_list);
}
if (!list_empty(pending)) if (first)
ret = list_first_entry(pending, struct async_entry, ret = first->cookie;
domain_list)->cookie;
spin_unlock_irqrestore(&async_lock, flags); spin_unlock_irqrestore(&async_lock, flags);
return ret; return ret;

View File

@ -1254,9 +1254,9 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
return retval; return retval;
} }
int current_cpuset_is_being_rebound(void) bool current_cpuset_is_being_rebound(void)
{ {
int ret; bool ret;
rcu_read_lock(); rcu_read_lock();
ret = task_cs(current) == cpuset_being_rebound; ret = task_cs(current) == cpuset_being_rebound;

View File

@ -355,7 +355,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len,
ret = sched_getaffinity(pid, mask); ret = sched_getaffinity(pid, mask);
if (ret == 0) { if (ret == 0) {
size_t retlen = min_t(size_t, len, cpumask_size()); unsigned int retlen = min(len, cpumask_size());
if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8)) if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8))
ret = -EFAULT; ret = -EFAULT;

View File

@ -10,3 +10,7 @@ CONFIG_OPTIMIZE_INLINING=y
# CONFIG_SLAB is not set # CONFIG_SLAB is not set
# CONFIG_SLUB is not set # CONFIG_SLUB is not set
CONFIG_SLOB=y CONFIG_SLOB=y
CONFIG_CC_STACKPROTECTOR_NONE=y
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
# CONFIG_CC_STACKPROTECTOR_STRONG is not set
# CONFIG_CC_STACKPROTECTOR_AUTO is not set

View File

@ -1592,6 +1592,10 @@ static __latent_entropy struct task_struct *copy_process(
int retval; int retval;
struct task_struct *p; struct task_struct *p;
/*
* Don't allow sharing the root directory with processes in a different
* namespace
*/
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -2067,6 +2071,8 @@ long _do_fork(unsigned long clone_flags,
int __user *child_tidptr, int __user *child_tidptr,
unsigned long tls) unsigned long tls)
{ {
struct completion vfork;
struct pid *pid;
struct task_struct *p; struct task_struct *p;
int trace = 0; int trace = 0;
long nr; long nr;
@ -2092,43 +2098,40 @@ long _do_fork(unsigned long clone_flags,
p = copy_process(clone_flags, stack_start, stack_size, p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace, tls, NUMA_NO_NODE); child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
add_latent_entropy(); add_latent_entropy();
if (IS_ERR(p))
return PTR_ERR(p);
/* /*
* Do this prior waking up the new thread - the thread pointer * Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly. * might get invalid after that point, if the thread exits quickly.
*/ */
if (!IS_ERR(p)) { trace_sched_process_fork(current, p);
struct completion vfork;
struct pid *pid;
trace_sched_process_fork(current, p); pid = get_task_pid(p, PIDTYPE_PID);
nr = pid_vnr(pid);
pid = get_task_pid(p, PIDTYPE_PID); if (clone_flags & CLONE_PARENT_SETTID)
nr = pid_vnr(pid); put_user(nr, parent_tidptr);
if (clone_flags & CLONE_PARENT_SETTID) if (clone_flags & CLONE_VFORK) {
put_user(nr, parent_tidptr); p->vfork_done = &vfork;
init_completion(&vfork);
if (clone_flags & CLONE_VFORK) { get_task_struct(p);
p->vfork_done = &vfork;
init_completion(&vfork);
get_task_struct(p);
}
wake_up_new_task(p);
/* forking complete and child started to run, tell ptracer */
if (unlikely(trace))
ptrace_event_pid(trace, pid);
if (clone_flags & CLONE_VFORK) {
if (!wait_for_vfork_done(p, &vfork))
ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
}
put_pid(pid);
} else {
nr = PTR_ERR(p);
} }
wake_up_new_task(p);
/* forking complete and child started to run, tell ptracer */
if (unlikely(trace))
ptrace_event_pid(trace, pid);
if (clone_flags & CLONE_VFORK) {
if (!wait_for_vfork_done(p, &vfork))
ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
}
put_pid(pid);
return nr; return nr;
} }

View File

@ -862,24 +862,6 @@ static void put_pi_state(struct futex_pi_state *pi_state)
} }
} }
/*
* Look up the task based on what TID userspace gave us.
* We dont trust it.
*/
static struct task_struct *futex_find_get_task(pid_t pid)
{
struct task_struct *p;
rcu_read_lock();
p = find_task_by_vpid(pid);
if (p)
get_task_struct(p);
rcu_read_unlock();
return p;
}
#ifdef CONFIG_FUTEX_PI #ifdef CONFIG_FUTEX_PI
/* /*
@ -1183,7 +1165,7 @@ static int attach_to_pi_owner(u32 uval, union futex_key *key,
*/ */
if (!pid) if (!pid)
return -ESRCH; return -ESRCH;
p = futex_find_get_task(pid); p = find_get_task_by_vpid(pid);
if (!p) if (!p)
return -ESRCH; return -ESRCH;

View File

@ -10,7 +10,6 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/timer.h> #include <linux/timer.h>

View File

@ -358,7 +358,8 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
*/ */
if (kcov->mode != KCOV_MODE_INIT || !kcov->area) if (kcov->mode != KCOV_MODE_INIT || !kcov->area)
return -EINVAL; return -EINVAL;
if (kcov->t != NULL) t = current;
if (kcov->t != NULL || t->kcov != NULL)
return -EBUSY; return -EBUSY;
if (arg == KCOV_TRACE_PC) if (arg == KCOV_TRACE_PC)
kcov->mode = KCOV_MODE_TRACE_PC; kcov->mode = KCOV_MODE_TRACE_PC;
@ -370,7 +371,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
#endif #endif
else else
return -EINVAL; return -EINVAL;
t = current;
/* Cache in task struct for performance. */ /* Cache in task struct for performance. */
t->kcov_size = kcov->size; t->kcov_size = kcov->size;
t->kcov_area = kcov->area; t->kcov_area = kcov->area;

View File

@ -343,6 +343,19 @@ struct task_struct *find_task_by_vpid(pid_t vnr)
return find_task_by_pid_ns(vnr, task_active_pid_ns(current)); return find_task_by_pid_ns(vnr, task_active_pid_ns(current));
} }
struct task_struct *find_get_task_by_vpid(pid_t nr)
{
struct task_struct *task;
rcu_read_lock();
task = find_task_by_vpid(nr);
if (task)
get_task_struct(task);
rcu_read_unlock();
return task;
}
struct pid *get_task_pid(struct task_struct *task, enum pid_type type) struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
{ {
struct pid *pid; struct pid *pid;

View File

@ -1103,21 +1103,6 @@ int ptrace_request(struct task_struct *child, long request,
return ret; return ret;
} }
static struct task_struct *ptrace_get_task_struct(pid_t pid)
{
struct task_struct *child;
rcu_read_lock();
child = find_task_by_vpid(pid);
if (child)
get_task_struct(child);
rcu_read_unlock();
if (!child)
return ERR_PTR(-ESRCH);
return child;
}
#ifndef arch_ptrace_attach #ifndef arch_ptrace_attach
#define arch_ptrace_attach(child) do { } while (0) #define arch_ptrace_attach(child) do { } while (0)
#endif #endif
@ -1135,9 +1120,9 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
goto out; goto out;
} }
child = ptrace_get_task_struct(pid); child = find_get_task_by_vpid(pid);
if (IS_ERR(child)) { if (!child) {
ret = PTR_ERR(child); ret = -ESRCH;
goto out; goto out;
} }
@ -1281,9 +1266,9 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
goto out; goto out;
} }
child = ptrace_get_task_struct(pid); child = find_get_task_by_vpid(pid);
if (IS_ERR(child)) { if (!child) {
ret = PTR_ERR(child); ret = -ESRCH;
goto out; goto out;
} }

View File

@ -611,7 +611,6 @@ struct rchan *relay_open(const char *base_filename,
kref_put(&chan->kref, relay_destroy_channel); kref_put(&chan->kref, relay_destroy_channel);
mutex_unlock(&relay_channels_mutex); mutex_unlock(&relay_channels_mutex);
kfree(chan);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(relay_open); EXPORT_SYMBOL_GPL(relay_open);

View File

@ -1576,17 +1576,17 @@ static int strict_iomem_checks;
/* /*
* check if an address is reserved in the iomem resource tree * check if an address is reserved in the iomem resource tree
* returns 1 if reserved, 0 if not reserved. * returns true if reserved, false if not reserved.
*/ */
int iomem_is_exclusive(u64 addr) bool iomem_is_exclusive(u64 addr)
{ {
struct resource *p = &iomem_resource; struct resource *p = &iomem_resource;
int err = 0; bool err = false;
loff_t l; loff_t l;
int size = PAGE_SIZE; int size = PAGE_SIZE;
if (!strict_iomem_checks) if (!strict_iomem_checks)
return 0; return false;
addr = addr & PAGE_MASK; addr = addr & PAGE_MASK;
@ -1609,7 +1609,7 @@ int iomem_is_exclusive(u64 addr)
continue; continue;
if (IS_ENABLED(CONFIG_IO_STRICT_DEVMEM) if (IS_ENABLED(CONFIG_IO_STRICT_DEVMEM)
|| p->flags & IORESOURCE_EXCLUSIVE) { || p->flags & IORESOURCE_EXCLUSIVE) {
err = 1; err = true;
break; break;
} }
} }

View File

@ -4867,7 +4867,7 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
ret = sched_getaffinity(pid, mask); ret = sched_getaffinity(pid, mask);
if (ret == 0) { if (ret == 0) {
size_t retlen = min_t(size_t, len, cpumask_size()); unsigned int retlen = min(len, cpumask_size());
if (copy_to_user(user_mask_ptr, mask, retlen)) if (copy_to_user(user_mask_ptr, mask, retlen))
ret = -EFAULT; ret = -EFAULT;

View File

@ -218,6 +218,8 @@ static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
static int proc_dostring_coredump(struct ctl_table *table, int write, static int proc_dostring_coredump(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos); void __user *buffer, size_t *lenp, loff_t *ppos);
#endif #endif
static int proc_dopipe_max_size(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
/* Note: sysrq code uses it's own private copy */ /* Note: sysrq code uses it's own private copy */
@ -1812,8 +1814,7 @@ static struct ctl_table fs_table[] = {
.data = &pipe_max_size, .data = &pipe_max_size,
.maxlen = sizeof(pipe_max_size), .maxlen = sizeof(pipe_max_size),
.mode = 0644, .mode = 0644,
.proc_handler = &pipe_proc_fn, .proc_handler = proc_dopipe_max_size,
.extra1 = &pipe_min_size,
}, },
{ {
.procname = "pipe-user-pages-hard", .procname = "pipe-user-pages-hard",
@ -2615,29 +2616,17 @@ int proc_douintvec_minmax(struct ctl_table *table, int write,
do_proc_douintvec_minmax_conv, &param); do_proc_douintvec_minmax_conv, &param);
} }
struct do_proc_dopipe_max_size_conv_param {
unsigned int *min;
};
static int do_proc_dopipe_max_size_conv(unsigned long *lvalp, static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
unsigned int *valp, unsigned int *valp,
int write, void *data) int write, void *data)
{ {
struct do_proc_dopipe_max_size_conv_param *param = data;
if (write) { if (write) {
unsigned int val; unsigned int val;
if (*lvalp > UINT_MAX)
return -EINVAL;
val = round_pipe_size(*lvalp); val = round_pipe_size(*lvalp);
if (val == 0) if (val == 0)
return -EINVAL; return -EINVAL;
if (param->min && *param->min > val)
return -ERANGE;
*valp = val; *valp = val;
} else { } else {
unsigned int val = *valp; unsigned int val = *valp;
@ -2647,14 +2636,11 @@ static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
return 0; return 0;
} }
int proc_dopipe_max_size(struct ctl_table *table, int write, static int proc_dopipe_max_size(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
struct do_proc_dopipe_max_size_conv_param param = {
.min = (unsigned int *) table->extra1,
};
return do_proc_douintvec(table, write, buffer, lenp, ppos, return do_proc_douintvec(table, write, buffer, lenp, ppos,
do_proc_dopipe_max_size_conv, &param); do_proc_dopipe_max_size_conv, NULL);
} }
static void validate_coredump_safety(void) static void validate_coredump_safety(void)
@ -3160,12 +3146,6 @@ int proc_douintvec_minmax(struct ctl_table *table, int write,
return -ENOSYS; return -ENOSYS;
} }
int proc_dopipe_max_size(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
return -ENOSYS;
}
int proc_dointvec_jiffies(struct ctl_table *table, int write, int proc_dointvec_jiffies(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
@ -3209,7 +3189,6 @@ EXPORT_SYMBOL(proc_douintvec);
EXPORT_SYMBOL(proc_dointvec_jiffies); EXPORT_SYMBOL(proc_dointvec_jiffies);
EXPORT_SYMBOL(proc_dointvec_minmax); EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL_GPL(proc_douintvec_minmax); EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
EXPORT_SYMBOL_GPL(proc_dopipe_max_size);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies); EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring); EXPORT_SYMBOL(proc_dostring);

View File

@ -194,11 +194,7 @@ static int fill_stats_for_pid(pid_t pid, struct taskstats *stats)
{ {
struct task_struct *tsk; struct task_struct *tsk;
rcu_read_lock(); tsk = find_get_task_by_vpid(pid);
tsk = find_task_by_vpid(pid);
if (tsk)
get_task_struct(tsk);
rcu_read_unlock();
if (!tsk) if (!tsk)
return -ESRCH; return -ESRCH;
fill_stats(current_user_ns(), task_active_pid_ns(current), tsk, stats); fill_stats(current_user_ns(), task_active_pid_ns(current), tsk, stats);

View File

@ -37,7 +37,6 @@
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/kallsyms.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>

View File

@ -217,7 +217,7 @@ config ENABLE_MUST_CHECK
config FRAME_WARN config FRAME_WARN
int "Warn for stack frames larger than (needs gcc 4.4)" int "Warn for stack frames larger than (needs gcc 4.4)"
range 0 8192 range 0 8192
default 0 if KASAN default 3072 if KASAN_EXTRA
default 2048 if GCC_PLUGIN_LATENT_ENTROPY default 2048 if GCC_PLUGIN_LATENT_ENTROPY
default 1280 if (!64BIT && PARISC) default 1280 if (!64BIT && PARISC)
default 1024 if (!64BIT && !PARISC) default 1024 if (!64BIT && !PARISC)
@ -1641,7 +1641,10 @@ config DMA_API_DEBUG
If unsure, say N. If unsure, say N.
menu "Runtime Testing" menuconfig RUNTIME_TESTING_MENU
bool "Runtime Testing"
if RUNTIME_TESTING_MENU
config LKDTM config LKDTM
tristate "Linux Kernel Dump Test Tool Module" tristate "Linux Kernel Dump Test Tool Module"
@ -1841,7 +1844,7 @@ config TEST_BPF
If unsure, say N. If unsure, say N.
config TEST_FIND_BIT config FIND_BIT_BENCHMARK
tristate "Test find_bit functions" tristate "Test find_bit functions"
default n default n
help help
@ -1929,7 +1932,7 @@ config TEST_DEBUG_VIRTUAL
If unsure, say N. If unsure, say N.
endmenu # runtime tests endif # RUNTIME_TESTING_MENU
config MEMTEST config MEMTEST
bool "Memtest" bool "Memtest"

View File

@ -20,6 +20,17 @@ config KASAN
Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB
(the resulting kernel does not boot). (the resulting kernel does not boot).
config KASAN_EXTRA
bool "KAsan: extra checks"
depends on KASAN && DEBUG_KERNEL && !COMPILE_TEST
help
This enables further checks in the kernel address sanitizer, for now
it only includes the address-use-after-scope check that can lead
to excessive kernel stack usage, frame size warnings and longer
compile time.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 has more
choice choice
prompt "Instrumentation type" prompt "Instrumentation type"
depends on KASAN depends on KASAN

View File

@ -46,8 +46,8 @@ obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
obj-y += hexdump.o obj-y += hexdump.o
obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
obj-y += kstrtox.o obj-y += kstrtox.o
obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
obj-$(CONFIG_TEST_BPF) += test_bpf.o obj-$(CONFIG_TEST_BPF) += test_bpf.o
obj-$(CONFIG_TEST_FIND_BIT) += test_find_bit.o
obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o

View File

@ -1105,93 +1105,6 @@ int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order)
} }
EXPORT_SYMBOL(bitmap_allocate_region); EXPORT_SYMBOL(bitmap_allocate_region);
/**
* bitmap_from_u32array - copy the contents of a u32 array of bits to bitmap
* @bitmap: array of unsigned longs, the destination bitmap, non NULL
* @nbits: number of bits in @bitmap
* @buf: array of u32 (in host byte order), the source bitmap, non NULL
* @nwords: number of u32 words in @buf
*
* copy min(nbits, 32*nwords) bits from @buf to @bitmap, remaining
* bits between nword and nbits in @bitmap (if any) are cleared. In
* last word of @bitmap, the bits beyond nbits (if any) are kept
* unchanged.
*
* Return the number of bits effectively copied.
*/
unsigned int
bitmap_from_u32array(unsigned long *bitmap, unsigned int nbits,
const u32 *buf, unsigned int nwords)
{
unsigned int dst_idx, src_idx;
for (src_idx = dst_idx = 0; dst_idx < BITS_TO_LONGS(nbits); ++dst_idx) {
unsigned long part = 0;
if (src_idx < nwords)
part = buf[src_idx++];
#if BITS_PER_LONG == 64
if (src_idx < nwords)
part |= ((unsigned long) buf[src_idx++]) << 32;
#endif
if (dst_idx < nbits/BITS_PER_LONG)
bitmap[dst_idx] = part;
else {
unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);
bitmap[dst_idx] = (bitmap[dst_idx] & ~mask)
| (part & mask);
}
}
return min_t(unsigned int, nbits, 32*nwords);
}
EXPORT_SYMBOL(bitmap_from_u32array);
/**
* bitmap_to_u32array - copy the contents of bitmap to a u32 array of bits
* @buf: array of u32 (in host byte order), the dest bitmap, non NULL
* @nwords: number of u32 words in @buf
* @bitmap: array of unsigned longs, the source bitmap, non NULL
* @nbits: number of bits in @bitmap
*
* copy min(nbits, 32*nwords) bits from @bitmap to @buf. Remaining
* bits after nbits in @buf (if any) are cleared.
*
* Return the number of bits effectively copied.
*/
unsigned int
bitmap_to_u32array(u32 *buf, unsigned int nwords,
const unsigned long *bitmap, unsigned int nbits)
{
unsigned int dst_idx = 0, src_idx = 0;
while (dst_idx < nwords) {
unsigned long part = 0;
if (src_idx < BITS_TO_LONGS(nbits)) {
part = bitmap[src_idx];
if (src_idx >= nbits/BITS_PER_LONG)
part &= BITMAP_LAST_WORD_MASK(nbits);
src_idx++;
}
buf[dst_idx++] = part & 0xffffffffUL;
#if BITS_PER_LONG == 64
if (dst_idx < nwords) {
part >>= 32;
buf[dst_idx++] = part & 0xffffffffUL;
}
#endif
}
return min_t(unsigned int, nbits, 32*nwords);
}
EXPORT_SYMBOL(bitmap_to_u32array);
/** /**
* bitmap_copy_le - copy a bitmap, putting the bits into little-endian order. * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.
* @dst: destination buffer * @dst: destination buffer
@ -1214,3 +1127,59 @@ void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int n
} }
EXPORT_SYMBOL(bitmap_copy_le); EXPORT_SYMBOL(bitmap_copy_le);
#endif #endif
#if BITS_PER_LONG == 64
/**
* bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap
* @bitmap: array of unsigned longs, the destination bitmap
* @buf: array of u32 (in host byte order), the source bitmap
* @nbits: number of bits in @bitmap
*/
void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
unsigned int nbits)
{
unsigned int i, halfwords;
if (!nbits)
return;
halfwords = DIV_ROUND_UP(nbits, 32);
for (i = 0; i < halfwords; i++) {
bitmap[i/2] = (unsigned long) buf[i];
if (++i < halfwords)
bitmap[i/2] |= ((unsigned long) buf[i]) << 32;
}
/* Clear tail bits in last word beyond nbits. */
if (nbits % BITS_PER_LONG)
bitmap[(halfwords - 1) / 2] &= BITMAP_LAST_WORD_MASK(nbits);
}
EXPORT_SYMBOL(bitmap_from_arr32);
/**
* bitmap_to_arr32 - copy the contents of bitmap to a u32 array of bits
* @buf: array of u32 (in host byte order), the dest bitmap
* @bitmap: array of unsigned longs, the source bitmap
* @nbits: number of bits in @bitmap
*/
void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
{
unsigned int i, halfwords;
if (!nbits)
return;
halfwords = DIV_ROUND_UP(nbits, 32);
for (i = 0; i < halfwords; i++) {
buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
if (++i < halfwords)
buf[i] = (u32) (bitmap[i/2] >> 32);
}
/* Clear tail bits in last element of array beyond nbits. */
if (nbits % BITS_PER_LONG)
buf[halfwords - 1] &= (u32) (UINT_MAX >> ((-nbits) & 31));
}
EXPORT_SYMBOL(bitmap_to_arr32);
#endif

View File

@ -33,10 +33,11 @@ EXPORT_SYMBOL(cpumask_next);
int cpumask_next_and(int n, const struct cpumask *src1p, int cpumask_next_and(int n, const struct cpumask *src1p,
const struct cpumask *src2p) const struct cpumask *src2p)
{ {
while ((n = cpumask_next(n, src1p)) < nr_cpu_ids) /* -1 is a legal arg here. */
if (cpumask_test_cpu(n, src2p)) if (n != -1)
break; cpumask_check(n);
return n; return find_next_and_bit(cpumask_bits(src1p), cpumask_bits(src2p),
nr_cpumask_bits, n + 1);
} }
EXPORT_SYMBOL(cpumask_next_and); EXPORT_SYMBOL(cpumask_next_and);

View File

@ -21,22 +21,29 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#if !defined(find_next_bit) || !defined(find_next_zero_bit) #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
!defined(find_next_and_bit)
/* /*
* This is a common helper function for find_next_bit and * This is a common helper function for find_next_bit, find_next_zero_bit, and
* find_next_zero_bit. The difference is the "invert" argument, which * find_next_and_bit. The differences are:
* is XORed with each fetched word before searching it for one bits. * - The "invert" argument, which is XORed with each fetched word before
* searching it for one bits.
* - The optional "addr2", which is anded with "addr1" if present.
*/ */
static unsigned long _find_next_bit(const unsigned long *addr, static inline unsigned long _find_next_bit(const unsigned long *addr1,
unsigned long nbits, unsigned long start, unsigned long invert) const unsigned long *addr2, unsigned long nbits,
unsigned long start, unsigned long invert)
{ {
unsigned long tmp; unsigned long tmp;
if (unlikely(start >= nbits)) if (unlikely(start >= nbits))
return nbits; return nbits;
tmp = addr[start / BITS_PER_LONG] ^ invert; tmp = addr1[start / BITS_PER_LONG];
if (addr2)
tmp &= addr2[start / BITS_PER_LONG];
tmp ^= invert;
/* Handle 1st word. */ /* Handle 1st word. */
tmp &= BITMAP_FIRST_WORD_MASK(start); tmp &= BITMAP_FIRST_WORD_MASK(start);
@ -47,7 +54,10 @@ static unsigned long _find_next_bit(const unsigned long *addr,
if (start >= nbits) if (start >= nbits)
return nbits; return nbits;
tmp = addr[start / BITS_PER_LONG] ^ invert; tmp = addr1[start / BITS_PER_LONG];
if (addr2)
tmp &= addr2[start / BITS_PER_LONG];
tmp ^= invert;
} }
return min(start + __ffs(tmp), nbits); return min(start + __ffs(tmp), nbits);
@ -61,7 +71,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
unsigned long offset) unsigned long offset)
{ {
return _find_next_bit(addr, size, offset, 0UL); return _find_next_bit(addr, NULL, size, offset, 0UL);
} }
EXPORT_SYMBOL(find_next_bit); EXPORT_SYMBOL(find_next_bit);
#endif #endif
@ -70,11 +80,21 @@ EXPORT_SYMBOL(find_next_bit);
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
unsigned long offset) unsigned long offset)
{ {
return _find_next_bit(addr, size, offset, ~0UL); return _find_next_bit(addr, NULL, size, offset, ~0UL);
} }
EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_next_zero_bit);
#endif #endif
#if !defined(find_next_and_bit)
unsigned long find_next_and_bit(const unsigned long *addr1,
const unsigned long *addr2, unsigned long size,
unsigned long offset)
{
return _find_next_bit(addr1, addr2, size, offset, 0UL);
}
EXPORT_SYMBOL(find_next_and_bit);
#endif
#ifndef find_first_bit #ifndef find_first_bit
/* /*
* Find the first set bit in a memory region. * Find the first set bit in a memory region.
@ -146,15 +166,19 @@ static inline unsigned long ext2_swab(const unsigned long y)
} }
#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) #if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
static unsigned long _find_next_bit_le(const unsigned long *addr, static inline unsigned long _find_next_bit_le(const unsigned long *addr1,
unsigned long nbits, unsigned long start, unsigned long invert) const unsigned long *addr2, unsigned long nbits,
unsigned long start, unsigned long invert)
{ {
unsigned long tmp; unsigned long tmp;
if (unlikely(start >= nbits)) if (unlikely(start >= nbits))
return nbits; return nbits;
tmp = addr[start / BITS_PER_LONG] ^ invert; tmp = addr1[start / BITS_PER_LONG];
if (addr2)
tmp &= addr2[start / BITS_PER_LONG];
tmp ^= invert;
/* Handle 1st word. */ /* Handle 1st word. */
tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
@ -165,7 +189,10 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
if (start >= nbits) if (start >= nbits)
return nbits; return nbits;
tmp = addr[start / BITS_PER_LONG] ^ invert; tmp = addr1[start / BITS_PER_LONG];
if (addr2)
tmp &= addr2[start / BITS_PER_LONG];
tmp ^= invert;
} }
return min(start + __ffs(ext2_swab(tmp)), nbits); return min(start + __ffs(ext2_swab(tmp)), nbits);
@ -176,7 +203,7 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
unsigned long find_next_zero_bit_le(const void *addr, unsigned unsigned long find_next_zero_bit_le(const void *addr, unsigned
long size, unsigned long offset) long size, unsigned long offset)
{ {
return _find_next_bit_le(addr, size, offset, ~0UL); return _find_next_bit_le(addr, NULL, size, offset, ~0UL);
} }
EXPORT_SYMBOL(find_next_zero_bit_le); EXPORT_SYMBOL(find_next_zero_bit_le);
#endif #endif
@ -185,7 +212,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le);
unsigned long find_next_bit_le(const void *addr, unsigned unsigned long find_next_bit_le(const void *addr, unsigned
long size, unsigned long offset) long size, unsigned long offset)
{ {
return _find_next_bit_le(addr, size, offset, 0UL); return _find_next_bit_le(addr, NULL, size, offset, 0UL);
} }
EXPORT_SYMBOL(find_next_bit_le); EXPORT_SYMBOL(find_next_bit_le);
#endif #endif

View File

@ -35,6 +35,7 @@
#define SPARSE 500 #define SPARSE 500
static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata; static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata;
static DECLARE_BITMAP(bitmap2, BITMAP_LEN) __initdata;
/* /*
* This is Schlemiel the Painter's algorithm. It should be called after * This is Schlemiel the Painter's algorithm. It should be called after
@ -43,16 +44,15 @@ static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata;
static int __init test_find_first_bit(void *bitmap, unsigned long len) static int __init test_find_first_bit(void *bitmap, unsigned long len)
{ {
unsigned long i, cnt; unsigned long i, cnt;
cycles_t cycles; ktime_t time;
cycles = get_cycles(); time = ktime_get();
for (cnt = i = 0; i < len; cnt++) { for (cnt = i = 0; i < len; cnt++) {
i = find_first_bit(bitmap, len); i = find_first_bit(bitmap, len);
__clear_bit(i, bitmap); __clear_bit(i, bitmap);
} }
cycles = get_cycles() - cycles; time = ktime_get() - time;
pr_err("find_first_bit:\t\t%llu cycles,\t%ld iterations\n", pr_err("find_first_bit: %18llu ns, %6ld iterations\n", time, cnt);
(u64)cycles, cnt);
return 0; return 0;
} }
@ -60,14 +60,13 @@ static int __init test_find_first_bit(void *bitmap, unsigned long len)
static int __init test_find_next_bit(const void *bitmap, unsigned long len) static int __init test_find_next_bit(const void *bitmap, unsigned long len)
{ {
unsigned long i, cnt; unsigned long i, cnt;
cycles_t cycles; ktime_t time;
cycles = get_cycles(); time = ktime_get();
for (cnt = i = 0; i < BITMAP_LEN; cnt++) for (cnt = i = 0; i < BITMAP_LEN; cnt++)
i = find_next_bit(bitmap, BITMAP_LEN, i) + 1; i = find_next_bit(bitmap, BITMAP_LEN, i) + 1;
cycles = get_cycles() - cycles; time = ktime_get() - time;
pr_err("find_next_bit:\t\t%llu cycles,\t%ld iterations\n", pr_err("find_next_bit: %18llu ns, %6ld iterations\n", time, cnt);
(u64)cycles, cnt);
return 0; return 0;
} }
@ -75,14 +74,13 @@ static int __init test_find_next_bit(const void *bitmap, unsigned long len)
static int __init test_find_next_zero_bit(const void *bitmap, unsigned long len) static int __init test_find_next_zero_bit(const void *bitmap, unsigned long len)
{ {
unsigned long i, cnt; unsigned long i, cnt;
cycles_t cycles; ktime_t time;
cycles = get_cycles(); time = ktime_get();
for (cnt = i = 0; i < BITMAP_LEN; cnt++) for (cnt = i = 0; i < BITMAP_LEN; cnt++)
i = find_next_zero_bit(bitmap, len, i) + 1; i = find_next_zero_bit(bitmap, len, i) + 1;
cycles = get_cycles() - cycles; time = ktime_get() - time;
pr_err("find_next_zero_bit:\t%llu cycles,\t%ld iterations\n", pr_err("find_next_zero_bit: %18llu ns, %6ld iterations\n", time, cnt);
(u64)cycles, cnt);
return 0; return 0;
} }
@ -90,9 +88,9 @@ static int __init test_find_next_zero_bit(const void *bitmap, unsigned long len)
static int __init test_find_last_bit(const void *bitmap, unsigned long len) static int __init test_find_last_bit(const void *bitmap, unsigned long len)
{ {
unsigned long l, cnt = 0; unsigned long l, cnt = 0;
cycles_t cycles; ktime_t time;
cycles = get_cycles(); time = ktime_get();
do { do {
cnt++; cnt++;
l = find_last_bit(bitmap, len); l = find_last_bit(bitmap, len);
@ -100,9 +98,24 @@ static int __init test_find_last_bit(const void *bitmap, unsigned long len)
break; break;
len = l; len = l;
} while (len); } while (len);
time = ktime_get() - time;
pr_err("find_last_bit: %18llu ns, %6ld iterations\n", time, cnt);
return 0;
}
static int __init test_find_next_and_bit(const void *bitmap,
const void *bitmap2, unsigned long len)
{
unsigned long i, cnt;
cycles_t cycles;
cycles = get_cycles();
for (cnt = i = 0; i < BITMAP_LEN; cnt++)
i = find_next_and_bit(bitmap, bitmap2, BITMAP_LEN, i+1);
cycles = get_cycles() - cycles; cycles = get_cycles() - cycles;
pr_err("find_last_bit:\t\t%llu cycles,\t%ld iterations\n", pr_err("find_next_and_bit:\t\t%llu cycles, %ld iterations\n",
(u64)cycles, cnt); (u64)cycles, cnt);
return 0; return 0;
} }
@ -114,31 +127,36 @@ static int __init find_bit_test(void)
pr_err("\nStart testing find_bit() with random-filled bitmap\n"); pr_err("\nStart testing find_bit() with random-filled bitmap\n");
get_random_bytes(bitmap, sizeof(bitmap)); get_random_bytes(bitmap, sizeof(bitmap));
get_random_bytes(bitmap2, sizeof(bitmap2));
test_find_next_bit(bitmap, BITMAP_LEN); test_find_next_bit(bitmap, BITMAP_LEN);
test_find_next_zero_bit(bitmap, BITMAP_LEN); test_find_next_zero_bit(bitmap, BITMAP_LEN);
test_find_last_bit(bitmap, BITMAP_LEN); test_find_last_bit(bitmap, BITMAP_LEN);
test_find_first_bit(bitmap, BITMAP_LEN); test_find_first_bit(bitmap, BITMAP_LEN);
test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN);
pr_err("\nStart testing find_bit() with sparse bitmap\n"); pr_err("\nStart testing find_bit() with sparse bitmap\n");
bitmap_zero(bitmap, BITMAP_LEN); bitmap_zero(bitmap, BITMAP_LEN);
bitmap_zero(bitmap2, BITMAP_LEN);
while (nbits--) while (nbits--) {
__set_bit(prandom_u32() % BITMAP_LEN, bitmap); __set_bit(prandom_u32() % BITMAP_LEN, bitmap);
__set_bit(prandom_u32() % BITMAP_LEN, bitmap2);
}
test_find_next_bit(bitmap, BITMAP_LEN); test_find_next_bit(bitmap, BITMAP_LEN);
test_find_next_zero_bit(bitmap, BITMAP_LEN); test_find_next_zero_bit(bitmap, BITMAP_LEN);
test_find_last_bit(bitmap, BITMAP_LEN); test_find_last_bit(bitmap, BITMAP_LEN);
test_find_first_bit(bitmap, BITMAP_LEN); test_find_first_bit(bitmap, BITMAP_LEN);
test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN);
return 0; /*
* Everything is OK. Return error just to let user run benchmark
* again without annoying rmmod.
*/
return -EINVAL;
} }
module_init(find_bit_test); module_init(find_bit_test);
static void __exit test_find_bit_cleanup(void)
{
}
module_exit(test_find_bit_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -163,6 +163,21 @@ static inline u32 hash_stack(unsigned long *entries, unsigned int size)
STACK_HASH_SEED); STACK_HASH_SEED);
} }
/* Use our own, non-instrumented version of memcmp().
*
* We actually don't care about the order, just the equality.
*/
static inline
int stackdepot_memcmp(const unsigned long *u1, const unsigned long *u2,
unsigned int n)
{
for ( ; n-- ; u1++, u2++) {
if (*u1 != *u2)
return 1;
}
return 0;
}
/* Find a stack that is equal to the one stored in entries in the hash */ /* Find a stack that is equal to the one stored in entries in the hash */
static inline struct stack_record *find_stack(struct stack_record *bucket, static inline struct stack_record *find_stack(struct stack_record *bucket,
unsigned long *entries, int size, unsigned long *entries, int size,
@ -173,10 +188,8 @@ static inline struct stack_record *find_stack(struct stack_record *bucket,
for (found = bucket; found; found = found->next) { for (found = bucket; found; found = found->next) {
if (found->hash == hash && if (found->hash == hash &&
found->size == size && found->size == size &&
!memcmp(entries, found->entries, !stackdepot_memcmp(entries, found->entries, size))
size * sizeof(unsigned long))) {
return found; return found;
}
} }
return NULL; return NULL;
} }

View File

@ -23,7 +23,7 @@ __check_eq_uint(const char *srcfile, unsigned int line,
const unsigned int exp_uint, unsigned int x) const unsigned int exp_uint, unsigned int x)
{ {
if (exp_uint != x) { if (exp_uint != x) {
pr_warn("[%s:%u] expected %u, got %u\n", pr_err("[%s:%u] expected %u, got %u\n",
srcfile, line, exp_uint, x); srcfile, line, exp_uint, x);
return false; return false;
} }
@ -33,19 +33,13 @@ __check_eq_uint(const char *srcfile, unsigned int line,
static bool __init static bool __init
__check_eq_bitmap(const char *srcfile, unsigned int line, __check_eq_bitmap(const char *srcfile, unsigned int line,
const unsigned long *exp_bmap, unsigned int exp_nbits, const unsigned long *exp_bmap, const unsigned long *bmap,
const unsigned long *bmap, unsigned int nbits) unsigned int nbits)
{ {
if (exp_nbits != nbits) {
pr_warn("[%s:%u] bitmap length mismatch: expected %u, got %u\n",
srcfile, line, exp_nbits, nbits);
return false;
}
if (!bitmap_equal(exp_bmap, bmap, nbits)) { if (!bitmap_equal(exp_bmap, bmap, nbits)) {
pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n", pr_warn("[%s:%u] bitmaps contents differ: expected \"%*pbl\", got \"%*pbl\"\n",
srcfile, line, srcfile, line,
exp_nbits, exp_bmap, nbits, bmap); nbits, exp_bmap, nbits, bmap);
return false; return false;
} }
return true; return true;
@ -66,6 +60,10 @@ __check_eq_pbl(const char *srcfile, unsigned int line,
return true; return true;
} }
static bool __init
__check_eq_u32_array(const char *srcfile, unsigned int line,
const u32 *exp_arr, unsigned int exp_len,
const u32 *arr, unsigned int len) __used;
static bool __init static bool __init
__check_eq_u32_array(const char *srcfile, unsigned int line, __check_eq_u32_array(const char *srcfile, unsigned int line,
const u32 *exp_arr, unsigned int exp_len, const u32 *exp_arr, unsigned int exp_len,
@ -107,7 +105,65 @@ __check_eq_u32_array(const char *srcfile, unsigned int line,
#define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__) #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
#define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__) #define expect_eq_u32_array(...) __expect_eq(u32_array, ##__VA_ARGS__)
static void __init test_zero_fill_copy(void) static void __init test_zero_clear(void)
{
DECLARE_BITMAP(bmap, 1024);
/* Known way to set all bits */
memset(bmap, 0xff, 128);
expect_eq_pbl("0-22", bmap, 23);
expect_eq_pbl("0-1023", bmap, 1024);
/* single-word bitmaps */
bitmap_clear(bmap, 0, 9);
expect_eq_pbl("9-1023", bmap, 1024);
bitmap_zero(bmap, 35);
expect_eq_pbl("64-1023", bmap, 1024);
/* cross boundaries operations */
bitmap_clear(bmap, 79, 19);
expect_eq_pbl("64-78,98-1023", bmap, 1024);
bitmap_zero(bmap, 115);
expect_eq_pbl("128-1023", bmap, 1024);
/* Zeroing entire area */
bitmap_zero(bmap, 1024);
expect_eq_pbl("", bmap, 1024);
}
static void __init test_fill_set(void)
{
DECLARE_BITMAP(bmap, 1024);
/* Known way to clear all bits */
memset(bmap, 0x00, 128);
expect_eq_pbl("", bmap, 23);
expect_eq_pbl("", bmap, 1024);
/* single-word bitmaps */
bitmap_set(bmap, 0, 9);
expect_eq_pbl("0-8", bmap, 1024);
bitmap_fill(bmap, 35);
expect_eq_pbl("0-63", bmap, 1024);
/* cross boundaries operations */
bitmap_set(bmap, 79, 19);
expect_eq_pbl("0-63,79-97", bmap, 1024);
bitmap_fill(bmap, 115);
expect_eq_pbl("0-127", bmap, 1024);
/* Zeroing entire area */
bitmap_fill(bmap, 1024);
expect_eq_pbl("0-1023", bmap, 1024);
}
static void __init test_copy(void)
{ {
DECLARE_BITMAP(bmap1, 1024); DECLARE_BITMAP(bmap1, 1024);
DECLARE_BITMAP(bmap2, 1024); DECLARE_BITMAP(bmap2, 1024);
@ -116,36 +172,20 @@ static void __init test_zero_fill_copy(void)
bitmap_zero(bmap2, 1024); bitmap_zero(bmap2, 1024);
/* single-word bitmaps */ /* single-word bitmaps */
expect_eq_pbl("", bmap1, 23); bitmap_set(bmap1, 0, 19);
bitmap_fill(bmap1, 19);
expect_eq_pbl("0-18", bmap1, 1024);
bitmap_copy(bmap2, bmap1, 23); bitmap_copy(bmap2, bmap1, 23);
expect_eq_pbl("0-18", bmap2, 1024); expect_eq_pbl("0-18", bmap2, 1024);
bitmap_fill(bmap2, 23); bitmap_set(bmap2, 0, 23);
expect_eq_pbl("0-22", bmap2, 1024);
bitmap_copy(bmap2, bmap1, 23); bitmap_copy(bmap2, bmap1, 23);
expect_eq_pbl("0-18", bmap2, 1024); expect_eq_pbl("0-18", bmap2, 1024);
bitmap_zero(bmap1, 23);
expect_eq_pbl("", bmap1, 1024);
/* multi-word bitmaps */ /* multi-word bitmaps */
bitmap_zero(bmap1, 1024); bitmap_set(bmap1, 0, 109);
expect_eq_pbl("", bmap1, 1024);
bitmap_fill(bmap1, 109);
expect_eq_pbl("0-108", bmap1, 1024);
bitmap_copy(bmap2, bmap1, 1024); bitmap_copy(bmap2, bmap1, 1024);
expect_eq_pbl("0-108", bmap2, 1024); expect_eq_pbl("0-108", bmap2, 1024);
bitmap_fill(bmap2, 1024); bitmap_fill(bmap2, 1024);
expect_eq_pbl("0-1023", bmap2, 1024);
bitmap_copy(bmap2, bmap1, 1024); bitmap_copy(bmap2, bmap1, 1024);
expect_eq_pbl("0-108", bmap2, 1024); expect_eq_pbl("0-108", bmap2, 1024);
@ -160,9 +200,6 @@ static void __init test_zero_fill_copy(void)
bitmap_fill(bmap2, 1024); bitmap_fill(bmap2, 1024);
bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */ bitmap_copy(bmap2, bmap1, 97); /* ... but aligned on word length */
expect_eq_pbl("0-108,128-1023", bmap2, 1024); expect_eq_pbl("0-108,128-1023", bmap2, 1024);
bitmap_zero(bmap2, 97); /* ... but 0-padded til word length */
expect_eq_pbl("128-1023", bmap2, 1024);
} }
#define PARSE_TIME 0x1 #define PARSE_TIME 0x1
@ -255,171 +292,29 @@ static void __init test_bitmap_parselist(void)
} }
} }
static void __init test_bitmap_u32_array_conversions(void) static void __init test_bitmap_arr32(void)
{ {
DECLARE_BITMAP(bmap1, 1024); unsigned int nbits, next_bit, len = sizeof(exp) * 8;
DECLARE_BITMAP(bmap2, 1024); u32 arr[sizeof(exp) / 4];
u32 exp_arr[32], arr[32]; DECLARE_BITMAP(bmap2, len);
unsigned nbits;
for (nbits = 0 ; nbits < 257 ; ++nbits) { memset(arr, 0xa5, sizeof(arr));
const unsigned int used_u32s = DIV_ROUND_UP(nbits, 32);
unsigned int i, rv;
bitmap_zero(bmap1, nbits); for (nbits = 0; nbits < len; ++nbits) {
bitmap_set(bmap1, nbits, 1024 - nbits); /* garbage */ bitmap_to_arr32(arr, exp, nbits);
bitmap_from_arr32(bmap2, arr, nbits);
expect_eq_bitmap(bmap2, exp, nbits);
memset(arr, 0xff, sizeof(arr)); next_bit = find_next_bit(bmap2,
rv = bitmap_to_u32array(arr, used_u32s, bmap1, nbits); round_up(nbits, BITS_PER_LONG), nbits);
expect_eq_uint(nbits, rv); if (next_bit < round_up(nbits, BITS_PER_LONG))
pr_err("bitmap_copy_arr32(nbits == %d:"
" tail is not safely cleared: %d\n",
nbits, next_bit);
memset(exp_arr, 0xff, sizeof(exp_arr)); if (nbits < len - 32)
memset(exp_arr, 0, used_u32s*sizeof(*exp_arr)); expect_eq_uint(arr[DIV_ROUND_UP(nbits, 32)],
expect_eq_u32_array(exp_arr, 32, arr, 32); 0xa5a5a5a5);
bitmap_fill(bmap2, 1024);
rv = bitmap_from_u32array(bmap2, nbits, arr, used_u32s);
expect_eq_uint(nbits, rv);
expect_eq_bitmap(bmap1, 1024, bmap2, 1024);
for (i = 0 ; i < nbits ; ++i) {
/*
* test conversion bitmap -> u32[]
*/
bitmap_zero(bmap1, 1024);
__set_bit(i, bmap1);
bitmap_set(bmap1, nbits, 1024 - nbits); /* garbage */
memset(arr, 0xff, sizeof(arr));
rv = bitmap_to_u32array(arr, used_u32s, bmap1, nbits);
expect_eq_uint(nbits, rv);
/* 1st used u32 words contain expected bit set, the
* remaining words are left unchanged (0xff)
*/
memset(exp_arr, 0xff, sizeof(exp_arr));
memset(exp_arr, 0, used_u32s*sizeof(*exp_arr));
exp_arr[i/32] = (1U<<(i%32));
expect_eq_u32_array(exp_arr, 32, arr, 32);
/* same, with longer array to fill
*/
memset(arr, 0xff, sizeof(arr));
rv = bitmap_to_u32array(arr, 32, bmap1, nbits);
expect_eq_uint(nbits, rv);
/* 1st used u32 words contain expected bit set, the
* remaining words are all 0s
*/
memset(exp_arr, 0, sizeof(exp_arr));
exp_arr[i/32] = (1U<<(i%32));
expect_eq_u32_array(exp_arr, 32, arr, 32);
/*
* test conversion u32[] -> bitmap
*/
/* the 1st nbits of bmap2 are identical to
* bmap1, the remaining bits of bmap2 are left
* unchanged (all 1s)
*/
bitmap_fill(bmap2, 1024);
rv = bitmap_from_u32array(bmap2, nbits,
exp_arr, used_u32s);
expect_eq_uint(nbits, rv);
expect_eq_bitmap(bmap1, 1024, bmap2, 1024);
/* same, with more bits to fill
*/
memset(arr, 0xff, sizeof(arr)); /* garbage */
memset(arr, 0, used_u32s*sizeof(u32));
arr[i/32] = (1U<<(i%32));
bitmap_fill(bmap2, 1024);
rv = bitmap_from_u32array(bmap2, 1024, arr, used_u32s);
expect_eq_uint(used_u32s*32, rv);
/* the 1st nbits of bmap2 are identical to
* bmap1, the remaining bits of bmap2 are cleared
*/
bitmap_zero(bmap1, 1024);
__set_bit(i, bmap1);
expect_eq_bitmap(bmap1, 1024, bmap2, 1024);
/*
* test short conversion bitmap -> u32[] (1
* word too short)
*/
if (used_u32s > 1) {
bitmap_zero(bmap1, 1024);
__set_bit(i, bmap1);
bitmap_set(bmap1, nbits,
1024 - nbits); /* garbage */
memset(arr, 0xff, sizeof(arr));
rv = bitmap_to_u32array(arr, used_u32s - 1,
bmap1, nbits);
expect_eq_uint((used_u32s - 1)*32, rv);
/* 1st used u32 words contain expected
* bit set, the remaining words are
* left unchanged (0xff)
*/
memset(exp_arr, 0xff, sizeof(exp_arr));
memset(exp_arr, 0,
(used_u32s-1)*sizeof(*exp_arr));
if ((i/32) < (used_u32s - 1))
exp_arr[i/32] = (1U<<(i%32));
expect_eq_u32_array(exp_arr, 32, arr, 32);
}
/*
* test short conversion u32[] -> bitmap (3
* bits too short)
*/
if (nbits > 3) {
memset(arr, 0xff, sizeof(arr)); /* garbage */
memset(arr, 0, used_u32s*sizeof(*arr));
arr[i/32] = (1U<<(i%32));
bitmap_zero(bmap1, 1024);
rv = bitmap_from_u32array(bmap1, nbits - 3,
arr, used_u32s);
expect_eq_uint(nbits - 3, rv);
/* we are expecting the bit < nbits -
* 3 (none otherwise), and the rest of
* bmap1 unchanged (0-filled)
*/
bitmap_zero(bmap2, 1024);
if (i < nbits - 3)
__set_bit(i, bmap2);
expect_eq_bitmap(bmap2, 1024, bmap1, 1024);
/* do the same with bmap1 initially
* 1-filled
*/
bitmap_fill(bmap1, 1024);
rv = bitmap_from_u32array(bmap1, nbits - 3,
arr, used_u32s);
expect_eq_uint(nbits - 3, rv);
/* we are expecting the bit < nbits -
* 3 (none otherwise), and the rest of
* bmap1 unchanged (1-filled)
*/
bitmap_zero(bmap2, 1024);
if (i < nbits - 3)
__set_bit(i, bmap2);
bitmap_set(bmap2, nbits-3, 1024 - nbits + 3);
expect_eq_bitmap(bmap2, 1024, bmap1, 1024);
}
}
} }
} }
@ -453,8 +348,10 @@ static void noinline __init test_mem_optimisations(void)
static int __init test_bitmap_init(void) static int __init test_bitmap_init(void)
{ {
test_zero_fill_copy(); test_zero_clear();
test_bitmap_u32_array_conversions(); test_fill_set();
test_copy();
test_bitmap_arr32();
test_bitmap_parselist(); test_bitmap_parselist();
test_mem_optimisations(); test_mem_optimisations();

View File

@ -94,6 +94,37 @@ static noinline void __init kmalloc_pagealloc_oob_right(void)
ptr[size] = 0; ptr[size] = 0;
kfree(ptr); kfree(ptr);
} }
static noinline void __init kmalloc_pagealloc_uaf(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
pr_info("kmalloc pagealloc allocation: use-after-free\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr);
ptr[0] = 0;
}
static noinline void __init kmalloc_pagealloc_invalid_free(void)
{
char *ptr;
size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
pr_info("kmalloc pagealloc allocation: invalid-free\n");
ptr = kmalloc(size, GFP_KERNEL);
if (!ptr) {
pr_err("Allocation failed\n");
return;
}
kfree(ptr + 1);
}
#endif #endif
static noinline void __init kmalloc_large_oob_right(void) static noinline void __init kmalloc_large_oob_right(void)
@ -388,7 +419,7 @@ static noinline void __init kasan_stack_oob(void)
static noinline void __init ksize_unpoisons_memory(void) static noinline void __init ksize_unpoisons_memory(void)
{ {
char *ptr; char *ptr;
size_t size = 123, real_size = size; size_t size = 123, real_size;
pr_info("ksize() unpoisons the whole allocated chunk\n"); pr_info("ksize() unpoisons the whole allocated chunk\n");
ptr = kmalloc(size, GFP_KERNEL); ptr = kmalloc(size, GFP_KERNEL);
@ -472,6 +503,74 @@ static noinline void __init use_after_scope_test(void)
p[1023] = 1; p[1023] = 1;
} }
static noinline void __init kasan_alloca_oob_left(void)
{
volatile int i = 10;
char alloca_array[i];
char *p = alloca_array - 1;
pr_info("out-of-bounds to left on alloca\n");
*(volatile char *)p;
}
static noinline void __init kasan_alloca_oob_right(void)
{
volatile int i = 10;
char alloca_array[i];
char *p = alloca_array + i;
pr_info("out-of-bounds to right on alloca\n");
*(volatile char *)p;
}
static noinline void __init kmem_cache_double_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, 0, NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("double-free on heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
kmem_cache_free(cache, p);
kmem_cache_free(cache, p);
kmem_cache_destroy(cache);
}
static noinline void __init kmem_cache_invalid_free(void)
{
char *p;
size_t size = 200;
struct kmem_cache *cache;
cache = kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU,
NULL);
if (!cache) {
pr_err("Cache allocation failed\n");
return;
}
pr_info("invalid-free of heap object\n");
p = kmem_cache_alloc(cache, GFP_KERNEL);
if (!p) {
pr_err("Allocation failed\n");
kmem_cache_destroy(cache);
return;
}
kmem_cache_free(cache, p + 1);
kmem_cache_destroy(cache);
}
static int __init kmalloc_tests_init(void) static int __init kmalloc_tests_init(void)
{ {
/* /*
@ -485,6 +584,8 @@ static int __init kmalloc_tests_init(void)
kmalloc_node_oob_right(); kmalloc_node_oob_right();
#ifdef CONFIG_SLUB #ifdef CONFIG_SLUB
kmalloc_pagealloc_oob_right(); kmalloc_pagealloc_oob_right();
kmalloc_pagealloc_uaf();
kmalloc_pagealloc_invalid_free();
#endif #endif
kmalloc_large_oob_right(); kmalloc_large_oob_right();
kmalloc_oob_krealloc_more(); kmalloc_oob_krealloc_more();
@ -502,9 +603,13 @@ static int __init kmalloc_tests_init(void)
memcg_accounted_kmem_cache(); memcg_accounted_kmem_cache();
kasan_stack_oob(); kasan_stack_oob();
kasan_global_oob(); kasan_global_oob();
kasan_alloca_oob_left();
kasan_alloca_oob_right();
ksize_unpoisons_memory(); ksize_unpoisons_memory();
copy_user_test(); copy_user_test();
use_after_scope_test(); use_after_scope_test();
kmem_cache_double_free();
kmem_cache_invalid_free();
kasan_restore_multi_shot(multishot); kasan_restore_multi_shot(multishot);

View File

@ -39,5 +39,11 @@ static int __init test_sort_init(void)
return err; return err;
} }
static void __exit test_sort_exit(void)
{
}
module_init(test_sort_init); module_init(test_sort_init);
module_exit(test_sort_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

Some files were not shown because too many files have changed in this diff Show More