vm: add max_map_count isolate switch

Add the max_map_count isolation switch kernel.isolate_max_map_count;
The isolation of max_map_count is turned on by default. If you want
to turn it off, set kernel.isolate_max_map_count to 0;

Signed-off-by: Zhiguang Peng <zgpeng@tencent.com>
This commit is contained in:
zgpeng 2020-03-06 19:05:44 +08:00 committed by Xiaoming Gao
parent 1a0eb15adc
commit f2ba303dbd
8 changed files with 40 additions and 10 deletions

View File

@ -115,6 +115,7 @@ extern int mmap_rnd_compat_bits __read_mostly;
#define DEFAULT_MAX_MAP_COUNT (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
extern int sysctl_max_map_count;
extern int max_map_count_isolated;
extern unsigned long sysctl_user_reserve_kbytes;
extern unsigned long sysctl_admin_reserve_kbytes;

View File

@ -137,7 +137,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
ns->user_ns = get_user_ns(user_ns);
ns->ucounts = ucounts;
ns->nr_hashed = PIDNS_HASH_ADDING;
ns->max_map_count = parent_pid_ns->max_map_count;
ns->max_map_count = max_map_count_isolated ?
parent_pid_ns->max_map_count : sysctl_max_map_count;
INIT_WORK(&ns->proc_work, proc_cleanup_work);
set_bit(0, ns->pidmap[0].page);

View File

@ -343,6 +343,15 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "isolate_max_map_count",
.data = &max_map_count_isolated,
.maxlen = sizeof(max_map_count_isolated),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &one,
},
#endif
{
.procname = "print-fatal-signals-src-dst",
@ -2693,7 +2702,8 @@ static int proc_dointvec_max_map_count(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
#ifdef CONFIG_PID_NS
table->data = &task_active_pid_ns(current)->max_map_count;
table->data = max_map_count_isolated ?
&task_active_pid_ns(current)->max_map_count : &sysctl_max_map_count;
#endif
return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
}

View File

@ -148,7 +148,9 @@ static long madvise_behavior(struct vm_area_struct *vma,
if (start != vma->vm_start) {
#ifdef CONFIG_PID_NS
if (unlikely(mm->map_count >= task_active_pid_ns(current)->max_map_count))
if (unlikely(mm->map_count >= (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count)))
#else
if (unlikely(mm->map_count >= sysctl_max_map_count))
#endif
@ -170,7 +172,9 @@ static long madvise_behavior(struct vm_area_struct *vma,
if (end != vma->vm_end) {
#ifdef CONFIG_PID_NS
if (unlikely(mm->map_count >= task_active_pid_ns(current)->max_map_count))
if (unlikely(mm->map_count >= (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count)))
#else
if (unlikely(mm->map_count >= sysctl_max_map_count))
#endif

View File

@ -1385,7 +1385,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
/* Too many mappings? */
#ifdef CONFIG_PID_NS
if (mm->map_count > task_active_pid_ns(current)->max_map_count)
if (mm->map_count > (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count))
#else
if (mm->map_count > sysctl_max_map_count)
#endif
@ -2642,7 +2644,9 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long addr, int new_below)
{
#ifdef CONFIG_PID_NS
if (mm->map_count >= task_active_pid_ns(current)->max_map_count)
if (mm->map_count >= (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count))
#else
if (mm->map_count >= sysctl_max_map_count)
#endif
@ -2697,7 +2701,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
* its limit temporarily, to help free resources as expected.
*/
#ifdef CONFIG_PID_NS
if (end < vma->vm_end && mm->map_count >= task_active_pid_ns(current)->max_map_count)
if (end < vma->vm_end && mm->map_count >=
(max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count))
#else
if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count)
#endif
@ -2939,7 +2946,9 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla
return -ENOMEM;
#ifdef CONFIG_PID_NS
if (mm->map_count > task_active_pid_ns(current)->max_map_count)
if (mm->map_count > (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count))
#else
if (mm->map_count > sysctl_max_map_count)
#endif

View File

@ -278,7 +278,9 @@ static unsigned long move_vma(struct vm_area_struct *vma,
* which may split one vma into three before unmapping.
*/
#ifdef CONFIG_PID_NS
if (mm->map_count >= task_active_pid_ns(current)->max_map_count - 3)
if (mm->map_count >= (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count) - 3)
#else
if (mm->map_count >= sysctl_max_map_count - 3)
#endif

View File

@ -1488,7 +1488,9 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
return -ENOMEM;
#ifdef CONFIG_PID_NS
if (mm->map_count >= task_active_pid_ns(current)->max_map_count)
if (mm->map_count >= (max_map_count_isolated ?
task_active_pid_ns(current)->max_map_count :
sysctl_max_map_count))
#else
if (mm->map_count >= sysctl_max_map_count)
#endif

View File

@ -516,6 +516,7 @@ EXPORT_SYMBOL_GPL(__page_mapcount);
int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS;
int sysctl_overcommit_ratio __read_mostly = 50;
unsigned long sysctl_overcommit_kbytes __read_mostly;
int max_map_count_isolated = 1;
int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
unsigned long sysctl_user_reserve_kbytes __read_mostly = 1UL << 17; /* 128MB */
unsigned long sysctl_admin_reserve_kbytes __read_mostly = 1UL << 13; /* 8MB */