]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm, madvise: extract mm code from prctl_set_vma() to mm/madvise.c
authorVlastimil Babka <vbabka@suse.cz>
Tue, 24 Jun 2025 13:03:46 +0000 (15:03 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 13 Jul 2025 23:38:13 +0000 (16:38 -0700)
Setting anon_name is done via madvise_set_anon_name() and behaves a lot of
like other madvise operations.  However, apparently because madvise() has
lacked the 4th argument and prctl() not, the userspace entry point has
been implemented via prctl(PR_SET_VMA, ...) and handled first by
prctl_set_vma().

Currently prctl_set_vma() lives in kernel/sys.c but setting the
vma->anon_name is mm-specific code so extract it to a new
set_anon_vma_name() function under mm.  mm/madvise.c seems to be the most
straightforward place as that's where madvise_set_anon_name() lives.  Stop
declaring the latter in mm.h and instead declare set_anon_vma_name().

Link: https://lkml.kernel.org/r/20250624-anon_name_cleanup-v2-2-600075462a11@suse.cz
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: David Hildenbrand <david@redhat.com>
Tested-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Colin Cross <ccross@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/mm.h
kernel/sys.c
mm/madvise.c

index 0e0549f3d681f6c7a78e8dfa341a810e5a8f96c1..ef40f68c1183d4c95016575a4ee0171e12df9ba4 100644 (file)
@@ -4059,14 +4059,14 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping,
 #endif
 
 #ifdef CONFIG_ANON_VMA_NAME
-int madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
-                         unsigned long len_in,
-                         struct anon_vma_name *anon_name);
+int set_anon_vma_name(unsigned long addr, unsigned long size,
+                     const char __user *uname);
 #else
-static inline int
-madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
-                     unsigned long len_in, struct anon_vma_name *anon_name) {
-       return 0;
+static inline
+int set_anon_vma_name(unsigned long addr, unsigned long size,
+                     const char __user *uname)
+{
+       return -EINVAL;
 }
 #endif
 
index adc0de0aa364aebb23999f621717a5d32599921c..b153fb345ada28ea1a33386a32bcce9cb1b23475 100644 (file)
@@ -2343,54 +2343,14 @@ int __weak arch_lock_shadow_stack_status(struct task_struct *t, unsigned long st
 
 #define PR_IO_FLUSHER (PF_MEMALLOC_NOIO | PF_LOCAL_THROTTLE)
 
-#ifdef CONFIG_ANON_VMA_NAME
-
-#define ANON_VMA_NAME_MAX_LEN          80
-#define ANON_VMA_NAME_INVALID_CHARS    "\\`$[]"
-
-static inline bool is_valid_name_char(char ch)
-{
-       /* printable ascii characters, excluding ANON_VMA_NAME_INVALID_CHARS */
-       return ch > 0x1f && ch < 0x7f &&
-               !strchr(ANON_VMA_NAME_INVALID_CHARS, ch);
-}
-
 static int prctl_set_vma(unsigned long opt, unsigned long addr,
                         unsigned long size, unsigned long arg)
 {
-       struct mm_struct *mm = current->mm;
-       const char __user *uname;
-       struct anon_vma_name *anon_name = NULL;
        int error;
 
        switch (opt) {
        case PR_SET_VMA_ANON_NAME:
-               uname = (const char __user *)arg;
-               if (uname) {
-                       char *name, *pch;
-
-                       name = strndup_user(uname, ANON_VMA_NAME_MAX_LEN);
-                       if (IS_ERR(name))
-                               return PTR_ERR(name);
-
-                       for (pch = name; *pch != '\0'; pch++) {
-                               if (!is_valid_name_char(*pch)) {
-                                       kfree(name);
-                                       return -EINVAL;
-                               }
-                       }
-                       /* anon_vma has its own copy */
-                       anon_name = anon_vma_name_alloc(name);
-                       kfree(name);
-                       if (!anon_name)
-                               return -ENOMEM;
-
-               }
-
-               mmap_write_lock(mm);
-               error = madvise_set_anon_name(mm, addr, size, anon_name);
-               mmap_write_unlock(mm);
-               anon_vma_name_put(anon_name);
+               error = set_anon_vma_name(addr, size, (const char __user *)arg);
                break;
        default:
                error = -EINVAL;
@@ -2399,14 +2359,6 @@ static int prctl_set_vma(unsigned long opt, unsigned long addr,
        return error;
 }
 
-#else /* CONFIG_ANON_VMA_NAME */
-static int prctl_set_vma(unsigned long opt, unsigned long start,
-                        unsigned long size, unsigned long arg)
-{
-       return -EINVAL;
-}
-#endif /* CONFIG_ANON_VMA_NAME */
-
 static inline unsigned long get_current_mdwe(void)
 {
        unsigned long ret = 0;
index 0ca405017b37623e055b3079689a754ea9501b82..a2294bc1cc7bde965d49fde9f27e9a69936b9987 100644 (file)
@@ -134,8 +134,8 @@ static int replace_anon_vma_name(struct vm_area_struct *vma,
        return 0;
 }
 
-int madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
-                         unsigned long len_in, struct anon_vma_name *anon_name)
+static int madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
+               unsigned long len_in, struct anon_vma_name *anon_name)
 {
        unsigned long end;
        unsigned long len;
@@ -2096,3 +2096,51 @@ free_iov:
 out:
        return ret;
 }
+
+#ifdef CONFIG_ANON_VMA_NAME
+
+#define ANON_VMA_NAME_MAX_LEN          80
+#define ANON_VMA_NAME_INVALID_CHARS    "\\`$[]"
+
+static inline bool is_valid_name_char(char ch)
+{
+       /* printable ascii characters, excluding ANON_VMA_NAME_INVALID_CHARS */
+       return ch > 0x1f && ch < 0x7f &&
+               !strchr(ANON_VMA_NAME_INVALID_CHARS, ch);
+}
+
+int set_anon_vma_name(unsigned long addr, unsigned long size,
+                     const char __user *uname)
+{
+       struct anon_vma_name *anon_name = NULL;
+       struct mm_struct *mm = current->mm;
+       int error;
+
+       if (uname) {
+               char *name, *pch;
+
+               name = strndup_user(uname, ANON_VMA_NAME_MAX_LEN);
+               if (IS_ERR(name))
+                       return PTR_ERR(name);
+
+               for (pch = name; *pch != '\0'; pch++) {
+                       if (!is_valid_name_char(*pch)) {
+                               kfree(name);
+                               return -EINVAL;
+                       }
+               }
+               /* anon_vma has its own copy */
+               anon_name = anon_vma_name_alloc(name);
+               kfree(name);
+               if (!anon_name)
+                       return -ENOMEM;
+       }
+
+       mmap_write_lock(mm);
+       error = madvise_set_anon_name(mm, addr, size, anon_name);
+       mmap_write_unlock(mm);
+       anon_vma_name_put(anon_name);
+
+       return error;
+}
+#endif