1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1994-1995 S��ren Schmidt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include "opt_compat.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/capsicum.h>
37#include <sys/conf.h>
38#include <sys/dirent.h>
39#include <sys/fcntl.h>
40#include <sys/file.h>
41#include <sys/filedesc.h>
42#include <sys/lock.h>
43#include <sys/malloc.h>
44#include <sys/mman.h>
45#include <sys/mount.h>
46#include <sys/mutex.h>
47#include <sys/namei.h>
48#include <sys/proc.h>
49#include <sys/stat.h>
50#include <sys/sx.h>
51#include <sys/syscallsubr.h>
52#include <sys/sysproto.h>
53#include <sys/tty.h>
54#include <sys/unistd.h>
55#include <sys/vnode.h>
56
57#ifdef COMPAT_LINUX32
58#include <compat/freebsd32/freebsd32_misc.h>
59#include <machine/../linux32/linux.h>
60#include <machine/../linux32/linux32_proto.h>
61#else
62#include <machine/../linux/linux.h>
63#include <machine/../linux/linux_proto.h>
64#endif
65#include <compat/linux/linux_misc.h>
66#include <compat/linux/linux_util.h>
67#include <compat/linux/linux_file.h>
68
69static int	linux_common_open(struct thread *, int, const char *, int, int,
70		    enum uio_seg);
71static int	linux_getdents_error(struct thread *, int, int);
72
73static struct bsd_to_linux_bitmap seal_bitmap[] = {
74	BITMAP_1t1_LINUX(F_SEAL_SEAL),
75	BITMAP_1t1_LINUX(F_SEAL_SHRINK),
76	BITMAP_1t1_LINUX(F_SEAL_GROW),
77	BITMAP_1t1_LINUX(F_SEAL_WRITE),
78};
79
80#define	MFD_HUGETLB_ENTRY(_size)					\
81	{								\
82		.bsd_value = MFD_HUGE_##_size,				\
83		.linux_value = LINUX_HUGETLB_FLAG_ENCODE_##_size	\
84	}
85static struct bsd_to_linux_bitmap mfd_bitmap[] = {
86	BITMAP_1t1_LINUX(MFD_CLOEXEC),
87	BITMAP_1t1_LINUX(MFD_ALLOW_SEALING),
88	BITMAP_1t1_LINUX(MFD_HUGETLB),
89	MFD_HUGETLB_ENTRY(64KB),
90	MFD_HUGETLB_ENTRY(512KB),
91	MFD_HUGETLB_ENTRY(1MB),
92	MFD_HUGETLB_ENTRY(2MB),
93	MFD_HUGETLB_ENTRY(8MB),
94	MFD_HUGETLB_ENTRY(16MB),
95	MFD_HUGETLB_ENTRY(32MB),
96	MFD_HUGETLB_ENTRY(256MB),
97	MFD_HUGETLB_ENTRY(512MB),
98	MFD_HUGETLB_ENTRY(1GB),
99	MFD_HUGETLB_ENTRY(2GB),
100	MFD_HUGETLB_ENTRY(16GB),
101};
102#undef MFD_HUGETLB_ENTRY
103
104#ifdef LINUX_LEGACY_SYSCALLS
105int
106linux_creat(struct thread *td, struct linux_creat_args *args)
107{
108	char *path;
109	int error;
110
111	if (!LUSECONVPATH(td)) {
112		return (kern_openat(td, AT_FDCWD, args->path, UIO_USERSPACE,
113		    O_WRONLY | O_CREAT | O_TRUNC, args->mode));
114	}
115	LCONVPATHEXIST(td, args->path, &path);
116	error = kern_openat(td, AT_FDCWD, path, UIO_SYSSPACE,
117	    O_WRONLY | O_CREAT | O_TRUNC, args->mode);
118	LFREEPATH(path);
119	return (error);
120}
121#endif
122
123static int
124linux_common_openflags(int l_flags)
125{
126	int bsd_flags;
127
128	bsd_flags = 0;
129	switch (l_flags & LINUX_O_ACCMODE) {
130	case LINUX_O_WRONLY:
131		bsd_flags |= O_WRONLY;
132		break;
133	case LINUX_O_RDWR:
134		bsd_flags |= O_RDWR;
135		break;
136	default:
137		bsd_flags |= O_RDONLY;
138	}
139	if (l_flags & LINUX_O_NDELAY)
140		bsd_flags |= O_NONBLOCK;
141	if (l_flags & LINUX_O_APPEND)
142		bsd_flags |= O_APPEND;
143	if (l_flags & LINUX_O_SYNC)
144		bsd_flags |= O_FSYNC;
145	if (l_flags & LINUX_O_CLOEXEC)
146		bsd_flags |= O_CLOEXEC;
147	if (l_flags & LINUX_O_NONBLOCK)
148		bsd_flags |= O_NONBLOCK;
149	if (l_flags & LINUX_O_ASYNC)
150		bsd_flags |= O_ASYNC;
151	if (l_flags & LINUX_O_CREAT)
152		bsd_flags |= O_CREAT;
153	if (l_flags & LINUX_O_TRUNC)
154		bsd_flags |= O_TRUNC;
155	if (l_flags & LINUX_O_EXCL)
156		bsd_flags |= O_EXCL;
157	if (l_flags & LINUX_O_NOCTTY)
158		bsd_flags |= O_NOCTTY;
159	if (l_flags & LINUX_O_DIRECT)
160		bsd_flags |= O_DIRECT;
161	if (l_flags & LINUX_O_NOFOLLOW)
162		bsd_flags |= O_NOFOLLOW;
163	if (l_flags & LINUX_O_DIRECTORY)
164		bsd_flags |= O_DIRECTORY;
165	/* XXX LINUX_O_NOATIME: unable to be easily implemented. */
166	return (bsd_flags);
167}
168
169static int
170linux_common_open(struct thread *td, int dirfd, const char *path, int l_flags,
171    int mode, enum uio_seg seg)
172{
173	struct proc *p = td->td_proc;
174	struct file *fp;
175	int fd;
176	int bsd_flags, error;
177
178	bsd_flags = linux_common_openflags(l_flags);
179	error = kern_openat(td, dirfd, path, seg, bsd_flags, mode);
180	if (error != 0) {
181		if (error == EMLINK)
182			error = ELOOP;
183		goto done;
184	}
185	if (p->p_flag & P_CONTROLT)
186		goto done;
187	if (bsd_flags & O_NOCTTY)
188		goto done;
189
190	/*
191	 * XXX In between kern_openat() and fget(), another process
192	 * having the same filedesc could use that fd without
193	 * checking below.
194	*/
195	fd = td->td_retval[0];
196	if (fget(td, fd, &cap_ioctl_rights, &fp) == 0) {
197		if (fp->f_type != DTYPE_VNODE) {
198			fdrop(fp, td);
199			goto done;
200		}
201		sx_slock(&proctree_lock);
202		PROC_LOCK(p);
203		if (SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
204			PROC_UNLOCK(p);
205			sx_sunlock(&proctree_lock);
206			/* XXXPJD: Verify if TIOCSCTTY is allowed. */
207			(void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
208			    td->td_ucred, td);
209		} else {
210			PROC_UNLOCK(p);
211			sx_sunlock(&proctree_lock);
212		}
213		fdrop(fp, td);
214	}
215
216done:
217	return (error);
218}
219
220int
221linux_openat(struct thread *td, struct linux_openat_args *args)
222{
223	char *path;
224	int dfd, error;
225
226	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
227	if (!LUSECONVPATH(td)) {
228		return (linux_common_open(td, dfd, args->filename, args->flags,
229		    args->mode, UIO_USERSPACE));
230	}
231	if (args->flags & LINUX_O_CREAT)
232		LCONVPATH_AT(td, args->filename, &path, 1, dfd);
233	else
234		LCONVPATH_AT(td, args->filename, &path, 0, dfd);
235
236	error = linux_common_open(td, dfd, path, args->flags, args->mode,
237	    UIO_SYSSPACE);
238	LFREEPATH(path);
239	return (error);
240}
241
242#ifdef LINUX_LEGACY_SYSCALLS
243int
244linux_open(struct thread *td, struct linux_open_args *args)
245{
246	char *path;
247	int error;
248
249	if (!LUSECONVPATH(td)) {
250		return (linux_common_open(td, AT_FDCWD, args->path, args->flags,
251		    args->mode, UIO_USERSPACE));
252	}
253	if (args->flags & LINUX_O_CREAT)
254		LCONVPATHCREAT(td, args->path, &path);
255	else
256		LCONVPATHEXIST(td, args->path, &path);
257
258	error = linux_common_open(td, AT_FDCWD, path, args->flags, args->mode,
259	    UIO_SYSSPACE);
260	LFREEPATH(path);
261	return (error);
262}
263#endif
264
265int
266linux_name_to_handle_at(struct thread *td,
267    struct linux_name_to_handle_at_args *args)
268{
269	static const l_int valid_flags = (LINUX_AT_SYMLINK_FOLLOW |
270	    LINUX_AT_EMPTY_PATH);
271	static const l_uint fh_size = sizeof(fhandle_t);
272
273	fhandle_t fh;
274	l_uint fh_bytes;
275	l_int mount_id;
276	int error, fd, bsd_flags;
277
278	if (args->flags & ~valid_flags)
279		return (EINVAL);
280	if (args->flags & LINUX_AT_EMPTY_PATH)
281		/* XXX: not supported yet */
282		return (EOPNOTSUPP);
283
284	fd = args->dirfd;
285	if (fd == LINUX_AT_FDCWD)
286		fd = AT_FDCWD;
287
288	bsd_flags = 0;
289	if (!(args->flags & LINUX_AT_SYMLINK_FOLLOW))
290		bsd_flags |= AT_SYMLINK_NOFOLLOW;
291
292	if (!LUSECONVPATH(td)) {
293		error = kern_getfhat(td, bsd_flags, fd, args->name,
294		    UIO_USERSPACE, &fh, UIO_SYSSPACE);
295	} else {
296		char *path;
297
298		LCONVPATH_AT(td, args->name, &path, 0, fd);
299		error = kern_getfhat(td, bsd_flags, fd, path, UIO_SYSSPACE,
300		    &fh, UIO_SYSSPACE);
301		LFREEPATH(path);
302	}
303	if (error != 0)
304		return (error);
305
306	/* Emit mount_id -- required before EOVERFLOW case. */
307	mount_id = (fh.fh_fsid.val[0] ^ fh.fh_fsid.val[1]);
308	error = copyout(&mount_id, args->mnt_id, sizeof(mount_id));
309	if (error != 0)
310		return (error);
311
312	/* Check if there is room for handle. */
313	error = copyin(&args->handle->handle_bytes, &fh_bytes,
314	    sizeof(fh_bytes));
315	if (error != 0)
316		return (error);
317
318	if (fh_bytes < fh_size) {
319		error = copyout(&fh_size, &args->handle->handle_bytes,
320		    sizeof(fh_size));
321		if (error == 0)
322			error = EOVERFLOW;
323		return (error);
324	}
325
326	/* Emit handle. */
327	mount_id = 0;
328	/*
329	 * We don't use handle_type for anything yet, but initialize a known
330	 * value.
331	 */
332	error = copyout(&mount_id, &args->handle->handle_type,
333	    sizeof(mount_id));
334	if (error != 0)
335		return (error);
336
337	error = copyout(&fh, &args->handle->f_handle,
338	    sizeof(fh));
339	return (error);
340}
341
342int
343linux_open_by_handle_at(struct thread *td,
344    struct linux_open_by_handle_at_args *args)
345{
346	l_uint fh_bytes;
347	int bsd_flags, error;
348
349	error = copyin(&args->handle->handle_bytes, &fh_bytes,
350	    sizeof(fh_bytes));
351	if (error != 0)
352		return (error);
353
354	if (fh_bytes < sizeof(fhandle_t))
355		return (EINVAL);
356
357	bsd_flags = linux_common_openflags(args->flags);
358	return (kern_fhopen(td, (void *)&args->handle->f_handle, bsd_flags));
359}
360
361int
362linux_lseek(struct thread *td, struct linux_lseek_args *args)
363{
364
365	return (kern_lseek(td, args->fdes, args->off, args->whence));
366}
367
368#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
369int
370linux_llseek(struct thread *td, struct linux_llseek_args *args)
371{
372	int error;
373	off_t off;
374
375	off = (args->olow) | (((off_t) args->ohigh) << 32);
376
377	error = kern_lseek(td, args->fd, off, args->whence);
378	if (error != 0)
379		return (error);
380
381	error = copyout(td->td_retval, args->res, sizeof(off_t));
382	if (error != 0)
383		return (error);
384
385	td->td_retval[0] = 0;
386	return (0);
387}
388#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
389
390/*
391 * Note that linux_getdents(2) and linux_getdents64(2) have the same
392 * arguments. They only differ in the definition of struct dirent they
393 * operate on.
394 * Note that linux_readdir(2) is a special case of linux_getdents(2)
395 * where count is always equals 1, meaning that the buffer is one
396 * dirent-structure in size and that the code can't handle more anyway.
397 * Note that linux_readdir(2) can't be implemented by means of linux_getdents(2)
398 * as in case when the *dent buffer size is equal to 1 linux_getdents(2) will
399 * trash user stack.
400 */
401
402static int
403linux_getdents_error(struct thread *td, int fd, int err)
404{
405	struct vnode *vp;
406	struct file *fp;
407	int error;
408
409	/* Linux return ENOTDIR in case when fd is not a directory. */
410	error = getvnode(td, fd, &cap_read_rights, &fp);
411	if (error != 0)
412		return (error);
413	vp = fp->f_vnode;
414	if (vp->v_type != VDIR) {
415		fdrop(fp, td);
416		return (ENOTDIR);
417	}
418	fdrop(fp, td);
419	return (err);
420}
421
422struct l_dirent {
423	l_ulong		d_ino;
424	l_off_t		d_off;
425	l_ushort	d_reclen;
426	char		d_name[LINUX_NAME_MAX + 1];
427};
428
429struct l_dirent64 {
430	uint64_t	d_ino;
431	int64_t		d_off;
432	l_ushort	d_reclen;
433	u_char		d_type;
434	char		d_name[LINUX_NAME_MAX + 1];
435};
436
437/*
438 * Linux uses the last byte in the dirent buffer to store d_type,
439 * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes.
440 */
441#define LINUX_RECLEN(namlen)						\
442    roundup(offsetof(struct l_dirent, d_name) + (namlen) + 2, sizeof(l_ulong))
443
444#define LINUX_RECLEN64(namlen)						\
445    roundup(offsetof(struct l_dirent64, d_name) + (namlen) + 1,		\
446    sizeof(uint64_t))
447
448#ifdef LINUX_LEGACY_SYSCALLS
449int
450linux_getdents(struct thread *td, struct linux_getdents_args *args)
451{
452	struct dirent *bdp;
453	caddr_t inp, buf;		/* BSD-format */
454	int len, reclen;		/* BSD-format */
455	caddr_t outp;			/* Linux-format */
456	int resid, linuxreclen;		/* Linux-format */
457	caddr_t lbuf;			/* Linux-format */
458	off_t base;
459	struct l_dirent *linux_dirent;
460	int buflen, error;
461	size_t retval;
462
463	buflen = min(args->count, MAXBSIZE);
464	buf = malloc(buflen, M_TEMP, M_WAITOK);
465
466	error = kern_getdirentries(td, args->fd, buf, buflen,
467	    &base, NULL, UIO_SYSSPACE);
468	if (error != 0) {
469		error = linux_getdents_error(td, args->fd, error);
470		goto out1;
471	}
472
473	lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
474
475	len = td->td_retval[0];
476	inp = buf;
477	outp = (caddr_t)args->dent;
478	resid = args->count;
479	retval = 0;
480
481	while (len > 0) {
482		bdp = (struct dirent *) inp;
483		reclen = bdp->d_reclen;
484		linuxreclen = LINUX_RECLEN(bdp->d_namlen);
485		/*
486		 * No more space in the user supplied dirent buffer.
487		 * Return EINVAL.
488		 */
489		if (resid < linuxreclen) {
490			error = EINVAL;
491			goto out;
492		}
493
494		linux_dirent = (struct l_dirent*)lbuf;
495		linux_dirent->d_ino = bdp->d_fileno;
496		linux_dirent->d_off = base + reclen;
497		linux_dirent->d_reclen = linuxreclen;
498		/*
499		 * Copy d_type to last byte of l_dirent buffer
500		 */
501		lbuf[linuxreclen - 1] = bdp->d_type;
502		strlcpy(linux_dirent->d_name, bdp->d_name,
503		    linuxreclen - offsetof(struct l_dirent, d_name)-1);
504		error = copyout(linux_dirent, outp, linuxreclen);
505		if (error != 0)
506			goto out;
507
508		inp += reclen;
509		base += reclen;
510		len -= reclen;
511
512		retval += linuxreclen;
513		outp += linuxreclen;
514		resid -= linuxreclen;
515	}
516	td->td_retval[0] = retval;
517
518out:
519	free(lbuf, M_TEMP);
520out1:
521	free(buf, M_TEMP);
522	return (error);
523}
524#endif
525
526int
527linux_getdents64(struct thread *td, struct linux_getdents64_args *args)
528{
529	struct dirent *bdp;
530	caddr_t inp, buf;		/* BSD-format */
531	int len, reclen;		/* BSD-format */
532	caddr_t outp;			/* Linux-format */
533	int resid, linuxreclen;		/* Linux-format */
534	caddr_t lbuf;			/* Linux-format */
535	off_t base;
536	struct l_dirent64 *linux_dirent64;
537	int buflen, error;
538	size_t retval;
539
540	buflen = min(args->count, MAXBSIZE);
541	buf = malloc(buflen, M_TEMP, M_WAITOK);
542
543	error = kern_getdirentries(td, args->fd, buf, buflen,
544	    &base, NULL, UIO_SYSSPACE);
545	if (error != 0) {
546		error = linux_getdents_error(td, args->fd, error);
547		goto out1;
548	}
549
550	lbuf = malloc(LINUX_RECLEN64(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
551
552	len = td->td_retval[0];
553	inp = buf;
554	outp = (caddr_t)args->dirent;
555	resid = args->count;
556	retval = 0;
557
558	while (len > 0) {
559		bdp = (struct dirent *) inp;
560		reclen = bdp->d_reclen;
561		linuxreclen = LINUX_RECLEN64(bdp->d_namlen);
562		/*
563		 * No more space in the user supplied dirent buffer.
564		 * Return EINVAL.
565		 */
566		if (resid < linuxreclen) {
567			error = EINVAL;
568			goto out;
569		}
570
571		linux_dirent64 = (struct l_dirent64*)lbuf;
572		linux_dirent64->d_ino = bdp->d_fileno;
573		linux_dirent64->d_off = base + reclen;
574		linux_dirent64->d_reclen = linuxreclen;
575		linux_dirent64->d_type = bdp->d_type;
576		strlcpy(linux_dirent64->d_name, bdp->d_name,
577		    linuxreclen - offsetof(struct l_dirent64, d_name));
578		error = copyout(linux_dirent64, outp, linuxreclen);
579		if (error != 0)
580			goto out;
581
582		inp += reclen;
583		base += reclen;
584		len -= reclen;
585
586		retval += linuxreclen;
587		outp += linuxreclen;
588		resid -= linuxreclen;
589	}
590	td->td_retval[0] = retval;
591
592out:
593	free(lbuf, M_TEMP);
594out1:
595	free(buf, M_TEMP);
596	return (error);
597}
598
599#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
600int
601linux_readdir(struct thread *td, struct linux_readdir_args *args)
602{
603	struct dirent *bdp;
604	caddr_t buf;			/* BSD-format */
605	int linuxreclen;		/* Linux-format */
606	caddr_t lbuf;			/* Linux-format */
607	off_t base;
608	struct l_dirent *linux_dirent;
609	int buflen, error;
610
611	buflen = LINUX_RECLEN(LINUX_NAME_MAX);
612	buf = malloc(buflen, M_TEMP, M_WAITOK);
613
614	error = kern_getdirentries(td, args->fd, buf, buflen,
615	    &base, NULL, UIO_SYSSPACE);
616	if (error != 0) {
617		error = linux_getdents_error(td, args->fd, error);
618		goto out;
619	}
620	if (td->td_retval[0] == 0)
621		goto out;
622
623	lbuf = malloc(LINUX_RECLEN(LINUX_NAME_MAX), M_TEMP, M_WAITOK | M_ZERO);
624
625	bdp = (struct dirent *) buf;
626	linuxreclen = LINUX_RECLEN(bdp->d_namlen);
627
628	linux_dirent = (struct l_dirent*)lbuf;
629	linux_dirent->d_ino = bdp->d_fileno;
630	linux_dirent->d_off = linuxreclen;
631	linux_dirent->d_reclen = bdp->d_namlen;
632	strlcpy(linux_dirent->d_name, bdp->d_name,
633	    linuxreclen - offsetof(struct l_dirent, d_name));
634	error = copyout(linux_dirent, args->dent, linuxreclen);
635	if (error == 0)
636		td->td_retval[0] = linuxreclen;
637
638	free(lbuf, M_TEMP);
639out:
640	free(buf, M_TEMP);
641	return (error);
642}
643#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
644
645/*
646 * These exist mainly for hooks for doing /compat/linux translation.
647 */
648
649#ifdef LINUX_LEGACY_SYSCALLS
650int
651linux_access(struct thread *td, struct linux_access_args *args)
652{
653	char *path;
654	int error;
655
656	/* Linux convention. */
657	if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
658		return (EINVAL);
659
660	if (!LUSECONVPATH(td)) {
661		error = kern_accessat(td, AT_FDCWD, args->path, UIO_USERSPACE, 0,
662		    args->amode);
663	} else {
664		LCONVPATHEXIST(td, args->path, &path);
665		error = kern_accessat(td, AT_FDCWD, path, UIO_SYSSPACE, 0,
666		    args->amode);
667		LFREEPATH(path);
668	}
669
670	return (error);
671}
672#endif
673
674int
675linux_faccessat(struct thread *td, struct linux_faccessat_args *args)
676{
677	char *path;
678	int error, dfd;
679
680	/* Linux convention. */
681	if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
682		return (EINVAL);
683
684	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
685	if (!LUSECONVPATH(td)) {
686		error = kern_accessat(td, dfd, args->filename, UIO_USERSPACE, 0, args->amode);
687	} else {
688		LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
689		error = kern_accessat(td, dfd, path, UIO_SYSSPACE, 0, args->amode);
690		LFREEPATH(path);
691	}
692
693	return (error);
694}
695
696#ifdef LINUX_LEGACY_SYSCALLS
697int
698linux_unlink(struct thread *td, struct linux_unlink_args *args)
699{
700	char *path;
701	int error;
702	struct stat st;
703
704	if (!LUSECONVPATH(td)) {
705		error = kern_funlinkat(td, AT_FDCWD, args->path, FD_NONE,
706		    UIO_USERSPACE, 0, 0);
707		if (error == EPERM) {
708			/* Introduce POSIX noncompliant behaviour of Linux */
709			if (kern_statat(td, 0, AT_FDCWD, args->path,
710			    UIO_SYSSPACE, &st, NULL) == 0) {
711				if (S_ISDIR(st.st_mode))
712					error = EISDIR;
713			}
714		}
715	} else {
716		LCONVPATHEXIST(td, args->path, &path);
717		error = kern_funlinkat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0, 0);
718		if (error == EPERM) {
719			/* Introduce POSIX noncompliant behaviour of Linux */
720			if (kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st,
721			    NULL) == 0) {
722				if (S_ISDIR(st.st_mode))
723					error = EISDIR;
724			}
725		}
726		LFREEPATH(path);
727	}
728
729	return (error);
730}
731#endif
732
733static int
734linux_unlinkat_impl(struct thread *td, enum uio_seg pathseg, const char *path,
735    int dfd, struct linux_unlinkat_args *args)
736{
737	struct stat st;
738	int error;
739
740	if (args->flag & LINUX_AT_REMOVEDIR)
741		error = kern_frmdirat(td, dfd, path, FD_NONE, pathseg, 0);
742	else
743		error = kern_funlinkat(td, dfd, path, FD_NONE, pathseg, 0, 0);
744	if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) {
745		/* Introduce POSIX noncompliant behaviour of Linux */
746		if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path,
747		    UIO_SYSSPACE, &st, NULL) == 0 && S_ISDIR(st.st_mode))
748			error = EISDIR;
749	}
750	return (error);
751}
752
753int
754linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args)
755{
756	char *path;
757	int error, dfd;
758
759	if (args->flag & ~LINUX_AT_REMOVEDIR)
760		return (EINVAL);
761	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
762	if (!LUSECONVPATH(td)) {
763		return (linux_unlinkat_impl(td, UIO_USERSPACE, args->pathname,
764		    dfd, args));
765	}
766	LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
767	error = linux_unlinkat_impl(td, UIO_SYSSPACE, path, dfd, args);
768	LFREEPATH(path);
769	return (error);
770}
771int
772linux_chdir(struct thread *td, struct linux_chdir_args *args)
773{
774	char *path;
775	int error;
776
777	if (!LUSECONVPATH(td)) {
778		return (kern_chdir(td, args->path, UIO_USERSPACE));
779	}
780	LCONVPATHEXIST(td, args->path, &path);
781	error = kern_chdir(td, path, UIO_SYSSPACE);
782	LFREEPATH(path);
783	return (error);
784}
785
786#ifdef LINUX_LEGACY_SYSCALLS
787int
788linux_chmod(struct thread *td, struct linux_chmod_args *args)
789{
790	char *path;
791	int error;
792
793	if (!LUSECONVPATH(td)) {
794		return (kern_fchmodat(td, AT_FDCWD, args->path, UIO_USERSPACE,
795		    args->mode, 0));
796	}
797	LCONVPATHEXIST(td, args->path, &path);
798	error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode, 0);
799	LFREEPATH(path);
800	return (error);
801}
802#endif
803
804int
805linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args)
806{
807	char *path;
808	int error, dfd;
809
810	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
811	if (!LUSECONVPATH(td)) {
812		return (kern_fchmodat(td, dfd, args->filename, UIO_USERSPACE,
813		    args->mode, 0));
814	}
815	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
816	error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0);
817	LFREEPATH(path);
818	return (error);
819}
820
821#ifdef LINUX_LEGACY_SYSCALLS
822int
823linux_mkdir(struct thread *td, struct linux_mkdir_args *args)
824{
825	char *path;
826	int error;
827
828	if (!LUSECONVPATH(td)) {
829		return (kern_mkdirat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->mode));
830	}
831	LCONVPATHCREAT(td, args->path, &path);
832	error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, args->mode);
833	LFREEPATH(path);
834	return (error);
835}
836#endif
837
838int
839linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args)
840{
841	char *path;
842	int error, dfd;
843
844	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
845	if (!LUSECONVPATH(td)) {
846		return (kern_mkdirat(td, dfd, args->pathname, UIO_USERSPACE, args->mode));
847	}
848	LCONVPATHCREAT_AT(td, args->pathname, &path, dfd);
849	error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode);
850	LFREEPATH(path);
851	return (error);
852}
853
854#ifdef LINUX_LEGACY_SYSCALLS
855int
856linux_rmdir(struct thread *td, struct linux_rmdir_args *args)
857{
858	char *path;
859	int error;
860
861	if (!LUSECONVPATH(td)) {
862		return (kern_frmdirat(td, AT_FDCWD, args->path, FD_NONE,
863		    UIO_USERSPACE, 0));
864	}
865	LCONVPATHEXIST(td, args->path, &path);
866	error = kern_frmdirat(td, AT_FDCWD, path, FD_NONE, UIO_SYSSPACE, 0);
867	LFREEPATH(path);
868	return (error);
869}
870
871int
872linux_rename(struct thread *td, struct linux_rename_args *args)
873{
874	char *from, *to;
875	int error;
876
877	if (!LUSECONVPATH(td)) {
878		return (kern_renameat(td, AT_FDCWD, args->from, AT_FDCWD,
879		    args->to, UIO_USERSPACE));
880	}
881	LCONVPATHEXIST(td, args->from, &from);
882	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
883	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
884	if (to == NULL) {
885		LFREEPATH(from);
886		return (error);
887	}
888	error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE);
889	LFREEPATH(from);
890	LFREEPATH(to);
891	return (error);
892}
893#endif
894
895int
896linux_renameat(struct thread *td, struct linux_renameat_args *args)
897{
898	struct linux_renameat2_args renameat2_args = {
899	    .olddfd = args->olddfd,
900	    .oldname = args->oldname,
901	    .newdfd = args->newdfd,
902	    .newname = args->newname,
903	    .flags = 0
904	};
905
906	return (linux_renameat2(td, &renameat2_args));
907}
908
909int
910linux_renameat2(struct thread *td, struct linux_renameat2_args *args)
911{
912	char *from, *to;
913	int error, olddfd, newdfd;
914
915	if (args->flags != 0) {
916		if (args->flags & ~(LINUX_RENAME_EXCHANGE |
917		    LINUX_RENAME_NOREPLACE | LINUX_RENAME_WHITEOUT))
918			return (EINVAL);
919		if (args->flags & LINUX_RENAME_EXCHANGE &&
920		    args->flags & (LINUX_RENAME_NOREPLACE |
921		    LINUX_RENAME_WHITEOUT))
922			return (EINVAL);
923#if 0
924		/*
925		 * This spams the console on Ubuntu Focal.
926		 *
927		 * What's needed here is a general mechanism to let users know
928		 * about missing features without hogging the system.
929		 */
930		linux_msg(td, "renameat2 unsupported flags 0x%x",
931		    args->flags);
932#endif
933		return (EINVAL);
934	}
935
936	olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
937	newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
938	if (!LUSECONVPATH(td)) {
939		return (kern_renameat(td, olddfd, args->oldname, newdfd,
940		    args->newname, UIO_USERSPACE));
941	}
942	LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd);
943	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
944	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
945	if (to == NULL) {
946		LFREEPATH(from);
947		return (error);
948	}
949	error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE);
950	LFREEPATH(from);
951	LFREEPATH(to);
952	return (error);
953}
954
955#ifdef LINUX_LEGACY_SYSCALLS
956int
957linux_symlink(struct thread *td, struct linux_symlink_args *args)
958{
959	char *path, *to;
960	int error;
961
962	if (!LUSECONVPATH(td)) {
963		return (kern_symlinkat(td, args->path, AT_FDCWD, args->to,
964		    UIO_USERSPACE));
965	}
966	LCONVPATHEXIST(td, args->path, &path);
967	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
968	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
969	if (to == NULL) {
970		LFREEPATH(path);
971		return (error);
972	}
973	error = kern_symlinkat(td, path, AT_FDCWD, to, UIO_SYSSPACE);
974	LFREEPATH(path);
975	LFREEPATH(to);
976	return (error);
977}
978#endif
979
980int
981linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args)
982{
983	char *path, *to;
984	int error, dfd;
985
986	dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
987	if (!LUSECONVPATH(td)) {
988		return (kern_symlinkat(td, args->oldname, dfd, args->newname,
989		    UIO_USERSPACE));
990	}
991	LCONVPATHEXIST(td, args->oldname, &path);
992	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
993	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd);
994	if (to == NULL) {
995		LFREEPATH(path);
996		return (error);
997	}
998	error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE);
999	LFREEPATH(path);
1000	LFREEPATH(to);
1001	return (error);
1002}
1003
1004#ifdef LINUX_LEGACY_SYSCALLS
1005int
1006linux_readlink(struct thread *td, struct linux_readlink_args *args)
1007{
1008	char *name;
1009	int error;
1010
1011	if (!LUSECONVPATH(td)) {
1012		return (kern_readlinkat(td, AT_FDCWD, args->name, UIO_USERSPACE,
1013		    args->buf, UIO_USERSPACE, args->count));
1014	}
1015	LCONVPATHEXIST(td, args->name, &name);
1016	error = kern_readlinkat(td, AT_FDCWD, name, UIO_SYSSPACE,
1017	    args->buf, UIO_USERSPACE, args->count);
1018	LFREEPATH(name);
1019	return (error);
1020}
1021#endif
1022
1023int
1024linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args)
1025{
1026	char *name;
1027	int error, dfd;
1028
1029	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
1030	if (!LUSECONVPATH(td)) {
1031		return (kern_readlinkat(td, dfd, args->path, UIO_USERSPACE,
1032		    args->buf, UIO_USERSPACE, args->bufsiz));
1033	}
1034	LCONVPATHEXIST_AT(td, args->path, &name, dfd);
1035	error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf,
1036	    UIO_USERSPACE, args->bufsiz);
1037	LFREEPATH(name);
1038	return (error);
1039}
1040
1041int
1042linux_truncate(struct thread *td, struct linux_truncate_args *args)
1043{
1044	char *path;
1045	int error;
1046
1047	if (!LUSECONVPATH(td)) {
1048		return (kern_truncate(td, args->path, UIO_USERSPACE, args->length));
1049	}
1050	LCONVPATHEXIST(td, args->path, &path);
1051	error = kern_truncate(td, path, UIO_SYSSPACE, args->length);
1052	LFREEPATH(path);
1053	return (error);
1054}
1055
1056#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1057int
1058linux_truncate64(struct thread *td, struct linux_truncate64_args *args)
1059{
1060	char *path;
1061	off_t length;
1062	int error;
1063
1064#if defined(__amd64__) && defined(COMPAT_LINUX32)
1065	length = PAIR32TO64(off_t, args->length);
1066#else
1067	length = args->length;
1068#endif
1069
1070	if (!LUSECONVPATH(td)) {
1071		return (kern_truncate(td, args->path, UIO_USERSPACE, length));
1072	}
1073	LCONVPATHEXIST(td, args->path, &path);
1074	error = kern_truncate(td, path, UIO_SYSSPACE, length);
1075	LFREEPATH(path);
1076	return (error);
1077}
1078#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1079
1080int
1081linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args)
1082{
1083
1084	return (kern_ftruncate(td, args->fd, args->length));
1085}
1086
1087#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1088int
1089linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args)
1090{
1091	off_t length;
1092
1093#if defined(__amd64__) && defined(COMPAT_LINUX32)
1094	length = PAIR32TO64(off_t, args->length);
1095#else
1096	length = args->length;
1097#endif
1098
1099	return (kern_ftruncate(td, args->fd, length));
1100}
1101#endif
1102
1103#ifdef LINUX_LEGACY_SYSCALLS
1104int
1105linux_link(struct thread *td, struct linux_link_args *args)
1106{
1107	char *path, *to;
1108	int error;
1109
1110	if (!LUSECONVPATH(td)) {
1111		return (kern_linkat(td, AT_FDCWD, AT_FDCWD, args->path, args->to,
1112		    UIO_USERSPACE, FOLLOW));
1113	}
1114	LCONVPATHEXIST(td, args->path, &path);
1115	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
1116	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
1117	if (to == NULL) {
1118		LFREEPATH(path);
1119		return (error);
1120	}
1121	error = kern_linkat(td, AT_FDCWD, AT_FDCWD, path, to, UIO_SYSSPACE,
1122	    FOLLOW);
1123	LFREEPATH(path);
1124	LFREEPATH(to);
1125	return (error);
1126}
1127#endif
1128
1129int
1130linux_linkat(struct thread *td, struct linux_linkat_args *args)
1131{
1132	char *path, *to;
1133	int error, olddfd, newdfd, follow;
1134
1135	if (args->flag & ~LINUX_AT_SYMLINK_FOLLOW)
1136		return (EINVAL);
1137
1138	olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
1139	newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
1140	follow = (args->flag & LINUX_AT_SYMLINK_FOLLOW) == 0 ? NOFOLLOW :
1141	    FOLLOW;
1142	if (!LUSECONVPATH(td)) {
1143		return (kern_linkat(td, olddfd, newdfd, args->oldname,
1144		    args->newname, UIO_USERSPACE, follow));
1145	}
1146	LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd);
1147	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
1148	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
1149	if (to == NULL) {
1150		LFREEPATH(path);
1151		return (error);
1152	}
1153	error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, follow);
1154	LFREEPATH(path);
1155	LFREEPATH(to);
1156	return (error);
1157}
1158
1159int
1160linux_fdatasync(struct thread *td, struct linux_fdatasync_args *uap)
1161{
1162
1163	return (kern_fsync(td, uap->fd, false));
1164}
1165
1166int
1167linux_sync_file_range(struct thread *td, struct linux_sync_file_range_args *uap)
1168{
1169	off_t nbytes, offset;
1170
1171#if defined(__amd64__) && defined(COMPAT_LINUX32)
1172	nbytes = PAIR32TO64(off_t, uap->nbytes);
1173	offset = PAIR32TO64(off_t, uap->offset);
1174#else
1175	nbytes = uap->nbytes;
1176	offset = uap->offset;
1177#endif
1178
1179	if (offset < 0 || nbytes < 0 ||
1180	    (uap->flags & ~(LINUX_SYNC_FILE_RANGE_WAIT_BEFORE |
1181	    LINUX_SYNC_FILE_RANGE_WRITE |
1182	    LINUX_SYNC_FILE_RANGE_WAIT_AFTER)) != 0) {
1183		return (EINVAL);
1184	}
1185
1186	return (kern_fsync(td, uap->fd, false));
1187}
1188
1189int
1190linux_pread(struct thread *td, struct linux_pread_args *uap)
1191{
1192	struct vnode *vp;
1193	off_t offset;
1194	int error;
1195
1196#if defined(__amd64__) && defined(COMPAT_LINUX32)
1197	offset = PAIR32TO64(off_t, uap->offset);
1198#else
1199	offset = uap->offset;
1200#endif
1201
1202	error = kern_pread(td, uap->fd, uap->buf, uap->nbyte, offset);
1203	if (error == 0) {
1204		/* This seems to violate POSIX but Linux does it. */
1205		error = fgetvp(td, uap->fd, &cap_pread_rights, &vp);
1206		if (error != 0)
1207			return (error);
1208		if (vp->v_type == VDIR)
1209			error = EISDIR;
1210		vrele(vp);
1211	}
1212	return (error);
1213}
1214
1215int
1216linux_pwrite(struct thread *td, struct linux_pwrite_args *uap)
1217{
1218	off_t offset;
1219
1220#if defined(__amd64__) && defined(COMPAT_LINUX32)
1221	offset = PAIR32TO64(off_t, uap->offset);
1222#else
1223	offset = uap->offset;
1224#endif
1225
1226	return (kern_pwrite(td, uap->fd, uap->buf, uap->nbyte, offset));
1227}
1228
1229int
1230linux_preadv(struct thread *td, struct linux_preadv_args *uap)
1231{
1232	struct uio *auio;
1233	int error;
1234	off_t offset;
1235
1236	/*
1237	 * According http://man7.org/linux/man-pages/man2/preadv.2.html#NOTES
1238	 * pos_l and pos_h, respectively, contain the
1239	 * low order and high order 32 bits of offset.
1240	 */
1241	offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) <<
1242	    (sizeof(offset) * 4)) | uap->pos_l;
1243	if (offset < 0)
1244		return (EINVAL);
1245#ifdef COMPAT_LINUX32
1246	error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio);
1247#else
1248	error = copyinuio(uap->vec, uap->vlen, &auio);
1249#endif
1250	if (error != 0)
1251		return (error);
1252	error = kern_preadv(td, uap->fd, auio, offset);
1253	free(auio, M_IOV);
1254	return (error);
1255}
1256
1257int
1258linux_pwritev(struct thread *td, struct linux_pwritev_args *uap)
1259{
1260	struct uio *auio;
1261	int error;
1262	off_t offset;
1263
1264	/*
1265	 * According http://man7.org/linux/man-pages/man2/pwritev.2.html#NOTES
1266	 * pos_l and pos_h, respectively, contain the
1267	 * low order and high order 32 bits of offset.
1268	 */
1269	offset = (((off_t)uap->pos_h << (sizeof(offset) * 4)) <<
1270	    (sizeof(offset) * 4)) | uap->pos_l;
1271	if (offset < 0)
1272		return (EINVAL);
1273#ifdef COMPAT_LINUX32
1274	error = linux32_copyinuio(PTRIN(uap->vec), uap->vlen, &auio);
1275#else
1276	error = copyinuio(uap->vec, uap->vlen, &auio);
1277#endif
1278	if (error != 0)
1279		return (error);
1280	error = kern_pwritev(td, uap->fd, auio, offset);
1281	free(auio, M_IOV);
1282	return (error);
1283}
1284
1285int
1286linux_mount(struct thread *td, struct linux_mount_args *args)
1287{
1288	struct mntarg *ma = NULL;
1289	char *fstypename, *mntonname, *mntfromname, *data;
1290	int error, fsflags;
1291
1292	fstypename = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1293	mntonname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1294	mntfromname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1295	data = NULL;
1296	error = copyinstr(args->filesystemtype, fstypename, MNAMELEN - 1,
1297	    NULL);
1298	if (error != 0)
1299		goto out;
1300	if (args->specialfile != NULL) {
1301		error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL);
1302		if (error != 0)
1303			goto out;
1304	} else {
1305		mntfromname[0] = '\0';
1306	}
1307	error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL);
1308	if (error != 0)
1309		goto out;
1310
1311	if (strcmp(fstypename, "ext2") == 0) {
1312		strcpy(fstypename, "ext2fs");
1313	} else if (strcmp(fstypename, "proc") == 0) {
1314		strcpy(fstypename, "linprocfs");
1315	} else if (strcmp(fstypename, "vfat") == 0) {
1316		strcpy(fstypename, "msdosfs");
1317	} else if (strcmp(fstypename, "fuse") == 0) {
1318		char *fuse_options, *fuse_option, *fuse_name;
1319
1320		if (strcmp(mntfromname, "fuse") == 0)
1321			strcpy(mntfromname, "/dev/fuse");
1322
1323		strcpy(fstypename, "fusefs");
1324		data = malloc(MNAMELEN, M_TEMP, M_WAITOK);
1325		error = copyinstr(args->data, data, MNAMELEN - 1, NULL);
1326		if (error != 0)
1327			goto out;
1328
1329		fuse_options = data;
1330		while ((fuse_option = strsep(&fuse_options, ",")) != NULL) {
1331			fuse_name = strsep(&fuse_option, "=");
1332			if (fuse_name == NULL || fuse_option == NULL)
1333				goto out;
1334			ma = mount_arg(ma, fuse_name, fuse_option, -1);
1335		}
1336
1337		/*
1338		 * The FUSE server uses Linux errno values instead of FreeBSD
1339		 * ones; add a flag to tell fuse(4) to do errno translation.
1340		 */
1341		ma = mount_arg(ma, "linux_errnos", "1", -1);
1342	}
1343
1344	fsflags = 0;
1345
1346	/*
1347	 * Linux SYNC flag is not included; the closest equivalent
1348	 * FreeBSD has is !ASYNC, which is our default.
1349	 */
1350	if (args->rwflag & LINUX_MS_RDONLY)
1351		fsflags |= MNT_RDONLY;
1352	if (args->rwflag & LINUX_MS_NOSUID)
1353		fsflags |= MNT_NOSUID;
1354	if (args->rwflag & LINUX_MS_NOEXEC)
1355		fsflags |= MNT_NOEXEC;
1356	if (args->rwflag & LINUX_MS_REMOUNT)
1357		fsflags |= MNT_UPDATE;
1358
1359	ma = mount_arg(ma, "fstype", fstypename, -1);
1360	ma = mount_arg(ma, "fspath", mntonname, -1);
1361	ma = mount_arg(ma, "from", mntfromname, -1);
1362	error = kernel_mount(ma, fsflags);
1363out:
1364	free(fstypename, M_TEMP);
1365	free(mntonname, M_TEMP);
1366	free(mntfromname, M_TEMP);
1367	free(data, M_TEMP);
1368	return (error);
1369}
1370
1371#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1372int
1373linux_oldumount(struct thread *td, struct linux_oldumount_args *args)
1374{
1375
1376	return (kern_unmount(td, args->path, 0));
1377}
1378#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1379
1380#ifdef LINUX_LEGACY_SYSCALLS
1381int
1382linux_umount(struct thread *td, struct linux_umount_args *args)
1383{
1384	int flags;
1385
1386	flags = 0;
1387	if ((args->flags & LINUX_MNT_FORCE) != 0) {
1388		args->flags &= ~LINUX_MNT_FORCE;
1389		flags |= MNT_FORCE;
1390	}
1391	if (args->flags != 0) {
1392		linux_msg(td, "unsupported umount2 flags %#x", args->flags);
1393		return (EINVAL);
1394	}
1395
1396	return (kern_unmount(td, args->path, flags));
1397}
1398#endif
1399
1400/*
1401 * fcntl family of syscalls
1402 */
1403
1404struct l_flock {
1405	l_short		l_type;
1406	l_short		l_whence;
1407	l_off_t		l_start;
1408	l_off_t		l_len;
1409	l_pid_t		l_pid;
1410}
1411#if defined(__amd64__) && defined(COMPAT_LINUX32)
1412__packed
1413#endif
1414;
1415
1416static void
1417linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
1418{
1419	switch (linux_flock->l_type) {
1420	case LINUX_F_RDLCK:
1421		bsd_flock->l_type = F_RDLCK;
1422		break;
1423	case LINUX_F_WRLCK:
1424		bsd_flock->l_type = F_WRLCK;
1425		break;
1426	case LINUX_F_UNLCK:
1427		bsd_flock->l_type = F_UNLCK;
1428		break;
1429	default:
1430		bsd_flock->l_type = -1;
1431		break;
1432	}
1433	bsd_flock->l_whence = linux_flock->l_whence;
1434	bsd_flock->l_start = (off_t)linux_flock->l_start;
1435	bsd_flock->l_len = (off_t)linux_flock->l_len;
1436	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1437	bsd_flock->l_sysid = 0;
1438}
1439
1440static void
1441bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
1442{
1443	switch (bsd_flock->l_type) {
1444	case F_RDLCK:
1445		linux_flock->l_type = LINUX_F_RDLCK;
1446		break;
1447	case F_WRLCK:
1448		linux_flock->l_type = LINUX_F_WRLCK;
1449		break;
1450	case F_UNLCK:
1451		linux_flock->l_type = LINUX_F_UNLCK;
1452		break;
1453	}
1454	linux_flock->l_whence = bsd_flock->l_whence;
1455	linux_flock->l_start = (l_off_t)bsd_flock->l_start;
1456	linux_flock->l_len = (l_off_t)bsd_flock->l_len;
1457	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1458}
1459
1460#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1461struct l_flock64 {
1462	l_short		l_type;
1463	l_short		l_whence;
1464	l_loff_t	l_start;
1465	l_loff_t	l_len;
1466	l_pid_t		l_pid;
1467}
1468#if defined(__amd64__) && defined(COMPAT_LINUX32)
1469__packed
1470#endif
1471;
1472
1473static void
1474linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
1475{
1476	switch (linux_flock->l_type) {
1477	case LINUX_F_RDLCK:
1478		bsd_flock->l_type = F_RDLCK;
1479		break;
1480	case LINUX_F_WRLCK:
1481		bsd_flock->l_type = F_WRLCK;
1482		break;
1483	case LINUX_F_UNLCK:
1484		bsd_flock->l_type = F_UNLCK;
1485		break;
1486	default:
1487		bsd_flock->l_type = -1;
1488		break;
1489	}
1490	bsd_flock->l_whence = linux_flock->l_whence;
1491	bsd_flock->l_start = (off_t)linux_flock->l_start;
1492	bsd_flock->l_len = (off_t)linux_flock->l_len;
1493	bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
1494	bsd_flock->l_sysid = 0;
1495}
1496
1497static void
1498bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
1499{
1500	switch (bsd_flock->l_type) {
1501	case F_RDLCK:
1502		linux_flock->l_type = LINUX_F_RDLCK;
1503		break;
1504	case F_WRLCK:
1505		linux_flock->l_type = LINUX_F_WRLCK;
1506		break;
1507	case F_UNLCK:
1508		linux_flock->l_type = LINUX_F_UNLCK;
1509		break;
1510	}
1511	linux_flock->l_whence = bsd_flock->l_whence;
1512	linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
1513	linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
1514	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
1515}
1516#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1517
1518static int
1519fcntl_common(struct thread *td, struct linux_fcntl_args *args)
1520{
1521	struct l_flock linux_flock;
1522	struct flock bsd_flock;
1523	struct file *fp;
1524	long arg;
1525	int error, result;
1526
1527	switch (args->cmd) {
1528	case LINUX_F_DUPFD:
1529		return (kern_fcntl(td, args->fd, F_DUPFD, args->arg));
1530
1531	case LINUX_F_GETFD:
1532		return (kern_fcntl(td, args->fd, F_GETFD, 0));
1533
1534	case LINUX_F_SETFD:
1535		return (kern_fcntl(td, args->fd, F_SETFD, args->arg));
1536
1537	case LINUX_F_GETFL:
1538		error = kern_fcntl(td, args->fd, F_GETFL, 0);
1539		result = td->td_retval[0];
1540		td->td_retval[0] = 0;
1541		if (result & O_RDONLY)
1542			td->td_retval[0] |= LINUX_O_RDONLY;
1543		if (result & O_WRONLY)
1544			td->td_retval[0] |= LINUX_O_WRONLY;
1545		if (result & O_RDWR)
1546			td->td_retval[0] |= LINUX_O_RDWR;
1547		if (result & O_NDELAY)
1548			td->td_retval[0] |= LINUX_O_NONBLOCK;
1549		if (result & O_APPEND)
1550			td->td_retval[0] |= LINUX_O_APPEND;
1551		if (result & O_FSYNC)
1552			td->td_retval[0] |= LINUX_O_SYNC;
1553		if (result & O_ASYNC)
1554			td->td_retval[0] |= LINUX_O_ASYNC;
1555#ifdef LINUX_O_NOFOLLOW
1556		if (result & O_NOFOLLOW)
1557			td->td_retval[0] |= LINUX_O_NOFOLLOW;
1558#endif
1559#ifdef LINUX_O_DIRECT
1560		if (result & O_DIRECT)
1561			td->td_retval[0] |= LINUX_O_DIRECT;
1562#endif
1563		return (error);
1564
1565	case LINUX_F_SETFL:
1566		arg = 0;
1567		if (args->arg & LINUX_O_NDELAY)
1568			arg |= O_NONBLOCK;
1569		if (args->arg & LINUX_O_APPEND)
1570			arg |= O_APPEND;
1571		if (args->arg & LINUX_O_SYNC)
1572			arg |= O_FSYNC;
1573		if (args->arg & LINUX_O_ASYNC)
1574			arg |= O_ASYNC;
1575#ifdef LINUX_O_NOFOLLOW
1576		if (args->arg & LINUX_O_NOFOLLOW)
1577			arg |= O_NOFOLLOW;
1578#endif
1579#ifdef LINUX_O_DIRECT
1580		if (args->arg & LINUX_O_DIRECT)
1581			arg |= O_DIRECT;
1582#endif
1583		return (kern_fcntl(td, args->fd, F_SETFL, arg));
1584
1585	case LINUX_F_GETLK:
1586		error = copyin((void *)args->arg, &linux_flock,
1587		    sizeof(linux_flock));
1588		if (error)
1589			return (error);
1590		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1591		error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
1592		if (error)
1593			return (error);
1594		bsd_to_linux_flock(&bsd_flock, &linux_flock);
1595		return (copyout(&linux_flock, (void *)args->arg,
1596		    sizeof(linux_flock)));
1597
1598	case LINUX_F_SETLK:
1599		error = copyin((void *)args->arg, &linux_flock,
1600		    sizeof(linux_flock));
1601		if (error)
1602			return (error);
1603		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1604		return (kern_fcntl(td, args->fd, F_SETLK,
1605		    (intptr_t)&bsd_flock));
1606
1607	case LINUX_F_SETLKW:
1608		error = copyin((void *)args->arg, &linux_flock,
1609		    sizeof(linux_flock));
1610		if (error)
1611			return (error);
1612		linux_to_bsd_flock(&linux_flock, &bsd_flock);
1613		return (kern_fcntl(td, args->fd, F_SETLKW,
1614		     (intptr_t)&bsd_flock));
1615
1616	case LINUX_F_GETOWN:
1617		return (kern_fcntl(td, args->fd, F_GETOWN, 0));
1618
1619	case LINUX_F_SETOWN:
1620		/*
1621		 * XXX some Linux applications depend on F_SETOWN having no
1622		 * significant effect for pipes (SIGIO is not delivered for
1623		 * pipes under Linux-2.2.35 at least).
1624		 */
1625		error = fget(td, args->fd,
1626		    &cap_fcntl_rights, &fp);
1627		if (error)
1628			return (error);
1629		if (fp->f_type == DTYPE_PIPE) {
1630			fdrop(fp, td);
1631			return (EINVAL);
1632		}
1633		fdrop(fp, td);
1634
1635		return (kern_fcntl(td, args->fd, F_SETOWN, args->arg));
1636
1637	case LINUX_F_DUPFD_CLOEXEC:
1638		return (kern_fcntl(td, args->fd, F_DUPFD_CLOEXEC, args->arg));
1639	/*
1640	 * Our F_SEAL_* values match Linux one for maximum compatibility.  So we
1641	 * only needed to account for different values for fcntl(2) commands.
1642	 */
1643	case LINUX_F_GET_SEALS:
1644		error = kern_fcntl(td, args->fd, F_GET_SEALS, 0);
1645		if (error != 0)
1646			return (error);
1647		td->td_retval[0] = bsd_to_linux_bits(td->td_retval[0],
1648		    seal_bitmap, 0);
1649		return (0);
1650
1651	case LINUX_F_ADD_SEALS:
1652		return (kern_fcntl(td, args->fd, F_ADD_SEALS,
1653		    linux_to_bsd_bits(args->arg, seal_bitmap, 0)));
1654	default:
1655		linux_msg(td, "unsupported fcntl cmd %d", args->cmd);
1656		return (EINVAL);
1657	}
1658}
1659
1660int
1661linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
1662{
1663
1664	return (fcntl_common(td, args));
1665}
1666
1667#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1668int
1669linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
1670{
1671	struct l_flock64 linux_flock;
1672	struct flock bsd_flock;
1673	struct linux_fcntl_args fcntl_args;
1674	int error;
1675
1676	switch (args->cmd) {
1677	case LINUX_F_GETLK64:
1678		error = copyin((void *)args->arg, &linux_flock,
1679		    sizeof(linux_flock));
1680		if (error)
1681			return (error);
1682		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1683		error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
1684		if (error)
1685			return (error);
1686		bsd_to_linux_flock64(&bsd_flock, &linux_flock);
1687		return (copyout(&linux_flock, (void *)args->arg,
1688			    sizeof(linux_flock)));
1689
1690	case LINUX_F_SETLK64:
1691		error = copyin((void *)args->arg, &linux_flock,
1692		    sizeof(linux_flock));
1693		if (error)
1694			return (error);
1695		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1696		return (kern_fcntl(td, args->fd, F_SETLK,
1697		    (intptr_t)&bsd_flock));
1698
1699	case LINUX_F_SETLKW64:
1700		error = copyin((void *)args->arg, &linux_flock,
1701		    sizeof(linux_flock));
1702		if (error)
1703			return (error);
1704		linux_to_bsd_flock64(&linux_flock, &bsd_flock);
1705		return (kern_fcntl(td, args->fd, F_SETLKW,
1706		    (intptr_t)&bsd_flock));
1707	}
1708
1709	fcntl_args.fd = args->fd;
1710	fcntl_args.cmd = args->cmd;
1711	fcntl_args.arg = args->arg;
1712	return (fcntl_common(td, &fcntl_args));
1713}
1714#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1715
1716#ifdef LINUX_LEGACY_SYSCALLS
1717int
1718linux_chown(struct thread *td, struct linux_chown_args *args)
1719{
1720	char *path;
1721	int error;
1722
1723	if (!LUSECONVPATH(td)) {
1724		return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE,
1725		    args->uid, args->gid, 0));
1726	}
1727	LCONVPATHEXIST(td, args->path, &path);
1728	error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid,
1729	    args->gid, 0);
1730	LFREEPATH(path);
1731	return (error);
1732}
1733#endif
1734
1735int
1736linux_fchownat(struct thread *td, struct linux_fchownat_args *args)
1737{
1738	char *path;
1739	int error, dfd, flag;
1740
1741	if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
1742		return (EINVAL);
1743
1744	dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD :  args->dfd;
1745	flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
1746	    AT_SYMLINK_NOFOLLOW;
1747	if (!LUSECONVPATH(td)) {
1748		return (kern_fchownat(td, dfd, args->filename, UIO_USERSPACE,
1749		    args->uid, args->gid, flag));
1750	}
1751	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
1752	error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid,
1753	    flag);
1754	LFREEPATH(path);
1755	return (error);
1756}
1757
1758#ifdef LINUX_LEGACY_SYSCALLS
1759int
1760linux_lchown(struct thread *td, struct linux_lchown_args *args)
1761{
1762	char *path;
1763	int error;
1764
1765	if (!LUSECONVPATH(td)) {
1766		return (kern_fchownat(td, AT_FDCWD, args->path, UIO_USERSPACE, args->uid,
1767		    args->gid, AT_SYMLINK_NOFOLLOW));
1768	}
1769	LCONVPATHEXIST(td, args->path, &path);
1770	error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, args->uid, args->gid,
1771	    AT_SYMLINK_NOFOLLOW);
1772	LFREEPATH(path);
1773	return (error);
1774}
1775#endif
1776
1777static int
1778convert_fadvice(int advice)
1779{
1780	switch (advice) {
1781	case LINUX_POSIX_FADV_NORMAL:
1782		return (POSIX_FADV_NORMAL);
1783	case LINUX_POSIX_FADV_RANDOM:
1784		return (POSIX_FADV_RANDOM);
1785	case LINUX_POSIX_FADV_SEQUENTIAL:
1786		return (POSIX_FADV_SEQUENTIAL);
1787	case LINUX_POSIX_FADV_WILLNEED:
1788		return (POSIX_FADV_WILLNEED);
1789	case LINUX_POSIX_FADV_DONTNEED:
1790		return (POSIX_FADV_DONTNEED);
1791	case LINUX_POSIX_FADV_NOREUSE:
1792		return (POSIX_FADV_NOREUSE);
1793	default:
1794		return (-1);
1795	}
1796}
1797
1798int
1799linux_fadvise64(struct thread *td, struct linux_fadvise64_args *args)
1800{
1801	off_t offset;
1802	int advice;
1803
1804#if defined(__amd64__) && defined(COMPAT_LINUX32)
1805	offset = PAIR32TO64(off_t, args->offset);
1806#else
1807	offset = args->offset;
1808#endif
1809
1810	advice = convert_fadvice(args->advice);
1811	if (advice == -1)
1812		return (EINVAL);
1813	return (kern_posix_fadvise(td, args->fd, offset, args->len, advice));
1814}
1815
1816#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1817int
1818linux_fadvise64_64(struct thread *td, struct linux_fadvise64_64_args *args)
1819{
1820	off_t len, offset;
1821	int advice;
1822
1823#if defined(__amd64__) && defined(COMPAT_LINUX32)
1824	len = PAIR32TO64(off_t, args->len);
1825	offset = PAIR32TO64(off_t, args->offset);
1826#else
1827	len = args->len;
1828	offset = args->offset;
1829#endif
1830
1831	advice = convert_fadvice(args->advice);
1832	if (advice == -1)
1833		return (EINVAL);
1834	return (kern_posix_fadvise(td, args->fd, offset, len, advice));
1835}
1836#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
1837
1838#ifdef LINUX_LEGACY_SYSCALLS
1839int
1840linux_pipe(struct thread *td, struct linux_pipe_args *args)
1841{
1842	int fildes[2];
1843	int error;
1844
1845	error = kern_pipe(td, fildes, 0, NULL, NULL);
1846	if (error != 0)
1847		return (error);
1848
1849	error = copyout(fildes, args->pipefds, sizeof(fildes));
1850	if (error != 0) {
1851		(void)kern_close(td, fildes[0]);
1852		(void)kern_close(td, fildes[1]);
1853	}
1854
1855	return (error);
1856}
1857#endif
1858
1859int
1860linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
1861{
1862	int fildes[2];
1863	int error, flags;
1864
1865	if ((args->flags & ~(LINUX_O_NONBLOCK | LINUX_O_CLOEXEC)) != 0)
1866		return (EINVAL);
1867
1868	flags = 0;
1869	if ((args->flags & LINUX_O_NONBLOCK) != 0)
1870		flags |= O_NONBLOCK;
1871	if ((args->flags & LINUX_O_CLOEXEC) != 0)
1872		flags |= O_CLOEXEC;
1873	error = kern_pipe(td, fildes, flags, NULL, NULL);
1874	if (error != 0)
1875		return (error);
1876
1877	error = copyout(fildes, args->pipefds, sizeof(fildes));
1878	if (error != 0) {
1879		(void)kern_close(td, fildes[0]);
1880		(void)kern_close(td, fildes[1]);
1881	}
1882
1883	return (error);
1884}
1885
1886int
1887linux_dup3(struct thread *td, struct linux_dup3_args *args)
1888{
1889	int cmd;
1890	intptr_t newfd;
1891
1892	if (args->oldfd == args->newfd)
1893		return (EINVAL);
1894	if ((args->flags & ~LINUX_O_CLOEXEC) != 0)
1895		return (EINVAL);
1896	if (args->flags & LINUX_O_CLOEXEC)
1897		cmd = F_DUP2FD_CLOEXEC;
1898	else
1899		cmd = F_DUP2FD;
1900
1901	newfd = args->newfd;
1902	return (kern_fcntl(td, args->oldfd, cmd, newfd));
1903}
1904
1905int
1906linux_fallocate(struct thread *td, struct linux_fallocate_args *args)
1907{
1908	off_t len, offset;
1909
1910	/*
1911	 * We emulate only posix_fallocate system call for which
1912	 * mode should be 0.
1913	 */
1914	if (args->mode != 0)
1915		return (EOPNOTSUPP);
1916
1917#if defined(__amd64__) && defined(COMPAT_LINUX32)
1918	len = PAIR32TO64(off_t, args->len);
1919	offset = PAIR32TO64(off_t, args->offset);
1920#else
1921	len = args->len;
1922	offset = args->offset;
1923#endif
1924
1925	return (kern_posix_fallocate(td, args->fd, offset, len));
1926}
1927
1928int
1929linux_copy_file_range(struct thread *td, struct linux_copy_file_range_args
1930    *args)
1931{
1932	l_loff_t inoff, outoff, *inoffp, *outoffp;
1933	int error, flags;
1934
1935	/*
1936	 * copy_file_range(2) on Linux doesn't define any flags (yet), so is
1937	 * the native implementation.  Enforce it.
1938	 */
1939	if (args->flags != 0) {
1940		linux_msg(td, "copy_file_range unsupported flags 0x%x",
1941		    args->flags);
1942		return (EINVAL);
1943	}
1944	flags = 0;
1945	inoffp = outoffp = NULL;
1946	if (args->off_in != NULL) {
1947		error = copyin(args->off_in, &inoff, sizeof(l_loff_t));
1948		if (error != 0)
1949			return (error);
1950		inoffp = &inoff;
1951	}
1952	if (args->off_out != NULL) {
1953		error = copyin(args->off_out, &outoff, sizeof(l_loff_t));
1954		if (error != 0)
1955			return (error);
1956		outoffp = &outoff;
1957	}
1958
1959	error = kern_copy_file_range(td, args->fd_in, inoffp, args->fd_out,
1960	    outoffp, args->len, flags);
1961	if (error == 0 && args->off_in != NULL)
1962		error = copyout(inoffp, args->off_in, sizeof(l_loff_t));
1963	if (error == 0 && args->off_out != NULL)
1964		error = copyout(outoffp, args->off_out, sizeof(l_loff_t));
1965	return (error);
1966}
1967
1968#define	LINUX_MEMFD_PREFIX	"memfd:"
1969
1970int
1971linux_memfd_create(struct thread *td, struct linux_memfd_create_args *args)
1972{
1973	char memfd_name[LINUX_NAME_MAX + 1];
1974	int error, flags, shmflags, oflags;
1975
1976	/*
1977	 * This is our clever trick to avoid the heap allocation to copy in the
1978	 * uname.  We don't really need to go this far out of our way, but it
1979	 * does keep the rest of this function fairly clean as they don't have
1980	 * to worry about cleanup on the way out.
1981	 */
1982	error = copyinstr(args->uname_ptr,
1983	    memfd_name + sizeof(LINUX_MEMFD_PREFIX) - 1,
1984	    LINUX_NAME_MAX - sizeof(LINUX_MEMFD_PREFIX) - 1, NULL);
1985	if (error != 0) {
1986		if (error == ENAMETOOLONG)
1987			error = EINVAL;
1988		return (error);
1989	}
1990
1991	memcpy(memfd_name, LINUX_MEMFD_PREFIX, sizeof(LINUX_MEMFD_PREFIX) - 1);
1992	flags = linux_to_bsd_bits(args->flags, mfd_bitmap, 0);
1993	if ((flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB |
1994	    MFD_HUGE_MASK)) != 0)
1995		return (EINVAL);
1996	/* Size specified but no HUGETLB. */
1997	if ((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0)
1998		return (EINVAL);
1999	/* We don't actually support HUGETLB. */
2000	if ((flags & MFD_HUGETLB) != 0)
2001		return (ENOSYS);
2002	oflags = O_RDWR;
2003	shmflags = SHM_GROW_ON_WRITE;
2004	if ((flags & MFD_CLOEXEC) != 0)
2005		oflags |= O_CLOEXEC;
2006	if ((flags & MFD_ALLOW_SEALING) != 0)
2007		shmflags |= SHM_ALLOW_SEALING;
2008	return (kern_shm_open2(td, SHM_ANON, oflags, 0, shmflags, NULL,
2009	    memfd_name));
2010}
2011
2012int
2013linux_splice(struct thread *td, struct linux_splice_args *args)
2014{
2015
2016	linux_msg(td, "syscall splice not really implemented");
2017
2018	/*
2019	 * splice(2) is documented to return EINVAL in various circumstances;
2020	 * returning it instead of ENOSYS should hint the caller to use fallback
2021	 * instead.
2022	 */
2023	return (EINVAL);
2024}
2025