aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c16
-rw-r--r--fs/nfs/nfs4proc.c52
-rw-r--r--fs/nfs/nfs4xdr.c16
3 files changed, 71 insertions, 13 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 627f108ede23..ce8cb926526b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2072,7 +2072,7 @@ found:
2072 nfs_access_free_entry(entry); 2072 nfs_access_free_entry(entry);
2073} 2073}
2074 2074
2075static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) 2075void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
2076{ 2076{
2077 struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); 2077 struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
2078 if (cache == NULL) 2078 if (cache == NULL)
@@ -2098,6 +2098,20 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s
2098 spin_unlock(&nfs_access_lru_lock); 2098 spin_unlock(&nfs_access_lru_lock);
2099 } 2099 }
2100} 2100}
2101EXPORT_SYMBOL_GPL(nfs_access_add_cache);
2102
2103void nfs_access_set_mask(struct nfs_access_entry *entry, u32 access_result)
2104{
2105 entry->mask = 0;
2106 if (access_result & NFS4_ACCESS_READ)
2107 entry->mask |= MAY_READ;
2108 if (access_result &
2109 (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
2110 entry->mask |= MAY_WRITE;
2111 if (access_result & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
2112 entry->mask |= MAY_EXEC;
2113}
2114EXPORT_SYMBOL_GPL(nfs_access_set_mask);
2101 2115
2102static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) 2116static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
2103{ 2117{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 471a75f11ea2..5b3207f557d9 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);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 7ab29abb3160..657483c34e28 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -447,12 +447,14 @@ static int nfs4_stat_to_errno(int);
447 encode_sequence_maxsz + \ 447 encode_sequence_maxsz + \
448 encode_putfh_maxsz + \ 448 encode_putfh_maxsz + \
449 encode_open_maxsz + \ 449 encode_open_maxsz + \
450 encode_access_maxsz + \
450 encode_getfh_maxsz + \ 451 encode_getfh_maxsz + \
451 encode_getattr_maxsz) 452 encode_getattr_maxsz)
452#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ 453#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
453 decode_sequence_maxsz + \ 454 decode_sequence_maxsz + \
454 decode_putfh_maxsz + \ 455 decode_putfh_maxsz + \
455 decode_open_maxsz + \ 456 decode_open_maxsz + \
457 decode_access_maxsz + \
456 decode_getfh_maxsz + \ 458 decode_getfh_maxsz + \
457 decode_getattr_maxsz) 459 decode_getattr_maxsz)
458#define NFS4_enc_open_confirm_sz \ 460#define NFS4_enc_open_confirm_sz \
@@ -467,11 +469,13 @@ static int nfs4_stat_to_errno(int);
467 encode_sequence_maxsz + \ 469 encode_sequence_maxsz + \
468 encode_putfh_maxsz + \ 470 encode_putfh_maxsz + \
469 encode_open_maxsz + \ 471 encode_open_maxsz + \
472 encode_access_maxsz + \
470 encode_getattr_maxsz) 473 encode_getattr_maxsz)
471#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ 474#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
472 decode_sequence_maxsz + \ 475 decode_sequence_maxsz + \
473 decode_putfh_maxsz + \ 476 decode_putfh_maxsz + \
474 decode_open_maxsz + \ 477 decode_open_maxsz + \
478 decode_access_maxsz + \
475 decode_getattr_maxsz) 479 decode_getattr_maxsz)
476#define NFS4_enc_open_downgrade_sz \ 480#define NFS4_enc_open_downgrade_sz \
477 (compound_encode_hdr_maxsz + \ 481 (compound_encode_hdr_maxsz + \
@@ -2220,6 +2224,7 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
2220 encode_putfh(xdr, args->fh, &hdr); 2224 encode_putfh(xdr, args->fh, &hdr);
2221 encode_open(xdr, args, &hdr); 2225 encode_open(xdr, args, &hdr);
2222 encode_getfh(xdr, &hdr); 2226 encode_getfh(xdr, &hdr);
2227 encode_access(xdr, args->access, &hdr);
2223 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr); 2228 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
2224 encode_nops(&hdr); 2229 encode_nops(&hdr);
2225} 2230}
@@ -2256,6 +2261,7 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
2256 encode_sequence(xdr, &args->seq_args, &hdr); 2261 encode_sequence(xdr, &args->seq_args, &hdr);
2257 encode_putfh(xdr, args->fh, &hdr); 2262 encode_putfh(xdr, args->fh, &hdr);
2258 encode_open(xdr, args, &hdr); 2263 encode_open(xdr, args, &hdr);
2264 encode_access(xdr, args->access, &hdr);
2259 encode_getfattr(xdr, args->bitmask, &hdr); 2265 encode_getfattr(xdr, args->bitmask, &hdr);
2260 encode_nops(&hdr); 2266 encode_nops(&hdr);
2261} 2267}
@@ -4099,7 +4105,7 @@ out_overflow:
4099 return -EIO; 4105 return -EIO;
4100} 4106}
4101 4107
4102static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access) 4108static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
4103{ 4109{
4104 __be32 *p; 4110 __be32 *p;
4105 uint32_t supp, acc; 4111 uint32_t supp, acc;
@@ -4113,8 +4119,8 @@ static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
4113 goto out_overflow; 4119 goto out_overflow;
4114 supp = be32_to_cpup(p++); 4120 supp = be32_to_cpup(p++);
4115 acc = be32_to_cpup(p); 4121 acc = be32_to_cpup(p);
4116 access->supported = supp; 4122 *supported = supp;
4117 access->access = acc; 4123 *access = acc;
4118 return 0; 4124 return 0;
4119out_overflow: 4125out_overflow:
4120 print_overflow_msg(__func__, xdr); 4126 print_overflow_msg(__func__, xdr);
@@ -5892,7 +5898,7 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
5892 status = decode_putfh(xdr); 5898 status = decode_putfh(xdr);
5893 if (status != 0) 5899 if (status != 0)
5894 goto out; 5900 goto out;
5895 status = decode_access(xdr, res); 5901 status = decode_access(xdr, &res->supported, &res->access);
5896 if (status != 0) 5902 if (status != 0)
5897 goto out; 5903 goto out;
5898 decode_getfattr(xdr, res->fattr, res->server); 5904 decode_getfattr(xdr, res->fattr, res->server);
@@ -6233,6 +6239,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6233 status = decode_getfh(xdr, &res->fh); 6239 status = decode_getfh(xdr, &res->fh);
6234 if (status) 6240 if (status)
6235 goto out; 6241 goto out;
6242 decode_access(xdr, &res->access_supported, &res->access_result);
6236 decode_getfattr(xdr, res->f_attr, res->server); 6243 decode_getfattr(xdr, res->f_attr, res->server);
6237out: 6244out:
6238 return status; 6245 return status;
@@ -6281,6 +6288,7 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
6281 status = decode_open(xdr, res); 6288 status = decode_open(xdr, res);
6282 if (status) 6289 if (status)
6283 goto out; 6290 goto out;
6291 decode_access(xdr, &res->access_supported, &res->access_result);
6284 decode_getfattr(xdr, res->f_attr, res->server); 6292 decode_getfattr(xdr, res->f_attr, res->server);
6285out: 6293out:
6286 return status; 6294 return status;