Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp1191357pxu; Fri, 16 Oct 2020 06:16:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxgRy879BTz4K6BKjCdVK3LWoM4XifhQhKq2QJYgvqWKRQjAy3ev6g9jXwzu7L6nOxAvekH X-Received: by 2002:a17:906:5052:: with SMTP id e18mr3511135ejk.530.1602854169184; Fri, 16 Oct 2020 06:16:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602854169; cv=none; d=google.com; s=arc-20160816; b=ptdER2G9lfoDXaJpd5jKInqE/X9NdxiZiLZTOrotzzQnmcDgn1vM1P+pNC8+CL56bl KdpbUrEBU0/4zSlAry0YnOdKAnTmxu/02tqfAx3yaVg4p+dPH/93z4i0/CFFpVwzHo02 Soe3esYOnDufSz+e/HedW9uBesIydut6EA96cDedbgFtcStjW9deTqBNXJoxkEQgryyH lmTAb6CY9bRZTTBA7RL2sj0zAmd3h6dK0ker96SLrf/XOnFyQwQ8zetQu8T+aC98b8xD xBf4chHrNb7liOw0F70hXVxB/seoXzkDASP5MR+Trb5uA1fjgN+9ysFGn3KUuOEgT+Fk M1Zw== 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=pSm/g0kqVjlpnCUrgMA34WIyplgwS/+jMYU+gRHVlgw=; b=ZGOjR0yZKuTf8+vGuXdPSiQhGAXh1U1KaUYGUHGW1J1T9HLMSQ/+5NJ7O8AunvePnd xauTF7YTfvnt5KUI6+kL3Rigqc3eAUj5cyeW8wNj0yzoKHeSsztBbXIMLBUL9lh9ki+3 vE4RUfOjTNwypABpC0qCxMAH62rpoVKb/iJVVkq0j8GuuXkSwHVmCvMpimdUl2UHwZKk d2yrML6fQjrhRktyRPGqeMyoF0NrD2zZ0GaVYfFXvi5ZUEOjZUaKxMOQ0lvAO4V0rJrS VlOqGmN0DdC24r8de8FgldFhyPj3AwO/DjfLkq3xaN6D6p0MuQGBMHjoMkVIS5L3Hcm7 0New== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sargun.me header.s=google header.b=yEtWgvz7; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n14si1637983eja.99.2020.10.16.06.15.45; Fri, 16 Oct 2020 06:16:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-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=@sargun.me header.s=google header.b=yEtWgvz7; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407839AbgJPMqN (ORCPT + 99 others); Fri, 16 Oct 2020 08:46:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407810AbgJPMqD (ORCPT ); Fri, 16 Oct 2020 08:46:03 -0400 Received: from mail-pj1-x1042.google.com (mail-pj1-x1042.google.com [IPv6:2607:f8b0:4864:20::1042]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BCE7C061755 for ; Fri, 16 Oct 2020 05:46:01 -0700 (PDT) Received: by mail-pj1-x1042.google.com with SMTP id ds1so1326490pjb.5 for ; Fri, 16 Oct 2020 05:46:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pSm/g0kqVjlpnCUrgMA34WIyplgwS/+jMYU+gRHVlgw=; b=yEtWgvz7p6jYnSHOfZ8SZ61XE6LNnfmjHq2tgg4W0HalfMsdO1fu7hLigiTmd3cPa1 Epme0Xmw7MhQIRTFwtwNQ10nfw/43wDopvOLVJfhEnYYQoSzBKcpSAzeFuEvB85Lc0Nk IvaYD1A9N8146rLQPS6tGDPB4ns6JbD79//oY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pSm/g0kqVjlpnCUrgMA34WIyplgwS/+jMYU+gRHVlgw=; b=lzkBXvBIk6UiFNqHLaUnAq4xnf1MkddRfxJCp7Ue/NMCAC/ULtbbbQmNQkuRR7QxxY C+5/cSaWeBvm0OY1M4J8+WlYLjbmwyNNdQs3EOXoxaWVkUDFQY1pJUA9GHhC10hzLMAc DTLNa0vXSc7aBRklaiJd41RPQNNXKrk5o4NPAFCU31sMJ77l9jHOfqe2vS96ItK2DTRO dUNM/sJY9k/28f+6BZnPh+U4FJEVB0ObMbh+2kK7/uXuyPAT8vNhATAZP13TUTxX3jif K01ySQ/8GVFc3aZLo918eytwgylFTp22niZKnL4O3bWQNEHonyWb0ihkdWlLqzGwKJqj R1bA== X-Gm-Message-State: AOAM533rOxBe3wDF5VtNcJ7NXzokIOji24gfQRtTkZgCgdqnEQIzuwaC Oj/EmJ03C9KUsyCspKTwinpUUQ== X-Received: by 2002:a17:90b:3109:: with SMTP id gc9mr3917023pjb.74.1602852360786; Fri, 16 Oct 2020 05:46:00 -0700 (PDT) Received: from ubuntu.netflix.com (203.20.25.136.in-addr.arpa. [136.25.20.203]) by smtp.gmail.com with ESMTPSA id q123sm2906732pfq.56.2020.10.16.05.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:46:00 -0700 (PDT) From: Sargun Dhillon To: "J . Bruce Fields" , Chuck Lever , Trond Myklebust , Anna Schumaker , David Howells Cc: Sargun Dhillon , linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Al Viro , Kyle Anderson Subject: [RESEND PATCH v2 3/3] samples/vfs: Add example leveraging NFS with new APIs and user namespaces Date: Fri, 16 Oct 2020 05:45:50 -0700 Message-Id: <20201016124550.10739-4-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201016124550.10739-1-sargun@sargun.me> References: <20201016124550.10739-1-sargun@sargun.me> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org This adds an example which assumes you already have an NFS server setup, but does the work of creating a user namespace, and an NFS mount from that user namespace which then exposes different UIDs than that of the init user namespace. Signed-off-by: Sargun Dhillon Cc: J. Bruce Fields Cc: Chuck Lever Cc: Trond Myklebust Cc: Anna Schumaker Cc: David Howells Cc: Al Viro Cc: Kyle Anderson --- fs/nfs/flexfilelayout/flexfilelayout.c | 1 + samples/vfs/.gitignore | 2 + samples/vfs/Makefile | 3 +- samples/vfs/test-nfs-userns.c | 181 +++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 samples/vfs/test-nfs-userns.c diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f9348ed1bcda..ee45ff7d75ac 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -361,6 +361,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags) { + struct user_namespace *user_ns = lh->plh_lc_cred->user_ns; struct pnfs_layout_segment *ret; struct nfs4_ff_layout_segment *fls = NULL; struct xdr_stream stream; diff --git a/samples/vfs/.gitignore b/samples/vfs/.gitignore index 8fdabf7e5373..1d09826b31a6 100644 --- a/samples/vfs/.gitignore +++ b/samples/vfs/.gitignore @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only test-fsmount test-statx +test-nfs-userns + diff --git a/samples/vfs/Makefile b/samples/vfs/Makefile index 7f76875eaa70..6a2926080c08 100644 --- a/samples/vfs/Makefile +++ b/samples/vfs/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only test-fsmount-objs := test-fsmount.o vfs-helper.o -userprogs := test-fsmount test-statx +test-nfs-userns-objs := test-nfs-userns.o vfs-helper.o +userprogs := test-fsmount test-statx test-nfs-userns always-y := $(userprogs) diff --git a/samples/vfs/test-nfs-userns.c b/samples/vfs/test-nfs-userns.c new file mode 100644 index 000000000000..108af924cbdd --- /dev/null +++ b/samples/vfs/test-nfs-userns.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vfs-helper.h" + + +#define WELL_KNOWN_FD 100 + +static inline int pidfd_open(pid_t pid, unsigned int flags) +{ + return syscall(__NR_pidfd_open, pid, flags); +} + +static inline int pidfd_getfd(int pidfd, int fd, int flags) +{ + return syscall(__NR_pidfd_getfd, pidfd, fd, flags); +} + +static void write_to_path(const char *path, const char *str) +{ + int fd, len = strlen(str); + + fd = open(path, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Can't open %s: %s\n", path, strerror(errno)); + exit(1); + } + + if (write(fd, str, len) != len) { + fprintf(stderr, "Can't write string: %s\n", strerror(errno)); + exit(1); + } + + E(close(fd)); +} + +static int do_work(int sk) +{ + int fsfd; + + E(unshare(CLONE_NEWNS|CLONE_NEWUSER)); + + fsfd = fsopen("nfs4", 0); + E(fsfd); + + E(send(sk, &fsfd, sizeof(fsfd), 0)); + // Wait for the other side to close / finish / wrap up + recv(sk, &fsfd, sizeof(fsfd), 0); + E(close(sk)); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int pidfd, mntfd, fsfd, fsfdnum, status, sk_pair[2]; + struct statx statxbuf; + char buf[1024]; + pid_t pid; + + if (mkdir("/mnt/share", 0777) && errno != EEXIST) { + perror("mkdir"); + return 1; + } + + E(chmod("/mnt/share", 0777)); + + if (mkdir("/mnt/nfs", 0755) && errno != EEXIST) { + perror("mkdir"); + return 1; + } + + if (unlink("/mnt/share/newfile") && errno != ENOENT) { + perror("unlink"); + return 1; + } + + E(creat("/mnt/share/testfile", 0644)); + E(chown("/mnt/share/testfile", 1001, 1001)); + + /* exportfs is idempotent, but expects nfs-server to be running */ + if (system("exportfs -o no_root_squash,no_subtree_check,rw 127.0.0.0/8:/mnt/share")) { + fprintf(stderr, + "Could not export /mnt/share. Is NFS the server running?\n"); + return 1; + } + + E(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair)); + + pid = fork(); + E(pid); + if (pid == 0) { + E(close(sk_pair[0])); + return do_work(sk_pair[1]); + } + + E(close(sk_pair[1])); + + pidfd = pidfd_open(pid, 0); + E(pidfd); + + E(recv(sk_pair[0], &fsfdnum, sizeof(fsfdnum), 0)); + + fsfd = pidfd_getfd(pidfd, fsfdnum, 0); + if (fsfd == -1) { + perror("pidfd_getfd"); + return 1; + } + + + snprintf(buf, sizeof(buf) - 1, "/proc/%d/uid_map", pid); + write_to_path(buf, "0 1000 2"); + snprintf(buf, sizeof(buf) - 1, "/proc/%d/setgroups", pid); + write_to_path(buf, "deny"); + snprintf(buf, sizeof(buf) - 1, "/proc/%d/gid_map", pid); + write_to_path(buf, "0 1000 2"); + + /* Now we can proceed to mount */ + E_fsconfig(fsfd, FSCONFIG_SET_STRING, "vers", "4.1", 0); + E_fsconfig(fsfd, FSCONFIG_SET_STRING, "clientaddr", "127.0.0.1", 0); + E_fsconfig(fsfd, FSCONFIG_SET_STRING, "addr", "127.0.0.1", 0); + E_fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "127.0.0.1:/mnt/share", + 0); + E_fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0); + + /* Move into the namespace's of the worker */ + E(setns(pidfd, CLONE_NEWNS|CLONE_NEWUSER)); + E(close(pidfd)); + + /* Close our socket pair indicating the child should exit */ + E(close(sk_pair[0])); + assert(waitpid(pid, &status, 0) == pid); + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + fprintf(stderr, "worker exited nonzero\n"); + return 1; + } + + E(setuid(0)); + E(setgid(0)); + + /* Now do all the work of moving doing the mount in the child ns */ + E(syscall(__NR_mount, NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)); + + mntfd = fsmount(fsfd, 0, MS_NODEV); + if (mntfd < 0) { + E(close(fsfd)); + mount_error(fsfd, "fsmount"); + } + + E(move_mount(mntfd, "", AT_FDCWD, "/mnt/nfs", MOVE_MOUNT_F_EMPTY_PATH)); + E(close(mntfd)); + + /* Create the file through NFS */ + E(creat("/mnt/nfs/newfile", 0644)); + /* Check what the file's status is on the disk, accessed directly */ + E(statx(AT_FDCWD, "/mnt/share/newfile", 0, STATX_UID|STATX_GID, + &statxbuf)); + assert(statxbuf.stx_uid == 0); + assert(statxbuf.stx_gid == 0); + + E(statx(AT_FDCWD, "/mnt/nfs/testfile", 0, STATX_UID|STATX_GID, + &statxbuf)); + assert(statxbuf.stx_uid == 1); + assert(statxbuf.stx_gid == 1); + + + return 0; +} -- 2.25.1