162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _LINUX_MMAN_H
362306a36Sopenharmony_ci#define _LINUX_MMAN_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/mm.h>
662306a36Sopenharmony_ci#include <linux/percpu_counter.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/atomic.h>
962306a36Sopenharmony_ci#include <uapi/linux/mman.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * Arrange for legacy / undefined architecture specific flags to be
1362306a36Sopenharmony_ci * ignored by mmap handling code.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci#ifndef MAP_32BIT
1662306a36Sopenharmony_ci#define MAP_32BIT 0
1762306a36Sopenharmony_ci#endif
1862306a36Sopenharmony_ci#ifndef MAP_ABOVE4G
1962306a36Sopenharmony_ci#define MAP_ABOVE4G 0
2062306a36Sopenharmony_ci#endif
2162306a36Sopenharmony_ci#ifndef MAP_HUGE_2MB
2262306a36Sopenharmony_ci#define MAP_HUGE_2MB 0
2362306a36Sopenharmony_ci#endif
2462306a36Sopenharmony_ci#ifndef MAP_HUGE_1GB
2562306a36Sopenharmony_ci#define MAP_HUGE_1GB 0
2662306a36Sopenharmony_ci#endif
2762306a36Sopenharmony_ci#ifndef MAP_UNINITIALIZED
2862306a36Sopenharmony_ci#define MAP_UNINITIALIZED 0
2962306a36Sopenharmony_ci#endif
3062306a36Sopenharmony_ci#ifndef MAP_SYNC
3162306a36Sopenharmony_ci#define MAP_SYNC 0
3262306a36Sopenharmony_ci#endif
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/*
3562306a36Sopenharmony_ci * The historical set of flags that all mmap implementations implicitly
3662306a36Sopenharmony_ci * support when a ->mmap_validate() op is not provided in file_operations.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * MAP_EXECUTABLE and MAP_DENYWRITE are completely ignored throughout the
3962306a36Sopenharmony_ci * kernel.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci#define LEGACY_MAP_MASK (MAP_SHARED \
4262306a36Sopenharmony_ci		| MAP_PRIVATE \
4362306a36Sopenharmony_ci		| MAP_FIXED \
4462306a36Sopenharmony_ci		| MAP_ANONYMOUS \
4562306a36Sopenharmony_ci		| MAP_DENYWRITE \
4662306a36Sopenharmony_ci		| MAP_EXECUTABLE \
4762306a36Sopenharmony_ci		| MAP_UNINITIALIZED \
4862306a36Sopenharmony_ci		| MAP_GROWSDOWN \
4962306a36Sopenharmony_ci		| MAP_LOCKED \
5062306a36Sopenharmony_ci		| MAP_NORESERVE \
5162306a36Sopenharmony_ci		| MAP_POPULATE \
5262306a36Sopenharmony_ci		| MAP_NONBLOCK \
5362306a36Sopenharmony_ci		| MAP_STACK \
5462306a36Sopenharmony_ci		| MAP_HUGETLB \
5562306a36Sopenharmony_ci		| MAP_32BIT \
5662306a36Sopenharmony_ci		| MAP_ABOVE4G \
5762306a36Sopenharmony_ci		| MAP_HUGE_2MB \
5862306a36Sopenharmony_ci		| MAP_HUGE_1GB)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ciextern int sysctl_overcommit_memory;
6162306a36Sopenharmony_ciextern int sysctl_overcommit_ratio;
6262306a36Sopenharmony_ciextern unsigned long sysctl_overcommit_kbytes;
6362306a36Sopenharmony_ciextern struct percpu_counter vm_committed_as;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#ifdef CONFIG_SMP
6662306a36Sopenharmony_ciextern s32 vm_committed_as_batch;
6762306a36Sopenharmony_ciextern void mm_compute_batch(int overcommit_policy);
6862306a36Sopenharmony_ci#else
6962306a36Sopenharmony_ci#define vm_committed_as_batch 0
7062306a36Sopenharmony_cistatic inline void mm_compute_batch(int overcommit_policy)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci#endif
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciunsigned long vm_memory_committed(void);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic inline void vm_acct_memory(long pages)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	percpu_counter_add_batch(&vm_committed_as, pages, vm_committed_as_batch);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic inline void vm_unacct_memory(long pages)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	vm_acct_memory(-pages);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/*
8862306a36Sopenharmony_ci * Allow architectures to handle additional protection and flag bits. The
8962306a36Sopenharmony_ci * overriding macros must be defined in the arch-specific asm/mman.h file.
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#ifndef arch_calc_vm_prot_bits
9362306a36Sopenharmony_ci#define arch_calc_vm_prot_bits(prot, pkey) 0
9462306a36Sopenharmony_ci#endif
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#ifndef arch_calc_vm_flag_bits
9762306a36Sopenharmony_ci#define arch_calc_vm_flag_bits(flags) 0
9862306a36Sopenharmony_ci#endif
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#ifndef arch_validate_prot
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * This is called from mprotect().  PROT_GROWSDOWN and PROT_GROWSUP have
10362306a36Sopenharmony_ci * already been masked out.
10462306a36Sopenharmony_ci *
10562306a36Sopenharmony_ci * Returns true if the prot flags are valid
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_cistatic inline bool arch_validate_prot(unsigned long prot, unsigned long addr)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	return (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) == 0;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci#define arch_validate_prot arch_validate_prot
11262306a36Sopenharmony_ci#endif
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#ifndef arch_validate_flags
11562306a36Sopenharmony_ci/*
11662306a36Sopenharmony_ci * This is called from mmap() and mprotect() with the updated vma->vm_flags.
11762306a36Sopenharmony_ci *
11862306a36Sopenharmony_ci * Returns true if the VM_* flags are valid.
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistatic inline bool arch_validate_flags(unsigned long flags)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	return true;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci#define arch_validate_flags arch_validate_flags
12562306a36Sopenharmony_ci#endif
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/*
12862306a36Sopenharmony_ci * Optimisation macro.  It is equivalent to:
12962306a36Sopenharmony_ci *      (x & bit1) ? bit2 : 0
13062306a36Sopenharmony_ci * but this version is faster.
13162306a36Sopenharmony_ci * ("bit1" and "bit2" must be single bits)
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_ci#define _calc_vm_trans(x, bit1, bit2) \
13462306a36Sopenharmony_ci  ((!(bit1) || !(bit2)) ? 0 : \
13562306a36Sopenharmony_ci  ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \
13662306a36Sopenharmony_ci   : ((x) & (bit1)) / ((bit1) / (bit2))))
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/*
13962306a36Sopenharmony_ci * Combine the mmap "prot" argument into "vm_flags" used internally.
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic inline unsigned long
14262306a36Sopenharmony_cicalc_vm_prot_bits(unsigned long prot, unsigned long pkey)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return _calc_vm_trans(prot, PROT_READ,  VM_READ ) |
14562306a36Sopenharmony_ci	       _calc_vm_trans(prot, PROT_WRITE, VM_WRITE) |
14662306a36Sopenharmony_ci	       _calc_vm_trans(prot, PROT_EXEC,  VM_EXEC) |
14762306a36Sopenharmony_ci	       arch_calc_vm_prot_bits(prot, pkey);
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci/*
15162306a36Sopenharmony_ci * Combine the mmap "flags" argument into "vm_flags" used internally.
15262306a36Sopenharmony_ci */
15362306a36Sopenharmony_cistatic inline unsigned long
15462306a36Sopenharmony_cicalc_vm_flag_bits(unsigned long flags)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	return _calc_vm_trans(flags, MAP_GROWSDOWN,  VM_GROWSDOWN ) |
15762306a36Sopenharmony_ci	       _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    ) |
15862306a36Sopenharmony_ci	       _calc_vm_trans(flags, MAP_SYNC,	     VM_SYNC      ) |
15962306a36Sopenharmony_ci	       _calc_vm_trans(flags, MAP_XPM,	     VM_XPM      ) |
16062306a36Sopenharmony_ci	       arch_calc_vm_flag_bits(flags);
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ciunsigned long vm_commit_limit(void);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/*
16662306a36Sopenharmony_ci * Denies creating a writable executable mapping or gaining executable permissions.
16762306a36Sopenharmony_ci *
16862306a36Sopenharmony_ci * This denies the following:
16962306a36Sopenharmony_ci *
17062306a36Sopenharmony_ci * 	a)	mmap(PROT_WRITE | PROT_EXEC)
17162306a36Sopenharmony_ci *
17262306a36Sopenharmony_ci *	b)	mmap(PROT_WRITE)
17362306a36Sopenharmony_ci *		mprotect(PROT_EXEC)
17462306a36Sopenharmony_ci *
17562306a36Sopenharmony_ci *	c)	mmap(PROT_WRITE)
17662306a36Sopenharmony_ci *		mprotect(PROT_READ)
17762306a36Sopenharmony_ci *		mprotect(PROT_EXEC)
17862306a36Sopenharmony_ci *
17962306a36Sopenharmony_ci * But allows the following:
18062306a36Sopenharmony_ci *
18162306a36Sopenharmony_ci *	d)	mmap(PROT_READ | PROT_EXEC)
18262306a36Sopenharmony_ci *		mmap(PROT_READ | PROT_EXEC | PROT_BTI)
18362306a36Sopenharmony_ci */
18462306a36Sopenharmony_cistatic inline bool map_deny_write_exec(struct vm_area_struct *vma,  unsigned long vm_flags)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	if (!test_bit(MMF_HAS_MDWE, &current->mm->flags))
18762306a36Sopenharmony_ci		return false;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	if ((vm_flags & VM_EXEC) && (vm_flags & VM_WRITE))
19062306a36Sopenharmony_ci		return true;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (!(vma->vm_flags & VM_EXEC) && (vm_flags & VM_EXEC))
19362306a36Sopenharmony_ci		return true;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	return false;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci#endif /* _LINUX_MMAN_H */
199