1/*
2 * @TAG(OTHER_GPL)
3 */
4
5/*
6 * linux/fs/fat/file.c
7 *
8 * Written 1992,1993 by Werner Almesberger
9 *
10 * regular file handling primitives for fat-based filesystems
11 *
12 */
13
14#include <linux/capability.h>
15#include <linux/module.h>
16#include <linux/compat.h>
17#include <linux/mount.h>
18#include <linux/blkdev.h>
19#include <linux/backing-dev.h>
20#include <linux/fsnotify.h>
21#include <linux/security.h>
22#include "fat.h"
23
24static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
25{
26	u32 attr;
27
28#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
29	mutex_lock(&inode->i_mutex);
30#else
31        inode_lock_shared(inode);
32#endif
33	attr = fat_make_attrs(inode);
34#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
35	mutex_unlock(&inode->i_mutex);
36#else
37        inode_unlock_shared(inode);
38#endif
39
40	return put_user(attr, user_attr);
41}
42
43static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
44{
45	struct inode *inode = file_inode(file);
46	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
47	int is_dir = S_ISDIR(inode->i_mode);
48	u32 attr, oldattr;
49	struct iattr ia;
50	int err;
51
52	err = get_user(attr, user_attr);
53	if (err)
54		goto out;
55
56	err = mnt_want_write_file(file);
57	if (err)
58		goto out;
59
60#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
61	mutex_lock(&inode->i_mutex);
62#else
63        inode_lock_shared(inode);
64#endif
65
66	/*
67	 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
68	 * prevents the user from turning us into a VFAT
69	 * longname entry.  Also, we obviously can't set
70	 * any of the NTFS attributes in the high 24 bits.
71	 */
72	attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
73	/* Merge in ATTR_VOLUME and ATTR_DIR */
74	attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
75		(is_dir ? ATTR_DIR : 0);
76	oldattr = fat_make_attrs(inode);
77
78	/* Equivalent to a chmod() */
79	ia.ia_valid = ATTR_MODE | ATTR_CTIME;
80	ia.ia_ctime = current_fs_time(inode->i_sb);
81	if (is_dir)
82		ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
83	else {
84		ia.ia_mode = fat_make_mode(sbi, attr,
85			S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
86	}
87
88	/* The root directory has no attributes */
89	if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
90		err = -EINVAL;
91		goto out_unlock_inode;
92	}
93
94	if (sbi->options.sys_immutable &&
95	    ((attr | oldattr) & ATTR_SYS) &&
96	    !capable(CAP_LINUX_IMMUTABLE)) {
97		err = -EPERM;
98		goto out_unlock_inode;
99	}
100
101	/*
102	 * The security check is questionable...  We single
103	 * out the RO attribute for checking by the security
104	 * module, just because it maps to a file mode.
105	 */
106	err = security_inode_setattr(file->f_path.dentry, &ia);
107	if (err)
108		goto out_unlock_inode;
109
110	/* This MUST be done before doing anything irreversible... */
111	err = fat_setattr(file->f_path.dentry, &ia);
112	if (err)
113		goto out_unlock_inode;
114
115	fsnotify_change(file->f_path.dentry, ia.ia_valid);
116	if (sbi->options.sys_immutable) {
117		if (attr & ATTR_SYS)
118			inode->i_flags |= S_IMMUTABLE;
119		else
120			inode->i_flags &= ~S_IMMUTABLE;
121	}
122
123	fat_save_attrs(inode, attr);
124	mark_inode_dirty(inode);
125out_unlock_inode:
126#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
127	mutex_unlock(&inode->i_mutex);
128#else
129        inode_unlock_shared(inode);
130#endif
131	mnt_drop_write_file(file);
132out:
133	return err;
134}
135
136static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr)
137{
138	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
139	return put_user(sbi->vol_id, user_attr);
140}
141
142long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
143{
144	struct inode *inode = file_inode(filp);
145	u32 __user *user_attr = (u32 __user *)arg;
146
147	switch (cmd) {
148	case FAT_IOCTL_GET_ATTRIBUTES:
149		return fat_ioctl_get_attributes(inode, user_attr);
150	case FAT_IOCTL_SET_ATTRIBUTES:
151		return fat_ioctl_set_attributes(filp, user_attr);
152	case FAT_IOCTL_GET_VOLUME_ID:
153		return fat_ioctl_get_volume_id(inode, user_attr);
154	default:
155		return -ENOTTY;	/* Inappropriate ioctl for device */
156	}
157}
158
159#ifdef CONFIG_COMPAT
160static long fat_generic_compat_ioctl(struct file *filp, unsigned int cmd,
161				      unsigned long arg)
162
163{
164	return fat_generic_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
165}
166#endif
167
168static int fat_file_release(struct inode *inode, struct file *filp)
169{
170	if ((filp->f_mode & FMODE_WRITE) &&
171	     MSDOS_SB(inode->i_sb)->options.flush) {
172		fat_flush_inodes(inode->i_sb, inode, NULL);
173		congestion_wait(BLK_RW_ASYNC, HZ/10);
174	}
175	return 0;
176}
177
178int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
179{
180	struct inode *inode = filp->f_mapping->host;
181	int res, err;
182
183	res = generic_file_fsync(filp, start, end, datasync);
184	err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
185
186	return res ? res : err;
187}
188
189
190const struct file_operations fat_file_operations = {
191	.llseek		= generic_file_llseek,
192	.read_iter	= generic_file_read_iter,
193	.write_iter	= generic_file_write_iter,
194	.mmap		= generic_file_mmap,
195	.release	= fat_file_release,
196	.unlocked_ioctl	= fat_generic_ioctl,
197#ifdef CONFIG_COMPAT
198	.compat_ioctl	= fat_generic_compat_ioctl,
199#endif
200	.fsync		= fat_file_fsync,
201	.splice_read	= generic_file_splice_read,
202};
203
204static int fat_cont_expand(struct inode *inode, loff_t size)
205{
206	struct address_space *mapping = inode->i_mapping;
207	loff_t start = inode->i_size, count = size - inode->i_size;
208	int err;
209
210	err = generic_cont_expand_simple(inode, size);
211	if (err)
212		goto out;
213
214        inode->i_ctime = inode->i_mtime = current_time(inode);
215	mark_inode_dirty(inode);
216	if (IS_SYNC(inode)) {
217		int err2;
218
219		/*
220		 * Opencode syncing since we don't have a file open to use
221		 * standard fsync path.
222		 */
223		err = filemap_fdatawrite_range(mapping, start,
224					       start + count - 1);
225		err2 = sync_mapping_buffers(mapping);
226		if (!err)
227			err = err2;
228		err2 = write_inode_now(inode, 1);
229		if (!err)
230			err = err2;
231		if (!err) {
232			err =  filemap_fdatawait_range(mapping, start,
233						       start + count - 1);
234		}
235	}
236out:
237	return err;
238}
239
240/* Free all clusters after the skip'th cluster. */
241static int fat_free(struct inode *inode, int skip)
242{
243	struct super_block *sb = inode->i_sb;
244	int err, wait, free_start, i_start, i_logstart;
245
246	if (MSDOS_I(inode)->i_start == 0)
247		return 0;
248
249	fat_cache_inval_inode(inode);
250
251	wait = IS_DIRSYNC(inode);
252	i_start = free_start = MSDOS_I(inode)->i_start;
253	i_logstart = MSDOS_I(inode)->i_logstart;
254
255	/* First, we write the new file size. */
256	if (!skip) {
257		MSDOS_I(inode)->i_start = 0;
258		MSDOS_I(inode)->i_logstart = 0;
259	}
260	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
261        inode->i_ctime = inode->i_mtime = current_time(inode);
262	if (wait) {
263		err = fat_sync_inode(inode);
264		if (err) {
265			MSDOS_I(inode)->i_start = i_start;
266			MSDOS_I(inode)->i_logstart = i_logstart;
267			return err;
268		}
269	} else
270		mark_inode_dirty(inode);
271
272	/* Write a new EOF, and get the remaining cluster chain for freeing. */
273	if (skip) {
274		struct fat_entry fatent;
275		int ret, fclus, dclus;
276
277		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
278		if (ret < 0)
279			return ret;
280		else if (ret == FAT_ENT_EOF)
281			return 0;
282
283		fatent_init(&fatent);
284		ret = fat_ent_read(inode, &fatent, dclus);
285		if (ret == FAT_ENT_EOF) {
286			fatent_brelse(&fatent);
287			return 0;
288		} else if (ret == FAT_ENT_FREE) {
289			fat_fs_error(sb,
290				     "%s: invalid cluster chain (i_pos %lld)",
291				     __func__, MSDOS_I(inode)->i_pos);
292			ret = -EIO;
293		} else if (ret > 0) {
294			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
295			if (err)
296				ret = err;
297		}
298		fatent_brelse(&fatent);
299		if (ret < 0)
300			return ret;
301
302		free_start = ret;
303	}
304	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
305
306	/* Freeing the remained cluster chain */
307	return fat_free_clusters(inode, free_start);
308}
309
310void fat_truncate_blocks(struct inode *inode, loff_t offset)
311{
312	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
313	const unsigned int cluster_size = sbi->cluster_size;
314	int nr_clusters;
315
316	/*
317	 * This protects against truncating a file bigger than it was then
318	 * trying to write into the hole.
319	 */
320	if (MSDOS_I(inode)->mmu_private > offset)
321		MSDOS_I(inode)->mmu_private = offset;
322
323	nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
324
325	fat_free(inode, nr_clusters);
326	fat_flush_inodes(inode->i_sb, inode, NULL);
327}
328
329int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
330{
331	struct inode *inode = d_inode(dentry);
332	generic_fillattr(inode, stat);
333	stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
334
335	if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
336		/* Use i_pos for ino. This is used as fileid of nfs. */
337		stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode);
338	}
339	return 0;
340}
341//EXPORT_SYMBOL_GPL(fat_getattr);
342
343static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
344			     struct inode *inode, umode_t *mode_ptr)
345{
346	umode_t mask, perm;
347
348	/*
349	 * Note, the basic check is already done by a caller of
350	 * (attr->ia_mode & ~FAT_VALID_MODE)
351	 */
352
353	if (S_ISREG(inode->i_mode))
354		mask = sbi->options.fs_fmask;
355	else
356		mask = sbi->options.fs_dmask;
357
358	perm = *mode_ptr & ~(S_IFMT | mask);
359
360	/*
361	 * Of the r and x bits, all (subject to umask) must be present. Of the
362	 * w bits, either all (subject to umask) or none must be present.
363	 *
364	 * If fat_mode_can_hold_ro(inode) is false, can't change w bits.
365	 */
366	if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
367		return -EPERM;
368	if (fat_mode_can_hold_ro(inode)) {
369		if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
370			return -EPERM;
371	} else {
372		if ((perm & S_IWUGO) != (S_IWUGO & ~mask))
373			return -EPERM;
374	}
375
376	*mode_ptr &= S_IFMT | perm;
377
378	return 0;
379}
380
381static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
382{
383	umode_t allow_utime = sbi->options.allow_utime;
384
385	if (!uid_eq(current_fsuid(), inode->i_uid)) {
386		if (in_group_p(inode->i_gid))
387			allow_utime >>= 3;
388		if (allow_utime & MAY_WRITE)
389			return 1;
390	}
391
392	/* use a default check */
393	return 0;
394}
395
396#define TIMES_SET_FLAGS	(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
397/* valid file mode bits */
398#define FAT_VALID_MODE	(S_IFREG | S_IFDIR | S_IRWXUGO)
399
400int fat_setattr(struct dentry *dentry, struct iattr *attr)
401{
402	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
403	struct inode *inode = d_inode(dentry);
404	unsigned int ia_valid;
405	int error;
406
407	/* Check for setting the inode time. */
408	ia_valid = attr->ia_valid;
409	if (ia_valid & TIMES_SET_FLAGS) {
410		if (fat_allow_set_time(sbi, inode))
411			attr->ia_valid &= ~TIMES_SET_FLAGS;
412	}
413
414#if LINUX_VERSION_CODE > KERNEL_VERSION(4,9,0)
415        error = setattr_prepare(dentry, attr);
416#else
417	error = inode_change_ok(inode, attr);
418#endif
419	attr->ia_valid = ia_valid;
420	if (error) {
421		if (sbi->options.quiet)
422			error = 0;
423		goto out;
424	}
425
426	/*
427	 * Expand the file. Since inode_setattr() updates ->i_size
428	 * before calling the ->truncate(), but FAT needs to fill the
429	 * hole before it. XXX: this is no longer true with new truncate
430	 * sequence.
431	 */
432	if (attr->ia_valid & ATTR_SIZE) {
433		inode_dio_wait(inode);
434
435		if (attr->ia_size > inode->i_size) {
436			error = fat_cont_expand(inode, attr->ia_size);
437			if (error || attr->ia_valid == ATTR_SIZE)
438				goto out;
439			attr->ia_valid &= ~ATTR_SIZE;
440		}
441	}
442
443	if (((attr->ia_valid & ATTR_UID) &&
444	     (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
445	    ((attr->ia_valid & ATTR_GID) &&
446	     (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
447	    ((attr->ia_valid & ATTR_MODE) &&
448	     (attr->ia_mode & ~FAT_VALID_MODE)))
449		error = -EPERM;
450
451	if (error) {
452		if (sbi->options.quiet)
453			error = 0;
454		goto out;
455	}
456
457	/*
458	 * We don't return -EPERM here. Yes, strange, but this is too
459	 * old behavior.
460	 */
461	if (attr->ia_valid & ATTR_MODE) {
462		if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
463			attr->ia_valid &= ~ATTR_MODE;
464	}
465
466	if (attr->ia_valid & ATTR_SIZE) {
467		error = fat_block_truncate_page(inode, attr->ia_size);
468		if (error)
469			goto out;
470		down_write(&MSDOS_I(inode)->truncate_lock);
471		truncate_setsize(inode, attr->ia_size);
472		fat_truncate_blocks(inode, attr->ia_size);
473		up_write(&MSDOS_I(inode)->truncate_lock);
474	}
475
476	setattr_copy(inode, attr);
477	mark_inode_dirty(inode);
478out:
479	return error;
480}
481//EXPORT_SYMBOL_GPL(fat_setattr);
482
483const struct inode_operations fat_file_inode_operations = {
484	.setattr	= fat_setattr,
485	.getattr	= fat_getattr,
486};
487