Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp817238iob; Wed, 18 May 2022 13:44:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx5Wlp6dbXMI1+fCwyul55D+qBkAj2RAajXxGItuCh33WuWo9mIZuYelVf7sVwivi4nbjCX X-Received: by 2002:a17:902:f544:b0:161:9465:4421 with SMTP id h4-20020a170902f54400b0016194654421mr1387317plf.90.1652906680203; Wed, 18 May 2022 13:44:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652906680; cv=none; d=google.com; s=arc-20160816; b=tawb2jFpf7pCu9js8652UubQlAYXuVwOwlXiH0Wq7eiYF1xFavpIMz7sPq6LWj65dC lSr5IQFYKXV2pe5BgkOV1vOvpfqxS2+H+I+S3aBiNO+sW1UjsUY28Bk5t1xI3mgPja+v 759yvuSvauPMLEfUFWunriF3ijCdS6Nbd0bWkndksDbqM0ToLIhGGajserPc0K4Hu0Gr MWE3JTQj86m4ncYFo55fJ1PQpYizeNsIJdUBvuX0JQssSFWJGtBBSGN7uXZsW8MGBFW5 EsgWCTV6F8tHWOizg85hCOihIlIOTlI2ledwDySgzDNMKH2bZO+6HQSxNKUc6RgivlGF 9NLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:mime-version:message-id:date :dkim-signature; bh=CIr61HKlKWK8BgnDg7ZLMPTf6+BKTF/FV6epAVcSa/k=; b=ZEAHYJDieMwFrFq1OylnlJ/ulzQVS6F9b7JmIqyei64OB414tlQraAVvjqpP/lEsBv m8oRIRlcCso40LJzL1XLfc/hPo8vKHQxZq1LUVmod+RFrtXyf8MZNwg/AK/FKlRp5Bau JaWGER6psnPsamDrLhWBN+D5lnMp9e3incglRs4BnKALJAq05UGf6ZX3fc4BU3Ibw7We CFf6Kuf/qaw+QTraYUAyfdaSLSHMWnc4hW/KcDdxYDJzfFPktKqXS7r1SEW0LW3DRQkF BrXT8ibZ+JjASDEgYpMklmaTBmYJO2yLSreupjNtupBmITRxOsniHM/tIXkvgxEdE1u7 +yOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=oYScb9Tq; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id h17-20020a056a001a5100b0050e0d6d4019si4622438pfv.32.2022.05.18.13.44.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 May 2022 13:44:40 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=oYScb9Tq; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DED72104C83; Wed, 18 May 2022 13:43:52 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242734AbiERUnq (ORCPT + 99 others); Wed, 18 May 2022 16:43:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242772AbiERUn1 (ORCPT ); Wed, 18 May 2022 16:43:27 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68CCEA7E01 for ; Wed, 18 May 2022 13:43:21 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-2fed274f3fbso28527967b3.17 for ; Wed, 18 May 2022 13:43:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=CIr61HKlKWK8BgnDg7ZLMPTf6+BKTF/FV6epAVcSa/k=; b=oYScb9Tq2re7Q+570vAn+FAY8dEW4InJb7V4G9TlPme9NIh3kl07+hORXd26OP+Chm OevTtOQn+3PsbvIrUopd3zcgARQkqbwjk9KXW3IsJMVvFDBQDFoD/PGQpL3cbQ8QlOdz V6DTJvuRtqXPEZe792a+eemEvz4FdT9EA1CN7cc0CV1yjCOFqr2WkG1SJNXS08xTKatb +1WPUkJxRNzFuoGTcUlVWwvJyS16KxlSPB7mQbOQZlTb+8IqYBxi2f+Wc1bjUFDeQaFq HVztWTipQgBqjSOSLslEomu+FRtnfBD1C01yjYlIt2bQ2KlFCBPD1lxi2/b7W1c+lDSP qdMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=CIr61HKlKWK8BgnDg7ZLMPTf6+BKTF/FV6epAVcSa/k=; b=1k1HrzdEEg9g3ahp9QYrtep3JAzvkCQNNmoalGz3AzSul2TcFBGS3NkHEEl0E7nfts 4NW3ezHghOD3zk77xXiFo2xrnc5lT0pM/ISGQAji4CI10S10DAdAidSxifX3E+OG0HeN pEFq28oP5mvn4aFHYyr7mKE5RAj9p9ekV24OEDwz/YE8fOZNuvilLcLzkR+f1sjOzz2u Z9Z4riu1e6ispqbZrL8ZeLicO0nWRGG3tDfxbQ7EDJkt/gvEyuunI7O4MId+e51usjB5 V0Hrqm1/IvpCoUXHsytnWOhRZjK/r640u4O+DSUIfMR/5f6+7mHVxoXc3P852K7QFEbW LidQ== X-Gm-Message-State: AOAM5319trgDIyKkxGxVNJPKdulbjZvmhMqv33YdHyfqfm/Z0uRq3N3V cFu9Gzy3oftF5MGvY/FNA4lQSXmPwBc= X-Received: from surenb-desktop.mtv.corp.google.com ([2620:15c:211:200:88b3:2be3:5f71:58e2]) (user=surenb job=sendgmr) by 2002:a25:d312:0:b0:64d:74b9:5caa with SMTP id e18-20020a25d312000000b0064d74b95caamr1476152ybf.37.1652906600500; Wed, 18 May 2022 13:43:20 -0700 (PDT) Date: Wed, 18 May 2022 13:43:16 -0700 Message-Id: <20220518204316.13131-1-surenb@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [PATCH v3 1/1] selftests: vm: add process_mrelease tests From: Suren Baghdasaryan To: akpm@linux-foundation.org Cc: mhocko@suse.com, rientjes@google.com, willy@infradead.org, hannes@cmpxchg.org, guro@fb.com, minchan@kernel.org, kirill@shutemov.name, aarcange@redhat.com, brauner@kernel.org, hch@infradead.org, oleg@redhat.com, david@redhat.com, jannh@google.com, shakeelb@google.com, peterx@redhat.com, jhubbard@nvidia.com, shuah@kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, kernel-team@android.com, surenb@google.com Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Introduce process_mrelease syscall sanity tests which include tests which expect to fail: - process_mrelease with invalid pidfd and flags inputs - process_mrelease on a live process with no pending signals and valid process_mrelease usage which is expected to succeed. Because process_mrelease has to be used against a process with a pending SIGKILL, it's possible that the process exits before process_mrelease gets called. In such cases we retry the test with a victim that allocates twice more memory up to 1GB. This would require the victim process to spend more time during exit and process_mrelease has a better chance of catching the process before it exits and succeeding. On success the test reports the amount of memory the child had to allocate for reaping to succeed. Sample output: $ mrelease_test Success reaping a child with 1MB of memory allocations On failure the test reports the failure. Sample outputs: $ mrelease_test All process_mrelease attempts failed! $ mrelease_test process_mrelease: Invalid argument Signed-off-by: Suren Baghdasaryan --- Changes in v3: - Applied on git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm mm-stable, per Andrew - Fixed formatting for sample outputs in the description, per Shuah - Removed pidfd_open, process_mrelease, write_fault_pages functions, per Shuah - Moved child main routine into its own function, per Shuah - Followed tools/testing/selftests/pidfd/pidfd.h as a model to deal with undefined syscall numbers, per Shuah tools/testing/selftests/vm/.gitignore | 1 + tools/testing/selftests/vm/Makefile | 1 + tools/testing/selftests/vm/mrelease_test.c | 200 +++++++++++++++++++++ tools/testing/selftests/vm/run_vmtests.sh | 2 + 4 files changed, 204 insertions(+) create mode 100644 tools/testing/selftests/vm/mrelease_test.c diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore index 3cb4fa771ec2..6c2ac4208c27 100644 --- a/tools/testing/selftests/vm/.gitignore +++ b/tools/testing/selftests/vm/.gitignore @@ -10,6 +10,7 @@ map_populate thuge-gen compaction_test mlock2-tests +mrelease_test mremap_dontunmap mremap_test on-fault-limit diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile index f1228370e99b..8111a33e4824 100644 --- a/tools/testing/selftests/vm/Makefile +++ b/tools/testing/selftests/vm/Makefile @@ -44,6 +44,7 @@ TEST_GEN_FILES += memfd_secret TEST_GEN_FILES += migration TEST_GEN_FILES += mlock-random-test TEST_GEN_FILES += mlock2-tests +TEST_GEN_FILES += mrelease_test TEST_GEN_FILES += mremap_dontunmap TEST_GEN_FILES += mremap_test TEST_GEN_FILES += on-fault-limit diff --git a/tools/testing/selftests/vm/mrelease_test.c b/tools/testing/selftests/vm/mrelease_test.c new file mode 100644 index 000000000000..96671c2f7d48 --- /dev/null +++ b/tools/testing/selftests/vm/mrelease_test.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 Google LLC + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "util.h" + +#include "../kselftest.h" + +#ifndef __NR_pidfd_open +#define __NR_pidfd_open -1 +#endif + +#ifndef __NR_process_mrelease +#define __NR_process_mrelease -1 +#endif + +#define MB(x) (x << 20) +#define MAX_SIZE_MB 1024 + +static int alloc_noexit(unsigned long nr_pages, int pipefd) +{ + int ppid = getppid(); + int timeout = 10; /* 10sec timeout to get killed */ + unsigned long i; + char *buf; + + buf = (char *)mmap(NULL, nr_pages * PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, 0, 0); + if (buf == MAP_FAILED) { + perror("mmap failed, halting the test"); + return KSFT_FAIL; + } + + for (i = 0; i < nr_pages; i++) + *((unsigned long *)(buf + (i * PAGE_SIZE))) = i; + + /* Signal the parent that the child is ready */ + if (write(pipefd, "", 1) < 0) { + perror("write"); + return KSFT_FAIL; + } + + /* Wait to be killed (when reparenting happens) */ + while (getppid() == ppid && timeout > 0) { + sleep(1); + timeout--; + } + + munmap(buf, nr_pages * PAGE_SIZE); + + return (timeout > 0) ? KSFT_PASS : KSFT_FAIL; +} + +/* The process_mrelease calls in this test are expected to fail */ +static void run_negative_tests(int pidfd) +{ + /* Test invalid flags. Expect to fail with EINVAL error code. */ + if (!syscall(__NR_process_mrelease, pidfd, (unsigned int)-1) || + errno != EINVAL) { + perror("process_mrelease with wrong flags"); + exit(errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL); + } + /* + * Test reaping while process is alive with no pending SIGKILL. + * Expect to fail with EINVAL error code. + */ + if (!syscall(__NR_process_mrelease, pidfd, 0) || errno != EINVAL) { + perror("process_mrelease on a live process"); + exit(errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL); + } +} + +static int child_main(int pipefd[], size_t size) +{ + int res; + + /* Allocate and fault-in memory and wait to be killed */ + close(pipefd[0]); + res = alloc_noexit(MB(size) / PAGE_SIZE, pipefd[1]); + close(pipefd[1]); + return res; +} + +int main(void) +{ + int pipefd[2], pidfd; + bool success, retry; + size_t size; + pid_t pid; + char byte; + int res; + + /* Test a wrong pidfd */ + if (!syscall(__NR_process_mrelease, -1, 0) || errno != EBADF) { + perror("process_mrelease with wrong pidfd"); + exit(errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL); + } + + /* Start the test with 1MB child memory allocation */ + size = 1; +retry: + /* + * Pipe for the child to signal when it's done allocating + * memory + */ + if (pipe(pipefd)) { + perror("pipe"); + exit(KSFT_FAIL); + } + pid = fork(); + if (pid < 0) { + perror("fork"); + close(pipefd[0]); + close(pipefd[1]); + exit(KSFT_FAIL); + } + + if (pid == 0) { + /* Child main routine */ + res = child_main(pipefd, size); + exit(res); + } + + /* + * Parent main routine: + * Wait for the child to finish allocations, then kill and reap + */ + close(pipefd[1]); + /* Block until the child is ready */ + res = read(pipefd[0], &byte, 1); + close(pipefd[0]); + if (res < 0) { + perror("read"); + if (!kill(pid, SIGKILL)) + waitpid(pid, NULL, 0); + exit(KSFT_FAIL); + } + + pidfd = syscall(__NR_pidfd_open, pid, 0); + if (pidfd < 0) { + perror("pidfd_open"); + if (!kill(pid, SIGKILL)) + waitpid(pid, NULL, 0); + exit(KSFT_FAIL); + } + + /* Run negative tests which require a live child */ + run_negative_tests(pidfd); + + if (kill(pid, SIGKILL)) { + perror("kill"); + exit(errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL); + } + + success = (syscall(__NR_process_mrelease, pidfd, 0) == 0); + if (!success) { + /* + * If we failed to reap because the child exited too soon, + * before we could call process_mrelease. Double child's memory + * which causes it to spend more time on cleanup and increases + * our chances of reaping its memory before it exits. + * Retry until we succeed or reach MAX_SIZE_MB. + */ + if (errno == ESRCH) { + retry = (size <= MAX_SIZE_MB); + } else { + perror("process_mrelease"); + waitpid(pid, NULL, 0); + exit(errno == ENOSYS ? KSFT_SKIP : KSFT_FAIL); + } + } + + /* Cleanup to prevent zombies */ + if (waitpid(pid, NULL, 0) < 0) { + perror("waitpid"); + exit(KSFT_FAIL); + } + close(pidfd); + + if (!success) { + if (retry) { + size *= 2; + goto retry; + } + printf("All process_mrelease attempts failed!\n"); + exit(KSFT_FAIL); + } + + printf("Success reaping a child with %zuMB of memory allocations\n", + size); + return KSFT_PASS; +} diff --git a/tools/testing/selftests/vm/run_vmtests.sh b/tools/testing/selftests/vm/run_vmtests.sh index a2302b5faaf2..41fce8bea929 100755 --- a/tools/testing/selftests/vm/run_vmtests.sh +++ b/tools/testing/selftests/vm/run_vmtests.sh @@ -141,6 +141,8 @@ run_test ./mlock-random-test run_test ./mlock2-tests +run_test ./mrelease_test + run_test ./mremap_test run_test ./thuge-gen -- 2.36.1.124.g0e6072fb45-goog