From patchwork Fri Jul 15 02:12:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Vagin X-Patchwork-Id: 9231035 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 087DA60574 for ; Fri, 15 Jul 2016 02:13:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0D6928308 for ; Fri, 15 Jul 2016 02:13:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D566828326; Fri, 15 Jul 2016 02:13:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3333F28308 for ; Fri, 15 Jul 2016 02:13:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752257AbcGOCMq (ORCPT ); Thu, 14 Jul 2016 22:12:46 -0400 Received: from mail-pa0-f65.google.com ([209.85.220.65]:35803 "EHLO mail-pa0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751459AbcGOCMj (ORCPT ); Thu, 14 Jul 2016 22:12:39 -0400 Received: by mail-pa0-f65.google.com with SMTP id dx3so5413343pab.2; Thu, 14 Jul 2016 19:12:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=zz0Dy5mSVdIY7u8ng47syjHDT8kUKjAHB3ENLgHTWjU=; b=X2ITLnkxYJLGsva9K0Jwy6COrlR2h/j2xPr7Ll92hifFWoKZ0vc6wiQWh5uDp62nIt m665O5kwymYQvbtcFrKSVS9EVScdJVdxSnYsw98gGTk4zsjnvxAZW0W5KLSGGkII8us2 ZROpCy9o110VLCQ3ovHCPTG3I94PP4m8J03+jvBnQbTv7QYDvYOilcjQ35SrHEBbShf1 x3xCvyzwclE9RVAoF1vptYs1M5BO2Bwr9LF6FvAXeKV+hpamrMSsYsWse5Vt6y2HxcvR kV44aRbmT6FVsyDpyqqq+6vYb9/WKUJu0wzv6PsL87lvfu2XAFhUq9WyCq4Td895HjNq so6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=zz0Dy5mSVdIY7u8ng47syjHDT8kUKjAHB3ENLgHTWjU=; b=j1MQJGNzODp7Rxzk4KWBBiX/872njCuCTTdHqeg//DWCD2ejzVZXe1gA2Jjt4q9sw1 4kNUlYIL5dVgvDdXQhbntnufVSCtOhMvKkMWE0K3ff2C07+nSWmr/Ws8tQ7ZJ9BjIs61 RNT8YPcl7i2Ij6DFh0dmKLGHbcRcVjvpK2p9VvnDybYoNSGSCadOT1FVc6qJQvfWq4zM Yr+t7AFgdAa15UNy063vFNOO+ri0ZjAoQ1TObFGfY5P+Kbpu6zRilAG+gDgGt7RfTTSj WM6jcTZja0DNVHjPtgHzk1Ec0ZdnV+k+GNKIWJ4qvPNXsyA1pfqhHg4Wyrbbq8AKpjE2 PFsA== X-Gm-Message-State: ALyK8tJZQLp/SDhd07wKdNFFnr0J05tZLq8W9+KNkZ56fscR5+WRXIdscxqtElbrMqfJPQ== X-Received: by 10.66.156.9 with SMTP id wa9mr27610043pab.64.1468548758802; Thu, 14 Jul 2016 19:12:38 -0700 (PDT) Received: from laptop.localdomain (c-67-183-159-197.hsd1.wa.comcast.net. [67.183.159.197]) by smtp.gmail.com with ESMTPSA id by5sm7559894pad.36.2016.07.14.19.12.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 Jul 2016 19:12:38 -0700 (PDT) From: Andrey Vagin To: linux-kernel@vger.kernel.org Cc: linux-api@vger.kernel.org, containers@lists.linux-foundation.org, criu@openvz.org, linux-fsdevel@vger.kernel.org, "Eric W. Biederman" , James Bottomley , "Michael Kerrisk (man-pages)" , "W. Trevor King" , Alexander Viro , Serge Hallyn , Andrey Vagin Subject: [PATCH 5/5] tools/testing: add a test to check nsfs ioctl-s Date: Thu, 14 Jul 2016 19:12:22 -0700 Message-Id: <1468548742-32136-5-git-send-email-avagin@openvz.org> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1468548742-32136-1-git-send-email-avagin@openvz.org> References: <1468548742-32136-1-git-send-email-avagin@openvz.org> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There are two new ioctl-s: One ioctl for the user namespace that owns a file descriptor. One ioctl for the parent namespace of a namespace file descriptor. The test checks that these ioctl-s works and that they handle a case when a target namespace is outside of the current process namespace. Signed-off-by: Andrey Vagin --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/nsfs/Makefile | 12 +++++ tools/testing/selftests/nsfs/owner.c | 91 +++++++++++++++++++++++++++++++++++ tools/testing/selftests/nsfs/pidns.c | 74 ++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 tools/testing/selftests/nsfs/Makefile create mode 100644 tools/testing/selftests/nsfs/owner.c create mode 100644 tools/testing/selftests/nsfs/pidns.c diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index ff9e5f2..f770dba 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -15,6 +15,7 @@ TARGETS += memory-hotplug TARGETS += mount TARGETS += mqueue TARGETS += net +TARGETS += nsfs TARGETS += powerpc TARGETS += pstore TARGETS += ptrace diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile new file mode 100644 index 0000000..2306054 --- /dev/null +++ b/tools/testing/selftests/nsfs/Makefile @@ -0,0 +1,12 @@ +TEST_PROGS := owner pidns + +CFLAGS := -Wall -Werror + +all: owner pidns +owner: owner.c +pidns: pidns.c + +clean: + $(RM) owner pidns + +include ../lib.mk diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c new file mode 100644 index 0000000..c97aa50 --- /dev/null +++ b/tools/testing/selftests/nsfs/owner.c @@ -0,0 +1,91 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NSIO 0xb7 +#define NS_GET_USERNS _IO(NSIO, 0x1) + +#define pr_err(fmt, ...) \ + ({ \ + fprintf(stderr, "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + 1; \ + }) + +int main(int argc, char *argvp[]) +{ + int pfd[2], ns, uns, init_uns; + struct stat st1, st2; + char path[128]; + pid_t pid; + char c; + + if (pipe(pfd)) + return 1; + + pid = fork(); + if (pid < 0) + return pr_err("fork"); + if (pid == 0) { + prctl(PR_SET_PDEATHSIG, SIGKILL); + if (unshare(CLONE_NEWUTS | CLONE_NEWUSER)) + return pr_err("unshare"); + close(pfd[0]); + close(pfd[1]); + while (1) + sleep(1); + return 0; + } + close(pfd[1]); + if (read(pfd[0], &c, 1) != 0) + return pr_err("Unable to read from pipe"); + close(pfd[0]); + + snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid); + ns = open(path, O_RDONLY); + if (ns < 0) + return pr_err("Unable to open %s", path); + + uns = ioctl(ns, NS_GET_USERNS); + if (uns < 0) + return pr_err("Unable to get an owning user namespace"); + + if (fstat(uns, &st1)) + return pr_err("fstat"); + + snprintf(path, sizeof(path), "/proc/%d/ns/user", pid); + if (stat(path, &st2)) + return pr_err("stat"); + + if (st1.st_ino != st2.st_ino) + return pr_err("NS_GET_USERNS returned a wrong namespace"); + + init_uns = ioctl(uns, NS_GET_USERNS); + if (uns < 0) + return pr_err("Unable to get an owning user namespace"); + + if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != ENOENT) + return pr_err("Don't get ENOENT"); + + if (unshare(CLONE_NEWUSER)) + return pr_err("unshare"); + + if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM) + return pr_err("Don't get EPERM"); + + kill(pid, SIGKILL); + wait(NULL); + return 0; +} diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c new file mode 100644 index 0000000..99b1131 --- /dev/null +++ b/tools/testing/selftests/nsfs/pidns.c @@ -0,0 +1,74 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define pr_err(fmt, ...) \ + ({ \ + fprintf(stderr, "%s:%d:" fmt ": %m\n", \ + __func__, __LINE__, ##__VA_ARGS__); \ + 1; \ + }) + +#define NSIO 0xb7 +#define NS_GET_USERNS _IO(NSIO, 0x1) +#define NS_GET_PARENT _IO(NSIO, 0x2) + +#define __stack_aligned__ __attribute__((aligned(16))) +struct cr_clone_arg { + char stack[128] __stack_aligned__; + char stack_ptr[0]; +}; + +static int child(void *args) +{ + prctl(PR_SET_PDEATHSIG, SIGKILL); + while (1) + sleep(1); + exit(0); +} + +int main(int argc, char *argv[]) +{ + char path[] = "/proc/0123456789/ns/pid"; + struct cr_clone_arg ca; + struct stat st1, st2; + int ns, pns; + pid_t pid; + + pid = clone(child, ca.stack_ptr, CLONE_NEWPID | SIGCLD, NULL); + if (pid < 0) + return pr_err("clone"); + + snprintf(path, sizeof(path), "/proc/%d/ns/pid", pid); + ns = open(path, O_RDONLY); + if (ns < 0) + return pr_err("Unable to open %s", path); + + pns = ioctl(ns, NS_GET_PARENT); + if (pns < 0) + return pr_err("Unable to get a parent pidns"); + + if (stat("/proc/self/ns/pid", &st2)) + return pr_err("Unable to stat %s", path); + if (fstat(pns, &st1)) + return pr_err("Unable to stat the parent pidns"); + if (st1.st_ino != st2.st_ino) + return pr_err("NS_GET_PARENT returned a wrong namespace"); + + if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != ENOENT) + return pr_err("Don't get ENOENT");; + + kill(pid, SIGKILL); + wait(NULL); + return 0; +}