sys/kern: Allow custom fileops to specify fo_seek method. Previously only vnodes allowed lseek/pread[v]/pwrite[v], which meant converting a regular device to a cloning device doesn't always work. Semantics is: (*fp->f_ops->fo_seek)(fp, delta, whence, newoffp, flags) 1. Compute a new offset according to whence + delta -- that is, if whence is SEEK_CUR, add delta to fp->f_offset; if whence is SEEK_END, add delta to end of file; if whence is SEEK_CUR, use delta as is. 2. If newoffp is nonnull, return the new offset in *newoffp. 3. If flags & FOF_UPDATE_OFFSET, set fp->f_offset to the new offset. Access to fp->f_offset, and *newoffp if newoffp = &fp->f_offset, must happen under the object lock (e.g., vnode lock), in order to synchronize fp->f_offset reads and writes. This change has the side effect that every call to VOP_SEEK happens under the vnode lock now, when previously it didn't. However, from a review of all the VOP_SEEK implementations, it does not appear that any file system even examines the vnode, let alone locks it. So I think this is safe -- and essentially the only reasonable way to do things, given that it is used to validate a change from oldoff to newoff, and oldoff becomes stale the moment we unlock the vnode. No kernel bump because this reuses a spare entry in struct fileops, and it is safe for the entry to be null, so all existing fileops will continue to work as before (rejecting seek).diff -r1.93 -r1.94 src/sys/compat/netbsd32/netbsd32_fs.c
(riastradh)
--- src/sys/compat/netbsd32/netbsd32_fs.c 2021/02/16 14:47:20 1.93
+++ src/sys/compat/netbsd32/netbsd32_fs.c 2021/09/11 10:08:55 1.94
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: netbsd32_fs.c,v 1.93 2021/02/16 14:47:20 simonb Exp $ */ | 1 | /* $NetBSD: netbsd32_fs.c,v 1.94 2021/09/11 10:08:55 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2001 Matthew R. Green | 4 | * Copyright (c) 1998, 2001 Matthew R. Green | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -17,27 +17,27 @@ | @@ -17,27 +17,27 @@ | |||
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 24 | * 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 | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 | * SUCH DAMAGE. | 26 | * SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.93 2021/02/16 14:47:20 simonb Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.94 2021/09/11 10:08:55 riastradh Exp $"); | |
31 | 31 | |||
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/systm.h> | 33 | #include <sys/systm.h> | |
34 | #include <sys/mount.h> | 34 | #include <sys/mount.h> | |
35 | #include <sys/socket.h> | 35 | #include <sys/socket.h> | |
36 | #include <sys/socketvar.h> | 36 | #include <sys/socketvar.h> | |
37 | #include <sys/stat.h> | 37 | #include <sys/stat.h> | |
38 | #include <sys/time.h> | 38 | #include <sys/time.h> | |
39 | #include <sys/ktrace.h> | 39 | #include <sys/ktrace.h> | |
40 | #include <sys/resourcevar.h> | 40 | #include <sys/resourcevar.h> | |
41 | #include <sys/vnode.h> | 41 | #include <sys/vnode.h> | |
42 | #include <sys/file.h> | 42 | #include <sys/file.h> | |
43 | #include <sys/filedesc.h> | 43 | #include <sys/filedesc.h> | |
@@ -638,97 +638,85 @@ netbsd32___fhstat50(struct lwp *l, const | @@ -638,97 +638,85 @@ netbsd32___fhstat50(struct lwp *l, const | |||
638 | } | 638 | } | |
639 | 639 | |||
640 | int | 640 | int | |
641 | netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval) | 641 | netbsd32_preadv(struct lwp *l, const struct netbsd32_preadv_args *uap, register_t *retval) | |
642 | { | 642 | { | |
643 | /* { | 643 | /* { | |
644 | syscallarg(int) fd; | 644 | syscallarg(int) fd; | |
645 | syscallarg(const netbsd32_iovecp_t) iovp; | 645 | syscallarg(const netbsd32_iovecp_t) iovp; | |
646 | syscallarg(int) iovcnt; | 646 | syscallarg(int) iovcnt; | |
647 | syscallarg(int) pad; | 647 | syscallarg(int) pad; | |
648 | syscallarg(netbsd32_off_t) offset; | 648 | syscallarg(netbsd32_off_t) offset; | |
649 | } */ | 649 | } */ | |
650 | file_t *fp; | 650 | file_t *fp; | |
651 | struct vnode *vp; | |||
652 | off_t offset; | 651 | off_t offset; | |
653 | int error, fd = SCARG(uap, fd); | 652 | int error, fd = SCARG(uap, fd); | |
654 | 653 | |||
655 | if ((fp = fd_getfile(fd)) == NULL) | 654 | if ((fp = fd_getfile(fd)) == NULL) | |
656 | return EBADF; | 655 | return EBADF; | |
657 | 656 | |||
658 | if ((fp->f_flag & FREAD) == 0) { | 657 | if ((fp->f_flag & FREAD) == 0) { | |
659 | fd_putfile(fd); | 658 | fd_putfile(fd); | |
660 | return EBADF; | 659 | return EBADF; | |
661 | } | 660 | } | |
662 | 661 | |||
663 | vp = fp->f_vnode; | 662 | if (fp->f_ops->fo_seek == NULL) { | |
664 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | |||
665 | error = ESPIPE; | 663 | error = ESPIPE; | |
666 | goto out; | 664 | goto out; | |
667 | } | 665 | } | |
668 | 666 | |||
669 | offset = SCARG(uap, offset); | 667 | offset = SCARG(uap, offset); | |
670 | 668 | error = (*fp->f_ops->fo_seek)(fp, offset, SEEK_SET, &offset, 0); | ||
671 | /* | 669 | if (error) | |
672 | * XXX This works because no file systems actually | |||
673 | * XXX take any action on the seek operation. | |||
674 | */ | |||
675 | if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) | |||
676 | goto out; | 670 | goto out; | |
677 | 671 | |||
678 | return dofilereadv32(fd, fp, SCARG_P32(uap, iovp), | 672 | return dofilereadv32(fd, fp, SCARG_P32(uap, iovp), | |
679 | SCARG(uap, iovcnt), &offset, 0, retval); | 673 | SCARG(uap, iovcnt), &offset, 0, retval); | |
680 | 674 | |||
681 | out: | 675 | out: | |
682 | fd_putfile(fd); | 676 | fd_putfile(fd); | |
683 | return error; | 677 | return error; | |
684 | } | 678 | } | |
685 | 679 | |||
686 | int | 680 | int | |
687 | netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval) | 681 | netbsd32_pwritev(struct lwp *l, const struct netbsd32_pwritev_args *uap, register_t *retval) | |
688 | { | 682 | { | |
689 | /* { | 683 | /* { | |
690 | syscallarg(int) fd; | 684 | syscallarg(int) fd; | |
691 | syscallarg(const netbsd32_iovecp_t) iovp; | 685 | syscallarg(const netbsd32_iovecp_t) iovp; | |
692 | syscallarg(int) iovcnt; | 686 | syscallarg(int) iovcnt; | |
693 | syscallarg(int) pad; | 687 | syscallarg(int) pad; | |
694 | syscallarg(netbsd32_off_t) offset; | 688 | syscallarg(netbsd32_off_t) offset; | |
695 | } */ | 689 | } */ | |
696 | file_t *fp; | 690 | file_t *fp; | |
697 | struct vnode *vp; | |||
698 | off_t offset; | 691 | off_t offset; | |
699 | int error, fd = SCARG(uap, fd); | 692 | int error, fd = SCARG(uap, fd); | |
700 | 693 | |||
701 | if ((fp = fd_getfile(fd)) == NULL) | 694 | if ((fp = fd_getfile(fd)) == NULL) | |
702 | return EBADF; | 695 | return EBADF; | |
703 | 696 | |||
704 | if ((fp->f_flag & FWRITE) == 0) { | 697 | if ((fp->f_flag & FWRITE) == 0) { | |
705 | fd_putfile(fd); | 698 | fd_putfile(fd); | |
706 | return EBADF; | 699 | return EBADF; | |
707 | } | 700 | } | |
708 | 701 | |||
709 | vp = fp->f_vnode; | 702 | if (fp->f_ops->fo_seek == NULL) { | |
710 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | |||
711 | error = ESPIPE; | 703 | error = ESPIPE; | |
712 | goto out; | 704 | goto out; | |
713 | } | 705 | } | |
714 | 706 | |||
715 | offset = SCARG(uap, offset); | 707 | offset = SCARG(uap, offset); | |
716 | 708 | error = (*fp->f_ops->fo_seek)(fp, offset, SEEK_SET, &offset, 0); | ||
717 | /* | 709 | if (error) | |
718 | * XXX This works because no file systems actually | |||
719 | * XXX take any action on the seek operation. | |||
720 | */ | |||
721 | if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) | |||
722 | goto out; | 710 | goto out; | |
723 | 711 | |||
724 | return dofilewritev32(fd, fp, SCARG_P32(uap, iovp), | 712 | return dofilewritev32(fd, fp, SCARG_P32(uap, iovp), | |
725 | SCARG(uap, iovcnt), &offset, 0, retval); | 713 | SCARG(uap, iovcnt), &offset, 0, retval); | |
726 | 714 | |||
727 | out: | 715 | out: | |
728 | fd_putfile(fd); | 716 | fd_putfile(fd); | |
729 | return error; | 717 | return error; | |
730 | } | 718 | } | |
731 | 719 | |||
732 | /* | 720 | /* | |
733 | * Find pathname of process's current directory. | 721 | * Find pathname of process's current directory. | |
734 | * | 722 | * |
--- src/sys/kern/sys_generic.c 2020/05/23 23:42:43 1.132
+++ src/sys/kern/sys_generic.c 2021/09/11 10:08:55 1.133
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sys_generic.c,v 1.132 2020/05/23 23:42:43 ad Exp $ */ | 1 | /* $NetBSD: sys_generic.c,v 1.133 2021/09/11 10:08:55 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -60,27 +60,27 @@ | @@ -60,27 +60,27 @@ | |||
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
63 | * SUCH DAMAGE. | 63 | * SUCH DAMAGE. | |
64 | * | 64 | * | |
65 | * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95 | 65 | * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95 | |
66 | */ | 66 | */ | |
67 | 67 | |||
68 | /* | 68 | /* | |
69 | * System calls relating to files. | 69 | * System calls relating to files. | |
70 | */ | 70 | */ | |
71 | 71 | |||
72 | #include <sys/cdefs.h> | 72 | #include <sys/cdefs.h> | |
73 | __KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.132 2020/05/23 23:42:43 ad Exp $"); | 73 | __KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.133 2021/09/11 10:08:55 riastradh Exp $"); | |
74 | 74 | |||
75 | #include <sys/param.h> | 75 | #include <sys/param.h> | |
76 | #include <sys/systm.h> | 76 | #include <sys/systm.h> | |
77 | #include <sys/filedesc.h> | 77 | #include <sys/filedesc.h> | |
78 | #include <sys/ioctl.h> | 78 | #include <sys/ioctl.h> | |
79 | #include <sys/file.h> | 79 | #include <sys/file.h> | |
80 | #include <sys/proc.h> | 80 | #include <sys/proc.h> | |
81 | #include <sys/socketvar.h> | 81 | #include <sys/socketvar.h> | |
82 | #include <sys/signalvar.h> | 82 | #include <sys/signalvar.h> | |
83 | #include <sys/uio.h> | 83 | #include <sys/uio.h> | |
84 | #include <sys/kernel.h> | 84 | #include <sys/kernel.h> | |
85 | #include <sys/stat.h> | 85 | #include <sys/stat.h> | |
86 | #include <sys/kmem.h> | 86 | #include <sys/kmem.h> | |
@@ -198,37 +198,38 @@ do_filereadv(int fd, const struct iovec | @@ -198,37 +198,38 @@ do_filereadv(int fd, const struct iovec | |||
198 | return EINVAL; | 198 | return EINVAL; | |
199 | 199 | |||
200 | if ((fp = fd_getfile(fd)) == NULL) | 200 | if ((fp = fd_getfile(fd)) == NULL) | |
201 | return EBADF; | 201 | return EBADF; | |
202 | 202 | |||
203 | if ((fp->f_flag & FREAD) == 0) { | 203 | if ((fp->f_flag & FREAD) == 0) { | |
204 | fd_putfile(fd); | 204 | fd_putfile(fd); | |
205 | return EBADF; | 205 | return EBADF; | |
206 | } | 206 | } | |
207 | 207 | |||
208 | if (offset == NULL) | 208 | if (offset == NULL) | |
209 | offset = &fp->f_offset; | 209 | offset = &fp->f_offset; | |
210 | else { | 210 | else { | |
211 | struct vnode *vp = fp->f_vnode; | 211 | /* | |
212 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | 212 | * Caller must not specify &fp->f_offset -- we can't | |
213 | * safely dereference it for the call to fo_seek | |||
214 | * without holding some underlying object lock. | |||
215 | */ | |||
216 | KASSERT(offset != &fp->f_offset); | |||
217 | if (fp->f_ops->fo_seek == NULL) { | |||
213 | error = ESPIPE; | 218 | error = ESPIPE; | |
214 | goto out; | 219 | goto out; | |
215 | } | 220 | } | |
216 | /* | 221 | error = (*fp->f_ops->fo_seek)(fp, *offset, SEEK_SET, NULL, | |
217 | * Test that the device is seekable ? | 222 | 0); | |
218 | * XXX This works because no file systems actually | |||
219 | * XXX take any action on the seek operation. | |||
220 | */ | |||
221 | error = VOP_SEEK(vp, fp->f_offset, *offset, fp->f_cred); | |||
222 | if (error != 0) | 223 | if (error != 0) | |
223 | goto out; | 224 | goto out; | |
224 | } | 225 | } | |
225 | 226 | |||
226 | iovlen = iovcnt * sizeof(struct iovec); | 227 | iovlen = iovcnt * sizeof(struct iovec); | |
227 | if (flags & FOF_IOV_SYSSPACE) | 228 | if (flags & FOF_IOV_SYSSPACE) | |
228 | iov = __UNCONST(iovp); | 229 | iov = __UNCONST(iovp); | |
229 | else { | 230 | else { | |
230 | iov = aiov; | 231 | iov = aiov; | |
231 | if ((u_int)iovcnt > UIO_SMALLIOV) { | 232 | if ((u_int)iovcnt > UIO_SMALLIOV) { | |
232 | if ((u_int)iovcnt > IOV_MAX) { | 233 | if ((u_int)iovcnt > IOV_MAX) { | |
233 | error = EINVAL; | 234 | error = EINVAL; | |
234 | goto out; | 235 | goto out; | |
@@ -398,37 +399,38 @@ do_filewritev(int fd, const struct iovec | @@ -398,37 +399,38 @@ do_filewritev(int fd, const struct iovec | |||
398 | return EINVAL; | 399 | return EINVAL; | |
399 | 400 | |||
400 | if ((fp = fd_getfile(fd)) == NULL) | 401 | if ((fp = fd_getfile(fd)) == NULL) | |
401 | return EBADF; | 402 | return EBADF; | |
402 | 403 | |||
403 | if ((fp->f_flag & FWRITE) == 0) { | 404 | if ((fp->f_flag & FWRITE) == 0) { | |
404 | fd_putfile(fd); | 405 | fd_putfile(fd); | |
405 | return EBADF; | 406 | return EBADF; | |
406 | } | 407 | } | |
407 | 408 | |||
408 | if (offset == NULL) | 409 | if (offset == NULL) | |
409 | offset = &fp->f_offset; | 410 | offset = &fp->f_offset; | |
410 | else { | 411 | else { | |
411 | struct vnode *vp = fp->f_vnode; | 412 | /* | |
412 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | 413 | * Caller must not specify &fp->f_offset -- we can't | |
414 | * safely dereference it for the call to fo_seek | |||
415 | * without holding some underlying object lock. | |||
416 | */ | |||
417 | KASSERT(offset != &fp->f_offset); | |||
418 | if (fp->f_ops->fo_seek == NULL) { | |||
413 | error = ESPIPE; | 419 | error = ESPIPE; | |
414 | goto out; | 420 | goto out; | |
415 | } | 421 | } | |
416 | /* | 422 | error = (*fp->f_ops->fo_seek)(fp, *offset, SEEK_SET, NULL, | |
417 | * Test that the device is seekable ? | 423 | 0); | |
418 | * XXX This works because no file systems actually | |||
419 | * XXX take any action on the seek operation. | |||
420 | */ | |||
421 | error = VOP_SEEK(vp, fp->f_offset, *offset, fp->f_cred); | |||
422 | if (error != 0) | 424 | if (error != 0) | |
423 | goto out; | 425 | goto out; | |
424 | } | 426 | } | |
425 | 427 | |||
426 | iovlen = iovcnt * sizeof(struct iovec); | 428 | iovlen = iovcnt * sizeof(struct iovec); | |
427 | if (flags & FOF_IOV_SYSSPACE) | 429 | if (flags & FOF_IOV_SYSSPACE) | |
428 | iov = __UNCONST(iovp); | 430 | iov = __UNCONST(iovp); | |
429 | else { | 431 | else { | |
430 | iov = aiov; | 432 | iov = aiov; | |
431 | if ((u_int)iovcnt > UIO_SMALLIOV) { | 433 | if ((u_int)iovcnt > UIO_SMALLIOV) { | |
432 | if ((u_int)iovcnt > IOV_MAX) { | 434 | if ((u_int)iovcnt > IOV_MAX) { | |
433 | error = EINVAL; | 435 | error = EINVAL; | |
434 | goto out; | 436 | goto out; |
--- src/sys/kern/vfs_syscalls.c 2021/07/03 09:39:26 1.551
+++ src/sys/kern/vfs_syscalls.c 2021/09/11 10:08:55 1.552
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: vfs_syscalls.c,v 1.551 2021/07/03 09:39:26 mlelstv Exp $ */ | 1 | /* $NetBSD: vfs_syscalls.c,v 1.552 2021/09/11 10:08:55 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -60,27 +60,27 @@ | @@ -60,27 +60,27 @@ | |||
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
63 | * SUCH DAMAGE. | 63 | * SUCH DAMAGE. | |
64 | * | 64 | * | |
65 | * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 | 65 | * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 | |
66 | */ | 66 | */ | |
67 | 67 | |||
68 | /* | 68 | /* | |
69 | * Virtual File System System Calls | 69 | * Virtual File System System Calls | |
70 | */ | 70 | */ | |
71 | 71 | |||
72 | #include <sys/cdefs.h> | 72 | #include <sys/cdefs.h> | |
73 | __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.551 2021/07/03 09:39:26 mlelstv Exp $"); | 73 | __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.552 2021/09/11 10:08:55 riastradh Exp $"); | |
74 | 74 | |||
75 | #ifdef _KERNEL_OPT | 75 | #ifdef _KERNEL_OPT | |
76 | #include "opt_fileassoc.h" | 76 | #include "opt_fileassoc.h" | |
77 | #include "veriexec.h" | 77 | #include "veriexec.h" | |
78 | #endif | 78 | #endif | |
79 | 79 | |||
80 | #include <sys/param.h> | 80 | #include <sys/param.h> | |
81 | #include <sys/systm.h> | 81 | #include <sys/systm.h> | |
82 | #include <sys/namei.h> | 82 | #include <sys/namei.h> | |
83 | #include <sys/filedesc.h> | 83 | #include <sys/filedesc.h> | |
84 | #include <sys/kernel.h> | 84 | #include <sys/kernel.h> | |
85 | #include <sys/file.h> | 85 | #include <sys/file.h> | |
86 | #include <sys/fcntl.h> | 86 | #include <sys/fcntl.h> | |
@@ -2846,113 +2846,87 @@ out: | @@ -2846,113 +2846,87 @@ out: | |||
2846 | 2846 | |||
2847 | /* | 2847 | /* | |
2848 | * Reposition read/write file offset. | 2848 | * Reposition read/write file offset. | |
2849 | */ | 2849 | */ | |
2850 | int | 2850 | int | |
2851 | sys_lseek(struct lwp *l, const struct sys_lseek_args *uap, register_t *retval) | 2851 | sys_lseek(struct lwp *l, const struct sys_lseek_args *uap, register_t *retval) | |
2852 | { | 2852 | { | |
2853 | /* { | 2853 | /* { | |
2854 | syscallarg(int) fd; | 2854 | syscallarg(int) fd; | |
2855 | syscallarg(int) pad; | 2855 | syscallarg(int) pad; | |
2856 | syscallarg(off_t) offset; | 2856 | syscallarg(off_t) offset; | |
2857 | syscallarg(int) whence; | 2857 | syscallarg(int) whence; | |
2858 | } */ | 2858 | } */ | |
2859 | kauth_cred_t cred = l->l_cred; | |||
2860 | file_t *fp; | 2859 | file_t *fp; | |
2861 | struct vnode *vp; | |||
2862 | struct vattr vattr; | |||
2863 | off_t newoff; | |||
2864 | int error, fd; | 2860 | int error, fd; | |
2865 | 2861 | |||
2862 | switch (SCARG(uap, whence)) { | |||
2863 | case SEEK_CUR: | |||
2864 | case SEEK_END: | |||
2865 | case SEEK_SET: | |||
2866 | break; | |||
2867 | default: | |||
2868 | return EINVAL; | |||
2869 | } | |||
2870 | ||||
2866 | fd = SCARG(uap, fd); | 2871 | fd = SCARG(uap, fd); | |
2867 | 2872 | |||
2868 | if ((fp = fd_getfile(fd)) == NULL) | 2873 | if ((fp = fd_getfile(fd)) == NULL) | |
2869 | return (EBADF); | 2874 | return (EBADF); | |
2870 | 2875 | |||
2871 | vp = fp->f_vnode; | 2876 | if (fp->f_ops->fo_seek == NULL) { | |
2872 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | |||
2873 | error = ESPIPE; | 2877 | error = ESPIPE; | |
2874 | goto out; | 2878 | goto out; | |
2875 | } | 2879 | } | |
2876 | 2880 | |||
2877 | vn_lock(vp, LK_SHARED | LK_RETRY); | 2881 | error = (*fp->f_ops->fo_seek)(fp, SCARG(uap, offset), | |
2878 | 2882 | SCARG(uap, whence), (off_t *)retval, FOF_UPDATE_OFFSET); | ||
2879 | switch (SCARG(uap, whence)) { | |||
2880 | case SEEK_CUR: | |||
2881 | newoff = fp->f_offset + SCARG(uap, offset); | |||
2882 | break; | |||
2883 | case SEEK_END: | |||
2884 | error = VOP_GETATTR(vp, &vattr, cred); | |||
2885 | if (error) { | |||
2886 | VOP_UNLOCK(vp); | |||
2887 | goto out; | |||
2888 | } | |||
2889 | newoff = SCARG(uap, offset) + vattr.va_size; | |||
2890 | break; | |||
2891 | case SEEK_SET: | |||
2892 | newoff = SCARG(uap, offset); | |||
2893 | break; | |||
2894 | default: | |||
2895 | error = EINVAL; | |||
2896 | VOP_UNLOCK(vp); | |||
2897 | goto out; | |||
2898 | } | |||
2899 | VOP_UNLOCK(vp); | |||
2900 | if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) == 0) { | |||
2901 | *(off_t *)retval = fp->f_offset = newoff; | |||
2902 | } | |||
2903 | out: | 2883 | out: | |
2904 | fd_putfile(fd); | 2884 | fd_putfile(fd); | |
2905 | return (error); | 2885 | return (error); | |
2906 | } | 2886 | } | |
2907 | 2887 | |||
2908 | /* | 2888 | /* | |
2909 | * Positional read system call. | 2889 | * Positional read system call. | |
2910 | */ | 2890 | */ | |
2911 | int | 2891 | int | |
2912 | sys_pread(struct lwp *l, const struct sys_pread_args *uap, register_t *retval) | 2892 | sys_pread(struct lwp *l, const struct sys_pread_args *uap, register_t *retval) | |
2913 | { | 2893 | { | |
2914 | /* { | 2894 | /* { | |
2915 | syscallarg(int) fd; | 2895 | syscallarg(int) fd; | |
2916 | syscallarg(void *) buf; | 2896 | syscallarg(void *) buf; | |
2917 | syscallarg(size_t) nbyte; | 2897 | syscallarg(size_t) nbyte; | |
2918 | syscallarg(off_t) offset; | 2898 | syscallarg(off_t) offset; | |
2919 | } */ | 2899 | } */ | |
2920 | file_t *fp; | 2900 | file_t *fp; | |
2921 | struct vnode *vp; | |||
2922 | off_t offset; | 2901 | off_t offset; | |
2923 | int error, fd = SCARG(uap, fd); | 2902 | int error, fd = SCARG(uap, fd); | |
2924 | 2903 | |||
2925 | if ((fp = fd_getfile(fd)) == NULL) | 2904 | if ((fp = fd_getfile(fd)) == NULL) | |
2926 | return (EBADF); | 2905 | return (EBADF); | |
2927 | 2906 | |||
2928 | if ((fp->f_flag & FREAD) == 0) { | 2907 | if ((fp->f_flag & FREAD) == 0) { | |
2929 | fd_putfile(fd); | 2908 | fd_putfile(fd); | |
2930 | return (EBADF); | 2909 | return (EBADF); | |
2931 | } | 2910 | } | |
2932 | 2911 | |||
2933 | vp = fp->f_vnode; | 2912 | if (fp->f_ops->fo_seek == NULL) { | |
2934 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | |||
2935 | error = ESPIPE; | 2913 | error = ESPIPE; | |
2936 | goto out; | 2914 | goto out; | |
2937 | } | 2915 | } | |
2938 | 2916 | |||
2939 | offset = SCARG(uap, offset); | 2917 | offset = SCARG(uap, offset); | |
2940 | 2918 | error = (*fp->f_ops->fo_seek)(fp, offset, SEEK_SET, &offset, 0); | ||
2941 | /* | 2919 | if (error) | |
2942 | * XXX This works because no file systems actually | |||
2943 | * XXX take any action on the seek operation. | |||
2944 | */ | |||
2945 | if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) | |||
2946 | goto out; | 2920 | goto out; | |
2947 | 2921 | |||
2948 | /* dofileread() will unuse the descriptor for us */ | 2922 | /* dofileread() will unuse the descriptor for us */ | |
2949 | return (dofileread(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), | 2923 | return (dofileread(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), | |
2950 | &offset, 0, retval)); | 2924 | &offset, 0, retval)); | |
2951 | 2925 | |||
2952 | out: | 2926 | out: | |
2953 | fd_putfile(fd); | 2927 | fd_putfile(fd); | |
2954 | return (error); | 2928 | return (error); | |
2955 | } | 2929 | } | |
2956 | 2930 | |||
2957 | /* | 2931 | /* | |
2958 | * Positional scatter read system call. | 2932 | * Positional scatter read system call. | |
@@ -2975,51 +2949,45 @@ sys_preadv(struct lwp *l, const struct s | @@ -2975,51 +2949,45 @@ sys_preadv(struct lwp *l, const struct s | |||
2975 | /* | 2949 | /* | |
2976 | * Positional write system call. | 2950 | * Positional write system call. | |
2977 | */ | 2951 | */ | |
2978 | int | 2952 | int | |
2979 | sys_pwrite(struct lwp *l, const struct sys_pwrite_args *uap, register_t *retval) | 2953 | sys_pwrite(struct lwp *l, const struct sys_pwrite_args *uap, register_t *retval) | |
2980 | { | 2954 | { | |
2981 | /* { | 2955 | /* { | |
2982 | syscallarg(int) fd; | 2956 | syscallarg(int) fd; | |
2983 | syscallarg(const void *) buf; | 2957 | syscallarg(const void *) buf; | |
2984 | syscallarg(size_t) nbyte; | 2958 | syscallarg(size_t) nbyte; | |
2985 | syscallarg(off_t) offset; | 2959 | syscallarg(off_t) offset; | |
2986 | } */ | 2960 | } */ | |
2987 | file_t *fp; | 2961 | file_t *fp; | |
2988 | struct vnode *vp; | |||
2989 | off_t offset; | 2962 | off_t offset; | |
2990 | int error, fd = SCARG(uap, fd); | 2963 | int error, fd = SCARG(uap, fd); | |
2991 | 2964 | |||
2992 | if ((fp = fd_getfile(fd)) == NULL) | 2965 | if ((fp = fd_getfile(fd)) == NULL) | |
2993 | return (EBADF); | 2966 | return (EBADF); | |
2994 | 2967 | |||
2995 | if ((fp->f_flag & FWRITE) == 0) { | 2968 | if ((fp->f_flag & FWRITE) == 0) { | |
2996 | fd_putfile(fd); | 2969 | fd_putfile(fd); | |
2997 | return (EBADF); | 2970 | return (EBADF); | |
2998 | } | 2971 | } | |
2999 | 2972 | |||
3000 | vp = fp->f_vnode; | 2973 | if (fp->f_ops->fo_seek == NULL) { | |
3001 | if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { | |||
3002 | error = ESPIPE; | 2974 | error = ESPIPE; | |
3003 | goto out; | 2975 | goto out; | |
3004 | } | 2976 | } | |
3005 | 2977 | |||
3006 | offset = SCARG(uap, offset); | 2978 | offset = SCARG(uap, offset); | |
3007 | 2979 | error = (*fp->f_ops->fo_seek)(fp, offset, SEEK_SET, &offset, 0); | ||
3008 | /* | 2980 | if (error) | |
3009 | * XXX This works because no file systems actually | |||
3010 | * XXX take any action on the seek operation. | |||
3011 | */ | |||
3012 | if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) | |||
3013 | goto out; | 2981 | goto out; | |
3014 | 2982 | |||
3015 | /* dofilewrite() will unuse the descriptor for us */ | 2983 | /* dofilewrite() will unuse the descriptor for us */ | |
3016 | return (dofilewrite(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), | 2984 | return (dofilewrite(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), | |
3017 | &offset, 0, retval)); | 2985 | &offset, 0, retval)); | |
3018 | 2986 | |||
3019 | out: | 2987 | out: | |
3020 | fd_putfile(fd); | 2988 | fd_putfile(fd); | |
3021 | return (error); | 2989 | return (error); | |
3022 | } | 2990 | } | |
3023 | 2991 | |||
3024 | /* | 2992 | /* | |
3025 | * Positional gather write system call. | 2993 | * Positional gather write system call. |
--- src/sys/kern/vfs_vnops.c 2021/07/18 09:30:36 1.221
+++ src/sys/kern/vfs_vnops.c 2021/09/11 10:08:55 1.222
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: vfs_vnops.c,v 1.221 2021/07/18 09:30:36 dholland Exp $ */ | 1 | /* $NetBSD: vfs_vnops.c,v 1.222 2021/09/11 10:08:55 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -56,27 +56,27 @@ | @@ -56,27 +56,27 @@ | |||
56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
63 | * SUCH DAMAGE. | 63 | * SUCH DAMAGE. | |
64 | * | 64 | * | |
65 | * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 | 65 | * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 | |
66 | */ | 66 | */ | |
67 | 67 | |||
68 | #include <sys/cdefs.h> | 68 | #include <sys/cdefs.h> | |
69 | __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.221 2021/07/18 09:30:36 dholland Exp $"); | 69 | __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.222 2021/09/11 10:08:55 riastradh Exp $"); | |
70 | 70 | |||
71 | #include "veriexec.h" | 71 | #include "veriexec.h" | |
72 | 72 | |||
73 | #include <sys/param.h> | 73 | #include <sys/param.h> | |
74 | #include <sys/systm.h> | 74 | #include <sys/systm.h> | |
75 | #include <sys/kernel.h> | 75 | #include <sys/kernel.h> | |
76 | #include <sys/file.h> | 76 | #include <sys/file.h> | |
77 | #include <sys/stat.h> | 77 | #include <sys/stat.h> | |
78 | #include <sys/buf.h> | 78 | #include <sys/buf.h> | |
79 | #include <sys/proc.h> | 79 | #include <sys/proc.h> | |
80 | #include <sys/mount.h> | 80 | #include <sys/mount.h> | |
81 | #include <sys/namei.h> | 81 | #include <sys/namei.h> | |
82 | #include <sys/vnode.h> | 82 | #include <sys/vnode.h> | |
@@ -111,39 +111,41 @@ int (*vn_union_readdir_hook) (struct vno | @@ -111,39 +111,41 @@ int (*vn_union_readdir_hook) (struct vno | |||
111 | #include <sys/verified_exec.h> | 111 | #include <sys/verified_exec.h> | |
112 | 112 | |||
113 | static int vn_read(file_t *fp, off_t *offset, struct uio *uio, | 113 | static int vn_read(file_t *fp, off_t *offset, struct uio *uio, | |
114 | kauth_cred_t cred, int flags); | 114 | kauth_cred_t cred, int flags); | |
115 | static int vn_write(file_t *fp, off_t *offset, struct uio *uio, | 115 | static int vn_write(file_t *fp, off_t *offset, struct uio *uio, | |
116 | kauth_cred_t cred, int flags); | 116 | kauth_cred_t cred, int flags); | |
117 | static int vn_closefile(file_t *fp); | 117 | static int vn_closefile(file_t *fp); | |
118 | static int vn_poll(file_t *fp, int events); | 118 | static int vn_poll(file_t *fp, int events); | |
119 | static int vn_fcntl(file_t *fp, u_int com, void *data); | 119 | static int vn_fcntl(file_t *fp, u_int com, void *data); | |
120 | static int vn_statfile(file_t *fp, struct stat *sb); | 120 | static int vn_statfile(file_t *fp, struct stat *sb); | |
121 | static int vn_ioctl(file_t *fp, u_long com, void *data); | 121 | static int vn_ioctl(file_t *fp, u_long com, void *data); | |
122 | static int vn_mmap(struct file *, off_t *, size_t, int, int *, int *, | 122 | static int vn_mmap(struct file *, off_t *, size_t, int, int *, int *, | |
123 | struct uvm_object **, int *); | 123 | struct uvm_object **, int *); | |
124 | static int vn_seek(struct file *, off_t, int, off_t *, int); | |||
124 | 125 | |||
125 | const struct fileops vnops = { | 126 | const struct fileops vnops = { | |
126 | .fo_name = "vn", | 127 | .fo_name = "vn", | |
127 | .fo_read = vn_read, | 128 | .fo_read = vn_read, | |
128 | .fo_write = vn_write, | 129 | .fo_write = vn_write, | |
129 | .fo_ioctl = vn_ioctl, | 130 | .fo_ioctl = vn_ioctl, | |
130 | .fo_fcntl = vn_fcntl, | 131 | .fo_fcntl = vn_fcntl, | |
131 | .fo_poll = vn_poll, | 132 | .fo_poll = vn_poll, | |
132 | .fo_stat = vn_statfile, | 133 | .fo_stat = vn_statfile, | |
133 | .fo_close = vn_closefile, | 134 | .fo_close = vn_closefile, | |
134 | .fo_kqfilter = vn_kqfilter, | 135 | .fo_kqfilter = vn_kqfilter, | |
135 | .fo_restart = fnullop_restart, | 136 | .fo_restart = fnullop_restart, | |
136 | .fo_mmap = vn_mmap, | 137 | .fo_mmap = vn_mmap, | |
138 | .fo_seek = vn_seek, | |||
137 | }; | 139 | }; | |
138 | 140 | |||
139 | /* | 141 | /* | |
140 | * Common code for vnode open operations. | 142 | * Common code for vnode open operations. | |
141 | * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. | 143 | * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. | |
142 | * | 144 | * | |
143 | * at_dvp is the directory for openat(), if any. | 145 | * at_dvp is the directory for openat(), if any. | |
144 | * pb is the path. | 146 | * pb is the path. | |
145 | * nmode is additional namei flags, restricted to TRYEMULROOT and NOCHROOT. | 147 | * nmode is additional namei flags, restricted to TRYEMULROOT and NOCHROOT. | |
146 | * fmode is the open flags, converted from O_* to F* | 148 | * fmode is the open flags, converted from O_* to F* | |
147 | * cmode is the creation file permissions. | 149 | * cmode is the creation file permissions. | |
148 | * | 150 | * | |
149 | * XXX shouldn't cmode be mode_t? | 151 | * XXX shouldn't cmode be mode_t? | |
@@ -1100,27 +1102,76 @@ vn_mmap(struct file *fp, off_t *offp, si | @@ -1100,27 +1102,76 @@ vn_mmap(struct file *fp, off_t *offp, si | |||
1100 | * it can't be made executable later. | 1102 | * it can't be made executable later. | |
1101 | */ | 1103 | */ | |
1102 | maxprot &= ~VM_PROT_EXECUTE; | 1104 | maxprot &= ~VM_PROT_EXECUTE; | |
1103 | } | 1105 | } | |
1104 | #endif /* NVERIEXEC > 0 */ | 1106 | #endif /* NVERIEXEC > 0 */ | |
1105 | 1107 | |||
1106 | *uobjp = uobj; | 1108 | *uobjp = uobj; | |
1107 | *maxprotp = maxprot; | 1109 | *maxprotp = maxprot; | |
1108 | *flagsp = flags; | 1110 | *flagsp = flags; | |
1109 | 1111 | |||
1110 | return 0; | 1112 | return 0; | |
1111 | } | 1113 | } | |
1112 | 1114 | |||
1115 | static int | |||
1116 | vn_seek(struct file *fp, off_t delta, int whence, off_t *newoffp, | |||
1117 | int flags) | |||
1118 | { | |||
1119 | kauth_cred_t cred = fp->f_cred; | |||
1120 | off_t oldoff, newoff; | |||
1121 | struct vnode *vp = fp->f_vnode; | |||
1122 | struct vattr vattr; | |||
1123 | int error; | |||
1124 | ||||
1125 | if (vp->v_type == VFIFO) | |||
1126 | return ESPIPE; | |||
1127 | ||||
1128 | vn_lock(vp, LK_SHARED | LK_RETRY); | |||
1129 | ||||
1130 | /* Compute the old and new offsets. */ | |||
1131 | oldoff = fp->f_offset; | |||
1132 | switch (whence) { | |||
1133 | case SEEK_CUR: | |||
1134 | newoff = oldoff + delta; /* XXX arithmetic overflow */ | |||
1135 | break; | |||
1136 | case SEEK_END: | |||
1137 | error = VOP_GETATTR(vp, &vattr, cred); | |||
1138 | if (error) | |||
1139 | goto out; | |||
1140 | newoff = delta + vattr.va_size; /* XXX arithmetic overflow */ | |||
1141 | break; | |||
1142 | case SEEK_SET: | |||
1143 | newoff = delta; | |||
1144 | break; | |||
1145 | default: | |||
1146 | error = EINVAL; | |||
1147 | goto out; | |||
1148 | } | |||
1149 | ||||
1150 | /* Pass the proposed change to the file system to audit. */ | |||
1151 | error = VOP_SEEK(vp, oldoff, newoff, cred); | |||
1152 | if (error) | |||
1153 | goto out; | |||
1154 | ||||
1155 | /* Success! */ | |||
1156 | if (newoffp) | |||
1157 | *newoffp = newoff; | |||
1158 | if (flags & FOF_UPDATE_OFFSET) | |||
1159 | fp->f_offset = newoff; | |||
1160 | error = 0; | |||
1113 | 1161 | |||
1162 | out: VOP_UNLOCK(vp); | |||
1163 | return error; | |||
1164 | } | |||
1114 | 1165 | |||
1115 | /* | 1166 | /* | |
1116 | * Check that the vnode is still valid, and if so | 1167 | * Check that the vnode is still valid, and if so | |
1117 | * acquire requested lock. | 1168 | * acquire requested lock. | |
1118 | */ | 1169 | */ | |
1119 | int | 1170 | int | |
1120 | vn_lock(struct vnode *vp, int flags) | 1171 | vn_lock(struct vnode *vp, int flags) | |
1121 | { | 1172 | { | |
1122 | struct lwp *l; | 1173 | struct lwp *l; | |
1123 | int error; | 1174 | int error; | |
1124 | 1175 | |||
1125 | #if 0 | 1176 | #if 0 | |
1126 | KASSERT(vrefcnt(vp) > 0 || (vp->v_iflag & VI_ONWORKLST) != 0); | 1177 | KASSERT(vrefcnt(vp) > 0 || (vp->v_iflag & VI_ONWORKLST) != 0); |
--- src/sys/sys/file.h 2020/05/02 18:43:02 1.86
+++ src/sys/sys/file.h 2021/09/11 10:08:55 1.87
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: file.h,v 1.86 2020/05/02 18:43:02 christos Exp $ */ | 1 | /* $NetBSD: file.h,v 1.87 2021/09/11 10:08:55 riastradh Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -84,27 +84,27 @@ struct fileops { | @@ -84,27 +84,27 @@ struct fileops { | |||
84 | int (*fo_read) (struct file *, off_t *, struct uio *, | 84 | int (*fo_read) (struct file *, off_t *, struct uio *, | |
85 | kauth_cred_t, int); | 85 | kauth_cred_t, int); | |
86 | int (*fo_write) (struct file *, off_t *, struct uio *, | 86 | int (*fo_write) (struct file *, off_t *, struct uio *, | |
87 | kauth_cred_t, int); | 87 | kauth_cred_t, int); | |
88 | int (*fo_ioctl) (struct file *, u_long, void *); | 88 | int (*fo_ioctl) (struct file *, u_long, void *); | |
89 | int (*fo_fcntl) (struct file *, u_int, void *); | 89 | int (*fo_fcntl) (struct file *, u_int, void *); | |
90 | int (*fo_poll) (struct file *, int); | 90 | int (*fo_poll) (struct file *, int); | |
91 | int (*fo_stat) (struct file *, struct stat *); | 91 | int (*fo_stat) (struct file *, struct stat *); | |
92 | int (*fo_close) (struct file *); | 92 | int (*fo_close) (struct file *); | |
93 | int (*fo_kqfilter) (struct file *, struct knote *); | 93 | int (*fo_kqfilter) (struct file *, struct knote *); | |
94 | void (*fo_restart) (struct file *); | 94 | void (*fo_restart) (struct file *); | |
95 | int (*fo_mmap) (struct file *, off_t *, size_t, int, int *, | 95 | int (*fo_mmap) (struct file *, off_t *, size_t, int, int *, | |
96 | int *, struct uvm_object **, int *); | 96 | int *, struct uvm_object **, int *); | |
97 | void (*fo_spare2) (void); | 97 | int (*fo_seek) (struct file *, off_t, int, off_t *, int); | |
98 | }; | 98 | }; | |
99 | 99 | |||
100 | union file_data { | 100 | union file_data { | |
101 | struct vnode *fd_vp; // DTYPE_VNODE | 101 | struct vnode *fd_vp; // DTYPE_VNODE | |
102 | struct socket *fd_so; // DTYPE_SOCKET | 102 | struct socket *fd_so; // DTYPE_SOCKET | |
103 | struct pipe *fd_pipe; // DTYPE_PIPE | 103 | struct pipe *fd_pipe; // DTYPE_PIPE | |
104 | struct kqueue *fd_kq; // DTYPE_KQUEUE | 104 | struct kqueue *fd_kq; // DTYPE_KQUEUE | |
105 | void *fd_data; // DTYPE_MISC | 105 | void *fd_data; // DTYPE_MISC | |
106 | struct audio_file *fd_audioctx; // DTYPE_MISC (audio) | 106 | struct audio_file *fd_audioctx; // DTYPE_MISC (audio) | |
107 | struct pad_softc *fd_pad; // DTYPE_MISC (pad) | 107 | struct pad_softc *fd_pad; // DTYPE_MISC (pad) | |
108 | int fd_devunit; // DTYPE_MISC (tap) | 108 | int fd_devunit; // DTYPE_MISC (tap) | |
109 | struct bpf_d *fd_bpf; // DTYPE_MISC (bpf) | 109 | struct bpf_d *fd_bpf; // DTYPE_MISC (bpf) | |
110 | struct fcrypt *fd_fcrypt; // DTYPE_CRYPTO is not used | 110 | struct fcrypt *fd_fcrypt; // DTYPE_CRYPTO is not used |