aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
commit0ff08ba5d066619f9973bfcdb5a21320d54219d0 (patch)
tree526e4a5799eb3023e9d5d81e81c0964b1d928a3e /fs
parentc72bb316916b1a6cf35e1d5238566ef27b0b7f80 (diff)
parentd109148111cdfcdae94f797dc142468bd0ff7557 (diff)
Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from Bruce Fields: "Changes this time include: - 4.1 enabled on the server by default: the last 4.1-specific issues I know of are fixed, so we're not going to find the rest of the bugs without more exposure. - Experimental support for NFSv4.2 MAC Labeling (to allow running selinux over NFS), from Dave Quigley. - Fixes for some delicate cache/upcall races that could cause rare server hangs; thanks to Neil Brown and Bodo Stroesser for extreme debugging persistence. - Fixes for some bugs found at the recent NFS bakeathon, mostly v4 and v4.1-specific, but also a generic bug handling fragmented rpc calls" * 'for-3.11' of git://linux-nfs.org/~bfields/linux: (31 commits) nfsd4: support minorversion 1 by default nfsd4: allow destroy_session over destroyed session svcrpc: fix failures to handle -1 uid's sunrpc: Don't schedule an upcall on a replaced cache entry. net/sunrpc: xpt_auth_cache should be ignored when expired. sunrpc/cache: ensure items removed from cache do not have pending upcalls. sunrpc/cache: use cache_fresh_unlocked consistently and correctly. sunrpc/cache: remove races with queuing an upcall. nfsd4: return delegation immediately if lease fails nfsd4: do not throw away 4.1 lock state on last unlock nfsd4: delegation-based open reclaims should bypass permissions svcrpc: don't error out on small tcp fragment svcrpc: fix handling of too-short rpc's nfsd4: minor read_buf cleanup nfsd4: fix decoding of compounds across page boundaries nfsd4: clean up nfs4_open_delegation NFSD: Don't give out read delegations on creates nfsd4: allow client to send no cb_sec flavors nfsd4: fail attempts to request gss on the backchannel nfsd4: implement minimal SP4_MACH_CRED ...
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/Kconfig16
-rw-r--r--fs/nfsd/nfs4proc.c44
-rw-r--r--fs/nfsd/nfs4state.c225
-rw-r--r--fs/nfsd/nfs4xdr.c169
-rw-r--r--fs/nfsd/nfsd.h20
-rw-r--r--fs/nfsd/nfssvc.c2
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/vfs.c28
-rw-r--r--fs/nfsd/vfs.h7
-rw-r--r--fs/nfsd/xdr4.h4
10 files changed, 413 insertions, 103 deletions
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 430b6872806f..dc8f1ef665ce 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -81,6 +81,22 @@ config NFSD_V4
81 81
82 If unsure, say N. 82 If unsure, say N.
83 83
84config NFSD_V4_SECURITY_LABEL
85 bool "Provide Security Label support for NFSv4 server"
86 depends on NFSD_V4 && SECURITY
87 help
88
89 Say Y here if you want enable fine-grained security label attribute
90 support for NFS version 4. Security labels allow security modules like
91 SELinux and Smack to label files to facilitate enforcement of their policies.
92 Without this an NFSv4 mount will have the same label on each file.
93
94 If you do not wish to enable fine-grained security labels SELinux or
95 Smack policies on NFSv4 files, say N.
96
97 WARNING: there is still a chance of backwards-incompatible protocol changes.
98 For now we recommend "Y" only for developers and testers."
99
84config NFSD_FAULT_INJECTION 100config NFSD_FAULT_INJECTION
85 bool "NFS server manual fault injection" 101 bool "NFS server manual fault injection"
86 depends on NFSD_V4 && DEBUG_KERNEL 102 depends on NFSD_V4 && DEBUG_KERNEL
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 27d74a294515..a7cee864e7b2 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -42,6 +42,36 @@
42#include "current_stateid.h" 42#include "current_stateid.h"
43#include "netns.h" 43#include "netns.h"
44 44
45#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
46#include <linux/security.h>
47
48static inline void
49nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
50{
51 struct inode *inode = resfh->fh_dentry->d_inode;
52 int status;
53
54 mutex_lock(&inode->i_mutex);
55 status = security_inode_setsecctx(resfh->fh_dentry,
56 label->data, label->len);
57 mutex_unlock(&inode->i_mutex);
58
59 if (status)
60 /*
61 * XXX: We should really fail the whole open, but we may
62 * already have created a new file, so it may be too
63 * late. For now this seems the least of evils:
64 */
65 bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
66
67 return;
68}
69#else
70static inline void
71nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
72{ }
73#endif
74
45#define NFSDDBG_FACILITY NFSDDBG_PROC 75#define NFSDDBG_FACILITY NFSDDBG_PROC
46 76
47static u32 nfsd_attrmask[] = { 77static u32 nfsd_attrmask[] = {
@@ -239,6 +269,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
239 (u32 *)open->op_verf.data, 269 (u32 *)open->op_verf.data,
240 &open->op_truncate, &open->op_created); 270 &open->op_truncate, &open->op_created);
241 271
272 if (!status && open->op_label.len)
273 nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval);
274
242 /* 275 /*
243 * Following rfc 3530 14.2.16, use the returned bitmask 276 * Following rfc 3530 14.2.16, use the returned bitmask
244 * to indicate which attributes we used to store the 277 * to indicate which attributes we used to store the
@@ -263,7 +296,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
263 296
264 nfsd4_set_open_owner_reply_cache(cstate, open, resfh); 297 nfsd4_set_open_owner_reply_cache(cstate, open, resfh);
265 accmode = NFSD_MAY_NOP; 298 accmode = NFSD_MAY_NOP;
266 if (open->op_created) 299 if (open->op_created ||
300 open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
267 accmode |= NFSD_MAY_OWNER_OVERRIDE; 301 accmode |= NFSD_MAY_OWNER_OVERRIDE;
268 status = do_open_permission(rqstp, resfh, open, accmode); 302 status = do_open_permission(rqstp, resfh, open, accmode);
269 set_change_info(&open->op_cinfo, current_fh); 303 set_change_info(&open->op_cinfo, current_fh);
@@ -637,6 +671,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
637 if (status) 671 if (status)
638 goto out; 672 goto out;
639 673
674 if (create->cr_label.len)
675 nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
676
640 if (create->cr_acl != NULL) 677 if (create->cr_acl != NULL)
641 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, 678 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
642 create->cr_bmval); 679 create->cr_bmval);
@@ -916,6 +953,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
916 setattr->sa_acl); 953 setattr->sa_acl);
917 if (status) 954 if (status)
918 goto out; 955 goto out;
956 if (setattr->sa_label.len)
957 status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
958 &setattr->sa_label);
959 if (status)
960 goto out;
919 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, 961 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
920 0, (time_t)0); 962 0, (time_t)0);
921out: 963out:
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f17051838b41..280acef6f0dc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -97,19 +97,20 @@ nfs4_lock_state(void)
97 97
98static void free_session(struct nfsd4_session *); 98static void free_session(struct nfsd4_session *);
99 99
100void nfsd4_put_session(struct nfsd4_session *ses) 100static bool is_session_dead(struct nfsd4_session *ses)
101{ 101{
102 atomic_dec(&ses->se_ref); 102 return ses->se_flags & NFS4_SESSION_DEAD;
103} 103}
104 104
105static bool is_session_dead(struct nfsd4_session *ses) 105void nfsd4_put_session(struct nfsd4_session *ses)
106{ 106{
107 return ses->se_flags & NFS4_SESSION_DEAD; 107 if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses))
108 free_session(ses);
108} 109}
109 110
110static __be32 mark_session_dead_locked(struct nfsd4_session *ses) 111static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
111{ 112{
112 if (atomic_read(&ses->se_ref)) 113 if (atomic_read(&ses->se_ref) > ref_held_by_me)
113 return nfserr_jukebox; 114 return nfserr_jukebox;
114 ses->se_flags |= NFS4_SESSION_DEAD; 115 ses->se_flags |= NFS4_SESSION_DEAD;
115 return nfs_ok; 116 return nfs_ok;
@@ -364,19 +365,12 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
364} 365}
365 366
366static struct nfs4_delegation * 367static struct nfs4_delegation *
367alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) 368alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
368{ 369{
369 struct nfs4_delegation *dp; 370 struct nfs4_delegation *dp;
370 struct nfs4_file *fp = stp->st_file; 371 struct nfs4_file *fp = stp->st_file;
371 372
372 dprintk("NFSD alloc_init_deleg\n"); 373 dprintk("NFSD alloc_init_deleg\n");
373 /*
374 * Major work on the lease subsystem (for example, to support
375 * calbacks on stat) will be required before we can support
376 * write delegations properly.
377 */
378 if (type != NFS4_OPEN_DELEGATE_READ)
379 return NULL;
380 if (fp->fi_had_conflict) 374 if (fp->fi_had_conflict)
381 return NULL; 375 return NULL;
382 if (num_delegations > max_delegations) 376 if (num_delegations > max_delegations)
@@ -397,7 +391,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
397 INIT_LIST_HEAD(&dp->dl_recall_lru); 391 INIT_LIST_HEAD(&dp->dl_recall_lru);
398 get_nfs4_file(fp); 392 get_nfs4_file(fp);
399 dp->dl_file = fp; 393 dp->dl_file = fp;
400 dp->dl_type = type; 394 dp->dl_type = NFS4_OPEN_DELEGATE_READ;
401 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 395 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
402 dp->dl_time = 0; 396 dp->dl_time = 0;
403 atomic_set(&dp->dl_count, 1); 397 atomic_set(&dp->dl_count, 1);
@@ -1188,6 +1182,9 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
1188 target->cr_gid = source->cr_gid; 1182 target->cr_gid = source->cr_gid;
1189 target->cr_group_info = source->cr_group_info; 1183 target->cr_group_info = source->cr_group_info;
1190 get_group_info(target->cr_group_info); 1184 get_group_info(target->cr_group_info);
1185 target->cr_gss_mech = source->cr_gss_mech;
1186 if (source->cr_gss_mech)
1187 gss_mech_get(source->cr_gss_mech);
1191 return 0; 1188 return 0;
1192} 1189}
1193 1190
@@ -1262,6 +1259,31 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1262 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal); 1259 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
1263} 1260}
1264 1261
1262static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
1263{
1264 struct svc_cred *cr = &rqstp->rq_cred;
1265 u32 service;
1266
1267 service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor);
1268 return service == RPC_GSS_SVC_INTEGRITY ||
1269 service == RPC_GSS_SVC_PRIVACY;
1270}
1271
1272static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
1273{
1274 struct svc_cred *cr = &rqstp->rq_cred;
1275
1276 if (!cl->cl_mach_cred)
1277 return true;
1278 if (cl->cl_cred.cr_gss_mech != cr->cr_gss_mech)
1279 return false;
1280 if (!svc_rqst_integrity_protected(rqstp))
1281 return false;
1282 if (!cr->cr_principal)
1283 return false;
1284 return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
1285}
1286
1265static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) 1287static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
1266{ 1288{
1267 static u32 current_clientid = 1; 1289 static u32 current_clientid = 1;
@@ -1639,16 +1661,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1639 if (exid->flags & ~EXCHGID4_FLAG_MASK_A) 1661 if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
1640 return nfserr_inval; 1662 return nfserr_inval;
1641 1663
1642 /* Currently only support SP4_NONE */
1643 switch (exid->spa_how) { 1664 switch (exid->spa_how) {
1665 case SP4_MACH_CRED:
1666 if (!svc_rqst_integrity_protected(rqstp))
1667 return nfserr_inval;
1644 case SP4_NONE: 1668 case SP4_NONE:
1645 break; 1669 break;
1646 default: /* checked by xdr code */ 1670 default: /* checked by xdr code */
1647 WARN_ON_ONCE(1); 1671 WARN_ON_ONCE(1);
1648 case SP4_SSV: 1672 case SP4_SSV:
1649 return nfserr_encr_alg_unsupp; 1673 return nfserr_encr_alg_unsupp;
1650 case SP4_MACH_CRED:
1651 return nfserr_serverfault; /* no excuse :-/ */
1652 } 1674 }
1653 1675
1654 /* Cases below refer to rfc 5661 section 18.35.4: */ 1676 /* Cases below refer to rfc 5661 section 18.35.4: */
@@ -1663,6 +1685,10 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1663 status = nfserr_inval; 1685 status = nfserr_inval;
1664 goto out; 1686 goto out;
1665 } 1687 }
1688 if (!mach_creds_match(conf, rqstp)) {
1689 status = nfserr_wrong_cred;
1690 goto out;
1691 }
1666 if (!creds_match) { /* case 9 */ 1692 if (!creds_match) { /* case 9 */
1667 status = nfserr_perm; 1693 status = nfserr_perm;
1668 goto out; 1694 goto out;
@@ -1709,7 +1735,8 @@ out_new:
1709 status = nfserr_jukebox; 1735 status = nfserr_jukebox;
1710 goto out; 1736 goto out;
1711 } 1737 }
1712 new->cl_minorversion = 1; 1738 new->cl_minorversion = cstate->minorversion;
1739 new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
1713 1740
1714 gen_clid(new, nn); 1741 gen_clid(new, nn);
1715 add_to_unconfirmed(new); 1742 add_to_unconfirmed(new);
@@ -1839,6 +1866,24 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
1839 return nfs_ok; 1866 return nfs_ok;
1840} 1867}
1841 1868
1869static __be32 nfsd4_check_cb_sec(struct nfsd4_cb_sec *cbs)
1870{
1871 switch (cbs->flavor) {
1872 case RPC_AUTH_NULL:
1873 case RPC_AUTH_UNIX:
1874 return nfs_ok;
1875 default:
1876 /*
1877 * GSS case: the spec doesn't allow us to return this
1878 * error. But it also doesn't allow us not to support
1879 * GSS.
1880 * I'd rather this fail hard than return some error the
1881 * client might think it can already handle:
1882 */
1883 return nfserr_encr_alg_unsupp;
1884 }
1885}
1886
1842__be32 1887__be32
1843nfsd4_create_session(struct svc_rqst *rqstp, 1888nfsd4_create_session(struct svc_rqst *rqstp,
1844 struct nfsd4_compound_state *cstate, 1889 struct nfsd4_compound_state *cstate,
@@ -1854,6 +1899,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1854 1899
1855 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) 1900 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
1856 return nfserr_inval; 1901 return nfserr_inval;
1902 status = nfsd4_check_cb_sec(&cr_ses->cb_sec);
1903 if (status)
1904 return status;
1857 status = check_forechannel_attrs(&cr_ses->fore_channel, nn); 1905 status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
1858 if (status) 1906 if (status)
1859 return status; 1907 return status;
@@ -1874,6 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1874 WARN_ON_ONCE(conf && unconf); 1922 WARN_ON_ONCE(conf && unconf);
1875 1923
1876 if (conf) { 1924 if (conf) {
1925 status = nfserr_wrong_cred;
1926 if (!mach_creds_match(conf, rqstp))
1927 goto out_free_conn;
1877 cs_slot = &conf->cl_cs_slot; 1928 cs_slot = &conf->cl_cs_slot;
1878 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1929 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1879 if (status == nfserr_replay_cache) { 1930 if (status == nfserr_replay_cache) {
@@ -1890,6 +1941,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1890 status = nfserr_clid_inuse; 1941 status = nfserr_clid_inuse;
1891 goto out_free_conn; 1942 goto out_free_conn;
1892 } 1943 }
1944 status = nfserr_wrong_cred;
1945 if (!mach_creds_match(unconf, rqstp))
1946 goto out_free_conn;
1893 cs_slot = &unconf->cl_cs_slot; 1947 cs_slot = &unconf->cl_cs_slot;
1894 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1948 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1895 if (status) { 1949 if (status) {
@@ -1957,7 +2011,11 @@ __be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state
1957{ 2011{
1958 struct nfsd4_session *session = cstate->session; 2012 struct nfsd4_session *session = cstate->session;
1959 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2013 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2014 __be32 status;
1960 2015
2016 status = nfsd4_check_cb_sec(&bc->bc_cb_sec);
2017 if (status)
2018 return status;
1961 spin_lock(&nn->client_lock); 2019 spin_lock(&nn->client_lock);
1962 session->se_cb_prog = bc->bc_cb_program; 2020 session->se_cb_prog = bc->bc_cb_program;
1963 session->se_cb_sec = bc->bc_cb_sec; 2021 session->se_cb_sec = bc->bc_cb_sec;
@@ -1986,6 +2044,9 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1986 status = nfserr_badsession; 2044 status = nfserr_badsession;
1987 if (!session) 2045 if (!session)
1988 goto out; 2046 goto out;
2047 status = nfserr_wrong_cred;
2048 if (!mach_creds_match(session->se_client, rqstp))
2049 goto out;
1989 status = nfsd4_map_bcts_dir(&bcts->dir); 2050 status = nfsd4_map_bcts_dir(&bcts->dir);
1990 if (status) 2051 if (status)
1991 goto out; 2052 goto out;
@@ -2014,6 +2075,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
2014{ 2075{
2015 struct nfsd4_session *ses; 2076 struct nfsd4_session *ses;
2016 __be32 status; 2077 __be32 status;
2078 int ref_held_by_me = 0;
2017 struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id); 2079 struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
2018 2080
2019 nfs4_lock_state(); 2081 nfs4_lock_state();
@@ -2021,6 +2083,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
2021 if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) { 2083 if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
2022 if (!nfsd4_last_compound_op(r)) 2084 if (!nfsd4_last_compound_op(r))
2023 goto out; 2085 goto out;
2086 ref_held_by_me++;
2024 } 2087 }
2025 dump_sessionid(__func__, &sessionid->sessionid); 2088 dump_sessionid(__func__, &sessionid->sessionid);
2026 spin_lock(&nn->client_lock); 2089 spin_lock(&nn->client_lock);
@@ -2028,17 +2091,22 @@ nfsd4_destroy_session(struct svc_rqst *r,
2028 status = nfserr_badsession; 2091 status = nfserr_badsession;
2029 if (!ses) 2092 if (!ses)
2030 goto out_client_lock; 2093 goto out_client_lock;
2031 status = mark_session_dead_locked(ses); 2094 status = nfserr_wrong_cred;
2032 if (status) 2095 if (!mach_creds_match(ses->se_client, r))
2033 goto out_client_lock; 2096 goto out_client_lock;
2097 nfsd4_get_session_locked(ses);
2098 status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
2099 if (status)
2100 goto out_put_session;
2034 unhash_session(ses); 2101 unhash_session(ses);
2035 spin_unlock(&nn->client_lock); 2102 spin_unlock(&nn->client_lock);
2036 2103
2037 nfsd4_probe_callback_sync(ses->se_client); 2104 nfsd4_probe_callback_sync(ses->se_client);
2038 2105
2039 spin_lock(&nn->client_lock); 2106 spin_lock(&nn->client_lock);
2040 free_session(ses);
2041 status = nfs_ok; 2107 status = nfs_ok;
2108out_put_session:
2109 nfsd4_put_session(ses);
2042out_client_lock: 2110out_client_lock:
2043 spin_unlock(&nn->client_lock); 2111 spin_unlock(&nn->client_lock);
2044out: 2112out:
@@ -2058,26 +2126,31 @@ static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_s
2058 return NULL; 2126 return NULL;
2059} 2127}
2060 2128
2061static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) 2129static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
2062{ 2130{
2063 struct nfs4_client *clp = ses->se_client; 2131 struct nfs4_client *clp = ses->se_client;
2064 struct nfsd4_conn *c; 2132 struct nfsd4_conn *c;
2133 __be32 status = nfs_ok;
2065 int ret; 2134 int ret;
2066 2135
2067 spin_lock(&clp->cl_lock); 2136 spin_lock(&clp->cl_lock);
2068 c = __nfsd4_find_conn(new->cn_xprt, ses); 2137 c = __nfsd4_find_conn(new->cn_xprt, ses);
2069 if (c) { 2138 if (c)
2070 spin_unlock(&clp->cl_lock); 2139 goto out_free;
2071 free_conn(new); 2140 status = nfserr_conn_not_bound_to_session;
2072 return; 2141 if (clp->cl_mach_cred)
2073 } 2142 goto out_free;
2074 __nfsd4_hash_conn(new, ses); 2143 __nfsd4_hash_conn(new, ses);
2075 spin_unlock(&clp->cl_lock); 2144 spin_unlock(&clp->cl_lock);
2076 ret = nfsd4_register_conn(new); 2145 ret = nfsd4_register_conn(new);
2077 if (ret) 2146 if (ret)
2078 /* oops; xprt is already down: */ 2147 /* oops; xprt is already down: */
2079 nfsd4_conn_lost(&new->cn_xpt_user); 2148 nfsd4_conn_lost(&new->cn_xpt_user);
2080 return; 2149 return nfs_ok;
2150out_free:
2151 spin_unlock(&clp->cl_lock);
2152 free_conn(new);
2153 return status;
2081} 2154}
2082 2155
2083static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session) 2156static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session)
@@ -2169,8 +2242,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
2169 if (status) 2242 if (status)
2170 goto out_put_session; 2243 goto out_put_session;
2171 2244
2172 nfsd4_sequence_check_conn(conn, session); 2245 status = nfsd4_sequence_check_conn(conn, session);
2173 conn = NULL; 2246 conn = NULL;
2247 if (status)
2248 goto out_put_session;
2174 2249
2175 /* Success! bump slot seqid */ 2250 /* Success! bump slot seqid */
2176 slot->sl_seqid = seq->seqid; 2251 slot->sl_seqid = seq->seqid;
@@ -2232,7 +2307,10 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2232 status = nfserr_stale_clientid; 2307 status = nfserr_stale_clientid;
2233 goto out; 2308 goto out;
2234 } 2309 }
2235 2310 if (!mach_creds_match(clp, rqstp)) {
2311 status = nfserr_wrong_cred;
2312 goto out;
2313 }
2236 expire_client(clp); 2314 expire_client(clp);
2237out: 2315out:
2238 nfs4_unlock_state(); 2316 nfs4_unlock_state();
@@ -2940,13 +3018,13 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int f
2940 return fl; 3018 return fl;
2941} 3019}
2942 3020
2943static int nfs4_setlease(struct nfs4_delegation *dp, int flag) 3021static int nfs4_setlease(struct nfs4_delegation *dp)
2944{ 3022{
2945 struct nfs4_file *fp = dp->dl_file; 3023 struct nfs4_file *fp = dp->dl_file;
2946 struct file_lock *fl; 3024 struct file_lock *fl;
2947 int status; 3025 int status;
2948 3026
2949 fl = nfs4_alloc_init_lease(dp, flag); 3027 fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
2950 if (!fl) 3028 if (!fl)
2951 return -ENOMEM; 3029 return -ENOMEM;
2952 fl->fl_file = find_readable_file(fp); 3030 fl->fl_file = find_readable_file(fp);
@@ -2964,12 +3042,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
2964 return 0; 3042 return 0;
2965} 3043}
2966 3044
2967static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) 3045static int nfs4_set_delegation(struct nfs4_delegation *dp)
2968{ 3046{
2969 struct nfs4_file *fp = dp->dl_file; 3047 struct nfs4_file *fp = dp->dl_file;
2970 3048
2971 if (!fp->fi_lease) 3049 if (!fp->fi_lease)
2972 return nfs4_setlease(dp, flag); 3050 return nfs4_setlease(dp);
2973 spin_lock(&recall_lock); 3051 spin_lock(&recall_lock);
2974 if (fp->fi_had_conflict) { 3052 if (fp->fi_had_conflict) {
2975 spin_unlock(&recall_lock); 3053 spin_unlock(&recall_lock);
@@ -3005,6 +3083,9 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
3005 3083
3006/* 3084/*
3007 * Attempt to hand out a delegation. 3085 * Attempt to hand out a delegation.
3086 *
3087 * Note we don't support write delegations, and won't until the vfs has
3088 * proper support for them.
3008 */ 3089 */
3009static void 3090static void
3010nfs4_open_delegation(struct net *net, struct svc_fh *fh, 3091nfs4_open_delegation(struct net *net, struct svc_fh *fh,
@@ -3013,39 +3094,45 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3013 struct nfs4_delegation *dp; 3094 struct nfs4_delegation *dp;
3014 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 3095 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
3015 int cb_up; 3096 int cb_up;
3016 int status = 0, flag = 0; 3097 int status = 0;
3017 3098
3018 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); 3099 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
3019 flag = NFS4_OPEN_DELEGATE_NONE;
3020 open->op_recall = 0; 3100 open->op_recall = 0;
3021 switch (open->op_claim_type) { 3101 switch (open->op_claim_type) {
3022 case NFS4_OPEN_CLAIM_PREVIOUS: 3102 case NFS4_OPEN_CLAIM_PREVIOUS:
3023 if (!cb_up) 3103 if (!cb_up)
3024 open->op_recall = 1; 3104 open->op_recall = 1;
3025 flag = open->op_delegate_type; 3105 if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
3026 if (flag == NFS4_OPEN_DELEGATE_NONE) 3106 goto out_no_deleg;
3027 goto out;
3028 break; 3107 break;
3029 case NFS4_OPEN_CLAIM_NULL: 3108 case NFS4_OPEN_CLAIM_NULL:
3030 /* Let's not give out any delegations till everyone's 3109 /*
3031 * had the chance to reclaim theirs.... */ 3110 * Let's not give out any delegations till everyone's
3111 * had the chance to reclaim theirs....
3112 */
3032 if (locks_in_grace(net)) 3113 if (locks_in_grace(net))
3033 goto out; 3114 goto out_no_deleg;
3034 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) 3115 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
3035 goto out; 3116 goto out_no_deleg;
3117 /*
3118 * Also, if the file was opened for write or
3119 * create, there's a good chance the client's
3120 * about to write to it, resulting in an
3121 * immediate recall (since we don't support
3122 * write delegations):
3123 */
3036 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 3124 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
3037 flag = NFS4_OPEN_DELEGATE_WRITE; 3125 goto out_no_deleg;
3038 else 3126 if (open->op_create == NFS4_OPEN_CREATE)
3039 flag = NFS4_OPEN_DELEGATE_READ; 3127 goto out_no_deleg;
3040 break; 3128 break;
3041 default: 3129 default:
3042 goto out; 3130 goto out_no_deleg;
3043 } 3131 }
3044 3132 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
3045 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag);
3046 if (dp == NULL) 3133 if (dp == NULL)
3047 goto out_no_deleg; 3134 goto out_no_deleg;
3048 status = nfs4_set_delegation(dp, flag); 3135 status = nfs4_set_delegation(dp);
3049 if (status) 3136 if (status)
3050 goto out_free; 3137 goto out_free;
3051 3138
@@ -3053,24 +3140,23 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3053 3140
3054 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", 3141 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
3055 STATEID_VAL(&dp->dl_stid.sc_stateid)); 3142 STATEID_VAL(&dp->dl_stid.sc_stateid));
3056out: 3143 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
3057 open->op_delegate_type = flag;
3058 if (flag == NFS4_OPEN_DELEGATE_NONE) {
3059 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3060 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
3061 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3062
3063 /* 4.1 client asking for a delegation? */
3064 if (open->op_deleg_want)
3065 nfsd4_open_deleg_none_ext(open, status);
3066 }
3067 return; 3144 return;
3068out_free: 3145out_free:
3069 unhash_stid(&dp->dl_stid); 3146 unhash_stid(&dp->dl_stid);
3070 nfs4_put_delegation(dp); 3147 nfs4_put_delegation(dp);
3071out_no_deleg: 3148out_no_deleg:
3072 flag = NFS4_OPEN_DELEGATE_NONE; 3149 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
3073 goto out; 3150 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3151 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) {
3152 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3153 open->op_recall = 1;
3154 }
3155
3156 /* 4.1 client asking for a delegation? */
3157 if (open->op_deleg_want)
3158 nfsd4_open_deleg_none_ext(open, status);
3159 return;
3074} 3160}
3075 3161
3076static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, 3162static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
@@ -3427,7 +3513,7 @@ grace_disallows_io(struct net *net, struct inode *inode)
3427/* Returns true iff a is later than b: */ 3513/* Returns true iff a is later than b: */
3428static bool stateid_generation_after(stateid_t *a, stateid_t *b) 3514static bool stateid_generation_after(stateid_t *a, stateid_t *b)
3429{ 3515{
3430 return (s32)a->si_generation - (s32)b->si_generation > 0; 3516 return (s32)(a->si_generation - b->si_generation) > 0;
3431} 3517}
3432 3518
3433static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session) 3519static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
@@ -4435,7 +4521,6 @@ __be32
4435nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 4521nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4436 struct nfsd4_locku *locku) 4522 struct nfsd4_locku *locku)
4437{ 4523{
4438 struct nfs4_lockowner *lo;
4439 struct nfs4_ol_stateid *stp; 4524 struct nfs4_ol_stateid *stp;
4440 struct file *filp = NULL; 4525 struct file *filp = NULL;
4441 struct file_lock *file_lock = NULL; 4526 struct file_lock *file_lock = NULL;
@@ -4468,10 +4553,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4468 status = nfserr_jukebox; 4553 status = nfserr_jukebox;
4469 goto out; 4554 goto out;
4470 } 4555 }
4471 lo = lockowner(stp->st_stateowner);
4472 locks_init_lock(file_lock); 4556 locks_init_lock(file_lock);
4473 file_lock->fl_type = F_UNLCK; 4557 file_lock->fl_type = F_UNLCK;
4474 file_lock->fl_owner = (fl_owner_t)lo; 4558 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4475 file_lock->fl_pid = current->tgid; 4559 file_lock->fl_pid = current->tgid;
4476 file_lock->fl_file = filp; 4560 file_lock->fl_file = filp;
4477 file_lock->fl_flags = FL_POSIX; 4561 file_lock->fl_flags = FL_POSIX;
@@ -4490,11 +4574,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4490 update_stateid(&stp->st_stid.sc_stateid); 4574 update_stateid(&stp->st_stid.sc_stateid);
4491 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4575 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4492 4576
4493 if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) {
4494 WARN_ON_ONCE(cstate->replay_owner);
4495 release_lockowner(lo);
4496 }
4497
4498out: 4577out:
4499 nfsd4_bump_seqid(cstate, status); 4578 nfsd4_bump_seqid(cstate, status);
4500 if (!cstate->replay_owner) 4579 if (!cstate->replay_owner)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6cd86e0fe450..0c0f3ea90de5 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -55,6 +55,11 @@
55#include "cache.h" 55#include "cache.h"
56#include "netns.h" 56#include "netns.h"
57 57
58#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
59#include <linux/security.h>
60#endif
61
62
58#define NFSDDBG_FACILITY NFSDDBG_XDR 63#define NFSDDBG_FACILITY NFSDDBG_XDR
59 64
60/* 65/*
@@ -134,6 +139,19 @@ xdr_error: \
134 } \ 139 } \
135} while (0) 140} while (0)
136 141
142static void next_decode_page(struct nfsd4_compoundargs *argp)
143{
144 argp->pagelist++;
145 argp->p = page_address(argp->pagelist[0]);
146 if (argp->pagelen < PAGE_SIZE) {
147 argp->end = argp->p + (argp->pagelen>>2);
148 argp->pagelen = 0;
149 } else {
150 argp->end = argp->p + (PAGE_SIZE>>2);
151 argp->pagelen -= PAGE_SIZE;
152 }
153}
154
137static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 155static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
138{ 156{
139 /* We want more bytes than seem to be available. 157 /* We want more bytes than seem to be available.
@@ -161,16 +179,7 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
161 * guarantee p points to at least nbytes bytes. 179 * guarantee p points to at least nbytes bytes.
162 */ 180 */
163 memcpy(p, argp->p, avail); 181 memcpy(p, argp->p, avail);
164 /* step to next page */ 182 next_decode_page(argp);
165 argp->p = page_address(argp->pagelist[0]);
166 argp->pagelist++;
167 if (argp->pagelen < PAGE_SIZE) {
168 argp->end = argp->p + (argp->pagelen>>2);
169 argp->pagelen = 0;
170 } else {
171 argp->end = argp->p + (PAGE_SIZE>>2);
172 argp->pagelen -= PAGE_SIZE;
173 }
174 memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); 183 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
175 argp->p += XDR_QUADLEN(nbytes - avail); 184 argp->p += XDR_QUADLEN(nbytes - avail);
176 return p; 185 return p;
@@ -242,7 +251,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
242 251
243static __be32 252static __be32
244nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, 253nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
245 struct iattr *iattr, struct nfs4_acl **acl) 254 struct iattr *iattr, struct nfs4_acl **acl,
255 struct xdr_netobj *label)
246{ 256{
247 int expected_len, len = 0; 257 int expected_len, len = 0;
248 u32 dummy32; 258 u32 dummy32;
@@ -380,6 +390,32 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
380 goto xdr_error; 390 goto xdr_error;
381 } 391 }
382 } 392 }
393
394 label->len = 0;
395#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
396 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
397 READ_BUF(4);
398 len += 4;
399 READ32(dummy32); /* lfs: we don't use it */
400 READ_BUF(4);
401 len += 4;
402 READ32(dummy32); /* pi: we don't use it either */
403 READ_BUF(4);
404 len += 4;
405 READ32(dummy32);
406 READ_BUF(dummy32);
407 if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN)
408 return nfserr_badlabel;
409 len += (XDR_QUADLEN(dummy32) << 2);
410 READMEM(buf, dummy32);
411 label->data = kzalloc(dummy32 + 1, GFP_KERNEL);
412 if (!label->data)
413 return nfserr_jukebox;
414 defer_free(argp, kfree, label->data);
415 memcpy(label->data, buf, dummy32);
416 }
417#endif
418
383 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0 419 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
384 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1 420 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
385 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) 421 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
@@ -428,7 +464,11 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_
428 /* callback_sec_params4 */ 464 /* callback_sec_params4 */
429 READ_BUF(4); 465 READ_BUF(4);
430 READ32(nr_secflavs); 466 READ32(nr_secflavs);
431 cbs->flavor = (u32)(-1); 467 if (nr_secflavs)
468 cbs->flavor = (u32)(-1);
469 else
470 /* Is this legal? Be generous, take it to mean AUTH_NONE: */
471 cbs->flavor = 0;
432 for (i = 0; i < nr_secflavs; ++i) { 472 for (i = 0; i < nr_secflavs; ++i) {
433 READ_BUF(4); 473 READ_BUF(4);
434 READ32(dummy); 474 READ32(dummy);
@@ -576,7 +616,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
576 return status; 616 return status;
577 617
578 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, 618 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
579 &create->cr_acl); 619 &create->cr_acl, &create->cr_label);
580 if (status) 620 if (status)
581 goto out; 621 goto out;
582 622
@@ -827,7 +867,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
827 case NFS4_CREATE_UNCHECKED: 867 case NFS4_CREATE_UNCHECKED:
828 case NFS4_CREATE_GUARDED: 868 case NFS4_CREATE_GUARDED:
829 status = nfsd4_decode_fattr(argp, open->op_bmval, 869 status = nfsd4_decode_fattr(argp, open->op_bmval,
830 &open->op_iattr, &open->op_acl); 870 &open->op_iattr, &open->op_acl, &open->op_label);
831 if (status) 871 if (status)
832 goto out; 872 goto out;
833 break; 873 break;
@@ -841,7 +881,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
841 READ_BUF(NFS4_VERIFIER_SIZE); 881 READ_BUF(NFS4_VERIFIER_SIZE);
842 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); 882 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
843 status = nfsd4_decode_fattr(argp, open->op_bmval, 883 status = nfsd4_decode_fattr(argp, open->op_bmval,
844 &open->op_iattr, &open->op_acl); 884 &open->op_iattr, &open->op_acl, &open->op_label);
845 if (status) 885 if (status)
846 goto out; 886 goto out;
847 break; 887 break;
@@ -1063,7 +1103,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
1063 if (status) 1103 if (status)
1064 return status; 1104 return status;
1065 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, 1105 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
1066 &setattr->sa_acl); 1106 &setattr->sa_acl, &setattr->sa_label);
1067} 1107}
1068 1108
1069static __be32 1109static __be32
@@ -1567,6 +1607,7 @@ struct nfsd4_minorversion_ops {
1567static struct nfsd4_minorversion_ops nfsd4_minorversion[] = { 1607static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
1568 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) }, 1608 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
1569 [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, 1609 [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
1610 [2] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
1570}; 1611};
1571 1612
1572static __be32 1613static __be32
@@ -1953,6 +1994,36 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
1953 FATTR4_WORD0_RDATTR_ERROR) 1994 FATTR4_WORD0_RDATTR_ERROR)
1954#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID 1995#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1955 1996
1997#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
1998static inline __be32
1999nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen)
2000{
2001 __be32 *p = *pp;
2002
2003 if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4))
2004 return nfserr_resource;
2005
2006 /*
2007 * For now we use a 0 here to indicate the null translation; in
2008 * the future we may place a call to translation code here.
2009 */
2010 if ((*buflen -= 8) < 0)
2011 return nfserr_resource;
2012
2013 WRITE32(0); /* lfs */
2014 WRITE32(0); /* pi */
2015 p = xdr_encode_opaque(p, context, len);
2016 *buflen -= (XDR_QUADLEN(len) << 2) + 4;
2017
2018 *pp = p;
2019 return 0;
2020}
2021#else
2022static inline __be32
2023nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen)
2024{ return 0; }
2025#endif
2026
1956static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) 2027static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1957{ 2028{
1958 /* As per referral draft: */ 2029 /* As per referral draft: */
@@ -2012,6 +2083,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2012 int err; 2083 int err;
2013 int aclsupport = 0; 2084 int aclsupport = 0;
2014 struct nfs4_acl *acl = NULL; 2085 struct nfs4_acl *acl = NULL;
2086 void *context = NULL;
2087 int contextlen;
2088 bool contextsupport = false;
2015 struct nfsd4_compoundres *resp = rqstp->rq_resp; 2089 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2016 u32 minorversion = resp->cstate.minorversion; 2090 u32 minorversion = resp->cstate.minorversion;
2017 struct path path = { 2091 struct path path = {
@@ -2065,6 +2139,21 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2065 } 2139 }
2066 } 2140 }
2067 2141
2142#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2143 if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) ||
2144 bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
2145 err = security_inode_getsecctx(dentry->d_inode,
2146 &context, &contextlen);
2147 contextsupport = (err == 0);
2148 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2149 if (err == -EOPNOTSUPP)
2150 bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2151 else if (err)
2152 goto out_nfserr;
2153 }
2154 }
2155#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2156
2068 if (bmval2) { 2157 if (bmval2) {
2069 if ((buflen -= 16) < 0) 2158 if ((buflen -= 16) < 0)
2070 goto out_resource; 2159 goto out_resource;
@@ -2093,6 +2182,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2093 2182
2094 if (!aclsupport) 2183 if (!aclsupport)
2095 word0 &= ~FATTR4_WORD0_ACL; 2184 word0 &= ~FATTR4_WORD0_ACL;
2185 if (!contextsupport)
2186 word2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2096 if (!word2) { 2187 if (!word2) {
2097 if ((buflen -= 12) < 0) 2188 if ((buflen -= 12) < 0)
2098 goto out_resource; 2189 goto out_resource;
@@ -2400,6 +2491,12 @@ out_acl:
2400 get_parent_attributes(exp, &stat); 2491 get_parent_attributes(exp, &stat);
2401 WRITE64(stat.ino); 2492 WRITE64(stat.ino);
2402 } 2493 }
2494 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2495 status = nfsd4_encode_security_label(rqstp, context,
2496 contextlen, &p, &buflen);
2497 if (status)
2498 goto out;
2499 }
2403 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2500 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2404 WRITE32(3); 2501 WRITE32(3);
2405 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2502 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
@@ -2412,6 +2509,10 @@ out_acl:
2412 status = nfs_ok; 2509 status = nfs_ok;
2413 2510
2414out: 2511out:
2512#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2513 if (context)
2514 security_release_secctx(context, contextlen);
2515#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2415 kfree(acl); 2516 kfree(acl);
2416 if (fhp == &tempfh) 2517 if (fhp == &tempfh)
2417 fh_put(&tempfh); 2518 fh_put(&tempfh);
@@ -3176,16 +3277,18 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
3176{ 3277{
3177 __be32 *p; 3278 __be32 *p;
3178 3279
3179 RESERVE_SPACE(12); 3280 RESERVE_SPACE(16);
3180 if (nfserr) { 3281 if (nfserr) {
3181 WRITE32(2); 3282 WRITE32(3);
3283 WRITE32(0);
3182 WRITE32(0); 3284 WRITE32(0);
3183 WRITE32(0); 3285 WRITE32(0);
3184 } 3286 }
3185 else { 3287 else {
3186 WRITE32(2); 3288 WRITE32(3);
3187 WRITE32(setattr->sa_bmval[0]); 3289 WRITE32(setattr->sa_bmval[0]);
3188 WRITE32(setattr->sa_bmval[1]); 3290 WRITE32(setattr->sa_bmval[1]);
3291 WRITE32(setattr->sa_bmval[2]);
3189 } 3292 }
3190 ADJUST_ARGS(); 3293 ADJUST_ARGS();
3191 return nfserr; 3294 return nfserr;
@@ -3226,6 +3329,14 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
3226 return nfserr; 3329 return nfserr;
3227} 3330}
3228 3331
3332static const u32 nfs4_minimal_spo_must_enforce[2] = {
3333 [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
3334 1 << (OP_EXCHANGE_ID - 32) |
3335 1 << (OP_CREATE_SESSION - 32) |
3336 1 << (OP_DESTROY_SESSION - 32) |
3337 1 << (OP_DESTROY_CLIENTID - 32)
3338};
3339
3229static __be32 3340static __be32
3230nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, 3341nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
3231 struct nfsd4_exchange_id *exid) 3342 struct nfsd4_exchange_id *exid)
@@ -3264,6 +3375,20 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
3264 /* state_protect4_r. Currently only support SP4_NONE */ 3375 /* state_protect4_r. Currently only support SP4_NONE */
3265 BUG_ON(exid->spa_how != SP4_NONE); 3376 BUG_ON(exid->spa_how != SP4_NONE);
3266 WRITE32(exid->spa_how); 3377 WRITE32(exid->spa_how);
3378 switch (exid->spa_how) {
3379 case SP4_NONE:
3380 break;
3381 case SP4_MACH_CRED:
3382 /* spo_must_enforce bitmap: */
3383 WRITE32(2);
3384 WRITE32(nfs4_minimal_spo_must_enforce[0]);
3385 WRITE32(nfs4_minimal_spo_must_enforce[1]);
3386 /* empty spo_must_allow bitmap: */
3387 WRITE32(0);
3388 break;
3389 default:
3390 WARN_ON_ONCE(1);
3391 }
3267 3392
3268 /* The server_owner struct */ 3393 /* The server_owner struct */
3269 WRITE64(minor_id); /* Minor id */ 3394 WRITE64(minor_id); /* Minor id */
@@ -3635,13 +3760,17 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
3635 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 3760 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
3636 BUG_ON(iov->iov_len > PAGE_SIZE); 3761 BUG_ON(iov->iov_len > PAGE_SIZE);
3637 if (nfsd4_has_session(cs)) { 3762 if (nfsd4_has_session(cs)) {
3763 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
3764 struct nfs4_client *clp = cs->session->se_client;
3638 if (cs->status != nfserr_replay_cache) { 3765 if (cs->status != nfserr_replay_cache) {
3639 nfsd4_store_cache_entry(resp); 3766 nfsd4_store_cache_entry(resp);
3640 cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; 3767 cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
3641 } 3768 }
3642 /* Renew the clientid on success and on replay */ 3769 /* Renew the clientid on success and on replay */
3643 put_client_renew(cs->session->se_client); 3770 spin_lock(&nn->client_lock);
3644 nfsd4_put_session(cs->session); 3771 nfsd4_put_session(cs->session);
3772 spin_unlock(&nn->client_lock);
3773 put_client_renew(clp);
3645 } 3774 }
3646 return 1; 3775 return 1;
3647} 3776}
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index c0d93170585d..2bbd94e51efc 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -24,7 +24,7 @@
24/* 24/*
25 * nfsd version 25 * nfsd version
26 */ 26 */
27#define NFSD_SUPPORTED_MINOR_VERSION 1 27#define NFSD_SUPPORTED_MINOR_VERSION 2
28/* 28/*
29 * Maximum blocksizes supported by daemon under various circumstances. 29 * Maximum blocksizes supported by daemon under various circumstances.
30 */ 30 */
@@ -328,6 +328,13 @@ void nfsd_lockd_shutdown(void);
328#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \ 328#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
329 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) 329 (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
330 330
331#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
332#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
333 (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL)
334#else
335#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0
336#endif
337
331static inline u32 nfsd_suppattrs0(u32 minorversion) 338static inline u32 nfsd_suppattrs0(u32 minorversion)
332{ 339{
333 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 340 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
@@ -342,8 +349,11 @@ static inline u32 nfsd_suppattrs1(u32 minorversion)
342 349
343static inline u32 nfsd_suppattrs2(u32 minorversion) 350static inline u32 nfsd_suppattrs2(u32 minorversion)
344{ 351{
345 return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2 352 switch (minorversion) {
346 : NFSD4_SUPPORTED_ATTRS_WORD2; 353 default: return NFSD4_2_SUPPORTED_ATTRS_WORD2;
354 case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2;
355 case 0: return NFSD4_SUPPORTED_ATTRS_WORD2;
356 }
347} 357}
348 358
349/* These will return ERR_INVAL if specified in GETATTR or READDIR. */ 359/* These will return ERR_INVAL if specified in GETATTR or READDIR. */
@@ -356,7 +366,11 @@ static inline u32 nfsd_suppattrs2(u32 minorversion)
356#define NFSD_WRITEABLE_ATTRS_WORD1 \ 366#define NFSD_WRITEABLE_ATTRS_WORD1 \
357 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ 367 (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
358 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 368 | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
369#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
370#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL
371#else
359#define NFSD_WRITEABLE_ATTRS_WORD2 0 372#define NFSD_WRITEABLE_ATTRS_WORD2 0
373#endif
360 374
361#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ 375#define NFSD_SUPPATTR_EXCLCREAT_WORD0 \
362 NFSD_WRITEABLE_ATTRS_WORD0 376 NFSD_WRITEABLE_ATTRS_WORD0
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 262df5ccbf59..6b9f48ca4c25 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -116,7 +116,7 @@ struct svc_program nfsd_program = {
116 116
117}; 117};
118 118
119u32 nfsd_supported_minorversion; 119u32 nfsd_supported_minorversion = 1;
120 120
121int nfsd_vers(int vers, enum vers_op change) 121int nfsd_vers(int vers, enum vers_op change)
122{ 122{
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 274e2a114e05..424d8f5f2317 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -246,6 +246,7 @@ struct nfs4_client {
246 nfs4_verifier cl_verifier; /* generated by client */ 246 nfs4_verifier cl_verifier; /* generated by client */
247 time_t cl_time; /* time of last lease renewal */ 247 time_t cl_time; /* time of last lease renewal */
248 struct sockaddr_storage cl_addr; /* client ipaddress */ 248 struct sockaddr_storage cl_addr; /* client ipaddress */
249 bool cl_mach_cred; /* SP4_MACH_CRED in force */
249 struct svc_cred cl_cred; /* setclientid principal */ 250 struct svc_cred cl_cred; /* setclientid principal */
250 clientid_t cl_clientid; /* generated by server */ 251 clientid_t cl_clientid; /* generated by server */
251 nfs4_verifier cl_confirm; /* generated by server */ 252 nfs4_verifier cl_confirm; /* generated by server */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a6bc8a7423db..8ff6a0019b0b 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -28,6 +28,7 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <linux/exportfs.h> 29#include <linux/exportfs.h>
30#include <linux/writeback.h> 30#include <linux/writeback.h>
31#include <linux/security.h>
31 32
32#ifdef CONFIG_NFSD_V3 33#ifdef CONFIG_NFSD_V3
33#include "xdr3.h" 34#include "xdr3.h"
@@ -621,6 +622,33 @@ int nfsd4_is_junction(struct dentry *dentry)
621 return 0; 622 return 0;
622 return 1; 623 return 1;
623} 624}
625#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
626__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
627 struct xdr_netobj *label)
628{
629 __be32 error;
630 int host_error;
631 struct dentry *dentry;
632
633 error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
634 if (error)
635 return error;
636
637 dentry = fhp->fh_dentry;
638
639 mutex_lock(&dentry->d_inode->i_mutex);
640 host_error = security_inode_setsecctx(dentry, label->data, label->len);
641 mutex_unlock(&dentry->d_inode->i_mutex);
642 return nfserrno(host_error);
643}
644#else
645__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
646 struct xdr_netobj *label)
647{
648 return nfserr_notsupp;
649}
650#endif
651
624#endif /* defined(CONFIG_NFSD_V4) */ 652#endif /* defined(CONFIG_NFSD_V4) */
625 653
626#ifdef CONFIG_NFSD_V3 654#ifdef CONFIG_NFSD_V3
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 5b5894159f22..a4be2e389670 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -39,7 +39,6 @@
39typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); 39typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
40 40
41/* nfsd/vfs.c */ 41/* nfsd/vfs.c */
42int fh_lock_parent(struct svc_fh *, struct dentry *);
43int nfsd_racache_init(int); 42int nfsd_racache_init(int);
44void nfsd_racache_shutdown(void); 43void nfsd_racache_shutdown(void);
45int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, 44int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
@@ -56,6 +55,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *);
56__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, 55__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
57 struct nfs4_acl *); 56 struct nfs4_acl *);
58int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); 57int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
58__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
59 struct xdr_netobj *);
59#endif /* CONFIG_NFSD_V4 */ 60#endif /* CONFIG_NFSD_V4 */
60__be32 nfsd_create(struct svc_rqst *, struct svc_fh *, 61__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
61 char *name, int len, struct iattr *attrs, 62 char *name, int len, struct iattr *attrs,
@@ -92,17 +93,13 @@ __be32 nfsd_remove(struct svc_rqst *,
92 struct svc_fh *, char *, int); 93 struct svc_fh *, char *, int);
93__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, 94__be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
94 char *name, int len); 95 char *name, int len);
95int nfsd_truncate(struct svc_rqst *, struct svc_fh *,
96 unsigned long size);
97__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, 96__be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *,
98 loff_t *, struct readdir_cd *, filldir_t); 97 loff_t *, struct readdir_cd *, filldir_t);
99__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, 98__be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
100 struct kstatfs *, int access); 99 struct kstatfs *, int access);
101 100
102int nfsd_notify_change(struct inode *, struct iattr *);
103__be32 nfsd_permission(struct svc_rqst *, struct svc_export *, 101__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
104 struct dentry *, int); 102 struct dentry *, int);
105int nfsd_sync_dir(struct dentry *dp);
106 103
107#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 104#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
108struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int); 105struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 3b271d2092b6..b3ed6446ed8e 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -40,6 +40,7 @@
40#include "state.h" 40#include "state.h"
41#include "nfsd.h" 41#include "nfsd.h"
42 42
43#define NFSD4_MAX_SEC_LABEL_LEN 2048
43#define NFSD4_MAX_TAGLEN 128 44#define NFSD4_MAX_TAGLEN 128
44#define XDR_LEN(n) (((n) + 3) & ~3) 45#define XDR_LEN(n) (((n) + 3) & ~3)
45 46
@@ -118,6 +119,7 @@ struct nfsd4_create {
118 struct iattr cr_iattr; /* request */ 119 struct iattr cr_iattr; /* request */
119 struct nfsd4_change_info cr_cinfo; /* response */ 120 struct nfsd4_change_info cr_cinfo; /* response */
120 struct nfs4_acl *cr_acl; 121 struct nfs4_acl *cr_acl;
122 struct xdr_netobj cr_label;
121}; 123};
122#define cr_linklen u.link.namelen 124#define cr_linklen u.link.namelen
123#define cr_linkname u.link.name 125#define cr_linkname u.link.name
@@ -246,6 +248,7 @@ struct nfsd4_open {
246 struct nfs4_file *op_file; /* used during processing */ 248 struct nfs4_file *op_file; /* used during processing */
247 struct nfs4_ol_stateid *op_stp; /* used during processing */ 249 struct nfs4_ol_stateid *op_stp; /* used during processing */
248 struct nfs4_acl *op_acl; 250 struct nfs4_acl *op_acl;
251 struct xdr_netobj op_label;
249}; 252};
250#define op_iattr iattr 253#define op_iattr iattr
251 254
@@ -330,6 +333,7 @@ struct nfsd4_setattr {
330 u32 sa_bmval[3]; /* request */ 333 u32 sa_bmval[3]; /* request */
331 struct iattr sa_iattr; /* request */ 334 struct iattr sa_iattr; /* request */
332 struct nfs4_acl *sa_acl; 335 struct nfs4_acl *sa_acl;
336 struct xdr_netobj sa_label;
333}; 337};
334 338
335struct nfsd4_setclientid { 339struct nfsd4_setclientid {