From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52605C433E0 for ; Mon, 22 Feb 2021 09:57:32 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id BDBF664ED7 for ; Mon, 22 Feb 2021 09:57:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BDBF664ED7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 827B48D0003; Mon, 22 Feb 2021 04:57:17 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 740A68D0001; Mon, 22 Feb 2021 04:57:17 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 3DC948D0006; Mon, 22 Feb 2021 04:57:17 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 25EE38D0003 for ; Mon, 22 Feb 2021 04:57:17 -0500 (EST) Received: from smtpin12.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id E307A180ACEE4 for ; Mon, 22 Feb 2021 09:57:16 +0000 (UTC) X-FDA: 77845450872.12.DF3DB0E Received: from raptor.unsafe.ru (raptor.unsafe.ru [5.9.43.93]) by imf03.hostedemail.com (Postfix) with ESMTP id 9CEC7C000C4B for ; Mon, 22 Feb 2021 09:57:13 +0000 (UTC) Received: from comp-core-i7-2640m-0182e6.redhat.com (ip-94-113-225-162.net.upcbroadband.cz [94.113.225.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by raptor.unsafe.ru (Postfix) with ESMTPSA id 952B120A1E; Mon, 22 Feb 2021 09:57:15 +0000 (UTC) From: Alexey Gladkov To: LKML , io-uring@vger.kernel.org, Kernel Hardening , Linux Containers , linux-mm@kvack.org Cc: Alexey Gladkov , Andrew Morton , Christian Brauner , "Eric W . Biederman" , Jann Horn , Jens Axboe , Kees Cook , Linus Torvalds , Oleg Nesterov Subject: [PATCH v7 7/7] kselftests: Add test to check for rlimit changes in different user namespaces Date: Mon, 22 Feb 2021 10:56:32 +0100 Message-Id: <07f37fb07ac9845edd9ff8f44ecafa36f644611d.1613987704.git.gladkov.alexey@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.1 (raptor.unsafe.ru [5.9.43.93]); Mon, 22 Feb 2021 09:57:16 +0000 (UTC) X-Stat-Signature: ydnjzbqtw7jacqgfxg8j9kit9s943y59 X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: 9CEC7C000C4B Received-SPF: none (gmail.com>: No applicable sender policy available) receiver=imf03; identity=mailfrom; envelope-from=""; helo=raptor.unsafe.ru; client-ip=5.9.43.93 X-HE-DKIM-Result: none/none X-HE-Tag: 1613987833-410590 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The testcase runs few instances of the program with RLIMIT_NPROC=3D1 from user uid=3D60000, in different user namespaces. Signed-off-by: Alexey Gladkov --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/rlimits/.gitignore | 2 + tools/testing/selftests/rlimits/Makefile | 6 + tools/testing/selftests/rlimits/config | 1 + .../selftests/rlimits/rlimits-per-userns.c | 161 ++++++++++++++++++ 5 files changed, 171 insertions(+) create mode 100644 tools/testing/selftests/rlimits/.gitignore create mode 100644 tools/testing/selftests/rlimits/Makefile create mode 100644 tools/testing/selftests/rlimits/config create mode 100644 tools/testing/selftests/rlimits/rlimits-per-userns.c diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/M= akefile index 8a917cb4426a..a6d3fde4a617 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -46,6 +46,7 @@ TARGETS +=3D proc TARGETS +=3D pstore TARGETS +=3D ptrace TARGETS +=3D openat2 +TARGETS +=3D rlimits TARGETS +=3D rseq TARGETS +=3D rtc TARGETS +=3D seccomp diff --git a/tools/testing/selftests/rlimits/.gitignore b/tools/testing/s= elftests/rlimits/.gitignore new file mode 100644 index 000000000000..091021f255b3 --- /dev/null +++ b/tools/testing/selftests/rlimits/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +rlimits-per-userns diff --git a/tools/testing/selftests/rlimits/Makefile b/tools/testing/sel= ftests/rlimits/Makefile new file mode 100644 index 000000000000..03aadb406212 --- /dev/null +++ b/tools/testing/selftests/rlimits/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +CFLAGS +=3D -Wall -O2 -g +TEST_GEN_PROGS :=3D rlimits-per-userns + +include ../lib.mk diff --git a/tools/testing/selftests/rlimits/config b/tools/testing/selft= ests/rlimits/config new file mode 100644 index 000000000000..416bd53ce982 --- /dev/null +++ b/tools/testing/selftests/rlimits/config @@ -0,0 +1 @@ +CONFIG_USER_NS=3Dy diff --git a/tools/testing/selftests/rlimits/rlimits-per-userns.c b/tools= /testing/selftests/rlimits/rlimits-per-userns.c new file mode 100644 index 000000000000..26dc949e93ea --- /dev/null +++ b/tools/testing/selftests/rlimits/rlimits-per-userns.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Author: Alexey Gladkov + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NR_CHILDS 2 + +static char *service_prog; +static uid_t user =3D 60000; +static uid_t group =3D 60000; + +static void setrlimit_nproc(rlim_t n) +{ + pid_t pid =3D getpid(); + struct rlimit limit =3D { + .rlim_cur =3D n, + .rlim_max =3D n + }; + + warnx("(pid=3D%d): Setting RLIMIT_NPROC=3D%ld", pid, n); + + if (setrlimit(RLIMIT_NPROC, &limit) < 0) + err(EXIT_FAILURE, "(pid=3D%d): setrlimit(RLIMIT_NPROC)", pid); +} + +static pid_t fork_child(void) +{ + pid_t pid =3D fork(); + + if (pid < 0) + err(EXIT_FAILURE, "fork"); + + if (pid > 0) + return pid; + + pid =3D getpid(); + + warnx("(pid=3D%d): New process starting ...", pid); + + if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) + err(EXIT_FAILURE, "(pid=3D%d): prctl(PR_SET_PDEATHSIG)", pid); + + signal(SIGUSR1, SIG_DFL); + + warnx("(pid=3D%d): Changing to uid=3D%d, gid=3D%d", pid, user, group); + + if (setgid(group) < 0) + err(EXIT_FAILURE, "(pid=3D%d): setgid(%d)", pid, group); + if (setuid(user) < 0) + err(EXIT_FAILURE, "(pid=3D%d): setuid(%d)", pid, user); + + warnx("(pid=3D%d): Service running ...", pid); + + warnx("(pid=3D%d): Unshare user namespace", pid); + if (unshare(CLONE_NEWUSER) < 0) + err(EXIT_FAILURE, "unshare(CLONE_NEWUSER)"); + + char *const argv[] =3D { "service", NULL }; + char *const envp[] =3D { "I_AM_SERVICE=3D1", NULL }; + + warnx("(pid=3D%d): Executing real service ...", pid); + + execve(service_prog, argv, envp); + err(EXIT_FAILURE, "(pid=3D%d): execve", pid); +} + +int main(int argc, char **argv) +{ + size_t i; + pid_t child[NR_CHILDS]; + int wstatus[NR_CHILDS]; + int childs =3D NR_CHILDS; + pid_t pid; + + if (getenv("I_AM_SERVICE")) { + pause(); + exit(EXIT_SUCCESS); + } + + service_prog =3D argv[0]; + pid =3D getpid(); + + warnx("(pid=3D%d) Starting testcase", pid); + + /* + * This rlimit is not a problem for root because it can be exceeded. + */ + setrlimit_nproc(1); + + for (i =3D 0; i < NR_CHILDS; i++) { + child[i] =3D fork_child(); + wstatus[i] =3D 0; + usleep(250000); + } + + while (1) { + for (i =3D 0; i < NR_CHILDS; i++) { + if (child[i] <=3D 0) + continue; + + errno =3D 0; + pid_t ret =3D waitpid(child[i], &wstatus[i], WNOHANG); + + if (!ret || (!WIFEXITED(wstatus[i]) && !WIFSIGNALED(wstatus[i]))) + continue; + + if (ret < 0 && errno !=3D ECHILD) + warn("(pid=3D%d): waitpid(%d)", pid, child[i]); + + child[i] *=3D -1; + childs -=3D 1; + } + + if (!childs) + break; + + usleep(250000); + + for (i =3D 0; i < NR_CHILDS; i++) { + if (child[i] <=3D 0) + continue; + kill(child[i], SIGUSR1); + } + } + + for (i =3D 0; i < NR_CHILDS; i++) { + if (WIFEXITED(wstatus[i])) + warnx("(pid=3D%d): pid %d exited, status=3D%d", + pid, -child[i], WEXITSTATUS(wstatus[i])); + else if (WIFSIGNALED(wstatus[i])) + warnx("(pid=3D%d): pid %d killed by signal %d", + pid, -child[i], WTERMSIG(wstatus[i])); + + if (WIFSIGNALED(wstatus[i]) && WTERMSIG(wstatus[i]) =3D=3D SIGUSR1) + continue; + + warnx("(pid=3D%d): Test failed", pid); + exit(EXIT_FAILURE); + } + + warnx("(pid=3D%d): Test passed", pid); + exit(EXIT_SUCCESS); +} --=20 2.29.2