| From 1574dff8996ab1ed92c09012f8038b5566fce313 Mon Sep 17 00:00:00 2001 |
| From: Sachin Prabhu <sprabhu@redhat.com> |
| Date: Wed, 20 Apr 2011 13:09:35 +0100 |
| Subject: Open with O_CREAT flag set fails to open existing files on non writable directories |
| |
| From: Sachin Prabhu <sprabhu@redhat.com> |
| |
| commit 1574dff8996ab1ed92c09012f8038b5566fce313 upstream. |
| |
| An open on a NFS4 share using the O_CREAT flag on an existing file for |
| which we have permissions to open but contained in a directory with no |
| write permissions will fail with EACCES. |
| |
| A tcpdump shows that the client had set the open mode to UNCHECKED which |
| indicates that the file should be created if it doesn't exist and |
| encountering an existing flag is not an error. Since in this case the |
| file exists and can be opened by the user, the NFS server is wrong in |
| attempting to check create permissions on the parent directory. |
| |
| The patch adds a conditional statement to check for create permissions |
| only if the file doesn't exist. |
| |
| Signed-off-by: Sachin S. Prabhu <sprabhu@redhat.com> |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nfsd/vfs.c | 9 ++++++++- |
| 1 file changed, 8 insertions(+), 1 deletion(-) |
| |
| --- a/fs/nfsd/vfs.c |
| +++ b/fs/nfsd/vfs.c |
| @@ -1387,7 +1387,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s |
| goto out; |
| if (!(iap->ia_valid & ATTR_MODE)) |
| iap->ia_mode = 0; |
| - err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); |
| + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); |
| if (err) |
| goto out; |
| |
| @@ -1409,6 +1409,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s |
| if (IS_ERR(dchild)) |
| goto out_nfserr; |
| |
| + /* If file doesn't exist, check for permissions to create one */ |
| + if (!dchild->d_inode) { |
| + err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); |
| + if (err) |
| + goto out; |
| + } |
| + |
| err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); |
| if (err) |
| goto out; |