mm/ksm: fix ksm exec support for prctl
authorJinjiang Tu <tujinjiang@huawei.com>
Thu, 28 Mar 2024 11:10:08 +0000 (19:10 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 26 Apr 2024 03:56:29 +0000 (20:56 -0700)
Patch series "mm/ksm: fix ksm exec support for prctl", v4.

commit 3c6f33b7273a ("mm/ksm: support fork/exec for prctl") inherits
MMF_VM_MERGE_ANY flag when a task calls execve().  However, it doesn't
create the mm_slot, so ksmd will not try to scan this task.  The first
patch fixes the issue.

The second patch refactors to prepare for the third patch.  The third
patch extends the selftests of ksm to verfity the deduplication really
happens after fork/exec inherits ths KSM setting.

This patch (of 3):

commit 3c6f33b7273a ("mm/ksm: support fork/exec for prctl") inherits
MMF_VM_MERGE_ANY flag when a task calls execve().  Howerver, it doesn't
create the mm_slot, so ksmd will not try to scan this task.

To fix it, allocate and add the mm_slot to ksm_mm_head in __bprm_mm_init()
when the mm has MMF_VM_MERGE_ANY flag.

Link: https://lkml.kernel.org/r/20240328111010.1502191-1-tujinjiang@huawei.com
Link: https://lkml.kernel.org/r/20240328111010.1502191-2-tujinjiang@huawei.com
Fixes: 3c6f33b7273a ("mm/ksm: support fork/exec for prctl")
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Cc: Nanyong Sun <sunnanyong@huawei.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Stefan Roesch <shr@devkernel.io>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/exec.c
include/linux/ksm.h

index cf1df7f16e55cc7516236c724bd64f10affe9407..0c5f06d08c355a591f417ed0077b48eed0480836 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -67,6 +67,7 @@
 #include <linux/time_namespace.h>
 #include <linux/user_events.h>
 #include <linux/rseq.h>
+#include <linux/ksm.h>
 
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
@@ -267,6 +268,14 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
                goto err_free;
        }
 
+       /*
+        * Need to be called with mmap write lock
+        * held, to avoid race with ksmd.
+        */
+       err = ksm_execve(mm);
+       if (err)
+               goto err_ksm;
+
        /*
         * Place the stack at the largest stack address the architecture
         * supports. Later, we'll move this to an appropriate place. We don't
@@ -288,6 +297,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
        bprm->p = vma->vm_end - sizeof(void *);
        return 0;
 err:
+       ksm_exit(mm);
+err_ksm:
        mmap_write_unlock(mm);
 err_free:
        bprm->vma = NULL;
index 401348e9f92b4e3b7de61391393d0e08b64cdfb2..7e2b1de3996ac24fd82948e12ccf6a3d96e5923a 100644 (file)
@@ -59,6 +59,14 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
        return 0;
 }
 
+static inline int ksm_execve(struct mm_struct *mm)
+{
+       if (test_bit(MMF_VM_MERGE_ANY, &mm->flags))
+               return __ksm_enter(mm);
+
+       return 0;
+}
+
 static inline void ksm_exit(struct mm_struct *mm)
 {
        if (test_bit(MMF_VM_MERGEABLE, &mm->flags))
@@ -107,6 +115,11 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
        return 0;
 }
 
+static inline int ksm_execve(struct mm_struct *mm)
+{
+       return 0;
+}
+
 static inline void ksm_exit(struct mm_struct *mm)
 {
 }