• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_bit.h"
21 #include "xfs_log.h"
22 #include "xfs_inum.h"
23 #include "xfs_trans.h"
24 #include "xfs_sb.h"
25 #include "xfs_ag.h"
26 #include "xfs_dir2.h"
27 #include "xfs_alloc.h"
28 #include "xfs_dmapi.h"
29 #include "xfs_mount.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h"
33 #include "xfs_attr_sf.h"
34 #include "xfs_dir2_sf.h"
35 #include "xfs_dinode.h"
36 #include "xfs_inode.h"
37 #include "xfs_btree.h"
38 #include "xfs_ialloc.h"
39 #include "xfs_rtalloc.h"
40 #include "xfs_itable.h"
41 #include "xfs_error.h"
42 #include "xfs_rw.h"
43 #include "xfs_acl.h"
44 #include "xfs_attr.h"
45 #include "xfs_bmap.h"
46 #include "xfs_buf_item.h"
47 #include "xfs_utils.h"
48 #include "xfs_dfrag.h"
49 #include "xfs_fsops.h"
50 #include "xfs_vnodeops.h"
51 #include "xfs_quota.h"
52 #include "xfs_inode_item.h"
53 #include "xfs_export.h"
54 
55 #include <linux/capability.h>
56 #include <linux/dcache.h>
57 #include <linux/mount.h>
58 #include <linux/namei.h>
59 #include <linux/pagemap.h>
60 #include <linux/exportfs.h>
61 
62 /*
63  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
64  * a file or fs handle.
65  *
66  * XFS_IOC_PATH_TO_FSHANDLE
67  *    returns fs handle for a mount point or path within that mount point
68  * XFS_IOC_FD_TO_HANDLE
69  *    returns full handle for a FD opened in user space
70  * XFS_IOC_PATH_TO_HANDLE
71  *    returns full handle for a path
72  */
73 int
xfs_find_handle(unsigned int cmd,xfs_fsop_handlereq_t * hreq)74 xfs_find_handle(
75 	unsigned int		cmd,
76 	xfs_fsop_handlereq_t	*hreq)
77 {
78 	int			hsize;
79 	xfs_handle_t		handle;
80 	struct inode		*inode;
81 
82 	memset((char *)&handle, 0, sizeof(handle));
83 
84 	switch (cmd) {
85 	case XFS_IOC_PATH_TO_FSHANDLE:
86 	case XFS_IOC_PATH_TO_HANDLE: {
87 		struct path path;
88 		int error = user_lpath((const char __user *)hreq->path, &path);
89 		if (error)
90 			return error;
91 
92 		ASSERT(path.dentry);
93 		ASSERT(path.dentry->d_inode);
94 		inode = igrab(path.dentry->d_inode);
95 		path_put(&path);
96 		break;
97 	}
98 
99 	case XFS_IOC_FD_TO_HANDLE: {
100 		struct file	*file;
101 
102 		file = fget(hreq->fd);
103 		if (!file)
104 		    return -EBADF;
105 
106 		ASSERT(file->f_path.dentry);
107 		ASSERT(file->f_path.dentry->d_inode);
108 		inode = igrab(file->f_path.dentry->d_inode);
109 		fput(file);
110 		break;
111 	}
112 
113 	default:
114 		ASSERT(0);
115 		return -XFS_ERROR(EINVAL);
116 	}
117 
118 	if (inode->i_sb->s_magic != XFS_SB_MAGIC) {
119 		/* we're not in XFS anymore, Toto */
120 		iput(inode);
121 		return -XFS_ERROR(EINVAL);
122 	}
123 
124 	switch (inode->i_mode & S_IFMT) {
125 	case S_IFREG:
126 	case S_IFDIR:
127 	case S_IFLNK:
128 		break;
129 	default:
130 		iput(inode);
131 		return -XFS_ERROR(EBADF);
132 	}
133 
134 	/* now we can grab the fsid */
135 	memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
136 			sizeof(xfs_fsid_t));
137 	hsize = sizeof(xfs_fsid_t);
138 
139 	if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
140 		xfs_inode_t	*ip = XFS_I(inode);
141 		int		lock_mode;
142 
143 		/* need to get access to the xfs_inode to read the generation */
144 		lock_mode = xfs_ilock_map_shared(ip);
145 
146 		/* fill in fid section of handle from inode */
147 		handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
148 					sizeof(handle.ha_fid.fid_len);
149 		handle.ha_fid.fid_pad = 0;
150 		handle.ha_fid.fid_gen = ip->i_d.di_gen;
151 		handle.ha_fid.fid_ino = ip->i_ino;
152 
153 		xfs_iunlock_map_shared(ip, lock_mode);
154 
155 		hsize = XFS_HSIZE(handle);
156 	}
157 
158 	/* now copy our handle into the user buffer & write out the size */
159 	if (copy_to_user(hreq->ohandle, &handle, hsize) ||
160 	    copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) {
161 		iput(inode);
162 		return -XFS_ERROR(EFAULT);
163 	}
164 
165 	iput(inode);
166 	return 0;
167 }
168 
169 /*
170  * No need to do permission checks on the various pathname components
171  * as the handle operations are privileged.
172  */
173 STATIC int
xfs_handle_acceptable(void * context,struct dentry * dentry)174 xfs_handle_acceptable(
175 	void			*context,
176 	struct dentry		*dentry)
177 {
178 	return 1;
179 }
180 
181 /*
182  * Convert userspace handle data into a dentry.
183  */
184 struct dentry *
xfs_handle_to_dentry(struct file * parfilp,void __user * uhandle,u32 hlen)185 xfs_handle_to_dentry(
186 	struct file		*parfilp,
187 	void __user		*uhandle,
188 	u32			hlen)
189 {
190 	xfs_handle_t		handle;
191 	struct xfs_fid64	fid;
192 
193 	/*
194 	 * Only allow handle opens under a directory.
195 	 */
196 	if (!S_ISDIR(parfilp->f_path.dentry->d_inode->i_mode))
197 		return ERR_PTR(-ENOTDIR);
198 
199 	if (hlen != sizeof(xfs_handle_t))
200 		return ERR_PTR(-EINVAL);
201 	if (copy_from_user(&handle, uhandle, hlen))
202 		return ERR_PTR(-EFAULT);
203 	if (handle.ha_fid.fid_len !=
204 	    sizeof(handle.ha_fid) - sizeof(handle.ha_fid.fid_len))
205 		return ERR_PTR(-EINVAL);
206 
207 	memset(&fid, 0, sizeof(struct fid));
208 	fid.ino = handle.ha_fid.fid_ino;
209 	fid.gen = handle.ha_fid.fid_gen;
210 
211 	return exportfs_decode_fh(parfilp->f_path.mnt, (struct fid *)&fid, 3,
212 			FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
213 			xfs_handle_acceptable, NULL);
214 }
215 
216 STATIC struct dentry *
xfs_handlereq_to_dentry(struct file * parfilp,xfs_fsop_handlereq_t * hreq)217 xfs_handlereq_to_dentry(
218 	struct file		*parfilp,
219 	xfs_fsop_handlereq_t	*hreq)
220 {
221 	return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
222 }
223 
224 int
xfs_open_by_handle(struct file * parfilp,xfs_fsop_handlereq_t * hreq)225 xfs_open_by_handle(
226 	struct file		*parfilp,
227 	xfs_fsop_handlereq_t	*hreq)
228 {
229 	const struct cred	*cred = current_cred();
230 	int			error;
231 	int			fd;
232 	int			permflag;
233 	struct file		*filp;
234 	struct inode		*inode;
235 	struct dentry		*dentry;
236 
237 	if (!capable(CAP_SYS_ADMIN))
238 		return -XFS_ERROR(EPERM);
239 
240 	dentry = xfs_handlereq_to_dentry(parfilp, hreq);
241 	if (IS_ERR(dentry))
242 		return PTR_ERR(dentry);
243 	inode = dentry->d_inode;
244 
245 	/* Restrict xfs_open_by_handle to directories & regular files. */
246 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
247 		error = -XFS_ERROR(EPERM);
248 		goto out_dput;
249 	}
250 
251 #if BITS_PER_LONG != 32
252 	hreq->oflags |= O_LARGEFILE;
253 #endif
254 
255 	/* Put open permission in namei format. */
256 	permflag = hreq->oflags;
257 	if ((permflag+1) & O_ACCMODE)
258 		permflag++;
259 	if (permflag & O_TRUNC)
260 		permflag |= 2;
261 
262 	if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
263 	    (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
264 		error = -XFS_ERROR(EPERM);
265 		goto out_dput;
266 	}
267 
268 	if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
269 		error = -XFS_ERROR(EACCES);
270 		goto out_dput;
271 	}
272 
273 	/* Can't write directories. */
274 	if (S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
275 		error = -XFS_ERROR(EISDIR);
276 		goto out_dput;
277 	}
278 
279 	fd = get_unused_fd();
280 	if (fd < 0) {
281 		error = fd;
282 		goto out_dput;
283 	}
284 
285 	filp = dentry_open(dentry, mntget(parfilp->f_path.mnt),
286 			   hreq->oflags, cred);
287 	if (IS_ERR(filp)) {
288 		put_unused_fd(fd);
289 		return PTR_ERR(filp);
290 	}
291 
292 	if (inode->i_mode & S_IFREG) {
293 		filp->f_flags |= O_NOATIME;
294 		filp->f_mode |= FMODE_NOCMTIME;
295 	}
296 
297 	fd_install(fd, filp);
298 	return fd;
299 
300  out_dput:
301 	dput(dentry);
302 	return error;
303 }
304 
305 /*
306  * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
307  * unused first argument.
308  */
309 STATIC int
do_readlink(char __user * buffer,int buflen,const char * link)310 do_readlink(
311 	char __user		*buffer,
312 	int			buflen,
313 	const char		*link)
314 {
315         int len;
316 
317 	len = PTR_ERR(link);
318 	if (IS_ERR(link))
319 		goto out;
320 
321 	len = strlen(link);
322 	if (len > (unsigned) buflen)
323 		len = buflen;
324 	if (copy_to_user(buffer, link, len))
325 		len = -EFAULT;
326  out:
327 	return len;
328 }
329 
330 
331 int
xfs_readlink_by_handle(struct file * parfilp,xfs_fsop_handlereq_t * hreq)332 xfs_readlink_by_handle(
333 	struct file		*parfilp,
334 	xfs_fsop_handlereq_t	*hreq)
335 {
336 	struct dentry		*dentry;
337 	__u32			olen;
338 	void			*link;
339 	int			error;
340 
341 	if (!capable(CAP_SYS_ADMIN))
342 		return -XFS_ERROR(EPERM);
343 
344 	dentry = xfs_handlereq_to_dentry(parfilp, hreq);
345 	if (IS_ERR(dentry))
346 		return PTR_ERR(dentry);
347 
348 	/* Restrict this handle operation to symlinks only. */
349 	if (!S_ISLNK(dentry->d_inode->i_mode)) {
350 		error = -XFS_ERROR(EINVAL);
351 		goto out_dput;
352 	}
353 
354 	if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
355 		error = -XFS_ERROR(EFAULT);
356 		goto out_dput;
357 	}
358 
359 	link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
360 	if (!link) {
361 		error = -XFS_ERROR(ENOMEM);
362 		goto out_dput;
363 	}
364 
365 	error = -xfs_readlink(XFS_I(dentry->d_inode), link);
366 	if (error)
367 		goto out_kfree;
368 	error = do_readlink(hreq->ohandle, olen, link);
369 	if (error)
370 		goto out_kfree;
371 
372  out_kfree:
373 	kfree(link);
374  out_dput:
375 	dput(dentry);
376 	return error;
377 }
378 
379 STATIC int
xfs_fssetdm_by_handle(struct file * parfilp,void __user * arg)380 xfs_fssetdm_by_handle(
381 	struct file		*parfilp,
382 	void			__user *arg)
383 {
384 	int			error;
385 	struct fsdmidata	fsd;
386 	xfs_fsop_setdm_handlereq_t dmhreq;
387 	struct dentry		*dentry;
388 
389 	if (!capable(CAP_MKNOD))
390 		return -XFS_ERROR(EPERM);
391 	if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
392 		return -XFS_ERROR(EFAULT);
393 
394 	dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq);
395 	if (IS_ERR(dentry))
396 		return PTR_ERR(dentry);
397 
398 	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
399 		error = -XFS_ERROR(EPERM);
400 		goto out;
401 	}
402 
403 	if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
404 		error = -XFS_ERROR(EFAULT);
405 		goto out;
406 	}
407 
408 	error = -xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask,
409 				 fsd.fsd_dmstate);
410 
411  out:
412 	dput(dentry);
413 	return error;
414 }
415 
416 STATIC int
xfs_attrlist_by_handle(struct file * parfilp,void __user * arg)417 xfs_attrlist_by_handle(
418 	struct file		*parfilp,
419 	void			__user *arg)
420 {
421 	int			error = -ENOMEM;
422 	attrlist_cursor_kern_t	*cursor;
423 	xfs_fsop_attrlist_handlereq_t al_hreq;
424 	struct dentry		*dentry;
425 	char			*kbuf;
426 
427 	if (!capable(CAP_SYS_ADMIN))
428 		return -XFS_ERROR(EPERM);
429 	if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
430 		return -XFS_ERROR(EFAULT);
431 	if (al_hreq.buflen > XATTR_LIST_MAX)
432 		return -XFS_ERROR(EINVAL);
433 
434 	/*
435 	 * Reject flags, only allow namespaces.
436 	 */
437 	if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
438 		return -XFS_ERROR(EINVAL);
439 
440 	dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
441 	if (IS_ERR(dentry))
442 		return PTR_ERR(dentry);
443 
444 	kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL);
445 	if (!kbuf)
446 		goto out_dput;
447 
448 	cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
449 	error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
450 					al_hreq.flags, cursor);
451 	if (error)
452 		goto out_kfree;
453 
454 	if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
455 		error = -EFAULT;
456 
457  out_kfree:
458 	kfree(kbuf);
459  out_dput:
460 	dput(dentry);
461 	return error;
462 }
463 
464 int
xfs_attrmulti_attr_get(struct inode * inode,char * name,char __user * ubuf,__uint32_t * len,__uint32_t flags)465 xfs_attrmulti_attr_get(
466 	struct inode		*inode,
467 	char			*name,
468 	char			__user *ubuf,
469 	__uint32_t		*len,
470 	__uint32_t		flags)
471 {
472 	char			*kbuf;
473 	int			error = EFAULT;
474 
475 	if (*len > XATTR_SIZE_MAX)
476 		return EINVAL;
477 	kbuf = kmalloc(*len, GFP_KERNEL);
478 	if (!kbuf)
479 		return ENOMEM;
480 
481 	error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
482 	if (error)
483 		goto out_kfree;
484 
485 	if (copy_to_user(ubuf, kbuf, *len))
486 		error = EFAULT;
487 
488  out_kfree:
489 	kfree(kbuf);
490 	return error;
491 }
492 
493 int
xfs_attrmulti_attr_set(struct inode * inode,char * name,const char __user * ubuf,__uint32_t len,__uint32_t flags)494 xfs_attrmulti_attr_set(
495 	struct inode		*inode,
496 	char			*name,
497 	const char		__user *ubuf,
498 	__uint32_t		len,
499 	__uint32_t		flags)
500 {
501 	char			*kbuf;
502 	int			error = EFAULT;
503 
504 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
505 		return EPERM;
506 	if (len > XATTR_SIZE_MAX)
507 		return EINVAL;
508 
509 	kbuf = kmalloc(len, GFP_KERNEL);
510 	if (!kbuf)
511 		return ENOMEM;
512 
513 	if (copy_from_user(kbuf, ubuf, len))
514 		goto out_kfree;
515 
516 	error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
517 
518  out_kfree:
519 	kfree(kbuf);
520 	return error;
521 }
522 
523 int
xfs_attrmulti_attr_remove(struct inode * inode,char * name,__uint32_t flags)524 xfs_attrmulti_attr_remove(
525 	struct inode		*inode,
526 	char			*name,
527 	__uint32_t		flags)
528 {
529 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
530 		return EPERM;
531 	return xfs_attr_remove(XFS_I(inode), name, flags);
532 }
533 
534 STATIC int
xfs_attrmulti_by_handle(struct file * parfilp,void __user * arg)535 xfs_attrmulti_by_handle(
536 	struct file		*parfilp,
537 	void			__user *arg)
538 {
539 	int			error;
540 	xfs_attr_multiop_t	*ops;
541 	xfs_fsop_attrmulti_handlereq_t am_hreq;
542 	struct dentry		*dentry;
543 	unsigned int		i, size;
544 	char			*attr_name;
545 
546 	if (!capable(CAP_SYS_ADMIN))
547 		return -XFS_ERROR(EPERM);
548 	if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
549 		return -XFS_ERROR(EFAULT);
550 
551 	dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
552 	if (IS_ERR(dentry))
553 		return PTR_ERR(dentry);
554 
555 	error = E2BIG;
556 	size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
557 	if (!size || size > 16 * PAGE_SIZE)
558 		goto out_dput;
559 
560 	error = ENOMEM;
561 	ops = kmalloc(size, GFP_KERNEL);
562 	if (!ops)
563 		goto out_dput;
564 
565 	error = EFAULT;
566 	if (copy_from_user(ops, am_hreq.ops, size))
567 		goto out_kfree_ops;
568 
569 	attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
570 	if (!attr_name)
571 		goto out_kfree_ops;
572 
573 
574 	error = 0;
575 	for (i = 0; i < am_hreq.opcount; i++) {
576 		ops[i].am_error = strncpy_from_user(attr_name,
577 				ops[i].am_attrname, MAXNAMELEN);
578 		if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
579 			error = -ERANGE;
580 		if (ops[i].am_error < 0)
581 			break;
582 
583 		switch (ops[i].am_opcode) {
584 		case ATTR_OP_GET:
585 			ops[i].am_error = xfs_attrmulti_attr_get(
586 					dentry->d_inode, attr_name,
587 					ops[i].am_attrvalue, &ops[i].am_length,
588 					ops[i].am_flags);
589 			break;
590 		case ATTR_OP_SET:
591 			ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
592 			if (ops[i].am_error)
593 				break;
594 			ops[i].am_error = xfs_attrmulti_attr_set(
595 					dentry->d_inode, attr_name,
596 					ops[i].am_attrvalue, ops[i].am_length,
597 					ops[i].am_flags);
598 			mnt_drop_write(parfilp->f_path.mnt);
599 			break;
600 		case ATTR_OP_REMOVE:
601 			ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
602 			if (ops[i].am_error)
603 				break;
604 			ops[i].am_error = xfs_attrmulti_attr_remove(
605 					dentry->d_inode, attr_name,
606 					ops[i].am_flags);
607 			mnt_drop_write(parfilp->f_path.mnt);
608 			break;
609 		default:
610 			ops[i].am_error = EINVAL;
611 		}
612 	}
613 
614 	if (copy_to_user(am_hreq.ops, ops, size))
615 		error = XFS_ERROR(EFAULT);
616 
617 	kfree(attr_name);
618  out_kfree_ops:
619 	kfree(ops);
620  out_dput:
621 	dput(dentry);
622 	return -error;
623 }
624 
625 int
xfs_ioc_space(struct xfs_inode * ip,struct inode * inode,struct file * filp,int ioflags,unsigned int cmd,xfs_flock64_t * bf)626 xfs_ioc_space(
627 	struct xfs_inode	*ip,
628 	struct inode		*inode,
629 	struct file		*filp,
630 	int			ioflags,
631 	unsigned int		cmd,
632 	xfs_flock64_t		*bf)
633 {
634 	int			attr_flags = 0;
635 	int			error;
636 
637 	/*
638 	 * Only allow the sys admin to reserve space unless
639 	 * unwritten extents are enabled.
640 	 */
641 	if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
642 	    !capable(CAP_SYS_ADMIN))
643 		return -XFS_ERROR(EPERM);
644 
645 	if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
646 		return -XFS_ERROR(EPERM);
647 
648 	if (!(filp->f_mode & FMODE_WRITE))
649 		return -XFS_ERROR(EBADF);
650 
651 	if (!S_ISREG(inode->i_mode))
652 		return -XFS_ERROR(EINVAL);
653 
654 	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
655 		attr_flags |= XFS_ATTR_NONBLOCK;
656 	if (ioflags & IO_INVIS)
657 		attr_flags |= XFS_ATTR_DMI;
658 
659 	error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
660 	return -error;
661 }
662 
663 STATIC int
xfs_ioc_bulkstat(xfs_mount_t * mp,unsigned int cmd,void __user * arg)664 xfs_ioc_bulkstat(
665 	xfs_mount_t		*mp,
666 	unsigned int		cmd,
667 	void			__user *arg)
668 {
669 	xfs_fsop_bulkreq_t	bulkreq;
670 	int			count;	/* # of records returned */
671 	xfs_ino_t		inlast;	/* last inode number */
672 	int			done;
673 	int			error;
674 
675 	/* done = 1 if there are more stats to get and if bulkstat */
676 	/* should be called again (unused here, but used in dmapi) */
677 
678 	if (!capable(CAP_SYS_ADMIN))
679 		return -EPERM;
680 
681 	if (XFS_FORCED_SHUTDOWN(mp))
682 		return -XFS_ERROR(EIO);
683 
684 	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
685 		return -XFS_ERROR(EFAULT);
686 
687 	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
688 		return -XFS_ERROR(EFAULT);
689 
690 	if ((count = bulkreq.icount) <= 0)
691 		return -XFS_ERROR(EINVAL);
692 
693 	if (bulkreq.ubuffer == NULL)
694 		return -XFS_ERROR(EINVAL);
695 
696 	if (cmd == XFS_IOC_FSINUMBERS)
697 		error = xfs_inumbers(mp, &inlast, &count,
698 					bulkreq.ubuffer, xfs_inumbers_fmt);
699 	else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
700 		error = xfs_bulkstat_single(mp, &inlast,
701 						bulkreq.ubuffer, &done);
702 	else	/* XFS_IOC_FSBULKSTAT */
703 		error = xfs_bulkstat(mp, &inlast, &count,
704 			(bulkstat_one_pf)xfs_bulkstat_one, NULL,
705 			sizeof(xfs_bstat_t), bulkreq.ubuffer,
706 			BULKSTAT_FG_QUICK, &done);
707 
708 	if (error)
709 		return -error;
710 
711 	if (bulkreq.ocount != NULL) {
712 		if (copy_to_user(bulkreq.lastip, &inlast,
713 						sizeof(xfs_ino_t)))
714 			return -XFS_ERROR(EFAULT);
715 
716 		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
717 			return -XFS_ERROR(EFAULT);
718 	}
719 
720 	return 0;
721 }
722 
723 STATIC int
xfs_ioc_fsgeometry_v1(xfs_mount_t * mp,void __user * arg)724 xfs_ioc_fsgeometry_v1(
725 	xfs_mount_t		*mp,
726 	void			__user *arg)
727 {
728 	xfs_fsop_geom_v1_t	fsgeo;
729 	int			error;
730 
731 	error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
732 	if (error)
733 		return -error;
734 
735 	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
736 		return -XFS_ERROR(EFAULT);
737 	return 0;
738 }
739 
740 STATIC int
xfs_ioc_fsgeometry(xfs_mount_t * mp,void __user * arg)741 xfs_ioc_fsgeometry(
742 	xfs_mount_t		*mp,
743 	void			__user *arg)
744 {
745 	xfs_fsop_geom_t		fsgeo;
746 	int			error;
747 
748 	error = xfs_fs_geometry(mp, &fsgeo, 4);
749 	if (error)
750 		return -error;
751 
752 	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
753 		return -XFS_ERROR(EFAULT);
754 	return 0;
755 }
756 
757 /*
758  * Linux extended inode flags interface.
759  */
760 
761 STATIC unsigned int
xfs_merge_ioc_xflags(unsigned int flags,unsigned int start)762 xfs_merge_ioc_xflags(
763 	unsigned int	flags,
764 	unsigned int	start)
765 {
766 	unsigned int	xflags = start;
767 
768 	if (flags & FS_IMMUTABLE_FL)
769 		xflags |= XFS_XFLAG_IMMUTABLE;
770 	else
771 		xflags &= ~XFS_XFLAG_IMMUTABLE;
772 	if (flags & FS_APPEND_FL)
773 		xflags |= XFS_XFLAG_APPEND;
774 	else
775 		xflags &= ~XFS_XFLAG_APPEND;
776 	if (flags & FS_SYNC_FL)
777 		xflags |= XFS_XFLAG_SYNC;
778 	else
779 		xflags &= ~XFS_XFLAG_SYNC;
780 	if (flags & FS_NOATIME_FL)
781 		xflags |= XFS_XFLAG_NOATIME;
782 	else
783 		xflags &= ~XFS_XFLAG_NOATIME;
784 	if (flags & FS_NODUMP_FL)
785 		xflags |= XFS_XFLAG_NODUMP;
786 	else
787 		xflags &= ~XFS_XFLAG_NODUMP;
788 
789 	return xflags;
790 }
791 
792 STATIC unsigned int
xfs_di2lxflags(__uint16_t di_flags)793 xfs_di2lxflags(
794 	__uint16_t	di_flags)
795 {
796 	unsigned int	flags = 0;
797 
798 	if (di_flags & XFS_DIFLAG_IMMUTABLE)
799 		flags |= FS_IMMUTABLE_FL;
800 	if (di_flags & XFS_DIFLAG_APPEND)
801 		flags |= FS_APPEND_FL;
802 	if (di_flags & XFS_DIFLAG_SYNC)
803 		flags |= FS_SYNC_FL;
804 	if (di_flags & XFS_DIFLAG_NOATIME)
805 		flags |= FS_NOATIME_FL;
806 	if (di_flags & XFS_DIFLAG_NODUMP)
807 		flags |= FS_NODUMP_FL;
808 	return flags;
809 }
810 
811 STATIC int
xfs_ioc_fsgetxattr(xfs_inode_t * ip,int attr,void __user * arg)812 xfs_ioc_fsgetxattr(
813 	xfs_inode_t		*ip,
814 	int			attr,
815 	void			__user *arg)
816 {
817 	struct fsxattr		fa;
818 
819 	xfs_ilock(ip, XFS_ILOCK_SHARED);
820 	fa.fsx_xflags = xfs_ip2xflags(ip);
821 	fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
822 	fa.fsx_projid = ip->i_d.di_projid;
823 
824 	if (attr) {
825 		if (ip->i_afp) {
826 			if (ip->i_afp->if_flags & XFS_IFEXTENTS)
827 				fa.fsx_nextents = ip->i_afp->if_bytes /
828 							sizeof(xfs_bmbt_rec_t);
829 			else
830 				fa.fsx_nextents = ip->i_d.di_anextents;
831 		} else
832 			fa.fsx_nextents = 0;
833 	} else {
834 		if (ip->i_df.if_flags & XFS_IFEXTENTS)
835 			fa.fsx_nextents = ip->i_df.if_bytes /
836 						sizeof(xfs_bmbt_rec_t);
837 		else
838 			fa.fsx_nextents = ip->i_d.di_nextents;
839 	}
840 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
841 
842 	if (copy_to_user(arg, &fa, sizeof(fa)))
843 		return -EFAULT;
844 	return 0;
845 }
846 
847 STATIC void
xfs_set_diflags(struct xfs_inode * ip,unsigned int xflags)848 xfs_set_diflags(
849 	struct xfs_inode	*ip,
850 	unsigned int		xflags)
851 {
852 	unsigned int		di_flags;
853 
854 	/* can't set PREALLOC this way, just preserve it */
855 	di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
856 	if (xflags & XFS_XFLAG_IMMUTABLE)
857 		di_flags |= XFS_DIFLAG_IMMUTABLE;
858 	if (xflags & XFS_XFLAG_APPEND)
859 		di_flags |= XFS_DIFLAG_APPEND;
860 	if (xflags & XFS_XFLAG_SYNC)
861 		di_flags |= XFS_DIFLAG_SYNC;
862 	if (xflags & XFS_XFLAG_NOATIME)
863 		di_flags |= XFS_DIFLAG_NOATIME;
864 	if (xflags & XFS_XFLAG_NODUMP)
865 		di_flags |= XFS_DIFLAG_NODUMP;
866 	if (xflags & XFS_XFLAG_PROJINHERIT)
867 		di_flags |= XFS_DIFLAG_PROJINHERIT;
868 	if (xflags & XFS_XFLAG_NODEFRAG)
869 		di_flags |= XFS_DIFLAG_NODEFRAG;
870 	if (xflags & XFS_XFLAG_FILESTREAM)
871 		di_flags |= XFS_DIFLAG_FILESTREAM;
872 	if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
873 		if (xflags & XFS_XFLAG_RTINHERIT)
874 			di_flags |= XFS_DIFLAG_RTINHERIT;
875 		if (xflags & XFS_XFLAG_NOSYMLINKS)
876 			di_flags |= XFS_DIFLAG_NOSYMLINKS;
877 		if (xflags & XFS_XFLAG_EXTSZINHERIT)
878 			di_flags |= XFS_DIFLAG_EXTSZINHERIT;
879 	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
880 		if (xflags & XFS_XFLAG_REALTIME)
881 			di_flags |= XFS_DIFLAG_REALTIME;
882 		if (xflags & XFS_XFLAG_EXTSIZE)
883 			di_flags |= XFS_DIFLAG_EXTSIZE;
884 	}
885 
886 	ip->i_d.di_flags = di_flags;
887 }
888 
889 STATIC void
xfs_diflags_to_linux(struct xfs_inode * ip)890 xfs_diflags_to_linux(
891 	struct xfs_inode	*ip)
892 {
893 	struct inode		*inode = VFS_I(ip);
894 	unsigned int		xflags = xfs_ip2xflags(ip);
895 
896 	if (xflags & XFS_XFLAG_IMMUTABLE)
897 		inode->i_flags |= S_IMMUTABLE;
898 	else
899 		inode->i_flags &= ~S_IMMUTABLE;
900 	if (xflags & XFS_XFLAG_APPEND)
901 		inode->i_flags |= S_APPEND;
902 	else
903 		inode->i_flags &= ~S_APPEND;
904 	if (xflags & XFS_XFLAG_SYNC)
905 		inode->i_flags |= S_SYNC;
906 	else
907 		inode->i_flags &= ~S_SYNC;
908 	if (xflags & XFS_XFLAG_NOATIME)
909 		inode->i_flags |= S_NOATIME;
910 	else
911 		inode->i_flags &= ~S_NOATIME;
912 }
913 
914 #define FSX_PROJID	1
915 #define FSX_EXTSIZE	2
916 #define FSX_XFLAGS	4
917 #define FSX_NONBLOCK	8
918 
919 STATIC int
xfs_ioctl_setattr(xfs_inode_t * ip,struct fsxattr * fa,int mask)920 xfs_ioctl_setattr(
921 	xfs_inode_t		*ip,
922 	struct fsxattr		*fa,
923 	int			mask)
924 {
925 	struct xfs_mount	*mp = ip->i_mount;
926 	struct xfs_trans	*tp;
927 	unsigned int		lock_flags = 0;
928 	struct xfs_dquot	*udqp = NULL, *gdqp = NULL;
929 	struct xfs_dquot	*olddquot = NULL;
930 	int			code;
931 
932 	xfs_itrace_entry(ip);
933 
934 	if (mp->m_flags & XFS_MOUNT_RDONLY)
935 		return XFS_ERROR(EROFS);
936 	if (XFS_FORCED_SHUTDOWN(mp))
937 		return XFS_ERROR(EIO);
938 
939 	/*
940 	 * If disk quotas is on, we make sure that the dquots do exist on disk,
941 	 * before we start any other transactions. Trying to do this later
942 	 * is messy. We don't care to take a readlock to look at the ids
943 	 * in inode here, because we can't hold it across the trans_reserve.
944 	 * If the IDs do change before we take the ilock, we're covered
945 	 * because the i_*dquot fields will get updated anyway.
946 	 */
947 	if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
948 		code = XFS_QM_DQVOPALLOC(mp, ip, ip->i_d.di_uid,
949 					 ip->i_d.di_gid, fa->fsx_projid,
950 					 XFS_QMOPT_PQUOTA, &udqp, &gdqp);
951 		if (code)
952 			return code;
953 	}
954 
955 	/*
956 	 * For the other attributes, we acquire the inode lock and
957 	 * first do an error checking pass.
958 	 */
959 	tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
960 	code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
961 	if (code)
962 		goto error_return;
963 
964 	lock_flags = XFS_ILOCK_EXCL;
965 	xfs_ilock(ip, lock_flags);
966 
967 	/*
968 	 * CAP_FOWNER overrides the following restrictions:
969 	 *
970 	 * The user ID of the calling process must be equal
971 	 * to the file owner ID, except in cases where the
972 	 * CAP_FSETID capability is applicable.
973 	 */
974 	if (current_fsuid() != ip->i_d.di_uid && !capable(CAP_FOWNER)) {
975 		code = XFS_ERROR(EPERM);
976 		goto error_return;
977 	}
978 
979 	/*
980 	 * Do a quota reservation only if projid is actually going to change.
981 	 */
982 	if (mask & FSX_PROJID) {
983 		if (XFS_IS_PQUOTA_ON(mp) &&
984 		    ip->i_d.di_projid != fa->fsx_projid) {
985 			ASSERT(tp);
986 			code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
987 						capable(CAP_FOWNER) ?
988 						XFS_QMOPT_FORCE_RES : 0);
989 			if (code)	/* out of quota */
990 				goto error_return;
991 		}
992 	}
993 
994 	if (mask & FSX_EXTSIZE) {
995 		/*
996 		 * Can't change extent size if any extents are allocated.
997 		 */
998 		if (ip->i_d.di_nextents &&
999 		    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
1000 		     fa->fsx_extsize)) {
1001 			code = XFS_ERROR(EINVAL);	/* EFBIG? */
1002 			goto error_return;
1003 		}
1004 
1005 		/*
1006 		 * Extent size must be a multiple of the appropriate block
1007 		 * size, if set at all.
1008 		 */
1009 		if (fa->fsx_extsize != 0) {
1010 			xfs_extlen_t	size;
1011 
1012 			if (XFS_IS_REALTIME_INODE(ip) ||
1013 			    ((mask & FSX_XFLAGS) &&
1014 			    (fa->fsx_xflags & XFS_XFLAG_REALTIME))) {
1015 				size = mp->m_sb.sb_rextsize <<
1016 				       mp->m_sb.sb_blocklog;
1017 			} else {
1018 				size = mp->m_sb.sb_blocksize;
1019 			}
1020 
1021 			if (fa->fsx_extsize % size) {
1022 				code = XFS_ERROR(EINVAL);
1023 				goto error_return;
1024 			}
1025 		}
1026 	}
1027 
1028 
1029 	if (mask & FSX_XFLAGS) {
1030 		/*
1031 		 * Can't change realtime flag if any extents are allocated.
1032 		 */
1033 		if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1034 		    (XFS_IS_REALTIME_INODE(ip)) !=
1035 		    (fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1036 			code = XFS_ERROR(EINVAL);	/* EFBIG? */
1037 			goto error_return;
1038 		}
1039 
1040 		/*
1041 		 * If realtime flag is set then must have realtime data.
1042 		 */
1043 		if ((fa->fsx_xflags & XFS_XFLAG_REALTIME)) {
1044 			if ((mp->m_sb.sb_rblocks == 0) ||
1045 			    (mp->m_sb.sb_rextsize == 0) ||
1046 			    (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
1047 				code = XFS_ERROR(EINVAL);
1048 				goto error_return;
1049 			}
1050 		}
1051 
1052 		/*
1053 		 * Can't modify an immutable/append-only file unless
1054 		 * we have appropriate permission.
1055 		 */
1056 		if ((ip->i_d.di_flags &
1057 				(XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
1058 		     (fa->fsx_xflags &
1059 				(XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
1060 		    !capable(CAP_LINUX_IMMUTABLE)) {
1061 			code = XFS_ERROR(EPERM);
1062 			goto error_return;
1063 		}
1064 	}
1065 
1066 	xfs_trans_ijoin(tp, ip, lock_flags);
1067 	xfs_trans_ihold(tp, ip);
1068 
1069 	/*
1070 	 * Change file ownership.  Must be the owner or privileged.
1071 	 */
1072 	if (mask & FSX_PROJID) {
1073 		/*
1074 		 * CAP_FSETID overrides the following restrictions:
1075 		 *
1076 		 * The set-user-ID and set-group-ID bits of a file will be
1077 		 * cleared upon successful return from chown()
1078 		 */
1079 		if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
1080 		    !capable(CAP_FSETID))
1081 			ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
1082 
1083 		/*
1084 		 * Change the ownerships and register quota modifications
1085 		 * in the transaction.
1086 		 */
1087 		if (ip->i_d.di_projid != fa->fsx_projid) {
1088 			if (XFS_IS_PQUOTA_ON(mp)) {
1089 				olddquot = XFS_QM_DQVOPCHOWN(mp, tp, ip,
1090 							&ip->i_gdquot, gdqp);
1091 			}
1092 			ip->i_d.di_projid = fa->fsx_projid;
1093 
1094 			/*
1095 			 * We may have to rev the inode as well as
1096 			 * the superblock version number since projids didn't
1097 			 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
1098 			 */
1099 			if (ip->i_d.di_version == 1)
1100 				xfs_bump_ino_vers2(tp, ip);
1101 		}
1102 
1103 	}
1104 
1105 	if (mask & FSX_EXTSIZE)
1106 		ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
1107 	if (mask & FSX_XFLAGS) {
1108 		xfs_set_diflags(ip, fa->fsx_xflags);
1109 		xfs_diflags_to_linux(ip);
1110 	}
1111 
1112 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1113 	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
1114 
1115 	XFS_STATS_INC(xs_ig_attrchg);
1116 
1117 	/*
1118 	 * If this is a synchronous mount, make sure that the
1119 	 * transaction goes to disk before returning to the user.
1120 	 * This is slightly sub-optimal in that truncates require
1121 	 * two sync transactions instead of one for wsync filesystems.
1122 	 * One for the truncate and one for the timestamps since we
1123 	 * don't want to change the timestamps unless we're sure the
1124 	 * truncate worked.  Truncates are less than 1% of the laddis
1125 	 * mix so this probably isn't worth the trouble to optimize.
1126 	 */
1127 	if (mp->m_flags & XFS_MOUNT_WSYNC)
1128 		xfs_trans_set_sync(tp);
1129 	code = xfs_trans_commit(tp, 0);
1130 	xfs_iunlock(ip, lock_flags);
1131 
1132 	/*
1133 	 * Release any dquot(s) the inode had kept before chown.
1134 	 */
1135 	XFS_QM_DQRELE(mp, olddquot);
1136 	XFS_QM_DQRELE(mp, udqp);
1137 	XFS_QM_DQRELE(mp, gdqp);
1138 
1139 	if (code)
1140 		return code;
1141 
1142 	if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE)) {
1143 		XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
1144 				NULL, DM_RIGHT_NULL, NULL, NULL, 0, 0,
1145 				(mask & FSX_NONBLOCK) ? DM_FLAGS_NDELAY : 0);
1146 	}
1147 
1148 	return 0;
1149 
1150  error_return:
1151 	XFS_QM_DQRELE(mp, udqp);
1152 	XFS_QM_DQRELE(mp, gdqp);
1153 	xfs_trans_cancel(tp, 0);
1154 	if (lock_flags)
1155 		xfs_iunlock(ip, lock_flags);
1156 	return code;
1157 }
1158 
1159 STATIC int
xfs_ioc_fssetxattr(xfs_inode_t * ip,struct file * filp,void __user * arg)1160 xfs_ioc_fssetxattr(
1161 	xfs_inode_t		*ip,
1162 	struct file		*filp,
1163 	void			__user *arg)
1164 {
1165 	struct fsxattr		fa;
1166 	unsigned int		mask;
1167 
1168 	if (copy_from_user(&fa, arg, sizeof(fa)))
1169 		return -EFAULT;
1170 
1171 	mask = FSX_XFLAGS | FSX_EXTSIZE | FSX_PROJID;
1172 	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1173 		mask |= FSX_NONBLOCK;
1174 
1175 	return -xfs_ioctl_setattr(ip, &fa, mask);
1176 }
1177 
1178 STATIC int
xfs_ioc_getxflags(xfs_inode_t * ip,void __user * arg)1179 xfs_ioc_getxflags(
1180 	xfs_inode_t		*ip,
1181 	void			__user *arg)
1182 {
1183 	unsigned int		flags;
1184 
1185 	flags = xfs_di2lxflags(ip->i_d.di_flags);
1186 	if (copy_to_user(arg, &flags, sizeof(flags)))
1187 		return -EFAULT;
1188 	return 0;
1189 }
1190 
1191 STATIC int
xfs_ioc_setxflags(xfs_inode_t * ip,struct file * filp,void __user * arg)1192 xfs_ioc_setxflags(
1193 	xfs_inode_t		*ip,
1194 	struct file		*filp,
1195 	void			__user *arg)
1196 {
1197 	struct fsxattr		fa;
1198 	unsigned int		flags;
1199 	unsigned int		mask;
1200 
1201 	if (copy_from_user(&flags, arg, sizeof(flags)))
1202 		return -EFAULT;
1203 
1204 	if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
1205 		      FS_NOATIME_FL | FS_NODUMP_FL | \
1206 		      FS_SYNC_FL))
1207 		return -EOPNOTSUPP;
1208 
1209 	mask = FSX_XFLAGS;
1210 	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1211 		mask |= FSX_NONBLOCK;
1212 	fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
1213 
1214 	return -xfs_ioctl_setattr(ip, &fa, mask);
1215 }
1216 
1217 STATIC int
xfs_getbmap_format(void ** ap,struct getbmapx * bmv,int * full)1218 xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full)
1219 {
1220 	struct getbmap __user	*base = *ap;
1221 
1222 	/* copy only getbmap portion (not getbmapx) */
1223 	if (copy_to_user(base, bmv, sizeof(struct getbmap)))
1224 		return XFS_ERROR(EFAULT);
1225 
1226 	*ap += sizeof(struct getbmap);
1227 	return 0;
1228 }
1229 
1230 STATIC int
xfs_ioc_getbmap(struct xfs_inode * ip,int ioflags,unsigned int cmd,void __user * arg)1231 xfs_ioc_getbmap(
1232 	struct xfs_inode	*ip,
1233 	int			ioflags,
1234 	unsigned int		cmd,
1235 	void			__user *arg)
1236 {
1237 	struct getbmapx		bmx;
1238 	int			error;
1239 
1240 	if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
1241 		return -XFS_ERROR(EFAULT);
1242 
1243 	if (bmx.bmv_count < 2)
1244 		return -XFS_ERROR(EINVAL);
1245 
1246 	bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
1247 	if (ioflags & IO_INVIS)
1248 		bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ;
1249 
1250 	error = xfs_getbmap(ip, &bmx, xfs_getbmap_format,
1251 			    (struct getbmap *)arg+1);
1252 	if (error)
1253 		return -error;
1254 
1255 	/* copy back header - only size of getbmap */
1256 	if (copy_to_user(arg, &bmx, sizeof(struct getbmap)))
1257 		return -XFS_ERROR(EFAULT);
1258 	return 0;
1259 }
1260 
1261 STATIC int
xfs_getbmapx_format(void ** ap,struct getbmapx * bmv,int * full)1262 xfs_getbmapx_format(void **ap, struct getbmapx *bmv, int *full)
1263 {
1264 	struct getbmapx __user	*base = *ap;
1265 
1266 	if (copy_to_user(base, bmv, sizeof(struct getbmapx)))
1267 		return XFS_ERROR(EFAULT);
1268 
1269 	*ap += sizeof(struct getbmapx);
1270 	return 0;
1271 }
1272 
1273 STATIC int
xfs_ioc_getbmapx(struct xfs_inode * ip,void __user * arg)1274 xfs_ioc_getbmapx(
1275 	struct xfs_inode	*ip,
1276 	void			__user *arg)
1277 {
1278 	struct getbmapx		bmx;
1279 	int			error;
1280 
1281 	if (copy_from_user(&bmx, arg, sizeof(bmx)))
1282 		return -XFS_ERROR(EFAULT);
1283 
1284 	if (bmx.bmv_count < 2)
1285 		return -XFS_ERROR(EINVAL);
1286 
1287 	if (bmx.bmv_iflags & (~BMV_IF_VALID))
1288 		return -XFS_ERROR(EINVAL);
1289 
1290 	error = xfs_getbmap(ip, &bmx, xfs_getbmapx_format,
1291 			    (struct getbmapx *)arg+1);
1292 	if (error)
1293 		return -error;
1294 
1295 	/* copy back header */
1296 	if (copy_to_user(arg, &bmx, sizeof(struct getbmapx)))
1297 		return -XFS_ERROR(EFAULT);
1298 
1299 	return 0;
1300 }
1301 
1302 /*
1303  * Note: some of the ioctl's return positive numbers as a
1304  * byte count indicating success, such as readlink_by_handle.
1305  * So we don't "sign flip" like most other routines.  This means
1306  * true errors need to be returned as a negative value.
1307  */
1308 long
xfs_file_ioctl(struct file * filp,unsigned int cmd,unsigned long p)1309 xfs_file_ioctl(
1310 	struct file		*filp,
1311 	unsigned int		cmd,
1312 	unsigned long		p)
1313 {
1314 	struct inode		*inode = filp->f_path.dentry->d_inode;
1315 	struct xfs_inode	*ip = XFS_I(inode);
1316 	struct xfs_mount	*mp = ip->i_mount;
1317 	void			__user *arg = (void __user *)p;
1318 	int			ioflags = 0;
1319 	int			error;
1320 
1321 	if (filp->f_mode & FMODE_NOCMTIME)
1322 		ioflags |= IO_INVIS;
1323 
1324 	xfs_itrace_entry(ip);
1325 
1326 	switch (cmd) {
1327 	case XFS_IOC_ALLOCSP:
1328 	case XFS_IOC_FREESP:
1329 	case XFS_IOC_RESVSP:
1330 	case XFS_IOC_UNRESVSP:
1331 	case XFS_IOC_ALLOCSP64:
1332 	case XFS_IOC_FREESP64:
1333 	case XFS_IOC_RESVSP64:
1334 	case XFS_IOC_UNRESVSP64: {
1335 		xfs_flock64_t		bf;
1336 
1337 		if (copy_from_user(&bf, arg, sizeof(bf)))
1338 			return -XFS_ERROR(EFAULT);
1339 		return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
1340 	}
1341 	case XFS_IOC_DIOINFO: {
1342 		struct dioattr	da;
1343 		xfs_buftarg_t	*target =
1344 			XFS_IS_REALTIME_INODE(ip) ?
1345 			mp->m_rtdev_targp : mp->m_ddev_targp;
1346 
1347 		da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
1348 		da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
1349 
1350 		if (copy_to_user(arg, &da, sizeof(da)))
1351 			return -XFS_ERROR(EFAULT);
1352 		return 0;
1353 	}
1354 
1355 	case XFS_IOC_FSBULKSTAT_SINGLE:
1356 	case XFS_IOC_FSBULKSTAT:
1357 	case XFS_IOC_FSINUMBERS:
1358 		return xfs_ioc_bulkstat(mp, cmd, arg);
1359 
1360 	case XFS_IOC_FSGEOMETRY_V1:
1361 		return xfs_ioc_fsgeometry_v1(mp, arg);
1362 
1363 	case XFS_IOC_FSGEOMETRY:
1364 		return xfs_ioc_fsgeometry(mp, arg);
1365 
1366 	case XFS_IOC_GETVERSION:
1367 		return put_user(inode->i_generation, (int __user *)arg);
1368 
1369 	case XFS_IOC_FSGETXATTR:
1370 		return xfs_ioc_fsgetxattr(ip, 0, arg);
1371 	case XFS_IOC_FSGETXATTRA:
1372 		return xfs_ioc_fsgetxattr(ip, 1, arg);
1373 	case XFS_IOC_FSSETXATTR:
1374 		return xfs_ioc_fssetxattr(ip, filp, arg);
1375 	case XFS_IOC_GETXFLAGS:
1376 		return xfs_ioc_getxflags(ip, arg);
1377 	case XFS_IOC_SETXFLAGS:
1378 		return xfs_ioc_setxflags(ip, filp, arg);
1379 
1380 	case XFS_IOC_FSSETDM: {
1381 		struct fsdmidata	dmi;
1382 
1383 		if (copy_from_user(&dmi, arg, sizeof(dmi)))
1384 			return -XFS_ERROR(EFAULT);
1385 
1386 		error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1387 				dmi.fsd_dmstate);
1388 		return -error;
1389 	}
1390 
1391 	case XFS_IOC_GETBMAP:
1392 	case XFS_IOC_GETBMAPA:
1393 		return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
1394 
1395 	case XFS_IOC_GETBMAPX:
1396 		return xfs_ioc_getbmapx(ip, arg);
1397 
1398 	case XFS_IOC_FD_TO_HANDLE:
1399 	case XFS_IOC_PATH_TO_HANDLE:
1400 	case XFS_IOC_PATH_TO_FSHANDLE: {
1401 		xfs_fsop_handlereq_t	hreq;
1402 
1403 		if (copy_from_user(&hreq, arg, sizeof(hreq)))
1404 			return -XFS_ERROR(EFAULT);
1405 		return xfs_find_handle(cmd, &hreq);
1406 	}
1407 	case XFS_IOC_OPEN_BY_HANDLE: {
1408 		xfs_fsop_handlereq_t	hreq;
1409 
1410 		if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1411 			return -XFS_ERROR(EFAULT);
1412 		return xfs_open_by_handle(filp, &hreq);
1413 	}
1414 	case XFS_IOC_FSSETDM_BY_HANDLE:
1415 		return xfs_fssetdm_by_handle(filp, arg);
1416 
1417 	case XFS_IOC_READLINK_BY_HANDLE: {
1418 		xfs_fsop_handlereq_t	hreq;
1419 
1420 		if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
1421 			return -XFS_ERROR(EFAULT);
1422 		return xfs_readlink_by_handle(filp, &hreq);
1423 	}
1424 	case XFS_IOC_ATTRLIST_BY_HANDLE:
1425 		return xfs_attrlist_by_handle(filp, arg);
1426 
1427 	case XFS_IOC_ATTRMULTI_BY_HANDLE:
1428 		return xfs_attrmulti_by_handle(filp, arg);
1429 
1430 	case XFS_IOC_SWAPEXT: {
1431 		struct xfs_swapext	sxp;
1432 
1433 		if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1434 			return -XFS_ERROR(EFAULT);
1435 		error = xfs_swapext(&sxp);
1436 		return -error;
1437 	}
1438 
1439 	case XFS_IOC_FSCOUNTS: {
1440 		xfs_fsop_counts_t out;
1441 
1442 		error = xfs_fs_counts(mp, &out);
1443 		if (error)
1444 			return -error;
1445 
1446 		if (copy_to_user(arg, &out, sizeof(out)))
1447 			return -XFS_ERROR(EFAULT);
1448 		return 0;
1449 	}
1450 
1451 	case XFS_IOC_SET_RESBLKS: {
1452 		xfs_fsop_resblks_t inout;
1453 		__uint64_t	   in;
1454 
1455 		if (!capable(CAP_SYS_ADMIN))
1456 			return -EPERM;
1457 
1458 		if (copy_from_user(&inout, arg, sizeof(inout)))
1459 			return -XFS_ERROR(EFAULT);
1460 
1461 		/* input parameter is passed in resblks field of structure */
1462 		in = inout.resblks;
1463 		error = xfs_reserve_blocks(mp, &in, &inout);
1464 		if (error)
1465 			return -error;
1466 
1467 		if (copy_to_user(arg, &inout, sizeof(inout)))
1468 			return -XFS_ERROR(EFAULT);
1469 		return 0;
1470 	}
1471 
1472 	case XFS_IOC_GET_RESBLKS: {
1473 		xfs_fsop_resblks_t out;
1474 
1475 		if (!capable(CAP_SYS_ADMIN))
1476 			return -EPERM;
1477 
1478 		error = xfs_reserve_blocks(mp, NULL, &out);
1479 		if (error)
1480 			return -error;
1481 
1482 		if (copy_to_user(arg, &out, sizeof(out)))
1483 			return -XFS_ERROR(EFAULT);
1484 
1485 		return 0;
1486 	}
1487 
1488 	case XFS_IOC_FSGROWFSDATA: {
1489 		xfs_growfs_data_t in;
1490 
1491 		if (copy_from_user(&in, arg, sizeof(in)))
1492 			return -XFS_ERROR(EFAULT);
1493 
1494 		error = xfs_growfs_data(mp, &in);
1495 		return -error;
1496 	}
1497 
1498 	case XFS_IOC_FSGROWFSLOG: {
1499 		xfs_growfs_log_t in;
1500 
1501 		if (copy_from_user(&in, arg, sizeof(in)))
1502 			return -XFS_ERROR(EFAULT);
1503 
1504 		error = xfs_growfs_log(mp, &in);
1505 		return -error;
1506 	}
1507 
1508 	case XFS_IOC_FSGROWFSRT: {
1509 		xfs_growfs_rt_t in;
1510 
1511 		if (copy_from_user(&in, arg, sizeof(in)))
1512 			return -XFS_ERROR(EFAULT);
1513 
1514 		error = xfs_growfs_rt(mp, &in);
1515 		return -error;
1516 	}
1517 
1518 	case XFS_IOC_GOINGDOWN: {
1519 		__uint32_t in;
1520 
1521 		if (!capable(CAP_SYS_ADMIN))
1522 			return -EPERM;
1523 
1524 		if (get_user(in, (__uint32_t __user *)arg))
1525 			return -XFS_ERROR(EFAULT);
1526 
1527 		error = xfs_fs_goingdown(mp, in);
1528 		return -error;
1529 	}
1530 
1531 	case XFS_IOC_ERROR_INJECTION: {
1532 		xfs_error_injection_t in;
1533 
1534 		if (!capable(CAP_SYS_ADMIN))
1535 			return -EPERM;
1536 
1537 		if (copy_from_user(&in, arg, sizeof(in)))
1538 			return -XFS_ERROR(EFAULT);
1539 
1540 		error = xfs_errortag_add(in.errtag, mp);
1541 		return -error;
1542 	}
1543 
1544 	case XFS_IOC_ERROR_CLEARALL:
1545 		if (!capable(CAP_SYS_ADMIN))
1546 			return -EPERM;
1547 
1548 		error = xfs_errortag_clearall(mp, 1);
1549 		return -error;
1550 
1551 	default:
1552 		return -ENOTTY;
1553 	}
1554 }
1555