From patchwork Fri Jul 28 17:54:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Catalin Marinas X-Patchwork-Id: 108905 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp674502qge; Fri, 28 Jul 2017 10:55:04 -0700 (PDT) X-Received: by 10.98.202.12 with SMTP id n12mr8362214pfg.187.1501264504410; Fri, 28 Jul 2017 10:55:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501264504; cv=none; d=google.com; s=arc-20160816; b=vCqMEr3KnyWdmnWB0JGjLLD5Z5gnQ71wHPBAKiIrtXikmgifXbyO8UfxKn5VfcM9Ot NgUAHNkAhPbgSQ1ufu7Im/+qklVcF3XimXZednsWNlxYuDPszc/KiSWdM1mfempAC6TB 3GKo+Yh3jijseeWCaIiHgCkLcM4/LX4LLLKj8jS0HtVydefdtAJofdGqRFovbNvsOAb1 vUKpX7CDGp5gsvWmeez2eenqLxr1cNTN8d/208LRaUctxP1Chqyx4WfZGs4gAfpAJrUo DAQ1z+UgBuG3prwKvNUSeqTXyhJNJekmeVIAEPYwawVh93CohXqbSd5bf+DqV9se0hkk jBwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=aJCNYWnzWzr9jo5Ksc2Dd1us6j6f0P2IjKbrwiJkFqk=; b=jeQQGcm/KmUIr9o96BBXALf9dcv04mZ/VryKh019D4UU0aQvhkoxL7fdPbQ4+oVLse 3agl4mqXae9FS2ucxBUwCKw0ppc7/iLFYsekP4mC0MASWeP/nVA8/077vscyKusejsgk wlRb0D4+wz2BnyXal3EeBrGESewEjvNg2l5dJro7kxDRqzPZ8/cBnab73Zan/WgRwcDN ZtgYMW/ZPzdtaaDq9JSYCnFpGmQ2EYBP/t0VWIxsw4cEkbfrKwRYhgFWYJc2RhRrwgQZ k8jYiejwk17tFr7Hel7KNcsOZhqG/PFDKMYu5FXtYpi4R3JZQ+bLpcMTdm//6V5gj0UA nzMg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d4si13445302pln.567.2017.07.28.10.55.04; Fri, 28 Jul 2017 10:55:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752625AbdG1RzB (ORCPT + 26 others); Fri, 28 Jul 2017 13:55:01 -0400 Received: from foss.arm.com ([217.140.101.70]:33720 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752204AbdG1RzA (ORCPT ); Fri, 28 Jul 2017 13:55:00 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B86E380D; Fri, 28 Jul 2017 10:54:59 -0700 (PDT) Received: from armageddon.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id C67FA3F540; Fri, 28 Jul 2017 10:54:58 -0700 (PDT) From: Catalin Marinas To: linux-nfs@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Trond Myklebust , Anna Schumaker Subject: [RFC PATCH] NFS: Fix the access mask checks in NFSv4 Date: Fri, 28 Jul 2017 18:54:52 +0100 Message-Id: <20170728175452.49057-1-catalin.marinas@arm.com> X-Mailer: git-send-email 2.11.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit bd8b2441742b ("NFS: Store the raw NFS access mask in the inode's access cache") changed the way access mask is stored in struct nfs_access_entry. However, there a are couple of places NFSv4 code where it still uses the generic access bits instead of the raw NFS ones (e.g. MAY_READ instead of NFS_MAY_READ). Fixes: bd8b2441742b ("NFS: Store the raw NFS access mask in the inode's access cache") Cc: Trond Myklebust Cc: Anna Schumaker Signed-off-by: Catalin Marinas --- Hi Trond, I noticed with 4.13-rc2 on an arm64 system that I get random EPERM errors with an NFS root filesystem (only tried v4). The patch below appears to fix the problem, as is reverting the above commit and the next one in your series. Looking at nfs3_proc_access(), it appears it has the same problem. Happy to fix that as well if you think that's the right way. Thanks. fs/nfs/dir.c | 3 ++- fs/nfs/nfs4proc.c | 23 ++++------------------- include/linux/nfs_fs.h | 1 + 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3522b1249019..828a04924770 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2381,7 +2381,7 @@ EXPORT_SYMBOL_GPL(nfs_access_add_cache); #define NFS_DIR_MAY_WRITE NFS_MAY_WRITE #define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP) #define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE) -static int +int nfs_access_calc_mask(u32 access_result, umode_t umode) { int mask = 0; @@ -2402,6 +2402,7 @@ nfs_access_calc_mask(u32 access_result, umode_t umode) mask |= MAY_WRITE; return mask; } +EXPORT_SYMBOL_GPL(nfs_access_calc_mask); void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result) { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a0b4e1091340..b53b6ec21126 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2236,7 +2236,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred, int openflags) { struct nfs_access_entry cache; - u32 mask; + int mask, cache_mask; /* access call failed or for some reason the server doesn't * support any access modes -- defer access call until later */ @@ -2259,7 +2259,8 @@ static int nfs4_opendata_access(struct rpc_cred *cred, nfs_access_set_mask(&cache, opendata->o_res.access_result); nfs_access_add_cache(state->inode, &cache); - if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0) + cache_mask = nfs_access_calc_mask(cache.mask, state->inode->i_mode); + if ((mask & ~cache_mask & (MAY_READ | MAY_EXEC)) == 0) return 0; return -EACCES; @@ -3870,25 +3871,9 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry .rpc_resp = &res, .rpc_cred = entry->cred, }; - int mode = entry->mask; int status = 0; - /* - * Determine which access bits we want to ask for... - */ - if (mode & MAY_READ) - args.access |= NFS4_ACCESS_READ; - if (S_ISDIR(inode->i_mode)) { - if (mode & MAY_WRITE) - args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE; - if (mode & MAY_EXEC) - args.access |= NFS4_ACCESS_LOOKUP; - } else { - if (mode & MAY_WRITE) - args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND; - if (mode & MAY_EXEC) - args.access |= NFS4_ACCESS_EXECUTE; - } + args.access = entry->mask; res.fattr = nfs_alloc_fattr(); if (res.fattr == NULL) diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 5cc91d6381a3..792fd5049e91 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -340,6 +340,7 @@ extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct extern int nfs_getattr(const struct path *, struct kstat *, u32, unsigned int); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_set_mask(struct nfs_access_entry *, u32); +extern int nfs_access_calc_mask(u32 access_result, umode_t umode); extern int nfs_permission(struct inode *, int); extern int nfs_open(struct inode *, struct file *); extern int nfs_attribute_cache_expired(struct inode *inode);