1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * Copyright (c) 2022-2024 Oracle.
5 * All rights reserved.
6 */
7#include "xfs.h"
8#include "xfs_fs.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_shared.h"
12#include "xfs_trans_resv.h"
13#include "xfs_mount.h"
14#include "xfs_bmap_btree.h"
15#include "xfs_inode.h"
16#include "xfs_error.h"
17#include "xfs_trace.h"
18#include "xfs_trans.h"
19#include "xfs_da_format.h"
20#include "xfs_da_btree.h"
21#include "xfs_attr.h"
22#include "xfs_ioctl.h"
23#include "xfs_parent.h"
24#include "xfs_da_btree.h"
25#include "xfs_handle.h"
26#include "xfs_health.h"
27#include "xfs_icache.h"
28#include "xfs_export.h"
29#include "xfs_xattr.h"
30#include "xfs_acl.h"
31
32#include <linux/namei.h>
33
34static inline size_t
35xfs_filehandle_fid_len(void)
36{
37	struct xfs_handle	*handle = NULL;
38
39	return sizeof(struct xfs_fid) - sizeof(handle->ha_fid.fid_len);
40}
41
42static inline size_t
43xfs_filehandle_init(
44	struct xfs_mount	*mp,
45	xfs_ino_t		ino,
46	uint32_t		gen,
47	struct xfs_handle	*handle)
48{
49	memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
50
51	handle->ha_fid.fid_len = xfs_filehandle_fid_len();
52	handle->ha_fid.fid_pad = 0;
53	handle->ha_fid.fid_gen = gen;
54	handle->ha_fid.fid_ino = ino;
55
56	return sizeof(struct xfs_handle);
57}
58
59static inline size_t
60xfs_fshandle_init(
61	struct xfs_mount	*mp,
62	struct xfs_handle	*handle)
63{
64	memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
65	memset(&handle->ha_fid, 0, sizeof(handle->ha_fid));
66
67	return sizeof(struct xfs_fsid);
68}
69
70/*
71 * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
72 * a file or fs handle.
73 *
74 * XFS_IOC_PATH_TO_FSHANDLE
75 *    returns fs handle for a mount point or path within that mount point
76 * XFS_IOC_FD_TO_HANDLE
77 *    returns full handle for a FD opened in user space
78 * XFS_IOC_PATH_TO_HANDLE
79 *    returns full handle for a path
80 */
81int
82xfs_find_handle(
83	unsigned int		cmd,
84	xfs_fsop_handlereq_t	*hreq)
85{
86	int			hsize;
87	xfs_handle_t		handle;
88	struct inode		*inode;
89	struct fd		f = {NULL};
90	struct path		path;
91	int			error;
92	struct xfs_inode	*ip;
93
94	if (cmd == XFS_IOC_FD_TO_HANDLE) {
95		f = fdget(hreq->fd);
96		if (!f.file)
97			return -EBADF;
98		inode = file_inode(f.file);
99	} else {
100		error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
101		if (error)
102			return error;
103		inode = d_inode(path.dentry);
104	}
105	ip = XFS_I(inode);
106
107	/*
108	 * We can only generate handles for inodes residing on a XFS filesystem,
109	 * and only for regular files, directories or symbolic links.
110	 */
111	error = -EINVAL;
112	if (inode->i_sb->s_magic != XFS_SB_MAGIC)
113		goto out_put;
114
115	error = -EBADF;
116	if (!S_ISREG(inode->i_mode) &&
117	    !S_ISDIR(inode->i_mode) &&
118	    !S_ISLNK(inode->i_mode))
119		goto out_put;
120
121
122	memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
123
124	if (cmd == XFS_IOC_PATH_TO_FSHANDLE)
125		hsize = xfs_fshandle_init(ip->i_mount, &handle);
126	else
127		hsize = xfs_filehandle_init(ip->i_mount, ip->i_ino,
128				inode->i_generation, &handle);
129
130	error = -EFAULT;
131	if (copy_to_user(hreq->ohandle, &handle, hsize) ||
132	    copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
133		goto out_put;
134
135	error = 0;
136
137 out_put:
138	if (cmd == XFS_IOC_FD_TO_HANDLE)
139		fdput(f);
140	else
141		path_put(&path);
142	return error;
143}
144
145/*
146 * No need to do permission checks on the various pathname components
147 * as the handle operations are privileged.
148 */
149STATIC int
150xfs_handle_acceptable(
151	void			*context,
152	struct dentry		*dentry)
153{
154	return 1;
155}
156
157/* Convert handle already copied to kernel space into a dentry. */
158static struct dentry *
159xfs_khandle_to_dentry(
160	struct file		*file,
161	struct xfs_handle	*handle)
162{
163	struct xfs_fid64        fid = {
164		.ino		= handle->ha_fid.fid_ino,
165		.gen		= handle->ha_fid.fid_gen,
166	};
167
168	/*
169	 * Only allow handle opens under a directory.
170	 */
171	if (!S_ISDIR(file_inode(file)->i_mode))
172		return ERR_PTR(-ENOTDIR);
173
174	if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
175		return ERR_PTR(-EINVAL);
176
177	return exportfs_decode_fh(file->f_path.mnt, (struct fid *)&fid, 3,
178			FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
179			xfs_handle_acceptable, NULL);
180}
181
182/* Convert handle already copied to kernel space into an xfs_inode. */
183static struct xfs_inode *
184xfs_khandle_to_inode(
185	struct file		*file,
186	struct xfs_handle	*handle)
187{
188	struct xfs_inode	*ip = XFS_I(file_inode(file));
189	struct xfs_mount	*mp = ip->i_mount;
190	struct inode		*inode;
191
192	if (!S_ISDIR(VFS_I(ip)->i_mode))
193		return ERR_PTR(-ENOTDIR);
194
195	if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
196		return ERR_PTR(-EINVAL);
197
198	inode = xfs_nfs_get_inode(mp->m_super, handle->ha_fid.fid_ino,
199			handle->ha_fid.fid_gen);
200	if (IS_ERR(inode))
201		return ERR_CAST(inode);
202
203	return XFS_I(inode);
204}
205
206/*
207 * Convert userspace handle data into a dentry.
208 */
209struct dentry *
210xfs_handle_to_dentry(
211	struct file		*parfilp,
212	void __user		*uhandle,
213	u32			hlen)
214{
215	xfs_handle_t		handle;
216
217	if (hlen != sizeof(xfs_handle_t))
218		return ERR_PTR(-EINVAL);
219	if (copy_from_user(&handle, uhandle, hlen))
220		return ERR_PTR(-EFAULT);
221
222	return xfs_khandle_to_dentry(parfilp, &handle);
223}
224
225STATIC struct dentry *
226xfs_handlereq_to_dentry(
227	struct file		*parfilp,
228	xfs_fsop_handlereq_t	*hreq)
229{
230	return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
231}
232
233int
234xfs_open_by_handle(
235	struct file		*parfilp,
236	xfs_fsop_handlereq_t	*hreq)
237{
238	const struct cred	*cred = current_cred();
239	int			error;
240	int			fd;
241	int			permflag;
242	struct file		*filp;
243	struct inode		*inode;
244	struct dentry		*dentry;
245	fmode_t			fmode;
246	struct path		path;
247
248	if (!capable(CAP_SYS_ADMIN))
249		return -EPERM;
250
251	dentry = xfs_handlereq_to_dentry(parfilp, hreq);
252	if (IS_ERR(dentry))
253		return PTR_ERR(dentry);
254	inode = d_inode(dentry);
255
256	/* Restrict xfs_open_by_handle to directories & regular files. */
257	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
258		error = -EPERM;
259		goto out_dput;
260	}
261
262#if BITS_PER_LONG != 32
263	hreq->oflags |= O_LARGEFILE;
264#endif
265
266	permflag = hreq->oflags;
267	fmode = OPEN_FMODE(permflag);
268	if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
269	    (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
270		error = -EPERM;
271		goto out_dput;
272	}
273
274	if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
275		error = -EPERM;
276		goto out_dput;
277	}
278
279	/* Can't write directories. */
280	if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
281		error = -EISDIR;
282		goto out_dput;
283	}
284
285	fd = get_unused_fd_flags(0);
286	if (fd < 0) {
287		error = fd;
288		goto out_dput;
289	}
290
291	path.mnt = parfilp->f_path.mnt;
292	path.dentry = dentry;
293	filp = dentry_open(&path, hreq->oflags, cred);
294	dput(dentry);
295	if (IS_ERR(filp)) {
296		put_unused_fd(fd);
297		return PTR_ERR(filp);
298	}
299
300	if (S_ISREG(inode->i_mode)) {
301		filp->f_flags |= O_NOATIME;
302		filp->f_mode |= FMODE_NOCMTIME;
303	}
304
305	fd_install(fd, filp);
306	return fd;
307
308 out_dput:
309	dput(dentry);
310	return error;
311}
312
313int
314xfs_readlink_by_handle(
315	struct file		*parfilp,
316	xfs_fsop_handlereq_t	*hreq)
317{
318	struct dentry		*dentry;
319	__u32			olen;
320	int			error;
321
322	if (!capable(CAP_SYS_ADMIN))
323		return -EPERM;
324
325	dentry = xfs_handlereq_to_dentry(parfilp, hreq);
326	if (IS_ERR(dentry))
327		return PTR_ERR(dentry);
328
329	/* Restrict this handle operation to symlinks only. */
330	if (!d_is_symlink(dentry)) {
331		error = -EINVAL;
332		goto out_dput;
333	}
334
335	if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
336		error = -EFAULT;
337		goto out_dput;
338	}
339
340	error = vfs_readlink(dentry, hreq->ohandle, olen);
341
342 out_dput:
343	dput(dentry);
344	return error;
345}
346
347/*
348 * Format an attribute and copy it out to the user's buffer.
349 * Take care to check values and protect against them changing later,
350 * we may be reading them directly out of a user buffer.
351 */
352static void
353xfs_ioc_attr_put_listent(
354	struct xfs_attr_list_context *context,
355	int			flags,
356	unsigned char		*name,
357	int			namelen,
358	void			*value,
359	int			valuelen)
360{
361	struct xfs_attrlist	*alist = context->buffer;
362	struct xfs_attrlist_ent	*aep;
363	int			arraytop;
364
365	ASSERT(!context->seen_enough);
366	ASSERT(context->count >= 0);
367	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
368	ASSERT(context->firstu >= sizeof(*alist));
369	ASSERT(context->firstu <= context->bufsize);
370
371	/*
372	 * Only list entries in the right namespace.
373	 */
374	if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
375		return;
376
377	arraytop = sizeof(*alist) +
378			context->count * sizeof(alist->al_offset[0]);
379
380	/* decrement by the actual bytes used by the attr */
381	context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
382			namelen + 1, sizeof(uint32_t));
383	if (context->firstu < arraytop) {
384		trace_xfs_attr_list_full(context);
385		alist->al_more = 1;
386		context->seen_enough = 1;
387		return;
388	}
389
390	aep = context->buffer + context->firstu;
391	aep->a_valuelen = valuelen;
392	memcpy(aep->a_name, name, namelen);
393	aep->a_name[namelen] = 0;
394	alist->al_offset[context->count++] = context->firstu;
395	alist->al_count = context->count;
396	trace_xfs_attr_list_add(context);
397}
398
399static unsigned int
400xfs_attr_filter(
401	u32			ioc_flags)
402{
403	if (ioc_flags & XFS_IOC_ATTR_ROOT)
404		return XFS_ATTR_ROOT;
405	if (ioc_flags & XFS_IOC_ATTR_SECURE)
406		return XFS_ATTR_SECURE;
407	return 0;
408}
409
410static inline enum xfs_attr_update
411xfs_xattr_flags(
412	u32			ioc_flags,
413	void			*value)
414{
415	if (!value)
416		return XFS_ATTRUPDATE_REMOVE;
417	if (ioc_flags & XFS_IOC_ATTR_CREATE)
418		return XFS_ATTRUPDATE_CREATE;
419	if (ioc_flags & XFS_IOC_ATTR_REPLACE)
420		return XFS_ATTRUPDATE_REPLACE;
421	return XFS_ATTRUPDATE_UPSERT;
422}
423
424int
425xfs_ioc_attr_list(
426	struct xfs_inode		*dp,
427	void __user			*ubuf,
428	size_t				bufsize,
429	int				flags,
430	struct xfs_attrlist_cursor __user *ucursor)
431{
432	struct xfs_attr_list_context	context = { };
433	struct xfs_attrlist		*alist;
434	void				*buffer;
435	int				error;
436
437	if (bufsize < sizeof(struct xfs_attrlist) ||
438	    bufsize > XFS_XATTR_LIST_MAX)
439		return -EINVAL;
440
441	/*
442	 * Reject flags, only allow namespaces.
443	 */
444	if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
445		return -EINVAL;
446	if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
447		return -EINVAL;
448
449	/*
450	 * Validate the cursor.
451	 */
452	if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
453		return -EFAULT;
454	if (context.cursor.pad1 || context.cursor.pad2)
455		return -EINVAL;
456	if (!context.cursor.initted &&
457	    (context.cursor.hashval || context.cursor.blkno ||
458	     context.cursor.offset))
459		return -EINVAL;
460
461	buffer = kvzalloc(bufsize, GFP_KERNEL);
462	if (!buffer)
463		return -ENOMEM;
464
465	/*
466	 * Initialize the output buffer.
467	 */
468	context.dp = dp;
469	context.resynch = 1;
470	context.attr_filter = xfs_attr_filter(flags);
471	context.buffer = buffer;
472	context.bufsize = round_down(bufsize, sizeof(uint32_t));
473	context.firstu = context.bufsize;
474	context.put_listent = xfs_ioc_attr_put_listent;
475
476	alist = context.buffer;
477	alist->al_count = 0;
478	alist->al_more = 0;
479	alist->al_offset[0] = context.bufsize;
480
481	error = xfs_attr_list(&context);
482	if (error)
483		goto out_free;
484
485	if (copy_to_user(ubuf, buffer, bufsize) ||
486	    copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
487		error = -EFAULT;
488out_free:
489	kvfree(buffer);
490	return error;
491}
492
493int
494xfs_attrlist_by_handle(
495	struct file		*parfilp,
496	struct xfs_fsop_attrlist_handlereq __user *p)
497{
498	struct xfs_fsop_attrlist_handlereq al_hreq;
499	struct dentry		*dentry;
500	int			error = -ENOMEM;
501
502	if (!capable(CAP_SYS_ADMIN))
503		return -EPERM;
504	if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
505		return -EFAULT;
506
507	dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
508	if (IS_ERR(dentry))
509		return PTR_ERR(dentry);
510
511	error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
512				  al_hreq.buflen, al_hreq.flags, &p->pos);
513	dput(dentry);
514	return error;
515}
516
517static int
518xfs_attrmulti_attr_get(
519	struct inode		*inode,
520	unsigned char		*name,
521	unsigned char		__user *ubuf,
522	uint32_t		*len,
523	uint32_t		flags)
524{
525	struct xfs_da_args	args = {
526		.dp		= XFS_I(inode),
527		.attr_filter	= xfs_attr_filter(flags),
528		.name		= name,
529		.namelen	= strlen(name),
530		.valuelen	= *len,
531	};
532	int			error;
533
534	if (*len > XFS_XATTR_SIZE_MAX)
535		return -EINVAL;
536
537	error = xfs_attr_get(&args);
538	if (error)
539		goto out_kfree;
540
541	*len = args.valuelen;
542	if (copy_to_user(ubuf, args.value, args.valuelen))
543		error = -EFAULT;
544
545out_kfree:
546	kvfree(args.value);
547	return error;
548}
549
550static int
551xfs_attrmulti_attr_set(
552	struct inode		*inode,
553	unsigned char		*name,
554	const unsigned char	__user *ubuf,
555	uint32_t		len,
556	uint32_t		flags)
557{
558	struct xfs_da_args	args = {
559		.dp		= XFS_I(inode),
560		.attr_filter	= xfs_attr_filter(flags),
561		.name		= name,
562		.namelen	= strlen(name),
563	};
564	int			error;
565
566	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
567		return -EPERM;
568
569	if (ubuf) {
570		if (len > XFS_XATTR_SIZE_MAX)
571			return -EINVAL;
572		args.value = memdup_user(ubuf, len);
573		if (IS_ERR(args.value))
574			return PTR_ERR(args.value);
575		args.valuelen = len;
576	}
577
578	error = xfs_attr_change(&args, xfs_xattr_flags(flags, args.value));
579	if (!error && (flags & XFS_IOC_ATTR_ROOT))
580		xfs_forget_acl(inode, name);
581	kfree(args.value);
582	return error;
583}
584
585int
586xfs_ioc_attrmulti_one(
587	struct file		*parfilp,
588	struct inode		*inode,
589	uint32_t		opcode,
590	void __user		*uname,
591	void __user		*value,
592	uint32_t		*len,
593	uint32_t		flags)
594{
595	unsigned char		*name;
596	int			error;
597
598	if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
599		return -EINVAL;
600
601	name = strndup_user(uname, MAXNAMELEN);
602	if (IS_ERR(name))
603		return PTR_ERR(name);
604
605	switch (opcode) {
606	case ATTR_OP_GET:
607		error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
608		break;
609	case ATTR_OP_REMOVE:
610		value = NULL;
611		*len = 0;
612		fallthrough;
613	case ATTR_OP_SET:
614		error = mnt_want_write_file(parfilp);
615		if (error)
616			break;
617		error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
618		mnt_drop_write_file(parfilp);
619		break;
620	default:
621		error = -EINVAL;
622		break;
623	}
624
625	kfree(name);
626	return error;
627}
628
629int
630xfs_attrmulti_by_handle(
631	struct file		*parfilp,
632	void			__user *arg)
633{
634	int			error;
635	xfs_attr_multiop_t	*ops;
636	xfs_fsop_attrmulti_handlereq_t am_hreq;
637	struct dentry		*dentry;
638	unsigned int		i, size;
639
640	if (!capable(CAP_SYS_ADMIN))
641		return -EPERM;
642	if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
643		return -EFAULT;
644
645	/* overflow check */
646	if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
647		return -E2BIG;
648
649	dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
650	if (IS_ERR(dentry))
651		return PTR_ERR(dentry);
652
653	error = -E2BIG;
654	size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
655	if (!size || size > 16 * PAGE_SIZE)
656		goto out_dput;
657
658	ops = memdup_user(am_hreq.ops, size);
659	if (IS_ERR(ops)) {
660		error = PTR_ERR(ops);
661		goto out_dput;
662	}
663
664	error = 0;
665	for (i = 0; i < am_hreq.opcount; i++) {
666		ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
667				d_inode(dentry), ops[i].am_opcode,
668				ops[i].am_attrname, ops[i].am_attrvalue,
669				&ops[i].am_length, ops[i].am_flags);
670	}
671
672	if (copy_to_user(am_hreq.ops, ops, size))
673		error = -EFAULT;
674
675	kfree(ops);
676 out_dput:
677	dput(dentry);
678	return error;
679}
680
681struct xfs_getparents_ctx {
682	struct xfs_attr_list_context	context;
683	struct xfs_getparents_by_handle	gph;
684
685	/* File to target */
686	struct xfs_inode		*ip;
687
688	/* Internal buffer where we format records */
689	void				*krecords;
690
691	/* Last record filled out */
692	struct xfs_getparents_rec	*lastrec;
693
694	unsigned int			count;
695};
696
697static inline unsigned int
698xfs_getparents_rec_sizeof(
699	unsigned int		namelen)
700{
701	return round_up(sizeof(struct xfs_getparents_rec) + namelen + 1,
702			sizeof(uint64_t));
703}
704
705static void
706xfs_getparents_put_listent(
707	struct xfs_attr_list_context	*context,
708	int				flags,
709	unsigned char			*name,
710	int				namelen,
711	void				*value,
712	int				valuelen)
713{
714	struct xfs_getparents_ctx	*gpx =
715		container_of(context, struct xfs_getparents_ctx, context);
716	struct xfs_inode		*ip = context->dp;
717	struct xfs_mount		*mp = ip->i_mount;
718	struct xfs_getparents		*gp = &gpx->gph.gph_request;
719	struct xfs_getparents_rec	*gpr = gpx->krecords + context->firstu;
720	unsigned short			reclen =
721		xfs_getparents_rec_sizeof(namelen);
722	xfs_ino_t			ino;
723	uint32_t			gen;
724	int				error;
725
726	if (!(flags & XFS_ATTR_PARENT))
727		return;
728
729	error = xfs_parent_from_attr(mp, flags, name, namelen, value, valuelen,
730			&ino, &gen);
731	if (error) {
732		xfs_inode_mark_sick(ip, XFS_SICK_INO_PARENT);
733		context->seen_enough = -EFSCORRUPTED;
734		return;
735	}
736
737	/*
738	 * We found a parent pointer, but we've filled up the buffer.  Signal
739	 * to the caller that we did /not/ reach the end of the parent pointer
740	 * recordset.
741	 */
742	if (context->firstu > context->bufsize - reclen) {
743		context->seen_enough = 1;
744		return;
745	}
746
747	/* Format the parent pointer directly into the caller buffer. */
748	gpr->gpr_reclen = reclen;
749	xfs_filehandle_init(mp, ino, gen, &gpr->gpr_parent);
750	memcpy(gpr->gpr_name, name, namelen);
751	gpr->gpr_name[namelen] = 0;
752
753	trace_xfs_getparents_put_listent(ip, gp, context, gpr);
754
755	context->firstu += reclen;
756	gpx->count++;
757	gpx->lastrec = gpr;
758}
759
760/* Expand the last record to fill the rest of the caller's buffer. */
761static inline void
762xfs_getparents_expand_lastrec(
763	struct xfs_getparents_ctx	*gpx)
764{
765	struct xfs_getparents		*gp = &gpx->gph.gph_request;
766	struct xfs_getparents_rec	*gpr = gpx->lastrec;
767
768	if (!gpx->lastrec)
769		gpr = gpx->krecords;
770
771	gpr->gpr_reclen = gp->gp_bufsize - ((void *)gpr - gpx->krecords);
772
773	trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr);
774}
775
776/* Retrieve the parent pointers for a given inode. */
777STATIC int
778xfs_getparents(
779	struct xfs_getparents_ctx	*gpx)
780{
781	struct xfs_getparents		*gp = &gpx->gph.gph_request;
782	struct xfs_inode		*ip = gpx->ip;
783	struct xfs_mount		*mp = ip->i_mount;
784	size_t				bufsize;
785	int				error;
786
787	/* Check size of buffer requested by user */
788	if (gp->gp_bufsize > XFS_XATTR_LIST_MAX)
789		return -ENOMEM;
790	if (gp->gp_bufsize < xfs_getparents_rec_sizeof(1))
791		return -EINVAL;
792
793	if (gp->gp_iflags & ~XFS_GETPARENTS_IFLAGS_ALL)
794		return -EINVAL;
795	if (gp->gp_reserved)
796		return -EINVAL;
797
798	bufsize = round_down(gp->gp_bufsize, sizeof(uint64_t));
799	gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
800	if (!gpx->krecords) {
801		bufsize = min(bufsize, PAGE_SIZE);
802		gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
803		if (!gpx->krecords)
804			return -ENOMEM;
805	}
806
807	gpx->context.dp = ip;
808	gpx->context.resynch = 1;
809	gpx->context.put_listent = xfs_getparents_put_listent;
810	gpx->context.bufsize = bufsize;
811	/* firstu is used to track the bytes filled in the buffer */
812	gpx->context.firstu = 0;
813
814	/* Copy the cursor provided by caller */
815	memcpy(&gpx->context.cursor, &gp->gp_cursor,
816			sizeof(struct xfs_attrlist_cursor));
817	gpx->count = 0;
818	gp->gp_oflags = 0;
819
820	trace_xfs_getparents_begin(ip, gp, &gpx->context.cursor);
821
822	error = xfs_attr_list(&gpx->context);
823	if (error)
824		goto out_free_buf;
825	if (gpx->context.seen_enough < 0) {
826		error = gpx->context.seen_enough;
827		goto out_free_buf;
828	}
829	xfs_getparents_expand_lastrec(gpx);
830
831	/* Update the caller with the current cursor position */
832	memcpy(&gp->gp_cursor, &gpx->context.cursor,
833			sizeof(struct xfs_attrlist_cursor));
834
835	/* Is this the root directory? */
836	if (ip->i_ino == mp->m_sb.sb_rootino)
837		gp->gp_oflags |= XFS_GETPARENTS_OFLAG_ROOT;
838
839	if (gpx->context.seen_enough == 0) {
840		/*
841		 * If we did not run out of buffer space, then we reached the
842		 * end of the pptr recordset, so set the DONE flag.
843		 */
844		gp->gp_oflags |= XFS_GETPARENTS_OFLAG_DONE;
845	} else if (gpx->count == 0) {
846		/*
847		 * If we ran out of buffer space before copying any parent
848		 * pointers at all, the caller's buffer was too short.  Tell
849		 * userspace that, erm, the message is too long.
850		 */
851		error = -EMSGSIZE;
852		goto out_free_buf;
853	}
854
855	trace_xfs_getparents_end(ip, gp, &gpx->context.cursor);
856
857	ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize);
858
859	/* Copy the records to userspace. */
860	if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer),
861				gpx->krecords, gpx->context.firstu))
862		error = -EFAULT;
863
864out_free_buf:
865	kvfree(gpx->krecords);
866	gpx->krecords = NULL;
867	return error;
868}
869
870/* Retrieve the parents of this file and pass them back to userspace. */
871int
872xfs_ioc_getparents(
873	struct file			*file,
874	struct xfs_getparents __user	*ureq)
875{
876	struct xfs_getparents_ctx	gpx = {
877		.ip			= XFS_I(file_inode(file)),
878	};
879	struct xfs_getparents		*kreq = &gpx.gph.gph_request;
880	struct xfs_mount		*mp = gpx.ip->i_mount;
881	int				error;
882
883	if (!capable(CAP_SYS_ADMIN))
884		return -EPERM;
885	if (!xfs_has_parent(mp))
886		return -EOPNOTSUPP;
887	if (copy_from_user(kreq, ureq, sizeof(*kreq)))
888		return -EFAULT;
889
890	error = xfs_getparents(&gpx);
891	if (error)
892		return error;
893
894	if (copy_to_user(ureq, kreq, sizeof(*kreq)))
895		return -EFAULT;
896
897	return 0;
898}
899
900/* Retrieve the parents of this file handle and pass them back to userspace. */
901int
902xfs_ioc_getparents_by_handle(
903	struct file			*file,
904	struct xfs_getparents_by_handle __user	*ureq)
905{
906	struct xfs_getparents_ctx	gpx = { };
907	struct xfs_inode		*ip = XFS_I(file_inode(file));
908	struct xfs_mount		*mp = ip->i_mount;
909	struct xfs_getparents_by_handle	*kreq = &gpx.gph;
910	struct xfs_handle		*handle = &kreq->gph_handle;
911	int				error;
912
913	if (!capable(CAP_SYS_ADMIN))
914		return -EPERM;
915	if (!xfs_has_parent(mp))
916		return -EOPNOTSUPP;
917	if (copy_from_user(kreq, ureq, sizeof(*kreq)))
918		return -EFAULT;
919
920	/*
921	 * We don't use exportfs_decode_fh because it does too much work here.
922	 * If the handle refers to a directory, the exportfs code will walk
923	 * upwards through the directory tree to connect the dentries to the
924	 * root directory dentry.  For GETPARENTS we don't care about that
925	 * because we're not actually going to open a file descriptor; we only
926	 * want to open an inode and read its parent pointers.
927	 *
928	 * Note that xfs_scrub uses GETPARENTS to log that it will try to fix a
929	 * corrupted file's metadata.  For this usecase we would really rather
930	 * userspace single-step the path reconstruction to avoid loops or
931	 * other strange things if the directory tree is corrupt.
932	 */
933	gpx.ip = xfs_khandle_to_inode(file, handle);
934	if (IS_ERR(gpx.ip))
935		return PTR_ERR(gpx.ip);
936
937	error = xfs_getparents(&gpx);
938	if (error)
939		goto out_rele;
940
941	if (copy_to_user(ureq, kreq, sizeof(*kreq)))
942		error = -EFAULT;
943
944out_rele:
945	xfs_irele(gpx.ip);
946	return error;
947}
948