Bug Summary

File:kern/vfs_syscalls.c
Warning:line 291, column 4
Value stored to 'error' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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