From patchwork Thu Jul 14 18:20:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Vagin X-Patchwork-Id: 9230401 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 E681960572 for ; Thu, 14 Jul 2016 18:22:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC8D12817F for ; Thu, 14 Jul 2016 18:22:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D118E28285; Thu, 14 Jul 2016 18:22:04 +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 53A782817F for ; Thu, 14 Jul 2016 18:22:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751798AbcGNSVe (ORCPT ); Thu, 14 Jul 2016 14:21:34 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:35827 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751098AbcGNSUg (ORCPT ); Thu, 14 Jul 2016 14:20:36 -0400 Received: by mail-pf0-f194.google.com with SMTP id t190so5112438pfb.2; Thu, 14 Jul 2016 11:20:35 -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=0eBPpkho/n96HYD6oYMlWJWdbZR6a38QhUxqCJWz4xPldoKcnU6M7u/bwQRzkFZ9qF QTURlcJpmSgnleU4ZbOx5dQK6QN+q+2LK8pwPGwFWjT8lXgaF92H4lNv8stMSu0LRCPb JXYpiJZBPs83P9/O3+mBhy60dhn8weCE6F5/m36PdVON/WeEyyE/cav8AHfGMw8qDYtX o3CZdc/xRgLnFxe8Zzh/cHAAte+Kipi0fmld5jveBppwH1QxQu2gHuaLK1KfYxCAc6Wc oyKlqArcXAshTtcXzZ05HrUK4W9U+FOC/Oqz3G9dKJCJDxTQC7GTDxmMRBUHsow5REmF 1SIA== 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=Ph3vnClXDYiH+cNOCfoJqr7G8kTaw9vNAmCg2tW/2IeJ7A7g2WRyDdNoZtfjw/PRdO PgjjVJrOHvsUlT6NoqIXWO1grV6dAIFNpnrr7o2xFb7c6znhp2QFAKDKacLWXqxCc3bC QurkSX6vZaj0BSqUptzS+wxixGcLNq8EuT7uvA51sPrqi/DP9hPODCPdHIYtnQiYBEHS JCzmsKldvXZgAziRcL0YOT5gbDclkZd6cdggFsLi4l+IXubBWXV0+Afgt4cFw5284o2+ Q4nIgPh3v3LiBGGSmx55f6yWhYJKIo+5lyLqoKTmI8ZzBiHaY5ZL0L3gVJyvrtpqwPnU o6VA== X-Gm-Message-State: ALyK8tLUa038AmpkBPBJyQMy2DlCHYq7RjhDePwzp87S5A2bcuZ4vAjFUVWwvRDR12bPjw== X-Received: by 10.98.1.84 with SMTP id 81mr14763777pfb.155.1468520435171; Thu, 14 Jul 2016 11:20:35 -0700 (PDT) Received: from laptop.vz.com ([162.246.95.100]) by smtp.gmail.com with ESMTPSA id 89sm3515657pft.96.2016.07.14.11.20.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 Jul 2016 11:20:34 -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, Andrey Vagin Subject: [PATCH 5/5] tools/testing: add a test to check nsfs ioctl-s Date: Thu, 14 Jul 2016 11:20:19 -0700 Message-Id: <1468520419-28220-6-git-send-email-avagin@openvz.org> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1468520419-28220-1-git-send-email-avagin@openvz.org> References: <1468520419-28220-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; +}