2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1994-1995 Søren Schmidt
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_compat.h"
34 #include <sys/param.h>
35 #include <sys/capsicum.h>
36 #include <sys/dirent.h>
38 #include <sys/filedesc.h>
40 #include <sys/malloc.h>
41 #include <sys/mount.h>
42 #include <sys/namei.h>
44 #include <sys/syscallsubr.h>
45 #include <sys/systm.h>
47 #include <sys/vnode.h>
49 #include <sys/fcntl.h>
52 #include <machine/../linux32/linux.h>
53 #include <machine/../linux32/linux32_proto.h>
55 #include <machine/../linux/linux.h>
56 #include <machine/../linux/linux_proto.h>
59 #include <compat/linux/linux_util.h>
60 #include <compat/linux/linux_file.h>
64 translate_vnhook_major_minor(struct vnode *vp, struct stat *sb)
68 if (vp->v_type == VCHR && vp->v_rdev != NULL &&
69 linux_driver_get_major_minor(devtoname(vp->v_rdev),
70 &major, &minor) == 0) {
71 sb->st_rdev = (major << 8 | minor);
76 linux_kern_statat(struct thread *td, int flag, int fd, char *path,
77 enum uio_seg pathseg, struct stat *sbp)
80 return (kern_statat(td, flag, fd, path, pathseg, sbp,
81 translate_vnhook_major_minor));
85 linux_kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
89 return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp));
93 linux_kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,
97 return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
102 translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
109 * No capability rights required here.
111 if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
112 fget(td, fd, &cap_no_rights, &fp) != 0)
115 if (vp != NULL && vp->v_rdev != NULL &&
116 linux_driver_get_major_minor(devtoname(vp->v_rdev),
117 &major, &minor) == 0) {
118 buf->st_rdev = (major << 8 | minor);
119 } else if (fp->f_type == DTYPE_PTS) {
120 struct tty *tp = fp->f_data;
122 /* Convert the numbers for the slave device. */
123 if (linux_driver_get_major_minor(devtoname(tp->t_dev),
124 &major, &minor) == 0) {
125 buf->st_rdev = (major << 8 | minor);
132 * l_dev_t has the same encoding as dev_t in the latter's low 16 bits, so
133 * don't bother going through major() and minor(). Keep doing blind
134 * truncation, as for other fields. The previous version didn't even do
135 * blind truncation after dev_t was expanded to 64 bits. It failed to
136 * mask out bits 8-15 in minor(). These bits can only be nonzero in th
139 * This is only used for st_dev. st_dev is for the mounted-on device so
140 * it can't be a device that needs very special translation. The translation
141 * of blind truncation is done here. st_rdev is supposed to be specially
142 * translated in callers, with the blind truncation done there too and
143 * st_rdev in the native struct state abused to hold the linux st_rdev.
144 * Callers do the last step using an open-coded Linux makedev().
146 #define dev_to_ldev(d) ((uint16_t)(d))
149 newstat_copyout(struct stat *buf, void *ubuf)
151 struct l_newstat tbuf;
153 bzero(&tbuf, sizeof(tbuf));
154 tbuf.st_dev = dev_to_ldev(buf->st_dev);
155 tbuf.st_ino = buf->st_ino;
156 tbuf.st_mode = buf->st_mode;
157 tbuf.st_nlink = buf->st_nlink;
158 tbuf.st_uid = buf->st_uid;
159 tbuf.st_gid = buf->st_gid;
160 tbuf.st_rdev = buf->st_rdev;
161 tbuf.st_size = buf->st_size;
162 tbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
163 tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
164 tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
165 tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
166 tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
167 tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
168 tbuf.st_blksize = buf->st_blksize;
169 tbuf.st_blocks = buf->st_blocks;
171 return (copyout(&tbuf, ubuf, sizeof(tbuf)));
175 linux_newstat(struct thread *td, struct linux_newstat_args *args)
181 LCONVPATHEXIST(td, args->path, &path);
185 printf(ARGS(newstat, "%s, *"), path);
188 error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
192 return (newstat_copyout(&buf, args->buf));
196 linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
202 LCONVPATHEXIST(td, args->path, &path);
205 if (ldebug(newlstat))
206 printf(ARGS(newlstat, "%s, *"), path);
209 error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb);
213 return (newstat_copyout(&sb, args->buf));
217 linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
223 if (ldebug(newfstat))
224 printf(ARGS(newfstat, "%d, *"), args->fd);
227 error = kern_fstat(td, args->fd, &buf);
228 translate_fd_major_minor(td, args->fd, &buf);
230 error = newstat_copyout(&buf, args->buf);
235 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
237 stat_copyout(struct stat *buf, void *ubuf)
241 bzero(&lbuf, sizeof(lbuf));
242 lbuf.st_dev = dev_to_ldev(buf->st_dev);
243 lbuf.st_ino = buf->st_ino;
244 lbuf.st_mode = buf->st_mode;
245 lbuf.st_nlink = buf->st_nlink;
246 lbuf.st_uid = buf->st_uid;
247 lbuf.st_gid = buf->st_gid;
248 lbuf.st_rdev = buf->st_rdev;
249 lbuf.st_size = MIN(buf->st_size, INT32_MAX);
250 lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
251 lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
252 lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
253 lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
254 lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
255 lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
256 lbuf.st_blksize = buf->st_blksize;
257 lbuf.st_blocks = buf->st_blocks;
258 lbuf.st_flags = buf->st_flags;
259 lbuf.st_gen = buf->st_gen;
261 return (copyout(&lbuf, ubuf, sizeof(lbuf)));
265 linux_stat(struct thread *td, struct linux_stat_args *args)
271 LCONVPATHEXIST(td, args->path, &path);
275 printf(ARGS(stat, "%s, *"), path);
277 error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
283 return (stat_copyout(&buf, args->up));
287 linux_lstat(struct thread *td, struct linux_lstat_args *args)
293 LCONVPATHEXIST(td, args->path, &path);
297 printf(ARGS(lstat, "%s, *"), path);
299 error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf);
305 return (stat_copyout(&buf, args->up));
307 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
324 #define LINUX_CODA_SUPER_MAGIC 0x73757245L
325 #define LINUX_EXT2_SUPER_MAGIC 0xEF53L
326 #define LINUX_HPFS_SUPER_MAGIC 0xf995e849L
327 #define LINUX_ISOFS_SUPER_MAGIC 0x9660L
328 #define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
329 #define LINUX_NCP_SUPER_MAGIC 0x564cL
330 #define LINUX_NFS_SUPER_MAGIC 0x6969L
331 #define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
332 #define LINUX_PROC_SUPER_MAGIC 0x9fa0L
333 #define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
334 #define LINUX_ZFS_SUPER_MAGIC 0x2FC12FC1
335 #define LINUX_DEVFS_SUPER_MAGIC 0x1373L
336 #define LINUX_SHMFS_MAGIC 0x01021994
339 bsd_to_linux_ftype(const char *fstypename)
342 static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
343 {"ufs", LINUX_UFS_SUPER_MAGIC},
344 {"zfs", LINUX_ZFS_SUPER_MAGIC},
345 {"cd9660", LINUX_ISOFS_SUPER_MAGIC},
346 {"nfs", LINUX_NFS_SUPER_MAGIC},
347 {"ext2fs", LINUX_EXT2_SUPER_MAGIC},
348 {"procfs", LINUX_PROC_SUPER_MAGIC},
349 {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
350 {"ntfs", LINUX_NTFS_SUPER_MAGIC},
351 {"nwfs", LINUX_NCP_SUPER_MAGIC},
352 {"hpfs", LINUX_HPFS_SUPER_MAGIC},
353 {"coda", LINUX_CODA_SUPER_MAGIC},
354 {"devfs", LINUX_DEVFS_SUPER_MAGIC},
355 {"tmpfs", LINUX_SHMFS_MAGIC},
358 for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
359 if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
360 return (b2l_tbl[i].linux_type);
366 bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
368 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
371 #define LINUX_HIBITS 0xffffffff00000000ULL
373 tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
375 if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
376 (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
377 (tmp & LINUX_HIBITS))
381 linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
382 linux_statfs->f_bsize = bsd_statfs->f_bsize;
383 linux_statfs->f_blocks = bsd_statfs->f_blocks;
384 linux_statfs->f_bfree = bsd_statfs->f_bfree;
385 linux_statfs->f_bavail = bsd_statfs->f_bavail;
386 linux_statfs->f_ffree = bsd_statfs->f_ffree;
387 linux_statfs->f_files = bsd_statfs->f_files;
388 linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
389 linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
390 linux_statfs->f_namelen = MAXNAMLEN;
391 linux_statfs->f_frsize = bsd_statfs->f_bsize;
392 linux_statfs->f_flags = 0;
393 memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
399 linux_statfs(struct thread *td, struct linux_statfs_args *args)
401 struct l_statfs linux_statfs;
402 struct statfs *bsd_statfs;
406 LCONVPATHEXIST(td, args->path, &path);
410 printf(ARGS(statfs, "%s, *"), path);
412 bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
413 error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
416 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
417 free(bsd_statfs, M_STATFS);
420 return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
423 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
425 bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
428 linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
429 linux_statfs->f_bsize = bsd_statfs->f_bsize;
430 linux_statfs->f_blocks = bsd_statfs->f_blocks;
431 linux_statfs->f_bfree = bsd_statfs->f_bfree;
432 linux_statfs->f_bavail = bsd_statfs->f_bavail;
433 linux_statfs->f_ffree = bsd_statfs->f_ffree;
434 linux_statfs->f_files = bsd_statfs->f_files;
435 linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
436 linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
437 linux_statfs->f_namelen = MAXNAMLEN;
438 linux_statfs->f_frsize = bsd_statfs->f_bsize;
439 linux_statfs->f_flags = 0;
440 memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
444 linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
446 struct l_statfs64 linux_statfs;
447 struct statfs *bsd_statfs;
451 if (args->bufsize != sizeof(struct l_statfs64))
454 LCONVPATHEXIST(td, args->path, &path);
457 if (ldebug(statfs64))
458 printf(ARGS(statfs64, "%s, *"), path);
460 bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
461 error = kern_statfs(td, path, UIO_SYSSPACE, bsd_statfs);
464 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
465 free(bsd_statfs, M_STATFS);
468 return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
472 linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
474 struct l_statfs64 linux_statfs;
475 struct statfs *bsd_statfs;
479 if (ldebug(fstatfs64))
480 printf(ARGS(fstatfs64, "%d, *"), args->fd);
482 if (args->bufsize != sizeof(struct l_statfs64))
485 bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
486 error = kern_fstatfs(td, args->fd, bsd_statfs);
488 bsd_to_linux_statfs64(bsd_statfs, &linux_statfs);
489 free(bsd_statfs, M_STATFS);
492 return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
494 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
497 linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
499 struct l_statfs linux_statfs;
500 struct statfs *bsd_statfs;
505 printf(ARGS(fstatfs, "%d, *"), args->fd);
507 bsd_statfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
508 error = kern_fstatfs(td, args->fd, bsd_statfs);
510 error = bsd_to_linux_statfs(bsd_statfs, &linux_statfs);
511 free(bsd_statfs, M_STATFS);
514 return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
526 linux_ustat(struct thread *td, struct linux_ustat_args *args)
530 printf(ARGS(ustat, "%ju, *"), (uintmax_t)args->dev);
536 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
539 stat64_copyout(struct stat *buf, void *ubuf)
541 struct l_stat64 lbuf;
543 bzero(&lbuf, sizeof(lbuf));
544 lbuf.st_dev = dev_to_ldev(buf->st_dev);
545 lbuf.st_ino = buf->st_ino;
546 lbuf.st_mode = buf->st_mode;
547 lbuf.st_nlink = buf->st_nlink;
548 lbuf.st_uid = buf->st_uid;
549 lbuf.st_gid = buf->st_gid;
550 lbuf.st_rdev = buf->st_rdev;
551 lbuf.st_size = buf->st_size;
552 lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
553 lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
554 lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
555 lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
556 lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
557 lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
558 lbuf.st_blksize = buf->st_blksize;
559 lbuf.st_blocks = buf->st_blocks;
562 * The __st_ino field makes all the difference. In the Linux kernel
563 * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
564 * but without the assignment to __st_ino the runtime linker refuses
565 * to mmap(2) any shared libraries. I guess it's broken alright :-)
567 lbuf.__st_ino = buf->st_ino;
569 return (copyout(&lbuf, ubuf, sizeof(lbuf)));
573 linux_stat64(struct thread *td, struct linux_stat64_args *args)
579 LCONVPATHEXIST(td, args->filename, &filename);
583 printf(ARGS(stat64, "%s, *"), filename);
586 error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf);
590 return (stat64_copyout(&buf, args->statbuf));
594 linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
600 LCONVPATHEXIST(td, args->filename, &filename);
604 printf(ARGS(lstat64, "%s, *"), args->filename);
607 error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb);
611 return (stat64_copyout(&sb, args->statbuf));
615 linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
622 printf(ARGS(fstat64, "%d, *"), args->fd);
625 error = kern_fstat(td, args->fd, &buf);
626 translate_fd_major_minor(td, args->fd, &buf);
628 error = stat64_copyout(&buf, args->statbuf);
634 linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
637 int error, dfd, flag;
640 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
642 flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
643 AT_SYMLINK_NOFOLLOW : 0;
645 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
646 LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
649 if (ldebug(fstatat64))
650 printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag);
653 error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
655 error = stat64_copyout(&buf, args->statbuf);
661 #else /* __amd64__ && !COMPAT_LINUX32 */
664 linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args)
667 int error, dfd, flag;
670 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
672 flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
673 AT_SYMLINK_NOFOLLOW : 0;
675 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
676 LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
679 if (ldebug(newfstatat))
680 printf(ARGS(newfstatat, "%i, %s, %i"), args->dfd, path, args->flag);
683 error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
685 error = newstat_copyout(&buf, args->statbuf);
691 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
694 linux_syncfs(struct thread *td, struct linux_syncfs_args *args)
700 error = fgetvp(td, args->fd, &cap_fsync_rights, &vp);
703 * Linux syncfs() returns only EBADF, however fgetvp()
704 * can return EINVAL in case of file descriptor does
705 * not represent a vnode. XXX.
710 mtx_lock(&mountlist_mtx);
711 error = vfs_busy(mp, MBF_MNTLSTLOCK);
713 /* See comment above. */
714 mtx_unlock(&mountlist_mtx);
717 if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
718 vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
719 save = curthread_pflags_set(TDP_SYNCIO);
720 vfs_msync(mp, MNT_NOWAIT);
721 VFS_SYNC(mp, MNT_NOWAIT);
722 curthread_pflags_restore(save);
723 vn_finished_write(mp);