1 /*
2  * include/linux/nfsd/nfsfh.h
3  *
4  * This file describes the layout of the file handles as passed
5  * over the wire.
6  *
7  * Earlier versions of knfsd used to sign file handles using keyed MD5
8  * or SHA. I've removed this code, because it doesn't give you more
9  * security than blocking external access to port 2049 on your firewall.
10  *
11  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
12  */
13 
14 #ifndef _LINUX_NFSD_FH_H
15 #define _LINUX_NFSD_FH_H
16 
17 #include <asm/types.h>
18 #ifdef __KERNEL__
19 # include <linux/config.h>
20 # include <linux/types.h>
21 # include <linux/string.h>
22 # include <linux/fs.h>
23 #endif
24 #include <linux/nfsd/const.h>
25 #include <linux/nfsd/debug.h>
26 
27 /*
28  * This is the old "dentry style" Linux NFSv2 file handle.
29  *
30  * The xino and xdev fields are currently used to transport the
31  * ino/dev of the exported inode.
32  */
33 struct nfs_fhbase_old {
34 	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
35 	__u32		fb_ino;		/* our inode number */
36 	__u32		fb_dirino;	/* dir inode number, 0 for directories */
37 	__u32		fb_dev;		/* our device */
38 	__u32		fb_xdev;
39 	__u32		fb_xino;
40 	__u32		fb_generation;
41 };
42 
43 /*
44  * This is the new flexible, extensible style NFSv2/v3 file handle.
45  * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
46  *
47  * The file handle is seens as a list of 4byte words.
48  * The first word contains a version number (1) and four descriptor bytes
49  * that tell how the remaining 3 variable length fields should be handled.
50  * These three bytes are auth_type, fsid_type and fileid_type.
51  *
52  * All 4byte values are in host-byte-order.
53  *
54  * The auth_type field specifies how the filehandle can be authenticated
55  * This might allow a file to be confirmed to be in a writable part of a
56  * filetree without checking the path from it upto the root.
57  * Current values:
58  *     0  - No authentication.  fb_auth is 0 bytes long
59  * Possible future values:
60  *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
61  *          prefixed by a secret and with the important export flags.
62  *
63  * The fsid_type identifies how the filesystem (or export point) is
64  *    encoded.
65  *  Current values:
66  *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
67  *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
68  *              says we mustn't.  We must break it up and reassemble.
69  *  Possible future encodings:
70  *     1  - 4 byte user specified identifier
71  *
72  * The fileid_type identified how the file within the filesystem is encoded.
73  * This is (will be) passed to, and set by, the underlying filesystem if it supports
74  * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
75  * only use the values 1 and 2 as defined below:
76  *  Current values:
77  *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
78  *    1   - 32bit inode number, 32 bit generation number.
79  *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
80  *
81  */
82 struct nfs_fhbase_new {
83 	__u8		fb_version;	/* == 1, even => nfs_fhbase_old */
84 	__u8		fb_auth_type;
85 	__u8		fb_fsid_type;
86 	__u8		fb_fileid_type;
87 	__u32		fb_auth[1];
88 /*	__u32		fb_fsid[0]; floating */
89 /*	__u32		fb_fileid[0]; floating */
90 };
91 
92 struct knfsd_fh {
93 	unsigned int	fh_size;	/* significant for NFSv3.
94 					 * Points to the current size while building
95 					 * a new file handle
96 					 */
97 	union {
98 		struct nfs_fhbase_old	fh_old;
99 		__u32			fh_pad[NFS3_FHSIZE/4];
100 		struct nfs_fhbase_new	fh_new;
101 	} fh_base;
102 };
103 
104 #define ofh_dcookie		fh_base.fh_old.fb_dcookie
105 #define ofh_ino			fh_base.fh_old.fb_ino
106 #define ofh_dirino		fh_base.fh_old.fb_dirino
107 #define ofh_dev			fh_base.fh_old.fb_dev
108 #define ofh_xdev		fh_base.fh_old.fb_xdev
109 #define ofh_xino		fh_base.fh_old.fb_xino
110 #define ofh_generation		fh_base.fh_old.fb_generation
111 
112 #define	fh_version		fh_base.fh_new.fb_version
113 #define	fh_fsid_type		fh_base.fh_new.fb_fsid_type
114 #define	fh_auth_type		fh_base.fh_new.fb_auth_type
115 #define	fh_fileid_type		fh_base.fh_new.fb_fileid_type
116 #define	fh_auth			fh_base.fh_new.fb_auth
117 
118 #ifdef __KERNEL__
119 
120 /*
121  * Conversion macros for the filehandle fields.
122  */
kdev_t_to_u32(kdev_t dev)123 static inline __u32 kdev_t_to_u32(kdev_t dev)
124 {
125 	return (__u32) dev;
126 }
127 
u32_to_kdev_t(__u32 udev)128 static inline kdev_t u32_to_kdev_t(__u32 udev)
129 {
130 	return (kdev_t) udev;
131 }
132 
ino_t_to_u32(ino_t ino)133 static inline __u32 ino_t_to_u32(ino_t ino)
134 {
135 	return (__u32) ino;
136 }
137 
u32_to_ino_t(__u32 uino)138 static inline ino_t u32_to_ino_t(__u32 uino)
139 {
140 	return (ino_t) uino;
141 }
142 
143 /*
144  * This is the internal representation of an NFS handle used in knfsd.
145  * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
146  */
147 typedef struct svc_fh {
148 	struct knfsd_fh		fh_handle;	/* FH data */
149 	struct dentry *		fh_dentry;	/* validated dentry */
150 	struct svc_export *	fh_export;	/* export pointer */
151 	int			fh_maxsize;	/* max size for fh_handle */
152 
153 	unsigned char		fh_locked;	/* inode locked by us */
154 
155 #ifdef CONFIG_NFSD_V3
156 	unsigned char		fh_post_saved;	/* post-op attrs saved */
157 	unsigned char		fh_pre_saved;	/* pre-op attrs saved */
158 
159 	/* Pre-op attributes saved during fh_lock */
160 	__u64			fh_pre_size;	/* size before operation */
161 	time_t			fh_pre_mtime;	/* mtime before oper */
162 	time_t			fh_pre_ctime;	/* ctime before oper */
163 
164 	/* Post-op attributes saved in fh_unlock */
165 	umode_t			fh_post_mode;	/* i_mode */
166 	nlink_t			fh_post_nlink;	/* i_nlink */
167 	uid_t			fh_post_uid;	/* i_uid */
168 	gid_t			fh_post_gid;	/* i_gid */
169 	__u64			fh_post_size;	/* i_size */
170 	unsigned long		fh_post_blocks; /* i_blocks */
171 	unsigned long		fh_post_blksize;/* i_blksize */
172 	kdev_t			fh_post_rdev;	/* i_rdev */
173 	time_t			fh_post_atime;	/* i_atime */
174 	time_t			fh_post_mtime;	/* i_mtime */
175 	time_t			fh_post_ctime;	/* i_ctime */
176 #endif /* CONFIG_NFSD_V3 */
177 
178 } svc_fh;
179 
180 /*
181  * Shorthand for dprintk()'s
182  */
SVCFH_fmt(struct svc_fh * fhp)183 inline static char * SVCFH_fmt(struct svc_fh *fhp)
184 {
185 	struct knfsd_fh *fh = &fhp->fh_handle;
186 
187 	static char buf[80];
188 	sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
189 		fh->fh_size,
190 		fh->fh_base.fh_pad[0],
191 		fh->fh_base.fh_pad[1],
192 		fh->fh_base.fh_pad[2],
193 		fh->fh_base.fh_pad[3],
194 		fh->fh_base.fh_pad[4],
195 		fh->fh_base.fh_pad[5]);
196 	return buf;
197 }
198 /*
199  * Function prototypes
200  */
201 u32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
202 int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
203 int	fh_update(struct svc_fh *);
204 void	fh_put(struct svc_fh *);
205 
206 static __inline__ struct svc_fh *
fh_copy(struct svc_fh * dst,struct svc_fh * src)207 fh_copy(struct svc_fh *dst, struct svc_fh *src)
208 {
209 	if (src->fh_dentry || src->fh_locked) {
210 		struct dentry *dentry = src->fh_dentry;
211 		printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
212 			dentry->d_parent->d_name.name, dentry->d_name.name);
213 	}
214 
215 	*dst = *src;
216 	return dst;
217 }
218 
219 static __inline__ struct svc_fh *
fh_init(struct svc_fh * fhp,int maxsize)220 fh_init(struct svc_fh *fhp, int maxsize)
221 {
222 	memset(fhp, 0, sizeof(*fhp));
223 	fhp->fh_maxsize = maxsize;
224 	return fhp;
225 }
226 
227 #ifdef CONFIG_NFSD_V3
228 /*
229  * Fill in the pre_op attr for the wcc data
230  */
231 static inline void
fill_pre_wcc(struct svc_fh * fhp)232 fill_pre_wcc(struct svc_fh *fhp)
233 {
234 	struct inode    *inode;
235 
236 	inode = fhp->fh_dentry->d_inode;
237 	if (!fhp->fh_pre_saved) {
238 		fhp->fh_pre_mtime = inode->i_mtime;
239 			fhp->fh_pre_ctime = inode->i_ctime;
240 			fhp->fh_pre_size  = inode->i_size;
241 			fhp->fh_pre_saved = 1;
242 	}
243 }
244 
245 /*
246  * Fill in the post_op attr for the wcc data
247  */
248 static inline void
fill_post_wcc(struct svc_fh * fhp)249 fill_post_wcc(struct svc_fh *fhp)
250 {
251 	struct inode    *inode = fhp->fh_dentry->d_inode;
252 
253 	if (fhp->fh_post_saved)
254 		printk("nfsd: inode locked twice during operation.\n");
255 
256 	fhp->fh_post_mode       = inode->i_mode;
257 	fhp->fh_post_nlink      = inode->i_nlink;
258 	fhp->fh_post_uid	= inode->i_uid;
259 	fhp->fh_post_gid	= inode->i_gid;
260 	fhp->fh_post_size       = inode->i_size;
261 	if (inode->i_blksize) {
262 		fhp->fh_post_blksize    = inode->i_blksize;
263 		fhp->fh_post_blocks     = inode->i_blocks;
264 	} else {
265 		fhp->fh_post_blksize    = BLOCK_SIZE;
266 		/* how much do we care for accuracy with MinixFS? */
267 		fhp->fh_post_blocks     = (inode->i_size+511) >> 9;
268 	}
269 	fhp->fh_post_rdev       = inode->i_rdev;
270 	fhp->fh_post_atime      = inode->i_atime;
271 	fhp->fh_post_mtime      = inode->i_mtime;
272 	fhp->fh_post_ctime      = inode->i_ctime;
273 	fhp->fh_post_saved      = 1;
274 }
275 #else
276 #define	fill_pre_wcc(ignored)
277 #define fill_post_wcc(notused)
278 #endif /* CONFIG_NFSD_V3 */
279 
280 
281 /*
282  * Lock a file handle/inode
283  * NOTE: both fh_lock and fh_unlock are done "by hand" in
284  * vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once
285  * so, any changes here should be reflected there.
286  */
287 static inline void
fh_lock(struct svc_fh * fhp)288 fh_lock(struct svc_fh *fhp)
289 {
290 	struct dentry	*dentry = fhp->fh_dentry;
291 	struct inode	*inode;
292 
293 	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
294 			SVCFH_fmt(fhp), fhp->fh_locked);
295 
296 	if (!fhp->fh_dentry) {
297 		printk(KERN_ERR "fh_lock: fh not verified!\n");
298 		return;
299 	}
300 	if (fhp->fh_locked) {
301 		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
302 			dentry->d_parent->d_name.name, dentry->d_name.name);
303 		return;
304 	}
305 
306 	inode = dentry->d_inode;
307 	down(&inode->i_sem);
308 	fill_pre_wcc(fhp);
309 	fhp->fh_locked = 1;
310 }
311 
312 /*
313  * Unlock a file handle/inode
314  */
315 static inline void
fh_unlock(struct svc_fh * fhp)316 fh_unlock(struct svc_fh *fhp)
317 {
318 	if (!fhp->fh_dentry)
319 		printk(KERN_ERR "fh_unlock: fh not verified!\n");
320 
321 	if (fhp->fh_locked) {
322 		fill_post_wcc(fhp);
323 		up(&fhp->fh_dentry->d_inode->i_sem);
324 		fhp->fh_locked = 0;
325 	}
326 }
327 #endif /* __KERNEL__ */
328 
329 
330 #endif /* _LINUX_NFSD_FH_H */
331