From patchwork Tue Mar 19 22:31:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Lawrence X-Patchwork-Id: 1058729 X-Patchwork-Delegate: petr.vorel@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="LcvCTt7p"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44P79C57T7z9sNH for ; Wed, 20 Mar 2019 09:32:47 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 79D2B3EAE9B for ; Tue, 19 Mar 2019 23:32:44 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-6.smtp.seeweb.it (in-6.smtp.seeweb.it [217.194.8.6]) by picard.linux.it (Postfix) with ESMTP id 6A04D3EA169 for ; Tue, 19 Mar 2019 23:32:42 +0100 (CET) Received: from mail-vk1-xa4a.google.com (mail-vk1-xa4a.google.com [IPv6:2607:f8b0:4864:20::a4a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-6.smtp.seeweb.it (Postfix) with ESMTPS id 9E18D1400DAA for ; Tue, 19 Mar 2019 23:32:41 +0100 (CET) Received: by mail-vk1-xa4a.google.com with SMTP id y125so232559vky.19 for ; Tue, 19 Mar 2019 15:32:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=NSFCG/5t9qVl2e4vZ7G7IfGTI1El9gryolq6/AwvEv0=; b=LcvCTt7px0WkxdRSFiT0MwzZxBWtJhra7darwZKQEA6i8I6Qvz/pf8lZhD4e5JS+qT N4ArZFbBQcumjA07A7ErGCUSrSaj1hugfw0SjcRpds24KBvjkhkVJiQoRFmf3nyY6W6u ITDcT4UjF0v3jBgFrveFlgY03UYafMvn2zarQaEyDwm+ca6RS5cMUBWkjp6DhCS/vSLq YOiZ2NvJK2Qhr0T2KiDedFyEFLVBbrd1I0xOTW43WfXIiuE4+njbvHCDNFBIOQ/9zfSO hzRJVedxLeRTrfk9ew9mfKebwL8xDX1t9U3Mko466dVPbvaHE3OmqAcTRwA/9LaAdZit dyQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=NSFCG/5t9qVl2e4vZ7G7IfGTI1El9gryolq6/AwvEv0=; b=YQIgqxjipn6Yn7xtwQnt7Gro6Pi5UmbLxw2+NqeMyPkIGZN3D0qXh/o4/nwV25ga6M pgWDU/Fc0u01jqgyEApChQqBsTuxqnY9hc4mJ8zUBUeMb9Kgb9RhYRRUKtrY0cMwrEGp ux9PFF3nCqok6GgidBFKIisFZOxi+TjDvcFBEV3/D6xYcR7dV5NLYSB/axg01wiGo64O DhJviLv32JLXCEvXIj1QfT6T9mvj0tP/lHiDnW/Cme6X0W+19YzbuFDQMC9frvSfEvek KDo/59isAd39u2Exmqn8uPQCNG2am1WbLS9XjBQt6nRpNRkf5XW88cU+rFjaacBDuxMy IPFA== X-Gm-Message-State: APjAAAVn7UnZaMqDCDVj69UYBUurv0fp+A/eiZz3KktNqrPqiz9sI19X +uP9OLoEPbsd5aSPXEPtcx5p0bMb6Jq5GAozc8o= X-Google-Smtp-Source: APXvYqzh55FCslKmgdHaFRVs8yfEI7LKLyng7XBZmxNONpZhezSQO7bHdO4ZxT83ZpW4KdviSteLYHX/Dzxgap9wiDM= X-Received: by 2002:a1f:8d0b:: with SMTP id p11mr10625981vkd.0.1553034760201; Tue, 19 Mar 2019 15:32:40 -0700 (PDT) Date: Tue, 19 Mar 2019 15:31:57 -0700 Message-Id: <20190319223157.47453-1-paullawrence@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog From: Paul Lawrence To: pvorel@suse.cz, chrubis@suse.cz, ltp@lists.linux.it, kernel-team@android.com, maennich@google.com X-Virus-Scanned: clamav-milter 0.99.2 at in-6.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-7.4 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-6.smtp.seeweb.it Subject: [LTP] [PATCH] Add ltp pivot_root test X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Signed-off-by: Paul Lawrence --- runtest/syscalls | 2 + testcases/kernel/syscalls/pivot_root/Makefile | 11 + .../kernel/syscalls/pivot_root/pivot_root01.c | 193 ++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 testcases/kernel/syscalls/pivot_root/Makefile create mode 100644 testcases/kernel/syscalls/pivot_root/pivot_root01.c diff --git a/runtest/syscalls b/runtest/syscalls index 668c87cd1..debda74b8 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -835,6 +835,8 @@ pipe11 pipe11 pipe2_01 pipe2_01 pipe2_02 pipe2_02 +pivot_root01 pivot_root01 + poll01 poll01 poll02 poll02 diff --git a/testcases/kernel/syscalls/pivot_root/Makefile b/testcases/kernel/syscalls/pivot_root/Makefile new file mode 100644 index 000000000..6a3810270 --- /dev/null +++ b/testcases/kernel/syscalls/pivot_root/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2019 Google, Inc. + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +LDLIBS += $(CAP_LIBS) + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/pivot_root/pivot_root01.c b/testcases/kernel/syscalls/pivot_root/pivot_root01.c new file mode 100644 index 000000000..d5f2bd1ca --- /dev/null +++ b/testcases/kernel/syscalls/pivot_root/pivot_root01.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Copyright (c) 2019 Google, Inc. + +#define _GNU_SOURCE + +#include "config.h" + +#include +#include +#include + +#include +#include + +#include "tst_test.h" + +#ifdef HAVE_UNSHARE + +#ifdef HAVE_LIBCAP +#include +#endif + +#define CHROOT_DIR "chroot" +#define NEW_ROOT "/new_root" +#define PUT_OLD "/new_root/put_old" +#define PUT_OLD_FS "/put_old_fs" +#define PUT_OLD_BAD "/put_old_fs/put_old" + +enum { + /* + * Test consists of a series of steps that allow pivot_root to succeed, + * which is run when param is NORMAL. All other values tweak one of the + * steps to induce a failure, and check the errno is as expected. + */ + NORMAL, + + /* + * EBUSY + * new_root or put_old are on the current root file system + */ + NEW_ROOT_ON_CURRENT_ROOT, + + /* + * EINVAL + * put_old is not underneath new_root + * Note: if put_old and new_root are on the same fs, + * pivot_root fails with EBUSY before testing reachability + */ + PUT_OLD_NOT_UNDERNEATH_NEW_ROOT, + + /* + * ENOTDIR + * new_root or put_old is not a directory + */ + PUT_OLD_NOT_DIR, + + /* + * EPERM + * The calling process does not have the CAP_SYS_ADMIN capability. + */ + NO_CAP_SYS_ADMIN, +}; + +static const struct test_case { + int test_case; + int expected_error; +} test_cases[] = { + {NORMAL, 0}, + {NEW_ROOT_ON_CURRENT_ROOT, EBUSY}, + {PUT_OLD_NOT_UNDERNEATH_NEW_ROOT, EINVAL}, + {PUT_OLD_NOT_DIR, ENOTDIR}, + {NO_CAP_SYS_ADMIN, EPERM}, +}; + +#ifdef HAVE_LIBCAP +static void drop_cap_sys_admin(void) +{ + cap_value_t cap_value[] = { CAP_SYS_ADMIN }; + cap_t cap = cap_get_proc(); + if (!cap) + tst_brk(TFAIL | TERRNO, "cap_get_proc failed"); + + if (cap_set_flag(cap, CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR)) + tst_brk(TFAIL | TERRNO, "cap_set_flag failed"); + + if (cap_set_proc(cap)) + tst_brk(TFAIL | TERRNO, "cap_set_proc failed"); +} +#endif + +static void run(unsigned int test_case) +{ + /* Work in child process - needed to undo unshare and chroot */ + if (SAFE_FORK()) { + tst_reap_children(); + return; + } + + /* pivot_root requires no shared mounts exist in process namespace */ + TEST(unshare(CLONE_NEWNS | CLONE_FS)); + if (TST_RET == -1) + tst_brk(TFAIL | TERRNO, "unshare failed"); + + /* + * Create an initial root dir. pivot_root doesn't work if the initial root + * dir is a initramfs, so use chroot to create a safe environment + */ + SAFE_MOUNT("none", "/", NULL, MS_REC|MS_PRIVATE, NULL); + SAFE_MOUNT("none", CHROOT_DIR, "tmpfs", 0, 0); + SAFE_CHROOT(CHROOT_DIR); + + SAFE_MKDIR(NEW_ROOT, 0777); + + /* + * pivot_root only works if new_root is a mount point, so mount a tmpfs + * unless testing for that fail mode + */ + if (test_cases[test_case].test_case != NEW_ROOT_ON_CURRENT_ROOT) + SAFE_MOUNT("none", NEW_ROOT, "tmpfs", 0, 0); + + /* + * Create put_old under new_root, unless testing for that specific fail + * mode + */ + const char* actual_put_old = NULL; + if (test_cases[test_case].test_case == PUT_OLD_NOT_UNDERNEATH_NEW_ROOT) { + actual_put_old = PUT_OLD_BAD; + SAFE_MKDIR(PUT_OLD_FS, 0777); + SAFE_MOUNT("none", PUT_OLD_FS, "tmpfs", 0, 0); + SAFE_MKDIR(PUT_OLD_BAD, 0777); + } else { + actual_put_old = PUT_OLD; + + if (test_cases[test_case].test_case == PUT_OLD_NOT_DIR) + SAFE_CREAT(PUT_OLD, 0777); + else + SAFE_MKDIR(PUT_OLD, 0777); + } + + if (test_cases[test_case].test_case == NO_CAP_SYS_ADMIN) { +#ifdef HAVE_LIBCAP + drop_cap_sys_admin(); +#else + tst_res(TCONF, + "System doesn't have POSIX capabilities support"); + return; +#endif + } + + TEST(syscall(__NR_pivot_root, NEW_ROOT, actual_put_old)); + + if (test_cases[test_case].test_case == NORMAL) { + if (TST_RET) { + tst_res(TFAIL | TERRNO, "pivot_root failed"); + return; + } else { + tst_res(TPASS, "pivot_root succeeded"); + return; + } + } + + if (TST_RET == 0) { + tst_res(TFAIL, "pivot_root succeeded unexpectedly"); + return; + } + + if (errno != test_cases[test_case].expected_error) { + tst_res(TFAIL | TERRNO, "pivot_root failed with wrong errno"); + return; + } + + tst_res(TPASS, "pivot_root failed as expected with %s", + strerror(errno)); +} + +static void setup(void) +{ + SAFE_MKDIR(CHROOT_DIR, 0777); +} + +static struct tst_test test = { + .test = run, + .tcnt = ARRAY_SIZE(test_cases), + .needs_tmpdir = 1, + .needs_root = 1, + .forks_child = 1, + .setup = setup, +}; + +#else + TST_TEST_TCONF("unshare is undefined."); +#endif