From patchwork Fri Oct 16 12:37:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841673 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 0757414B5 for ; Fri, 16 Oct 2020 12:38:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CF24F21556 for ; Fri, 16 Oct 2020 12:38:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="Fclu/Hcd" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2394863AbgJPMiK (ORCPT ); Fri, 16 Oct 2020 08:38:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407659AbgJPMh6 (ORCPT ); Fri, 16 Oct 2020 08:37:58 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85E14C0613D8 for ; Fri, 16 Oct 2020 05:37:57 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id w11so1204216pll.8 for ; Fri, 16 Oct 2020 05:37:57 -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=Fclu/Hcd9RUYb5bhdLv7nP6MVmLHBec0xUHjiPj2P9iuLZ2oZ78cy16qzjTX1AnSF+ JWidmtD/NwsrtFvD4tYxFSvZbydhfqut8Mf3U44L72etGGSU0TvzgWeDJ5OMJKrvJRg8 BNykXmTdlVRYyBa5otSpqUSF2TAon2r3LN9GA= 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=cK0442WL9vaa3tSsaQLpZ+vFqGJWtt1Qn10Y4MlRs0kFqWvdT8T+/XP/lwRMxzhh8m 0ng82DLFSHm/pnqEv2q7WZ/Ya/CUd0BkiEXAnVXXukhFVZSFResZDsKRvvxDjp16qm5x mKREBpbQFnyFRCyYkzTgFDUjmu0oIcyPnztffglNo5VwIXT/0J6aBp4SGqwxDkD/PB/d 53igCPKt0dNA7iUcqhqj/bCAcg729KKPyJQLBX+OfBO+aufPrFl5sHPNfnOXb/bORPjP U7qBsgG/Vmaqzs1H3T1GZrQMLtaIabWCAsD7DU+4i2vxgxGc9/RrrJExL1h1/5DMftia TPSw== X-Gm-Message-State: AOAM530iAUjjhaBp+aKSCgaRkKAdwoycmegyLN046DFu+nggF/VzfU9U DB5dXEwRAINgYIosUdhpmJEozA== X-Google-Smtp-Source: ABdhPJxjDFChxVXxiEd7JKRNmQQO8e1xGCxiZnHvjAwWIP91ABczY49KhJpRTA3ABUSFrK6kuQvWzg== X-Received: by 2002:a17:90a:6984:: with SMTP id s4mr4042149pjj.206.1602851876951; Fri, 16 Oct 2020 05:37:56 -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 q8sm2857216pfg.118.2020.10.16.05.37.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:37: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: [PATCH v2 1/3] NFS: Use cred from fscontext during fsmount Date: Fri, 16 Oct 2020 05:37:43 -0700 Message-Id: <20201016123745.9510-2-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201016123745.9510-1-sargun@sargun.me> References: <20201016123745.9510-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:37:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841669 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 4D444175A for ; Fri, 16 Oct 2020 12:38:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 112A921527 for ; Fri, 16 Oct 2020 12:38:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="fLa8iRJm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407655AbgJPMiE (ORCPT ); Fri, 16 Oct 2020 08:38:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36944 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407671AbgJPMiD (ORCPT ); Fri, 16 Oct 2020 08:38:03 -0400 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 398B1C061755 for ; Fri, 16 Oct 2020 05:38:00 -0700 (PDT) Received: by mail-pf1-x442.google.com with SMTP id 144so1436027pfb.4 for ; Fri, 16 Oct 2020 05:38:00 -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=HqaYZUMkPSpLLEjOUbnHI46g98PupVda3GBY5xIdI7Y=; b=fLa8iRJm3pZRFs3LJk+qvkdZNLt8PKHk1DZ1czE6YVY+NyqomcV0WvQeqMm27MzkYu GwHr9Yx7aKxkI9KBqCEb0KK0gvKxVyLQRImBDRADJRXbhZCp0QZA8THonT0ckHS8r8Hr MD8XGgWjCGZjTRE12R7TPeev+20YhPQD/UcaE= 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=HqaYZUMkPSpLLEjOUbnHI46g98PupVda3GBY5xIdI7Y=; b=frmBq9+tRffmL/vVc491nKUiyCRfUMt+YNcBAU4ae1IENkEBVev/pXP5i9jwdPae2s aNuXq4AkAvC0EGsYviB2rg01lhAiTMRgNRH3Ozm3h6rtqhvph8FSIhdxneOTnhg7XRfL 80wkvLMwXcN4EuFWQbqYifFDeMZvEezBZsLSSUGEtc6afvq9Eg3Eqp1DwUm//lW8UI7N Z07VPZYRxo7f8Uhf3kSDFwb4eabKcCG6UD49ETFZF5Xfd504vSXE3OYXCWWDnPemKGWj Fnfgp/mHYCjYt7ziEx1Yqjk4jmkvPTxWk54EB/9gKAKqXeHlmolW2WZzxW4HY0z6iyKg RJTQ== X-Gm-Message-State: AOAM533gjltnBq1ez3KgBCfZ2SX/XpIC2rv8/rnRzy67tFvYQmc2uqyx WLhro6pse3JH5gIpJqlDW4xyYg== X-Google-Smtp-Source: ABdhPJxmrT2hmJIi2JVagSZ831T8sA2/y8kiYJuLUzDNhvARz+k4ExUL23VS3oEALSZOngdaE0FZLg== X-Received: by 2002:a63:4102:: with SMTP id o2mr2932789pga.354.1602851879506; Fri, 16 Oct 2020 05:37: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 q8sm2857216pfg.118.2020.10.16.05.37.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:37: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: [PATCH v2 2/3] samples/vfs: Split out common code for new syscall APIs Date: Fri, 16 Oct 2020 05:37:44 -0700 Message-Id: <20201016123745.9510-3-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201016123745.9510-1-sargun@sargun.me> References: <20201016123745.9510-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. 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..bae2bc03c923 --- /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); +} \ No newline at end of file diff --git a/samples/vfs/vfs-helper.h b/samples/vfs/vfs-helper.h new file mode 100644 index 000000000000..be460ab48247 --- /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:37:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 11841667 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 D9C7917E6 for ; Fri, 16 Oct 2020 12:38:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B6FB321556 for ; Fri, 16 Oct 2020 12:38:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=sargun.me header.i=@sargun.me header.b="ZofBjHmF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407674AbgJPMiF (ORCPT ); Fri, 16 Oct 2020 08:38:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2407673AbgJPMiD (ORCPT ); Fri, 16 Oct 2020 08:38:03 -0400 Received: from mail-pl1-x643.google.com (mail-pl1-x643.google.com [IPv6:2607:f8b0:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38BADC0613DE for ; Fri, 16 Oct 2020 05:38:03 -0700 (PDT) Received: by mail-pl1-x643.google.com with SMTP id v12so1194194ply.12 for ; Fri, 16 Oct 2020 05:38:03 -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=ZofBjHmFEzh8k/jv3Xv9FOXjTIFt44p7MxklZsXXFBNcEvp/9mK0PgC0MpBydrarf6 Ol1T9EsuLLHcnXId30EVmeTG9qYnwkJNr7omAC6SJJyfQUORT6PK9LLSd9u07jAMdRdl Wm5Mk/khP7Oz9xIhPn+F6hMBXKGKDp4l08vXA= 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=EVYa5L6aQ+lxqpYJO0X5JfWGklwvuV9vgoMB0GiEiUbUhXTTAzaK0V0h36UV4AON9S jrjyNB8GZSdevsY4TEPSKGX8tLOU8pJar+UhreiaPlvjCbmz1wVkabJ5PjQF/8NTL09I 3cM54PjMA1kBtoE4GmocGQ90jnjtnQV2jwOP+LNiewaPzTiPcxGSNf3UfugdGP7uBkZA BgF78y7v2rsEfBNqjLpDIoOk6c269IMzUR7p2NR9NYdI6fw2qqg8vfrEVILU3mXoUivt +Qi6dva8kCrLK0+7gmi8brkVQVtTVpuofYq36mxWEUjH+qMaMGArhXr1Wkf3AgQ8a2zo 5Mfw== X-Gm-Message-State: AOAM533zlIQihCMePMwdZUE/EYzICIVfJqSk9q70BVCl4OKPc0XIltCB IUTXc2s8lD3M4VsO73g0uUbsyA== X-Google-Smtp-Source: ABdhPJydhcMiywSGELxv4usVXpQYvgMDh5G/dC07Tj4PXHyS/HRp1DtB9I1qZEhynLJ6J8Gk0l0Gyg== X-Received: by 2002:a17:90a:e391:: with SMTP id b17mr3795975pjz.33.1602851882645; Fri, 16 Oct 2020 05:38:02 -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 q8sm2857216pfg.118.2020.10.16.05.38.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 05:38:02 -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: [PATCH v2 3/3] samples/vfs: Add example leveraging NFS with new APIs and user namespaces Date: Fri, 16 Oct 2020 05:37:45 -0700 Message-Id: <20201016123745.9510-4-sargun@sargun.me> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201016123745.9510-1-sargun@sargun.me> References: <20201016123745.9510-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; +}