Bug Summary

File:kern/vfs_syscalls.c
Warning:line 693, column 9
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name vfs_syscalls.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/kern/vfs_syscalls.c
1/* $OpenBSD: vfs_syscalls.c,v 1.362 2023/07/05 15:13:28 beck Exp $ */
2/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94
38 */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/namei.h>
43#include <sys/filedesc.h>
44#include <sys/conf.h>
45#include <sys/fcntl.h>
46#include <sys/file.h>
47#include <sys/stat.h>
48#include <sys/lock.h>
49#include <sys/vnode.h>
50#include <sys/mount.h>
51#include <sys/proc.h>
52#include <sys/pledge.h>
53#include <sys/uio.h>
54#include <sys/malloc.h>
55#include <sys/pool.h>
56#include <sys/ktrace.h>
57#include <sys/unistd.h>
58#include <sys/specdev.h>
59#include <sys/resourcevar.h>
60#include <sys/signalvar.h>
61
62#include <sys/syscallargs.h>
63
64extern int suid_clear;
65
66static int change_dir(struct nameidata *, struct proc *);
67
68void checkdirs(struct vnode *);
69
70int copyout_statfs(struct statfs *, void *, struct proc *);
71
72int doopenat(struct proc *, int, const char *, int, mode_t, register_t *);
73int domknodat(struct proc *, int, const char *, mode_t, dev_t);
74int dolinkat(struct proc *, int, const char *, int, const char *, int);
75int dosymlinkat(struct proc *, const char *, int, const char *);
76int dounlinkat(struct proc *, int, const char *, int);
77int dofaccessat(struct proc *, int, const char *, int, int);
78int dofstatat(struct proc *, int, const char *, struct stat *, int);
79int doreadlinkat(struct proc *, int, const char *, char *, size_t,
80 register_t *);
81int dochflagsat(struct proc *, int, const char *, u_int, int);
82int dovchflags(struct proc *, struct vnode *, u_int);
83int dofchmodat(struct proc *, int, const char *, mode_t, int);
84int dofchownat(struct proc *, int, const char *, uid_t, gid_t, int);
85int dorenameat(struct proc *, int, const char *, int, const char *);
86int domkdirat(struct proc *, int, const char *, mode_t);
87int doutimensat(struct proc *, int, const char *, struct timespec [2], int);
88int dovutimens(struct proc *, struct vnode *, struct timespec [2]);
89int dofutimens(struct proc *, int, struct timespec [2]);
90int dounmount_leaf(struct mount *, int, struct proc *);
91
92/*
93 * Virtual File System System Calls
94 */
95
96/*
97 * Mount a file system.
98 */
99int
100sys_mount(struct proc *p, void *v, register_t *retval)
101{
102 struct sys_mount_args /* {
103 syscallarg(const char *) type;
104 syscallarg(const char *) path;
105 syscallarg(int) flags;
106 syscallarg(void *) data;
107 } */ *uap = v;
108 struct vnode *vp;
109 struct mount *mp;
110 int error, mntflag = 0;
111 char fstypename[MFSNAMELEN16];
112 char fspath[MNAMELEN90];
113 struct nameidata nd;
114 struct vfsconf *vfsp;
115 int flags = SCARG(uap, flags)((uap)->flags.le.datum);
116 void *args = NULL((void *)0);
117
118 if ((error = suser(p)))
119 return (error);
120
121 /*
122 * Mount points must fit in MNAMELEN, not MAXPATHLEN.
123 */
124 error = copyinstr(SCARG(uap, path)((uap)->path.le.datum), fspath, MNAMELEN90, NULL((void *)0));
125 if (error)
126 return(error);
127
128 /*
129 * Get vnode to be covered
130 */
131 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_SYSSPACE, -100, fspath
, p)
;
132 if ((error = namei(&nd)) != 0)
133 goto fail;
134 vp = nd.ni_vp;
135 if (flags & MNT_UPDATE0x00010000) {
136 if ((vp->v_flag & VROOT0x0001) == 0) {
137 vput(vp);
138 error = EINVAL22;
139 goto fail;
140 }
141 mp = vp->v_mount;
142 vfsp = mp->mnt_vfc;
143
144 args = malloc(vfsp->vfc_datasize, M_TEMP127, M_WAITOK0x0001 | M_ZERO0x0008);
145 error = copyin(SCARG(uap, data)((uap)->data.le.datum), args, vfsp->vfc_datasize);
146 if (error) {
147 vput(vp);
148 goto fail;
149 }
150
151 mntflag = mp->mnt_flag;
152 /*
153 * We only allow the filesystem to be reloaded if it
154 * is currently mounted read-only.
155 */
156 if ((flags & MNT_RELOAD0x00040000) &&
157 ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0)) {
158 vput(vp);
159 error = EOPNOTSUPP45; /* Needs translation */
160 goto fail;
161 }
162
163 if ((error = vfs_busy(mp, VB_READ0x01|VB_NOWAIT0x04)) != 0) {
164 vput(vp);
165 goto fail;
166 }
167 mp->mnt_flag |= flags & (MNT_RELOAD0x00040000 | MNT_UPDATE0x00010000);
168 goto update;
169 }
170 /*
171 * Do not allow disabling of permission checks unless exec and access to
172 * device files is disabled too.
173 */
174 if ((flags & MNT_NOPERM0x00000020) &&
175 (flags & (MNT_NODEV0x00000010 | MNT_NOEXEC0x00000004)) != (MNT_NODEV0x00000010 | MNT_NOEXEC0x00000004)) {
176 vput(vp);
177 error = EPERM1;
178 goto fail;
179 }
180 if ((error = vinvalbuf(vp, V_SAVE0x0001, p->p_ucred, p, 0, INFSLP0xffffffffffffffffULL)) != 0) {
181 vput(vp);
182 goto fail;
183 }
184 if (vp->v_type != VDIR) {
185 vput(vp);
186 goto fail;
187 }
188 error = copyinstr(SCARG(uap, type)((uap)->type.le.datum), fstypename, MFSNAMELEN16, NULL((void *)0));
189 if (error) {
190 vput(vp);
191 goto fail;
192 }
193 vfsp = vfs_byname(fstypename);
194 if (vfsp == NULL((void *)0)) {
195 vput(vp);
196 error = EOPNOTSUPP45;
197 goto fail;
198 }
199
200 args = malloc(vfsp->vfc_datasize, M_TEMP127, M_WAITOK0x0001 | M_ZERO0x0008);
201 error = copyin(SCARG(uap, data)((uap)->data.le.datum), args, vfsp->vfc_datasize);
202 if (error) {
203 vput(vp);
204 goto fail;
205 }
206
207 if (vp->v_mountedherev_un.vu_mountedhere != NULL((void *)0)) {
208 vput(vp);
209 error = EBUSY16;
210 goto fail;
211 }
212
213 /*
214 * Allocate and initialize the file system.
215 */
216 mp = vfs_mount_alloc(vp, vfsp);
217 mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
218
219update:
220 /* Ensure that the parent mountpoint does not get unmounted. */
221 error = vfs_busy(vp->v_mount, VB_READ0x01|VB_NOWAIT0x04|VB_DUPOK0x10);
222 if (error) {
223 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
224 mp->mnt_flag = mntflag;
225 vfs_unbusy(mp);
226 } else {
227 vfs_unbusy(mp);
228 vfs_mount_free(mp);
229 }
230 vput(vp);
231 goto fail;
232 }
233
234 /*
235 * Set the mount level flags.
236 */
237 if (flags & MNT_RDONLY0x00000001)
238 mp->mnt_flag |= MNT_RDONLY0x00000001;
239 else if (mp->mnt_flag & MNT_RDONLY0x00000001)
240 mp->mnt_flag |= MNT_WANTRDWR0x02000000;
241 mp->mnt_flag &=~ (MNT_NOSUID0x00000008 | MNT_NOEXEC0x00000004 | MNT_WXALLOWED0x00000800 | MNT_NODEV0x00000010 |
242 MNT_SYNCHRONOUS0x00000002 | MNT_ASYNC0x00000040 | MNT_NOATIME0x00008000 | MNT_NOPERM0x00000020 | MNT_FORCE0x00080000);
243 mp->mnt_flag |= flags & (MNT_NOSUID0x00000008 | MNT_NOEXEC0x00000004 | MNT_WXALLOWED0x00000800 |
244 MNT_NODEV0x00000010 | MNT_SYNCHRONOUS0x00000002 | MNT_ASYNC0x00000040 | MNT_NOATIME0x00008000 | MNT_NOPERM0x00000020 |
245 MNT_FORCE0x00080000);
246 /*
247 * Mount the filesystem.
248 */
249 error = VFS_MOUNT(mp, fspath, args, &nd, p)(*(mp)->mnt_op->vfs_mount)(mp, fspath, args, &nd, p
)
;
250 if (!error) {
251 mp->mnt_stat.f_ctime = gettime();
252 }
253 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
254 vfs_unbusy(vp->v_mount);
255 vput(vp);
256 if (mp->mnt_flag & MNT_WANTRDWR0x02000000)
257 mp->mnt_flag &= ~MNT_RDONLY0x00000001;
258 mp->mnt_flag &= ~MNT_OP_FLAGS(0x00010000 | 0x00040000 | 0x00080000 | 0x02000000);
259 if (error)
260 mp->mnt_flag = mntflag;
261
262 if ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0) {
263 if (mp->mnt_syncer == NULL((void *)0))
264 error = vfs_allocate_syncvnode(mp);
265 } else {
266 if (mp->mnt_syncer != NULL((void *)0))
267 vgone(mp->mnt_syncer);
268 mp->mnt_syncer = NULL((void *)0);
269 }
270
271 vfs_unbusy(mp);
272 goto fail;
273 }
274
275 mp->mnt_flag &= ~MNT_OP_FLAGS(0x00010000 | 0x00040000 | 0x00080000 | 0x02000000);
276 vp->v_mountedherev_un.vu_mountedhere = mp;
277
278 /*
279 * Put the new filesystem on the mount list after root.
280 */
281 cache_purge(vp);
282 if (!error) {
283 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list)do { (mp)->mnt_list.tqe_next = ((void *)0); (mp)->mnt_list
.tqe_prev = (&mountlist)->tqh_last; *(&mountlist)->
tqh_last = (mp); (&mountlist)->tqh_last = &(mp)->
mnt_list.tqe_next; } while (0)
;
284 checkdirs(vp);
285 vfs_unbusy(vp->v_mount);
286 VOP_UNLOCK(vp);
287 if ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0)
288 error = vfs_allocate_syncvnode(mp);
289 vfs_unbusy(mp);
290 (void) VFS_STATFS(mp, &mp->mnt_stat, p)(*(mp)->mnt_op->vfs_statfs)(mp, &mp->mnt_stat, p
)
;
291 if ((error = VFS_START(mp, 0, p)(*(mp)->mnt_op->vfs_start)(mp, 0, p)) != 0)
292 vrele(vp);
293 } else {
294 mp->mnt_vnodecovered->v_mountedherev_un.vu_mountedhere = NULL((void *)0);
295 vfs_unbusy(mp);
296 vfs_mount_free(mp);
297 vfs_unbusy(vp->v_mount);
298 vput(vp);
299 }
300fail:
301 if (args)
302 free(args, M_TEMP127, vfsp->vfc_datasize);
303 return (error);
304}
305
306/*
307 * Scan all active processes to see if any of them have a current
308 * or root directory onto which the new filesystem has just been
309 * mounted. If so, replace them with the new mount point, keeping
310 * track of how many were replaced. That's the number of references
311 * the old vnode had that we've replaced, so finish by vrele()'ing
312 * it that many times. This puts off any possible sleeping until
313 * we've finished walking the allprocess list.
314 */
315void
316checkdirs(struct vnode *olddp)
317{
318 struct filedesc *fdp;
319 struct vnode *newdp;
320 struct process *pr;
321 u_int free_count = 0;
322
323 if (olddp->v_usecount == 1)
324 return;
325 if (VFS_ROOT(olddp->v_mountedhere, &newdp)(*(olddp->v_un.vu_mountedhere)->mnt_op->vfs_root)(olddp
->v_un.vu_mountedhere, &newdp)
)
326 panic("mount: lost mount");
327 LIST_FOREACH(pr, &allprocess, ps_list)for((pr) = ((&allprocess)->lh_first); (pr)!= ((void *)
0); (pr) = ((pr)->ps_list.le_next))
{
328 fdp = pr->ps_fd;
329 if (fdp->fd_cdir == olddp) {
330 free_count++;
331 vref(newdp);
332 fdp->fd_cdir = newdp;
333 }
334 if (fdp->fd_rdir == olddp) {
335 free_count++;
336 vref(newdp);
337 fdp->fd_rdir = newdp;
338 }
339 }
340 if (rootvnode == olddp) {
341 free_count++;
342 vref(newdp);
343 rootvnode = newdp;
344 }
345 while (free_count-- > 0)
346 vrele(olddp);
347 vput(newdp);
348}
349
350/*
351 * Unmount a file system.
352 *
353 * Note: unmount takes a path to the vnode mounted on as argument,
354 * not special file (as before).
355 */
356int
357sys_unmount(struct proc *p, void *v, register_t *retval)
358{
359 struct sys_unmount_args /* {
360 syscallarg(const char *) path;
361 syscallarg(int) flags;
362 } */ *uap = v;
363 struct vnode *vp;
364 struct mount *mp;
365 int error;
366 struct nameidata nd;
367
368 if ((error = suser(p)) != 0)
369 return (error);
370
371 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
372 SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
;
373 if ((error = namei(&nd)) != 0)
374 return (error);
375 vp = nd.ni_vp;
376 mp = vp->v_mount;
377
378 /*
379 * Don't allow unmounting the root file system.
380 */
381 if (mp->mnt_flag & MNT_ROOTFS0x00004000) {
382 vput(vp);
383 return (EINVAL22);
384 }
385
386 /*
387 * Must be the root of the filesystem
388 */
389 if ((vp->v_flag & VROOT0x0001) == 0) {
390 vput(vp);
391 return (EINVAL22);
392 }
393 vput(vp);
394
395 if (vfs_busy(mp, VB_WRITE0x02|VB_WAIT0x08))
396 return (EBUSY16);
397
398 return (dounmount(mp, SCARG(uap, flags)((uap)->flags.le.datum) & MNT_FORCE0x00080000, p));
399}
400
401/*
402 * Do the actual file system unmount.
403 */
404int
405dounmount(struct mount *mp, int flags, struct proc *p)
406{
407 SLIST_HEAD(, mount)struct { struct mount *slh_first; } mplist;
408 struct mount *nmp;
409 int error;
410
411 SLIST_INIT(&mplist){ ((&mplist)->slh_first) = ((void *)0); };
412 SLIST_INSERT_HEAD(&mplist, mp, mnt_dounmount)do { (mp)->mnt_dounmount.sle_next = (&mplist)->slh_first
; (&mplist)->slh_first = (mp); } while (0)
;
413
414 /*
415 * Collect nested mount points. This takes advantage of the mount list
416 * being ordered - nested mount points come after their parent.
417 */
418 while ((mp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next)) != NULL((void *)0)) {
419 SLIST_FOREACH(nmp, &mplist, mnt_dounmount)for((nmp) = ((&mplist)->slh_first); (nmp) != ((void *)
0); (nmp) = ((nmp)->mnt_dounmount.sle_next))
{
420 if (mp->mnt_vnodecovered == NULLVP((struct vnode *)((void *)0)) ||
421 mp->mnt_vnodecovered->v_mount != nmp)
422 continue;
423
424 if ((flags & MNT_FORCE0x00080000) == 0) {
425 error = EBUSY16;
426 goto err;
427 }
428 error = vfs_busy(mp, VB_WRITE0x02|VB_WAIT0x08|VB_DUPOK0x10);
429 if (error) {
430 if ((flags & MNT_DOOMED0x08000000)) {
431 /*
432 * If the mount point was busy due to
433 * being unmounted, it has been removed
434 * from the mount list already.
435 * Restart the iteration from the last
436 * collected busy entry.
437 */
438 mp = SLIST_FIRST(&mplist)((&mplist)->slh_first);
439 break;
440 }
441 goto err;
442 }
443 SLIST_INSERT_HEAD(&mplist, mp, mnt_dounmount)do { (mp)->mnt_dounmount.sle_next = (&mplist)->slh_first
; (&mplist)->slh_first = (mp); } while (0)
;
444 break;
445 }
446 }
447
448 /*
449 * Nested mount points cannot appear during this loop as mounting
450 * requires a read lock for the parent mount point.
451 */
452 while ((mp = SLIST_FIRST(&mplist)((&mplist)->slh_first)) != NULL((void *)0)) {
453 SLIST_REMOVE(&mplist, mp, mount, mnt_dounmount)do { if ((&mplist)->slh_first == (mp)) { do { ((&mplist
))->slh_first = ((&mplist))->slh_first->mnt_dounmount
.sle_next; } while (0); } else { struct mount *curelm = (&
mplist)->slh_first; while (curelm->mnt_dounmount.sle_next
!= (mp)) curelm = curelm->mnt_dounmount.sle_next; curelm->
mnt_dounmount.sle_next = curelm->mnt_dounmount.sle_next->
mnt_dounmount.sle_next; } ((mp)->mnt_dounmount.sle_next) =
((void *)-1); } while (0)
;
454 error = dounmount_leaf(mp, flags, p);
455 if (error)
456 goto err;
457 }
458 return (0);
459
460err:
461 while ((mp = SLIST_FIRST(&mplist)((&mplist)->slh_first)) != NULL((void *)0)) {
462 SLIST_REMOVE(&mplist, mp, mount, mnt_dounmount)do { if ((&mplist)->slh_first == (mp)) { do { ((&mplist
))->slh_first = ((&mplist))->slh_first->mnt_dounmount
.sle_next; } while (0); } else { struct mount *curelm = (&
mplist)->slh_first; while (curelm->mnt_dounmount.sle_next
!= (mp)) curelm = curelm->mnt_dounmount.sle_next; curelm->
mnt_dounmount.sle_next = curelm->mnt_dounmount.sle_next->
mnt_dounmount.sle_next; } ((mp)->mnt_dounmount.sle_next) =
((void *)-1); } while (0)
;
463 vfs_unbusy(mp);
464 }
465 return (error);
466}
467
468int
469dounmount_leaf(struct mount *mp, int flags, struct proc *p)
470{
471 struct vnode *coveredvp;
472 struct vnode *vp, *nvp;
473 int error;
474 int hadsyncer = 0;
475
476 mp->mnt_flag &=~ MNT_ASYNC0x00000040;
477 cache_purgevfs(mp); /* remove cache entries for this file sys */
478 if (mp->mnt_syncer != NULL((void *)0)) {
479 hadsyncer = 1;
480 vgone(mp->mnt_syncer);
481 mp->mnt_syncer = NULL((void *)0);
482 }
483
484 /*
485 * Before calling file system unmount, make sure
486 * all unveils to vnodes in here are dropped.
487 */
488 TAILQ_FOREACH_SAFE(vp , &mp->mnt_vnodelist, v_mntvnodes, nvp)for ((vp) = ((&mp->mnt_vnodelist)->tqh_first); (vp)
!= ((void *)0) && ((nvp) = ((vp)->v_mntvnodes.tqe_next
), 1); (vp) = (nvp))
{
489 unveil_removevnode(vp);
490 }
491
492 if (((mp->mnt_flag & MNT_RDONLY0x00000001) ||
493 (error = VFS_SYNC(mp, MNT_WAIT, 0, p->p_ucred, p)(*(mp)->mnt_op->vfs_sync)(mp, 1, 0, p->p_ucred, p)) == 0) ||
494 (flags & MNT_FORCE0x00080000))
495 error = VFS_UNMOUNT(mp, flags, p)(*(mp)->mnt_op->vfs_unmount)(mp, flags, p);
496
497 if (error && !(flags & MNT_DOOMED0x08000000)) {
498 if ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0 && hadsyncer)
499 (void) vfs_allocate_syncvnode(mp);
500 vfs_unbusy(mp);
501 return (error);
502 }
503
504 TAILQ_REMOVE(&mountlist, mp, mnt_list)do { if (((mp)->mnt_list.tqe_next) != ((void *)0)) (mp)->
mnt_list.tqe_next->mnt_list.tqe_prev = (mp)->mnt_list.tqe_prev
; else (&mountlist)->tqh_last = (mp)->mnt_list.tqe_prev
; *(mp)->mnt_list.tqe_prev = (mp)->mnt_list.tqe_next; (
(mp)->mnt_list.tqe_prev) = ((void *)-1); ((mp)->mnt_list
.tqe_next) = ((void *)-1); } while (0)
;
505 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP((struct vnode *)((void *)0))) {
506 coveredvp->v_mountedherev_un.vu_mountedhere = NULL((void *)0);
507 vrele(coveredvp);
508 }
509
510 if (!TAILQ_EMPTY(&mp->mnt_vnodelist)(((&mp->mnt_vnodelist)->tqh_first) == ((void *)0)))
511 panic("unmount: dangling vnode");
512
513 vfs_unbusy(mp);
514 vfs_mount_free(mp);
515
516 return (0);
517}
518
519/*
520 * Sync each mounted filesystem.
521 */
522int
523sys_sync(struct proc *p, void *v, register_t *retval)
524{
525 struct mount *mp;
526 int asyncflag;
527
528 TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list)for((mp) = (*(((struct mntlist *)((&mountlist)->tqh_last
))->tqh_last)); (mp) != ((void *)0); (mp) = (*(((struct mntlist
*)((mp)->mnt_list.tqe_prev))->tqh_last)))
{
529 if (vfs_busy(mp, VB_READ0x01|VB_NOWAIT0x04))
530 continue;
531 if ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0) {
532 asyncflag = mp->mnt_flag & MNT_ASYNC0x00000040;
533 mp->mnt_flag &= ~MNT_ASYNC0x00000040;
534 uvm_vnp_sync(mp);
535 VFS_SYNC(mp, MNT_NOWAIT, 0, p->p_ucred, p)(*(mp)->mnt_op->vfs_sync)(mp, 2, 0, p->p_ucred, p);
536 if (asyncflag)
537 mp->mnt_flag |= MNT_ASYNC0x00000040;
538 }
539 vfs_unbusy(mp);
540 }
541
542 return (0);
543}
544
545/*
546 * Change filesystem quotas.
547 */
548int
549sys_quotactl(struct proc *p, void *v, register_t *retval)
550{
551 struct sys_quotactl_args /* {
552 syscallarg(const char *) path;
553 syscallarg(int) cmd;
554 syscallarg(int) uid;
555 syscallarg(char *) arg;
556 } */ *uap = v;
557 struct mount *mp;
558 int error;
559 struct nameidata nd;
560
561 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040, UIO_USERSPACE, -100, ((uap)->
path.le.datum), p)
;
562 if ((error = namei(&nd)) != 0)
563 return (error);
564 mp = nd.ni_vp->v_mount;
565 vrele(nd.ni_vp);
566 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),(*(mp)->mnt_op->vfs_quotactl)(mp, ((uap)->cmd.le.datum
), ((uap)->uid.le.datum), ((uap)->arg.le.datum), p)
567 SCARG(uap, arg), p)(*(mp)->mnt_op->vfs_quotactl)(mp, ((uap)->cmd.le.datum
), ((uap)->uid.le.datum), ((uap)->arg.le.datum), p)
);
568}
569
570int
571copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p)
572{
573 size_t co_sz1 = offsetof(struct statfs, f_fsid)__builtin_offsetof(struct statfs, f_fsid);
574 size_t co_off2 = co_sz1 + sizeof(fsid_t);
575 size_t co_sz2 = sizeof(struct statfs) - co_off2;
576 char *s, *d;
577 int error;
578
579 /* Don't let non-root see filesystem id (for NFS security) */
580 if (suser(p)) {
581 fsid_t fsid;
582
583 s = (char *)sp;
584 d = (char *)uaddr;
585
586 memset(&fsid, 0, sizeof(fsid))__builtin_memset((&fsid), (0), (sizeof(fsid)));
587
588 if ((error = copyout(s, d, co_sz1)) != 0)
589 return (error);
590 if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0)
591 return (error);
592 return (copyout(s + co_off2, d + co_off2, co_sz2));
593 }
594
595 return (copyout(sp, uaddr, sizeof(*sp)));
596}
597
598/*
599 * Get filesystem statistics.
600 */
601int
602sys_statfs(struct proc *p, void *v, register_t *retval)
603{
604 struct sys_statfs_args /* {
605 syscallarg(const char *) path;
606 syscallarg(struct statfs *) buf;
607 } */ *uap = v;
608 struct mount *mp;
609 struct statfs *sp;
610 int error;
611 struct nameidata nd;
612
613 NDINIT(&nd, LOOKUP, FOLLOW | BYPASSUNVEIL, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x400000, UIO_USERSPACE, -100, (
(uap)->path.le.datum), p)
614 SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040 | 0x400000, UIO_USERSPACE, -100, (
(uap)->path.le.datum), p)
;
615 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
616 nd.ni_unveil = UNVEIL_READ0x01;
617 if ((error = namei(&nd)) != 0)
618 return (error);
619 mp = nd.ni_vp->v_mount;
620 sp = &mp->mnt_stat;
621 vrele(nd.ni_vp);
622 if ((error = VFS_STATFS(mp, sp, p)(*(mp)->mnt_op->vfs_statfs)(mp, sp, p)) != 0)
623 return (error);
624 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK0x0400ffff;
625
626 return (copyout_statfs(sp, SCARG(uap, buf)((uap)->buf.le.datum), p));
627}
628
629/*
630 * Get filesystem statistics.
631 */
632int
633sys_fstatfs(struct proc *p, void *v, register_t *retval)
634{
635 struct sys_fstatfs_args /* {
636 syscallarg(int) fd;
637 syscallarg(struct statfs *) buf;
638 } */ *uap = v;
639 struct file *fp;
640 struct mount *mp;
641 struct statfs *sp;
642 int error;
643
644 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
645 return (error);
646 mp = ((struct vnode *)fp->f_data)->v_mount;
647 if (!mp) {
648 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
649 return (ENOENT2);
650 }
651 sp = &mp->mnt_stat;
652 error = VFS_STATFS(mp, sp, p)(*(mp)->mnt_op->vfs_statfs)(mp, sp, p);
653 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
654 if (error)
655 return (error);
656 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK0x0400ffff;
657
658 return (copyout_statfs(sp, SCARG(uap, buf)((uap)->buf.le.datum), p));
659}
660
661/*
662 * Get statistics on all filesystems.
663 */
664int
665sys_getfsstat(struct proc *p, void *v, register_t *retval)
666{
667 struct sys_getfsstat_args /* {
668 syscallarg(struct statfs *) buf;
669 syscallarg(size_t) bufsize;
670 syscallarg(int) flags;
671 } */ *uap = v;
672 struct mount *mp;
673 struct statfs *sp;
674 struct statfs *sfsp;
675 size_t count, maxcount;
676 int error, flags = SCARG(uap, flags)((uap)->flags.le.datum);
677
678 maxcount = SCARG(uap, bufsize)((uap)->bufsize.le.datum) / sizeof(struct statfs);
679 sfsp = SCARG(uap, buf)((uap)->buf.le.datum);
680 count = 0;
681
682 TAILQ_FOREACH(mp, &mountlist, mnt_list)for((mp) = ((&mountlist)->tqh_first); (mp) != ((void *
)0); (mp) = ((mp)->mnt_list.tqe_next))
{
683 if (vfs_busy(mp, VB_READ0x01|VB_NOWAIT0x04))
684 continue;
685 if (sfsp && count < maxcount) {
686 sp = &mp->mnt_stat;
687
688 /* Refresh stats unless MNT_NOWAIT is specified */
689 if (flags != MNT_NOWAIT2 &&
690 flags != MNT_LAZY3 &&
691 (flags == MNT_WAIT1 ||
692 flags == 0) &&
693 (error = VFS_STATFS(mp, sp, p)(*(mp)->mnt_op->vfs_statfs)(mp, sp, p))) {
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
694 vfs_unbusy(mp);
695 continue;
696 }
697
698 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK0x0400ffff;
699#if notyet
700 if (mp->mnt_flag & MNT_SOFTDEP0x04000000)
701 sp->f_eflags = STATFS_SOFTUPD;
702#endif
703 error = (copyout_statfs(sp, sfsp, p));
704 if (error) {
705 vfs_unbusy(mp);
706 return (error);
707 }
708 sfsp++;
709 }
710 count++;
711 vfs_unbusy(mp);
712 }
713
714 if (sfsp && count > maxcount)
715 *retval = maxcount;
716 else
717 *retval = count;
718
719 return (0);
720}
721
722/*
723 * Change current working directory to a given file descriptor.
724 */
725int
726sys_fchdir(struct proc *p, void *v, register_t *retval)
727{
728 struct sys_fchdir_args /* {
729 syscallarg(int) fd;
730 } */ *uap = v;
731 struct filedesc *fdp = p->p_fd;
732 struct vnode *vp, *tdp, *old_cdir;
733 struct mount *mp;
734 struct file *fp;
735 int error;
736
737 if ((fp = fd_getfile(fdp, SCARG(uap, fd)((uap)->fd.le.datum))) == NULL((void *)0))
738 return (EBADF9);
739 vp = fp->f_data;
740 if (fp->f_type != DTYPE_VNODE1 || vp->v_type != VDIR) {
741 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
742 return (ENOTDIR20);
743 }
744 vref(vp);
745 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
746 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
747 error = VOP_ACCESS(vp, VEXEC00100, p->p_ucred, p);
748
749 while (!error && (mp = vp->v_mountedherev_un.vu_mountedhere) != NULL((void *)0)) {
750 if (vfs_busy(mp, VB_READ0x01|VB_WAIT0x08))
751 continue;
752 error = VFS_ROOT(mp, &tdp)(*(mp)->mnt_op->vfs_root)(mp, &tdp);
753 vfs_unbusy(mp);
754 if (error)
755 break;
756 vput(vp);
757 vp = tdp;
758 }
759 if (error) {
760 vput(vp);
761 return (error);
762 }
763 VOP_UNLOCK(vp);
764 old_cdir = fdp->fd_cdir;
765 fdp->fd_cdir = vp;
766 vrele(old_cdir);
767 return (0);
768}
769
770/*
771 * Change current working directory (``.'').
772 */
773int
774sys_chdir(struct proc *p, void *v, register_t *retval)
775{
776 struct sys_chdir_args /* {
777 syscallarg(const char *) path;
778 } */ *uap = v;
779 struct filedesc *fdp = p->p_fd;
780 struct vnode *old_cdir;
781 int error;
782 struct nameidata nd;
783
784 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
785 SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
;
786 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
787 nd.ni_unveil = UNVEIL_READ0x01;
788 if ((error = change_dir(&nd, p)) != 0)
789 return (error);
790 old_cdir = fdp->fd_cdir;
791 fdp->fd_cdir = nd.ni_vp;
792 vrele(old_cdir);
793 return (0);
794}
795
796/*
797 * Change notion of root (``/'') directory.
798 */
799int
800sys_chroot(struct proc *p, void *v, register_t *retval)
801{
802 struct sys_chroot_args /* {
803 syscallarg(const char *) path;
804 } */ *uap = v;
805 struct filedesc *fdp = p->p_fd;
806 struct vnode *old_cdir, *old_rdir;
807 int error;
808 struct nameidata nd;
809
810 if ((error = suser(p)) != 0)
811 return (error);
812 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
813 SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
;
814 if ((error = change_dir(&nd, p)) != 0)
815 return (error);
816 if (fdp->fd_rdir != NULL((void *)0)) {
817 /*
818 * A chroot() done inside a changed root environment does
819 * an automatic chdir to avoid the out-of-tree experience.
820 */
821 vref(nd.ni_vp);
822 old_rdir = fdp->fd_rdir;
823 old_cdir = fdp->fd_cdir;
824 fdp->fd_rdir = fdp->fd_cdir = nd.ni_vp;
825 vrele(old_rdir);
826 vrele(old_cdir);
827 } else
828 fdp->fd_rdir = nd.ni_vp;
829 atomic_setbits_intx86_atomic_setbits_u32(&p->p_p->ps_flags, PS_CHROOT0x01000000);
830 return (0);
831}
832
833/*
834 * Common routine for chroot and chdir.
835 */
836static int
837change_dir(struct nameidata *ndp, struct proc *p)
838{
839 struct vnode *vp;
840 int error;
841
842 if ((error = namei(ndp)) != 0)
843 return (error);
844 vp = ndp->ni_vp;
845 if (vp->v_type != VDIR)
846 error = ENOTDIR20;
847 else
848 error = VOP_ACCESS(vp, VEXEC00100, p->p_ucred, p);
849 if (error)
850 vput(vp);
851 else
852 VOP_UNLOCK(vp);
853 return (error);
854}
855
856int
857sys___realpath(struct proc *p, void *v, register_t *retval)
858{
859 struct sys___realpath_args /* {
860 syscallarg(const char *) pathname;
861 syscallarg(char *) resolved;
862 } */ *uap = v;
863 char *pathname;
864 char *rpbuf;
865 struct nameidata nd;
866 size_t pathlen;
867 int error = 0;
868
869 if (SCARG(uap, pathname)((uap)->pathname.le.datum) == NULL((void *)0))
870 return (EINVAL22);
871
872 pathname = pool_get(&namei_pool, PR_WAITOK0x0001);
873 rpbuf = pool_get(&namei_pool, PR_WAITOK0x0001);
874
875 if ((error = copyinstr(SCARG(uap, pathname)((uap)->pathname.le.datum), pathname, MAXPATHLEN1024,
876 &pathlen)))
877 goto end;
878
879 if (pathlen == 1) { /* empty string "" */
880 error = ENOENT2;
881 goto end;
882 }
883 if (pathlen < 2) {
884 error = EINVAL22;
885 goto end;
886 }
887
888 /* Get cwd for relative path if needed, prepend to rpbuf */
889 rpbuf[0] = '\0';
890 if (pathname[0] != '/') {
891 int cwdlen = MAXPATHLEN1024 * 4; /* for vfs_getcwd_common */
892 char *cwdbuf, *bp;
893
894 cwdbuf = malloc(cwdlen, M_TEMP127, M_WAITOK0x0001);
895
896 /* vfs_getcwd_common fills this in backwards */
897 bp = &cwdbuf[cwdlen - 1];
898 *bp = '\0';
899
900 error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL((void *)0), &bp, cwdbuf,
901 cwdlen/2, GETCWD_CHECK_ACCESS0x0001, p);
902
903 if (error) {
904 free(cwdbuf, M_TEMP127, cwdlen);
905 goto end;
906 }
907
908 if (strlcpy(rpbuf, bp, MAXPATHLEN1024) >= MAXPATHLEN1024) {
909 free(cwdbuf, M_TEMP127, cwdlen);
910 error = ENAMETOOLONG63;
911 goto end;
912 }
913
914 free(cwdbuf, M_TEMP127, cwdlen);
915 }
916
917 NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME | REALPATH, UIO_SYSSPACE,ndinitat(&nd, 0, 0x0040 | 0x000800 | 0x020000, UIO_SYSSPACE
, -100, pathname, p)
918 pathname, p)ndinitat(&nd, 0, 0x0040 | 0x000800 | 0x020000, UIO_SYSSPACE
, -100, pathname, p)
;
919
920 nd.ni_cnd.cn_rpbuf = rpbuf;
921 nd.ni_cnd.cn_rpi = strlen(rpbuf);
922
923 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
924 nd.ni_unveil = UNVEIL_READ0x01;
925 if ((error = namei(&nd)) != 0)
926 goto end;
927
928 /* release reference from namei */
929 if (nd.ni_vp)
930 vrele(nd.ni_vp);
931
932 error = copyoutstr(nd.ni_cnd.cn_rpbuf, SCARG(uap, resolved)((uap)->resolved.le.datum),
933 MAXPATHLEN1024, NULL((void *)0));
934
935#ifdef KTRACE1
936 if (KTRPOINT(p, KTR_NAMEI)((p)->p_p->ps_traceflag & (1<<(3)) &&
((p)->p_flag & 0x00000001) == 0)
)
937 ktrnamei(p, nd.ni_cnd.cn_rpbuf);
938#endif
939 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
940end:
941 pool_put(&namei_pool, rpbuf);
942 pool_put(&namei_pool, pathname);
943 return (error);
944}
945
946int
947sys_unveil(struct proc *p, void *v, register_t *retval)
948{
949 struct sys_unveil_args /* {
950 syscallarg(const char *) path;
951 syscallarg(const char *) permissions;
952 } */ *uap = v;
953 struct process *pr = p->p_p;
954 char *pathname, *c;
955 struct nameidata nd;
956 size_t pathlen;
957 char permissions[5];
958 int error, allow;
959
960 if (SCARG(uap, path)((uap)->path.le.datum) == NULL((void *)0) && SCARG(uap, permissions)((uap)->permissions.le.datum) == NULL((void *)0)) {
961 pr->ps_uvdone = 1;
962 return (0);
963 }
964
965 if (pr->ps_uvdone != 0)
966 return EPERM1;
967
968 error = copyinstr(SCARG(uap, permissions)((uap)->permissions.le.datum), permissions,
969 sizeof(permissions), NULL((void *)0));
970 if (error)
971 return (error);
972 pathname = pool_get(&namei_pool, PR_WAITOK0x0001);
973 error = copyinstr(SCARG(uap, path)((uap)->path.le.datum), pathname, MAXPATHLEN1024, &pathlen);
974 if (error)
975 goto end;
976
977#ifdef KTRACE1
978 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
979 ktrstruct(p, "unveil", permissions, strlen(permissions));
980#endif
981 if (pathlen < 2) {
982 error = EINVAL22;
983 goto end;
984 }
985
986 /* find root "/" or "//" */
987 for (c = pathname; *c != '\0'; c++) {
988 if (*c != '/')
989 break;
990 }
991 if (*c == '\0')
992 /* root directory */
993 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME,ndinitat(&nd, 0, 0x0040 | 0x0004 | 0x000800, UIO_SYSSPACE
, -100, pathname, p)
994 UIO_SYSSPACE, pathname, p)ndinitat(&nd, 0, 0x0040 | 0x0004 | 0x000800, UIO_SYSSPACE
, -100, pathname, p)
;
995 else
996 NDINIT(&nd, CREATE, FOLLOW | LOCKLEAF | LOCKPARENT | SAVENAME,ndinitat(&nd, 1, 0x0040 | 0x0004 | 0x0008 | 0x000800, UIO_SYSSPACE
, -100, pathname, p)
997 UIO_SYSSPACE, pathname, p)ndinitat(&nd, 1, 0x0040 | 0x0004 | 0x0008 | 0x000800, UIO_SYSSPACE
, -100, pathname, p)
;
998
999 nd.ni_pledge = PLEDGE_UNVEIL0x0000001000000000ULL;
1000 if ((error = namei(&nd)) != 0)
1001 goto end;
1002
1003 /*
1004 * XXX Any access to the file or directory will allow us to
1005 * pledge path it
1006 */
1007 allow = ((nd.ni_vp &&
1008 (VOP_ACCESS(nd.ni_vp, VREAD00400, p->p_ucred, p) == 0 ||
1009 VOP_ACCESS(nd.ni_vp, VWRITE00200, p->p_ucred, p) == 0 ||
1010 VOP_ACCESS(nd.ni_vp, VEXEC00100, p->p_ucred, p) == 0)) ||
1011 (nd.ni_dvp &&
1012 (VOP_ACCESS(nd.ni_dvp, VREAD00400, p->p_ucred, p) == 0 ||
1013 VOP_ACCESS(nd.ni_dvp, VWRITE00200, p->p_ucred, p) == 0 ||
1014 VOP_ACCESS(nd.ni_dvp, VEXEC00100, p->p_ucred, p) == 0)));
1015
1016 /* release lock from namei, but keep ref */
1017 if (nd.ni_vp)
1018 VOP_UNLOCK(nd.ni_vp);
1019 if (nd.ni_dvp && nd.ni_dvp != nd.ni_vp)
1020 VOP_UNLOCK(nd.ni_dvp);
1021
1022 if (allow)
1023 error = unveil_add(p, &nd, permissions);
1024 else
1025 error = EPERM1;
1026
1027 /* release vref from namei, but not vref from unveil_add */
1028 if (nd.ni_vp)
1029 vrele(nd.ni_vp);
1030 if (nd.ni_dvp)
1031 vrele(nd.ni_dvp);
1032
1033 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
1034end:
1035 pool_put(&namei_pool, pathname);
1036
1037 return (error);
1038}
1039
1040/*
1041 * Check permissions, allocate an open file structure,
1042 * and call the device open routine if any.
1043 */
1044int
1045sys_open(struct proc *p, void *v, register_t *retval)
1046{
1047 struct sys_open_args /* {
1048 syscallarg(const char *) path;
1049 syscallarg(int) flags;
1050 syscallarg(mode_t) mode;
1051 } */ *uap = v;
1052
1053 return (doopenat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, flags)((uap)->flags.le.datum),
1054 SCARG(uap, mode)((uap)->mode.le.datum), retval));
1055}
1056
1057int
1058sys_openat(struct proc *p, void *v, register_t *retval)
1059{
1060 struct sys_openat_args /* {
1061 syscallarg(int) fd;
1062 syscallarg(const char *) path;
1063 syscallarg(int) flags;
1064 syscallarg(mode_t) mode;
1065 } */ *uap = v;
1066
1067 return (doopenat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
1068 SCARG(uap, flags)((uap)->flags.le.datum), SCARG(uap, mode)((uap)->mode.le.datum), retval));
1069}
1070
1071int
1072doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
1073 register_t *retval)
1074{
1075 struct filedesc *fdp = p->p_fd;
1076 struct file *fp;
1077 struct vnode *vp;
1078 struct vattr vattr;
1079 int flags, cloexec, cmode;
1080 int type, indx, error, localtrunc = 0;
1081 struct flock lf;
1082 struct nameidata nd;
1083 uint64_t ni_pledge = 0;
1084 u_char ni_unveil = 0;
1085
1086 if (oflags & (O_EXLOCK0x0020 | O_SHLOCK0x0010)) {
1087 error = pledge_flock(p);
1088 if (error != 0)
1089 return (error);
1090 }
1091
1092 cloexec = (oflags & O_CLOEXEC0x10000) ? UF_EXCLOSE0x01 : 0;
1093
1094 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1095 if ((error = falloc(p, &fp, &indx)) != 0) {
1096 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1097 return (error);
1098 }
1099 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1100
1101 flags = FFLAGS(oflags)(((oflags) & ~0x0003) | (((oflags) + 1) & 0x0003));
1102 if (flags & FREAD0x0001) {
1103 ni_pledge |= PLEDGE_RPATH0x0000000000000001ULL;
1104 ni_unveil |= UNVEIL_READ0x01;
1105 }
1106 if (flags & FWRITE0x0002) {
1107 ni_pledge |= PLEDGE_WPATH0x0000000000000002ULL;
1108 ni_unveil |= UNVEIL_WRITE0x02;
1109 }
1110 if (oflags & O_CREAT0x0200) {
1111 ni_pledge |= PLEDGE_CPATH0x0000000000000004ULL;
1112 ni_unveil |= UNVEIL_CREATE0x04;
1113 }
1114
1115 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) &~ S_ISTXT0001000;
1116 if ((p->p_p->ps_flags & PS_PLEDGE0x00100000))
1117 cmode &= ACCESSPERMS(0000700|0000070|0000007);
1118 NDINITAT(&nd, 0, 0, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, 0, UIO_USERSPACE, fd, path, p);
1119 nd.ni_pledge = ni_pledge;
1120 nd.ni_unveil = ni_unveil;
1121 p->p_dupfd = -1; /* XXX check for fdopen */
1122 if ((flags & O_TRUNC0x0400) && (flags & (O_EXLOCK0x0020 | O_SHLOCK0x0010))) {
1123 localtrunc = 1;
1124 flags &= ~O_TRUNC0x0400; /* Must do truncate ourselves */
1125 }
1126 if ((error = vn_open(&nd, flags, cmode)) != 0) {
1127 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1128 if (error == ENODEV19 &&
1129 p->p_dupfd >= 0 && /* XXX from fdopen */
1130 (error =
1131 dupfdopen(p, indx, flags)) == 0) {
1132 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1133 closef(fp, p);
1134 *retval = indx;
1135 return (error);
1136 }
1137 if (error == ERESTART-1)
1138 error = EINTR4;
1139 fdremove(fdp, indx);
1140 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1141 closef(fp, p);
1142 return (error);
1143 }
1144 p->p_dupfd = 0;
1145 vp = nd.ni_vp;
1146 fp->f_flag = flags & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004);
1147 fp->f_type = DTYPE_VNODE1;
1148 fp->f_ops = &vnops;
1149 fp->f_data = vp;
1150 if (flags & (O_EXLOCK0x0020 | O_SHLOCK0x0010)) {
1151 lf.l_whence = SEEK_SET0;
1152 lf.l_start = 0;
1153 lf.l_len = 0;
1154 if (flags & O_EXLOCK0x0020)
1155 lf.l_type = F_WRLCK3;
1156 else
1157 lf.l_type = F_RDLCK1;
1158 type = F_FLOCK0x020;
1159 if ((flags & FNONBLOCK0x0004) == 0)
1160 type |= F_WAIT0x010;
1161 VOP_UNLOCK(vp);
1162 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK8, &lf, type);
1163 if (error) {
1164 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1165 /* closef will vn_close the file for us. */
1166 fdremove(fdp, indx);
1167 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1168 closef(fp, p);
1169 return (error);
1170 }
1171 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
1172 atomic_setbits_intx86_atomic_setbits_u32(&fp->f_iflags, FIF_HASLOCK0x01);
1173 }
1174 if (localtrunc) {
1175 if ((fp->f_flag & FWRITE0x0002) == 0)
1176 error = EACCES13;
1177 else if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001))
1178 error = EROFS30;
1179 else if (vp->v_type == VDIR)
1180 error = EISDIR21;
1181 else if ((error = vn_writechk(vp)) == 0) {
1182 VATTR_NULL(&vattr)vattr_null(&vattr);
1183 vattr.va_size = 0;
1184 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1185 }
1186 if (error) {
1187 VOP_UNLOCK(vp);
1188 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1189 /* closef will close the file for us. */
1190 fdremove(fdp, indx);
1191 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1192 closef(fp, p);
1193 return (error);
1194 }
1195 }
1196 VOP_UNLOCK(vp);
1197 *retval = indx;
1198 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1199 fdinsert(fdp, indx, cloexec, fp);
1200 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1201 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
1202 return (error);
1203}
1204
1205/*
1206 * Open a new created file (in /tmp) suitable for mmaping.
1207 */
1208int
1209sys___tmpfd(struct proc *p, void *v, register_t *retval)
1210{
1211 struct sys___tmpfd_args /* {
1212 syscallarg(int) flags;
1213 } */ *uap = v;
1214 struct filedesc *fdp = p->p_fd;
1215 struct file *fp;
1216 struct vnode *vp;
1217 int oflags = SCARG(uap, flags)((uap)->flags.le.datum);
1218 int flags, cloexec, cmode;
1219 int indx, error;
1220 unsigned int i;
1221 struct nameidata nd;
1222 char path[64];
1223 static const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
1224
1225 /* most flags are hardwired */
1226 oflags = O_RDWR0x0002 | O_CREAT0x0200 | O_EXCL0x0800 | O_NOFOLLOW0x0100 | (oflags & O_CLOEXEC0x10000);
1227
1228 cloexec = (oflags & O_CLOEXEC0x10000) ? UF_EXCLOSE0x01 : 0;
1229
1230 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1231 if ((error = falloc(p, &fp, &indx)) != 0) {
1232 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1233 return (error);
1234 }
1235 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1236
1237 flags = FFLAGS(oflags)(((oflags) & ~0x0003) | (((oflags) + 1) & 0x0003));
1238
1239 arc4random_buf(path, sizeof(path));
1240 memcpy(path, "/tmp/", 5)__builtin_memcpy((path), ("/tmp/"), (5));
1241 for (i = 5; i < sizeof(path) - 1; i++)
1242 path[i] = letters[(unsigned char)path[i] & 63];
1243 path[sizeof(path)-1] = 0;
1244
1245 cmode = 0600;
1246 NDINITAT(&nd, 0, KERNELPATH, UIO_SYSSPACE, AT_FDCWD, path, p)ndinitat(&nd, 0, 0x800000, UIO_SYSSPACE, -100, path, p);
1247 if ((error = vn_open(&nd, flags, cmode)) != 0) {
1248 if (error == ERESTART-1)
1249 error = EINTR4;
1250 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1251 fdremove(fdp, indx);
1252 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1253 closef(fp, p);
1254 return (error);
1255 }
1256 vp = nd.ni_vp;
1257 fp->f_flag = flags & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004);
1258 fp->f_type = DTYPE_VNODE1;
1259 fp->f_ops = &vnops;
1260 fp->f_data = vp;
1261 VOP_UNLOCK(vp);
1262 *retval = indx;
1263 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1264 fdinsert(fdp, indx, cloexec, fp);
1265 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1266 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
1267
1268 /* unlink it */
1269 /* XXX
1270 * there is a wee race here, although it is mostly inconsequential.
1271 * perhaps someday we can create a file like object without a name...
1272 */
1273 NDINITAT(&nd, DELETE, KERNELPATH | LOCKPARENT | LOCKLEAF, UIO_SYSSPACE,ndinitat(&nd, 2, 0x800000 | 0x0008 | 0x0004, UIO_SYSSPACE
, -100, path, p)
1274 AT_FDCWD, path, p)ndinitat(&nd, 2, 0x800000 | 0x0008 | 0x0004, UIO_SYSSPACE
, -100, path, p)
;
1275 if ((error = namei(&nd)) != 0) {
1276 printf("can't unlink temp file! %d\n", error);
1277 error = 0;
1278 } else {
1279 vp = nd.ni_vp;
1280 uvm_vnp_uncache(vp);
1281 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1282 if (error) {
1283 printf("error removing vop: %d\n", error);
1284 error = 0;
1285 }
1286 }
1287
1288 return (error);
1289}
1290
1291/*
1292 * Get file handle system call
1293 */
1294int
1295sys_getfh(struct proc *p, void *v, register_t *retval)
1296{
1297 struct sys_getfh_args /* {
1298 syscallarg(const char *) fname;
1299 syscallarg(fhandle_t *) fhp;
1300 } */ *uap = v;
1301 struct vnode *vp;
1302 fhandle_t fh;
1303 int error;
1304 struct nameidata nd;
1305
1306 /*
1307 * Must be super user
1308 */
1309 error = suser(p);
1310 if (error)
1311 return (error);
1312 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->fname.le.datum), p)
1313 SCARG(uap, fname), p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->fname.le.datum), p)
;
1314 error = namei(&nd);
1315 if (error)
1316 return (error);
1317 vp = nd.ni_vp;
1318 memset(&fh, 0, sizeof(fh))__builtin_memset((&fh), (0), (sizeof(fh)));
1319 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1320 error = VFS_VPTOFH(vp, &fh.fh_fid)(*(vp)->v_mount->mnt_op->vfs_vptofh)(vp, &fh.fh_fid
)
;
1321 vput(vp);
1322 if (error)
1323 return (error);
1324 error = copyout(&fh, SCARG(uap, fhp)((uap)->fhp.le.datum), sizeof(fh));
1325 return (error);
1326}
1327
1328/*
1329 * Open a file given a file handle.
1330 *
1331 * Check permissions, allocate an open file structure,
1332 * and call the device open routine if any.
1333 */
1334int
1335sys_fhopen(struct proc *p, void *v, register_t *retval)
1336{
1337 struct sys_fhopen_args /* {
1338 syscallarg(const fhandle_t *) fhp;
1339 syscallarg(int) flags;
1340 } */ *uap = v;
1341 struct filedesc *fdp = p->p_fd;
1342 struct file *fp;
1343 struct vnode *vp = NULL((void *)0);
1344 struct mount *mp;
1345 struct ucred *cred = p->p_ucred;
1346 int flags, cloexec;
1347 int type, indx, error=0;
1348 struct flock lf;
1349 struct vattr va;
1350 fhandle_t fh;
1351
1352 /*
1353 * Must be super user
1354 */
1355 if ((error = suser(p)))
1356 return (error);
1357
1358 flags = FFLAGS(SCARG(uap, flags))(((((uap)->flags.le.datum)) & ~0x0003) | (((((uap)->
flags.le.datum)) + 1) & 0x0003))
;
1359 if ((flags & (FREAD0x0001 | FWRITE0x0002)) == 0)
1360 return (EINVAL22);
1361 if ((flags & O_CREAT0x0200))
1362 return (EINVAL22);
1363
1364 cloexec = (flags & O_CLOEXEC0x10000) ? UF_EXCLOSE0x01 : 0;
1365
1366 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1367 if ((error = falloc(p, &fp, &indx)) != 0) {
1368 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1369 fp = NULL((void *)0);
1370 goto bad;
1371 }
1372 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1373
1374 if ((error = copyin(SCARG(uap, fhp)((uap)->fhp.le.datum), &fh, sizeof(fhandle_t))) != 0)
1375 goto bad;
1376
1377 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL((void *)0)) {
1378 error = ESTALE70;
1379 goto bad;
1380 }
1381
1382 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)(*(mp)->mnt_op->vfs_fhtovp)(mp, &fh.fh_fid, &vp
)
) != 0) {
1383 vp = NULL((void *)0); /* most likely unnecessary sanity for bad: */
1384 goto bad;
1385 }
1386
1387 /* Now do an effective vn_open */
1388
1389 if (vp->v_type == VSOCK) {
1390 error = EOPNOTSUPP45;
1391 goto bad;
1392 }
1393 if ((flags & O_DIRECTORY0x20000) && vp->v_type != VDIR) {
1394 error = ENOTDIR20;
1395 goto bad;
1396 }
1397 if (flags & FREAD0x0001) {
1398 if ((error = VOP_ACCESS(vp, VREAD00400, cred, p)) != 0)
1399 goto bad;
1400 }
1401 if (flags & (FWRITE0x0002 | O_TRUNC0x0400)) {
1402 if (vp->v_type == VDIR) {
1403 error = EISDIR21;
1404 goto bad;
1405 }
1406 if ((error = VOP_ACCESS(vp, VWRITE00200, cred, p)) != 0 ||
1407 (error = vn_writechk(vp)) != 0)
1408 goto bad;
1409 }
1410 if (flags & O_TRUNC0x0400) {
1411 VATTR_NULL(&va)vattr_null(&va);
1412 va.va_size = 0;
1413 if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
1414 goto bad;
1415 }
1416 if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
1417 goto bad;
1418 if (flags & FWRITE0x0002)
1419 vp->v_writecount++;
1420
1421 /* done with modified vn_open, now finish what sys_open does. */
1422
1423 fp->f_flag = flags & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004);
1424 fp->f_type = DTYPE_VNODE1;
1425 fp->f_ops = &vnops;
1426 fp->f_data = vp;
1427 if (flags & (O_EXLOCK0x0020 | O_SHLOCK0x0010)) {
1428 lf.l_whence = SEEK_SET0;
1429 lf.l_start = 0;
1430 lf.l_len = 0;
1431 if (flags & O_EXLOCK0x0020)
1432 lf.l_type = F_WRLCK3;
1433 else
1434 lf.l_type = F_RDLCK1;
1435 type = F_FLOCK0x020;
1436 if ((flags & FNONBLOCK0x0004) == 0)
1437 type |= F_WAIT0x010;
1438 VOP_UNLOCK(vp);
1439 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK8, &lf, type);
1440 if (error) {
1441 vp = NULL((void *)0); /* closef will vn_close the file */
1442 goto bad;
1443 }
1444 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
1445 atomic_setbits_intx86_atomic_setbits_u32(&fp->f_iflags, FIF_HASLOCK0x01);
1446 }
1447 VOP_UNLOCK(vp);
1448 *retval = indx;
1449 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1450 fdinsert(fdp, indx, cloexec, fp);
1451 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1452 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
1453 return (0);
1454
1455bad:
1456 if (fp) {
1457 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
1458 fdremove(fdp, indx);
1459 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
1460 closef(fp, p);
1461 if (vp != NULL((void *)0))
1462 vput(vp);
1463 }
1464 return (error);
1465}
1466
1467int
1468sys_fhstat(struct proc *p, void *v, register_t *retval)
1469{
1470 struct sys_fhstat_args /* {
1471 syscallarg(const fhandle_t *) fhp;
1472 syscallarg(struct stat *) sb;
1473 } */ *uap = v;
1474 struct stat sb;
1475 int error;
1476 fhandle_t fh;
1477 struct mount *mp;
1478 struct vnode *vp;
1479
1480 /*
1481 * Must be super user
1482 */
1483 if ((error = suser(p)))
1484 return (error);
1485
1486 if ((error = copyin(SCARG(uap, fhp)((uap)->fhp.le.datum), &fh, sizeof(fhandle_t))) != 0)
1487 return (error);
1488
1489 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL((void *)0))
1490 return (ESTALE70);
1491 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)(*(mp)->mnt_op->vfs_fhtovp)(mp, &fh.fh_fid, &vp
)
))
1492 return (error);
1493 error = vn_stat(vp, &sb, p);
1494 vput(vp);
1495 if (error)
1496 return (error);
1497 error = copyout(&sb, SCARG(uap, sb)((uap)->sb.le.datum), sizeof(sb));
1498 return (error);
1499}
1500
1501int
1502sys_fhstatfs(struct proc *p, void *v, register_t *retval)
1503{
1504 struct sys_fhstatfs_args /* {
1505 syscallarg(const fhandle_t *) fhp;
1506 syscallarg(struct statfs *) buf;
1507 } */ *uap = v;
1508 struct statfs *sp;
1509 fhandle_t fh;
1510 struct mount *mp;
1511 struct vnode *vp;
1512 int error;
1513
1514 /*
1515 * Must be super user
1516 */
1517 if ((error = suser(p)))
1518 return (error);
1519
1520 if ((error = copyin(SCARG(uap, fhp)((uap)->fhp.le.datum), &fh, sizeof(fhandle_t))) != 0)
1521 return (error);
1522
1523 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL((void *)0))
1524 return (ESTALE70);
1525 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)(*(mp)->mnt_op->vfs_fhtovp)(mp, &fh.fh_fid, &vp
)
))
1526 return (error);
1527 mp = vp->v_mount;
1528 sp = &mp->mnt_stat;
1529 vput(vp);
1530 if ((error = VFS_STATFS(mp, sp, p)(*(mp)->mnt_op->vfs_statfs)(mp, sp, p)) != 0)
1531 return (error);
1532 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK0x0400ffff;
1533 return (copyout(sp, SCARG(uap, buf)((uap)->buf.le.datum), sizeof(*sp)));
1534}
1535
1536/*
1537 * Create a special file or named pipe.
1538 */
1539int
1540sys_mknod(struct proc *p, void *v, register_t *retval)
1541{
1542 struct sys_mknod_args /* {
1543 syscallarg(const char *) path;
1544 syscallarg(mode_t) mode;
1545 syscallarg(int) dev;
1546 } */ *uap = v;
1547
1548 return (domknodat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, mode)((uap)->mode.le.datum),
1549 SCARG(uap, dev)((uap)->dev.le.datum)));
1550}
1551
1552int
1553sys_mknodat(struct proc *p, void *v, register_t *retval)
1554{
1555 struct sys_mknodat_args /* {
1556 syscallarg(int) fd;
1557 syscallarg(const char *) path;
1558 syscallarg(mode_t) mode;
1559 syscallarg(dev_t) dev;
1560 } */ *uap = v;
1561
1562 return (domknodat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
1563 SCARG(uap, mode)((uap)->mode.le.datum), SCARG(uap, dev)((uap)->dev.le.datum)));
1564}
1565
1566int
1567domknodat(struct proc *p, int fd, const char *path, mode_t mode, dev_t dev)
1568{
1569 struct vnode *vp;
1570 struct vattr vattr;
1571 int error;
1572 struct nameidata nd;
1573
1574 if (dev == VNOVAL(-1))
1575 return (EINVAL22);
1576 NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 1, 0x0008, UIO_USERSPACE, fd, path, p);
1577 nd.ni_pledge = PLEDGE_DPATH0x0000000010000000ULL;
1578 nd.ni_unveil = UNVEIL_CREATE0x04;
1579 if ((error = namei(&nd)) != 0)
1580 return (error);
1581 vp = nd.ni_vp;
1582 if (!S_ISFIFO(mode)((mode & 0170000) == 0010000) || dev != 0) {
1583 if (!vnoperm(nd.ni_dvp) && (error = suser(p)) != 0)
1584 goto out;
1585 if (p->p_fd->fd_rdir) {
1586 error = EINVAL22;
1587 goto out;
1588 }
1589 }
1590 if (vp != NULL((void *)0))
1591 error = EEXIST17;
1592 else {
1593 VATTR_NULL(&vattr)vattr_null(&vattr);
1594 vattr.va_mode = (mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) &~ p->p_fd->fd_cmask;
1595 if ((p->p_p->ps_flags & PS_PLEDGE0x00100000))
1596 vattr.va_mode &= ACCESSPERMS(0000700|0000070|0000007);
1597 vattr.va_rdev = dev;
1598
1599 switch (mode & S_IFMT0170000) {
1600 case S_IFMT0170000: /* used by badsect to flag bad sectors */
1601 vattr.va_type = VBAD;
1602 break;
1603 case S_IFCHR0020000:
1604 vattr.va_type = VCHR;
1605 break;
1606 case S_IFBLK0060000:
1607 vattr.va_type = VBLK;
1608 break;
1609 case S_IFIFO0010000:
1610#ifndef FIFO1
1611 error = EOPNOTSUPP45;
1612 break;
1613#else
1614 if (dev == 0) {
1615 vattr.va_type = VFIFO;
1616 break;
1617 }
1618 /* FALLTHROUGH */
1619#endif /* FIFO */
1620 default:
1621 error = EINVAL22;
1622 break;
1623 }
1624 }
1625out:
1626 if (!error) {
1627 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1628 vput(nd.ni_dvp);
1629 } else {
1630 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1631 if (nd.ni_dvp == vp)
1632 vrele(nd.ni_dvp);
1633 else
1634 vput(nd.ni_dvp);
1635 if (vp)
1636 vrele(vp);
1637 }
1638 return (error);
1639}
1640
1641/*
1642 * Create a named pipe.
1643 */
1644int
1645sys_mkfifo(struct proc *p, void *v, register_t *retval)
1646{
1647 struct sys_mkfifo_args /* {
1648 syscallarg(const char *) path;
1649 syscallarg(mode_t) mode;
1650 } */ *uap = v;
1651
1652 return (domknodat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum),
1653 (SCARG(uap, mode)((uap)->mode.le.datum) & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) | S_IFIFO0010000, 0));
1654}
1655
1656int
1657sys_mkfifoat(struct proc *p, void *v, register_t *retval)
1658{
1659 struct sys_mkfifoat_args /* {
1660 syscallarg(int) fd;
1661 syscallarg(const char *) path;
1662 syscallarg(mode_t) mode;
1663 } */ *uap = v;
1664
1665 return (domknodat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
1666 (SCARG(uap, mode)((uap)->mode.le.datum) & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) | S_IFIFO0010000, 0));
1667}
1668
1669/*
1670 * Make a hard file link.
1671 */
1672int
1673sys_link(struct proc *p, void *v, register_t *retval)
1674{
1675 struct sys_link_args /* {
1676 syscallarg(const char *) path;
1677 syscallarg(const char *) link;
1678 } */ *uap = v;
1679
1680 return (dolinkat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), AT_FDCWD-100,
1681 SCARG(uap, link)((uap)->link.le.datum), AT_SYMLINK_FOLLOW0x04));
1682}
1683
1684int
1685sys_linkat(struct proc *p, void *v, register_t *retval)
1686{
1687 struct sys_linkat_args /* {
1688 syscallarg(int) fd1;
1689 syscallarg(const char *) path1;
1690 syscallarg(int) fd2;
1691 syscallarg(const char *) path2;
1692 syscallarg(int) flag;
1693 } */ *uap = v;
1694
1695 return (dolinkat(p, SCARG(uap, fd1)((uap)->fd1.le.datum), SCARG(uap, path1)((uap)->path1.le.datum),
1696 SCARG(uap, fd2)((uap)->fd2.le.datum), SCARG(uap, path2)((uap)->path2.le.datum), SCARG(uap, flag)((uap)->flag.le.datum)));
1697}
1698
1699int
1700dolinkat(struct proc *p, int fd1, const char *path1, int fd2,
1701 const char *path2, int flag)
1702{
1703 struct vnode *vp;
1704 struct nameidata nd;
1705 int error, follow;
1706 int flags;
1707
1708 if (flag & ~AT_SYMLINK_FOLLOW0x04)
1709 return (EINVAL22);
1710
1711 follow = (flag & AT_SYMLINK_FOLLOW0x04) ? FOLLOW0x0040 : NOFOLLOW0x0000;
1712 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd1, path1, p)ndinitat(&nd, 0, follow, UIO_USERSPACE, fd1, path1, p);
1713 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
1714 nd.ni_unveil = UNVEIL_READ0x01;
1715 if ((error = namei(&nd)) != 0)
1716 return (error);
1717 vp = nd.ni_vp;
1718
1719 flags = LOCKPARENT0x0008;
1720 if (vp->v_type == VDIR) {
1721 flags |= STRIPSLASHES0x100000;
1722 }
1723
1724 NDINITAT(&nd, CREATE, flags, UIO_USERSPACE, fd2, path2, p)ndinitat(&nd, 1, flags, UIO_USERSPACE, fd2, path2, p);
1725 nd.ni_pledge = PLEDGE_CPATH0x0000000000000004ULL;
1726 nd.ni_unveil = UNVEIL_CREATE0x04;
1727 if ((error = namei(&nd)) != 0)
1728 goto out;
1729 if (nd.ni_vp) {
1730 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1731 if (nd.ni_dvp == nd.ni_vp)
1732 vrele(nd.ni_dvp);
1733 else
1734 vput(nd.ni_dvp);
1735 vrele(nd.ni_vp);
1736 error = EEXIST17;
1737 goto out;
1738 }
1739 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1740out:
1741 vrele(vp);
1742 return (error);
1743}
1744
1745/*
1746 * Make a symbolic link.
1747 */
1748int
1749sys_symlink(struct proc *p, void *v, register_t *retval)
1750{
1751 struct sys_symlink_args /* {
1752 syscallarg(const char *) path;
1753 syscallarg(const char *) link;
1754 } */ *uap = v;
1755
1756 return (dosymlinkat(p, SCARG(uap, path)((uap)->path.le.datum), AT_FDCWD-100, SCARG(uap, link)((uap)->link.le.datum)));
1757}
1758
1759int
1760sys_symlinkat(struct proc *p, void *v, register_t *retval)
1761{
1762 struct sys_symlinkat_args /* {
1763 syscallarg(const char *) path;
1764 syscallarg(int) fd;
1765 syscallarg(const char *) link;
1766 } */ *uap = v;
1767
1768 return (dosymlinkat(p, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, fd)((uap)->fd.le.datum),
1769 SCARG(uap, link)((uap)->link.le.datum)));
1770}
1771
1772int
1773dosymlinkat(struct proc *p, const char *upath, int fd, const char *link)
1774{
1775 struct vattr vattr;
1776 char *path;
1777 int error;
1778 struct nameidata nd;
1779
1780 path = pool_get(&namei_pool, PR_WAITOK0x0001);
1781 error = copyinstr(upath, path, MAXPATHLEN1024, NULL((void *)0));
1782 if (error)
1783 goto out;
1784 NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, link, p)ndinitat(&nd, 1, 0x0008, UIO_USERSPACE, fd, link, p);
1785 nd.ni_pledge = PLEDGE_CPATH0x0000000000000004ULL;
1786 nd.ni_unveil = UNVEIL_CREATE0x04;
1787 if ((error = namei(&nd)) != 0)
1788 goto out;
1789 if (nd.ni_vp) {
1790 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1791 if (nd.ni_dvp == nd.ni_vp)
1792 vrele(nd.ni_dvp);
1793 else
1794 vput(nd.ni_dvp);
1795 vrele(nd.ni_vp);
1796 error = EEXIST17;
1797 goto out;
1798 }
1799 VATTR_NULL(&vattr)vattr_null(&vattr);
1800 vattr.va_mode = ACCESSPERMS(0000700|0000070|0000007) &~ p->p_fd->fd_cmask;
1801 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1802out:
1803 pool_put(&namei_pool, path);
1804 return (error);
1805}
1806
1807/*
1808 * Delete a name from the filesystem.
1809 */
1810int
1811sys_unlink(struct proc *p, void *v, register_t *retval)
1812{
1813 struct sys_unlink_args /* {
1814 syscallarg(const char *) path;
1815 } */ *uap = v;
1816
1817 return (dounlinkat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), 0));
1818}
1819
1820int
1821sys_unlinkat(struct proc *p, void *v, register_t *retval)
1822{
1823 struct sys_unlinkat_args /* {
1824 syscallarg(int) fd;
1825 syscallarg(const char *) path;
1826 syscallarg(int) flag;
1827 } */ *uap = v;
1828
1829 return (dounlinkat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
1830 SCARG(uap, flag)((uap)->flag.le.datum)));
1831}
1832
1833int
1834dounlinkat(struct proc *p, int fd, const char *path, int flag)
1835{
1836 struct vnode *vp;
1837 int error;
1838 struct nameidata nd;
1839
1840 if (flag & ~AT_REMOVEDIR0x08)
1841 return (EINVAL22);
1842
1843 NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 2, 0x0008 | 0x0004, UIO_USERSPACE, fd, path
, p)
1844 fd, path, p)ndinitat(&nd, 2, 0x0008 | 0x0004, UIO_USERSPACE, fd, path
, p)
;
1845 nd.ni_pledge = PLEDGE_CPATH0x0000000000000004ULL;
1846 nd.ni_unveil = UNVEIL_CREATE0x04;
1847 if ((error = namei(&nd)) != 0)
1848 return (error);
1849 vp = nd.ni_vp;
1850
1851 if (flag & AT_REMOVEDIR0x08) {
1852 if (vp->v_type != VDIR) {
1853 error = ENOTDIR20;
1854 goto out;
1855 }
1856 /*
1857 * No rmdir "." please.
1858 */
1859 if (nd.ni_dvp == vp) {
1860 error = EINVAL22;
1861 goto out;
1862 }
1863 /*
1864 * A mounted on directory cannot be deleted.
1865 */
1866 if (vp->v_mountedherev_un.vu_mountedhere != NULL((void *)0)) {
1867 error = EBUSY16;
1868 goto out;
1869 }
1870 }
1871
1872 /*
1873 * The root of a mounted filesystem cannot be deleted.
1874 */
1875 if (vp->v_flag & VROOT0x0001)
1876 error = EBUSY16;
1877out:
1878 if (!error) {
1879 if (flag & AT_REMOVEDIR0x08) {
1880 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1881 } else {
1882 (void)uvm_vnp_uncache(vp);
1883 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1884 }
1885 } else {
1886 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1887 if (nd.ni_dvp == vp)
1888 vrele(nd.ni_dvp);
1889 else
1890 vput(nd.ni_dvp);
1891 vput(vp);
1892 }
1893 return (error);
1894}
1895
1896/*
1897 * Reposition read/write file offset.
1898 */
1899int
1900sys_lseek(struct proc *p, void *v, register_t *retval)
1901{
1902 struct sys_lseek_args /* {
1903 syscallarg(int) fd;
1904 syscallarg(off_t) offset;
1905 syscallarg(int) whence;
1906 } */ *uap = v;
1907 struct filedesc *fdp = p->p_fd;
1908 struct file *fp;
1909 off_t offset;
1910 int error;
1911
1912 if ((fp = fd_getfile(fdp, SCARG(uap, fd)((uap)->fd.le.datum))) == NULL((void *)0))
1913 return (EBADF9);
1914 if (fp->f_ops->fo_seek == NULL((void *)0)) {
1915 error = ESPIPE29;
1916 goto bad;
1917 }
1918 offset = SCARG(uap, offset)((uap)->offset.le.datum);
1919
1920 error = (*fp->f_ops->fo_seek)(fp, &offset, SCARG(uap, whence)((uap)->whence.le.datum), p);
1921 if (error)
1922 goto bad;
1923
1924 *(off_t *)retval = offset;
1925 mtx_enter(&fp->f_mtx);
1926 fp->f_seek++;
1927 mtx_leave(&fp->f_mtx);
1928 error = 0;
1929 bad:
1930 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
1931 return (error);
1932}
1933
1934/*
1935 * Check access permissions.
1936 */
1937int
1938sys_access(struct proc *p, void *v, register_t *retval)
1939{
1940 struct sys_access_args /* {
1941 syscallarg(const char *) path;
1942 syscallarg(int) amode;
1943 } */ *uap = v;
1944
1945 return (dofaccessat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum),
1946 SCARG(uap, amode)((uap)->amode.le.datum), 0));
1947}
1948
1949int
1950sys_faccessat(struct proc *p, void *v, register_t *retval)
1951{
1952 struct sys_faccessat_args /* {
1953 syscallarg(int) fd;
1954 syscallarg(const char *) path;
1955 syscallarg(int) amode;
1956 syscallarg(int) flag;
1957 } */ *uap = v;
1958
1959 return (dofaccessat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
1960 SCARG(uap, amode)((uap)->amode.le.datum), SCARG(uap, flag)((uap)->flag.le.datum)));
1961}
1962
1963int
1964dofaccessat(struct proc *p, int fd, const char *path, int amode, int flag)
1965{
1966 struct vnode *vp;
1967 struct ucred *newcred, *oldcred;
1968 struct nameidata nd;
1969 int error;
1970
1971 if (amode & ~(R_OK0x04 | W_OK0x02 | X_OK0x01))
1972 return (EINVAL22);
1973 if (flag & ~AT_EACCESS0x01)
1974 return (EINVAL22);
1975
1976 newcred = NULL((void *)0);
1977 oldcred = p->p_ucred;
1978
1979 /*
1980 * If access as real ids was requested and they really differ,
1981 * give the thread new creds with them reset
1982 */
1983 if ((flag & AT_EACCESS0x01) == 0 &&
1984 (oldcred->cr_uid != oldcred->cr_ruid ||
1985 (oldcred->cr_gid != oldcred->cr_rgid))) {
1986 p->p_ucred = newcred = crdup(oldcred);
1987 newcred->cr_uid = newcred->cr_ruid;
1988 newcred->cr_gid = newcred->cr_rgid;
1989 }
1990
1991 NDINITAT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, fd, path
, p)
;
1992 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
1993 nd.ni_unveil = UNVEIL_READ0x01;
1994 if ((error = namei(&nd)) != 0)
1995 goto out;
1996 vp = nd.ni_vp;
1997
1998 /* Flags == 0 means only check for existence. */
1999 if (amode) {
2000 int vflags = 0;
2001
2002 if (amode & R_OK0x04)
2003 vflags |= VREAD00400;
2004 if (amode & W_OK0x02)
2005 vflags |= VWRITE00200;
2006 if (amode & X_OK0x01)
2007 vflags |= VEXEC00100;
2008
2009 error = VOP_ACCESS(vp, vflags, p->p_ucred, p);
2010 if (!error && (vflags & VWRITE00200))
2011 error = vn_writechk(vp);
2012 }
2013 vput(vp);
2014out:
2015 if (newcred != NULL((void *)0)) {
2016 p->p_ucred = oldcred;
2017 crfree(newcred);
2018 }
2019 return (error);
2020}
2021
2022/*
2023 * Get file status; this version follows links.
2024 */
2025int
2026sys_stat(struct proc *p, void *v, register_t *retval)
2027{
2028 struct sys_stat_args /* {
2029 syscallarg(const char *) path;
2030 syscallarg(struct stat *) ub;
2031 } */ *uap = v;
2032
2033 return (dofstatat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, ub)((uap)->ub.le.datum), 0));
2034}
2035
2036int
2037sys_fstatat(struct proc *p, void *v, register_t *retval)
2038{
2039 struct sys_fstatat_args /* {
2040 syscallarg(int) fd;
2041 syscallarg(const char *) path;
2042 syscallarg(struct stat *) buf;
2043 syscallarg(int) flag;
2044 } */ *uap = v;
2045
2046 return (dofstatat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
2047 SCARG(uap, buf)((uap)->buf.le.datum), SCARG(uap, flag)((uap)->flag.le.datum)));
2048}
2049
2050int
2051dofstatat(struct proc *p, int fd, const char *path, struct stat *buf, int flag)
2052{
2053 struct stat sb;
2054 int error, follow;
2055 struct nameidata nd;
2056
2057 if (flag & ~AT_SYMLINK_NOFOLLOW0x02)
2058 return (EINVAL22);
2059
2060
2061 follow = (flag & AT_SYMLINK_NOFOLLOW0x02) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2062 NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, follow | 0x0004, UIO_USERSPACE, fd, path
, p)
;
2063 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
2064 nd.ni_unveil = UNVEIL_READ0x01;
2065 if ((error = namei(&nd)) != 0)
2066 return (error);
2067 error = vn_stat(nd.ni_vp, &sb, p);
2068 vput(nd.ni_vp);
2069 if (error)
2070 return (error);
2071 /* Don't let non-root see generation numbers (for NFS security) */
2072 if (suser(p))
2073 sb.st_gen = 0;
2074 error = copyout(&sb, buf, sizeof(sb));
2075#ifdef KTRACE1
2076 if (error == 0 && KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
2077 ktrstat(p, &sb)ktrstruct((p), "stat", (&sb), sizeof(struct stat));
2078#endif
2079 return (error);
2080}
2081
2082/*
2083 * Get file status; this version does not follow links.
2084 */
2085int
2086sys_lstat(struct proc *p, void *v, register_t *retval)
2087{
2088 struct sys_lstat_args /* {
2089 syscallarg(const char *) path;
2090 syscallarg(struct stat *) ub;
2091 } */ *uap = v;
2092
2093 return (dofstatat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, ub)((uap)->ub.le.datum),
2094 AT_SYMLINK_NOFOLLOW0x02));
2095}
2096
2097/*
2098 * Get configurable pathname variables.
2099 */
2100int
2101sys_pathconf(struct proc *p, void *v, register_t *retval)
2102{
2103 struct sys_pathconf_args /* {
2104 syscallarg(const char *) path;
2105 syscallarg(int) name;
2106 } */ *uap = v;
2107 int error;
2108 struct nameidata nd;
2109
2110 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
2111 SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040 | 0x0004, UIO_USERSPACE, -100, ((
uap)->path.le.datum), p)
;
2112 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
2113 nd.ni_unveil = UNVEIL_READ0x01;
2114 if ((error = namei(&nd)) != 0)
2115 return (error);
2116 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name)((uap)->name.le.datum), retval);
2117 vput(nd.ni_vp);
2118 return (error);
2119}
2120
2121/*
2122 * Return target name of a symbolic link.
2123 */
2124int
2125sys_readlink(struct proc *p, void *v, register_t *retval)
2126{
2127 struct sys_readlink_args /* {
2128 syscallarg(const char *) path;
2129 syscallarg(char *) buf;
2130 syscallarg(size_t) count;
2131 } */ *uap = v;
2132
2133 return (doreadlinkat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, buf)((uap)->buf.le.datum),
2134 SCARG(uap, count)((uap)->count.le.datum), retval));
2135}
2136
2137int
2138sys_readlinkat(struct proc *p, void *v, register_t *retval)
2139{
2140 struct sys_readlinkat_args /* {
2141 syscallarg(int) fd;
2142 syscallarg(const char *) path;
2143 syscallarg(char *) buf;
2144 syscallarg(size_t) count;
2145 } */ *uap = v;
2146
2147 return (doreadlinkat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
2148 SCARG(uap, buf)((uap)->buf.le.datum), SCARG(uap, count)((uap)->count.le.datum), retval));
2149}
2150
2151int
2152doreadlinkat(struct proc *p, int fd, const char *path, char *buf,
2153 size_t count, register_t *retval)
2154{
2155 struct vnode *vp;
2156 struct iovec aiov;
2157 struct uio auio;
2158 int error;
2159 struct nameidata nd;
2160
2161 NDINITAT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, 0x0000 | 0x0004, UIO_USERSPACE, fd, path
, p)
;
2162 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL;
2163 nd.ni_unveil = UNVEIL_READ0x01;
2164 if ((error = namei(&nd)) != 0)
2165 return (error);
2166 vp = nd.ni_vp;
2167 if (vp->v_type != VLNK)
2168 error = EINVAL22;
2169 else {
2170 aiov.iov_base = buf;
2171 aiov.iov_len = count;
2172 auio.uio_iov = &aiov;
2173 auio.uio_iovcnt = 1;
2174 auio.uio_offset = 0;
2175 auio.uio_rw = UIO_READ;
2176 auio.uio_segflg = UIO_USERSPACE;
2177 auio.uio_procp = p;
2178 auio.uio_resid = count;
2179 error = VOP_READLINK(vp, &auio, p->p_ucred);
2180 *retval = count - auio.uio_resid;
2181 }
2182 vput(vp);
2183 return (error);
2184}
2185
2186/*
2187 * Change flags of a file given a path name.
2188 */
2189int
2190sys_chflags(struct proc *p, void *v, register_t *retval)
2191{
2192 struct sys_chflags_args /* {
2193 syscallarg(const char *) path;
2194 syscallarg(u_int) flags;
2195 } */ *uap = v;
2196
2197 return (dochflagsat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum),
2198 SCARG(uap, flags)((uap)->flags.le.datum), 0));
2199}
2200
2201int
2202sys_chflagsat(struct proc *p, void *v, register_t *retval)
2203{
2204 struct sys_chflagsat_args /* {
2205 syscallarg(int) fd;
2206 syscallarg(const char *) path;
2207 syscallarg(u_int) flags;
2208 syscallarg(int) atflags;
2209 } */ *uap = v;
2210
2211 return (dochflagsat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
2212 SCARG(uap, flags)((uap)->flags.le.datum), SCARG(uap, atflags)((uap)->atflags.le.datum)));
2213}
2214
2215int
2216dochflagsat(struct proc *p, int fd, const char *path, u_int flags, int atflags)
2217{
2218 struct nameidata nd;
2219 int error, follow;
2220
2221 if (atflags & ~AT_SYMLINK_NOFOLLOW0x02)
2222 return (EINVAL22);
2223
2224 follow = (atflags & AT_SYMLINK_NOFOLLOW0x02) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2225 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, follow, UIO_USERSPACE, fd, path, p);
2226 nd.ni_pledge = PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2227 nd.ni_unveil = UNVEIL_WRITE0x02;
2228 if ((error = namei(&nd)) != 0)
2229 return (error);
2230 return (dovchflags(p, nd.ni_vp, flags));
2231}
2232
2233/*
2234 * Change flags of a file given a file descriptor.
2235 */
2236int
2237sys_fchflags(struct proc *p, void *v, register_t *retval)
2238{
2239 struct sys_fchflags_args /* {
2240 syscallarg(int) fd;
2241 syscallarg(u_int) flags;
2242 } */ *uap = v;
2243 struct file *fp;
2244 struct vnode *vp;
2245 int error;
2246
2247 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
2248 return (error);
2249 vp = fp->f_data;
2250 vref(vp);
2251 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2252 return (dovchflags(p, vp, SCARG(uap, flags)((uap)->flags.le.datum)));
2253}
2254
2255int
2256dovchflags(struct proc *p, struct vnode *vp, u_int flags)
2257{
2258 struct vattr vattr;
2259 int error;
2260
2261 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2262 if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2263 error = EROFS30;
2264 else if (flags == VNOVAL(-1))
2265 error = EINVAL22;
2266 else {
2267 if (suser(p)) {
2268 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2269 != 0)
2270 goto out;
2271 if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2272 error = EINVAL22;
2273 goto out;
2274 }
2275 }
2276 VATTR_NULL(&vattr)vattr_null(&vattr);
2277 vattr.va_flags = flags;
2278 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2279 }
2280out:
2281 vput(vp);
2282 return (error);
2283}
2284
2285/*
2286 * Change mode of a file given path name.
2287 */
2288int
2289sys_chmod(struct proc *p, void *v, register_t *retval)
2290{
2291 struct sys_chmod_args /* {
2292 syscallarg(const char *) path;
2293 syscallarg(mode_t) mode;
2294 } */ *uap = v;
2295
2296 return (dofchmodat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, mode)((uap)->mode.le.datum), 0));
2297}
2298
2299int
2300sys_fchmodat(struct proc *p, void *v, register_t *retval)
2301{
2302 struct sys_fchmodat_args /* {
2303 syscallarg(int) fd;
2304 syscallarg(const char *) path;
2305 syscallarg(mode_t) mode;
2306 syscallarg(int) flag;
2307 } */ *uap = v;
2308
2309 return (dofchmodat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
2310 SCARG(uap, mode)((uap)->mode.le.datum), SCARG(uap, flag)((uap)->flag.le.datum)));
2311}
2312
2313int
2314dofchmodat(struct proc *p, int fd, const char *path, mode_t mode, int flag)
2315{
2316 struct vnode *vp;
2317 struct vattr vattr;
2318 int error, follow;
2319 struct nameidata nd;
2320
2321 if (mode & ~(S_IFMT0170000 | ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)))
2322 return (EINVAL22);
2323 if ((p->p_p->ps_flags & PS_PLEDGE0x00100000))
2324 mode &= ACCESSPERMS(0000700|0000070|0000007);
2325 if (flag & ~AT_SYMLINK_NOFOLLOW0x02)
2326 return (EINVAL22);
2327
2328 follow = (flag & AT_SYMLINK_NOFOLLOW0x02) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2329 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, follow, UIO_USERSPACE, fd, path, p);
2330 nd.ni_pledge = PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2331 nd.ni_unveil = UNVEIL_WRITE0x02;
2332 if ((error = namei(&nd)) != 0)
2333 return (error);
2334 vp = nd.ni_vp;
2335 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2336 if (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2337 error = EROFS30;
2338 else {
2339 VATTR_NULL(&vattr)vattr_null(&vattr);
2340 vattr.va_mode = mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007);
2341 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2342 }
2343 vput(vp);
2344 return (error);
2345}
2346
2347/*
2348 * Change mode of a file given a file descriptor.
2349 */
2350int
2351sys_fchmod(struct proc *p, void *v, register_t *retval)
2352{
2353 struct sys_fchmod_args /* {
2354 syscallarg(int) fd;
2355 syscallarg(mode_t) mode;
2356 } */ *uap = v;
2357 struct vattr vattr;
2358 struct vnode *vp;
2359 struct file *fp;
2360 mode_t mode = SCARG(uap, mode)((uap)->mode.le.datum);
2361 int error;
2362
2363 if (mode & ~(S_IFMT0170000 | ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)))
2364 return (EINVAL22);
2365 if ((p->p_p->ps_flags & PS_PLEDGE0x00100000))
2366 mode &= ACCESSPERMS(0000700|0000070|0000007);
2367
2368 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
2369 return (error);
2370 vp = fp->f_data;
2371 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2372 if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2373 error = EROFS30;
2374 else {
2375 VATTR_NULL(&vattr)vattr_null(&vattr);
2376 vattr.va_mode = mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007);
2377 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2378 }
2379 VOP_UNLOCK(vp);
2380 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2381 return (error);
2382}
2383
2384/*
2385 * Set ownership given a path name.
2386 */
2387int
2388sys_chown(struct proc *p, void *v, register_t *retval)
2389{
2390 struct sys_chown_args /* {
2391 syscallarg(const char *) path;
2392 syscallarg(uid_t) uid;
2393 syscallarg(gid_t) gid;
2394 } */ *uap = v;
2395
2396 return (dofchownat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, uid)((uap)->uid.le.datum),
2397 SCARG(uap, gid)((uap)->gid.le.datum), 0));
2398}
2399
2400int
2401sys_fchownat(struct proc *p, void *v, register_t *retval)
2402{
2403 struct sys_fchownat_args /* {
2404 syscallarg(int) fd;
2405 syscallarg(const char *) path;
2406 syscallarg(uid_t) uid;
2407 syscallarg(gid_t) gid;
2408 syscallarg(int) flag;
2409 } */ *uap = v;
2410
2411 return (dofchownat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
2412 SCARG(uap, uid)((uap)->uid.le.datum), SCARG(uap, gid)((uap)->gid.le.datum), SCARG(uap, flag)((uap)->flag.le.datum)));
2413}
2414
2415int
2416dofchownat(struct proc *p, int fd, const char *path, uid_t uid, gid_t gid,
2417 int flag)
2418{
2419 struct vnode *vp;
2420 struct vattr vattr;
2421 int error, follow;
2422 struct nameidata nd;
2423 mode_t mode;
2424
2425 if (flag & ~AT_SYMLINK_NOFOLLOW0x02)
2426 return (EINVAL22);
2427
2428 follow = (flag & AT_SYMLINK_NOFOLLOW0x02) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2429 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, follow, UIO_USERSPACE, fd, path, p);
2430 nd.ni_pledge = PLEDGE_CHOWN0x0000000080000000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2431 nd.ni_unveil = UNVEIL_WRITE0x02;
2432 if ((error = namei(&nd)) != 0)
2433 return (error);
2434 vp = nd.ni_vp;
2435 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2436 if (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2437 error = EROFS30;
2438 else {
2439 if ((error = pledge_chown(p, uid, gid)))
2440 goto out;
2441 if ((uid != -1 || gid != -1) &&
2442 !vnoperm(vp) &&
2443 (suser(p) || suid_clear)) {
2444 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2445 if (error)
2446 goto out;
2447 mode = vattr.va_mode & ~(VSUID04000 | VSGID02000);
2448 if (mode == vattr.va_mode)
2449 mode = VNOVAL(-1);
2450 } else
2451 mode = VNOVAL(-1);
2452 VATTR_NULL(&vattr)vattr_null(&vattr);
2453 vattr.va_uid = uid;
2454 vattr.va_gid = gid;
2455 vattr.va_mode = mode;
2456 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2457 }
2458out:
2459 vput(vp);
2460 return (error);
2461}
2462
2463/*
2464 * Set ownership given a path name, without following links.
2465 */
2466int
2467sys_lchown(struct proc *p, void *v, register_t *retval)
2468{
2469 struct sys_lchown_args /* {
2470 syscallarg(const char *) path;
2471 syscallarg(uid_t) uid;
2472 syscallarg(gid_t) gid;
2473 } */ *uap = v;
2474 struct vnode *vp;
2475 struct vattr vattr;
2476 int error;
2477 struct nameidata nd;
2478 mode_t mode;
2479 uid_t uid = SCARG(uap, uid)((uap)->uid.le.datum);
2480 gid_t gid = SCARG(uap, gid)((uap)->gid.le.datum);
2481
2482 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p)ndinitat(&nd, 0, 0x0000, UIO_USERSPACE, -100, ((uap)->
path.le.datum), p)
;
2483 nd.ni_pledge = PLEDGE_CHOWN0x0000000080000000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2484 nd.ni_unveil = UNVEIL_WRITE0x02;
2485 if ((error = namei(&nd)) != 0)
2486 return (error);
2487 vp = nd.ni_vp;
2488 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2489 if (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2490 error = EROFS30;
2491 else {
2492 if ((error = pledge_chown(p, uid, gid)))
2493 goto out;
2494 if ((uid != -1 || gid != -1) &&
2495 !vnoperm(vp) &&
2496 (suser(p) || suid_clear)) {
2497 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2498 if (error)
2499 goto out;
2500 mode = vattr.va_mode & ~(VSUID04000 | VSGID02000);
2501 if (mode == vattr.va_mode)
2502 mode = VNOVAL(-1);
2503 } else
2504 mode = VNOVAL(-1);
2505 VATTR_NULL(&vattr)vattr_null(&vattr);
2506 vattr.va_uid = uid;
2507 vattr.va_gid = gid;
2508 vattr.va_mode = mode;
2509 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2510 }
2511out:
2512 vput(vp);
2513 return (error);
2514}
2515
2516/*
2517 * Set ownership given a file descriptor.
2518 */
2519int
2520sys_fchown(struct proc *p, void *v, register_t *retval)
2521{
2522 struct sys_fchown_args /* {
2523 syscallarg(int) fd;
2524 syscallarg(uid_t) uid;
2525 syscallarg(gid_t) gid;
2526 } */ *uap = v;
2527 struct vnode *vp;
2528 struct vattr vattr;
2529 int error;
2530 struct file *fp;
2531 mode_t mode;
2532 uid_t uid = SCARG(uap, uid)((uap)->uid.le.datum);
2533 gid_t gid = SCARG(uap, gid)((uap)->gid.le.datum);
2534
2535 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
2536 return (error);
2537 vp = fp->f_data;
2538 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2539 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001))
2540 error = EROFS30;
2541 else {
2542 if ((error = pledge_chown(p, uid, gid)))
2543 goto out;
2544 if ((uid != -1 || gid != -1) &&
2545 !vnoperm(vp) &&
2546 (suser(p) || suid_clear)) {
2547 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2548 if (error)
2549 goto out;
2550 mode = vattr.va_mode & ~(VSUID04000 | VSGID02000);
2551 if (mode == vattr.va_mode)
2552 mode = VNOVAL(-1);
2553 } else
2554 mode = VNOVAL(-1);
2555 VATTR_NULL(&vattr)vattr_null(&vattr);
2556 vattr.va_uid = uid;
2557 vattr.va_gid = gid;
2558 vattr.va_mode = mode;
2559 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2560 }
2561out:
2562 VOP_UNLOCK(vp);
2563 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2564 return (error);
2565}
2566
2567/*
2568 * Set the access and modification times given a path name.
2569 */
2570int
2571sys_utimes(struct proc *p, void *v, register_t *retval)
2572{
2573 struct sys_utimes_args /* {
2574 syscallarg(const char *) path;
2575 syscallarg(const struct timeval *) tptr;
2576 } */ *uap = v;
2577
2578 struct timespec ts[2];
2579 struct timeval tv[2];
2580 const struct timeval *tvp;
2581 int error;
2582
2583 tvp = SCARG(uap, tptr)((uap)->tptr.le.datum);
2584 if (tvp != NULL((void *)0)) {
2585 error = copyin(tvp, tv, sizeof(tv));
2586 if (error)
2587 return (error);
2588#ifdef KTRACE1
2589 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
2590 ktrabstimeval(p, &tv)ktrstruct((p), "abstimeval", (&tv), sizeof(struct timeval
))
;
2591#endif
2592 if (!timerisvalid(&tv[0])((&tv[0])->tv_usec >= 0 && (&tv[0])->
tv_usec < 1000000)
|| !timerisvalid(&tv[1])((&tv[1])->tv_usec >= 0 && (&tv[1])->
tv_usec < 1000000)
)
2593 return (EINVAL22);
2594 TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0])do { (&ts[0])->tv_sec = (&tv[0])->tv_sec; (&
ts[0])->tv_nsec = (&tv[0])->tv_usec * 1000; } while
(0)
;
2595 TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1])do { (&ts[1])->tv_sec = (&tv[1])->tv_sec; (&
ts[1])->tv_nsec = (&tv[1])->tv_usec * 1000; } while
(0)
;
2596 } else
2597 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW-2L;
2598
2599 return (doutimensat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), ts, 0));
2600}
2601
2602int
2603sys_utimensat(struct proc *p, void *v, register_t *retval)
2604{
2605 struct sys_utimensat_args /* {
2606 syscallarg(int) fd;
2607 syscallarg(const char *) path;
2608 syscallarg(const struct timespec *) times;
2609 syscallarg(int) flag;
2610 } */ *uap = v;
2611
2612 struct timespec ts[2];
2613 const struct timespec *tsp;
2614 int error, i;
2615
2616 tsp = SCARG(uap, times)((uap)->times.le.datum);
2617 if (tsp != NULL((void *)0)) {
2618 error = copyin(tsp, ts, sizeof(ts));
2619 if (error)
2620 return (error);
2621 for (i = 0; i < nitems(ts)(sizeof((ts)) / sizeof((ts)[0])); i++) {
2622 if (ts[i].tv_nsec == UTIME_NOW-2L)
2623 continue;
2624 if (ts[i].tv_nsec == UTIME_OMIT-1L)
2625 continue;
2626#ifdef KTRACE1
2627 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
2628 ktrabstimespec(p, &ts[i])ktrstruct((p), "abstimespec", (&ts[i]), sizeof(struct timespec
))
;
2629#endif
2630 if (!timespecisvalid(&ts[i])((&ts[i])->tv_nsec >= 0 && (&ts[i])->
tv_nsec < 1000000000L)
)
2631 return (EINVAL22);
2632 }
2633 } else
2634 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW-2L;
2635
2636 return (doutimensat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum), ts,
2637 SCARG(uap, flag)((uap)->flag.le.datum)));
2638}
2639
2640int
2641doutimensat(struct proc *p, int fd, const char *path,
2642 struct timespec ts[2], int flag)
2643{
2644 struct vnode *vp;
2645 int error, follow;
2646 struct nameidata nd;
2647
2648 if (flag & ~AT_SYMLINK_NOFOLLOW0x02)
2649 return (EINVAL22);
2650
2651 follow = (flag & AT_SYMLINK_NOFOLLOW0x02) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2652 NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p)ndinitat(&nd, 0, follow, UIO_USERSPACE, fd, path, p);
2653 nd.ni_pledge = PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2654 nd.ni_unveil = UNVEIL_WRITE0x02;
2655 if ((error = namei(&nd)) != 0)
2656 return (error);
2657 vp = nd.ni_vp;
2658
2659 return (dovutimens(p, vp, ts));
2660}
2661
2662int
2663dovutimens(struct proc *p, struct vnode *vp, struct timespec ts[2])
2664{
2665 struct vattr vattr;
2666 struct timespec now;
2667 int error;
2668
2669#ifdef KTRACE1
2670 /* if they're both UTIME_NOW, then don't report either */
2671 if ((ts[0].tv_nsec != UTIME_NOW-2L || ts[1].tv_nsec != UTIME_NOW-2L) &&
2672 KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
) {
2673 ktrabstimespec(p, &ts[0])ktrstruct((p), "abstimespec", (&ts[0]), sizeof(struct timespec
))
;
2674 ktrabstimespec(p, &ts[1])ktrstruct((p), "abstimespec", (&ts[1]), sizeof(struct timespec
))
;
2675 }
2676#endif
2677
2678 VATTR_NULL(&vattr)vattr_null(&vattr);
2679
2680 /* make sure ctime is updated even if neither mtime nor atime is */
2681 vattr.va_vaflags = VA_UTIMES_CHANGE0x04;
2682
2683 if (ts[0].tv_nsec == UTIME_NOW-2L || ts[1].tv_nsec == UTIME_NOW-2L) {
2684 if (ts[0].tv_nsec == UTIME_NOW-2L && ts[1].tv_nsec == UTIME_NOW-2L)
2685 vattr.va_vaflags |= VA_UTIMES_NULL0x01;
2686
2687 getnanotime(&now);
2688 if (ts[0].tv_nsec == UTIME_NOW-2L)
2689 ts[0] = now;
2690 if (ts[1].tv_nsec == UTIME_NOW-2L)
2691 ts[1] = now;
2692 }
2693
2694 if (ts[0].tv_nsec != UTIME_OMIT-1L)
2695 vattr.va_atime = ts[0];
2696 if (ts[1].tv_nsec != UTIME_OMIT-1L)
2697 vattr.va_mtime = ts[1];
2698
2699 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2700 if (vp->v_mount->mnt_flag & MNT_RDONLY0x00000001)
2701 error = EROFS30;
2702 else
2703 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2704 vput(vp);
2705 return (error);
2706}
2707
2708/*
2709 * Set the access and modification times given a file descriptor.
2710 */
2711int
2712sys_futimes(struct proc *p, void *v, register_t *retval)
2713{
2714 struct sys_futimes_args /* {
2715 syscallarg(int) fd;
2716 syscallarg(const struct timeval *) tptr;
2717 } */ *uap = v;
2718 struct timeval tv[2];
2719 struct timespec ts[2];
2720 const struct timeval *tvp;
2721 int error;
2722
2723 tvp = SCARG(uap, tptr)((uap)->tptr.le.datum);
2724 if (tvp != NULL((void *)0)) {
2725 error = copyin(tvp, tv, sizeof(tv));
2726 if (error)
2727 return (error);
2728#ifdef KTRACE1
2729 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
) {
2730 ktrabstimeval(p, &tv[0])ktrstruct((p), "abstimeval", (&tv[0]), sizeof(struct timeval
))
;
2731 ktrabstimeval(p, &tv[1])ktrstruct((p), "abstimeval", (&tv[1]), sizeof(struct timeval
))
;
2732 }
2733#endif
2734 if (!timerisvalid(&tv[0])((&tv[0])->tv_usec >= 0 && (&tv[0])->
tv_usec < 1000000)
|| !timerisvalid(&tv[1])((&tv[1])->tv_usec >= 0 && (&tv[1])->
tv_usec < 1000000)
)
2735 return (EINVAL22);
2736 TIMEVAL_TO_TIMESPEC(&tv[0], &ts[0])do { (&ts[0])->tv_sec = (&tv[0])->tv_sec; (&
ts[0])->tv_nsec = (&tv[0])->tv_usec * 1000; } while
(0)
;
2737 TIMEVAL_TO_TIMESPEC(&tv[1], &ts[1])do { (&ts[1])->tv_sec = (&tv[1])->tv_sec; (&
ts[1])->tv_nsec = (&tv[1])->tv_usec * 1000; } while
(0)
;
2738 } else
2739 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW-2L;
2740
2741 return (dofutimens(p, SCARG(uap, fd)((uap)->fd.le.datum), ts));
2742}
2743
2744int
2745sys_futimens(struct proc *p, void *v, register_t *retval)
2746{
2747 struct sys_futimens_args /* {
2748 syscallarg(int) fd;
2749 syscallarg(const struct timespec *) times;
2750 } */ *uap = v;
2751 struct timespec ts[2];
2752 const struct timespec *tsp;
2753 int error, i;
2754
2755 tsp = SCARG(uap, times)((uap)->times.le.datum);
2756 if (tsp != NULL((void *)0)) {
2757 error = copyin(tsp, ts, sizeof(ts));
2758 if (error)
2759 return (error);
2760 for (i = 0; i < nitems(ts)(sizeof((ts)) / sizeof((ts)[0])); i++) {
2761 if (ts[i].tv_nsec == UTIME_NOW-2L)
2762 continue;
2763 if (ts[i].tv_nsec == UTIME_OMIT-1L)
2764 continue;
2765#ifdef KTRACE1
2766 if (KTRPOINT(p, KTR_STRUCT)((p)->p_p->ps_traceflag & (1<<(8)) &&
((p)->p_flag & 0x00000001) == 0)
)
2767 ktrabstimespec(p, &ts[i])ktrstruct((p), "abstimespec", (&ts[i]), sizeof(struct timespec
))
;
2768#endif
2769 if (!timespecisvalid(&ts[i])((&ts[i])->tv_nsec >= 0 && (&ts[i])->
tv_nsec < 1000000000L)
)
2770 return (EINVAL22);
2771 }
2772 } else
2773 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW-2L;
2774
2775 return (dofutimens(p, SCARG(uap, fd)((uap)->fd.le.datum), ts));
2776}
2777
2778int
2779dofutimens(struct proc *p, int fd, struct timespec ts[2])
2780{
2781 struct file *fp;
2782 struct vnode *vp;
2783 int error;
2784
2785 if ((error = getvnode(p, fd, &fp)) != 0)
2786 return (error);
2787 vp = fp->f_data;
2788 vref(vp);
2789 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2790
2791 return (dovutimens(p, vp, ts));
2792}
2793
2794/*
2795 * Truncate a file given a vnode.
2796 */
2797int
2798dotruncate(struct proc *p, struct vnode *vp, off_t len)
2799{
2800 struct vattr vattr;
2801 int error;
2802
2803 if (len < 0)
2804 return EINVAL22;
2805 if (vp->v_type == VDIR)
2806 return EISDIR21;
2807 if ((error = vn_writechk(vp)) != 0)
2808 return error;
2809 if (vp->v_type == VREG && len > lim_cur_proc(p, RLIMIT_FSIZE1)) {
2810 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2811 return error;
2812 if (len > vattr.va_size) {
2813 /* if extending over the limit, send signal and fail */
2814 psignal(p, SIGXFSZ25);
2815 return EFBIG27;
2816 }
2817 }
2818 VATTR_NULL(&vattr)vattr_null(&vattr);
2819 vattr.va_size = len;
2820 return VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2821}
2822
2823/*
2824 * Truncate a file given its path name.
2825 */
2826int
2827sys_truncate(struct proc *p, void *v, register_t *retval)
2828{
2829 struct sys_truncate_args /* {
2830 syscallarg(const char *) path;
2831 syscallarg(off_t) length;
2832 } */ *uap = v;
2833 struct vnode *vp;
2834 int error;
2835 struct nameidata nd;
2836
2837 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040, UIO_USERSPACE, -100, ((uap)->
path.le.datum), p)
;
2838 nd.ni_pledge = PLEDGE_FATTR0x0000000000004000ULL | PLEDGE_RPATH0x0000000000000001ULL;
2839 nd.ni_unveil = UNVEIL_WRITE0x02;
2840 if ((error = namei(&nd)) != 0)
2841 return (error);
2842 vp = nd.ni_vp;
2843 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2844 if ((error = VOP_ACCESS(vp, VWRITE00200, p->p_ucred, p)) == 0)
2845 error = dotruncate(p, vp, SCARG(uap, length)((uap)->length.le.datum));
2846 vput(vp);
2847 return (error);
2848}
2849
2850/*
2851 * Truncate a file given a file descriptor.
2852 */
2853int
2854sys_ftruncate(struct proc *p, void *v, register_t *retval)
2855{
2856 struct sys_ftruncate_args /* {
2857 syscallarg(int) fd;
2858 syscallarg(off_t) length;
2859 } */ *uap = v;
2860 struct vnode *vp;
2861 struct file *fp;
2862 int error;
2863
2864 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
2865 return (error);
2866 if ((fp->f_flag & FWRITE0x0002) == 0) {
2867 error = EINVAL22;
2868 goto bad;
2869 }
2870 vp = fp->f_data;
2871 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2872 error = dotruncate(p, vp, SCARG(uap, length)((uap)->length.le.datum));
2873 VOP_UNLOCK(vp);
2874bad:
2875 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2876 return (error);
2877}
2878
2879/*
2880 * Sync an open file.
2881 */
2882int
2883sys_fsync(struct proc *p, void *v, register_t *retval)
2884{
2885 struct sys_fsync_args /* {
2886 syscallarg(int) fd;
2887 } */ *uap = v;
2888 struct vnode *vp;
2889 struct file *fp;
2890 int error;
2891
2892 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
2893 return (error);
2894 vp = fp->f_data;
2895 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
2896 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT1, p);
2897#ifdef FFS_SOFTUPDATES1
2898 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP0x04000000))
2899 error = softdep_fsync(vp);
2900#endif
2901
2902 VOP_UNLOCK(vp);
2903 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
2904 return (error);
2905}
2906
2907/*
2908 * Rename files. Source and destination must either both be directories,
2909 * or both not be directories. If target is a directory, it must be empty.
2910 */
2911int
2912sys_rename(struct proc *p, void *v, register_t *retval)
2913{
2914 struct sys_rename_args /* {
2915 syscallarg(const char *) from;
2916 syscallarg(const char *) to;
2917 } */ *uap = v;
2918
2919 return (dorenameat(p, AT_FDCWD-100, SCARG(uap, from)((uap)->from.le.datum), AT_FDCWD-100,
2920 SCARG(uap, to)((uap)->to.le.datum)));
2921}
2922
2923int
2924sys_renameat(struct proc *p, void *v, register_t *retval)
2925{
2926 struct sys_renameat_args /* {
2927 syscallarg(int) fromfd;
2928 syscallarg(const char *) from;
2929 syscallarg(int) tofd;
2930 syscallarg(const char *) to;
2931 } */ *uap = v;
2932
2933 return (dorenameat(p, SCARG(uap, fromfd)((uap)->fromfd.le.datum), SCARG(uap, from)((uap)->from.le.datum),
2934 SCARG(uap, tofd)((uap)->tofd.le.datum), SCARG(uap, to)((uap)->to.le.datum)));
2935}
2936
2937int
2938dorenameat(struct proc *p, int fromfd, const char *from, int tofd,
2939 const char *to)
2940{
2941 struct vnode *tvp, *fvp, *tdvp;
2942 struct nameidata fromnd, tond;
2943 int error;
2944 int flags;
2945
2946 NDINITAT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,ndinitat(&fromnd, 2, 0x0010 | 0x001000, UIO_USERSPACE, fromfd
, from, p)
2947 fromfd, from, p)ndinitat(&fromnd, 2, 0x0010 | 0x001000, UIO_USERSPACE, fromfd
, from, p)
;
2948 fromnd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_CPATH0x0000000000000004ULL;
2949 fromnd.ni_unveil = UNVEIL_READ0x01 | UNVEIL_CREATE0x04;
2950 if ((error = namei(&fromnd)) != 0)
2951 return (error);
2952 fvp = fromnd.ni_vp;
2953
2954 flags = LOCKPARENT0x0008 | LOCKLEAF0x0004 | NOCACHE0x0020 | SAVESTART0x001000;
2955 /*
2956 * rename("foo/", "bar/"); is OK
2957 */
2958 if (fvp->v_type == VDIR)
2959 flags |= STRIPSLASHES0x100000;
2960
2961 NDINITAT(&tond, RENAME, flags, UIO_USERSPACE, tofd, to, p)ndinitat(&tond, 3, flags, UIO_USERSPACE, tofd, to, p);
2962 tond.ni_pledge = PLEDGE_CPATH0x0000000000000004ULL;
2963 tond.ni_unveil = UNVEIL_CREATE0x04;
2964 if ((error = namei(&tond)) != 0) {
2965 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2966 vrele(fromnd.ni_dvp);
2967 vrele(fvp);
2968 goto out1;
2969 }
2970 tdvp = tond.ni_dvp;
2971 tvp = tond.ni_vp;
2972 if (tvp != NULL((void *)0)) {
2973 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2974 error = ENOTDIR20;
2975 goto out;
2976 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2977 error = EISDIR21;
2978 goto out;
2979 }
2980 }
2981 if (fvp == tdvp)
2982 error = EINVAL22;
2983 /*
2984 * If source is the same as the destination (that is the
2985 * same inode number)
2986 */
2987 if (fvp == tvp)
2988 error = -1;
2989out:
2990 if (!error) {
2991 if (tvp) {
2992 (void)uvm_vnp_uncache(tvp);
2993 }
2994 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2995 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2996 } else {
2997 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2998 if (tdvp == tvp)
2999 vrele(tdvp);
3000 else
3001 vput(tdvp);
3002 if (tvp)
3003 vput(tvp);
3004 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3005 vrele(fromnd.ni_dvp);
3006 vrele(fvp);
3007 }
3008 vrele(tond.ni_startdir);
3009 pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
3010out1:
3011 if (fromnd.ni_startdir)
3012 vrele(fromnd.ni_startdir);
3013 pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
3014 if (error == -1)
3015 return (0);
3016 return (error);
3017}
3018
3019/*
3020 * Make a directory file.
3021 */
3022int
3023sys_mkdir(struct proc *p, void *v, register_t *retval)
3024{
3025 struct sys_mkdir_args /* {
3026 syscallarg(const char *) path;
3027 syscallarg(mode_t) mode;
3028 } */ *uap = v;
3029
3030 return (domkdirat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), SCARG(uap, mode)((uap)->mode.le.datum)));
3031}
3032
3033int
3034sys_mkdirat(struct proc *p, void *v, register_t *retval)
3035{
3036 struct sys_mkdirat_args /* {
3037 syscallarg(int) fd;
3038 syscallarg(const char *) path;
3039 syscallarg(mode_t) mode;
3040 } */ *uap = v;
3041
3042 return (domkdirat(p, SCARG(uap, fd)((uap)->fd.le.datum), SCARG(uap, path)((uap)->path.le.datum),
3043 SCARG(uap, mode)((uap)->mode.le.datum)));
3044}
3045
3046int
3047domkdirat(struct proc *p, int fd, const char *path, mode_t mode)
3048{
3049 struct vnode *vp;
3050 struct vattr vattr;
3051 int error;
3052 struct nameidata nd;
3053
3054 NDINITAT(&nd, CREATE, LOCKPARENT | STRIPSLASHES, UIO_USERSPACE,ndinitat(&nd, 1, 0x0008 | 0x100000, UIO_USERSPACE, fd, path
, p)
3055 fd, path, p)ndinitat(&nd, 1, 0x0008 | 0x100000, UIO_USERSPACE, fd, path
, p)
;
3056 nd.ni_pledge = PLEDGE_CPATH0x0000000000000004ULL;
3057 nd.ni_unveil = UNVEIL_CREATE0x04;
3058 if ((error = namei(&nd)) != 0)
3059 return (error);
3060 vp = nd.ni_vp;
3061 if (vp != NULL((void *)0)) {
3062 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
3063 if (nd.ni_dvp == vp)
3064 vrele(nd.ni_dvp);
3065 else
3066 vput(nd.ni_dvp);
3067 vrele(vp);
3068 return (EEXIST17);
3069 }
3070 VATTR_NULL(&vattr)vattr_null(&vattr);
3071 vattr.va_type = VDIR;
3072 vattr.va_mode = (mode & ACCESSPERMS(0000700|0000070|0000007)) &~ p->p_fd->fd_cmask;
3073 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3074 if (!error)
3075 vput(nd.ni_vp);
3076 return (error);
3077}
3078
3079/*
3080 * Remove a directory file.
3081 */
3082int
3083sys_rmdir(struct proc *p, void *v, register_t *retval)
3084{
3085 struct sys_rmdir_args /* {
3086 syscallarg(const char *) path;
3087 } */ *uap = v;
3088
3089 return (dounlinkat(p, AT_FDCWD-100, SCARG(uap, path)((uap)->path.le.datum), AT_REMOVEDIR0x08));
3090}
3091
3092/*
3093 * Read a block of directory entries in a file system independent format.
3094 */
3095int
3096sys_getdents(struct proc *p, void *v, register_t *retval)
3097{
3098 struct sys_getdents_args /* {
3099 syscallarg(int) fd;
3100 syscallarg(void *) buf;
3101 syscallarg(size_t) buflen;
3102 } */ *uap = v;
3103 struct vnode *vp;
3104 struct file *fp;
3105 struct uio auio;
3106 struct iovec aiov;
3107 size_t buflen;
3108 int error, eofflag;
3109
3110 buflen = SCARG(uap, buflen)((uap)->buflen.le.datum);
3111
3112 if (buflen > INT_MAX0x7fffffff)
3113 return (EINVAL22);
3114 if ((error = getvnode(p, SCARG(uap, fd)((uap)->fd.le.datum), &fp)) != 0)
3115 return (error);
3116 if ((fp->f_flag & FREAD0x0001) == 0) {
3117 error = EBADF9;
3118 goto bad;
3119 }
3120 vp = fp->f_data;
3121 if (vp->v_type != VDIR) {
3122 error = EINVAL22;
3123 goto bad;
3124 }
3125
3126 vn_lock(vp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
3127
3128 if (fp->f_offset < 0) {
3129 VOP_UNLOCK(vp);
3130 error = EINVAL22;
3131 goto bad;
3132 }
3133
3134 aiov.iov_base = SCARG(uap, buf)((uap)->buf.le.datum);
3135 aiov.iov_len = buflen;
3136 auio.uio_iov = &aiov;
3137 auio.uio_iovcnt = 1;
3138 auio.uio_rw = UIO_READ;
3139 auio.uio_segflg = UIO_USERSPACE;
3140 auio.uio_procp = p;
3141 auio.uio_resid = buflen;
3142 auio.uio_offset = fp->f_offset;
3143 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
3144 mtx_enter(&fp->f_mtx);
3145 fp->f_offset = auio.uio_offset;
3146 mtx_leave(&fp->f_mtx);
3147 VOP_UNLOCK(vp);
3148 if (error)
3149 goto bad;
3150 *retval = buflen - auio.uio_resid;
3151bad:
3152 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
3153 return (error);
3154}
3155
3156/*
3157 * Set the mode mask for creation of filesystem nodes.
3158 */
3159int
3160sys_umask(struct proc *p, void *v, register_t *retval)
3161{
3162 struct sys_umask_args /* {
3163 syscallarg(mode_t) newmask;
3164 } */ *uap = v;
3165 struct filedesc *fdp = p->p_fd;
3166
3167 fdplock(fdp)do { do { int _s = rw_status(&netlock); if ((splassert_ctl
> 0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL
, __func__); } while (0); rw_enter_write(&(fdp)->fd_lock
); } while (0)
;
3168 *retval = fdp->fd_cmask;
3169 fdp->fd_cmask = SCARG(uap, newmask)((uap)->newmask.le.datum) & ACCESSPERMS(0000700|0000070|0000007);
3170 fdpunlock(fdp)rw_exit_write(&(fdp)->fd_lock);
3171 return (0);
3172}
3173
3174/*
3175 * Void all references to file by ripping underlying filesystem
3176 * away from vnode.
3177 */
3178int
3179sys_revoke(struct proc *p, void *v, register_t *retval)
3180{
3181 struct sys_revoke_args /* {
3182 syscallarg(const char *) path;
3183 } */ *uap = v;
3184 struct vnode *vp;
3185 struct vattr vattr;
3186 int error;
3187 struct nameidata nd;
3188
3189 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p)ndinitat(&nd, 0, 0x0040, UIO_USERSPACE, -100, ((uap)->
path.le.datum), p)
;
3190 nd.ni_pledge = PLEDGE_RPATH0x0000000000000001ULL | PLEDGE_TTY0x0000000000010000ULL;
3191 nd.ni_unveil = UNVEIL_READ0x01;
3192 if ((error = namei(&nd)) != 0)
3193 return (error);
3194 vp = nd.ni_vp;
3195 if (vp->v_type != VCHR || (u_int)major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8)
& 0xff)
>= nchrdev ||
3196 cdevsw[major(vp->v_rdev)(((unsigned)(vp->v_un.vu_specinfo->si_rdev) >> 8)
& 0xff)
].d_type != D_TTY2) {
3197 error = ENOTTY25;
3198 goto out;
3199 }
3200 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
3201 goto out;
3202 if (p->p_ucred->cr_uid != vattr.va_uid &&
3203 (error = suser(p)))
3204 goto out;
3205 if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED0x0800)))
3206 VOP_REVOKE(vp, REVOKEALL0x0001);
3207out:
3208 vrele(vp);
3209 return (error);
3210}
3211
3212/*
3213 * Convert a user file descriptor to a kernel file entry.
3214 *
3215 * On return *fpp is FREF:ed.
3216 */
3217int
3218getvnode(struct proc *p, int fd, struct file **fpp)
3219{
3220 struct file *fp;
3221 struct vnode *vp;
3222
3223 if ((fp = fd_getfile(p->p_fd, fd)) == NULL((void *)0))
3224 return (EBADF9);
3225
3226 if (fp->f_type != DTYPE_VNODE1) {
3227 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
3228 return (EINVAL22);
3229 }
3230
3231 vp = fp->f_data;
3232 if (vp->v_type == VBAD) {
3233 FRELE(fp, p)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, p) : 0)
;
3234 return (EBADF9);
3235 }
3236
3237 *fpp = fp;
3238
3239 return (0);
3240}
3241
3242/*
3243 * Positional read system call.
3244 */
3245int
3246sys_pread(struct proc *p, void *v, register_t *retval)
3247{
3248 struct sys_pread_args /* {
3249 syscallarg(int) fd;
3250 syscallarg(void *) buf;
3251 syscallarg(size_t) nbyte;
3252 syscallarg(off_t) offset;
3253 } */ *uap = v;
3254 struct iovec iov;
3255 struct uio auio;
3256
3257 iov.iov_base = SCARG(uap, buf)((uap)->buf.le.datum);
3258 iov.iov_len = SCARG(uap, nbyte)((uap)->nbyte.le.datum);
3259 if (iov.iov_len > SSIZE_MAX0x7fffffffffffffffL)
3260 return (EINVAL22);
3261
3262 auio.uio_iov = &iov;
3263 auio.uio_iovcnt = 1;
3264 auio.uio_resid = iov.iov_len;
3265 auio.uio_offset = SCARG(uap, offset)((uap)->offset.le.datum);
3266
3267 return (dofilereadv(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, FO_POSITION0x00000001, retval));
3268}
3269
3270/*
3271 * Positional scatter read system call.
3272 */
3273int
3274sys_preadv(struct proc *p, void *v, register_t *retval)
3275{
3276 struct sys_preadv_args /* {
3277 syscallarg(int) fd;
3278 syscallarg(const struct iovec *) iovp;
3279 syscallarg(int) iovcnt;
3280 syscallarg(off_t) offset;
3281 } */ *uap = v;
3282 struct iovec aiov[UIO_SMALLIOV8], *iov = NULL((void *)0);
3283 int error, iovcnt = SCARG(uap, iovcnt)((uap)->iovcnt.le.datum);
3284 struct uio auio;
3285 size_t resid;
3286
3287 error = iovec_copyin(SCARG(uap, iovp)((uap)->iovp.le.datum), &iov, aiov, iovcnt, &resid);
3288 if (error)
3289 goto done;
3290
3291 auio.uio_iov = iov;
3292 auio.uio_iovcnt = iovcnt;
3293 auio.uio_resid = resid;
3294 auio.uio_offset = SCARG(uap, offset)((uap)->offset.le.datum);
3295
3296 error = dofilereadv(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, FO_POSITION0x00000001, retval);
3297 done:
3298 iovec_free(iov, iovcnt);
3299 return (error);
3300}
3301
3302/*
3303 * Positional write system call.
3304 */
3305int
3306sys_pwrite(struct proc *p, void *v, register_t *retval)
3307{
3308 struct sys_pwrite_args /* {
3309 syscallarg(int) fd;
3310 syscallarg(const void *) buf;
3311 syscallarg(size_t) nbyte;
3312 syscallarg(off_t) offset;
3313 } */ *uap = v;
3314 struct iovec iov;
3315 struct uio auio;
3316
3317 iov.iov_base = (void *)SCARG(uap, buf)((uap)->buf.le.datum);
3318 iov.iov_len = SCARG(uap, nbyte)((uap)->nbyte.le.datum);
3319 if (iov.iov_len > SSIZE_MAX0x7fffffffffffffffL)
3320 return (EINVAL22);
3321
3322 auio.uio_iov = &iov;
3323 auio.uio_iovcnt = 1;
3324 auio.uio_resid = iov.iov_len;
3325 auio.uio_offset = SCARG(uap, offset)((uap)->offset.le.datum);
3326
3327 return (dofilewritev(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, FO_POSITION0x00000001, retval));
3328}
3329
3330/*
3331 * Positional gather write system call.
3332 */
3333int
3334sys_pwritev(struct proc *p, void *v, register_t *retval)
3335{
3336 struct sys_pwritev_args /* {
3337 syscallarg(int) fd;
3338 syscallarg(const struct iovec *) iovp;
3339 syscallarg(int) iovcnt;
3340 syscallarg(off_t) offset;
3341 } */ *uap = v;
3342 struct iovec aiov[UIO_SMALLIOV8], *iov = NULL((void *)0);
3343 int error, iovcnt = SCARG(uap, iovcnt)((uap)->iovcnt.le.datum);
3344 struct uio auio;
3345 size_t resid;
3346
3347 error = iovec_copyin(SCARG(uap, iovp)((uap)->iovp.le.datum), &iov, aiov, iovcnt, &resid);
3348 if (error)
3349 goto done;
3350
3351 auio.uio_iov = iov;
3352 auio.uio_iovcnt = iovcnt;
3353 auio.uio_resid = resid;
3354 auio.uio_offset = SCARG(uap, offset)((uap)->offset.le.datum);
3355
3356 error = dofilewritev(p, SCARG(uap, fd)((uap)->fd.le.datum), &auio, FO_POSITION0x00000001, retval);
3357 done:
3358 iovec_free(iov, iovcnt);
3359 return (error);
3360}