aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsfh.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r--fs/nfsd/nfsfh.c110
1 files changed, 57 insertions, 53 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 7011d62acfc8..468f17a78441 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -95,6 +95,22 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
95 return 0; 95 return 0;
96} 96}
97 97
98static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
99 struct svc_export *exp)
100{
101 /* Check if the request originated from a secure port. */
102 if (!rqstp->rq_secure && EX_SECURE(exp)) {
103 char buf[RPC_MAX_ADDRBUFLEN];
104 dprintk(KERN_WARNING
105 "nfsd: request from insecure port %s!\n",
106 svc_print_addr(rqstp, buf, sizeof(buf)));
107 return nfserr_perm;
108 }
109
110 /* Set user creds for this exportpoint */
111 return nfserrno(nfsd_setuser(rqstp, exp));
112}
113
98/* 114/*
99 * Perform sanity checks on the dentry in a client's file handle. 115 * Perform sanity checks on the dentry in a client's file handle.
100 * 116 *
@@ -115,8 +131,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
115 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); 131 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
116 132
117 if (!fhp->fh_dentry) { 133 if (!fhp->fh_dentry) {
118 __u32 *datap=NULL; 134 struct fid *fid = NULL, sfid;
119 __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
120 int fileid_type; 135 int fileid_type;
121 int data_left = fh->fh_size/4; 136 int data_left = fh->fh_size/4;
122 137
@@ -128,7 +143,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
128 143
129 if (fh->fh_version == 1) { 144 if (fh->fh_version == 1) {
130 int len; 145 int len;
131 datap = fh->fh_auth;
132 if (--data_left<0) goto out; 146 if (--data_left<0) goto out;
133 switch (fh->fh_auth_type) { 147 switch (fh->fh_auth_type) {
134 case 0: break; 148 case 0: break;
@@ -144,9 +158,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
144 fh->fh_fsid[1] = fh->fh_fsid[2]; 158 fh->fh_fsid[1] = fh->fh_fsid[2];
145 } 159 }
146 if ((data_left -= len)<0) goto out; 160 if ((data_left -= len)<0) goto out;
147 exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); 161 exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
148 datap += len; 162 fh->fh_auth);
163 fid = (struct fid *)(fh->fh_auth + len);
149 } else { 164 } else {
165 __u32 tfh[2];
150 dev_t xdev; 166 dev_t xdev;
151 ino_t xino; 167 ino_t xino;
152 if (fh->fh_size != NFS_FHSIZE) 168 if (fh->fh_size != NFS_FHSIZE)
@@ -167,18 +183,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
167 goto out; 183 goto out;
168 } 184 }
169 185
170 /* Check if the request originated from a secure port. */ 186 error = nfsd_setuser_and_check_port(rqstp, exp);
171 error = nfserr_perm;
172 if (!rqstp->rq_secure && EX_SECURE(exp)) {
173 char buf[RPC_MAX_ADDRBUFLEN];
174 printk(KERN_WARNING
175 "nfsd: request from insecure port %s!\n",
176 svc_print_addr(rqstp, buf, sizeof(buf)));
177 goto out;
178 }
179
180 /* Set user creds for this exportpoint */
181 error = nfserrno(nfsd_setuser(rqstp, exp));
182 if (error) 187 if (error)
183 goto out; 188 goto out;
184 189
@@ -190,22 +195,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
190 error = nfserr_badhandle; 195 error = nfserr_badhandle;
191 196
192 if (fh->fh_version != 1) { 197 if (fh->fh_version != 1) {
193 tfh[0] = fh->ofh_ino; 198 sfid.i32.ino = fh->ofh_ino;
194 tfh[1] = fh->ofh_generation; 199 sfid.i32.gen = fh->ofh_generation;
195 tfh[2] = fh->ofh_dirino; 200 sfid.i32.parent_ino = fh->ofh_dirino;
196 datap = tfh; 201 fid = &sfid;
197 data_left = 3; 202 data_left = 3;
198 if (fh->ofh_dirino == 0) 203 if (fh->ofh_dirino == 0)
199 fileid_type = 1; 204 fileid_type = FILEID_INO32_GEN;
200 else 205 else
201 fileid_type = 2; 206 fileid_type = FILEID_INO32_GEN_PARENT;
202 } else 207 } else
203 fileid_type = fh->fh_fileid_type; 208 fileid_type = fh->fh_fileid_type;
204 209
205 if (fileid_type == 0) 210 if (fileid_type == FILEID_ROOT)
206 dentry = dget(exp->ex_dentry); 211 dentry = dget(exp->ex_dentry);
207 else { 212 else {
208 dentry = exportfs_decode_fh(exp->ex_mnt, datap, 213 dentry = exportfs_decode_fh(exp->ex_mnt, fid,
209 data_left, fileid_type, 214 data_left, fileid_type,
210 nfsd_acceptable, exp); 215 nfsd_acceptable, exp);
211 } 216 }
@@ -227,18 +232,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
227 fhp->fh_export = exp; 232 fhp->fh_export = exp;
228 nfsd_nr_verified++; 233 nfsd_nr_verified++;
229 } else { 234 } else {
230 /* just rechecking permissions 235 /*
231 * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well) 236 * just rechecking permissions
237 * (e.g. nfsproc_create calls fh_verify, then nfsd_create
238 * does as well)
232 */ 239 */
233 dprintk("nfsd: fh_verify - just checking\n"); 240 dprintk("nfsd: fh_verify - just checking\n");
234 dentry = fhp->fh_dentry; 241 dentry = fhp->fh_dentry;
235 exp = fhp->fh_export; 242 exp = fhp->fh_export;
236 /* Set user creds for this exportpoint; necessary even 243 /*
244 * Set user creds for this exportpoint; necessary even
237 * in the "just checking" case because this may be a 245 * in the "just checking" case because this may be a
238 * filehandle that was created by fh_compose, and that 246 * filehandle that was created by fh_compose, and that
239 * is about to be used in another nfsv4 compound 247 * is about to be used in another nfsv4 compound
240 * operation */ 248 * operation.
241 error = nfserrno(nfsd_setuser(rqstp, exp)); 249 */
250 error = nfsd_setuser_and_check_port(rqstp, exp);
242 if (error) 251 if (error)
243 goto out; 252 goto out;
244 } 253 }
@@ -286,16 +295,21 @@ out:
286 * an inode. In this case a call to fh_update should be made 295 * an inode. In this case a call to fh_update should be made
287 * before the fh goes out on the wire ... 296 * before the fh goes out on the wire ...
288 */ 297 */
289static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, 298static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
290 __u32 *datap, int *maxsize) 299 struct dentry *dentry)
291{ 300{
292 if (dentry == exp->ex_dentry) { 301 if (dentry != exp->ex_dentry) {
293 *maxsize = 0; 302 struct fid *fid = (struct fid *)
294 return 0; 303 (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1);
295 } 304 int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
305 int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
296 306
297 return exportfs_encode_fh(dentry, datap, maxsize, 307 fhp->fh_handle.fh_fileid_type =
298 !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); 308 exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
309 fhp->fh_handle.fh_size += maxsize * 4;
310 } else {
311 fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
312 }
299} 313}
300 314
301/* 315/*
@@ -457,12 +471,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
457 datap += len/4; 471 datap += len/4;
458 fhp->fh_handle.fh_size = 4 + len; 472 fhp->fh_handle.fh_size = 4 + len;
459 473
460 if (inode) { 474 if (inode)
461 int size = (fhp->fh_maxsize-len-4)/4; 475 _fh_update(fhp, exp, dentry);
462 fhp->fh_handle.fh_fileid_type =
463 _fh_update(dentry, exp, datap, &size);
464 fhp->fh_handle.fh_size += size*4;
465 }
466 if (fhp->fh_handle.fh_fileid_type == 255) 476 if (fhp->fh_handle.fh_fileid_type == 255)
467 return nfserr_opnotsupp; 477 return nfserr_opnotsupp;
468 } 478 }
@@ -479,7 +489,6 @@ __be32
479fh_update(struct svc_fh *fhp) 489fh_update(struct svc_fh *fhp)
480{ 490{
481 struct dentry *dentry; 491 struct dentry *dentry;
482 __u32 *datap;
483 492
484 if (!fhp->fh_dentry) 493 if (!fhp->fh_dentry)
485 goto out_bad; 494 goto out_bad;
@@ -490,15 +499,10 @@ fh_update(struct svc_fh *fhp)
490 if (fhp->fh_handle.fh_version != 1) { 499 if (fhp->fh_handle.fh_version != 1) {
491 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); 500 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
492 } else { 501 } else {
493 int size; 502 if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
494 if (fhp->fh_handle.fh_fileid_type != 0)
495 goto out; 503 goto out;
496 datap = fhp->fh_handle.fh_auth+ 504
497 fhp->fh_handle.fh_size/4 -1; 505 _fh_update(fhp, fhp->fh_export, dentry);
498 size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
499 fhp->fh_handle.fh_fileid_type =
500 _fh_update(dentry, fhp->fh_export, datap, &size);
501 fhp->fh_handle.fh_size += size*4;
502 if (fhp->fh_handle.fh_fileid_type == 255) 506 if (fhp->fh_handle.fh_fileid_type == 255)
503 return nfserr_opnotsupp; 507 return nfserr_opnotsupp;
504 } 508 }