1 /*
2  * linux/fs/nfsd/nfsfh.c
3  *
4  * NFS server file handle treatment.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  * Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
8  * Extensive rewrite by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
9  */
10 
11 #include <linux/sched.h>
12 #include <linux/slab.h>
13 #include <linux/fs.h>
14 #include <linux/unistd.h>
15 #include <linux/string.h>
16 #include <linux/stat.h>
17 #include <linux/dcache.h>
18 #include <asm/pgtable.h>
19 
20 #include <linux/sunrpc/svc.h>
21 #include <linux/nfsd/nfsd.h>
22 
23 #define NFSDDBG_FACILITY		NFSDDBG_FH
24 #define NFSD_PARANOIA 1
25 /* #define NFSD_DEBUG_VERBOSE 1 */
26 
27 
28 static int nfsd_nr_verified;
29 static int nfsd_nr_put;
30 
31 
32 struct nfsd_getdents_callback {
33 	char *name;		/* name that was found. It already points to a buffer NAME_MAX+1 is size */
34 	unsigned long ino;	/* the inum we are looking for */
35 	int found;		/* inode matched? */
36 	int sequence;		/* sequence counter */
37 };
38 
39 /*
40  * A rather strange filldir function to capture
41  * the name matching the specified inode number.
42  */
filldir_one(void * __buf,const char * name,int len,loff_t pos,ino_t ino,unsigned int d_type)43 static int filldir_one(void * __buf, const char * name, int len,
44 			loff_t pos, ino_t ino, unsigned int d_type)
45 {
46 	struct nfsd_getdents_callback *buf = __buf;
47 	int result = 0;
48 
49 	buf->sequence++;
50 #ifdef NFSD_DEBUG_VERBOSE
51 dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
52 #endif
53 	if (buf->ino == ino) {
54 		memcpy(buf->name, name, len);
55 		buf->name[len] = '\0';
56 		buf->found = 1;
57 		result = -1;
58 	}
59 	return result;
60 }
61 
62 /**
63  * nfsd_get_name - default nfsd_operations->get_name function
64  * @dentry: the directory in which to find a name
65  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
66  * @child:  the dentry for the child directory.
67  *
68  * calls readdir on the parent until it finds an entry with
69  * the same inode number as the child, and returns that.
70  */
nfsd_get_name(struct dentry * dentry,char * name,struct dentry * child)71 static int nfsd_get_name(struct dentry *dentry, char *name,
72 			struct dentry *child)
73 {
74 	struct inode *dir = dentry->d_inode;
75 	int error;
76 	struct file file;
77 	struct nfsd_getdents_callback buffer;
78 
79 	error = -ENOTDIR;
80 	if (!dir || !S_ISDIR(dir->i_mode))
81 		goto out;
82 	error = -EINVAL;
83 	if (!dir->i_fop)
84 		goto out;
85 	/*
86 	 * Open the directory ...
87 	 */
88 	error = init_private_file(&file, dentry, FMODE_READ);
89 	if (error)
90 		goto out;
91 	error = -EINVAL;
92 	if (!file.f_op->readdir)
93 		goto out_close;
94 
95 	buffer.name = name;
96 	buffer.ino = child->d_inode->i_ino;
97 	buffer.found = 0;
98 	buffer.sequence = 0;
99 	while (1) {
100 		int old_seq = buffer.sequence;
101 
102 		error = vfs_readdir(&file, filldir_one, &buffer);
103 
104 		if (error < 0)
105 			break;
106 
107 		error = 0;
108 		if (buffer.found)
109 			break;
110 		error = -ENOENT;
111 		if (old_seq == buffer.sequence)
112 			break;
113 	}
114 
115 out_close:
116 	if (file.f_op->release)
117 		file.f_op->release(dir, &file);
118 out:
119 	return error;
120 }
121 
122 /* this should be provided by each filesystem in an nfsd_operations interface as
123  * iget isn't really the right interface
124  */
nfsd_iget(struct super_block * sb,unsigned long ino,__u32 generation)125 static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
126 {
127 
128 	/* iget isn't really right if the inode is currently unallocated!!
129 	 * This should really all be done inside each filesystem
130 	 *
131 	 * ext2fs' read_inode has been strengthed to return a bad_inode if the inode
132 	 *   had been deleted.
133 	 *
134 	 * Currently we don't know the generation for parent directory, so a generation
135 	 * of 0 means "accept any"
136 	 */
137 	struct inode *inode;
138 	struct list_head *lp;
139 	struct dentry *result;
140 	if (ino == 0)
141 		return ERR_PTR(-ESTALE);
142 	inode = iget(sb, ino);
143 	if (inode == NULL)
144 		return ERR_PTR(-ENOMEM);
145 	if (is_bad_inode(inode)
146 	    || (generation && inode->i_generation != generation)
147 		) {
148 		/* we didn't find the right inode.. */
149 		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
150 			inode->i_ino,
151 			inode->i_nlink, atomic_read(&inode->i_count),
152 			inode->i_generation,
153 			generation);
154 
155 		iput(inode);
156 		return ERR_PTR(-ESTALE);
157 	}
158 	/* now to find a dentry.
159 	 * If possible, get a well-connected one
160 	 */
161 	spin_lock(&dcache_lock);
162 	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
163 		result = list_entry(lp,struct dentry, d_alias);
164 		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
165 			dget_locked(result);
166 			result->d_vfs_flags |= DCACHE_REFERENCED;
167 			spin_unlock(&dcache_lock);
168 			iput(inode);
169 			return result;
170 		}
171 	}
172 	spin_unlock(&dcache_lock);
173 	result = d_alloc_root(inode);
174 	if (result == NULL) {
175 		iput(inode);
176 		return ERR_PTR(-ENOMEM);
177 	}
178 	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
179 	return result;
180 }
181 
nfsd_get_dentry(struct super_block * sb,__u32 * fh,int len,int fhtype,int parent)182 static struct dentry *nfsd_get_dentry(struct super_block *sb, __u32 *fh,
183 					     int len, int fhtype, int parent)
184 {
185 	if (sb->s_op->fh_to_dentry)
186 		return sb->s_op->fh_to_dentry(sb, fh, len, fhtype, parent);
187 	switch (fhtype) {
188 	case 1:
189 		if (len < 2)
190 			break;
191 		if (parent)
192 			break;
193 		return nfsd_iget(sb, fh[0], fh[1]);
194 
195 	case 2:
196 		if (len < 3)
197 			break;
198 		if (parent)
199 			return nfsd_iget(sb,fh[2],0);
200 		return nfsd_iget(sb,fh[0],fh[1]);
201 	default: break;
202 	}
203 	return ERR_PTR(-EINVAL);
204 }
205 
206 
207 /* this routine links an IS_ROOT dentry into the dcache tree.  It gains "parent"
208  * as a parent and "name" as a name
209  * It should possibly go in dcache.c
210  */
d_splice(struct dentry * target,struct dentry * parent,struct qstr * name)211 int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
212 {
213 	struct dentry *tdentry;
214 #ifdef NFSD_PARANOIA
215 	if (!IS_ROOT(target))
216 		printk("nfsd: d_splice with no-root target: %s/%s\n", parent->d_name.name, name->name);
217 	if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
218 		printk("nfsd: d_splice with non-DISCONNECTED target: %s/%s\n", parent->d_name.name, name->name);
219 #endif
220 	tdentry = d_alloc(parent, name);
221 	if (tdentry == NULL)
222 		return -ENOMEM;
223 	d_move(target, tdentry);
224 
225 	/* tdentry will have been made a "child" of target (the parent of target)
226 	 * make it an IS_ROOT instead
227 	 */
228 	spin_lock(&dcache_lock);
229 	list_del_init(&tdentry->d_child);
230 	tdentry->d_parent = tdentry;
231 	spin_unlock(&dcache_lock);
232 	d_rehash(target);
233 	dput(tdentry);
234 
235 	/* if parent is properly connected, then we can assert that
236 	 * the children are connected, but it must be a singluar (non-forking)
237 	 * branch
238 	 */
239 	if (!(parent->d_flags & DCACHE_NFSD_DISCONNECTED)) {
240 		while (target) {
241 			target->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
242 			parent = target;
243 			spin_lock(&dcache_lock);
244 			if (list_empty(&parent->d_subdirs))
245 				target = NULL;
246 			else {
247 				target = list_entry(parent->d_subdirs.next, struct dentry, d_child);
248 #ifdef NFSD_PARANOIA
249 				/* must be only child */
250 				if (target->d_child.next != &parent->d_subdirs
251 				    || target->d_child.prev != &parent->d_subdirs)
252 					printk("nfsd: d_splice found non-singular disconnected branch: %s/%s\n",
253 					       parent->d_name.name, target->d_name.name);
254 #endif
255 			}
256 			spin_unlock(&dcache_lock);
257 		}
258 	}
259 	return 0;
260 }
261 
262 /* this routine finds the dentry of the parent of a given directory
263  * it should be in the filesystem accessed by nfsd_operations
264  * it assumes lookup("..") works.
265  */
nfsd_findparent(struct dentry * child)266 struct dentry *nfsd_findparent(struct dentry *child)
267 {
268 	struct dentry *tdentry, *pdentry;
269 	tdentry = d_alloc(child, &(const struct qstr) {"..", 2, 0});
270 	if (!tdentry)
271 		return ERR_PTR(-ENOMEM);
272 
273 	/* I'm going to assume that if the returned dentry is different, then
274 	 * it is well connected.  But nobody returns different dentrys do they?
275 	 */
276 	down(&child->d_inode->i_sem);
277 	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
278 	up(&child->d_inode->i_sem);
279 	d_drop(tdentry); /* we never want ".." hashed */
280 	if (!pdentry && tdentry->d_inode == NULL) {
281 		/* File system cannot find ".." ... sad but possible */
282 		pdentry = ERR_PTR(-EINVAL);
283 	}
284 	if (!pdentry) {
285 		/* I don't want to return a ".." dentry.
286 		 * I would prefer to return an unconnected "IS_ROOT" dentry,
287 		 * though a properly connected dentry is even better
288 		 */
289 		/* if first or last of alias list is not tdentry, use that
290 		 * else make a root dentry
291 		 */
292 		struct list_head *aliases = &tdentry->d_inode->i_dentry;
293 		spin_lock(&dcache_lock);
294 		if (aliases->next != aliases) {
295 			pdentry = list_entry(aliases->next, struct dentry, d_alias);
296 			if (pdentry == tdentry)
297 				pdentry = list_entry(aliases->prev, struct dentry, d_alias);
298 			if (pdentry == tdentry)
299 				pdentry = NULL;
300 			if (pdentry) dget_locked(pdentry);
301 		}
302 		spin_unlock(&dcache_lock);
303 		if (pdentry == NULL) {
304 			pdentry = d_alloc_root(tdentry->d_inode);
305 			if (pdentry) {
306 				igrab(tdentry->d_inode);
307 				pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
308 				pdentry->d_op = child->d_op;
309 			}
310 		}
311 		if (pdentry == NULL)
312 			pdentry = ERR_PTR(-ENOMEM);
313 	}
314 	dput(tdentry); /* it is not hashed, it will be discarded */
315 	return pdentry;
316 }
317 
splice(struct dentry * child,struct dentry * parent)318 static struct dentry *splice(struct dentry *child, struct dentry *parent)
319 {
320 	int err = 0, nerr;
321 	struct qstr qs;
322 	char namebuf[256];
323 	struct list_head *lp;
324 	/* child is an IS_ROOT (anonymous) dentry, but it is hypothesised that
325 	 * it should be a child of parent.
326 	 * We see if we can find a name and, if we can - splice it in.
327 	 * We lookup the name before locking (i_sem) the directory as namelookup
328 	 * also claims i_sem.  If the name gets changed then we will loop around
329 	 * and try again in find_fh_dentry.
330 	 */
331 
332 	nerr = nfsd_get_name(parent, namebuf, child);
333 
334 	/*
335 	 * We now claim the parent i_sem so that no-one else tries to create
336 	 * a dentry in the parent while we are.
337 	 */
338 
339 	down(&parent->d_inode->i_sem);
340 
341 	/* Now, things might have changed while we waited.
342 	 * Possibly a friendly filesystem found child and spliced it in in response
343 	 * to a lookup (though nobody does this yet).  In this case, just succeed.
344 	 */
345 	if (child->d_parent == parent) goto out;
346 
347 	/* Possibly a new dentry has been made for this child->d_inode in
348 	 * parent by a lookup.  In this case return that dentry. Caller must
349 	 * notice and act accordingly
350 	 */
351 	spin_lock(&dcache_lock);
352 	list_for_each(lp, &child->d_inode->i_dentry) {
353 		struct dentry *tmp = list_entry(lp,struct dentry, d_alias);
354 		if (!list_empty(&tmp->d_hash) &&
355 		    tmp->d_parent == parent) {
356 			child = dget_locked(tmp);
357 			spin_unlock(&dcache_lock);
358 			goto out;
359 		}
360 	}
361 	spin_unlock(&dcache_lock);
362 
363 	/* now we need that name.  If there was an error getting it, now is th
364 	 * time to bail out.
365 	 */
366 	if ((err = nerr))
367 		goto out;
368 	qs.name = namebuf;
369 	qs.len = strlen(namebuf);
370 	if (find_inode_number(parent, &qs) != 0) {
371 		/* Now that IS odd.  I wonder what it means... */
372 		err = -EEXIST;
373 		printk("nfsd-fh: found a name that I didn't expect: %s/%s\n", parent->d_name.name, qs.name);
374 		goto out;
375 	}
376 	err = d_splice(child, parent, &qs);
377 	dprintk("nfsd_fh: found name %s for ino %ld\n", child->d_name.name, child->d_inode->i_ino);
378  out:
379 	up(&parent->d_inode->i_sem);
380 	if (err)
381 		return ERR_PTR(err);
382 	else
383 		return child;
384 }
385 
386 /*
387  * This is the basic lookup mechanism for turning an NFS file handle
388  * into a dentry.
389  * We use nfsd_iget and if that doesn't return a suitably connected dentry,
390  * we try to find the parent, and the parent of that and so-on until a
391  * connection if made.
392  */
393 static struct dentry *
find_fh_dentry(struct super_block * sb,__u32 * datap,int len,int fhtype,int needpath)394 find_fh_dentry(struct super_block *sb, __u32 *datap, int len, int fhtype, int needpath)
395 {
396 	struct dentry *dentry, *result = NULL;
397 	struct dentry *tmp;
398 	int err = -ESTALE;
399 	/* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free)
400 	 * dcache path ever exists, as otherwise two partial paths might get
401 	 * joined together, which would be very confusing.
402 	 * If there is ever an unconnected non-root directory, then this lock
403 	 * must be held.
404 	 */
405 
406 
407 	nfsdstats.fh_lookup++;
408 	/*
409 	 * Attempt to find the inode.
410 	 */
411  retry:
412 	down(&sb->s_nfsd_free_path_sem);
413 	result = nfsd_get_dentry(sb, datap, len, fhtype, 0);
414 	if (IS_ERR(result)
415 	    || !(result->d_flags & DCACHE_NFSD_DISCONNECTED)
416 	    || (!S_ISDIR(result->d_inode->i_mode) && ! needpath)) {
417 		up(&sb->s_nfsd_free_path_sem);
418 
419 		err = PTR_ERR(result);
420 		if (IS_ERR(result))
421 			goto err_out;
422 		if ((result->d_flags & DCACHE_NFSD_DISCONNECTED))
423 			nfsdstats.fh_anon++;
424 		return result;
425 	}
426 
427 	/* It's a directory, or we are required to confirm the file's
428 	 * location in the tree.
429 	 */
430 	dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,datap[0]);
431 
432 	if (!S_ISDIR(result->d_inode->i_mode)) {
433 		nfsdstats.fh_nocache_nondir++;
434 			/* need to iget dirino and make sure this inode is in that directory */
435 			dentry = nfsd_get_dentry(sb, datap, len, fhtype, 1);
436 			err = PTR_ERR(dentry);
437 			if (IS_ERR(dentry))
438 				goto err_result;
439 			err = -ESTALE;
440 			if (!dentry->d_inode
441 			    || !S_ISDIR(dentry->d_inode->i_mode)) {
442 				goto err_dentry;
443 			}
444 			tmp = splice(result, dentry);
445 			err = PTR_ERR(tmp);
446 			if (IS_ERR(tmp))
447 				goto err_dentry;
448 			if (tmp != result) {
449 				/* it is safe to just use tmp instead, but we must discard result first */
450 				d_drop(result);
451 				dput(result);
452 				result = tmp;
453 			}
454 	} else {
455 		nfsdstats.fh_nocache_dir++;
456 		dentry = dget(result);
457 	}
458 
459 	while(dentry->d_flags & DCACHE_NFSD_DISCONNECTED) {
460 		/* LOOP INVARIANT */
461 		/* haven't found a place in the tree yet, but we do have a free path
462 		 * from dentry down to result, and dentry is a directory.
463 		 * Have a hold on dentry and result */
464 		struct dentry *pdentry;
465 		struct inode *parent;
466 
467 		pdentry = nfsd_findparent(dentry);
468 		err = PTR_ERR(pdentry);
469 		if (IS_ERR(pdentry))
470 			goto err_dentry;
471 		parent = pdentry->d_inode;
472 		err = -EACCES;
473 		if (!parent) {
474 			dput(pdentry);
475 			goto err_dentry;
476 		}
477 
478 		tmp = splice(dentry, pdentry);
479 		if (tmp != dentry) {
480 			/* Something wrong.  We need to drop the whole dentry->result path
481 			 * whatever it was
482 			 */
483 			struct dentry *d;
484 			for (d=result ; d ; d=(d->d_parent == d)?NULL:d->d_parent)
485 				d_drop(d);
486 		}
487 		if (IS_ERR(tmp)) {
488 			err = PTR_ERR(tmp);
489 			dput(pdentry);
490 			goto err_dentry;
491 		}
492 		if (tmp != dentry) {
493 			/* we lost a race,  try again
494 			 */
495 			dput(pdentry);
496 			dput(tmp);
497 			dput(dentry);
498 			dput(result);	/* this will discard the whole free path, so we can up the semaphore */
499 			up(&sb->s_nfsd_free_path_sem);
500 			goto retry;
501 		}
502 		dput(dentry);
503 		dentry = pdentry;
504 	}
505 	dput(dentry);
506 	up(&sb->s_nfsd_free_path_sem);
507 	return result;
508 
509 err_dentry:
510 	dput(dentry);
511 err_result:
512 	dput(result);
513 	up(&sb->s_nfsd_free_path_sem);
514 err_out:
515 	if (err == -ESTALE)
516 		nfsdstats.fh_stale++;
517 	return ERR_PTR(err);
518 }
519 
520 /*
521  * Perform sanity checks on the dentry in a client's file handle.
522  *
523  * Note that the file handle dentry may need to be freed even after
524  * an error return.
525  *
526  * This is only called at the start of an nfsproc call, so fhp points to
527  * a svc_fh which is all 0 except for the over-the-wire file handle.
528  */
529 u32
fh_verify(struct svc_rqst * rqstp,struct svc_fh * fhp,int type,int access)530 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
531 {
532 	struct knfsd_fh	*fh = &fhp->fh_handle;
533 	struct svc_export *exp;
534 	struct dentry	*dentry;
535 	struct inode	*inode;
536 	u32		error = 0;
537 
538 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
539 
540 	/* keep this filehandle for possible reference  when encoding attributes */
541 	rqstp->rq_reffh = fh;
542 
543 	if (!fhp->fh_dentry) {
544 		kdev_t xdev = NODEV;
545 		ino_t xino = 0;
546 		__u32 *datap=NULL;
547 		int data_left = fh->fh_size/4;
548 		int nfsdev;
549 		int fsid = 0;
550 
551 		error = nfserr_stale;
552 		if (rqstp->rq_vers == 3)
553 			error = nfserr_badhandle;
554 		if (fh->fh_version == 1) {
555 
556 			datap = fh->fh_auth;
557 			if (--data_left<0) goto out;
558 			switch (fh->fh_auth_type) {
559 			case 0: break;
560 			default: goto out;
561 			}
562 
563 			switch (fh->fh_fsid_type) {
564 			case 0:
565 				if ((data_left-=2)<0) goto out;
566 				nfsdev = ntohl(*datap++);
567 				xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
568 				xino = *datap++;
569 				break;
570 			case 1:
571 				if ((data_left-=1)<0) goto out;
572 				fsid = *datap++;
573 				break;
574 			default:
575 				goto out;
576 			}
577 		} else {
578 			if (fh->fh_size != NFS_FHSIZE)
579 				goto out;
580 			/* assume old filehandle format */
581 			xdev = u32_to_kdev_t(fh->ofh_xdev);
582 			xino = u32_to_ino_t(fh->ofh_xino);
583 		}
584 
585 		/*
586 		 * Look up the export entry.
587 		 */
588 		error = nfserr_stale;
589 		if (fh->fh_version == 1 && fh->fh_fsid_type == 1)
590 			exp = exp_get_fsid(rqstp->rq_client, fsid);
591 		else
592 			exp = exp_get(rqstp->rq_client, xdev, xino);
593 
594 		if (!exp)
595 			/* export entry revoked */
596 			goto out;
597 
598 		/* Check if the request originated from a secure port. */
599 		error = nfserr_perm;
600 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
601 			printk(KERN_WARNING
602 			       "nfsd: request from insecure port (%08x:%d)!\n",
603 			       ntohl(rqstp->rq_addr.sin_addr.s_addr),
604 			       ntohs(rqstp->rq_addr.sin_port));
605 			goto out;
606 		}
607 
608 		/* Set user creds if we haven't done so already. */
609 		nfsd_setuser(rqstp, exp);
610 
611 		/*
612 		 * Look up the dentry using the NFS file handle.
613 		 */
614 		error = nfserr_stale;
615 		if (rqstp->rq_vers == 3)
616 			error = nfserr_badhandle;
617 
618 		if (fh->fh_version == 1) {
619 			/* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
620 			 *  then should use that */
621 			switch (fh->fh_fileid_type) {
622 			case 0:
623 				dentry = dget(exp->ex_dentry);
624 				/* need to revalidate the inode */
625 				inode = dentry->d_inode;
626 				if (inode->i_op && inode->i_op->revalidate)
627 					if (inode->i_op->revalidate(dentry)) {
628 						dput(dentry);
629 						dentry = ERR_PTR(-ESTALE);
630 					}
631 				break;
632 			default:
633 				dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
634 							datap, data_left, fh->fh_fileid_type,
635 							!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
636 			}
637 		} else {
638 			__u32 tfh[3];
639 			tfh[0] = fh->ofh_ino;
640 			tfh[1] = fh->ofh_generation;
641 			tfh[2] = fh->ofh_dirino;
642 			dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
643 						tfh, 3, fh->ofh_dirino?2:1,
644 						!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
645 		}
646 		if (IS_ERR(dentry)) {
647 			if (PTR_ERR(dentry) != -EINVAL)
648 				error = nfserrno(PTR_ERR(dentry));
649 			goto out;
650 		}
651 #ifdef NFSD_PARANOIA
652 		if (S_ISDIR(dentry->d_inode->i_mode) &&
653 		    (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
654 			printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
655 			       dentry->d_parent->d_name.name, dentry->d_name.name);
656 		}
657 #endif
658 
659 		fhp->fh_dentry = dentry;
660 		fhp->fh_export = exp;
661 		nfsd_nr_verified++;
662 	} else {
663 		/* just rechecking permissions
664 		 * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
665 		 */
666 		dprintk("nfsd: fh_verify - just checking\n");
667 		dentry = fhp->fh_dentry;
668 		exp = fhp->fh_export;
669 	}
670 
671 	inode = dentry->d_inode;
672 
673 	/* Type check. The correct error return for type mismatches
674 	 * does not seem to be generally agreed upon. SunOS seems to
675 	 * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
676 	 * spec says this is incorrect (implementation notes for the
677 	 * write call).
678 	 */
679 
680 	/* Type can be negative to e.g. exclude directories from linking */
681 	if (type > 0 && (inode->i_mode & S_IFMT) != type) {
682 		if (type == S_IFDIR)
683 			error = nfserr_notdir;
684 		else if ((inode->i_mode & S_IFMT) == S_IFDIR)
685 			error = nfserr_isdir;
686 		else
687 			error = nfserr_inval;
688 		goto out;
689 	}
690 	if (type < 0 && (inode->i_mode & S_IFMT) == -type) {
691 		error = (type == -S_IFDIR)? nfserr_isdir : nfserr_notdir;
692 		goto out;
693 	}
694 
695 	/*
696 	 * Security: Check that the export is valid for dentry <gam3@acm.org>
697 	 */
698 	error = 0;
699 
700 	if (!(exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
701 		struct dentry *tdentry = dentry;
702 
703 		while (tdentry != exp->ex_dentry && !IS_ROOT(tdentry)) {
704 			struct dentry *parent = tdentry->d_parent;
705 
706 			/* make sure parents give x permission to user */
707 			error = permission(parent->d_inode, MAY_EXEC);
708 			if (error)
709 				break;
710 			tdentry = parent;
711 		}
712 		if (exp->ex_dentry != tdentry) {
713 			error = nfserr_stale;
714 			printk("fh_verify: no root_squashed access at %s/%s.\n",
715 			       dentry->d_parent->d_name.name,
716 			       dentry->d_name.name);
717 			goto out;
718 		}
719 	}
720 
721 	/* Finally, check access permissions. */
722 	if (!error) {
723 		error = nfsd_permission(exp, dentry, access);
724 	}
725 #ifdef NFSD_PARANOIA_EXTREME
726 	if (error) {
727 		printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
728 		       dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
729 	}
730 #endif
731 out:
732 	if (error == nfserr_stale)
733 		nfsdstats.fh_stale++;
734 	return error;
735 }
736 
737 /*
738  * Compose a file handle for an NFS reply.
739  *
740  * Note that when first composed, the dentry may not yet have
741  * an inode.  In this case a call to fh_update should be made
742  * before the fh goes out on the wire ...
743  */
_fh_update(struct dentry * dentry,struct svc_export * exp,__u32 * datap,int * maxsize)744 inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
745 		      __u32 *datap, int *maxsize)
746 {
747 	struct super_block *sb = dentry->d_inode->i_sb;
748 
749 	if (dentry == exp->ex_dentry) {
750 		*maxsize = 0;
751 		return 0;
752 	}
753 
754 	if (sb->s_op->dentry_to_fh) {
755 		int need_parent = !S_ISDIR(dentry->d_inode->i_mode) &&
756 			!(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
757 
758 		int type = sb->s_op->dentry_to_fh(dentry, datap, maxsize, need_parent);
759 		return type;
760 	}
761 
762 	if (*maxsize < 2)
763 		return 255;
764 	*datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
765 	*datap++ = dentry->d_inode->i_generation;
766 	if (*maxsize ==2 ||
767 	    S_ISDIR(dentry->d_inode->i_mode) ||
768 	    (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
769 		*maxsize = 2;
770 		return 1;
771 	}
772 	*datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
773 	*maxsize = 3;
774 	return 2;
775 }
776 
777 /*
778  * for composing old style file handles
779  */
_fh_update_old(struct dentry * dentry,struct svc_export * exp,struct knfsd_fh * fh)780 inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
781 			   struct knfsd_fh *fh)
782 {
783 	fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
784 	fh->ofh_generation = dentry->d_inode->i_generation;
785 	if (S_ISDIR(dentry->d_inode->i_mode) ||
786 	    (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
787 		fh->ofh_dirino = 0;
788 }
789 
790 int
fh_compose(struct svc_fh * fhp,struct svc_export * exp,struct dentry * dentry,struct svc_fh * ref_fh)791 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
792 {
793 	/* ref_fh is a reference file handle.
794 	 * if it is non-null, then we should compose a filehandle which is
795 	 * of the same version, where possible.
796 	 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
797 	 * Then create a 32byte filehandle using nfs_fhbase_old
798 	 * But only do this if dentry_to_fh is not available
799 	 *
800 	 */
801 
802 	struct inode * inode = dentry->d_inode;
803 	struct dentry *parent = dentry->d_parent;
804 	__u32 *datap;
805 
806 	dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
807 		exp->ex_dev, (long) exp->ex_ino,
808 		parent->d_name.name, dentry->d_name.name,
809 		(inode ? inode->i_ino : 0));
810 
811 	if (fhp->fh_locked || fhp->fh_dentry) {
812 		printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
813 			parent->d_name.name, dentry->d_name.name);
814 	}
815 	if (fhp->fh_maxsize < NFS_FHSIZE)
816 		printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
817 		       fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
818 
819 	fhp->fh_dentry = dentry; /* our internal copy */
820 	fhp->fh_export = exp;
821 
822 	if (ref_fh &&
823 	    ref_fh->fh_handle.fh_version == 0xca &&
824 	    parent->d_inode->i_sb->s_op->dentry_to_fh == NULL) {
825 		/* old style filehandle please */
826 		memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
827 		fhp->fh_handle.fh_size = NFS_FHSIZE;
828 		fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
829 		fhp->fh_handle.ofh_dev =  htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
830 		fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
831 		fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino);
832 		fhp->fh_handle.ofh_dirino = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
833 		if (inode)
834 			_fh_update_old(dentry, exp, &fhp->fh_handle);
835 	} else {
836 		fhp->fh_handle.fh_version = 1;
837 		fhp->fh_handle.fh_auth_type = 0;
838 		datap = fhp->fh_handle.fh_auth+0;
839 		if ((exp->ex_flags & NFSEXP_FSID) &&
840 		    (!ref_fh || ref_fh->fh_handle.fh_fsid_type == 1)) {
841 			fhp->fh_handle.fh_fsid_type = 1;
842 			/* fsid_type 1 == 4 bytes filesystem id */
843 			*datap++ = exp->ex_fsid;
844 			fhp->fh_handle.fh_size = 2*4;
845 		} else {
846 			fhp->fh_handle.fh_fsid_type = 0;
847 			/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
848 			*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
849 			*datap++ = ino_t_to_u32(exp->ex_ino);
850 			fhp->fh_handle.fh_size = 3*4;
851 		}
852 		if (inode) {
853 			int size = fhp->fh_maxsize/4 - 3;
854 			fhp->fh_handle.fh_fileid_type =
855 				_fh_update(dentry, exp, datap, &size);
856 			fhp->fh_handle.fh_size += size*4;
857 		}
858 	}
859 
860 	nfsd_nr_verified++;
861 	if (fhp->fh_handle.fh_fileid_type == 255)
862 		return nfserr_opnotsupp;
863 	return 0;
864 }
865 
866 /*
867  * Update file handle information after changing a dentry.
868  * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
869  */
870 int
fh_update(struct svc_fh * fhp)871 fh_update(struct svc_fh *fhp)
872 {
873 	struct dentry *dentry;
874 	__u32 *datap;
875 
876 	if (!fhp->fh_dentry)
877 		goto out_bad;
878 
879 	dentry = fhp->fh_dentry;
880 	if (!dentry->d_inode)
881 		goto out_negative;
882 	if (fhp->fh_handle.fh_version != 1) {
883 		_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
884 	} else {
885 		int size;
886 		if (fhp->fh_handle.fh_fileid_type != 0)
887 			goto out_uptodate;
888 		datap = fhp->fh_handle.fh_auth+
889 			fhp->fh_handle.fh_size/4 -1;
890 		size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
891 		fhp->fh_handle.fh_fileid_type =
892 			_fh_update(dentry, fhp->fh_export, datap, &size);
893 		fhp->fh_handle.fh_size += size*4;
894 	}
895 out:
896 	return 0;
897 
898 out_bad:
899 	printk(KERN_ERR "fh_update: fh not verified!\n");
900 	goto out;
901 out_negative:
902 	printk(KERN_ERR "fh_update: %s/%s still negative!\n",
903 		dentry->d_parent->d_name.name, dentry->d_name.name);
904 	goto out;
905 out_uptodate:
906 	printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
907 		dentry->d_parent->d_name.name, dentry->d_name.name);
908 	goto out;
909 }
910 
911 /*
912  * Release a file handle.
913  */
914 void
fh_put(struct svc_fh * fhp)915 fh_put(struct svc_fh *fhp)
916 {
917 	struct dentry * dentry = fhp->fh_dentry;
918 	if (dentry) {
919 		fh_unlock(fhp);
920 		fhp->fh_dentry = NULL;
921 		dput(dentry);
922 		nfsd_nr_put++;
923 	}
924 	return;
925 }
926