forked from TencentOS/TencentOS-kernel
vm:isolate max_map_count by pid namespace
Signed-off-by: Zhiguang Peng <zgpeng@tencent.com> Signed-off-by: Liu Hua <shookliu@tencent.com>
This commit is contained in:
parent
a9ab22a3dd
commit
ec970f2dff
|
|
@ -53,6 +53,7 @@ struct pid_namespace {
|
|||
int hide_pid;
|
||||
int reboot; /* group exit code if this pidns was rebooted */
|
||||
struct ns_common ns;
|
||||
int max_map_count;
|
||||
} __randomize_layout;
|
||||
|
||||
extern struct pid_namespace init_pid_ns;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/proc_ns.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/sched/sysctl.h>
|
||||
|
||||
#define pid_hashfn(nr, ns) \
|
||||
hash_long((unsigned long)nr + (unsigned long)ns, pidhash_shift)
|
||||
|
|
@ -78,6 +79,7 @@ struct pid_namespace init_pid_ns = {
|
|||
.level = 0,
|
||||
.child_reaper = &init_task,
|
||||
.user_ns = &init_user_ns,
|
||||
.max_map_count = DEFAULT_MAX_MAP_COUNT,
|
||||
.ns.inum = PROC_PID_INIT_INO,
|
||||
#ifdef CONFIG_PID_NS
|
||||
.ns.ops = &pidns_operations,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/sysctl.h>
|
||||
|
||||
struct pid_cache {
|
||||
int nr_ids;
|
||||
|
|
@ -136,6 +137,7 @@ 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 = DEFAULT_MAX_MAP_COUNT;
|
||||
INIT_WORK(&ns->proc_work, proc_cleanup_work);
|
||||
|
||||
set_bit(0, ns->pidmap[0].page);
|
||||
|
|
|
|||
|
|
@ -208,6 +208,9 @@ static int proc_taint(struct ctl_table *table, int write,
|
|||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
#endif
|
||||
|
||||
static int proc_dointvec_max_map_count(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
||||
#ifdef CONFIG_PRINTK
|
||||
static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
|
@ -1509,7 +1512,7 @@ static struct ctl_table vm_table[] = {
|
|||
.data = &sysctl_max_map_count,
|
||||
.maxlen = sizeof(sysctl_max_map_count),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.proc_handler = proc_dointvec_max_map_count,
|
||||
.extra1 = &zero,
|
||||
},
|
||||
#else
|
||||
|
|
@ -2523,6 +2526,15 @@ int proc_douintvec(struct ctl_table *table, int write,
|
|||
do_proc_douintvec_conv, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
#endif
|
||||
return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Taint values can only be increased
|
||||
* This means we can safely use a temporary.
|
||||
|
|
|
|||
14
mm/madvise.c
14
mm/madvise.c
|
|
@ -147,7 +147,12 @@ static long madvise_behavior(struct vm_area_struct *vma,
|
|||
*prev = vma;
|
||||
|
||||
if (start != vma->vm_start) {
|
||||
if (unlikely(mm->map_count >= sysctl_max_map_count)) {
|
||||
#ifdef CONFIG_PID_NS
|
||||
if (unlikely(mm->map_count >= task_active_pid_ns(current)->max_map_count))
|
||||
#else
|
||||
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
||||
#endif
|
||||
{
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -164,7 +169,12 @@ static long madvise_behavior(struct vm_area_struct *vma,
|
|||
}
|
||||
|
||||
if (end != vma->vm_end) {
|
||||
if (unlikely(mm->map_count >= sysctl_max_map_count)) {
|
||||
#ifdef CONFIG_PID_NS
|
||||
if (unlikely(mm->map_count >= task_active_pid_ns(current)->max_map_count))
|
||||
#else
|
||||
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
||||
#endif
|
||||
{
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
16
mm/mmap.c
16
mm/mmap.c
|
|
@ -1384,7 +1384,11 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
|
|||
return -EOVERFLOW;
|
||||
|
||||
/* Too many mappings? */
|
||||
#ifdef CONFIG_PID_NS
|
||||
if (mm->map_count > task_active_pid_ns(current)->max_map_count)
|
||||
#else
|
||||
if (mm->map_count > sysctl_max_map_count)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
/* Obtain the address to map to. we verify (or select) it and ensure
|
||||
|
|
@ -2637,7 +2641,11 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
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)
|
||||
#else
|
||||
if (mm->map_count >= sysctl_max_map_count)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
return __split_vma(mm, vma, addr, new_below);
|
||||
|
|
@ -2688,7 +2696,11 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
|
|||
* not exceed its limit; but let map_count go just above
|
||||
* 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)
|
||||
#else
|
||||
if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
error = __split_vma(mm, vma, start, 0);
|
||||
|
|
@ -2926,7 +2938,11 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla
|
|||
if (!may_expand_vm(mm, flags, len >> PAGE_SHIFT))
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_PID_NS
|
||||
if (mm->map_count > task_active_pid_ns(current)->max_map_count)
|
||||
#else
|
||||
if (mm->map_count > sysctl_max_map_count)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
if (security_vm_enough_memory_mm(mm, len >> PAGE_SHIFT))
|
||||
|
|
|
|||
|
|
@ -277,7 +277,11 @@ static unsigned long move_vma(struct vm_area_struct *vma,
|
|||
* We'd prefer to avoid failure later on in do_munmap:
|
||||
* 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)
|
||||
#else
|
||||
if (mm->map_count >= sysctl_max_map_count - 3)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1487,7 +1487,11 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
if (vma->vm_file)
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_PID_NS
|
||||
if (mm->map_count >= task_active_pid_ns(current)->max_map_count)
|
||||
#else
|
||||
if (mm->map_count >= sysctl_max_map_count)
|
||||
#endif
|
||||
return -ENOMEM;
|
||||
|
||||
region = kmem_cache_alloc(vm_region_jar, GFP_KERNEL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue