forked from Minki/linux
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "13 patches. Subsystems affected by this patch series: resource, squashfs, hfsplus, modprobe, and mm (hugetlb, slub, userfaultfd, ksm, pagealloc, kasan, pagemap, and ioremap)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: mm/ioremap: fix iomap_max_page_shift docs: admin-guide: update description for kernel.modprobe sysctl hfsplus: prevent corruption in shrinking truncate mm/filemap: fix readahead return types kasan: fix unit tests with CONFIG_UBSAN_LOCAL_BOUNDS enabled mm: fix struct page layout on 32-bit systems ksm: revert "use GET_KSM_PAGE_NOLOCK to get ksm page in remove_rmap_item_from_tree()" userfaultfd: release page in error path to avoid BUG_ON squashfs: fix divide error in calculate_skip() kernel/resource: fix return code check in __request_free_mem_region mm, slub: move slub_debug static key enabling outside slab_mutex mm/hugetlb: fix cow where page writtable in child mm/hugetlb: fix F_SEAL_FUTURE_WRITE
This commit is contained in:
commit
a4147415bd
@ -483,10 +483,11 @@ modprobe
|
||||
========
|
||||
|
||||
The full path to the usermode helper for autoloading kernel modules,
|
||||
by default "/sbin/modprobe". This binary is executed when the kernel
|
||||
requests a module. For example, if userspace passes an unknown
|
||||
filesystem type to mount(), then the kernel will automatically request
|
||||
the corresponding filesystem module by executing this usermode helper.
|
||||
by default ``CONFIG_MODPROBE_PATH``, which in turn defaults to
|
||||
"/sbin/modprobe". This binary is executed when the kernel requests a
|
||||
module. For example, if userspace passes an unknown filesystem type
|
||||
to mount(), then the kernel will automatically request the
|
||||
corresponding filesystem module by executing this usermode helper.
|
||||
This usermode helper should insert the needed module into the kernel.
|
||||
|
||||
This sysctl only affects module autoloading. It has no effect on the
|
||||
|
@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode *inode)
|
||||
res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
|
||||
if (res)
|
||||
break;
|
||||
hfs_brec_remove(&fd);
|
||||
|
||||
mutex_unlock(&fd.tree->tree_lock);
|
||||
start = hip->cached_start;
|
||||
if (blk_cnt <= start)
|
||||
hfs_brec_remove(&fd);
|
||||
mutex_unlock(&fd.tree->tree_lock);
|
||||
hfsplus_free_extents(sb, hip->cached_extents,
|
||||
alloc_cnt - start, alloc_cnt - blk_cnt);
|
||||
hfsplus_dump_extent(hip->cached_extents);
|
||||
mutex_lock(&fd.tree->tree_lock);
|
||||
if (blk_cnt > start) {
|
||||
hip->extent_state |= HFSPLUS_EXT_DIRTY;
|
||||
break;
|
||||
@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode *inode)
|
||||
alloc_cnt = start;
|
||||
hip->cached_start = hip->cached_blocks = 0;
|
||||
hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
|
||||
mutex_lock(&fd.tree->tree_lock);
|
||||
}
|
||||
hfs_find_exit(&fd);
|
||||
|
||||
|
@ -131,6 +131,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
|
||||
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
|
||||
loff_t len, vma_len;
|
||||
int ret;
|
||||
struct hstate *h = hstate_file(file);
|
||||
@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
||||
vma->vm_ops = &hugetlb_vm_ops;
|
||||
|
||||
ret = seal_check_future_write(info->seals, vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* page based offset in vm_pgoff could be sufficiently large to
|
||||
* overflow a loff_t when converted to byte offset. This can
|
||||
|
@ -394,7 +394,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
|
||||
{
|
||||
struct inode *inode = rac->mapping->host;
|
||||
loff_t pos = readahead_pos(rac);
|
||||
loff_t length = readahead_length(rac);
|
||||
size_t length = readahead_length(rac);
|
||||
struct iomap_readpage_ctx ctx = {
|
||||
.rac = rac,
|
||||
};
|
||||
@ -402,7 +402,7 @@ void iomap_readahead(struct readahead_control *rac, const struct iomap_ops *ops)
|
||||
trace_iomap_readahead(inode, readahead_count(rac));
|
||||
|
||||
while (length > 0) {
|
||||
loff_t ret = iomap_apply(inode, pos, length, 0, ops,
|
||||
ssize_t ret = iomap_apply(inode, pos, length, 0, ops,
|
||||
&ctx, iomap_readahead_actor);
|
||||
if (ret <= 0) {
|
||||
WARN_ON_ONCE(ret == 0);
|
||||
|
@ -211,11 +211,11 @@ failure:
|
||||
* If the skip factor is limited in this way then the file will use multiple
|
||||
* slots.
|
||||
*/
|
||||
static inline int calculate_skip(int blocks)
|
||||
static inline int calculate_skip(u64 blocks)
|
||||
{
|
||||
int skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
|
||||
u64 skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
|
||||
* SQUASHFS_META_INDEXES);
|
||||
return min(SQUASHFS_CACHED_BLKS - 1, skip + 1);
|
||||
return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3216,5 +3216,37 @@ void mem_dump_obj(void *object);
|
||||
static inline void mem_dump_obj(void *object) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it
|
||||
* @seals: the seals to check
|
||||
* @vma: the vma to operate on
|
||||
*
|
||||
* Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on
|
||||
* the vma flags. Return 0 if check pass, or <0 for errors.
|
||||
*/
|
||||
static inline int seal_check_future_write(int seals, struct vm_area_struct *vma)
|
||||
{
|
||||
if (seals & F_SEAL_FUTURE_WRITE) {
|
||||
/*
|
||||
* New PROT_WRITE and MAP_SHARED mmaps are not allowed when
|
||||
* "future write" seal active.
|
||||
*/
|
||||
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
|
||||
* MAP_SHARED and read-only, take care to not allow mprotect to
|
||||
* revert protections on such mappings. Do this only for shared
|
||||
* mappings. For private mappings, don't need to mask
|
||||
* VM_MAYWRITE as we still want them to be COW-writable.
|
||||
*/
|
||||
if (vma->vm_flags & VM_SHARED)
|
||||
vma->vm_flags &= ~(VM_MAYWRITE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_MM_H */
|
||||
|
@ -97,10 +97,10 @@ struct page {
|
||||
};
|
||||
struct { /* page_pool used by netstack */
|
||||
/**
|
||||
* @dma_addr: might require a 64-bit value even on
|
||||
* @dma_addr: might require a 64-bit value on
|
||||
* 32-bit architectures.
|
||||
*/
|
||||
dma_addr_t dma_addr;
|
||||
unsigned long dma_addr[2];
|
||||
};
|
||||
struct { /* slab, slob and slub */
|
||||
union {
|
||||
|
@ -997,9 +997,9 @@ static inline loff_t readahead_pos(struct readahead_control *rac)
|
||||
* readahead_length - The number of bytes in this readahead request.
|
||||
* @rac: The readahead request.
|
||||
*/
|
||||
static inline loff_t readahead_length(struct readahead_control *rac)
|
||||
static inline size_t readahead_length(struct readahead_control *rac)
|
||||
{
|
||||
return (loff_t)rac->_nr_pages * PAGE_SIZE;
|
||||
return rac->_nr_pages * PAGE_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1024,7 +1024,7 @@ static inline unsigned int readahead_count(struct readahead_control *rac)
|
||||
* readahead_batch_length - The number of bytes in the current batch.
|
||||
* @rac: The readahead request.
|
||||
*/
|
||||
static inline loff_t readahead_batch_length(struct readahead_control *rac)
|
||||
static inline size_t readahead_batch_length(struct readahead_control *rac)
|
||||
{
|
||||
return rac->_batch_count * PAGE_SIZE;
|
||||
}
|
||||
|
@ -198,7 +198,17 @@ static inline void page_pool_recycle_direct(struct page_pool *pool,
|
||||
|
||||
static inline dma_addr_t page_pool_get_dma_addr(struct page *page)
|
||||
{
|
||||
return page->dma_addr;
|
||||
dma_addr_t ret = page->dma_addr[0];
|
||||
if (sizeof(dma_addr_t) > sizeof(unsigned long))
|
||||
ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
|
||||
{
|
||||
page->dma_addr[0] = addr;
|
||||
if (sizeof(dma_addr_t) > sizeof(unsigned long))
|
||||
page->dma_addr[1] = upper_32_bits(addr);
|
||||
}
|
||||
|
||||
static inline bool is_page_pool_compiled_in(void)
|
||||
|
@ -1805,7 +1805,7 @@ static struct resource *__request_free_mem_region(struct device *dev,
|
||||
REGION_DISJOINT)
|
||||
continue;
|
||||
|
||||
if (!__request_region_locked(res, &iomem_resource, addr, size,
|
||||
if (__request_region_locked(res, &iomem_resource, addr, size,
|
||||
name, 0))
|
||||
break;
|
||||
|
||||
|
@ -654,8 +654,20 @@ static char global_array[10];
|
||||
|
||||
static void kasan_global_oob(struct kunit *test)
|
||||
{
|
||||
volatile int i = 3;
|
||||
char *p = &global_array[ARRAY_SIZE(global_array) + i];
|
||||
/*
|
||||
* Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS
|
||||
* from failing here and panicing the kernel, access the array via a
|
||||
* volatile pointer, which will prevent the compiler from being able to
|
||||
* determine the array bounds.
|
||||
*
|
||||
* This access uses a volatile pointer to char (char *volatile) rather
|
||||
* than the more conventional pointer to volatile char (volatile char *)
|
||||
* because we want to prevent the compiler from making inferences about
|
||||
* the pointer itself (i.e. its array bounds), not the data that it
|
||||
* refers to.
|
||||
*/
|
||||
char *volatile array = global_array;
|
||||
char *p = &array[ARRAY_SIZE(global_array) + 3];
|
||||
|
||||
/* Only generic mode instruments globals. */
|
||||
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
|
||||
@ -703,8 +715,9 @@ static void ksize_uaf(struct kunit *test)
|
||||
static void kasan_stack_oob(struct kunit *test)
|
||||
{
|
||||
char stack_array[10];
|
||||
volatile int i = OOB_TAG_OFF;
|
||||
char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
|
||||
/* See comment in kasan_global_oob. */
|
||||
char *volatile array = stack_array;
|
||||
char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF];
|
||||
|
||||
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK);
|
||||
|
||||
@ -715,7 +728,9 @@ static void kasan_alloca_oob_left(struct kunit *test)
|
||||
{
|
||||
volatile int i = 10;
|
||||
char alloca_array[i];
|
||||
char *p = alloca_array - 1;
|
||||
/* See comment in kasan_global_oob. */
|
||||
char *volatile array = alloca_array;
|
||||
char *p = array - 1;
|
||||
|
||||
/* Only generic mode instruments dynamic allocas. */
|
||||
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
|
||||
@ -728,7 +743,9 @@ static void kasan_alloca_oob_right(struct kunit *test)
|
||||
{
|
||||
volatile int i = 10;
|
||||
char alloca_array[i];
|
||||
char *p = alloca_array + i;
|
||||
/* See comment in kasan_global_oob. */
|
||||
char *volatile array = alloca_array;
|
||||
char *p = array + i;
|
||||
|
||||
/* Only generic mode instruments dynamic allocas. */
|
||||
KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
|
||||
|
@ -4056,6 +4056,7 @@ again:
|
||||
* See Documentation/vm/mmu_notifier.rst
|
||||
*/
|
||||
huge_ptep_set_wrprotect(src, addr, src_pte);
|
||||
entry = huge_pte_wrprotect(entry);
|
||||
}
|
||||
|
||||
page_dup_rmap(ptepage, true);
|
||||
|
@ -16,16 +16,16 @@
|
||||
#include "pgalloc-track.h"
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
|
||||
static bool __ro_after_init iomap_max_page_shift = PAGE_SHIFT;
|
||||
static unsigned int __ro_after_init iomap_max_page_shift = BITS_PER_LONG - 1;
|
||||
|
||||
static int __init set_nohugeiomap(char *str)
|
||||
{
|
||||
iomap_max_page_shift = P4D_SHIFT;
|
||||
iomap_max_page_shift = PAGE_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
early_param("nohugeiomap", set_nohugeiomap);
|
||||
#else /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|
||||
static const bool iomap_max_page_shift = PAGE_SHIFT;
|
||||
static const unsigned int iomap_max_page_shift = PAGE_SHIFT;
|
||||
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|
||||
|
||||
int ioremap_page_range(unsigned long addr,
|
||||
|
3
mm/ksm.c
3
mm/ksm.c
@ -776,11 +776,12 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
|
||||
struct page *page;
|
||||
|
||||
stable_node = rmap_item->head;
|
||||
page = get_ksm_page(stable_node, GET_KSM_PAGE_NOLOCK);
|
||||
page = get_ksm_page(stable_node, GET_KSM_PAGE_LOCK);
|
||||
if (!page)
|
||||
goto out;
|
||||
|
||||
hlist_del(&rmap_item->hlist);
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
if (!hlist_empty(&stable_node->hlist))
|
||||
|
34
mm/shmem.c
34
mm/shmem.c
@ -2258,25 +2258,11 @@ out_nomem:
|
||||
static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(file_inode(file));
|
||||
int ret;
|
||||
|
||||
if (info->seals & F_SEAL_FUTURE_WRITE) {
|
||||
/*
|
||||
* New PROT_WRITE and MAP_SHARED mmaps are not allowed when
|
||||
* "future write" seal active.
|
||||
*/
|
||||
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
|
||||
* MAP_SHARED and read-only, take care to not allow mprotect to
|
||||
* revert protections on such mappings. Do this only for shared
|
||||
* mappings. For private mappings, don't need to mask
|
||||
* VM_MAYWRITE as we still want them to be COW-writable.
|
||||
*/
|
||||
if (vma->vm_flags & VM_SHARED)
|
||||
vma->vm_flags &= ~(VM_MAYWRITE);
|
||||
}
|
||||
ret = seal_check_future_write(info->seals, vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* arm64 - allow memory tagging on RAM-based files */
|
||||
vma->vm_flags |= VM_MTE_ALLOWED;
|
||||
@ -2375,8 +2361,18 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
||||
pgoff_t offset, max_off;
|
||||
|
||||
ret = -ENOMEM;
|
||||
if (!shmem_inode_acct_block(inode, 1))
|
||||
if (!shmem_inode_acct_block(inode, 1)) {
|
||||
/*
|
||||
* We may have got a page, returned -ENOENT triggering a retry,
|
||||
* and now we find ourselves with -ENOMEM. Release the page, to
|
||||
* avoid a BUG_ON in our caller.
|
||||
*/
|
||||
if (unlikely(*pagep)) {
|
||||
put_page(*pagep);
|
||||
*pagep = NULL;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!*pagep) {
|
||||
page = shmem_alloc_page(gfp, info, pgoff);
|
||||
|
@ -318,6 +318,16 @@ kmem_cache_create_usercopy(const char *name,
|
||||
const char *cache_name;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_SLUB_DEBUG
|
||||
/*
|
||||
* If no slub_debug was enabled globally, the static key is not yet
|
||||
* enabled by setup_slub_debug(). Enable it if the cache is being
|
||||
* created with any of the debugging flags passed explicitly.
|
||||
*/
|
||||
if (flags & SLAB_DEBUG_FLAGS)
|
||||
static_branch_enable(&slub_debug_enabled);
|
||||
#endif
|
||||
|
||||
mutex_lock(&slab_mutex);
|
||||
|
||||
err = kmem_cache_sanity_check(name, size);
|
||||
|
@ -3828,15 +3828,6 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
|
||||
|
||||
static int kmem_cache_open(struct kmem_cache *s, slab_flags_t flags)
|
||||
{
|
||||
#ifdef CONFIG_SLUB_DEBUG
|
||||
/*
|
||||
* If no slub_debug was enabled globally, the static key is not yet
|
||||
* enabled by setup_slub_debug(). Enable it if the cache is being
|
||||
* created with any of the debugging flags passed explicitly.
|
||||
*/
|
||||
if (flags & SLAB_DEBUG_FLAGS)
|
||||
static_branch_enable(&slub_debug_enabled);
|
||||
#endif
|
||||
s->flags = kmem_cache_flags(s->size, flags, s->name);
|
||||
#ifdef CONFIG_SLAB_FREELIST_HARDENED
|
||||
s->random = get_random_long();
|
||||
|
@ -174,8 +174,10 @@ static void page_pool_dma_sync_for_device(struct page_pool *pool,
|
||||
struct page *page,
|
||||
unsigned int dma_sync_size)
|
||||
{
|
||||
dma_addr_t dma_addr = page_pool_get_dma_addr(page);
|
||||
|
||||
dma_sync_size = min(dma_sync_size, pool->p.max_len);
|
||||
dma_sync_single_range_for_device(pool->p.dev, page->dma_addr,
|
||||
dma_sync_single_range_for_device(pool->p.dev, dma_addr,
|
||||
pool->p.offset, dma_sync_size,
|
||||
pool->p.dma_dir);
|
||||
}
|
||||
@ -195,7 +197,7 @@ static bool page_pool_dma_map(struct page_pool *pool, struct page *page)
|
||||
if (dma_mapping_error(pool->p.dev, dma))
|
||||
return false;
|
||||
|
||||
page->dma_addr = dma;
|
||||
page_pool_set_dma_addr(page, dma);
|
||||
|
||||
if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV)
|
||||
page_pool_dma_sync_for_device(pool, page, pool->p.max_len);
|
||||
@ -331,13 +333,13 @@ void page_pool_release_page(struct page_pool *pool, struct page *page)
|
||||
*/
|
||||
goto skip_dma_unmap;
|
||||
|
||||
dma = page->dma_addr;
|
||||
dma = page_pool_get_dma_addr(page);
|
||||
|
||||
/* When page is unmapped, it cannot be returned our pool */
|
||||
/* When page is unmapped, it cannot be returned to our pool */
|
||||
dma_unmap_page_attrs(pool->p.dev, dma,
|
||||
PAGE_SIZE << pool->p.order, pool->p.dma_dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
page->dma_addr = 0;
|
||||
page_pool_set_dma_addr(page, 0);
|
||||
skip_dma_unmap:
|
||||
/* This may be the last page returned, releasing the pool, so
|
||||
* it is not safe to reference pool afterwards.
|
||||
|
Loading…
Reference in New Issue
Block a user