18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/mm.h>
38c2ecf20Sopenharmony_ci#include <linux/slab.h>
48c2ecf20Sopenharmony_ci#include <linux/string.h>
58c2ecf20Sopenharmony_ci#include <linux/compiler.h>
68c2ecf20Sopenharmony_ci#include <linux/export.h>
78c2ecf20Sopenharmony_ci#include <linux/err.h>
88c2ecf20Sopenharmony_ci#include <linux/sched.h>
98c2ecf20Sopenharmony_ci#include <linux/sched/mm.h>
108c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
118c2ecf20Sopenharmony_ci#include <linux/sched/task_stack.h>
128c2ecf20Sopenharmony_ci#include <linux/security.h>
138c2ecf20Sopenharmony_ci#include <linux/swap.h>
148c2ecf20Sopenharmony_ci#include <linux/swapops.h>
158c2ecf20Sopenharmony_ci#include <linux/mman.h>
168c2ecf20Sopenharmony_ci#include <linux/hugetlb.h>
178c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
188c2ecf20Sopenharmony_ci#include <linux/userfaultfd_k.h>
198c2ecf20Sopenharmony_ci#include <linux/elf.h>
208c2ecf20Sopenharmony_ci#include <linux/elf-randomize.h>
218c2ecf20Sopenharmony_ci#include <linux/personality.h>
228c2ecf20Sopenharmony_ci#include <linux/random.h>
238c2ecf20Sopenharmony_ci#include <linux/processor.h>
248c2ecf20Sopenharmony_ci#include <linux/sizes.h>
258c2ecf20Sopenharmony_ci#include <linux/compat.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "internal.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/**
328c2ecf20Sopenharmony_ci * kfree_const - conditionally free memory
338c2ecf20Sopenharmony_ci * @x: pointer to the memory
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * Function calls kfree only if @x is not in .rodata section.
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_civoid kfree_const(const void *x)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	if (!is_kernel_rodata((unsigned long)x))
408c2ecf20Sopenharmony_ci		kfree(x);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kfree_const);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/**
458c2ecf20Sopenharmony_ci * kstrdup - allocate space for and copy an existing string
468c2ecf20Sopenharmony_ci * @s: the string to duplicate
478c2ecf20Sopenharmony_ci * @gfp: the GFP mask used in the kmalloc() call when allocating memory
488c2ecf20Sopenharmony_ci *
498c2ecf20Sopenharmony_ci * Return: newly allocated copy of @s or %NULL in case of error
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_cichar *kstrdup(const char *s, gfp_t gfp)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	size_t len;
548c2ecf20Sopenharmony_ci	char *buf;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	if (!s)
578c2ecf20Sopenharmony_ci		return NULL;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	len = strlen(s) + 1;
608c2ecf20Sopenharmony_ci	buf = kmalloc_track_caller(len, gfp);
618c2ecf20Sopenharmony_ci	if (buf)
628c2ecf20Sopenharmony_ci		memcpy(buf, s, len);
638c2ecf20Sopenharmony_ci	return buf;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrdup);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/**
688c2ecf20Sopenharmony_ci * kstrdup_const - conditionally duplicate an existing const string
698c2ecf20Sopenharmony_ci * @s: the string to duplicate
708c2ecf20Sopenharmony_ci * @gfp: the GFP mask used in the kmalloc() call when allocating memory
718c2ecf20Sopenharmony_ci *
728c2ecf20Sopenharmony_ci * Note: Strings allocated by kstrdup_const should be freed by kfree_const and
738c2ecf20Sopenharmony_ci * must not be passed to krealloc().
748c2ecf20Sopenharmony_ci *
758c2ecf20Sopenharmony_ci * Return: source string if it is in .rodata section otherwise
768c2ecf20Sopenharmony_ci * fallback to kstrdup.
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_ciconst char *kstrdup_const(const char *s, gfp_t gfp)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	if (is_kernel_rodata((unsigned long)s))
818c2ecf20Sopenharmony_ci		return s;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return kstrdup(s, gfp);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrdup_const);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/**
888c2ecf20Sopenharmony_ci * kstrndup - allocate space for and copy an existing string
898c2ecf20Sopenharmony_ci * @s: the string to duplicate
908c2ecf20Sopenharmony_ci * @max: read at most @max chars from @s
918c2ecf20Sopenharmony_ci * @gfp: the GFP mask used in the kmalloc() call when allocating memory
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * Note: Use kmemdup_nul() instead if the size is known exactly.
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * Return: newly allocated copy of @s or %NULL in case of error
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cichar *kstrndup(const char *s, size_t max, gfp_t gfp)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	size_t len;
1008c2ecf20Sopenharmony_ci	char *buf;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	if (!s)
1038c2ecf20Sopenharmony_ci		return NULL;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	len = strnlen(s, max);
1068c2ecf20Sopenharmony_ci	buf = kmalloc_track_caller(len+1, gfp);
1078c2ecf20Sopenharmony_ci	if (buf) {
1088c2ecf20Sopenharmony_ci		memcpy(buf, s, len);
1098c2ecf20Sopenharmony_ci		buf[len] = '\0';
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci	return buf;
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kstrndup);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/**
1168c2ecf20Sopenharmony_ci * kmemdup - duplicate region of memory
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci * @src: memory region to duplicate
1198c2ecf20Sopenharmony_ci * @len: memory region length
1208c2ecf20Sopenharmony_ci * @gfp: GFP mask to use
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * Return: newly allocated copy of @src or %NULL in case of error
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_civoid *kmemdup(const void *src, size_t len, gfp_t gfp)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	void *p;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	p = kmalloc_track_caller(len, gfp);
1298c2ecf20Sopenharmony_ci	if (p)
1308c2ecf20Sopenharmony_ci		memcpy(p, src, len);
1318c2ecf20Sopenharmony_ci	return p;
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kmemdup);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci/**
1368c2ecf20Sopenharmony_ci * kmemdup_nul - Create a NUL-terminated string from unterminated data
1378c2ecf20Sopenharmony_ci * @s: The data to stringify
1388c2ecf20Sopenharmony_ci * @len: The size of the data
1398c2ecf20Sopenharmony_ci * @gfp: the GFP mask used in the kmalloc() call when allocating memory
1408c2ecf20Sopenharmony_ci *
1418c2ecf20Sopenharmony_ci * Return: newly allocated copy of @s with NUL-termination or %NULL in
1428c2ecf20Sopenharmony_ci * case of error
1438c2ecf20Sopenharmony_ci */
1448c2ecf20Sopenharmony_cichar *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	char *buf;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	if (!s)
1498c2ecf20Sopenharmony_ci		return NULL;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	buf = kmalloc_track_caller(len + 1, gfp);
1528c2ecf20Sopenharmony_ci	if (buf) {
1538c2ecf20Sopenharmony_ci		memcpy(buf, s, len);
1548c2ecf20Sopenharmony_ci		buf[len] = '\0';
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci	return buf;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kmemdup_nul);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/**
1618c2ecf20Sopenharmony_ci * memdup_user - duplicate memory region from user space
1628c2ecf20Sopenharmony_ci *
1638c2ecf20Sopenharmony_ci * @src: source address in user space
1648c2ecf20Sopenharmony_ci * @len: number of bytes to copy
1658c2ecf20Sopenharmony_ci *
1668c2ecf20Sopenharmony_ci * Return: an ERR_PTR() on failure.  Result is physically
1678c2ecf20Sopenharmony_ci * contiguous, to be freed by kfree().
1688c2ecf20Sopenharmony_ci */
1698c2ecf20Sopenharmony_civoid *memdup_user(const void __user *src, size_t len)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	void *p;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	p = kmalloc_track_caller(len, GFP_USER | __GFP_NOWARN);
1748c2ecf20Sopenharmony_ci	if (!p)
1758c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	if (copy_from_user(p, src, len)) {
1788c2ecf20Sopenharmony_ci		kfree(p);
1798c2ecf20Sopenharmony_ci		return ERR_PTR(-EFAULT);
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	return p;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memdup_user);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci/**
1878c2ecf20Sopenharmony_ci * vmemdup_user - duplicate memory region from user space
1888c2ecf20Sopenharmony_ci *
1898c2ecf20Sopenharmony_ci * @src: source address in user space
1908c2ecf20Sopenharmony_ci * @len: number of bytes to copy
1918c2ecf20Sopenharmony_ci *
1928c2ecf20Sopenharmony_ci * Return: an ERR_PTR() on failure.  Result may be not
1938c2ecf20Sopenharmony_ci * physically contiguous.  Use kvfree() to free.
1948c2ecf20Sopenharmony_ci */
1958c2ecf20Sopenharmony_civoid *vmemdup_user(const void __user *src, size_t len)
1968c2ecf20Sopenharmony_ci{
1978c2ecf20Sopenharmony_ci	void *p;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	p = kvmalloc(len, GFP_USER);
2008c2ecf20Sopenharmony_ci	if (!p)
2018c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (copy_from_user(p, src, len)) {
2048c2ecf20Sopenharmony_ci		kvfree(p);
2058c2ecf20Sopenharmony_ci		return ERR_PTR(-EFAULT);
2068c2ecf20Sopenharmony_ci	}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	return p;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vmemdup_user);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci/**
2138c2ecf20Sopenharmony_ci * strndup_user - duplicate an existing string from user space
2148c2ecf20Sopenharmony_ci * @s: The string to duplicate
2158c2ecf20Sopenharmony_ci * @n: Maximum number of bytes to copy, including the trailing NUL.
2168c2ecf20Sopenharmony_ci *
2178c2ecf20Sopenharmony_ci * Return: newly allocated copy of @s or an ERR_PTR() in case of error
2188c2ecf20Sopenharmony_ci */
2198c2ecf20Sopenharmony_cichar *strndup_user(const char __user *s, long n)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	char *p;
2228c2ecf20Sopenharmony_ci	long length;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	length = strnlen_user(s, n);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	if (!length)
2278c2ecf20Sopenharmony_ci		return ERR_PTR(-EFAULT);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	if (length > n)
2308c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	p = memdup_user(s, length);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	if (IS_ERR(p))
2358c2ecf20Sopenharmony_ci		return p;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	p[length - 1] = '\0';
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return p;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(strndup_user);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/**
2448c2ecf20Sopenharmony_ci * memdup_user_nul - duplicate memory region from user space and NUL-terminate
2458c2ecf20Sopenharmony_ci *
2468c2ecf20Sopenharmony_ci * @src: source address in user space
2478c2ecf20Sopenharmony_ci * @len: number of bytes to copy
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci * Return: an ERR_PTR() on failure.
2508c2ecf20Sopenharmony_ci */
2518c2ecf20Sopenharmony_civoid *memdup_user_nul(const void __user *src, size_t len)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	char *p;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	/*
2568c2ecf20Sopenharmony_ci	 * Always use GFP_KERNEL, since copy_from_user() can sleep and
2578c2ecf20Sopenharmony_ci	 * cause pagefault, which makes it pointless to use GFP_NOFS
2588c2ecf20Sopenharmony_ci	 * or GFP_ATOMIC.
2598c2ecf20Sopenharmony_ci	 */
2608c2ecf20Sopenharmony_ci	p = kmalloc_track_caller(len + 1, GFP_KERNEL);
2618c2ecf20Sopenharmony_ci	if (!p)
2628c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (copy_from_user(p, src, len)) {
2658c2ecf20Sopenharmony_ci		kfree(p);
2668c2ecf20Sopenharmony_ci		return ERR_PTR(-EFAULT);
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci	p[len] = '\0';
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	return p;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(memdup_user_nul);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_civoid __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
2758c2ecf20Sopenharmony_ci		struct vm_area_struct *prev)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	struct vm_area_struct *next;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	vma->vm_prev = prev;
2808c2ecf20Sopenharmony_ci	if (prev) {
2818c2ecf20Sopenharmony_ci		next = prev->vm_next;
2828c2ecf20Sopenharmony_ci		prev->vm_next = vma;
2838c2ecf20Sopenharmony_ci	} else {
2848c2ecf20Sopenharmony_ci		next = mm->mmap;
2858c2ecf20Sopenharmony_ci		mm->mmap = vma;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci	vma->vm_next = next;
2888c2ecf20Sopenharmony_ci	if (next)
2898c2ecf20Sopenharmony_ci		next->vm_prev = vma;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_civoid __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	struct vm_area_struct *prev, *next;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	next = vma->vm_next;
2978c2ecf20Sopenharmony_ci	prev = vma->vm_prev;
2988c2ecf20Sopenharmony_ci	if (prev)
2998c2ecf20Sopenharmony_ci		prev->vm_next = next;
3008c2ecf20Sopenharmony_ci	else
3018c2ecf20Sopenharmony_ci		mm->mmap = next;
3028c2ecf20Sopenharmony_ci	if (next)
3038c2ecf20Sopenharmony_ci		next->vm_prev = prev;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci/* Check if the vma is being used as a stack by this task */
3078c2ecf20Sopenharmony_ciint vma_is_stack_for_current(struct vm_area_struct *vma)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	struct task_struct * __maybe_unused t = current;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci#ifndef STACK_RND_MASK
3158c2ecf20Sopenharmony_ci#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12))     /* 8MB of VA */
3168c2ecf20Sopenharmony_ci#endif
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ciunsigned long randomize_stack_top(unsigned long stack_top)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	unsigned long random_variable = 0;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (current->flags & PF_RANDOMIZE) {
3238c2ecf20Sopenharmony_ci		random_variable = get_random_long();
3248c2ecf20Sopenharmony_ci		random_variable &= STACK_RND_MASK;
3258c2ecf20Sopenharmony_ci		random_variable <<= PAGE_SHIFT;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci#ifdef CONFIG_STACK_GROWSUP
3288c2ecf20Sopenharmony_ci	return PAGE_ALIGN(stack_top) + random_variable;
3298c2ecf20Sopenharmony_ci#else
3308c2ecf20Sopenharmony_ci	return PAGE_ALIGN(stack_top) - random_variable;
3318c2ecf20Sopenharmony_ci#endif
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci/**
3358c2ecf20Sopenharmony_ci * randomize_page - Generate a random, page aligned address
3368c2ecf20Sopenharmony_ci * @start:	The smallest acceptable address the caller will take.
3378c2ecf20Sopenharmony_ci * @range:	The size of the area, starting at @start, within which the
3388c2ecf20Sopenharmony_ci *		random address must fall.
3398c2ecf20Sopenharmony_ci *
3408c2ecf20Sopenharmony_ci * If @start + @range would overflow, @range is capped.
3418c2ecf20Sopenharmony_ci *
3428c2ecf20Sopenharmony_ci * NOTE: Historical use of randomize_range, which this replaces, presumed that
3438c2ecf20Sopenharmony_ci * @start was already page aligned.  We now align it regardless.
3448c2ecf20Sopenharmony_ci *
3458c2ecf20Sopenharmony_ci * Return: A page aligned address within [start, start + range).  On error,
3468c2ecf20Sopenharmony_ci * @start is returned.
3478c2ecf20Sopenharmony_ci */
3488c2ecf20Sopenharmony_ciunsigned long randomize_page(unsigned long start, unsigned long range)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	if (!PAGE_ALIGNED(start)) {
3518c2ecf20Sopenharmony_ci		range -= PAGE_ALIGN(start) - start;
3528c2ecf20Sopenharmony_ci		start = PAGE_ALIGN(start);
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	if (start > ULONG_MAX - range)
3568c2ecf20Sopenharmony_ci		range = ULONG_MAX - start;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	range >>= PAGE_SHIFT;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	if (range == 0)
3618c2ecf20Sopenharmony_ci		return start;
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	return start + (get_random_long() % range << PAGE_SHIFT);
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
3678c2ecf20Sopenharmony_ciunsigned long arch_randomize_brk(struct mm_struct *mm)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	/* Is the current task 32bit ? */
3708c2ecf20Sopenharmony_ci	if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
3718c2ecf20Sopenharmony_ci		return randomize_page(mm->brk, SZ_32M);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	return randomize_page(mm->brk, SZ_1G);
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ciunsigned long arch_mmap_rnd(void)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	unsigned long rnd;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
3818c2ecf20Sopenharmony_ci	if (is_compat_task())
3828c2ecf20Sopenharmony_ci		rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
3838c2ecf20Sopenharmony_ci	else
3848c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS */
3858c2ecf20Sopenharmony_ci		rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	return rnd << PAGE_SHIFT;
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic int mmap_is_legacy(struct rlimit *rlim_stack)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	if (current->personality & ADDR_COMPAT_LAYOUT)
3938c2ecf20Sopenharmony_ci		return 1;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	if (rlim_stack->rlim_cur == RLIM_INFINITY)
3968c2ecf20Sopenharmony_ci		return 1;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	return sysctl_legacy_va_layout;
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci/*
4028c2ecf20Sopenharmony_ci * Leave enough space between the mmap area and the stack to honour ulimit in
4038c2ecf20Sopenharmony_ci * the face of randomisation.
4048c2ecf20Sopenharmony_ci */
4058c2ecf20Sopenharmony_ci#define MIN_GAP		(SZ_128M)
4068c2ecf20Sopenharmony_ci#define MAX_GAP		(STACK_TOP / 6 * 5)
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	unsigned long gap = rlim_stack->rlim_cur;
4118c2ecf20Sopenharmony_ci	unsigned long pad = stack_guard_gap;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	/* Account for stack randomization if necessary */
4148c2ecf20Sopenharmony_ci	if (current->flags & PF_RANDOMIZE)
4158c2ecf20Sopenharmony_ci		pad += (STACK_RND_MASK << PAGE_SHIFT);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	/* Values close to RLIM_INFINITY can overflow. */
4188c2ecf20Sopenharmony_ci	if (gap + pad > gap)
4198c2ecf20Sopenharmony_ci		gap += pad;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (gap < MIN_GAP)
4228c2ecf20Sopenharmony_ci		gap = MIN_GAP;
4238c2ecf20Sopenharmony_ci	else if (gap > MAX_GAP)
4248c2ecf20Sopenharmony_ci		gap = MAX_GAP;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	return PAGE_ALIGN(STACK_TOP - gap - rnd);
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_civoid arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	unsigned long random_factor = 0UL;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	if (current->flags & PF_RANDOMIZE)
4348c2ecf20Sopenharmony_ci		random_factor = arch_mmap_rnd();
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (mmap_is_legacy(rlim_stack)) {
4378c2ecf20Sopenharmony_ci		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
4388c2ecf20Sopenharmony_ci		mm->get_unmapped_area = arch_get_unmapped_area;
4398c2ecf20Sopenharmony_ci	} else {
4408c2ecf20Sopenharmony_ci		mm->mmap_base = mmap_base(random_factor, rlim_stack);
4418c2ecf20Sopenharmony_ci		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci#elif defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
4458c2ecf20Sopenharmony_civoid arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	mm->mmap_base = TASK_UNMAPPED_BASE;
4488c2ecf20Sopenharmony_ci	mm->get_unmapped_area = arch_get_unmapped_area;
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci#endif
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/**
4538c2ecf20Sopenharmony_ci * __account_locked_vm - account locked pages to an mm's locked_vm
4548c2ecf20Sopenharmony_ci * @mm:          mm to account against
4558c2ecf20Sopenharmony_ci * @pages:       number of pages to account
4568c2ecf20Sopenharmony_ci * @inc:         %true if @pages should be considered positive, %false if not
4578c2ecf20Sopenharmony_ci * @task:        task used to check RLIMIT_MEMLOCK
4588c2ecf20Sopenharmony_ci * @bypass_rlim: %true if checking RLIMIT_MEMLOCK should be skipped
4598c2ecf20Sopenharmony_ci *
4608c2ecf20Sopenharmony_ci * Assumes @task and @mm are valid (i.e. at least one reference on each), and
4618c2ecf20Sopenharmony_ci * that mmap_lock is held as writer.
4628c2ecf20Sopenharmony_ci *
4638c2ecf20Sopenharmony_ci * Return:
4648c2ecf20Sopenharmony_ci * * 0       on success
4658c2ecf20Sopenharmony_ci * * -ENOMEM if RLIMIT_MEMLOCK would be exceeded.
4668c2ecf20Sopenharmony_ci */
4678c2ecf20Sopenharmony_ciint __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc,
4688c2ecf20Sopenharmony_ci			struct task_struct *task, bool bypass_rlim)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	unsigned long locked_vm, limit;
4718c2ecf20Sopenharmony_ci	int ret = 0;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	mmap_assert_write_locked(mm);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	locked_vm = mm->locked_vm;
4768c2ecf20Sopenharmony_ci	if (inc) {
4778c2ecf20Sopenharmony_ci		if (!bypass_rlim) {
4788c2ecf20Sopenharmony_ci			limit = task_rlimit(task, RLIMIT_MEMLOCK) >> PAGE_SHIFT;
4798c2ecf20Sopenharmony_ci			if (locked_vm + pages > limit)
4808c2ecf20Sopenharmony_ci				ret = -ENOMEM;
4818c2ecf20Sopenharmony_ci		}
4828c2ecf20Sopenharmony_ci		if (!ret)
4838c2ecf20Sopenharmony_ci			mm->locked_vm = locked_vm + pages;
4848c2ecf20Sopenharmony_ci	} else {
4858c2ecf20Sopenharmony_ci		WARN_ON_ONCE(pages > locked_vm);
4868c2ecf20Sopenharmony_ci		mm->locked_vm = locked_vm - pages;
4878c2ecf20Sopenharmony_ci	}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	pr_debug("%s: [%d] caller %ps %c%lu %lu/%lu%s\n", __func__, task->pid,
4908c2ecf20Sopenharmony_ci		 (void *)_RET_IP_, (inc) ? '+' : '-', pages << PAGE_SHIFT,
4918c2ecf20Sopenharmony_ci		 locked_vm << PAGE_SHIFT, task_rlimit(task, RLIMIT_MEMLOCK),
4928c2ecf20Sopenharmony_ci		 ret ? " - exceeded" : "");
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return ret;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__account_locked_vm);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci/**
4998c2ecf20Sopenharmony_ci * account_locked_vm - account locked pages to an mm's locked_vm
5008c2ecf20Sopenharmony_ci * @mm:          mm to account against, may be NULL
5018c2ecf20Sopenharmony_ci * @pages:       number of pages to account
5028c2ecf20Sopenharmony_ci * @inc:         %true if @pages should be considered positive, %false if not
5038c2ecf20Sopenharmony_ci *
5048c2ecf20Sopenharmony_ci * Assumes a non-NULL @mm is valid (i.e. at least one reference on it).
5058c2ecf20Sopenharmony_ci *
5068c2ecf20Sopenharmony_ci * Return:
5078c2ecf20Sopenharmony_ci * * 0       on success, or if mm is NULL
5088c2ecf20Sopenharmony_ci * * -ENOMEM if RLIMIT_MEMLOCK would be exceeded.
5098c2ecf20Sopenharmony_ci */
5108c2ecf20Sopenharmony_ciint account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc)
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	int ret;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	if (pages == 0 || !mm)
5158c2ecf20Sopenharmony_ci		return 0;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	mmap_write_lock(mm);
5188c2ecf20Sopenharmony_ci	ret = __account_locked_vm(mm, pages, inc, current,
5198c2ecf20Sopenharmony_ci				  capable(CAP_IPC_LOCK));
5208c2ecf20Sopenharmony_ci	mmap_write_unlock(mm);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	return ret;
5238c2ecf20Sopenharmony_ci}
5248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(account_locked_vm);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ciunsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
5278c2ecf20Sopenharmony_ci	unsigned long len, unsigned long prot,
5288c2ecf20Sopenharmony_ci	unsigned long flag, unsigned long pgoff)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	unsigned long ret;
5318c2ecf20Sopenharmony_ci	struct mm_struct *mm = current->mm;
5328c2ecf20Sopenharmony_ci	unsigned long populate;
5338c2ecf20Sopenharmony_ci	LIST_HEAD(uf);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	ret = security_mmap_file(file, prot, flag);
5368c2ecf20Sopenharmony_ci	if (!ret) {
5378c2ecf20Sopenharmony_ci		if (mmap_write_lock_killable(mm))
5388c2ecf20Sopenharmony_ci			return -EINTR;
5398c2ecf20Sopenharmony_ci		ret = do_mmap(file, addr, len, prot, flag, pgoff, &populate,
5408c2ecf20Sopenharmony_ci			      &uf);
5418c2ecf20Sopenharmony_ci		mmap_write_unlock(mm);
5428c2ecf20Sopenharmony_ci		userfaultfd_unmap_complete(mm, &uf);
5438c2ecf20Sopenharmony_ci		if (populate)
5448c2ecf20Sopenharmony_ci			mm_populate(ret, populate);
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci	return ret;
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ciunsigned long vm_mmap(struct file *file, unsigned long addr,
5508c2ecf20Sopenharmony_ci	unsigned long len, unsigned long prot,
5518c2ecf20Sopenharmony_ci	unsigned long flag, unsigned long offset)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	if (unlikely(offset + PAGE_ALIGN(len) < offset))
5548c2ecf20Sopenharmony_ci		return -EINVAL;
5558c2ecf20Sopenharmony_ci	if (unlikely(offset_in_page(offset)))
5568c2ecf20Sopenharmony_ci		return -EINVAL;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vm_mmap);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci/**
5638c2ecf20Sopenharmony_ci * kvmalloc_node - attempt to allocate physically contiguous memory, but upon
5648c2ecf20Sopenharmony_ci * failure, fall back to non-contiguous (vmalloc) allocation.
5658c2ecf20Sopenharmony_ci * @size: size of the request.
5668c2ecf20Sopenharmony_ci * @flags: gfp mask for the allocation - must be compatible (superset) with GFP_KERNEL.
5678c2ecf20Sopenharmony_ci * @node: numa node to allocate from
5688c2ecf20Sopenharmony_ci *
5698c2ecf20Sopenharmony_ci * Uses kmalloc to get the memory but if the allocation fails then falls back
5708c2ecf20Sopenharmony_ci * to the vmalloc allocator. Use kvfree for freeing the memory.
5718c2ecf20Sopenharmony_ci *
5728c2ecf20Sopenharmony_ci * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported.
5738c2ecf20Sopenharmony_ci * __GFP_RETRY_MAYFAIL is supported, and it should be used only if kmalloc is
5748c2ecf20Sopenharmony_ci * preferable to the vmalloc fallback, due to visible performance drawbacks.
5758c2ecf20Sopenharmony_ci *
5768c2ecf20Sopenharmony_ci * Please note that any use of gfp flags outside of GFP_KERNEL is careful to not
5778c2ecf20Sopenharmony_ci * fall back to vmalloc.
5788c2ecf20Sopenharmony_ci *
5798c2ecf20Sopenharmony_ci * Return: pointer to the allocated memory of %NULL in case of failure
5808c2ecf20Sopenharmony_ci */
5818c2ecf20Sopenharmony_civoid *kvmalloc_node(size_t size, gfp_t flags, int node)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	gfp_t kmalloc_flags = flags;
5848c2ecf20Sopenharmony_ci	void *ret;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	/*
5878c2ecf20Sopenharmony_ci	 * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
5888c2ecf20Sopenharmony_ci	 * so the given set of flags has to be compatible.
5898c2ecf20Sopenharmony_ci	 */
5908c2ecf20Sopenharmony_ci	if ((flags & GFP_KERNEL) != GFP_KERNEL)
5918c2ecf20Sopenharmony_ci		return kmalloc_node(size, flags, node);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	/*
5948c2ecf20Sopenharmony_ci	 * We want to attempt a large physically contiguous block first because
5958c2ecf20Sopenharmony_ci	 * it is less likely to fragment multiple larger blocks and therefore
5968c2ecf20Sopenharmony_ci	 * contribute to a long term fragmentation less than vmalloc fallback.
5978c2ecf20Sopenharmony_ci	 * However make sure that larger requests are not too disruptive - no
5988c2ecf20Sopenharmony_ci	 * OOM killer and no allocation failure warnings as we have a fallback.
5998c2ecf20Sopenharmony_ci	 */
6008c2ecf20Sopenharmony_ci	if (size > PAGE_SIZE) {
6018c2ecf20Sopenharmony_ci		kmalloc_flags |= __GFP_NOWARN;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci		if (!(kmalloc_flags & __GFP_RETRY_MAYFAIL))
6048c2ecf20Sopenharmony_ci			kmalloc_flags |= __GFP_NORETRY;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	ret = kmalloc_node(size, kmalloc_flags, node);
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	/*
6108c2ecf20Sopenharmony_ci	 * It doesn't really make sense to fallback to vmalloc for sub page
6118c2ecf20Sopenharmony_ci	 * requests
6128c2ecf20Sopenharmony_ci	 */
6138c2ecf20Sopenharmony_ci	if (ret || size <= PAGE_SIZE)
6148c2ecf20Sopenharmony_ci		return ret;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	/* Don't even allow crazy sizes */
6178c2ecf20Sopenharmony_ci	if (unlikely(size > INT_MAX)) {
6188c2ecf20Sopenharmony_ci		WARN_ON_ONCE(!(flags & __GFP_NOWARN));
6198c2ecf20Sopenharmony_ci		return NULL;
6208c2ecf20Sopenharmony_ci	}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	return __vmalloc_node(size, 1, flags, node,
6238c2ecf20Sopenharmony_ci			__builtin_return_address(0));
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kvmalloc_node);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci/**
6288c2ecf20Sopenharmony_ci * kvfree() - Free memory.
6298c2ecf20Sopenharmony_ci * @addr: Pointer to allocated memory.
6308c2ecf20Sopenharmony_ci *
6318c2ecf20Sopenharmony_ci * kvfree frees memory allocated by any of vmalloc(), kmalloc() or kvmalloc().
6328c2ecf20Sopenharmony_ci * It is slightly more efficient to use kfree() or vfree() if you are certain
6338c2ecf20Sopenharmony_ci * that you know which one to use.
6348c2ecf20Sopenharmony_ci *
6358c2ecf20Sopenharmony_ci * Context: Either preemptible task context or not-NMI interrupt.
6368c2ecf20Sopenharmony_ci */
6378c2ecf20Sopenharmony_civoid kvfree(const void *addr)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	if (is_vmalloc_addr(addr))
6408c2ecf20Sopenharmony_ci		vfree(addr);
6418c2ecf20Sopenharmony_ci	else
6428c2ecf20Sopenharmony_ci		kfree(addr);
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kvfree);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci/**
6478c2ecf20Sopenharmony_ci * kvfree_sensitive - Free a data object containing sensitive information.
6488c2ecf20Sopenharmony_ci * @addr: address of the data object to be freed.
6498c2ecf20Sopenharmony_ci * @len: length of the data object.
6508c2ecf20Sopenharmony_ci *
6518c2ecf20Sopenharmony_ci * Use the special memzero_explicit() function to clear the content of a
6528c2ecf20Sopenharmony_ci * kvmalloc'ed object containing sensitive data to make sure that the
6538c2ecf20Sopenharmony_ci * compiler won't optimize out the data clearing.
6548c2ecf20Sopenharmony_ci */
6558c2ecf20Sopenharmony_civoid kvfree_sensitive(const void *addr, size_t len)
6568c2ecf20Sopenharmony_ci{
6578c2ecf20Sopenharmony_ci	if (likely(!ZERO_OR_NULL_PTR(addr))) {
6588c2ecf20Sopenharmony_ci		memzero_explicit((void *)addr, len);
6598c2ecf20Sopenharmony_ci		kvfree(addr);
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kvfree_sensitive);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_civoid *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags)
6658c2ecf20Sopenharmony_ci{
6668c2ecf20Sopenharmony_ci	void *newp;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	if (oldsize >= newsize)
6698c2ecf20Sopenharmony_ci		return (void *)p;
6708c2ecf20Sopenharmony_ci	newp = kvmalloc(newsize, flags);
6718c2ecf20Sopenharmony_ci	if (!newp)
6728c2ecf20Sopenharmony_ci		return NULL;
6738c2ecf20Sopenharmony_ci	memcpy(newp, p, oldsize);
6748c2ecf20Sopenharmony_ci	kvfree(p);
6758c2ecf20Sopenharmony_ci	return newp;
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kvrealloc);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_cistatic inline void *__page_rmapping(struct page *page)
6808c2ecf20Sopenharmony_ci{
6818c2ecf20Sopenharmony_ci	unsigned long mapping;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	mapping = (unsigned long)page->mapping;
6848c2ecf20Sopenharmony_ci	mapping &= ~PAGE_MAPPING_FLAGS;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	return (void *)mapping;
6878c2ecf20Sopenharmony_ci}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci/**
6908c2ecf20Sopenharmony_ci * __vmalloc_array - allocate memory for a virtually contiguous array.
6918c2ecf20Sopenharmony_ci * @n: number of elements.
6928c2ecf20Sopenharmony_ci * @size: element size.
6938c2ecf20Sopenharmony_ci * @flags: the type of memory to allocate (see kmalloc).
6948c2ecf20Sopenharmony_ci */
6958c2ecf20Sopenharmony_civoid *__vmalloc_array(size_t n, size_t size, gfp_t flags)
6968c2ecf20Sopenharmony_ci{
6978c2ecf20Sopenharmony_ci	size_t bytes;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	if (unlikely(check_mul_overflow(n, size, &bytes)))
7008c2ecf20Sopenharmony_ci		return NULL;
7018c2ecf20Sopenharmony_ci	return __vmalloc(bytes, flags);
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__vmalloc_array);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci/**
7068c2ecf20Sopenharmony_ci * vmalloc_array - allocate memory for a virtually contiguous array.
7078c2ecf20Sopenharmony_ci * @n: number of elements.
7088c2ecf20Sopenharmony_ci * @size: element size.
7098c2ecf20Sopenharmony_ci */
7108c2ecf20Sopenharmony_civoid *vmalloc_array(size_t n, size_t size)
7118c2ecf20Sopenharmony_ci{
7128c2ecf20Sopenharmony_ci	return __vmalloc_array(n, size, GFP_KERNEL);
7138c2ecf20Sopenharmony_ci}
7148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vmalloc_array);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci/**
7178c2ecf20Sopenharmony_ci * __vcalloc - allocate and zero memory for a virtually contiguous array.
7188c2ecf20Sopenharmony_ci * @n: number of elements.
7198c2ecf20Sopenharmony_ci * @size: element size.
7208c2ecf20Sopenharmony_ci * @flags: the type of memory to allocate (see kmalloc).
7218c2ecf20Sopenharmony_ci */
7228c2ecf20Sopenharmony_civoid *__vcalloc(size_t n, size_t size, gfp_t flags)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	return __vmalloc_array(n, size, flags | __GFP_ZERO);
7258c2ecf20Sopenharmony_ci}
7268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__vcalloc);
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci/**
7298c2ecf20Sopenharmony_ci * vcalloc - allocate and zero memory for a virtually contiguous array.
7308c2ecf20Sopenharmony_ci * @n: number of elements.
7318c2ecf20Sopenharmony_ci * @size: element size.
7328c2ecf20Sopenharmony_ci */
7338c2ecf20Sopenharmony_civoid *vcalloc(size_t n, size_t size)
7348c2ecf20Sopenharmony_ci{
7358c2ecf20Sopenharmony_ci	return __vmalloc_array(n, size, GFP_KERNEL | __GFP_ZERO);
7368c2ecf20Sopenharmony_ci}
7378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(vcalloc);
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci/* Neutral page->mapping pointer to address_space or anon_vma or other */
7408c2ecf20Sopenharmony_civoid *page_rmapping(struct page *page)
7418c2ecf20Sopenharmony_ci{
7428c2ecf20Sopenharmony_ci	page = compound_head(page);
7438c2ecf20Sopenharmony_ci	return __page_rmapping(page);
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci/*
7478c2ecf20Sopenharmony_ci * Return true if this page is mapped into pagetables.
7488c2ecf20Sopenharmony_ci * For compound page it returns true if any subpage of compound page is mapped.
7498c2ecf20Sopenharmony_ci */
7508c2ecf20Sopenharmony_cibool page_mapped(struct page *page)
7518c2ecf20Sopenharmony_ci{
7528c2ecf20Sopenharmony_ci	int i;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	if (likely(!PageCompound(page)))
7558c2ecf20Sopenharmony_ci		return atomic_read(&page->_mapcount) >= 0;
7568c2ecf20Sopenharmony_ci	page = compound_head(page);
7578c2ecf20Sopenharmony_ci	if (atomic_read(compound_mapcount_ptr(page)) >= 0)
7588c2ecf20Sopenharmony_ci		return true;
7598c2ecf20Sopenharmony_ci	if (PageHuge(page))
7608c2ecf20Sopenharmony_ci		return false;
7618c2ecf20Sopenharmony_ci	for (i = 0; i < compound_nr(page); i++) {
7628c2ecf20Sopenharmony_ci		if (atomic_read(&page[i]._mapcount) >= 0)
7638c2ecf20Sopenharmony_ci			return true;
7648c2ecf20Sopenharmony_ci	}
7658c2ecf20Sopenharmony_ci	return false;
7668c2ecf20Sopenharmony_ci}
7678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(page_mapped);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistruct anon_vma *page_anon_vma(struct page *page)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	unsigned long mapping;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	page = compound_head(page);
7748c2ecf20Sopenharmony_ci	mapping = (unsigned long)page->mapping;
7758c2ecf20Sopenharmony_ci	if ((mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON)
7768c2ecf20Sopenharmony_ci		return NULL;
7778c2ecf20Sopenharmony_ci	return __page_rmapping(page);
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_cistruct address_space *page_mapping(struct page *page)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	struct address_space *mapping;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	page = compound_head(page);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	/* This happens if someone calls flush_dcache_page on slab page */
7878c2ecf20Sopenharmony_ci	if (unlikely(PageSlab(page)))
7888c2ecf20Sopenharmony_ci		return NULL;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	if (unlikely(PageSwapCache(page))) {
7918c2ecf20Sopenharmony_ci		swp_entry_t entry;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci		entry.val = page_private(page);
7948c2ecf20Sopenharmony_ci		return swap_address_space(entry);
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	mapping = page->mapping;
7988c2ecf20Sopenharmony_ci	if ((unsigned long)mapping & PAGE_MAPPING_ANON)
7998c2ecf20Sopenharmony_ci		return NULL;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return (void *)((unsigned long)mapping & ~PAGE_MAPPING_FLAGS);
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(page_mapping);
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci/*
8068c2ecf20Sopenharmony_ci * For file cache pages, return the address_space, otherwise return NULL
8078c2ecf20Sopenharmony_ci */
8088c2ecf20Sopenharmony_cistruct address_space *page_mapping_file(struct page *page)
8098c2ecf20Sopenharmony_ci{
8108c2ecf20Sopenharmony_ci	if (unlikely(PageSwapCache(page)))
8118c2ecf20Sopenharmony_ci		return NULL;
8128c2ecf20Sopenharmony_ci	return page_mapping(page);
8138c2ecf20Sopenharmony_ci}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci/* Slow path of page_mapcount() for compound pages */
8168c2ecf20Sopenharmony_ciint __page_mapcount(struct page *page)
8178c2ecf20Sopenharmony_ci{
8188c2ecf20Sopenharmony_ci	int ret;
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	ret = atomic_read(&page->_mapcount) + 1;
8218c2ecf20Sopenharmony_ci	/*
8228c2ecf20Sopenharmony_ci	 * For file THP page->_mapcount contains total number of mapping
8238c2ecf20Sopenharmony_ci	 * of the page: no need to look into compound_mapcount.
8248c2ecf20Sopenharmony_ci	 */
8258c2ecf20Sopenharmony_ci	if (!PageAnon(page) && !PageHuge(page))
8268c2ecf20Sopenharmony_ci		return ret;
8278c2ecf20Sopenharmony_ci	page = compound_head(page);
8288c2ecf20Sopenharmony_ci	ret += atomic_read(compound_mapcount_ptr(page)) + 1;
8298c2ecf20Sopenharmony_ci	if (PageDoubleMap(page))
8308c2ecf20Sopenharmony_ci		ret--;
8318c2ecf20Sopenharmony_ci	return ret;
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__page_mapcount);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ciint sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS;
8368c2ecf20Sopenharmony_ciint sysctl_overcommit_ratio __read_mostly = 50;
8378c2ecf20Sopenharmony_ciunsigned long sysctl_overcommit_kbytes __read_mostly;
8388c2ecf20Sopenharmony_ciint sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
8398c2ecf20Sopenharmony_ciunsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
8408c2ecf20Sopenharmony_ciunsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ciint overcommit_ratio_handler(struct ctl_table *table, int write, void *buffer,
8438c2ecf20Sopenharmony_ci		size_t *lenp, loff_t *ppos)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	int ret;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	ret = proc_dointvec(table, write, buffer, lenp, ppos);
8488c2ecf20Sopenharmony_ci	if (ret == 0 && write)
8498c2ecf20Sopenharmony_ci		sysctl_overcommit_kbytes = 0;
8508c2ecf20Sopenharmony_ci	return ret;
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_cistatic void sync_overcommit_as(struct work_struct *dummy)
8548c2ecf20Sopenharmony_ci{
8558c2ecf20Sopenharmony_ci	percpu_counter_sync(&vm_committed_as);
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ciint overcommit_policy_handler(struct ctl_table *table, int write, void *buffer,
8598c2ecf20Sopenharmony_ci		size_t *lenp, loff_t *ppos)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	struct ctl_table t;
8628c2ecf20Sopenharmony_ci	int new_policy = -1;
8638c2ecf20Sopenharmony_ci	int ret;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	/*
8668c2ecf20Sopenharmony_ci	 * The deviation of sync_overcommit_as could be big with loose policy
8678c2ecf20Sopenharmony_ci	 * like OVERCOMMIT_ALWAYS/OVERCOMMIT_GUESS. When changing policy to
8688c2ecf20Sopenharmony_ci	 * strict OVERCOMMIT_NEVER, we need to reduce the deviation to comply
8698c2ecf20Sopenharmony_ci	 * with the strict "NEVER", and to avoid possible race condtion (even
8708c2ecf20Sopenharmony_ci	 * though user usually won't too frequently do the switching to policy
8718c2ecf20Sopenharmony_ci	 * OVERCOMMIT_NEVER), the switch is done in the following order:
8728c2ecf20Sopenharmony_ci	 *	1. changing the batch
8738c2ecf20Sopenharmony_ci	 *	2. sync percpu count on each CPU
8748c2ecf20Sopenharmony_ci	 *	3. switch the policy
8758c2ecf20Sopenharmony_ci	 */
8768c2ecf20Sopenharmony_ci	if (write) {
8778c2ecf20Sopenharmony_ci		t = *table;
8788c2ecf20Sopenharmony_ci		t.data = &new_policy;
8798c2ecf20Sopenharmony_ci		ret = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
8808c2ecf20Sopenharmony_ci		if (ret || new_policy == -1)
8818c2ecf20Sopenharmony_ci			return ret;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci		mm_compute_batch(new_policy);
8848c2ecf20Sopenharmony_ci		if (new_policy == OVERCOMMIT_NEVER)
8858c2ecf20Sopenharmony_ci			schedule_on_each_cpu(sync_overcommit_as);
8868c2ecf20Sopenharmony_ci		sysctl_overcommit_memory = new_policy;
8878c2ecf20Sopenharmony_ci	} else {
8888c2ecf20Sopenharmony_ci		ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
8898c2ecf20Sopenharmony_ci	}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	return ret;
8928c2ecf20Sopenharmony_ci}
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ciint overcommit_kbytes_handler(struct ctl_table *table, int write, void *buffer,
8958c2ecf20Sopenharmony_ci		size_t *lenp, loff_t *ppos)
8968c2ecf20Sopenharmony_ci{
8978c2ecf20Sopenharmony_ci	int ret;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
9008c2ecf20Sopenharmony_ci	if (ret == 0 && write)
9018c2ecf20Sopenharmony_ci		sysctl_overcommit_ratio = 0;
9028c2ecf20Sopenharmony_ci	return ret;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci/*
9068c2ecf20Sopenharmony_ci * Committed memory limit enforced when OVERCOMMIT_NEVER policy is used
9078c2ecf20Sopenharmony_ci */
9088c2ecf20Sopenharmony_ciunsigned long vm_commit_limit(void)
9098c2ecf20Sopenharmony_ci{
9108c2ecf20Sopenharmony_ci	unsigned long allowed;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	if (sysctl_overcommit_kbytes)
9138c2ecf20Sopenharmony_ci		allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
9148c2ecf20Sopenharmony_ci	else
9158c2ecf20Sopenharmony_ci		allowed = ((totalram_pages() - hugetlb_total_pages())
9168c2ecf20Sopenharmony_ci			   * sysctl_overcommit_ratio / 100);
9178c2ecf20Sopenharmony_ci	allowed += total_swap_pages;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	return allowed;
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci/*
9238c2ecf20Sopenharmony_ci * Make sure vm_committed_as in one cacheline and not cacheline shared with
9248c2ecf20Sopenharmony_ci * other variables. It can be updated by several CPUs frequently.
9258c2ecf20Sopenharmony_ci */
9268c2ecf20Sopenharmony_cistruct percpu_counter vm_committed_as ____cacheline_aligned_in_smp;
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci/*
9298c2ecf20Sopenharmony_ci * The global memory commitment made in the system can be a metric
9308c2ecf20Sopenharmony_ci * that can be used to drive ballooning decisions when Linux is hosted
9318c2ecf20Sopenharmony_ci * as a guest. On Hyper-V, the host implements a policy engine for dynamically
9328c2ecf20Sopenharmony_ci * balancing memory across competing virtual machines that are hosted.
9338c2ecf20Sopenharmony_ci * Several metrics drive this policy engine including the guest reported
9348c2ecf20Sopenharmony_ci * memory commitment.
9358c2ecf20Sopenharmony_ci *
9368c2ecf20Sopenharmony_ci * The time cost of this is very low for small platforms, and for big
9378c2ecf20Sopenharmony_ci * platform like a 2S/36C/72T Skylake server, in worst case where
9388c2ecf20Sopenharmony_ci * vm_committed_as's spinlock is under severe contention, the time cost
9398c2ecf20Sopenharmony_ci * could be about 30~40 microseconds.
9408c2ecf20Sopenharmony_ci */
9418c2ecf20Sopenharmony_ciunsigned long vm_memory_committed(void)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	return percpu_counter_sum_positive(&vm_committed_as);
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(vm_memory_committed);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci/*
9488c2ecf20Sopenharmony_ci * Check that a process has enough memory to allocate a new virtual
9498c2ecf20Sopenharmony_ci * mapping. 0 means there is enough memory for the allocation to
9508c2ecf20Sopenharmony_ci * succeed and -ENOMEM implies there is not.
9518c2ecf20Sopenharmony_ci *
9528c2ecf20Sopenharmony_ci * We currently support three overcommit policies, which are set via the
9538c2ecf20Sopenharmony_ci * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-accounting.rst
9548c2ecf20Sopenharmony_ci *
9558c2ecf20Sopenharmony_ci * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
9568c2ecf20Sopenharmony_ci * Additional code 2002 Jul 20 by Robert Love.
9578c2ecf20Sopenharmony_ci *
9588c2ecf20Sopenharmony_ci * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise.
9598c2ecf20Sopenharmony_ci *
9608c2ecf20Sopenharmony_ci * Note this is a helper function intended to be used by LSMs which
9618c2ecf20Sopenharmony_ci * wish to use this logic.
9628c2ecf20Sopenharmony_ci */
9638c2ecf20Sopenharmony_ciint __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	long allowed;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	vm_acct_memory(pages);
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	/*
9708c2ecf20Sopenharmony_ci	 * Sometimes we want to use more memory than we have
9718c2ecf20Sopenharmony_ci	 */
9728c2ecf20Sopenharmony_ci	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
9738c2ecf20Sopenharmony_ci		return 0;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
9768c2ecf20Sopenharmony_ci		if (pages > totalram_pages() + total_swap_pages)
9778c2ecf20Sopenharmony_ci			goto error;
9788c2ecf20Sopenharmony_ci		return 0;
9798c2ecf20Sopenharmony_ci	}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	allowed = vm_commit_limit();
9828c2ecf20Sopenharmony_ci	/*
9838c2ecf20Sopenharmony_ci	 * Reserve some for root
9848c2ecf20Sopenharmony_ci	 */
9858c2ecf20Sopenharmony_ci	if (!cap_sys_admin)
9868c2ecf20Sopenharmony_ci		allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	/*
9898c2ecf20Sopenharmony_ci	 * Don't let a single process grow so big a user can't recover
9908c2ecf20Sopenharmony_ci	 */
9918c2ecf20Sopenharmony_ci	if (mm) {
9928c2ecf20Sopenharmony_ci		long reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci		allowed -= min_t(long, mm->total_vm / 32, reserve);
9958c2ecf20Sopenharmony_ci	}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	if (percpu_counter_read_positive(&vm_committed_as) < allowed)
9988c2ecf20Sopenharmony_ci		return 0;
9998c2ecf20Sopenharmony_cierror:
10008c2ecf20Sopenharmony_ci	vm_unacct_memory(pages);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	return -ENOMEM;
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci/**
10068c2ecf20Sopenharmony_ci * get_cmdline() - copy the cmdline value to a buffer.
10078c2ecf20Sopenharmony_ci * @task:     the task whose cmdline value to copy.
10088c2ecf20Sopenharmony_ci * @buffer:   the buffer to copy to.
10098c2ecf20Sopenharmony_ci * @buflen:   the length of the buffer. Larger cmdline values are truncated
10108c2ecf20Sopenharmony_ci *            to this length.
10118c2ecf20Sopenharmony_ci *
10128c2ecf20Sopenharmony_ci * Return: the size of the cmdline field copied. Note that the copy does
10138c2ecf20Sopenharmony_ci * not guarantee an ending NULL byte.
10148c2ecf20Sopenharmony_ci */
10158c2ecf20Sopenharmony_ciint get_cmdline(struct task_struct *task, char *buffer, int buflen)
10168c2ecf20Sopenharmony_ci{
10178c2ecf20Sopenharmony_ci	int res = 0;
10188c2ecf20Sopenharmony_ci	unsigned int len;
10198c2ecf20Sopenharmony_ci	struct mm_struct *mm = get_task_mm(task);
10208c2ecf20Sopenharmony_ci	unsigned long arg_start, arg_end, env_start, env_end;
10218c2ecf20Sopenharmony_ci	if (!mm)
10228c2ecf20Sopenharmony_ci		goto out;
10238c2ecf20Sopenharmony_ci	if (!mm->arg_end)
10248c2ecf20Sopenharmony_ci		goto out_mm;	/* Shh! No looking before we're done */
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	spin_lock(&mm->arg_lock);
10278c2ecf20Sopenharmony_ci	arg_start = mm->arg_start;
10288c2ecf20Sopenharmony_ci	arg_end = mm->arg_end;
10298c2ecf20Sopenharmony_ci	env_start = mm->env_start;
10308c2ecf20Sopenharmony_ci	env_end = mm->env_end;
10318c2ecf20Sopenharmony_ci	spin_unlock(&mm->arg_lock);
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	len = arg_end - arg_start;
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	if (len > buflen)
10368c2ecf20Sopenharmony_ci		len = buflen;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	res = access_process_vm(task, arg_start, buffer, len, FOLL_FORCE);
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	/*
10418c2ecf20Sopenharmony_ci	 * If the nul at the end of args has been overwritten, then
10428c2ecf20Sopenharmony_ci	 * assume application is using setproctitle(3).
10438c2ecf20Sopenharmony_ci	 */
10448c2ecf20Sopenharmony_ci	if (res > 0 && buffer[res-1] != '\0' && len < buflen) {
10458c2ecf20Sopenharmony_ci		len = strnlen(buffer, res);
10468c2ecf20Sopenharmony_ci		if (len < res) {
10478c2ecf20Sopenharmony_ci			res = len;
10488c2ecf20Sopenharmony_ci		} else {
10498c2ecf20Sopenharmony_ci			len = env_end - env_start;
10508c2ecf20Sopenharmony_ci			if (len > buflen - res)
10518c2ecf20Sopenharmony_ci				len = buflen - res;
10528c2ecf20Sopenharmony_ci			res += access_process_vm(task, env_start,
10538c2ecf20Sopenharmony_ci						 buffer+res, len,
10548c2ecf20Sopenharmony_ci						 FOLL_FORCE);
10558c2ecf20Sopenharmony_ci			res = strnlen(buffer, res);
10568c2ecf20Sopenharmony_ci		}
10578c2ecf20Sopenharmony_ci	}
10588c2ecf20Sopenharmony_ciout_mm:
10598c2ecf20Sopenharmony_ci	mmput(mm);
10608c2ecf20Sopenharmony_ciout:
10618c2ecf20Sopenharmony_ci	return res;
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ciint __weak memcmp_pages(struct page *page1, struct page *page2)
10658c2ecf20Sopenharmony_ci{
10668c2ecf20Sopenharmony_ci	char *addr1, *addr2;
10678c2ecf20Sopenharmony_ci	int ret;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	addr1 = kmap_atomic(page1);
10708c2ecf20Sopenharmony_ci	addr2 = kmap_atomic(page2);
10718c2ecf20Sopenharmony_ci	ret = memcmp(addr1, addr2, PAGE_SIZE);
10728c2ecf20Sopenharmony_ci	kunmap_atomic(addr2);
10738c2ecf20Sopenharmony_ci	kunmap_atomic(addr1);
10748c2ecf20Sopenharmony_ci	return ret;
10758c2ecf20Sopenharmony_ci}
1076