Commit 34c5c898 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'akpm' (patches from Andrew)

Merge misc fixes from Andrew Morton:
 "10 patches.

  Subsystems affected by this patch series: mm (pagealloc, gup, kasan,
  and userfaultfd), ipc, selftests, watchdog, bitmap, procfs, and lib"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  userfaultfd: hugetlbfs: fix new flag usage in error path
  lib: kunit: suppress a compilation warning of frame size
  proc: remove Alexey from MAINTAINERS
  linux/bits.h: fix compilation error with GENMASK
  watchdog: reliable handling of timestamps
  kasan: slab: always reset the tag in get_freepointer_safe()
  tools/testing/selftests/exec: fix link error
  ipc/mqueue, msg, sem: avoid relying on a stack reference past its expiry
  Revert "mm/gup: check page posion status for coredump."
  mm/shuffle: fix section mismatch warning
parents 4ff2473b e32905e5
...@@ -14735,7 +14735,6 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/p54 ...@@ -14735,7 +14735,6 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/p54
F: drivers/net/wireless/intersil/prism54/ F: drivers/net/wireless/intersil/prism54/
PROC FILESYSTEM PROC FILESYSTEM
R: Alexey Dobriyan <adobriyan@gmail.com>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
L: linux-fsdevel@vger.kernel.org L: linux-fsdevel@vger.kernel.org
S: Maintained S: Maintained
......
...@@ -529,7 +529,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart, ...@@ -529,7 +529,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
* the subpool and global reserve usage count can need * the subpool and global reserve usage count can need
* to be adjusted. * to be adjusted.
*/ */
VM_BUG_ON(PagePrivate(page)); VM_BUG_ON(HPageRestoreReserve(page));
remove_huge_page(page); remove_huge_page(page);
freed++; freed++;
if (!truncate_op) { if (!truncate_op) {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/build_bug.h> #include <linux/build_bug.h>
#define GENMASK_INPUT_CHECK(h, l) \ #define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \ (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__builtin_constant_p((l) > (h)), (l) > (h), 0))) __is_constexpr((l) > (h)), (l) > (h), 0)))
#else #else
/* /*
* BUILD_BUG_ON_ZERO is not available in h files included from asm files, * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
......
...@@ -3,4 +3,12 @@ ...@@ -3,4 +3,12 @@
#include <vdso/const.h> #include <vdso/const.h>
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.
* Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
#endif /* _LINUX_CONST_H */ #endif /* _LINUX_CONST_H */
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#ifndef _LINUX_MINMAX_H #ifndef _LINUX_MINMAX_H
#define _LINUX_MINMAX_H #define _LINUX_MINMAX_H
#include <linux/const.h>
/* /*
* min()/max()/clamp() macros must accomplish three things: * min()/max()/clamp() macros must accomplish three things:
* *
...@@ -17,14 +19,6 @@ ...@@ -17,14 +19,6 @@
#define __typecheck(x, y) \ #define __typecheck(x, y) \
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.
* Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
#define __no_side_effects(x, y) \ #define __no_side_effects(x, y) \
(__is_constexpr(x) && __is_constexpr(y)) (__is_constexpr(x) && __is_constexpr(y))
......
...@@ -1004,12 +1004,14 @@ static inline void __pipelined_op(struct wake_q_head *wake_q, ...@@ -1004,12 +1004,14 @@ static inline void __pipelined_op(struct wake_q_head *wake_q,
struct mqueue_inode_info *info, struct mqueue_inode_info *info,
struct ext_wait_queue *this) struct ext_wait_queue *this)
{ {
struct task_struct *task;
list_del(&this->list); list_del(&this->list);
get_task_struct(this->task); task = get_task_struct(this->task);
/* see MQ_BARRIER for purpose/pairing */ /* see MQ_BARRIER for purpose/pairing */
smp_store_release(&this->state, STATE_READY); smp_store_release(&this->state, STATE_READY);
wake_q_add_safe(wake_q, this->task); wake_q_add_safe(wake_q, task);
} }
/* pipelined_send() - send a message directly to the task waiting in /* pipelined_send() - send a message directly to the task waiting in
......
...@@ -251,11 +251,13 @@ static void expunge_all(struct msg_queue *msq, int res, ...@@ -251,11 +251,13 @@ static void expunge_all(struct msg_queue *msq, int res,
struct msg_receiver *msr, *t; struct msg_receiver *msr, *t;
list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) { list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
get_task_struct(msr->r_tsk); struct task_struct *r_tsk;
r_tsk = get_task_struct(msr->r_tsk);
/* see MSG_BARRIER for purpose/pairing */ /* see MSG_BARRIER for purpose/pairing */
smp_store_release(&msr->r_msg, ERR_PTR(res)); smp_store_release(&msr->r_msg, ERR_PTR(res));
wake_q_add_safe(wake_q, msr->r_tsk); wake_q_add_safe(wake_q, r_tsk);
} }
} }
......
...@@ -784,12 +784,14 @@ static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q) ...@@ -784,12 +784,14 @@ static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q)
static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error, static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error,
struct wake_q_head *wake_q) struct wake_q_head *wake_q)
{ {
get_task_struct(q->sleeper); struct task_struct *sleeper;
sleeper = get_task_struct(q->sleeper);
/* see SEM_BARRIER_2 for purpose/pairing */ /* see SEM_BARRIER_2 for purpose/pairing */
smp_store_release(&q->status, error); smp_store_release(&q->status, error);
wake_q_add_safe(wake_q, q->sleeper); wake_q_add_safe(wake_q, sleeper);
} }
static void unlink_queue(struct sem_array *sma, struct sem_queue *q) static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
......
...@@ -302,10 +302,10 @@ void touch_softlockup_watchdog_sync(void) ...@@ -302,10 +302,10 @@ void touch_softlockup_watchdog_sync(void)
__this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT); __this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT);
} }
static int is_softlockup(unsigned long touch_ts, unsigned long period_ts) static int is_softlockup(unsigned long touch_ts,
unsigned long period_ts,
unsigned long now)
{ {
unsigned long now = get_timestamp();
if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){ if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){
/* Warn about unreasonable delays. */ /* Warn about unreasonable delays. */
if (time_after(now, period_ts + get_softlockup_thresh())) if (time_after(now, period_ts + get_softlockup_thresh()))
...@@ -353,8 +353,7 @@ static int softlockup_fn(void *data) ...@@ -353,8 +353,7 @@ static int softlockup_fn(void *data)
/* watchdog kicker functions */ /* watchdog kicker functions */
static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
{ {
unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); unsigned long touch_ts, period_ts, now;
unsigned long period_ts = __this_cpu_read(watchdog_report_ts);
struct pt_regs *regs = get_irq_regs(); struct pt_regs *regs = get_irq_regs();
int duration; int duration;
int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace; int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
...@@ -376,12 +375,23 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) ...@@ -376,12 +375,23 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
/* .. and repeat */ /* .. and repeat */
hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
/*
* Read the current timestamp first. It might become invalid anytime
* when a virtual machine is stopped by the host or when the watchog
* is touched from NMI.
*/
now = get_timestamp();
/* /*
* If a virtual machine is stopped by the host it can look to * If a virtual machine is stopped by the host it can look to
* the watchdog like a soft lockup. Check to see if the host * the watchdog like a soft lockup. This function touches the watchdog.
* stopped the vm before we process the timestamps.
*/ */
kvm_check_and_clear_guest_paused(); kvm_check_and_clear_guest_paused();
/*
* The stored timestamp is comparable with @now only when not touched.
* It might get touched anytime from NMI. Make sure that is_softlockup()
* uses the same (valid) value.
*/
period_ts = READ_ONCE(*this_cpu_ptr(&watchdog_report_ts));
/* Reset the interval when touched by known problematic code. */ /* Reset the interval when touched by known problematic code. */
if (period_ts == SOFTLOCKUP_DELAY_REPORT) { if (period_ts == SOFTLOCKUP_DELAY_REPORT) {
...@@ -398,13 +408,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) ...@@ -398,13 +408,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
return HRTIMER_RESTART; return HRTIMER_RESTART;
} }
/* check for a softlockup /* Check for a softlockup. */
* This is done by making sure a high priority task is touch_ts = __this_cpu_read(watchdog_touch_ts);
* being scheduled. The task touches the watchdog to duration = is_softlockup(touch_ts, period_ts, now);
* indicate it is getting cpu time. If it hasn't then
* this is a good indication some task is hogging the cpu
*/
duration = is_softlockup(touch_ts, period_ts);
if (unlikely(duration)) { if (unlikely(duration)) {
/* /*
* Prevent multiple soft-lockup reports if one cpu is already * Prevent multiple soft-lockup reports if one cpu is already
......
...@@ -348,6 +348,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o ...@@ -348,6 +348,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o
obj-$(CONFIG_PLDMFW) += pldmfw/ obj-$(CONFIG_PLDMFW) += pldmfw/
# KUnit tests # KUnit tests
CFLAGS_bitfield_kunit.o := $(call cc-option,-Wframe-larger-than=10240)
obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
......
...@@ -1593,10 +1593,6 @@ struct page *get_dump_page(unsigned long addr) ...@@ -1593,10 +1593,6 @@ struct page *get_dump_page(unsigned long addr)
FOLL_FORCE | FOLL_DUMP | FOLL_GET); FOLL_FORCE | FOLL_DUMP | FOLL_GET);
if (locked) if (locked)
mmap_read_unlock(mm); mmap_read_unlock(mm);
if (ret == 1 && is_page_poisoned(page))
return NULL;
return (ret == 1) ? page : NULL; return (ret == 1) ? page : NULL;
} }
#endif /* CONFIG_ELF_CORE */ #endif /* CONFIG_ELF_CORE */
......
...@@ -96,26 +96,6 @@ static inline void set_page_refcounted(struct page *page) ...@@ -96,26 +96,6 @@ static inline void set_page_refcounted(struct page *page)
set_page_count(page, 1); set_page_count(page, 1);
} }
/*
* When kernel touch the user page, the user page may be have been marked
* poison but still mapped in user space, if without this page, the kernel
* can guarantee the data integrity and operation success, the kernel is
* better to check the posion status and avoid touching it, be good not to
* panic, coredump for process fatal signal is a sample case matching this
* scenario. Or if kernel can't guarantee the data integrity, it's better
* not to call this function, let kernel touch the poison page and get to
* panic.
*/
static inline bool is_page_poisoned(struct page *page)
{
if (PageHWPoison(page))
return true;
else if (PageHuge(page) && PageHWPoison(compound_head(page)))
return true;
return false;
}
extern unsigned long highest_memmap_pfn; extern unsigned long highest_memmap_pfn;
/* /*
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key); DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
extern void __shuffle_free_memory(pg_data_t *pgdat); extern void __shuffle_free_memory(pg_data_t *pgdat);
extern bool shuffle_pick_tail(void); extern bool shuffle_pick_tail(void);
static inline void shuffle_free_memory(pg_data_t *pgdat) static inline void __meminit shuffle_free_memory(pg_data_t *pgdat)
{ {
if (!static_branch_unlikely(&page_alloc_shuffle_key)) if (!static_branch_unlikely(&page_alloc_shuffle_key))
return; return;
...@@ -18,7 +18,7 @@ static inline void shuffle_free_memory(pg_data_t *pgdat) ...@@ -18,7 +18,7 @@ static inline void shuffle_free_memory(pg_data_t *pgdat)
} }
extern void __shuffle_zone(struct zone *z); extern void __shuffle_zone(struct zone *z);
static inline void shuffle_zone(struct zone *z) static inline void __meminit shuffle_zone(struct zone *z)
{ {
if (!static_branch_unlikely(&page_alloc_shuffle_key)) if (!static_branch_unlikely(&page_alloc_shuffle_key))
return; return;
......
...@@ -301,6 +301,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object) ...@@ -301,6 +301,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
if (!debug_pagealloc_enabled_static()) if (!debug_pagealloc_enabled_static())
return get_freepointer(s, object); return get_freepointer(s, object);
object = kasan_reset_tag(object);
freepointer_addr = (unsigned long)object + s->offset; freepointer_addr = (unsigned long)object + s->offset;
copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p)); copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
return freelist_ptr(s, p, freepointer_addr); return freelist_ptr(s, p, freepointer_addr);
......
...@@ -360,38 +360,38 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, ...@@ -360,38 +360,38 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
* If a reservation for the page existed in the reservation * If a reservation for the page existed in the reservation
* map of a private mapping, the map was modified to indicate * map of a private mapping, the map was modified to indicate
* the reservation was consumed when the page was allocated. * the reservation was consumed when the page was allocated.
* We clear the PagePrivate flag now so that the global * We clear the HPageRestoreReserve flag now so that the global
* reserve count will not be incremented in free_huge_page. * reserve count will not be incremented in free_huge_page.
* The reservation map will still indicate the reservation * The reservation map will still indicate the reservation
* was consumed and possibly prevent later page allocation. * was consumed and possibly prevent later page allocation.
* This is better than leaking a global reservation. If no * This is better than leaking a global reservation. If no
* reservation existed, it is still safe to clear PagePrivate * reservation existed, it is still safe to clear
* as no adjustments to reservation counts were made during * HPageRestoreReserve as no adjustments to reservation counts
* allocation. * were made during allocation.
* *
* The reservation map for shared mappings indicates which * The reservation map for shared mappings indicates which
* pages have reservations. When a huge page is allocated * pages have reservations. When a huge page is allocated
* for an address with a reservation, no change is made to * for an address with a reservation, no change is made to
* the reserve map. In this case PagePrivate will be set * the reserve map. In this case HPageRestoreReserve will be
* to indicate that the global reservation count should be * set to indicate that the global reservation count should be
* incremented when the page is freed. This is the desired * incremented when the page is freed. This is the desired
* behavior. However, when a huge page is allocated for an * behavior. However, when a huge page is allocated for an
* address without a reservation a reservation entry is added * address without a reservation a reservation entry is added
* to the reservation map, and PagePrivate will not be set. * to the reservation map, and HPageRestoreReserve will not be
* When the page is freed, the global reserve count will NOT * set. When the page is freed, the global reserve count will
* be incremented and it will appear as though we have leaked * NOT be incremented and it will appear as though we have
* reserved page. In this case, set PagePrivate so that the * leaked reserved page. In this case, set HPageRestoreReserve
* global reserve count will be incremented to match the * so that the global reserve count will be incremented to
* reservation map entry which was created. * match the reservation map entry which was created.
* *
* Note that vm_alloc_shared is based on the flags of the vma * Note that vm_alloc_shared is based on the flags of the vma
* for which the page was originally allocated. dst_vma could * for which the page was originally allocated. dst_vma could
* be different or NULL on error. * be different or NULL on error.
*/ */
if (vm_alloc_shared) if (vm_alloc_shared)
SetPagePrivate(page); SetHPageRestoreReserve(page);
else else
ClearPagePrivate(page); ClearHPageRestoreReserve(page);
put_page(page); put_page(page);
} }
BUG_ON(copied < 0); BUG_ON(copied < 0);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/build_bug.h> #include <linux/build_bug.h>
#define GENMASK_INPUT_CHECK(h, l) \ #define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \ (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__builtin_constant_p((l) > (h)), (l) > (h), 0))) __is_constexpr((l) > (h)), (l) > (h), 0)))
#else #else
/* /*
* BUILD_BUG_ON_ZERO is not available in h files included from asm files, * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
......
...@@ -3,4 +3,12 @@ ...@@ -3,4 +3,12 @@
#include <vdso/const.h> #include <vdso/const.h>
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.
* Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
*/
#define __is_constexpr(x) \
(sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
#endif /* _LINUX_CONST_H */ #endif /* _LINUX_CONST_H */
...@@ -28,8 +28,8 @@ $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat ...@@ -28,8 +28,8 @@ $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
cp $< $@ cp $< $@
chmod -x $@ chmod -x $@
$(OUTPUT)/load_address_4096: load_address.c $(OUTPUT)/load_address_4096: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie -static $< -o $@
$(OUTPUT)/load_address_2097152: load_address.c $(OUTPUT)/load_address_2097152: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie -static $< -o $@
$(OUTPUT)/load_address_16777216: load_address.c $(OUTPUT)/load_address_16777216: load_address.c
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie -static $< -o $@
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment