Received: by 2002:a05:6a10:a841:0:0:0:0 with SMTP id d1csp427364pxy; Thu, 22 Apr 2021 05:31:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzBkEL4WLEyU368HnVBJT0XTqjHGBVHoa+fbmZinFbJREmZH+Z6gcs0x8yTGi2m0mJNHyIR X-Received: by 2002:a05:6a00:b87:b029:257:b86:5cbf with SMTP id g7-20020a056a000b87b02902570b865cbfmr3060273pfj.15.1619094660726; Thu, 22 Apr 2021 05:31:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1619094660; cv=none; d=google.com; s=arc-20160816; b=Lhv5ABZq2IXLuvbZ2SiR0A7D5ljc6sQcVsVKNWfs9CdNTpBdcQMjy0BMlTeHWPZL/S JEYcejS2uRwddmW4/5bRs9ZItZOrypvAwiP+JLoYgtiu4RTXLeHwCQLSrQCX51VsL9zS 4Ht9+E6Tot076t2EEWU7gbcpB60BkoBDWgI2t9plT7O7w3wsolsSur0s0OGEom+KBlPf atmLI2/mXjSRIqL0kztDwtoLG+gcvRlv3PMfEsBfXGHrqImShd9B0uWxLv2/+SO3YkR/ pVSIln1krI0yVFp0C7E1nwcF8uLAhT+vkTsZOi/J+2EkZ5omR1tC/0pO+/OiRROf7tf2 yvhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=6fHOChRme2wS+00a3A6SOKVpEXQg/sq/0orWM/clrU4=; b=WC8HxApQrB40LqGf3PPfZphHM6TfmYATNYrvhnZFYpZZoYG0v7pnyWx64Be+UAAC3v Bp8Nz/OG5VrM1z54LKfmfxpLij9WDvGvP6nokrFQEviF8Snl2/r+6zusUYUU9MOLB1L9 Pzbk4MmBmp7e5V5sgNsNYbjqgM39moznwCmVGB/cX0O17Qr314jG/JpeL9IcQ0cgGDFY Ue4U5uhUc7sp9P58QTQQC74+IGZaGPQg89XsjGKVWvUbxnY2O8sEyc6j/3GCFGMgUFf7 7tGm4vQMSgAfnTW1DAxZmKksTN5sn5SdrCDlPCSnAJTtlcvuLBw8tYKnJo6JAYgV2ERd uhUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=hK3t3bW+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id fs12si2904639pjb.17.2021.04.22.05.30.47; Thu, 22 Apr 2021 05:31:00 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=hK3t3bW+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236441AbhDVM2l (ORCPT + 99 others); Thu, 22 Apr 2021 08:28:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:36876 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236380AbhDVM2c (ORCPT ); Thu, 22 Apr 2021 08:28:32 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 9561661574; Thu, 22 Apr 2021 12:27:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1619094477; bh=fP29DG3NBsXSw/mOMG+IGXDEiWXAJ3rxrytILV+WtVo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hK3t3bW+/iIxipJnxe9I6TLE22NYRford0WwCIAeQGh1SjTM8qYc+EbGcJJjDe8Oz 5Jkenhy/Sqg9Mpj9JGoUa4s73zlFtUwDk1ustshaC0qB9GGJefRHFbJ1dTTVKC9zff zEQHWVjSz7d1cqvyIMF+3ede0vYUPzfzw933N+uyLDy5yIZ73uh49j8AaKc9Ynu2lS 4Sa4nbc0zwPwtQWlpFlRwIDbGluohwObqZq8oKpqy2mnp07OdHJMEr/KyNHD2raNso YtMjaVSWXyeC3354rpBhOgk36g0SCSKiCZ8l/XlwnowxzAEXnFztZAyil1SI/MwYxF RnDJqGW7vPwOg== From: legion@kernel.org To: LKML , 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 v11 8/9] kselftests: Add test to check for rlimit changes in different user namespaces Date: Thu, 22 Apr 2021 14:27:15 +0200 Message-Id: <28cafdcdd4abd8494b34a27f1970b666b30de8bf.1619094428.git.legion@kernel.org> X-Mailer: git-send-email 2.29.3 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexey Gladkov The testcase runs few instances of the program with RLIMIT_NPROC=1 from user uid=60000, 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/Makefile index 6c575cf34a71..a4ea1481bd9a 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -48,6 +48,7 @@ TARGETS += proc TARGETS += pstore TARGETS += ptrace TARGETS += openat2 +TARGETS += rlimits TARGETS += rseq TARGETS += rtc TARGETS += seccomp diff --git a/tools/testing/selftests/rlimits/.gitignore b/tools/testing/selftests/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/selftests/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 += -Wall -O2 -g +TEST_GEN_PROGS := rlimits-per-userns + +include ../lib.mk diff --git a/tools/testing/selftests/rlimits/config b/tools/testing/selftests/rlimits/config new file mode 100644 index 000000000000..416bd53ce982 --- /dev/null +++ b/tools/testing/selftests/rlimits/config @@ -0,0 +1 @@ +CONFIG_USER_NS=y 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 = 60000; +static uid_t group = 60000; + +static void setrlimit_nproc(rlim_t n) +{ + pid_t pid = getpid(); + struct rlimit limit = { + .rlim_cur = n, + .rlim_max = n + }; + + warnx("(pid=%d): Setting RLIMIT_NPROC=%ld", pid, n); + + if (setrlimit(RLIMIT_NPROC, &limit) < 0) + err(EXIT_FAILURE, "(pid=%d): setrlimit(RLIMIT_NPROC)", pid); +} + +static pid_t fork_child(void) +{ + pid_t pid = fork(); + + if (pid < 0) + err(EXIT_FAILURE, "fork"); + + if (pid > 0) + return pid; + + pid = getpid(); + + warnx("(pid=%d): New process starting ...", pid); + + if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) + err(EXIT_FAILURE, "(pid=%d): prctl(PR_SET_PDEATHSIG)", pid); + + signal(SIGUSR1, SIG_DFL); + + warnx("(pid=%d): Changing to uid=%d, gid=%d", pid, user, group); + + if (setgid(group) < 0) + err(EXIT_FAILURE, "(pid=%d): setgid(%d)", pid, group); + if (setuid(user) < 0) + err(EXIT_FAILURE, "(pid=%d): setuid(%d)", pid, user); + + warnx("(pid=%d): Service running ...", pid); + + warnx("(pid=%d): Unshare user namespace", pid); + if (unshare(CLONE_NEWUSER) < 0) + err(EXIT_FAILURE, "unshare(CLONE_NEWUSER)"); + + char *const argv[] = { "service", NULL }; + char *const envp[] = { "I_AM_SERVICE=1", NULL }; + + warnx("(pid=%d): Executing real service ...", pid); + + execve(service_prog, argv, envp); + err(EXIT_FAILURE, "(pid=%d): execve", pid); +} + +int main(int argc, char **argv) +{ + size_t i; + pid_t child[NR_CHILDS]; + int wstatus[NR_CHILDS]; + int childs = NR_CHILDS; + pid_t pid; + + if (getenv("I_AM_SERVICE")) { + pause(); + exit(EXIT_SUCCESS); + } + + service_prog = argv[0]; + pid = getpid(); + + warnx("(pid=%d) Starting testcase", pid); + + /* + * This rlimit is not a problem for root because it can be exceeded. + */ + setrlimit_nproc(1); + + for (i = 0; i < NR_CHILDS; i++) { + child[i] = fork_child(); + wstatus[i] = 0; + usleep(250000); + } + + while (1) { + for (i = 0; i < NR_CHILDS; i++) { + if (child[i] <= 0) + continue; + + errno = 0; + pid_t ret = waitpid(child[i], &wstatus[i], WNOHANG); + + if (!ret || (!WIFEXITED(wstatus[i]) && !WIFSIGNALED(wstatus[i]))) + continue; + + if (ret < 0 && errno != ECHILD) + warn("(pid=%d): waitpid(%d)", pid, child[i]); + + child[i] *= -1; + childs -= 1; + } + + if (!childs) + break; + + usleep(250000); + + for (i = 0; i < NR_CHILDS; i++) { + if (child[i] <= 0) + continue; + kill(child[i], SIGUSR1); + } + } + + for (i = 0; i < NR_CHILDS; i++) { + if (WIFEXITED(wstatus[i])) + warnx("(pid=%d): pid %d exited, status=%d", + pid, -child[i], WEXITSTATUS(wstatus[i])); + else if (WIFSIGNALED(wstatus[i])) + warnx("(pid=%d): pid %d killed by signal %d", + pid, -child[i], WTERMSIG(wstatus[i])); + + if (WIFSIGNALED(wstatus[i]) && WTERMSIG(wstatus[i]) == SIGUSR1) + continue; + + warnx("(pid=%d): Test failed", pid); + exit(EXIT_FAILURE); + } + + warnx("(pid=%d): Test passed", pid); + exit(EXIT_SUCCESS); +} -- 2.29.3