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
This commit is contained in:
Коммит
34c5c89890
|
@ -14735,7 +14735,6 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/p54
|
|||
F: drivers/net/wireless/intersil/prism54/
|
||||
|
||||
PROC FILESYSTEM
|
||||
R: Alexey Dobriyan <adobriyan@gmail.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
|
@ -529,7 +529,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
|
|||
* the subpool and global reserve usage count can need
|
||||
* to be adjusted.
|
||||
*/
|
||||
VM_BUG_ON(PagePrivate(page));
|
||||
VM_BUG_ON(HPageRestoreReserve(page));
|
||||
remove_huge_page(page);
|
||||
freed++;
|
||||
if (!truncate_op) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/build_bug.h>
|
||||
#define GENMASK_INPUT_CHECK(h, l) \
|
||||
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
|
||||
__builtin_constant_p((l) > (h)), (l) > (h), 0)))
|
||||
__is_constexpr((l) > (h)), (l) > (h), 0)))
|
||||
#else
|
||||
/*
|
||||
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
|
||||
|
|
|
@ -3,4 +3,12 @@
|
|||
|
||||
#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 */
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#ifndef _LINUX_MINMAX_H
|
||||
#define _LINUX_MINMAX_H
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
/*
|
||||
* min()/max()/clamp() macros must accomplish three things:
|
||||
*
|
||||
|
@ -17,14 +19,6 @@
|
|||
#define __typecheck(x, y) \
|
||||
(!!(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) \
|
||||
(__is_constexpr(x) && __is_constexpr(y))
|
||||
|
||||
|
|
|
@ -1004,12 +1004,14 @@ static inline void __pipelined_op(struct wake_q_head *wake_q,
|
|||
struct mqueue_inode_info *info,
|
||||
struct ext_wait_queue *this)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
list_del(&this->list);
|
||||
get_task_struct(this->task);
|
||||
task = get_task_struct(this->task);
|
||||
|
||||
/* see MQ_BARRIER for purpose/pairing */
|
||||
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
|
||||
|
|
|
@ -251,11 +251,13 @@ static void expunge_all(struct msg_queue *msq, int res,
|
|||
struct msg_receiver *msr, *t;
|
||||
|
||||
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 */
|
||||
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 @@ would_block:
|
|||
static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error,
|
||||
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 */
|
||||
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)
|
||||
|
|
|
@ -302,10 +302,10 @@ void touch_softlockup_watchdog_sync(void)
|
|||
__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){
|
||||
/* Warn about unreasonable delays. */
|
||||
if (time_after(now, period_ts + get_softlockup_thresh()))
|
||||
|
@ -353,8 +353,7 @@ static int softlockup_fn(void *data)
|
|||
/* watchdog kicker functions */
|
||||
static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
||||
{
|
||||
unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
|
||||
unsigned long period_ts = __this_cpu_read(watchdog_report_ts);
|
||||
unsigned long touch_ts, period_ts, now;
|
||||
struct pt_regs *regs = get_irq_regs();
|
||||
int duration;
|
||||
int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
|
||||
|
@ -376,12 +375,23 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|||
/* .. and repeat */
|
||||
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
|
||||
* the watchdog like a soft lockup. Check to see if the host
|
||||
* stopped the vm before we process the timestamps.
|
||||
* the watchdog like a soft lockup. This function touches the watchdog.
|
||||
*/
|
||||
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. */
|
||||
if (period_ts == SOFTLOCKUP_DELAY_REPORT) {
|
||||
|
@ -398,13 +408,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|||
return HRTIMER_RESTART;
|
||||
}
|
||||
|
||||
/* check for a softlockup
|
||||
* This is done by making sure a high priority task is
|
||||
* being scheduled. The task touches the watchdog to
|
||||
* 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);
|
||||
/* Check for a softlockup. */
|
||||
touch_ts = __this_cpu_read(watchdog_touch_ts);
|
||||
duration = is_softlockup(touch_ts, period_ts, now);
|
||||
if (unlikely(duration)) {
|
||||
/*
|
||||
* Prevent multiple soft-lockup reports if one cpu is already
|
||||
|
|
|
@ -348,6 +348,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o
|
|||
obj-$(CONFIG_PLDMFW) += pldmfw/
|
||||
|
||||
# KUnit tests
|
||||
CFLAGS_bitfield_kunit.o := $(call cc-option,-Wframe-larger-than=10240)
|
||||
obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
|
||||
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
|
||||
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
|
||||
|
|
4
mm/gup.c
4
mm/gup.c
|
@ -1593,10 +1593,6 @@ struct page *get_dump_page(unsigned long addr)
|
|||
FOLL_FORCE | FOLL_DUMP | FOLL_GET);
|
||||
if (locked)
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
if (ret == 1 && is_page_poisoned(page))
|
||||
return NULL;
|
||||
|
||||
return (ret == 1) ? page : NULL;
|
||||
}
|
||||
#endif /* CONFIG_ELF_CORE */
|
||||
|
|
|
@ -96,26 +96,6 @@ static inline void set_page_refcounted(struct page *page)
|
|||
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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
|
||||
extern void __shuffle_free_memory(pg_data_t *pgdat);
|
||||
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))
|
||||
return;
|
||||
|
@ -18,7 +18,7 @@ static inline void shuffle_free_memory(pg_data_t *pgdat)
|
|||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
|
|
@ -301,6 +301,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
|
|||
if (!debug_pagealloc_enabled_static())
|
||||
return get_freepointer(s, object);
|
||||
|
||||
object = kasan_reset_tag(object);
|
||||
freepointer_addr = (unsigned long)object + s->offset;
|
||||
copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
|
||||
return freelist_ptr(s, p, freepointer_addr);
|
||||
|
|
|
@ -360,38 +360,38 @@ out:
|
|||
* If a reservation for the page existed in the reservation
|
||||
* map of a private mapping, the map was modified to indicate
|
||||
* 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.
|
||||
* The reservation map will still indicate the reservation
|
||||
* was consumed and possibly prevent later page allocation.
|
||||
* This is better than leaking a global reservation. If no
|
||||
* reservation existed, it is still safe to clear PagePrivate
|
||||
* as no adjustments to reservation counts were made during
|
||||
* allocation.
|
||||
* reservation existed, it is still safe to clear
|
||||
* HPageRestoreReserve as no adjustments to reservation counts
|
||||
* were made during allocation.
|
||||
*
|
||||
* The reservation map for shared mappings indicates which
|
||||
* pages have reservations. When a huge page is allocated
|
||||
* for an address with a reservation, no change is made to
|
||||
* the reserve map. In this case PagePrivate will be set
|
||||
* to indicate that the global reservation count should be
|
||||
* the reserve map. In this case HPageRestoreReserve will be
|
||||
* set to indicate that the global reservation count should be
|
||||
* incremented when the page is freed. This is the desired
|
||||
* behavior. However, when a huge page is allocated for an
|
||||
* address without a reservation a reservation entry is added
|
||||
* to the reservation map, and PagePrivate will not be set.
|
||||
* When the page is freed, the global reserve count will NOT
|
||||
* be incremented and it will appear as though we have leaked
|
||||
* reserved page. In this case, set PagePrivate so that the
|
||||
* global reserve count will be incremented to match the
|
||||
* reservation map entry which was created.
|
||||
* to the reservation map, and HPageRestoreReserve will not be
|
||||
* set. When the page is freed, the global reserve count will
|
||||
* NOT be incremented and it will appear as though we have
|
||||
* leaked reserved page. In this case, set HPageRestoreReserve
|
||||
* so that the global reserve count will be incremented to
|
||||
* match the reservation map entry which was created.
|
||||
*
|
||||
* Note that vm_alloc_shared is based on the flags of the vma
|
||||
* for which the page was originally allocated. dst_vma could
|
||||
* be different or NULL on error.
|
||||
*/
|
||||
if (vm_alloc_shared)
|
||||
SetPagePrivate(page);
|
||||
SetHPageRestoreReserve(page);
|
||||
else
|
||||
ClearPagePrivate(page);
|
||||
ClearHPageRestoreReserve(page);
|
||||
put_page(page);
|
||||
}
|
||||
BUG_ON(copied < 0);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/build_bug.h>
|
||||
#define GENMASK_INPUT_CHECK(h, l) \
|
||||
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
|
||||
__builtin_constant_p((l) > (h)), (l) > (h), 0)))
|
||||
__is_constexpr((l) > (h)), (l) > (h), 0)))
|
||||
#else
|
||||
/*
|
||||
* BUILD_BUG_ON_ZERO is not available in h files included from asm files,
|
||||
|
|
|
@ -3,4 +3,12 @@
|
|||
|
||||
#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 */
|
||||
|
|
|
@ -28,8 +28,8 @@ $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
|
|||
cp $< $@
|
||||
chmod -x $@
|
||||
$(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
|
||||
$(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
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie -static $< -o $@
|
||||
|
|
Загрузка…
Ссылка в новой задаче