aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h3
-rw-r--r--include/uapi/linux/prctl.h3
-rw-r--r--kernel/fork.c11
-rw-r--r--kernel/sys.c15
4 files changed, 29 insertions, 3 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 35300f390eb6..c270fa68a32b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -177,6 +177,9 @@ extern unsigned int kobjsize(const void *objp);
177 */ 177 */
178#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP) 178#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP)
179 179
180/* This mask defines which mm->def_flags a process can inherit its parent */
181#define VM_INIT_DEF_MASK VM_NOHUGEPAGE
182
180/* 183/*
181 * mapping from the currently active vm_flags protection bits (the 184 * mapping from the currently active vm_flags protection bits (the
182 * low four bits) to a page protection mask.. 185 * low four bits) to a page protection mask..
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 289760f424aa..58afc04c107e 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -149,4 +149,7 @@
149 149
150#define PR_GET_TID_ADDRESS 40 150#define PR_GET_TID_ADDRESS 40
151 151
152#define PR_SET_THP_DISABLE 41
153#define PR_GET_THP_DISABLE 42
154
152#endif /* _LINUX_PRCTL_H */ 155#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/fork.c b/kernel/fork.c
index abc45890f0a5..e40c0a01d5a6 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -530,8 +530,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
530 atomic_set(&mm->mm_count, 1); 530 atomic_set(&mm->mm_count, 1);
531 init_rwsem(&mm->mmap_sem); 531 init_rwsem(&mm->mmap_sem);
532 INIT_LIST_HEAD(&mm->mmlist); 532 INIT_LIST_HEAD(&mm->mmlist);
533 mm->flags = (current->mm) ?
534 (current->mm->flags & MMF_INIT_MASK) : default_dump_filter;
535 mm->core_state = NULL; 533 mm->core_state = NULL;
536 atomic_long_set(&mm->nr_ptes, 0); 534 atomic_long_set(&mm->nr_ptes, 0);
537 memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); 535 memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
@@ -540,8 +538,15 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
540 mm_init_owner(mm, p); 538 mm_init_owner(mm, p);
541 clear_tlb_flush_pending(mm); 539 clear_tlb_flush_pending(mm);
542 540
543 if (likely(!mm_alloc_pgd(mm))) { 541 if (current->mm) {
542 mm->flags = current->mm->flags & MMF_INIT_MASK;
543 mm->def_flags = current->mm->def_flags & VM_INIT_DEF_MASK;
544 } else {
545 mm->flags = default_dump_filter;
544 mm->def_flags = 0; 546 mm->def_flags = 0;
547 }
548
549 if (likely(!mm_alloc_pgd(mm))) {
545 mmu_notifier_mm_init(mm); 550 mmu_notifier_mm_init(mm);
546 return mm; 551 return mm;
547 } 552 }
diff --git a/kernel/sys.c b/kernel/sys.c
index adaeab6f7a87..fba0f29401ea 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1996,6 +1996,21 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
1996 if (arg2 || arg3 || arg4 || arg5) 1996 if (arg2 || arg3 || arg4 || arg5)
1997 return -EINVAL; 1997 return -EINVAL;
1998 return current->no_new_privs ? 1 : 0; 1998 return current->no_new_privs ? 1 : 0;
1999 case PR_GET_THP_DISABLE:
2000 if (arg2 || arg3 || arg4 || arg5)
2001 return -EINVAL;
2002 error = !!(me->mm->def_flags & VM_NOHUGEPAGE);
2003 break;
2004 case PR_SET_THP_DISABLE:
2005 if (arg3 || arg4 || arg5)
2006 return -EINVAL;
2007 down_write(&me->mm->mmap_sem);
2008 if (arg2)
2009 me->mm->def_flags |= VM_NOHUGEPAGE;
2010 else
2011 me->mm->def_flags &= ~VM_NOHUGEPAGE;
2012 up_write(&me->mm->mmap_sem);
2013 break;
1999 default: 2014 default:
2000 error = -EINVAL; 2015 error = -EINVAL;
2001 break; 2016 break;