aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 471a75f11ea..5b3207f557d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -104,6 +104,8 @@ static int nfs4_map_errors(int err)
104 return -EACCES; 104 return -EACCES;
105 case -NFS4ERR_MINOR_VERS_MISMATCH: 105 case -NFS4ERR_MINOR_VERS_MISMATCH:
106 return -EPROTONOSUPPORT; 106 return -EPROTONOSUPPORT;
107 case -NFS4ERR_ACCESS:
108 return -EACCES;
107 default: 109 default:
108 dprintk("%s could not handle NFSv4 error %d\n", 110 dprintk("%s could not handle NFSv4 error %d\n",
109 __func__, -err); 111 __func__, -err);
@@ -860,6 +862,9 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
860 p->o_arg.fh = NFS_FH(dir); 862 p->o_arg.fh = NFS_FH(dir);
861 p->o_arg.open_flags = flags; 863 p->o_arg.open_flags = flags;
862 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); 864 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
865 /* ask server to check for all possible rights as results are cached */
866 p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY |
867 NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE;
863 p->o_arg.clientid = server->nfs_client->cl_clientid; 868 p->o_arg.clientid = server->nfs_client->cl_clientid;
864 p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); 869 p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
865 p->o_arg.id.uniquifier = sp->so_seqid.owner_id; 870 p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
@@ -1643,6 +1648,39 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
1643 return status; 1648 return status;
1644} 1649}
1645 1650
1651static int nfs4_opendata_access(struct rpc_cred *cred,
1652 struct nfs4_opendata *opendata,
1653 struct nfs4_state *state, fmode_t fmode)
1654{
1655 struct nfs_access_entry cache;
1656 u32 mask;
1657
1658 /* access call failed or for some reason the server doesn't
1659 * support any access modes -- defer access call until later */
1660 if (opendata->o_res.access_supported == 0)
1661 return 0;
1662
1663 mask = 0;
1664 if (fmode & FMODE_READ)
1665 mask |= MAY_READ;
1666 if (fmode & FMODE_WRITE)
1667 mask |= MAY_WRITE;
1668 if (fmode & FMODE_EXEC)
1669 mask |= MAY_EXEC;
1670
1671 cache.cred = cred;
1672 cache.jiffies = jiffies;
1673 nfs_access_set_mask(&cache, opendata->o_res.access_result);
1674 nfs_access_add_cache(state->inode, &cache);
1675
1676 if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
1677 return 0;
1678
1679 /* even though OPEN succeeded, access is denied. Close the file */
1680 nfs4_close_state(state, fmode);
1681 return -NFS4ERR_ACCESS;
1682}
1683
1646/* 1684/*
1647 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata 1685 * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
1648 */ 1686 */
@@ -1900,6 +1938,10 @@ static int _nfs4_do_open(struct inode *dir,
1900 if (server->caps & NFS_CAP_POSIX_LOCK) 1938 if (server->caps & NFS_CAP_POSIX_LOCK)
1901 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); 1939 set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
1902 1940
1941 status = nfs4_opendata_access(cred, opendata, state, fmode);
1942 if (status != 0)
1943 goto err_opendata_put;
1944
1903 if (opendata->o_arg.open_flags & O_EXCL) { 1945 if (opendata->o_arg.open_flags & O_EXCL) {
1904 nfs4_exclusive_attrset(opendata, sattr); 1946 nfs4_exclusive_attrset(opendata, sattr);
1905 1947
@@ -1945,7 +1987,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
1945 struct nfs4_state *res; 1987 struct nfs4_state *res;
1946 int status; 1988 int status;
1947 1989
1948 fmode &= FMODE_READ|FMODE_WRITE; 1990 fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC;
1949 do { 1991 do {
1950 status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, 1992 status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
1951 &res, ctx_th); 1993 &res, ctx_th);
@@ -2771,13 +2813,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
2771 2813
2772 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); 2814 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
2773 if (!status) { 2815 if (!status) {
2774 entry->mask = 0; 2816 nfs_access_set_mask(entry, res.access);
2775 if (res.access & NFS4_ACCESS_READ)
2776 entry->mask |= MAY_READ;
2777 if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
2778 entry->mask |= MAY_WRITE;
2779 if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
2780 entry->mask |= MAY_EXEC;
2781 nfs_refresh_inode(inode, res.fattr); 2817 nfs_refresh_inode(inode, res.fattr);
2782 } 2818 }
2783 nfs_free_fattr(res.fattr); 2819 nfs_free_fattr(res.fattr);