From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98926221736 for ; Fri, 4 Jul 2025 06:07:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609255; cv=none; b=MgM0Xnot3O8x6Nq59JND/lSskKGx6vs2pcdXyj7SSnGCQXmHxDA927XowgrGawpH4N6KGqqeKqD2DYI6vj+5bqoqvfa4P7YDZFjIYh7Gi8WhRy5367JlGkq8xOYo3q7M8R/mEkwNuEVW+I72YKh4SpIT9udrHfyAMg2YF7/Z76U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609255; c=relaxed/simple; bh=jRnrVoMZdZS4l+fMWfTBazH3LP8URmBuww3v7sYZO+k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pZ0qTZT6/w4CTYKNQnzk/wDoMnky9SVEeTSTChbknVLCXvZOcY6CrXjYaLa9+qY+5udDnGKRcHVLkCfp5u+wsnY2smcq5jrO4AuU0q9ri8U2Kv0gB5CoDgcEm6M/Wm9TgI//YxlLMzYSfikJH72xxPPnaJncB9UUfPExfqNCWAc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=mlMCISks; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mlMCISks" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b3635eca369so789887a12.0 for ; Thu, 03 Jul 2025 23:07:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609253; x=1752214053; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=w/p/DdbsN4UfikZMzfuS86WplKsUwY/RIZs4YxJfzTQ=; b=mlMCISksXbms6LMHAiXuPK4eHCFTBPqkbt0cZMr1v6jUXS852Re4sZDbpe+dLjZNPK ldWwStMsB01nzqfovLon/OxRcw33TQFXIg3j7j1oS5h+FAE587FuavQufkmV+5v1Pe0D 3PoSfAmQY8gAhzHBZ9wWvc7ln96ROisGjkSRvNRGnmkLeLKQgw6O5v18NpTi+1mJp4P+ 7pq70aUHAmmwz/cc7/4hRHmSQksguWvXaryvvWsUPjoNAbeMBwUzD72oPrVSkKVSJXUG ZVXQM8VsJAOgfS7JWKaK4nYPLX60+V7UheD9rxPcclKiJTEtAJt8yWrF+ZQM8+rk7/vs TNXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609253; x=1752214053; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=w/p/DdbsN4UfikZMzfuS86WplKsUwY/RIZs4YxJfzTQ=; b=vElseu2yPp8oFvEdSTYOJ1PqWeHG9lx3cbL5AN5k0tOM4OlDE16L7dESKT+eYQVCa5 ILmYoRsocUQvLru9WlszrrpoiGiS6NJeNSqWp8sGJUqa188aQWk4RU4E4uxvAJbKXWjQ O0gDQk8qZmw6npFiLGgFSE9cMjHFdGBoudgPjWKtt3sNfS+7yYilkS7edn0O1Qcflx2P TfrvRVnIqn4a7AFSSILFAVr6sNKlzsBpma77PpcsYXcQHhIytAbHCt/UEsSjqsVBM82S 6Y8944TTdrhnSXh3yZydpLVdfj4KH7KOzer++XrJC2bc8c0c2IXwJq1wWZYpYfId+nzZ qIYA== X-Forwarded-Encrypted: i=1; AJvYcCVC7CqBBa+Aprm682YKqwtKHsVQh3/g2Qi5e/8hKlfzRRBfDqJhlh5NQr1FTaoMSdaqg8WPgREPK5ZEwXY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx9o2sRy9qFmSHR37F2wpId1eGezoSEeQYRxfZmy5P5zVFCM6qE LJ6p3LyRDD41lK57ZcCy+WyugztGChsfPl8f8dyzl5HJLPeSK00ukMLtm+n0Smsr1PaNdHbcCXJ iCw3KRg== X-Google-Smtp-Source: AGHT+IGe4kvFdpfc/Mpb408KRqsGgEcfVEZiF0gAMPeVKlU4LDHWMtl8j9Q2SZhpvBnNf3nLr5wLPwhVxXI= X-Received: from pgcv5.prod.google.com ([2002:a05:6a02:5305:b0:b2d:249f:ea07]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:10c:b0:222:d63a:249d with SMTP id adf61e73a8af0-225c01dd60fmr2355744637.20.1751609252909; Thu, 03 Jul 2025 23:07:32 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:19 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-2-surenb@google.com> Subject: [PATCH v6 1/8] selftests/proc: add /proc/pid/maps tearing from vma split test From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The /proc/pid/maps file is generated page by page, with the mmap_lock released between pages. This can lead to inconsistent reads if the underlying vmas are concurrently modified. For instance, if a vma split or merge occurs at a page boundary while /proc/pid/maps is being read, the same vma might be seen twice: once before and once after the change. This duplication is considered acceptable for userspace handling. However, observing a "hole" where a vma should be (e.g., due to a vma being replaced and the space temporarily being empty) is unacceptable. Implement a test that: 1. Forks a child process which continuously modifies its address space, specifically targeting a vma at the boundary between two pages. 2. The parent process repeatedly reads the child's /proc/pid/maps. 3. The parent process checks the last vma of the first page and the first vma of the second page for consistency, looking for the effects of vma splits or merges. The test duration is configurable via the -d command-line parameter in seconds to increase the likelihood of catching the race condition. The default test duration is 5 seconds. Example Command: proc-maps-race -d 10 Signed-off-by: Suren Baghdasaryan --- tools/testing/selftests/proc/.gitignore | 1 + tools/testing/selftests/proc/Makefile | 1 + tools/testing/selftests/proc/proc-maps-race.c | 459 ++++++++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 tools/testing/selftests/proc/proc-maps-race.c diff --git a/tools/testing/selftests/proc/.gitignore b/tools/testing/selfte= sts/proc/.gitignore index 973968f45bba..19bb333e2485 100644 --- a/tools/testing/selftests/proc/.gitignore +++ b/tools/testing/selftests/proc/.gitignore @@ -5,6 +5,7 @@ /proc-2-is-kthread /proc-fsconfig-hidepid /proc-loadavg-001 +/proc-maps-race /proc-multiple-procfs /proc-empty-vm /proc-pid-vm diff --git a/tools/testing/selftests/proc/Makefile b/tools/testing/selftest= s/proc/Makefile index b12921b9794b..50aba102201a 100644 --- a/tools/testing/selftests/proc/Makefile +++ b/tools/testing/selftests/proc/Makefile @@ -9,6 +9,7 @@ TEST_GEN_PROGS +=3D fd-002-posix-eq TEST_GEN_PROGS +=3D fd-003-kthread TEST_GEN_PROGS +=3D proc-2-is-kthread TEST_GEN_PROGS +=3D proc-loadavg-001 +TEST_GEN_PROGS +=3D proc-maps-race TEST_GEN_PROGS +=3D proc-empty-vm TEST_GEN_PROGS +=3D proc-pid-vm TEST_GEN_PROGS +=3D proc-self-map-files-001 diff --git a/tools/testing/selftests/proc/proc-maps-race.c b/tools/testing/= selftests/proc/proc-maps-race.c new file mode 100644 index 000000000000..523afd83d34f --- /dev/null +++ b/tools/testing/selftests/proc/proc-maps-race.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2025 Suren Baghdasaryan + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Fork a child that concurrently modifies address space while the main + * process is reading /proc/$PID/maps and verifying the results. Address + * space modifications include: + * VMA splitting and merging + * + */ +#undef NDEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long test_duration_sec =3D 5UL; +static int page_size; + +/* /proc/pid/maps parsing routines */ +struct page_content { + char *data; + ssize_t size; +}; + +#define LINE_MAX_SIZE 256 + +struct line_content { + char text[LINE_MAX_SIZE]; + unsigned long start_addr; + unsigned long end_addr; +}; + +static void read_two_pages(int maps_fd, struct page_content *page1, + struct page_content *page2) +{ + ssize_t bytes_read; + + assert(lseek(maps_fd, 0, SEEK_SET) >=3D 0); + bytes_read =3D read(maps_fd, page1->data, page_size); + assert(bytes_read > 0 && bytes_read < page_size); + page1->size =3D bytes_read; + + bytes_read =3D read(maps_fd, page2->data, page_size); + assert(bytes_read > 0 && bytes_read < page_size); + page2->size =3D bytes_read; +} + +static void copy_first_line(struct page_content *page, char *first_line) +{ + char *pos =3D strchr(page->data, '\n'); + + strncpy(first_line, page->data, pos - page->data); + first_line[pos - page->data] =3D '\0'; +} + +static void copy_last_line(struct page_content *page, char *last_line) +{ + /* Get the last line in the first page */ + const char *end =3D page->data + page->size - 1; + /* skip last newline */ + const char *pos =3D end - 1; + + /* search previous newline */ + while (pos[-1] !=3D '\n') + pos--; + strncpy(last_line, pos, end - pos); + last_line[end - pos] =3D '\0'; +} + +/* Read the last line of the first page and the first line of the second p= age */ +static void read_boundary_lines(int maps_fd, struct page_content *page1, + struct page_content *page2, + struct line_content *last_line, + struct line_content *first_line) +{ + read_two_pages(maps_fd, page1, page2); + + copy_last_line(page1, last_line->text); + copy_first_line(page2, first_line->text); + + assert(sscanf(last_line->text, "%lx-%lx", &last_line->start_addr, + &last_line->end_addr) =3D=3D 2); + assert(sscanf(first_line->text, "%lx-%lx", &first_line->start_addr, + &first_line->end_addr) =3D=3D 2); +} + +/* Thread synchronization routines */ +enum test_state { + INIT, + CHILD_READY, + PARENT_READY, + SETUP_READY, + SETUP_MODIFY_MAPS, + SETUP_MAPS_MODIFIED, + SETUP_RESTORE_MAPS, + SETUP_MAPS_RESTORED, + TEST_READY, + TEST_DONE, +}; + +struct vma_modifier_info; + +typedef void (*vma_modifier_op)(const struct vma_modifier_info *mod_info); +typedef void (*vma_mod_result_check_op)(struct line_content *mod_last_line, + struct line_content *mod_first_line, + struct line_content *restored_last_line, + struct line_content *restored_first_line); + +struct vma_modifier_info { + int vma_count; + void *addr; + int prot; + void *next_addr; + vma_modifier_op vma_modify; + vma_modifier_op vma_restore; + vma_mod_result_check_op vma_mod_check; + pthread_mutex_t sync_lock; + pthread_cond_t sync_cond; + enum test_state curr_state; + bool exit; + void *child_mapped_addr[]; +}; + +static void wait_for_state(struct vma_modifier_info *mod_info, enum test_s= tate state) +{ + pthread_mutex_lock(&mod_info->sync_lock); + while (mod_info->curr_state !=3D state) + pthread_cond_wait(&mod_info->sync_cond, &mod_info->sync_lock); + pthread_mutex_unlock(&mod_info->sync_lock); +} + +static void signal_state(struct vma_modifier_info *mod_info, enum test_sta= te state) +{ + pthread_mutex_lock(&mod_info->sync_lock); + mod_info->curr_state =3D state; + pthread_cond_signal(&mod_info->sync_cond); + pthread_mutex_unlock(&mod_info->sync_lock); +} + +/* VMA modification routines */ +static void *child_vma_modifier(struct vma_modifier_info *mod_info) +{ + int prot =3D PROT_READ | PROT_WRITE; + int i; + + for (i =3D 0; i < mod_info->vma_count; i++) { + mod_info->child_mapped_addr[i] =3D mmap(NULL, page_size * 3, prot, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(mod_info->child_mapped_addr[i] !=3D MAP_FAILED); + /* change protection in adjacent maps to prevent merging */ + prot ^=3D PROT_WRITE; + } + signal_state(mod_info, CHILD_READY); + wait_for_state(mod_info, PARENT_READY); + while (true) { + signal_state(mod_info, SETUP_READY); + wait_for_state(mod_info, SETUP_MODIFY_MAPS); + if (mod_info->exit) + break; + + mod_info->vma_modify(mod_info); + signal_state(mod_info, SETUP_MAPS_MODIFIED); + wait_for_state(mod_info, SETUP_RESTORE_MAPS); + mod_info->vma_restore(mod_info); + signal_state(mod_info, SETUP_MAPS_RESTORED); + + wait_for_state(mod_info, TEST_READY); + while (mod_info->curr_state !=3D TEST_DONE) { + mod_info->vma_modify(mod_info); + mod_info->vma_restore(mod_info); + } + } + for (i =3D 0; i < mod_info->vma_count; i++) + munmap(mod_info->child_mapped_addr[i], page_size * 3); + + return NULL; +} + +static void stop_vma_modifier(struct vma_modifier_info *mod_info) +{ + wait_for_state(mod_info, SETUP_READY); + mod_info->exit =3D true; + signal_state(mod_info, SETUP_MODIFY_MAPS); +} + +static void capture_mod_pattern(int maps_fd, + struct vma_modifier_info *mod_info, + struct page_content *page1, + struct page_content *page2, + struct line_content *last_line, + struct line_content *first_line, + struct line_content *mod_last_line, + struct line_content *mod_first_line, + struct line_content *restored_last_line, + struct line_content *restored_first_line) +{ + signal_state(mod_info, SETUP_MODIFY_MAPS); + wait_for_state(mod_info, SETUP_MAPS_MODIFIED); + + /* Copy last line of the first page and first line of the last page */ + read_boundary_lines(maps_fd, page1, page2, mod_last_line, mod_first_line); + + signal_state(mod_info, SETUP_RESTORE_MAPS); + wait_for_state(mod_info, SETUP_MAPS_RESTORED); + + /* Copy last line of the first page and first line of the last page */ + read_boundary_lines(maps_fd, page1, page2, restored_last_line, restored_f= irst_line); + + mod_info->vma_mod_check(mod_last_line, mod_first_line, + restored_last_line, restored_first_line); + + /* + * The content of these lines after modify+resore should be the same + * as the original. + */ + assert(strcmp(restored_last_line->text, last_line->text) =3D=3D 0); + assert(strcmp(restored_first_line->text, first_line->text) =3D=3D 0); +} + +static inline void split_vma(const struct vma_modifier_info *mod_info) +{ + assert(mmap(mod_info->addr, page_size, mod_info->prot | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0) !=3D MAP_FAILED); +} + +static inline void merge_vma(const struct vma_modifier_info *mod_info) +{ + assert(mmap(mod_info->addr, page_size, mod_info->prot, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0) !=3D MAP_FAILED); +} + +static inline void check_split_result(struct line_content *mod_last_line, + struct line_content *mod_first_line, + struct line_content *restored_last_line, + struct line_content *restored_first_line) +{ + /* Make sure vmas at the boundaries are changing */ + assert(strcmp(mod_last_line->text, restored_last_line->text) !=3D 0); + assert(strcmp(mod_first_line->text, restored_first_line->text) !=3D 0); +} + +static void test_maps_tearing_from_split(int maps_fd, + struct vma_modifier_info *mod_info, + struct page_content *page1, + struct page_content *page2, + struct line_content *last_line, + struct line_content *first_line) +{ + struct line_content split_last_line; + struct line_content split_first_line; + struct line_content restored_last_line; + struct line_content restored_first_line; + + wait_for_state(mod_info, SETUP_READY); + + /* re-read the file to avoid using stale data from previous test */ + read_boundary_lines(maps_fd, page1, page2, last_line, first_line); + + mod_info->vma_modify =3D split_vma; + mod_info->vma_restore =3D merge_vma; + mod_info->vma_mod_check =3D check_split_result; + + capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, + &split_last_line, &split_first_line, + &restored_last_line, &restored_first_line); + + /* Now start concurrent modifications for test_duration_sec */ + signal_state(mod_info, TEST_READY); + + struct line_content new_last_line; + struct line_content new_first_line; + struct timespec start_ts, end_ts; + + clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + do { + bool last_line_changed; + bool first_line_changed; + + read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); + + /* Check if we read vmas after split */ + if (!strcmp(new_last_line.text, split_last_line.text)) { + /* + * The vmas should be consistent with split results, + * however if vma was concurrently restored after a + * split, it can be reported twice (first the original + * split one, then the same vma but extended after the + * merge) because we found it as the next vma again. + * In that case new first line will be the same as the + * last restored line. + */ + assert(!strcmp(new_first_line.text, split_first_line.text) || + !strcmp(new_first_line.text, restored_last_line.text)); + } else { + /* The vmas should be consistent with merge results */ + assert(!strcmp(new_last_line.text, restored_last_line.text) && + !strcmp(new_first_line.text, restored_first_line.text)); + } + /* + * First and last lines should change in unison. If the last + * line changed then the first line should change as well and + * vice versa. + */ + last_line_changed =3D strcmp(new_last_line.text, last_line->text) !=3D 0; + first_line_changed =3D strcmp(new_first_line.text, first_line->text) != =3D 0; + assert(last_line_changed =3D=3D first_line_changed); + + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + + /* Signal the modifyer thread to stop and wait until it exits */ + signal_state(mod_info, TEST_DONE); +} + +int usage(void) +{ + fprintf(stderr, "Userland /proc/pid/{s}maps race test cases\n"); + fprintf(stderr, " -d: Duration for time-consuming tests\n"); + fprintf(stderr, " -h: Help screen\n"); + exit(-1); +} + +int main(int argc, char **argv) +{ + struct vma_modifier_info *mod_info; + pthread_mutexattr_t mutex_attr; + pthread_condattr_t cond_attr; + int shared_mem_size; + char fname[32]; + int vma_count; + int maps_fd; + int status; + pid_t pid; + int opt; + + while ((opt =3D getopt(argc, argv, "d:h")) !=3D -1) { + if (opt =3D=3D 'd') + test_duration_sec =3D strtoul(optarg, NULL, 0); + else if (opt =3D=3D 'h') + usage(); + } + + page_size =3D sysconf(_SC_PAGESIZE); + /* + * Have to map enough vmas for /proc/pid/maps to contain more than one + * page worth of vmas. Assume at least 32 bytes per line in maps output + */ + vma_count =3D page_size / 32 + 1; + shared_mem_size =3D sizeof(struct vma_modifier_info) + vma_count * sizeof= (void *); + + /* map shared memory for communication with the child process */ + mod_info =3D (struct vma_modifier_info *)mmap(NULL, shared_mem_size, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + assert(mod_info !=3D MAP_FAILED); + + /* Initialize shared members */ + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); + assert(!pthread_mutex_init(&mod_info->sync_lock, &mutex_attr)); + pthread_condattr_init(&cond_attr); + pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + assert(!pthread_cond_init(&mod_info->sync_cond, &cond_attr)); + mod_info->vma_count =3D vma_count; + mod_info->curr_state =3D INIT; + mod_info->exit =3D false; + + pid =3D fork(); + if (!pid) { + /* Child process */ + child_vma_modifier(mod_info); + return 0; + } + + sprintf(fname, "/proc/%d/maps", pid); + maps_fd =3D open(fname, O_RDONLY); + assert(maps_fd !=3D -1); + + /* Wait for the child to map the VMAs */ + wait_for_state(mod_info, CHILD_READY); + + /* Read first two pages */ + struct page_content page1; + struct page_content page2; + + page1.data =3D malloc(page_size); + assert(page1.data); + page2.data =3D malloc(page_size); + assert(page2.data); + + struct line_content last_line; + struct line_content first_line; + + read_boundary_lines(maps_fd, &page1, &page2, &last_line, &first_line); + + /* + * Find the addresses corresponding to the last line in the first page + * and the first line in the last page. + */ + mod_info->addr =3D NULL; + mod_info->next_addr =3D NULL; + for (int i =3D 0; i < mod_info->vma_count; i++) { + if (mod_info->child_mapped_addr[i] =3D=3D (void *)last_line.start_addr) { + mod_info->addr =3D mod_info->child_mapped_addr[i]; + mod_info->prot =3D PROT_READ; + /* Even VMAs have write permission */ + if ((i % 2) =3D=3D 0) + mod_info->prot |=3D PROT_WRITE; + } else if (mod_info->child_mapped_addr[i] =3D=3D (void *)first_line.star= t_addr) { + mod_info->next_addr =3D mod_info->child_mapped_addr[i]; + } + + if (mod_info->addr && mod_info->next_addr) + break; + } + assert(mod_info->addr && mod_info->next_addr); + + signal_state(mod_info, PARENT_READY); + + test_maps_tearing_from_split(maps_fd, mod_info, &page1, &page2, + &last_line, &first_line); + + stop_vma_modifier(mod_info); + + free(page2.data); + free(page1.data); + + for (int i =3D 0; i < vma_count; i++) + munmap(mod_info->child_mapped_addr[i], page_size); + close(maps_fd); + waitpid(pid, &status, 0); + munmap(mod_info, shared_mem_size); + + return 0; +} --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EEAF223DDA for ; Fri, 4 Jul 2025 06:07:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609257; cv=none; b=gI7Csble5FKSNgQEBCtJoLgSjPvO6Mq8tgD+0hu1E3fmY+mPvWHjdiWxlaI2CjhQoAtE+b5Kn6CeX+gOIOF7PVN3eeky+8a0VjHmbPtjKOw1HhkPEEtRu3c0z+LvL9WfQ/63joh+UP98MHMGDaeJ9L1/oNTA674oBT+S8sXSzr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609257; c=relaxed/simple; bh=ulewSdFhhtT6XYUvitzcBD75LHyogn8pm3lfZUrI9VI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=NMkNM1raQrQmTdyg4bqDx9g6GzxgHpp6bBoxRtVBLzjykcEtIWfISIDMJoaPgT7Me9ggcJvSgIoc2LCgdkqK01oBe3Yb+I7L9FDkCtyB795r5ZnM3njGkR8uoR4s6q9op6rv6QsyxSF/DNB5qK3DCYDoqXVd4pBdYh5PljRirtk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fh58pI9k; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fh58pI9k" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b3216490a11so833352a12.3 for ; Thu, 03 Jul 2025 23:07:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609255; x=1752214055; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=OwmJhXkBZ0rkJP8ZDJsJXdxfIUoApnDNh42agcrLiOc=; b=fh58pI9kE4RSWF3lEcppnc3bOQwmyYNocvqm0Ts/0CvM6SBSuPOGT/JgnVi3R7QLCE 5wne/xGTSUNn4elvupvomd86kItawhJcex1UiCNHTHeNEq28hlygbBYsSZLhG6+KdQCW Na2X4IpP0nC/d7UI5wrsGH6wc+4nDeTPTb5DTaNTpG59uPB9rR2mw+Wqzj0sgHYYbsw/ +zNYy5ziY+IWKZjFuq2/CzlNR11mj5mkQLAfZgTnL+aThdGsJKzwPMrgK+CEkabWFcMe IO80vO40XD3XBZfltX+FPRLLpXvUvCIYrd9PpBztIlRq6LWhn8mdrxCVW7jsNdPgflbc Rhrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609255; x=1752214055; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OwmJhXkBZ0rkJP8ZDJsJXdxfIUoApnDNh42agcrLiOc=; b=M0iw6JKm6B40mc4D0KETwEE4X2UMDIlTixuIxrrmro+geAR6QedBV0ZevCeys64Yak Lgq99OG9CJMuxLXwfdzUmj3/furDYZBHxU4MfrqcXJpVr5NrHRxaNuAdg7/8hDOytoIV kDQ60CSKZjxKw89h3QJ5zarP/53LIr5Wk1GfVtuYAHED/j+mDxEfuVgeIgEFhm/iuvoK lgp2JLa0wBiRIngul6eqVNcnUz74HNRcHo5Gxr02WOUMlM7piuzkvxGDr7bzpjDze0+y /XFaYFeM49TEAPfkX1c2W87of/vuWbTWJ9y71IppPPksTLylqqg5p02Z0rlQT3crWHcN afkA== X-Forwarded-Encrypted: i=1; AJvYcCX4OyQmy7lrNUsElZ8S0loDUXrWt1JvvLaqO0lLPysNqO09w9arIenKsloCxth1nMsqvkIZIu+0BohAtpI=@vger.kernel.org X-Gm-Message-State: AOJu0Yw/EGuLjQIyt0klpVhwzCPkAI0D2OBXeqG/o5/xbAu3H0VLmhBo 4wNd/moWv3VMLknbXHrMpX5VoPw4eDru6726Q8j7FFlOFmPV+ohjyfYml9VTuClPGZHU1P2FbaP zk6uD8A== X-Google-Smtp-Source: AGHT+IGoB8QNnIkSWC4/zUTdGlarrbysVsWS8O8UNA9J6spZjeT17zKRWVRCaC7cIc1X4P3itAYlZ+WiQX4= X-Received: from pgah2.prod.google.com ([2002:a05:6a02:4e82:b0:b31:ebae:e100]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:914c:b0:220:a241:91a5 with SMTP id adf61e73a8af0-225b85f40demr2440780637.16.1751609254814; Thu, 03 Jul 2025 23:07:34 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:20 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-3-surenb@google.com> Subject: [PATCH v6 2/8] selftests/proc: extend /proc/pid/maps tearing test to include vma resizing From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Test that /proc/pid/maps does not report unexpected holes in the address space when a vma at the edge of the page is being concurrently remapped. This remapping results in the vma shrinking and expanding from under the reader. We should always see either shrunk or expanded (original) version of the vma. Signed-off-by: Suren Baghdasaryan --- tools/testing/selftests/proc/proc-maps-race.c | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tools/testing/selftests/proc/proc-maps-race.c b/tools/testing/= selftests/proc/proc-maps-race.c index 523afd83d34f..10365b4e68e1 100644 --- a/tools/testing/selftests/proc/proc-maps-race.c +++ b/tools/testing/selftests/proc/proc-maps-race.c @@ -336,6 +336,86 @@ static void test_maps_tearing_from_split(int maps_fd, signal_state(mod_info, TEST_DONE); } =20 +static inline void shrink_vma(const struct vma_modifier_info *mod_info) +{ + assert(mremap(mod_info->addr, page_size * 3, page_size, 0) !=3D MAP_FAILE= D); +} + +static inline void expand_vma(const struct vma_modifier_info *mod_info) +{ + assert(mremap(mod_info->addr, page_size, page_size * 3, 0) !=3D MAP_FAILE= D); +} + +static inline void check_shrink_result(struct line_content *mod_last_line, + struct line_content *mod_first_line, + struct line_content *restored_last_line, + struct line_content *restored_first_line) +{ + /* Make sure only the last vma of the first page is changing */ + assert(strcmp(mod_last_line->text, restored_last_line->text) !=3D 0); + assert(strcmp(mod_first_line->text, restored_first_line->text) =3D=3D 0); +} + +static void test_maps_tearing_from_resize(int maps_fd, + struct vma_modifier_info *mod_info, + struct page_content *page1, + struct page_content *page2, + struct line_content *last_line, + struct line_content *first_line) +{ + struct line_content shrunk_last_line; + struct line_content shrunk_first_line; + struct line_content restored_last_line; + struct line_content restored_first_line; + + wait_for_state(mod_info, SETUP_READY); + + /* re-read the file to avoid using stale data from previous test */ + read_boundary_lines(maps_fd, page1, page2, last_line, first_line); + + mod_info->vma_modify =3D shrink_vma; + mod_info->vma_restore =3D expand_vma; + mod_info->vma_mod_check =3D check_shrink_result; + + capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, + &shrunk_last_line, &shrunk_first_line, + &restored_last_line, &restored_first_line); + + /* Now start concurrent modifications for test_duration_sec */ + signal_state(mod_info, TEST_READY); + + struct line_content new_last_line; + struct line_content new_first_line; + struct timespec start_ts, end_ts; + + clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + do { + read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); + + /* Check if we read vmas after shrinking it */ + if (!strcmp(new_last_line.text, shrunk_last_line.text)) { + /* + * The vmas should be consistent with shrunk results, + * however if the vma was concurrently restored, it + * can be reported twice (first as shrunk one, then + * as restored one) because we found it as the next vma + * again. In that case new first line will be the same + * as the last restored line. + */ + assert(!strcmp(new_first_line.text, shrunk_first_line.text) || + !strcmp(new_first_line.text, restored_last_line.text)); + } else { + /* The vmas should be consistent with the original/resored state */ + assert(!strcmp(new_last_line.text, restored_last_line.text) && + !strcmp(new_first_line.text, restored_first_line.text)); + } + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + + /* Signal the modifyer thread to stop and wait until it exits */ + signal_state(mod_info, TEST_DONE); +} + int usage(void) { fprintf(stderr, "Userland /proc/pid/{s}maps race test cases\n"); @@ -444,6 +524,9 @@ int main(int argc, char **argv) test_maps_tearing_from_split(maps_fd, mod_info, &page1, &page2, &last_line, &first_line); =20 + test_maps_tearing_from_resize(maps_fd, mod_info, &page1, &page2, + &last_line, &first_line); + stop_vma_modifier(mod_info); =20 free(page2.data); --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B1DF22D4C0 for ; Fri, 4 Jul 2025 06:07:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609259; cv=none; b=WrQLHPUb2ha40GLH4hPhUTT/Y1HHKBVOxaAJN7FUjMETTR8rfK4Dj6mu06DjVE2F1qSXaHIiyr7mxykbd8LSDKEyCuYvocw5+Cujb3iCNV0KmtE5hanUNcRDNOnaX13hAQASj2pFvSfcNSXuUPIyRt0bvg0admGuHpnBFoJnCos= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609259; c=relaxed/simple; bh=ZMGFntAQnjjtMoQxDdiUKIBvPxmH73C1FhJ2CMHVp1Y=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dmOk1TCuL1iM2UB7tPvU51nOp6XBcQycVdtU1wot7s4vtSCeQbwQyZOYvFzFdOt5VQc5SLTZa4BhxtlhQWFjK/u88clIbpFSndFlfpUcbV1clr5aJ7KyrYkxwvHGZ/x50MDTrgtFlyJj2IFdlBqtmqKwRGE22kFw3UdX1nJV0uk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=GfFUvIBL; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="GfFUvIBL" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-748f13ef248so654680b3a.3 for ; Thu, 03 Jul 2025 23:07:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609257; x=1752214057; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Li63ssKppcLITl1ITfej/YujyWpoLXNJQdKFDqdnOTk=; b=GfFUvIBLQCAo6ht0eCpGERhFqayrzK5V6J3ggaN38JVh8XOrJ2fXUOW3GNUwQqo15B naLl71iKAtRimhZCj1X4U3R23gtJ/TdDF8JgBnUk4iwUzs8DQmAYeqdq46ZnAgJXkFI2 eFL7K96+8leh888chkb0j2DVLNq9ziYbsa9zsJHg5TAIlSos/GJE9HuQBIp7ZrXJWSAI js6A5W4zQUVHZJ4pf6h0gPmbdJtdP5hDF94J7VFl0TmIBYQK1QuZRNT6/gP48zKMjwg9 eWbJr7vRJyd2tF/BsRjpRjR1TY2vKsUmwOXc6APTfn7LfYVqM9czW+RyTCqzC+MLmaT3 +8fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609257; x=1752214057; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Li63ssKppcLITl1ITfej/YujyWpoLXNJQdKFDqdnOTk=; b=rWp8gvmu5rEnX/VTn+IFe5/dGI7LyzGZC9J81ZPIx7UhODJMASCZ1g1e8868/EGImh URT7QZEjmd78pz4ecV5WHjcYYxvRRxj4MU0Wb2N8g4Uw2NPZsMFP1X3tAaERe9cce76Y 8bAuiishH3PmRdZnSYdQlokSNtyDb7fefYR22GcaP2g3h+GK9WP7ieEFE7ExtT27KeoC FlunWfkL5Wn8UswU0YVSujo6Ja3l6c3p5fU8RvBzFKXh6cpyG/hDiK5l8R5opY6gu83n Wfbr0BTju7m/h1+V3pbn1c0F2QSiQIEGD+lVjvyEjZE1eF9XHkRs5ESkYo1vGAx+M9kH EjbQ== X-Forwarded-Encrypted: i=1; AJvYcCWlwg1IJJYrPyjxk9q6SGc9++ysAjEg6Cp5G5WWtdrlo/IfkmoUNBz5GYb9wdocoPUGc+ZCpAB8UEA8CUM=@vger.kernel.org X-Gm-Message-State: AOJu0YwsMM47AznM2rkkAHGxknVHEB95d1Nsj+3SLb6AG7RbM4gk5fvj PTOH+mU05lf6YFodqF3CwCVCfMhYYk8H7fAm5YDinLS2F/hw4RjygTxFdH5na+AD0Gj4vU8Wg/K tpCTbGg== X-Google-Smtp-Source: AGHT+IFg2kF2IsphyTUD4Tvtt+9uGgwrJfxzBAwNyZq9idmvq78iXfjYjXpbgDrlsnLunNcFZOzQ5AK3W2w= X-Received: from pgji5.prod.google.com ([2002:a63:d445:0:b0:b11:3ba:92e4]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:e90:b0:222:d817:2f4a with SMTP id adf61e73a8af0-22609a8977dmr1043637637.17.1751609256747; Thu, 03 Jul 2025 23:07:36 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:21 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-4-surenb@google.com> Subject: [PATCH v6 3/8] selftests/proc: extend /proc/pid/maps tearing test to include vma remapping From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Test that /proc/pid/maps does not report unexpected holes in the address space when we concurrently remap a part of a vma into the middle of another vma. This remapping results in the destination vma being split into three parts and the part in the middle being patched back from, all done concurrently from under the reader. We should always see either original vma or the split one with no holes. Signed-off-by: Suren Baghdasaryan --- tools/testing/selftests/proc/proc-maps-race.c | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tools/testing/selftests/proc/proc-maps-race.c b/tools/testing/= selftests/proc/proc-maps-race.c index 10365b4e68e1..764821ffd63d 100644 --- a/tools/testing/selftests/proc/proc-maps-race.c +++ b/tools/testing/selftests/proc/proc-maps-race.c @@ -416,6 +416,95 @@ static void test_maps_tearing_from_resize(int maps_fd, signal_state(mod_info, TEST_DONE); } =20 +static inline void remap_vma(const struct vma_modifier_info *mod_info) +{ + /* + * Remap the last page of the next vma into the middle of the vma. + * This splits the current vma and the first and middle parts (the + * parts at lower addresses) become the last vma objserved in the + * first page and the first vma observed in the last page. + */ + assert(mremap(mod_info->next_addr + page_size * 2, page_size, + page_size, MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP, + mod_info->addr + page_size) !=3D MAP_FAILED); +} + +static inline void patch_vma(const struct vma_modifier_info *mod_info) +{ + assert(!mprotect(mod_info->addr + page_size, page_size, + mod_info->prot)); +} + +static inline void check_remap_result(struct line_content *mod_last_line, + struct line_content *mod_first_line, + struct line_content *restored_last_line, + struct line_content *restored_first_line) +{ + /* Make sure vmas at the boundaries are changing */ + assert(strcmp(mod_last_line->text, restored_last_line->text) !=3D 0); + assert(strcmp(mod_first_line->text, restored_first_line->text) !=3D 0); +} + +static void test_maps_tearing_from_remap(int maps_fd, + struct vma_modifier_info *mod_info, + struct page_content *page1, + struct page_content *page2, + struct line_content *last_line, + struct line_content *first_line) +{ + struct line_content remapped_last_line; + struct line_content remapped_first_line; + struct line_content restored_last_line; + struct line_content restored_first_line; + + wait_for_state(mod_info, SETUP_READY); + + /* re-read the file to avoid using stale data from previous test */ + read_boundary_lines(maps_fd, page1, page2, last_line, first_line); + + mod_info->vma_modify =3D remap_vma; + mod_info->vma_restore =3D patch_vma; + mod_info->vma_mod_check =3D check_remap_result; + + capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, + &remapped_last_line, &remapped_first_line, + &restored_last_line, &restored_first_line); + + /* Now start concurrent modifications for test_duration_sec */ + signal_state(mod_info, TEST_READY); + + struct line_content new_last_line; + struct line_content new_first_line; + struct timespec start_ts, end_ts; + + clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + do { + read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); + + /* Check if we read vmas after remapping it */ + if (!strcmp(new_last_line.text, remapped_last_line.text)) { + /* + * The vmas should be consistent with remap results, + * however if the vma was concurrently restored, it + * can be reported twice (first as split one, then + * as restored one) because we found it as the next vma + * again. In that case new first line will be the same + * as the last restored line. + */ + assert(!strcmp(new_first_line.text, remapped_first_line.text) || + !strcmp(new_first_line.text, restored_last_line.text)); + } else { + /* The vmas should be consistent with the original/resored state */ + assert(!strcmp(new_last_line.text, restored_last_line.text) && + !strcmp(new_first_line.text, restored_first_line.text)); + } + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + + /* Signal the modifyer thread to stop and wait until it exits */ + signal_state(mod_info, TEST_DONE); +} + int usage(void) { fprintf(stderr, "Userland /proc/pid/{s}maps race test cases\n"); @@ -527,6 +616,9 @@ int main(int argc, char **argv) test_maps_tearing_from_resize(maps_fd, mod_info, &page1, &page2, &last_line, &first_line); =20 + test_maps_tearing_from_remap(maps_fd, mod_info, &page1, &page2, + &last_line, &first_line); + stop_vma_modifier(mod_info); =20 free(page2.data); --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC47223816C for ; Fri, 4 Jul 2025 06:07:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609261; cv=none; b=J23vlE+prZHwWBBAjPpGxgTIKjSdTegBDiyCNlZt8s61BoWJzFUZjFOblW44d4R9jr7mBQ8/fsxzfPgyW5bnk65P7IMTC0jzDbodlODsD/3i0/cSS7Qzj1YAkMS4YZhZahghESR8x1rOye2fSu8YGYo+XS/oqlCF5+YgC1jIVl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609261; c=relaxed/simple; bh=6/KDaBp6ZM8MWS9qb0wO08Ku16BqGmytBKM3lNMr5qw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rnBBiYyyZuFMUsBTyX38+ats+8BVTyC8gTTUiDUjSXUKSCH4RJceZrYK2+ZSYb86ExpLFz0HncT1aqzxfa7rSP0qKZrHewi5fJQtRuIzKAD08lvqMYKZOG0qicMjRLnuqAejQoiriEzHZPzPGiTgg4Bwd6qCNwqSF53YSC+W8oY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=4ffK5AO6; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="4ffK5AO6" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-23632fd6248so5867815ad.3 for ; Thu, 03 Jul 2025 23:07:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609259; x=1752214059; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Wz+/Rb5/fWdnaWsOelI+A9jPFxhtbRCP90y3FqomvrU=; b=4ffK5AO6g6JajBAiHR1LBfKyuiiNpcLzOvei42nDr1LYOryigi0WSc5YqWybLDDF68 uWyrrzspQoIeAMWZ3i1QNZhQ0ojIwwLgYFGVI3BKOzCgt4UqVLNI2Mj+gvPrJU6CLcrP +x7bgv+N+DbpuDwf/W5+VHAttb9TJ5SpoElxjXo1ptt7H4trq2TZ1D/AloH+i6ESbnpg 95gf/oF9j+GfJPjrPT7ZlApFOHrgLdiv8W/xsxDLVaqJTESk4FwIpBsVCe6vfK+P2vet JdL3z4X402t5vP3S5iZOx4syriJLfeMN5J3kdcPAfss1mYXoBXp/Qu4Rh4hXhbrne62l CltA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609259; x=1752214059; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Wz+/Rb5/fWdnaWsOelI+A9jPFxhtbRCP90y3FqomvrU=; b=WGENwmq2rHZKP3wxsdPBxakOf2APpv72LByAfTPdNcs9X8dnZz1avbEETLBIw9IyYY /aWt72fz6PuOUvpLy/pjFbKjup4pdeg9LDTsouxkozFfBH0MpBXmybyPZtZSPkYbcAjg 5iy0IiC/RQzLCnGZ/5tO33N3HPHSEWrivP/+hR8SRNRoogcwI/a0YAbFJbSQdELSKUER vTb4YLiyZyffRbDBuxjM66cSi1ylCZV3ZqfCjEDoPTYKrMVPvX2Pqkl/q6sGQ54pkIf7 0kHweoSPANyMZb6fanGp8GV/qR/LMpxpZGLHDcgqtJ2L21u1G3FCFGAyGfnIpOt4etKE lmaw== X-Forwarded-Encrypted: i=1; AJvYcCUVDKWmW/6Lp415EqT6bGdq7LFzUZYWQ3JqO6XS/+AvOVQYJVp/IXFtQftuZ4qzWFbvYUh7NeP6CK/nckM=@vger.kernel.org X-Gm-Message-State: AOJu0Yxhj6Xg6+xpXvbyX2drMEW5kWpL59ClOugrhSGVcwC0c+o4sL+7 BaGWhqOpgkGmBkpV6ehcBfYqu6XySYZRVnk7RuSqJBJmzYrktcbY1XH2srdFkfNs/ft5mVx6eLo yADzrug== X-Google-Smtp-Source: AGHT+IGb2+UYZlfBpIllsB5zBRnjJDEHHc7eLL5E2NOd532QUxSqIns3SjUtZteR3l3V6p3oyrgM+kKIc4Y= X-Received: from pjbrs14.prod.google.com ([2002:a17:90b:2b8e:b0:312:187d:382d]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:11c3:b0:234:d7b2:2ab4 with SMTP id d9443c01a7336-23c85de4dfamr22462935ad.17.1751609258994; Thu, 03 Jul 2025 23:07:38 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:22 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-5-surenb@google.com> Subject: [PATCH v6 4/8] selftests/proc: test PROCMAP_QUERY ioctl while vma is concurrently modified From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend /proc/pid/maps tearing test to verify PROCMAP_QUERY ioctl operation correctness while the vma is being concurrently modified. Signed-off-by: Suren Baghdasaryan --- tools/testing/selftests/proc/proc-maps-race.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tools/testing/selftests/proc/proc-maps-race.c b/tools/testing/= selftests/proc/proc-maps-race.c index 764821ffd63d..6acdafdac9db 100644 --- a/tools/testing/selftests/proc/proc-maps-race.c +++ b/tools/testing/selftests/proc/proc-maps-race.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -239,6 +241,21 @@ static void capture_mod_pattern(int maps_fd, assert(strcmp(restored_first_line->text, first_line->text) =3D=3D 0); } =20 +static void query_addr_at(int maps_fd, void *addr, + unsigned long *vma_start, unsigned long *vma_end) +{ + struct procmap_query q; + + memset(&q, 0, sizeof(q)); + q.size =3D sizeof(q); + /* Find the VMA at the split address */ + q.query_addr =3D (unsigned long long)addr; + q.query_flags =3D 0; + assert(!ioctl(maps_fd, PROCMAP_QUERY, &q)); + *vma_start =3D q.vma_start; + *vma_end =3D q.vma_end; +} + static inline void split_vma(const struct vma_modifier_info *mod_info) { assert(mmap(mod_info->addr, page_size, mod_info->prot | PROT_EXEC, @@ -299,6 +316,8 @@ static void test_maps_tearing_from_split(int maps_fd, do { bool last_line_changed; bool first_line_changed; + unsigned long vma_start; + unsigned long vma_end; =20 read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); =20 @@ -329,6 +348,19 @@ static void test_maps_tearing_from_split(int maps_fd, first_line_changed =3D strcmp(new_first_line.text, first_line->text) != =3D 0; assert(last_line_changed =3D=3D first_line_changed); =20 + /* Check if PROCMAP_QUERY ioclt() finds the right VMA */ + query_addr_at(maps_fd, mod_info->addr + page_size, + &vma_start, &vma_end); + /* + * The vma at the split address can be either the same as + * original one (if read before the split) or the same as the + * first line in the second page (if read after the split). + */ + assert((vma_start =3D=3D last_line->start_addr && + vma_end =3D=3D last_line->end_addr) || + (vma_start =3D=3D split_first_line.start_addr && + vma_end =3D=3D split_first_line.end_addr)); + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); =20 @@ -390,6 +422,9 @@ static void test_maps_tearing_from_resize(int maps_fd, =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); do { + unsigned long vma_start; + unsigned long vma_end; + read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); =20 /* Check if we read vmas after shrinking it */ @@ -409,6 +444,17 @@ static void test_maps_tearing_from_resize(int maps_fd, assert(!strcmp(new_last_line.text, restored_last_line.text) && !strcmp(new_first_line.text, restored_first_line.text)); } + + /* Check if PROCMAP_QUERY ioclt() finds the right VMA */ + query_addr_at(maps_fd, mod_info->addr, &vma_start, &vma_end); + /* + * The vma should stay at the same address and have either the + * original size of 3 pages or 1 page if read after shrinking. + */ + assert(vma_start =3D=3D last_line->start_addr && + (vma_end - vma_start =3D=3D page_size * 3 || + vma_end - vma_start =3D=3D page_size)); + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); =20 @@ -479,6 +525,9 @@ static void test_maps_tearing_from_remap(int maps_fd, =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); do { + unsigned long vma_start; + unsigned long vma_end; + read_boundary_lines(maps_fd, page1, page2, &new_last_line, &new_first_li= ne); =20 /* Check if we read vmas after remapping it */ @@ -498,6 +547,19 @@ static void test_maps_tearing_from_remap(int maps_fd, assert(!strcmp(new_last_line.text, restored_last_line.text) && !strcmp(new_first_line.text, restored_first_line.text)); } + + /* Check if PROCMAP_QUERY ioclt() finds the right VMA */ + query_addr_at(maps_fd, mod_info->addr + page_size, &vma_start, &vma_end); + /* + * The vma should either stay at the same address and have the + * original size of 3 pages or we should find the remapped vma + * at the remap destination address with size of 1 page. + */ + assert((vma_start =3D=3D last_line->start_addr && + vma_end - vma_start =3D=3D page_size * 3) || + (vma_start =3D=3D last_line->start_addr + page_size && + vma_end - vma_start =3D=3D page_size)); + clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); =20 --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EBDF323F294 for ; Fri, 4 Jul 2025 06:07:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609263; cv=none; b=rMVDlccqHLMNz9Z8ZaMDhuSLyY0wWaN4B/HBvOej4X9sU5Lhafx29SPekh08has5c9t0SVhbSQBh6C7M6Vyrp5fnevwIWqdeGjsAgyNpZBB512sQB8H8zroRDEG0ucILWE559vfb4uTk+zoGRPkddH3KGTprELLto6og5tx2Bm4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609263; c=relaxed/simple; bh=WMdtgrr0/nAUiC/6BwG7uLPF5Tm6Y08FEzL5Ntj1PoA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=FtduYzOD6Gu84174Im80K+7wIt9MFRF+otzJZBSy8efX86C6fLBwxcfpHdOo4DEyNugDKnGii48JQAyNAyvabk0zEq6GDYn/0wgnEV6W9EKauR2YAowa/hGtaOIVzKD9HJXy8CvcU6fL33TiNpiIv6RwQvZNahnHwNKvz7rtT9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qy/k+efT; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qy/k+efT" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-313fb0ec33bso675108a91.2 for ; Thu, 03 Jul 2025 23:07:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609261; x=1752214061; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=+EEGEPDve4y58hrdp46uj5UK2kmzvt0af85C6yPTlxY=; b=qy/k+efTDrNtBdNa203lTcB5j6dqlIYuPB01jkga8ZsqJijRxpkGZXechiH2kmwTxc 33boSKWbIEo3adm9qFr73nPVUVvOIW5bkW+jl2WIxM94YZ5HYf4IETmXgiAv7bLCud9K 0K5bitxkoADzI5G1RtTletSciyJ08dJDPi5rJxhLK8wsSk31jTB85ivoQXpoI0aHXm0V CxRDm3p8Vkzks+s/o/+pTBllPiFiCfqAKk4UeUg7WYbVk2z38VXxoiQ25cpd2gEDbXLv 0ubC4s3iDN0myg4rQis+3yLBRTXvGR8ILpIExkf1A1TB3KvuYJuXIp6RxXHRTt27zSUN NeLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609261; x=1752214061; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+EEGEPDve4y58hrdp46uj5UK2kmzvt0af85C6yPTlxY=; b=C8YaxBkLDJKFBEsfBv4dtDNCtbJXb6uzp33kXCbgNG/vcluXWcWqWak4iIHb9Ggv/L NhjJnfopNw9wYVWM1xJCKrA/bNoIxVaTo+qzX0EBeefBJ6AnQTGFbhi7hIyGOC4hjuhc rYjduTEIMjY4CMpAkD7gVNWgAcgKkZeYPwr8KErZp8zFZlXNeJvlBWCHeJeAJMn49XAX lKk+TRmKzuxG//MQ8E3Bfj9Ujo3DKVh06GgEV1qXsw54sH/wqDhZtv9be1JsG1QLx7W1 bQk20WcJu1ds63VBoliD7u0UL4syrlAn6dDUnBm78f9hRibg+OIJbwjQUavq03OJZVu7 23VQ== X-Forwarded-Encrypted: i=1; AJvYcCVBhELyTRB1Jmu4Z/Kse7gxiKRYrH/bBhRrLq5rWqt2IKRDnINCTfODA+htSOgr2kldiidCoXPIO109BFo=@vger.kernel.org X-Gm-Message-State: AOJu0YwW8FtRHzfVwNMHUzQGo0TU7azqv85Ycp0pYRjslYZiHNOeop0U Cgoj9+XkGoXfJ3Ixq1i9v2QjnMSOblbNPVGhc82gwCSYPRdk4YEzEFOjeJLp/nDg25kLsUKAMIU 3gnSVoQ== X-Google-Smtp-Source: AGHT+IGwByjyjbWto9oY/VtnoR6krv+OKvQ79zjK0W0qyloVZR9Tx47plfk6bg9opHV46dxYuI5qPKfJ5JE= X-Received: from pgha7.prod.google.com ([2002:a63:d407:0:b0:b2c:3dd5:8139]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:c888:b0:21a:de8e:5e6d with SMTP id adf61e73a8af0-225be6e4963mr2470660637.8.1751609261073; Thu, 03 Jul 2025 23:07:41 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:23 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-6-surenb@google.com> Subject: [PATCH v6 5/8] selftests/proc: add verbose more for tests to facilitate debugging From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add verbose mode to the proc tests to print debugging information. Usage: proc-pid-vm -v Signed-off-by: Suren Baghdasaryan --- tools/testing/selftests/proc/proc-maps-race.c | 159 ++++++++++++++++-- 1 file changed, 146 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/proc/proc-maps-race.c b/tools/testing/= selftests/proc/proc-maps-race.c index 6acdafdac9db..5f912fedd6cf 100644 --- a/tools/testing/selftests/proc/proc-maps-race.c +++ b/tools/testing/selftests/proc/proc-maps-race.c @@ -39,6 +39,7 @@ =20 static unsigned long test_duration_sec =3D 5UL; static int page_size; +static bool verbose; =20 /* /proc/pid/maps parsing routines */ struct page_content { @@ -207,6 +208,99 @@ static void stop_vma_modifier(struct vma_modifier_info= *mod_info) signal_state(mod_info, SETUP_MODIFY_MAPS); } =20 +static void print_first_lines(char *text, int nr) +{ + const char *end =3D text; + + while (nr && (end =3D strchr(end, '\n')) !=3D NULL) { + nr--; + end++; + } + + if (end) { + int offs =3D end - text; + + text[offs] =3D '\0'; + printf(text); + text[offs] =3D '\n'; + printf("\n"); + } else { + printf(text); + } +} + +static void print_last_lines(char *text, int nr) +{ + const char *start =3D text + strlen(text); + + nr++; /* to ignore the last newline */ + while (nr) { + while (start > text && *start !=3D '\n') + start--; + nr--; + start--; + } + printf(start); +} + +static void print_boundaries(const char *title, + struct page_content *page1, + struct page_content *page2) +{ + if (!verbose) + return; + + printf("%s", title); + /* Print 3 boundary lines from each page */ + print_last_lines(page1->data, 3); + printf("-----------------page boundary-----------------\n"); + print_first_lines(page2->data, 3); +} + +static bool print_boundaries_on(bool condition, const char *title, + struct page_content *page1, + struct page_content *page2) +{ + if (verbose && condition) + print_boundaries(title, page1, page2); + + return condition; +} + +static void report_test_start(const char *name) +{ + if (verbose) + printf("=3D=3D=3D=3D %s =3D=3D=3D=3D\n", name); +} + +static struct timespec print_ts; + +static void start_test_loop(struct timespec *ts) +{ + if (verbose) + print_ts.tv_sec =3D ts->tv_sec; +} + +static void end_test_iteration(struct timespec *ts) +{ + if (!verbose) + return; + + /* Update every second */ + if (print_ts.tv_sec =3D=3D ts->tv_sec) + return; + + printf("."); + fflush(stdout); + print_ts.tv_sec =3D ts->tv_sec; +} + +static void end_test_loop(void) +{ + if (verbose) + printf("\n"); +} + static void capture_mod_pattern(int maps_fd, struct vma_modifier_info *mod_info, struct page_content *page1, @@ -218,18 +312,24 @@ static void capture_mod_pattern(int maps_fd, struct line_content *restored_last_line, struct line_content *restored_first_line) { + print_boundaries("Before modification", page1, page2); + signal_state(mod_info, SETUP_MODIFY_MAPS); wait_for_state(mod_info, SETUP_MAPS_MODIFIED); =20 /* Copy last line of the first page and first line of the last page */ read_boundary_lines(maps_fd, page1, page2, mod_last_line, mod_first_line); =20 + print_boundaries("After modification", page1, page2); + signal_state(mod_info, SETUP_RESTORE_MAPS); wait_for_state(mod_info, SETUP_MAPS_RESTORED); =20 /* Copy last line of the first page and first line of the last page */ read_boundary_lines(maps_fd, page1, page2, restored_last_line, restored_f= irst_line); =20 + print_boundaries("After restore", page1, page2); + mod_info->vma_mod_check(mod_last_line, mod_first_line, restored_last_line, restored_first_line); =20 @@ -301,6 +401,7 @@ static void test_maps_tearing_from_split(int maps_fd, mod_info->vma_restore =3D merge_vma; mod_info->vma_mod_check =3D check_split_result; =20 + report_test_start("Tearing from split"); capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, &split_last_line, &split_first_line, &restored_last_line, &restored_first_line); @@ -313,6 +414,7 @@ static void test_maps_tearing_from_split(int maps_fd, struct timespec start_ts, end_ts; =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + start_test_loop(&start_ts); do { bool last_line_changed; bool first_line_changed; @@ -332,12 +434,18 @@ static void test_maps_tearing_from_split(int maps_fd, * In that case new first line will be the same as the * last restored line. */ - assert(!strcmp(new_first_line.text, split_first_line.text) || - !strcmp(new_first_line.text, restored_last_line.text)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, split_first_line.text) && + strcmp(new_first_line.text, restored_last_line.text), + "Split result invalid", page1, page2)); } else { /* The vmas should be consistent with merge results */ - assert(!strcmp(new_last_line.text, restored_last_line.text) && - !strcmp(new_first_line.text, restored_first_line.text)); + assert(!print_boundaries_on( + strcmp(new_last_line.text, restored_last_line.text), + "Merge result invalid", page1, page2)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, restored_first_line.text), + "Merge result invalid", page1, page2)); } /* * First and last lines should change in unison. If the last @@ -362,7 +470,9 @@ static void test_maps_tearing_from_split(int maps_fd, vma_end =3D=3D split_first_line.end_addr)); =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + end_test_iteration(&end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + end_test_loop(); =20 /* Signal the modifyer thread to stop and wait until it exits */ signal_state(mod_info, TEST_DONE); @@ -409,6 +519,7 @@ static void test_maps_tearing_from_resize(int maps_fd, mod_info->vma_restore =3D expand_vma; mod_info->vma_mod_check =3D check_shrink_result; =20 + report_test_start("Tearing from resize"); capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, &shrunk_last_line, &shrunk_first_line, &restored_last_line, &restored_first_line); @@ -421,6 +532,7 @@ static void test_maps_tearing_from_resize(int maps_fd, struct timespec start_ts, end_ts; =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + start_test_loop(&start_ts); do { unsigned long vma_start; unsigned long vma_end; @@ -437,12 +549,18 @@ static void test_maps_tearing_from_resize(int maps_fd, * again. In that case new first line will be the same * as the last restored line. */ - assert(!strcmp(new_first_line.text, shrunk_first_line.text) || - !strcmp(new_first_line.text, restored_last_line.text)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, shrunk_first_line.text) && + strcmp(new_first_line.text, restored_last_line.text), + "Shrink result invalid", page1, page2)); } else { /* The vmas should be consistent with the original/resored state */ - assert(!strcmp(new_last_line.text, restored_last_line.text) && - !strcmp(new_first_line.text, restored_first_line.text)); + assert(!print_boundaries_on( + strcmp(new_last_line.text, restored_last_line.text), + "Expand result invalid", page1, page2)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, restored_first_line.text), + "Expand result invalid", page1, page2)); } =20 /* Check if PROCMAP_QUERY ioclt() finds the right VMA */ @@ -456,7 +574,9 @@ static void test_maps_tearing_from_resize(int maps_fd, vma_end - vma_start =3D=3D page_size)); =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + end_test_iteration(&end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + end_test_loop(); =20 /* Signal the modifyer thread to stop and wait until it exits */ signal_state(mod_info, TEST_DONE); @@ -512,6 +632,7 @@ static void test_maps_tearing_from_remap(int maps_fd, mod_info->vma_restore =3D patch_vma; mod_info->vma_mod_check =3D check_remap_result; =20 + report_test_start("Tearing from remap"); capture_mod_pattern(maps_fd, mod_info, page1, page2, last_line, first_lin= e, &remapped_last_line, &remapped_first_line, &restored_last_line, &restored_first_line); @@ -524,6 +645,7 @@ static void test_maps_tearing_from_remap(int maps_fd, struct timespec start_ts, end_ts; =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &start_ts); + start_test_loop(&start_ts); do { unsigned long vma_start; unsigned long vma_end; @@ -540,12 +662,18 @@ static void test_maps_tearing_from_remap(int maps_fd, * again. In that case new first line will be the same * as the last restored line. */ - assert(!strcmp(new_first_line.text, remapped_first_line.text) || - !strcmp(new_first_line.text, restored_last_line.text)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, remapped_first_line.text) && + strcmp(new_first_line.text, restored_last_line.text), + "Remap result invalid", page1, page2)); } else { /* The vmas should be consistent with the original/resored state */ - assert(!strcmp(new_last_line.text, restored_last_line.text) && - !strcmp(new_first_line.text, restored_first_line.text)); + assert(!print_boundaries_on( + strcmp(new_last_line.text, restored_last_line.text), + "Remap restore result invalid", page1, page2)); + assert(!print_boundaries_on( + strcmp(new_first_line.text, restored_first_line.text), + "Remap restore result invalid", page1, page2)); } =20 /* Check if PROCMAP_QUERY ioclt() finds the right VMA */ @@ -561,7 +689,9 @@ static void test_maps_tearing_from_remap(int maps_fd, vma_end - vma_start =3D=3D page_size)); =20 clock_gettime(CLOCK_MONOTONIC_COARSE, &end_ts); + end_test_iteration(&end_ts); } while (end_ts.tv_sec - start_ts.tv_sec < test_duration_sec); + end_test_loop(); =20 /* Signal the modifyer thread to stop and wait until it exits */ signal_state(mod_info, TEST_DONE); @@ -571,6 +701,7 @@ int usage(void) { fprintf(stderr, "Userland /proc/pid/{s}maps race test cases\n"); fprintf(stderr, " -d: Duration for time-consuming tests\n"); + fprintf(stderr, " -v: Verbose mode\n"); fprintf(stderr, " -h: Help screen\n"); exit(-1); } @@ -588,9 +719,11 @@ int main(int argc, char **argv) pid_t pid; int opt; =20 - while ((opt =3D getopt(argc, argv, "d:h")) !=3D -1) { + while ((opt =3D getopt(argc, argv, "d:vh")) !=3D -1) { if (opt =3D=3D 'd') test_duration_sec =3D strtoul(optarg, NULL, 0); + else if (opt =3D=3D 'v') + verbose =3D true; else if (opt =3D=3D 'h') usage(); } --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2B55242D79 for ; Fri, 4 Jul 2025 06:07:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609265; cv=none; b=AnDpj9XlSCX6qWzmMEZX94SRKfzHY5VhBqx63vAURfBKz1/CmxxS51FH9+Pn422YJATeaqwNwTwN/pSDL0NQ9CyvYfFOn1sMjorHw4iWHS7NeIQ4gElSN4QWAmfebxyQpOyanLLqNU9021LQjHPg8hWNAm6qXpgPqIb0iPu3QIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609265; c=relaxed/simple; bh=Ckxo6CgOFeLwkg+7L2QC60dmSgMIafJFsZkepFdeJnQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=bHw8e/Gb/wG3ds174mR1tmlhVDFB3ClQQsD+6n4dNS/8o843r+X1DIJy3nIWZbVs+flX8tZfBP4Bk0WV2rGbYAvJh++/GRmScuS08QfIc+GNNvhzbHK6jk3k79mB06B/wFQLb+nx4murkJVa+9kttaF7QjncRtrpGUNqZSCm34E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=pOSeexGj; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="pOSeexGj" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-313fab41f4bso912694a91.0 for ; Thu, 03 Jul 2025 23:07:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609263; x=1752214063; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=h5UIhHsA2QH3v7duxv2jqX5tfGSl+3WijZnkCT/PyKo=; b=pOSeexGjSzNEtzQ3RDxauUjgOnWOxJ82VTNUiJ6eL8erzaEzj2MjtAiGkKrijQLMzZ juaHSK1FjpMK0rf198IqtTuUIzJcaFEltpB+1LMB7QoS3KUlnOL1wTgq96uW8tRaauAZ 626nEYOUf7+j+JeQH3PNXPJOZQuFAGqwTe2stuRSvMT6q0q2lnjX5+U31NQgNP00dtZB XWcx/1fFyXSYXSUvF1VeYTp+BezstZqh+NFaTVFMx/I9Z8nypQ94HUdS2hypqHSKP94F 0ux+8QXwF/VNEe/s4aDxaEBaCh8IzH5fvUpOawyNzYRbuBiW8UtqGmqg/D+kwqqYEiPF l/2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609263; x=1752214063; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=h5UIhHsA2QH3v7duxv2jqX5tfGSl+3WijZnkCT/PyKo=; b=UVua8BpSwm/+FfuZA21qIh6ChOpOmjYPR5XGzlNf/MviN/pudQJVJ6t5ySIlQPGb/Q tDZA6OaVq23Hfljf7+sgWdwa1bVX70FwnLXEQob0LLkusFdS+iaXTC1UpMiRC55z402M IQphkX+kZZAkxmVHBykqy5WQxGAVdsfGjornNIDxoj16ZrUJNswEddZqDcA9AJR/0cLG lGnx5Jvp3UooM4jjnCLJAcIQdxWxseZPVEulEEITRbnEBUe2NF8tc+GNiQEhFoJn1PuX 23fgJeAV2Aj94U50GO9JL8J3R7eKQfImfM0ErNQ/PicPmqQJFlBx592m4GKxMGKIgfG7 OLrA== X-Forwarded-Encrypted: i=1; AJvYcCXx0KIN4twBimH3Hs+0CKOOb+HZlvc4OHm3lRZLnqw0WsAMYHKr7VEeDKxJrJCLgO2irio1zvqtzDOboKE=@vger.kernel.org X-Gm-Message-State: AOJu0Yy/ABEJLdMrsxA69pu0i/LFrnKx/2nU4g3tGgI9Y9+ygiUKrBZ2 qIcn2uffD7NKfcJTQKWQR9a/DEPiKhQ28txjIhkbaetPNOlj+CYOcs8K1iVbTrsj3BSZHUjemXm zkLIl+g== X-Google-Smtp-Source: AGHT+IGb1KdAzn5YP1WDTyP0Cp9f49AuhUCkK4JgigY7PefACgEs5tH7aIbj4XAEANijeDnY8cuDukZytlM= X-Received: from pjtd10.prod.google.com ([2002:a17:90b:4a:b0:311:c197:70a4]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2702:b0:314:2939:efdc with SMTP id 98e67ed59e1d1-31aac44a392mr2310092a91.13.1751609263074; Thu, 03 Jul 2025 23:07:43 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:24 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-7-surenb@google.com> Subject: [PATCH v6 6/8] fs/proc/task_mmu: remove conversion of seq_file position to unsigned From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Back in 2.6 era, last_addr used to be stored in seq_file->version variable, which was unsigned long. As a result, sentinels to represent gate vma and end of all vmas used unsigned values. In more recent kernels we don't used seq_file->version anymore and therefore conversion from loff_t into unsigned type is not needed. Similarly, sentinel values don't need to be unsigned. Remove type conversion for set_file position and change sentinel values to signed. Signed-off-by: Suren Baghdasaryan Reviewed-by: Lorenzo Stoakes Reviewed-by: Vlastimil Babka --- fs/proc/task_mmu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 751479eb128f..b8bc06d05a72 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -135,7 +135,7 @@ static struct vm_area_struct *proc_get_vma(struct proc_= maps_private *priv, if (vma) { *ppos =3D vma->vm_start; } else { - *ppos =3D -2UL; + *ppos =3D -2; vma =3D get_gate_vma(priv->mm); } =20 @@ -145,11 +145,11 @@ static struct vm_area_struct *proc_get_vma(struct pro= c_maps_private *priv, static void *m_start(struct seq_file *m, loff_t *ppos) { struct proc_maps_private *priv =3D m->private; - unsigned long last_addr =3D *ppos; + loff_t last_addr =3D *ppos; struct mm_struct *mm; =20 /* See m_next(). Zero at the start or after lseek. */ - if (last_addr =3D=3D -1UL) + if (last_addr =3D=3D -1) return NULL; =20 priv->task =3D get_proc_task(priv->inode); @@ -170,9 +170,9 @@ static void *m_start(struct seq_file *m, loff_t *ppos) return ERR_PTR(-EINTR); } =20 - vma_iter_init(&priv->iter, mm, last_addr); + vma_iter_init(&priv->iter, mm, (unsigned long)last_addr); hold_task_mempolicy(priv); - if (last_addr =3D=3D -2UL) + if (last_addr =3D=3D -2) return get_gate_vma(mm); =20 return proc_get_vma(priv, ppos); @@ -180,8 +180,8 @@ static void *m_start(struct seq_file *m, loff_t *ppos) =20 static void *m_next(struct seq_file *m, void *v, loff_t *ppos) { - if (*ppos =3D=3D -2UL) { - *ppos =3D -1UL; + if (*ppos =3D=3D -2) { + *ppos =3D -1; return NULL; } return proc_get_vma(m->private, ppos); --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02365222561 for ; Fri, 4 Jul 2025 06:07:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609267; cv=none; b=bbLfzOt5fVqqnXci6j2iiGjpmg2wdOiHIbvrGuhjZZTI2d8IMced44OpA+FM0XcfKun6BLFMfVjy5+g7rf6Cbs5eF6VtyQ3d0jJmXzf9VjPQtilfy5OsltXbnZrQZZ7Egl0DOq5T/+OlLr1Jl+rnu1QwFINz/gUctUkkda2Ca2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609267; c=relaxed/simple; bh=ldcFF1mghDA07EpAp/w0hayCexC2/uagTVEfPtokacg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XFKj2BMQVT1HbpG2cKZWXVE5/teUZ7fNtQUkUFbQYEzM5mI78aJR3QDNjBVnaKemixy+ayHfN0WD0OjLxuduxp2bOIaqyBN8Tv8PNYbUBhwrZw8SRhr1m9x7wTos7UjHRn3dxkTMz96QWZB/7kDdLPH/hVH2OIve7Vthdg1QcLA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=XI80Qrkd; arc=none smtp.client-ip=209.85.210.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="XI80Qrkd" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-74ce2491c0fso937667b3a.0 for ; Thu, 03 Jul 2025 23:07:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609265; x=1752214065; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=V87ghHwj2x/F08cA4iUlHoTxBegCjR03gbXdVLHzhkQ=; b=XI80Qrkd+t5+RRZzxlJXAb1SpowpB2XBtKtqRI4lmw8GsSeF1mO1cyv9lb3mie3cy5 IDXGZ+0UQRDsDU70E3iBGVbfdjwDnrpJr/f4Ct0mymKZt61kAUHyaip/3/0Syzhg0I6J +IRhLgMMM2InQDEtt/Mv7Fk6Brnmq09OXRw3EoiUUQ4qP7aBIFi2fi/Ly0/22gMaQr1J PHLp6VbaPweAtkgg2xv8HDNEd6akxTUSVoW4P9rHGhuUPPj5UcgUBw+WkPWaif93dctg Iz97Srbt81M/1ewwdN3TjuQHcCNEJQrkGcRidRdtS50GADHto3XkEM+utR/dofcWWTtH Hxjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609265; x=1752214065; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=V87ghHwj2x/F08cA4iUlHoTxBegCjR03gbXdVLHzhkQ=; b=dnLSLMvC+MGqOI0YIQYFAbWEm233StBRSk4uZosAiqg30KKVUGSrVnJcK0OtNZtUTe gFUh3sGt5c3JwOA25lbPJPJ46B2yIUkUByYMNgPN4vuftNxgIKRSq6O4TQmvXia8osLT GtHs2viAU4ucJAoo0nRZm5os71/vFmukiKfT7dD5oNm90IMFHPDthWbZriOW3RiSifXQ 9OJSc4jwUUlpCc2sfUYRF4yRyTSQUkF9L0RU/+jJeyxXYTBUN+xkAq9IKO8Z6vWVH9EZ fEGlQ4ia2/5pJAx3QgBiG1uin7iI9jQ+9mWxA94Q5diCND6ivxR3vCWZwAw876xiOBQ4 mpcg== X-Forwarded-Encrypted: i=1; AJvYcCXKVAxwtZGUa86mmvDOLP5B52K4ojeT7DaaINb/aF3oIIRi8wAB7Y6qEg+g2+dAFbhIVWTalx9sQEl7DLs=@vger.kernel.org X-Gm-Message-State: AOJu0YyAUIDrSiLalO6ieY1YCeaZJOirXBtXY97cege0EIRwww5PkVzk JRMjpe6pEMw9YuBLef7L4RreVIPmkdkmNaSLWWlDneodRIF4vT5B+n/xp/eCwwbxS1U33DGwXqE UPSwdww== X-Google-Smtp-Source: AGHT+IHa4YAEN8ymTNIzYo1RkEc+q9IqwmzCpnw8Sx/y3o7WA6jQRp5CcMpLhh5Oi7FcyNjv7oAKTzvc1WM= X-Received: from pfbfc40.prod.google.com ([2002:a05:6a00:2e28:b0:746:fd4c:1fcf]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:4fc9:b0:748:f406:b09 with SMTP id d2e1a72fcca58-74ce6a6e9b6mr2178587b3a.23.1751609265125; Thu, 03 Jul 2025 23:07:45 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:25 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-8-surenb@google.com> Subject: [PATCH v6 7/8] fs/proc/task_mmu: read proc/pid/maps under per-vma lock From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With maple_tree supporting vma tree traversal under RCU and per-vma locks, /proc/pid/maps can be read while holding individual vma locks instead of locking the entire address space. Completely lockless approach (walking vma tree under RCU) would be quite complex with the main issue being get_vma_name() using callbacks which might not work correctly with a stable vma copy, requiring original (unstable) vma - see special_mapping_name() for an example. When per-vma lock acquisition fails, we take the mmap_lock for reading, lock the vma, release the mmap_lock and continue. This fallback to mmap read lock guarantees the reader to make forward progress even during lock contention. This will interfere with the writer but for a very short time while we are acquiring the per-vma lock and only when there was contention on the vma reader is interested in. We shouldn't see a repeated fallback to mmap read locks in practice, as this require a very unlikely series of lock contentions (for instance due to repeated vma split operations). However even if this did somehow happen, we would still progress. One case requiring special handling is when vma changes between the time it was found and the time it got locked. A problematic case would be if vma got shrunk so that it's start moved higher in the address space and a new vma was installed at the beginning: reader found: |--------VMA A--------| VMA is modified: |-VMA B-|----VMA A----| reader locks modified VMA A reader reports VMA A: | gap |----VMA A----| This would result in reporting a gap in the address space that does not exist. To prevent this we retry the lookup after locking the vma, however we do that only when we identify a gap and detect that the address space was changed after we found the vma. This change is designed to reduce mmap_lock contention and prevent a process reading /proc/pid/maps files (often a low priority task, such as monitoring/data collection services) from blocking address space updates. Note that this change has a userspace visible disadvantage: it allows for sub-page data tearing as opposed to the previous mechanism where data tearing could happen only between pages of generated output data. Since current userspace considers data tearing between pages to be acceptable, we assume is will be able to handle sub-page data tearing as well. Signed-off-by: Suren Baghdasaryan Reviewed-by: Liam R. Howlett Reviewed-by: Lorenzo Stoakes --- fs/proc/internal.h | 5 ++ fs/proc/task_mmu.c | 118 ++++++++++++++++++++++++++++++++++---- include/linux/mmap_lock.h | 11 ++++ mm/madvise.c | 3 +- mm/mmap_lock.c | 88 ++++++++++++++++++++++++++++ 5 files changed, 214 insertions(+), 11 deletions(-) diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 3d48ffe72583..7c235451c5ea 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -384,6 +384,11 @@ struct proc_maps_private { struct task_struct *task; struct mm_struct *mm; struct vma_iterator iter; + loff_t last_pos; +#ifdef CONFIG_PER_VMA_LOCK + bool mmap_locked; + struct vm_area_struct *locked_vma; +#endif #ifdef CONFIG_NUMA struct mempolicy *task_mempolicy; #endif diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index b8bc06d05a72..ff3fe488ce51 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -127,15 +127,107 @@ static void release_task_mempolicy(struct proc_maps_= private *priv) } #endif =20 -static struct vm_area_struct *proc_get_vma(struct proc_maps_private *priv, - loff_t *ppos) +#ifdef CONFIG_PER_VMA_LOCK + +static void unlock_vma(struct proc_maps_private *priv) +{ + if (priv->locked_vma) { + vma_end_read(priv->locked_vma); + priv->locked_vma =3D NULL; + } +} + +static const struct seq_operations proc_pid_maps_op; + +static inline bool lock_vma_range(struct seq_file *m, + struct proc_maps_private *priv) +{ + /* + * smaps and numa_maps perform page table walk, therefore require + * mmap_lock but maps can be read with locking just the vma. + */ + if (m->op !=3D &proc_pid_maps_op) { + if (mmap_read_lock_killable(priv->mm)) + return false; + + priv->mmap_locked =3D true; + } else { + rcu_read_lock(); + priv->locked_vma =3D NULL; + priv->mmap_locked =3D false; + } + + return true; +} + +static inline void unlock_vma_range(struct proc_maps_private *priv) +{ + if (priv->mmap_locked) { + mmap_read_unlock(priv->mm); + } else { + unlock_vma(priv); + rcu_read_unlock(); + } +} + +static struct vm_area_struct *get_next_vma(struct proc_maps_private *priv, + loff_t last_pos) +{ + struct vm_area_struct *vma; + + if (priv->mmap_locked) + return vma_next(&priv->iter); + + unlock_vma(priv); + vma =3D lock_next_vma(priv->mm, &priv->iter, last_pos); + if (!IS_ERR_OR_NULL(vma)) + priv->locked_vma =3D vma; + + return vma; +} + +#else /* CONFIG_PER_VMA_LOCK */ + +static inline bool lock_vma_range(struct seq_file *m, + struct proc_maps_private *priv) { - struct vm_area_struct *vma =3D vma_next(&priv->iter); + return mmap_read_lock_killable(priv->mm) =3D=3D 0; +} + +static inline void unlock_vma_range(struct proc_maps_private *priv) +{ + mmap_read_unlock(priv->mm); +} + +static struct vm_area_struct *get_next_vma(struct proc_maps_private *priv, + loff_t last_pos) +{ + return vma_next(&priv->iter); +} =20 +#endif /* CONFIG_PER_VMA_LOCK */ + +static struct vm_area_struct *proc_get_vma(struct seq_file *m, loff_t *ppo= s) +{ + struct proc_maps_private *priv =3D m->private; + struct vm_area_struct *vma; + + vma =3D get_next_vma(priv, *ppos); + /* EINTR is possible */ + if (IS_ERR(vma)) + return vma; + + /* Store previous position to be able to restart if needed */ + priv->last_pos =3D *ppos; if (vma) { - *ppos =3D vma->vm_start; + /* + * Track the end of the reported vma to ensure position changes + * even if previous vma was merged with the next vma and we + * found the extended vma with the same vm_start. + */ + *ppos =3D vma->vm_end; } else { - *ppos =3D -2; + *ppos =3D -2; /* -2 indicates gate vma */ vma =3D get_gate_vma(priv->mm); } =20 @@ -163,28 +255,34 @@ static void *m_start(struct seq_file *m, loff_t *ppos) return NULL; } =20 - if (mmap_read_lock_killable(mm)) { + if (!lock_vma_range(m, priv)) { mmput(mm); put_task_struct(priv->task); priv->task =3D NULL; return ERR_PTR(-EINTR); } =20 + /* + * Reset current position if last_addr was set before + * and it's not a sentinel. + */ + if (last_addr > 0) + *ppos =3D last_addr =3D priv->last_pos; vma_iter_init(&priv->iter, mm, (unsigned long)last_addr); hold_task_mempolicy(priv); if (last_addr =3D=3D -2) return get_gate_vma(mm); =20 - return proc_get_vma(priv, ppos); + return proc_get_vma(m, ppos); } =20 static void *m_next(struct seq_file *m, void *v, loff_t *ppos) { if (*ppos =3D=3D -2) { - *ppos =3D -1; + *ppos =3D -1; /* -1 indicates no more vmas */ return NULL; } - return proc_get_vma(m->private, ppos); + return proc_get_vma(m, ppos); } =20 static void m_stop(struct seq_file *m, void *v) @@ -196,7 +294,7 @@ static void m_stop(struct seq_file *m, void *v) return; =20 release_task_mempolicy(priv); - mmap_read_unlock(mm); + unlock_vma_range(priv); mmput(mm); put_task_struct(priv->task); priv->task =3D NULL; diff --git a/include/linux/mmap_lock.h b/include/linux/mmap_lock.h index 5da384bd0a26..1f4f44951abe 100644 --- a/include/linux/mmap_lock.h +++ b/include/linux/mmap_lock.h @@ -309,6 +309,17 @@ void vma_mark_detached(struct vm_area_struct *vma); struct vm_area_struct *lock_vma_under_rcu(struct mm_struct *mm, unsigned long address); =20 +/* + * Locks next vma pointed by the iterator. Confirms the locked vma has not + * been modified and will retry under mmap_lock protection if modification + * was detected. Should be called from read RCU section. + * Returns either a valid locked VMA, NULL if no more VMAs or -EINTR if the + * process was interrupted. + */ +struct vm_area_struct *lock_next_vma(struct mm_struct *mm, + struct vma_iterator *iter, + unsigned long address); + #else /* CONFIG_PER_VMA_LOCK */ =20 static inline void mm_lock_seqcount_init(struct mm_struct *mm) {} diff --git a/mm/madvise.c b/mm/madvise.c index a34c2c89a53b..e61e32b2cd91 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -108,7 +108,8 @@ void anon_vma_name_free(struct kref *kref) =20 struct anon_vma_name *anon_vma_name(struct vm_area_struct *vma) { - mmap_assert_locked(vma->vm_mm); + if (!rwsem_is_locked(&vma->vm_mm->mmap_lock)) + vma_assert_locked(vma); =20 return vma->anon_name; } diff --git a/mm/mmap_lock.c b/mm/mmap_lock.c index 5f725cc67334..ed0e5e2171cd 100644 --- a/mm/mmap_lock.c +++ b/mm/mmap_lock.c @@ -178,6 +178,94 @@ struct vm_area_struct *lock_vma_under_rcu(struct mm_st= ruct *mm, count_vm_vma_lock_event(VMA_LOCK_ABORT); return NULL; } + +static struct vm_area_struct *lock_vma_under_mmap_lock(struct mm_struct *m= m, + struct vma_iterator *iter, + unsigned long address) +{ + struct vm_area_struct *vma; + int ret; + + ret =3D mmap_read_lock_killable(mm); + if (ret) + return ERR_PTR(ret); + + /* Lookup the vma at the last position again under mmap_read_lock */ + vma_iter_init(iter, mm, address); + vma =3D vma_next(iter); + if (vma) + vma_start_read_locked(vma); + + mmap_read_unlock(mm); + + return vma; +} + +struct vm_area_struct *lock_next_vma(struct mm_struct *mm, + struct vma_iterator *iter, + unsigned long address) +{ + struct vm_area_struct *vma; + unsigned int mm_wr_seq; + bool mmap_unlocked; + + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "no rcu read lock held"); +retry: + /* Start mmap_lock speculation in case we need to verify the vma later */ + mmap_unlocked =3D mmap_lock_speculate_try_begin(mm, &mm_wr_seq); + vma =3D vma_next(iter); + if (!vma) + return NULL; + + vma =3D vma_start_read(mm, vma); + + if (IS_ERR_OR_NULL(vma)) { + /* + * Retry immediately if the vma gets detached from under us. + * Infinite loop should not happen because the vma we find will + * have to be constantly knocked out from under us. + */ + if (PTR_ERR(vma) =3D=3D -EAGAIN) { + vma_iter_init(iter, mm, address); + goto retry; + } + + goto out; + } + + /* + * Verify the vma we locked belongs to the same address space and it's + * not behind of the last search position. + */ + if (unlikely(vma->vm_mm !=3D mm || address >=3D vma->vm_end)) + goto out_unlock; + + /* + * vma can be ahead of the last search position but we need to verify + * it was not shrunk after we found it and another vma has not been + * installed ahead of it. Otherwise we might observe a gap that should + * not be there. + */ + if (address < vma->vm_start) { + /* Verify only if the address space might have changed since vma lookup.= */ + if (!mmap_unlocked || mmap_lock_speculate_retry(mm, mm_wr_seq)) { + vma_iter_init(iter, mm, address); + if (vma !=3D vma_next(iter)) + goto out_unlock; + } + } + + return vma; + +out_unlock: + vma_end_read(vma); +out: + rcu_read_unlock(); + vma =3D lock_vma_under_mmap_lock(mm, iter, address); + rcu_read_lock(); + + return vma; +} #endif /* CONFIG_PER_VMA_LOCK */ =20 #ifdef CONFIG_LOCK_MM_AND_FIND_VMA --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 22:53:22 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44E33223DF0 for ; Fri, 4 Jul 2025 06:07:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609269; cv=none; b=QKNVr37vVgOkbNSFgdofqGavNOFrTfAyXo5GcPyhUqvFEZFz9IHnsFlRWcxjKuYUCwaB1r7rLucx9IJBI5XO957YS33nXf3LKuorhPJcNmDKk8i6nscCqEIuT1JXPxDsY46mPQPqMlx0DL7PKPC4bSbM01iIizhG2G2pcicZqRM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751609269; c=relaxed/simple; bh=GVjaIfP3+dNOMqyxREilBSvkaK3Gx5u4JJ4xi47FD70=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=BJEoBEdm4cZ7L0dgBf3a0o67mxvaprD8GX6QPvWtBpqu41QCP6bTHP9ypeAZGphqd2oHvN69r4RCVNnHovwyWLe9EiIAZYAHdMO9xUgWJuqimkVAj8giGNx0iP3dslFds/xnzjhz+llbdsE9vN6M9xhjeh1+EPjfZtbxWlqXbmc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Xh6vLH/s; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--surenb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Xh6vLH/s" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-747ddba7c90so513117b3a.0 for ; Thu, 03 Jul 2025 23:07:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1751609267; x=1752214067; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=2vVO5jxx/ZJrgheBL7RPOjE/kXWGqgLicQNUNDfyGkA=; b=Xh6vLH/sg5bApKW5O+yFJNSR0Abp8YRJNBuAQkeSGKOxuvU9ZOyqqi+YwBkF7tVhy2 Eb9IWYQTOTnV72EVrcNGhOkmXKO02lsJdLHY+i9i6me6z6+CvGW6w3tEo1YyTokwCmKh LCTPWbBT8ngpnuOv8NR47Y7zgJsvbhemwV0VjWa8Gc7GFqlBPjN5pl1UsFgVx8oGl4I3 e1hTEH9QthLWYWnWr7o6OCzXWPuM2LGJjrTaKGBy5A8DiiOQmM6xS35bKQZ+bGA5JW99 WchrVmOyC2DDQWDnREhz4beYygqDqbWPVlJIbvQpYFijhxoebdn82fKDhn6bHPgdIMon qRsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751609267; x=1752214067; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=2vVO5jxx/ZJrgheBL7RPOjE/kXWGqgLicQNUNDfyGkA=; b=THQKXb2Y3OClydopKwrO/Ewz2IoTNXt2J006KeDFb+R3h5U/tNNU1zpHOp/24bLPt2 ccsJMtwcumYsapGFVCWpA11ZSYekl3rZNn5FkfUmf8hmKIHFEZqD9SIETrCevWk7PX3P zndtN9FMy/a5WN33ou2gUkXssWoE2GFictbQjpZkPWEAlLmC9V8LRLAhg+36KCTXDjZr fNERUU4Qwxp+mPc84TGW+sLZBpT21nHfz5Hxwap9SlKeFgGq/+lEOCRj8NSimQZ+KYbI 5tkphr0Oxp0P86GQ9vxRvAF68pgM1NBWxgpe2+CLXbKyKuNXt9pFZoENYij7mTebkpsI s4/Q== X-Forwarded-Encrypted: i=1; AJvYcCUMi7uRZro8Z8cRI1FpafQ8y+3IV89KomI6C3UGs9uUj25gWVcSLpa3GvGvRmZK/yhYth6yhh3HfLgTklY=@vger.kernel.org X-Gm-Message-State: AOJu0YxVCwJ3y6Gp86Nx/WI5BsXGR3nhTHxNnnP8JwhgYVMvlxEOLQJT tUgmoyQ1PCjV95q4YwCv3AUMVZgrND0x6lVfvnmTR94QkbRnPmr9viAqks0CgMX5/33JpaGemo7 zIbWH1g== X-Google-Smtp-Source: AGHT+IGK2PS7F/Js/FFS6q/dLVUjbaZBo7PGzhlpQvuYSYZ/AxLr1RaHAdn4y2306pdsG4prKULLG7rLEWE= X-Received: from pftb16.prod.google.com ([2002:a05:6a00:2d0:b0:746:3185:144e]) (user=surenb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:3c8b:b0:748:3485:b99d with SMTP id d2e1a72fcca58-74ce65c53bamr2551001b3a.18.1751609267282; Thu, 03 Jul 2025 23:07:47 -0700 (PDT) Date: Thu, 3 Jul 2025 23:07:26 -0700 In-Reply-To: <20250704060727.724817-1-surenb@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250704060727.724817-1-surenb@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250704060727.724817-9-surenb@google.com> Subject: [PATCH v6 8/8] fs/proc/task_mmu: execute PROCMAP_QUERY ioctl under per-vma locks From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: Liam.Howlett@oracle.com, lorenzo.stoakes@oracle.com, david@redhat.com, vbabka@suse.cz, peterx@redhat.com, jannh@google.com, hannes@cmpxchg.org, mhocko@kernel.org, paulmck@kernel.org, shuah@kernel.org, adobriyan@gmail.com, brauner@kernel.org, josef@toxicpanda.com, yebin10@huawei.com, linux@weissschuh.net, willy@infradead.org, osalvador@suse.de, andrii@kernel.org, ryan.roberts@arm.com, christophe.leroy@csgroup.eu, tjmercier@google.com, kaleshsingh@google.com, aha310510@gmail.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, surenb@google.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Utilize per-vma locks to stabilize vma after lookup without taking mmap_lock during PROCMAP_QUERY ioctl execution. While we might take mmap_lock for reading during contention, we do that momentarily only to lock the vma. This change is designed to reduce mmap_lock contention and prevent PROCMAP_QUERY ioctl calls from blocking address space updates. Signed-off-by: Suren Baghdasaryan Acked-by: Andrii Nakryiko Reviewed-by: Liam R. Howlett Reviewed-by: Lorenzo Stoakes --- fs/proc/task_mmu.c | 60 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index ff3fe488ce51..0496d5969a51 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -487,28 +487,64 @@ static int pid_maps_open(struct inode *inode, struct = file *file) PROCMAP_QUERY_VMA_FLAGS \ ) =20 -static int query_vma_setup(struct mm_struct *mm) +#ifdef CONFIG_PER_VMA_LOCK + +static int query_vma_setup(struct proc_maps_private *priv) { - return mmap_read_lock_killable(mm); + priv->locked_vma =3D NULL; + priv->mmap_locked =3D false; + + return 0; } =20 -static void query_vma_teardown(struct mm_struct *mm, struct vm_area_struct= *vma) +static void query_vma_teardown(struct proc_maps_private *priv) { - mmap_read_unlock(mm); + unlock_vma(priv); +} + +static struct vm_area_struct *query_vma_find_by_addr(struct proc_maps_priv= ate *priv, + unsigned long addr) +{ + struct vm_area_struct *vma; + + rcu_read_lock(); + vma_iter_init(&priv->iter, priv->mm, addr); + vma =3D get_next_vma(priv, addr); + rcu_read_unlock(); + + return vma; } =20 -static struct vm_area_struct *query_vma_find_by_addr(struct mm_struct *mm,= unsigned long addr) +#else /* CONFIG_PER_VMA_LOCK */ + +static int query_vma_setup(struct proc_maps_private *priv) { - return find_vma(mm, addr); + return mmap_read_lock_killable(priv->mm); } =20 -static struct vm_area_struct *query_matching_vma(struct mm_struct *mm, +static void query_vma_teardown(struct proc_maps_private *priv) +{ + mmap_read_unlock(priv->mm); +} + +static struct vm_area_struct *query_vma_find_by_addr(struct proc_maps_priv= ate *priv, + unsigned long addr) +{ + return find_vma(priv->mm, addr); +} + +#endif /* CONFIG_PER_VMA_LOCK */ + +static struct vm_area_struct *query_matching_vma(struct proc_maps_private = *priv, unsigned long addr, u32 flags) { struct vm_area_struct *vma; =20 next_vma: - vma =3D query_vma_find_by_addr(mm, addr); + vma =3D query_vma_find_by_addr(priv, addr); + if (IS_ERR(vma)) + return vma; + if (!vma) goto no_vma; =20 @@ -584,13 +620,13 @@ static int do_procmap_query(struct proc_maps_private = *priv, void __user *uarg) if (!mm || !mmget_not_zero(mm)) return -ESRCH; =20 - err =3D query_vma_setup(mm); + err =3D query_vma_setup(priv); if (err) { mmput(mm); return err; } =20 - vma =3D query_matching_vma(mm, karg.query_addr, karg.query_flags); + vma =3D query_matching_vma(priv, karg.query_addr, karg.query_flags); if (IS_ERR(vma)) { err =3D PTR_ERR(vma); vma =3D NULL; @@ -675,7 +711,7 @@ static int do_procmap_query(struct proc_maps_private *p= riv, void __user *uarg) } =20 /* unlock vma or mmap_lock, and put mm_struct before copying data to user= */ - query_vma_teardown(mm, vma); + query_vma_teardown(priv); mmput(mm); =20 if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr= ), @@ -695,7 +731,7 @@ static int do_procmap_query(struct proc_maps_private *p= riv, void __user *uarg) return 0; =20 out: - query_vma_teardown(mm, vma); + query_vma_teardown(priv); mmput(mm); kfree(name_buf); return err; --=20 2.50.0.727.gbf7dc18ff4-goog