diff options
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r-- | fs/nfsd/nfsfh.c | 110 |
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 | ||
98 | static __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 | */ |
289 | static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | 298 | static 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 | |||
479 | fh_update(struct svc_fh *fhp) | 489 | fh_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 | } |