From patchwork Fri Oct 16 12:45:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841679 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4D0A314B2 for ; Fri, 16 Oct 2020 12:46:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 19AA4207F7 for ; Fri, 16 Oct 2020 12:46:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="rvvX9vjw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407821AbgJPMqA (ORCPT ); Fri, 16 Oct 2020 08:46:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407594AbgJPMp7 (ORCPT ); Fri, 16 Oct 2020 08:45:59 -0400 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25857C0613D8 for ; Fri, 16 Oct 2020 05:45:58 -0700 (PDT) Received: by mail-pg1-x541.google.com with SMTP id g29so1393743pgl.2 for ; Fri, 16 Oct 2020 05:45:58 -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=rjQ1D5B+qargOyy25A8yvKQ0xoEiGNZxg2F9KkU+Vqc=; b=rvvX9vjwBy6pgW5A1sZMeli8uVvshsQbi7OfAvSfKv+cfunjCEdoM9PDcEMZt6u8am ti4utoFydxTM6dfWPQgNDQtqFZ5gJ1w7XEBLyAB08qriub02wS0nKi8WBk2Wl/GMt0+F UMH6mHhxsp21/JqgdH6CdMU+2XaH7RpSHSDOE= 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=rjQ1D5B+qargOyy25A8yvKQ0xoEiGNZxg2F9KkU+Vqc=; b=f9dHPYJDhOeIAZz9+H5FV6mdK6RwTgFMEBZPhlWfBLHuCEgXhBMZiG75VXufoQLqDc Tg+GwN7T7rp/S57lAzC+M0aYAJdwkkcfY5/AN4h679CHLMbKdv0Ni3bxWxlT1ZHYt91S APFle1ckMxQT3VA+QkKxjbdKt0vVGvDpl921KuDaFVsj711jQGBs1sw0AlLUozfz0boc piv/Eaz3f76x27uX1Ly8ncDXB3azjjdc1mRhd9D8XtXFG6L9q5i4zo59biu78baaojmM 3785Oe4LWJtYliLIfk9clvbOJ1gT+NBBgwcCbgvvwDPtu5FwzCQ/3uXnUuEcNRIXYIcU qKHQ== X-Gm-Message-State: AOAM530dAJC2yM3kGowHvXm618IHuUDsHasiZ2YJfnpzLXlRQznyM93o IUt0WmOHEBzXQjqitciJ7X/0UA== X-Google-Smtp-Source: ABdhPJyGw5sBLcgSohIBCu2iy7zrVUgKUib9rZilW+TIEcZbkw0CflLpTDkjcXvAI0orCvPYxdnVmA== X-Received: by 2002:a62:e81a:0:b029:152:97f9:9775 with SMTP id c26-20020a62e81a0000b029015297f99775mr3374158pfi.29.1602852357318; Fri, 16 Oct 2020 05:45:57 -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.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:45:56 -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 1/3] NFS: Use cred from fscontext during fsmount Date: Fri, 16 Oct 2020 05:45:48 -0700 Message-Id: <20201016124550.10739-2-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 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org In several patches, support was introduced to NFS for user namespaces: ccfe51a5161c: SUNRPC: Fix the server AUTH_UNIX userspace mappings e6667c73a27d: SUNRPC: rsi_parse() should use the current user namespace 1a58e8a0e5c1: NFS: Store the credential of the mount process in the nfs_server 283ebe3ec415: SUNRPC: Use the client user namespace when encoding creds ac83228a7101: SUNRPC: Use namespace of listening daemon in the client AUTH_GSS upcall 264d948ce7d0: NFS: Convert NFSv3 to use the container user namespace 58002399da65: NFSv4: Convert the NFS client idmapper to use the container user namespace c207db2f5da5: NFS: Convert NFSv2 to use the container user namespace 3b7eb5e35d0f: NFS: When mounting, don't share filesystems between different user namespaces All of these commits are predicated on the NFS server being created with credentials that are in the user namespace of interest. The new VFS mount APIs help in this[1], in that the creation of the FSFD (fsopen) captures a set of credentials at creation time. Normally, the new file system API users automatically get their super block's user_ns set to the fc->user_ns in sget_fc, but since NFS has to do special manipulation of UIDs / GIDs on the wire, it keeps track of credentials itself. Unfortunately, the credentials that the NFS uses are the current_creds at the time FSCONFIG_CMD_CREATE is called. When FSCONFIG_CMD_CREATE is called, simultaneously, mount_capable is checked -- which checks if the user has CAP_SYS_ADMIN in the init_user_ns because NFS does not have FS_USERNS_MOUNT. This makes a subtle change so that the struct cred from fsopen is used instead. Since the fs_context is available at server creation time, and it has the credentials, we can just use those. This roughly allows a privileged user to mount on behalf of an unprivileged usernamespace, by forking off and calling fsopen in the unprivileged user namespace. It can then pass back that fsfd to the privileged process which can configure the NFS mount, and then it can call FSCONFIG_CMD_CREATE before switching back into the mount namespace of the container, and finish up the mounting process and call fsmount and move_mount. This change makes a small user space change if the user performs this elaborate process of passing around file descriptors, and switching namespaces. There may be a better way to go about this, or even enable FS_USERNS_MOUNT on NFS, but this seems like the safest and most straightforward approach. [1]: https://lore.kernel.org/linux-fsdevel/155059610368.17079.2220554006494174417.stgit@warthog.procyon.org.uk/ 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/client.c | 2 +- fs/nfs/nfs4client.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index f1ff3076e4a4..fdefcc649884 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -967,7 +967,7 @@ struct nfs_server *nfs_create_server(struct fs_context *fc) if (!server) return ERR_PTR(-ENOMEM); - server->cred = get_cred(current_cred()); + server->cred = get_cred(fc->cred); error = -ENOMEM; fattr = nfs_alloc_fattr(); diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 0bd77cc1f639..92ff6fb8e324 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -1120,7 +1120,7 @@ struct nfs_server *nfs4_create_server(struct fs_context *fc) if (!server) return ERR_PTR(-ENOMEM); - server->cred = get_cred(current_cred()); + server->cred = get_cred(fc->cred); auth_probe = ctx->auth_info.flavor_len < 1; From patchwork Fri Oct 16 12:45:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841685 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9663A1752 for ; Fri, 16 Oct 2020 12:46:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DBFC207F7 for ; Fri, 16 Oct 2020 12:46:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="zLSr0gdG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405534AbgJPMqG (ORCPT ); Fri, 16 Oct 2020 08:46:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38220 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407817AbgJPMqA (ORCPT ); Fri, 16 Oct 2020 08:46:00 -0400 Received: from mail-pj1-x1043.google.com (mail-pj1-x1043.google.com [IPv6:2607:f8b0:4864:20::1043]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B78F7C0613D4 for ; Fri, 16 Oct 2020 05:45:59 -0700 (PDT) Received: by mail-pj1-x1043.google.com with SMTP id g16so1331441pjv.3 for ; Fri, 16 Oct 2020 05:45:59 -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=zfpu2RY3BLQcacz+b5uN64wMjRtGFL0k4RIBY8oywBk=; b=zLSr0gdG5dO5uL02lr6hhuWgPJuV+DhuryfJMwauvX/vNTPfarbu9cjvo3WOFkCkLo heEsHVHcI3pREiOh1IKTstIV7vqySOCMyvmib8udbhXEbacXX0k5p3Xp6s/gYmIJu/Jr DycwHU8agAL+X2PLKZMGkPBB6/H+WIAUXqN+M= 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=zfpu2RY3BLQcacz+b5uN64wMjRtGFL0k4RIBY8oywBk=; b=p26Aa03bs9PrJTztZzYKepAr7P/iZuIX+kAJU0f8eIpRQl40kYNpHDSbBcByRqXI67 in5LTuQCCpSaomYrvPTwifi5iqt7xw/H1NjZXNUz65xqKus6XlLaVCjgfo3MI/uAowB+ khjdHGfMZ0SADSeX5G8dx7ciiIXQznJzLZydH2wl2JRr3aqK7KHHoqAyYtXqNxQT0tgz pmuEjT8uC+mHfQrNsT1JJCPplREiFtFxPqPQF1bTGbnzMAgFKr/m2aqi4a95f1tJIvFp uYSvXpjvFWkaCFUmljrTQhOtcdnXIFJSIalTpxVKIup1fCGsgPp5qFzUsHQLHEY6pQ3W rmuQ== X-Gm-Message-State: AOAM533bfCJL1I1nf/bUmCiWv3ZR8pbD35M8IE9Yp6I+8Ym34ARltcyj 43UeXXMn8j40Zs0HiON3UkCUig== X-Google-Smtp-Source: ABdhPJyeag97Mst00bO6+fLuoKv3MWaZDzeEJpTxt89tqvPlQVOhT9RhMDQgWCQDPaOaCeFY6zrizg== X-Received: by 2002:a17:90b:717:: with SMTP id s23mr4005616pjz.122.1602852359020; Fri, 16 Oct 2020 05:45:59 -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.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:45:58 -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 2/3] samples/vfs: Split out common code for new syscall APIs Date: Fri, 16 Oct 2020 05:45:49 -0700 Message-Id: <20201016124550.10739-3-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 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org There are a bunch of helper functions which make using the new mount APIs much easier. As we add examples of leveraging the new APIs, it probably makes sense to promote code reuse. Signed-off-by: Sargun Dhillon Cc: David Howells Cc: Al Viro Cc: Kyle Anderson --- samples/vfs/Makefile | 2 + samples/vfs/test-fsmount.c | 86 +------------------------------------- samples/vfs/vfs-helper.c | 43 +++++++++++++++++++ samples/vfs/vfs-helper.h | 55 ++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 85 deletions(-) create mode 100644 samples/vfs/vfs-helper.c create mode 100644 samples/vfs/vfs-helper.h diff --git a/samples/vfs/Makefile b/samples/vfs/Makefile index 00b6824f9237..7f76875eaa70 100644 --- a/samples/vfs/Makefile +++ b/samples/vfs/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only +test-fsmount-objs := test-fsmount.o vfs-helper.o userprogs := test-fsmount test-statx + always-y := $(userprogs) userccflags += -I usr/include diff --git a/samples/vfs/test-fsmount.c b/samples/vfs/test-fsmount.c index 50f47b72e85f..36a4fa886200 100644 --- a/samples/vfs/test-fsmount.c +++ b/samples/vfs/test-fsmount.c @@ -14,91 +14,7 @@ #include #include #include - -#define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0) - -static void check_messages(int fd) -{ - char buf[4096]; - int err, n; - - err = errno; - - for (;;) { - n = read(fd, buf, sizeof(buf)); - if (n < 0) - break; - n -= 2; - - switch (buf[0]) { - case 'e': - fprintf(stderr, "Error: %*.*s\n", n, n, buf + 2); - break; - case 'w': - fprintf(stderr, "Warning: %*.*s\n", n, n, buf + 2); - break; - case 'i': - fprintf(stderr, "Info: %*.*s\n", n, n, buf + 2); - break; - } - } - - errno = err; -} - -static __attribute__((noreturn)) -void mount_error(int fd, const char *s) -{ - check_messages(fd); - fprintf(stderr, "%s: %m\n", s); - exit(1); -} - -/* Hope -1 isn't a syscall */ -#ifndef __NR_fsopen -#define __NR_fsopen -1 -#endif -#ifndef __NR_fsmount -#define __NR_fsmount -1 -#endif -#ifndef __NR_fsconfig -#define __NR_fsconfig -1 -#endif -#ifndef __NR_move_mount -#define __NR_move_mount -1 -#endif - - -static inline int fsopen(const char *fs_name, unsigned int flags) -{ - return syscall(__NR_fsopen, fs_name, flags); -} - -static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags) -{ - return syscall(__NR_fsmount, fsfd, flags, ms_flags); -} - -static inline int fsconfig(int fsfd, unsigned int cmd, - const char *key, const void *val, int aux) -{ - return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux); -} - -static inline int move_mount(int from_dfd, const char *from_pathname, - int to_dfd, const char *to_pathname, - unsigned int flags) -{ - return syscall(__NR_move_mount, - from_dfd, from_pathname, - to_dfd, to_pathname, flags); -} - -#define E_fsconfig(fd, cmd, key, val, aux) \ - do { \ - if (fsconfig(fd, cmd, key, val, aux) == -1) \ - mount_error(fd, key ?: "create"); \ - } while (0) +#include "vfs-helper.h" int main(int argc, char *argv[]) { diff --git a/samples/vfs/vfs-helper.c b/samples/vfs/vfs-helper.c new file mode 100644 index 000000000000..136c6cb81540 --- /dev/null +++ b/samples/vfs/vfs-helper.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include "vfs-helper.h" + +void check_messages(int fd) +{ + char buf[4096]; + int err, n; + + err = errno; + + for (;;) { + n = read(fd, buf, sizeof(buf)); + if (n < 0) + break; + n -= 2; + + switch (buf[0]) { + case 'e': + fprintf(stderr, "Error: %*.*s\n", n, n, buf + 2); + break; + case 'w': + fprintf(stderr, "Warning: %*.*s\n", n, n, buf + 2); + break; + case 'i': + fprintf(stderr, "Info: %*.*s\n", n, n, buf + 2); + break; + } + } + + errno = err; +} + +__attribute__((noreturn)) +void mount_error(int fd, const char *s) +{ + check_messages(fd); + fprintf(stderr, "%s: %m\n", s); + exit(1); +} diff --git a/samples/vfs/vfs-helper.h b/samples/vfs/vfs-helper.h new file mode 100644 index 000000000000..28c441f2fcbf --- /dev/null +++ b/samples/vfs/vfs-helper.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include +#include +#include + +#define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0) + +/* Hope -1 isn't a syscall */ +#ifndef __NR_fsopen +#define __NR_fsopen -1 +#endif +#ifndef __NR_fsmount +#define __NR_fsmount -1 +#endif +#ifndef __NR_fsconfig +#define __NR_fsconfig -1 +#endif +#ifndef __NR_move_mount +#define __NR_move_mount -1 +#endif + +#define E_fsconfig(fd, cmd, key, val, aux) \ + do { \ + if (fsconfig(fd, cmd, key, val, aux) == -1) \ + mount_error(fd, key ?: "create"); \ + } while (0) + +static inline int fsopen(const char *fs_name, unsigned int flags) +{ + return syscall(__NR_fsopen, fs_name, flags); +} + +static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags) +{ + return syscall(__NR_fsmount, fsfd, flags, ms_flags); +} + +static inline int fsconfig(int fsfd, unsigned int cmd, + const char *key, const void *val, int aux) +{ + return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux); +} + +static inline int move_mount(int from_dfd, const char *from_pathname, + int to_dfd, const char *to_pathname, + unsigned int flags) +{ + return syscall(__NR_move_mount, + from_dfd, from_pathname, + to_dfd, to_pathname, flags); +} + +__attribute__((noreturn)) +void mount_error(int fd, const char *s); +void check_messages(int fd); From patchwork Fri Oct 16 12:45:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841691 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C07FE15E6 for ; Fri, 16 Oct 2020 12:46:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 95A2F207E8 for ; Fri, 16 Oct 2020 12:46:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="yEtWgvz7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407839AbgJPMqN (ORCPT ); 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-Google-Smtp-Source: ABdhPJwopKhTcd5efvly6yqdL5APFJcFTFOl+PUbxxo8hSB6Y5ASyHdEt4/NsC+tZyTziioLvOti8Q== 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 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; +}