Bug Summary

File:kern/vfs_syscalls.c
Warning:line 582, column 11
Copies out a struct with uncleared padding (>= 4 bytes)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-freebsd11.2 -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 -mrelocation-model static -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -masm-verbose -mconstructor-aliases -ffreestanding -mcode-model kernel -target-cpu x86-64 -target-feature -mmx -target-feature -sse -target-feature -aes -target-feature -avx -disable-red-zone -no-implicit-float -dwarf-column-info -debugger-tuning=gdb -nostdsysteminc -nobuiltininc -resource-dir /root/kernel-uninitialized-memory-checker/build/lib/clang/8.0.0 -include opt_global.h -I . -I /root/freebsd/sys -I /root/freebsd/sys/contrib/ck/include -I /root/freebsd/sys/contrib/libfdt -D _KERNEL -D HAVE_KERNEL_OPTION_HEADERS -D __printf__=__freebsd_kprintf__ -O2 -Wno-pointer-sign -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-address-of-packed-member -std=iso9899:1999 -fdebug-compilation-dir /usr/obj/root/freebsd/amd64.amd64/sys/GENERIC -ferror-limit 19 -fmessage-length 0 -fwrapv -stack-protector 1 -fobjc-runtime=gnustep -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker alpha.security.KernelMemoryDisclosure -analyzer-disable-checker core,unix,deadcode,nullability -analyzer-output=html -o /root/analyzer/2018-12-28-044519-76292-1 -x c /root/freebsd/sys/kern/vfs_syscalls.c -faddrsig
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD$")__asm__(".ident\t\"" "$FreeBSD$" "\"");
41
42#include "opt_capsicum.h"
43#include "opt_ktrace.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/bio.h>
48#include <sys/buf.h>
49#include <sys/capsicum.h>
50#include <sys/disk.h>
51#include <sys/sysent.h>
52#include <sys/malloc.h>
53#include <sys/mount.h>
54#include <sys/mutex.h>
55#include <sys/sysproto.h>
56#include <sys/namei.h>
57#include <sys/filedesc.h>
58#include <sys/kernel.h>
59#include <sys/fcntl.h>
60#include <sys/file.h>
61#include <sys/filio.h>
62#include <sys/limits.h>
63#include <sys/linker.h>
64#include <sys/rwlock.h>
65#include <sys/sdt.h>
66#include <sys/stat.h>
67#include <sys/sx.h>
68#include <sys/unistd.h>
69#include <sys/vnode.h>
70#include <sys/priv.h>
71#include <sys/proc.h>
72#include <sys/dirent.h>
73#include <sys/jail.h>
74#include <sys/syscallsubr.h>
75#include <sys/sysctl.h>
76#ifdef KTRACE1
77#include <sys/ktrace.h>
78#endif
79
80#include <machine/stdarg.h>
81
82#include <security/audit/audit.h>
83#include <security/mac/mac_framework.h>
84
85#include <vm/vm.h>
86#include <vm/vm_object.h>
87#include <vm/vm_page.h>
88#include <vm/uma.h>
89
90#include <ufs/ufs/quota.h>
91
92MALLOC_DEFINE(M_FADVISE, "fadvise", "posix_fadvise(2) information")struct malloc_type M_FADVISE[1] = { { ((void *)0), 877983977,
"fadvise", ((void *)0) } }; static struct sysinit M_FADVISE_init_sys_init
= { SI_SUB_KMEM, SI_ORDER_THIRD, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_init, ((void *)(M_FADVISE)) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* __set_sysinit_set_sym_M_FADVISE_init_sys_init __attribute__
((__section__("set_" "sysinit_set"))) __attribute__((__used__
)) = &(M_FADVISE_init_sys_init); static struct sysinit M_FADVISE_uninit_sys_uninit
= { SI_SUB_KMEM, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_uninit, ((void *)(M_FADVISE)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * __set_sysuninit_set_sym_M_FADVISE_uninit_sys_uninit __attribute__
((__section__("set_" "sysuninit_set"))) __attribute__((__used__
)) = &(M_FADVISE_uninit_sys_uninit)
;
93
94SDT_PROVIDER_DEFINE(vfs)struct sdt_provider sdt_provider_vfs[1] = { { "vfs", { ((void
*)0), ((void *)0) }, 0, 0 } }; __asm__(".globl " "__start_set_sdt_providers_set"
); __asm__(".globl " "__stop_set_sdt_providers_set"); static void
const * const __set_sdt_providers_set_sym_sdt_provider_vfs __attribute__
((__section__("set_" "sdt_providers_set"))) __attribute__((__used__
)) = &(sdt_provider_vfs);
;
95SDT_PROBE_DEFINE2(vfs, , stat, mode, "char *", "int")struct sdt_probe sdt_vfs__stat_mode[1] = { { sizeof(struct sdt_probe
), sdt_provider_vfs, { ((void *)0), ((void *)0) }, { ((void *
)0), ((void *)0) }, "", "stat", "mode", 0, 0, ((void *)0) } }
; __asm__(".globl " "__start_set_sdt_probes_set"); __asm__(".globl "
"__stop_set_sdt_probes_set"); static void const * const __set_sdt_probes_set_sym_sdt_vfs__stat_mode
__attribute__((__section__("set_" "sdt_probes_set"))) __attribute__
((__used__)) = &(sdt_vfs__stat_mode);; static struct sdt_argtype
sdta_vfs__stat_mode0[1] = { { 0, "char *", ((void *)0), { ((
void *)0), ((void *)0) }, sdt_vfs__stat_mode } }; __asm__(".globl "
"__start_set_sdt_argtypes_set"); __asm__(".globl " "__stop_set_sdt_argtypes_set"
); static void const * const __set_sdt_argtypes_set_sym_sdta_vfs__stat_mode0
__attribute__((__section__("set_" "sdt_argtypes_set"))) __attribute__
((__used__)) = &(sdta_vfs__stat_mode0);; static struct sdt_argtype
sdta_vfs__stat_mode1[1] = { { 1, "int", ((void *)0), { ((void
*)0), ((void *)0) }, sdt_vfs__stat_mode } }; __asm__(".globl "
"__start_set_sdt_argtypes_set"); __asm__(".globl " "__stop_set_sdt_argtypes_set"
); static void const * const __set_sdt_argtypes_set_sym_sdta_vfs__stat_mode1
__attribute__((__section__("set_" "sdt_argtypes_set"))) __attribute__
((__used__)) = &(sdta_vfs__stat_mode1);
;
96SDT_PROBE_DEFINE2(vfs, , stat, reg, "char *", "int")struct sdt_probe sdt_vfs__stat_reg[1] = { { sizeof(struct sdt_probe
), sdt_provider_vfs, { ((void *)0), ((void *)0) }, { ((void *
)0), ((void *)0) }, "", "stat", "reg", 0, 0, ((void *)0) } };
__asm__(".globl " "__start_set_sdt_probes_set"); __asm__(".globl "
"__stop_set_sdt_probes_set"); static void const * const __set_sdt_probes_set_sym_sdt_vfs__stat_reg
__attribute__((__section__("set_" "sdt_probes_set"))) __attribute__
((__used__)) = &(sdt_vfs__stat_reg);; static struct sdt_argtype
sdta_vfs__stat_reg0[1] = { { 0, "char *", ((void *)0), { ((void
*)0), ((void *)0) }, sdt_vfs__stat_reg } }; __asm__(".globl "
"__start_set_sdt_argtypes_set"); __asm__(".globl " "__stop_set_sdt_argtypes_set"
); static void const * const __set_sdt_argtypes_set_sym_sdta_vfs__stat_reg0
__attribute__((__section__("set_" "sdt_argtypes_set"))) __attribute__
((__used__)) = &(sdta_vfs__stat_reg0);; static struct sdt_argtype
sdta_vfs__stat_reg1[1] = { { 1, "int", ((void *)0), { ((void
*)0), ((void *)0) }, sdt_vfs__stat_reg } }; __asm__(".globl "
"__start_set_sdt_argtypes_set"); __asm__(".globl " "__stop_set_sdt_argtypes_set"
); static void const * const __set_sdt_argtypes_set_sym_sdta_vfs__stat_reg1
__attribute__((__section__("set_" "sdt_argtypes_set"))) __attribute__
((__used__)) = &(sdta_vfs__stat_reg1);
;
97
98static int kern_chflagsat(struct thread *td, int fd, const char *path,
99 enum uio_seg pathseg, u_long flags, int atflag);
100static int setfflags(struct thread *td, struct vnode *, u_long);
101static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
102static int getutimens(const struct timespec *, enum uio_seg,
103 struct timespec *, int *);
104static int setutimes(struct thread *td, struct vnode *,
105 const struct timespec *, int, int);
106static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
107 struct thread *td);
108static int kern_fhlinkat(struct thread *td, int fd, const char *path,
109 enum uio_seg pathseg, fhandle_t *fhp);
110static int kern_getfhat(struct thread *td, int flags, int fd,
111 const char *path, enum uio_seg pathseg, fhandle_t *fhp);
112static int kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg,
113 size_t count, struct thread *td);
114static int kern_linkat_vp(struct thread *td, struct vnode *vp, int fd,
115 const char *path, enum uio_seg segflag);
116
117/*
118 * Sync each mounted filesystem.
119 */
120#ifndef _SYS_SYSPROTO_H_
121struct sync_args {
122 int dummy;
123};
124#endif
125/* ARGSUSED */
126int
127sys_sync(struct thread *td, struct sync_args *uap)
128{
129 struct mount *mp, *nmp;
130 int save;
131
132 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (132))
;
133 for (mp = TAILQ_FIRST(&mountlist)((&mountlist)->tqh_first); mp != NULL((void *)0); mp = nmp) {
134 if (vfs_busy(mp, MBF_NOWAIT0x01 | MBF_MNTLSTLOCK0x02)) {
135 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
136 continue;
137 }
138 if ((mp->mnt_flag & MNT_RDONLY0x0000000000000001ULL) == 0 &&
139 vn_start_write(NULL((void *)0), &mp, V_NOWAIT0x0002) == 0) {
140 save = curthread_pflags_set(TDP_SYNCIO0x00000800);
141 vfs_msync(mp, MNT_NOWAIT2);
142 VFS_SYNC(mp, MNT_NOWAIT)({ int _rc; _rc = (*(mp)->mnt_op->vfs_sync)(mp, 2); _rc
; })
;
143 curthread_pflags_restore(save);
144 vn_finished_write(mp);
145 }
146 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (146))
;
147 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
148 vfs_unbusy(mp);
149 }
150 mtx_unlock(&mountlist_mtx)__mtx_unlock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (150))
;
151 return (0);
152}
153
154/*
155 * Change filesystem quotas.
156 */
157#ifndef _SYS_SYSPROTO_H_
158struct quotactl_args {
159 char *path;
160 int cmd;
161 int uid;
162 caddr_t arg;
163};
164#endif
165int
166sys_quotactl(struct thread *td, struct quotactl_args *uap)
167{
168 struct mount *mp;
169 struct nameidata nd;
170 int error;
171
172 AUDIT_ARG_CMD(uap->cmd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_cmd((uap->cmd)); } while (0)
;
173 AUDIT_ARG_UID(uap->uid)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_uid((uap->uid)); } while (0)
;
174 if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS0x00000020))
175 return (EPERM1);
176 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,NDINIT_ALL(&nd, 0, 0x0040 | 0x0004 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
177 uap->path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0004 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
;
178 if ((error = namei(&nd)) != 0)
179 return (error);
180 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
181 mp = nd.ni_vp->v_mount;
182 vfs_ref(mp);
183 vput(nd.ni_vp);
184 error = vfs_busy(mp, 0);
185 vfs_rel(mp);
186 if (error != 0)
187 return (error);
188 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg)({ int _rc; _rc = (*(mp)->mnt_op->vfs_quotactl)(mp, uap
->cmd, uap->uid, uap->arg); _rc; })
;
189
190 /*
191 * Since quota on operation typically needs to open quota
192 * file, the Q_QUOTAON handler needs to unbusy the mount point
193 * before calling into namei. Otherwise, unmount might be
194 * started between two vfs_busy() invocations (first is our,
195 * second is from mount point cross-walk code in lookup()),
196 * causing deadlock.
197 *
198 * Require that Q_QUOTAON handles the vfs_busy() reference on
199 * its own, always returning with ubusied mount point.
200 */
201 if ((uap->cmd >> SUBCMDSHIFT8) != Q_QUOTAON0x0100 &&
202 (uap->cmd >> SUBCMDSHIFT8) != Q_QUOTAOFF0x0200)
203 vfs_unbusy(mp);
204 return (error);
205}
206
207/*
208 * Used by statfs conversion routines to scale the block size up if
209 * necessary so that all of the block counts are <= 'max_size'. Note
210 * that 'max_size' should be a bitmask, i.e. 2^n - 1 for some non-zero
211 * value of 'n'.
212 */
213void
214statfs_scale_blocks(struct statfs *sf, long max_size)
215{
216 uint64_t count;
217 int shift;
218
219 KASSERT(powerof2(max_size + 1), ("%s: invalid max_size", __func__))do { if (__builtin_expect((!(((((max_size + 1)-1)&(max_size
+ 1))==0))), 0)) panic ("%s: invalid max_size", __func__); }
while (0)
;
220
221 /*
222 * Attempt to scale the block counts to give a more accurate
223 * overview to userland of the ratio of free space to used
224 * space. To do this, find the largest block count and compute
225 * a divisor that lets it fit into a signed integer <= max_size.
226 */
227 if (sf->f_bavail < 0)
228 count = -sf->f_bavail;
229 else
230 count = sf->f_bavail;
231 count = MAX(sf->f_blocks, MAX(sf->f_bfree, count))(((sf->f_blocks)>((((sf->f_bfree)>(count))?(sf->
f_bfree):(count))))?(sf->f_blocks):((((sf->f_bfree)>
(count))?(sf->f_bfree):(count))))
;
232 if (count <= max_size)
233 return;
234
235 count >>= flsl(max_size);
236 shift = 0;
237 while (count > 0) {
238 shift++;
239 count >>=1;
240 }
241
242 sf->f_bsize <<= shift;
243 sf->f_blocks >>= shift;
244 sf->f_bfree >>= shift;
245 sf->f_bavail >>= shift;
246}
247
248static int
249kern_do_statfs(struct thread *td, struct mount *mp, struct statfs *buf)
250{
251 struct statfs *sp;
252 int error;
253
254 if (mp == NULL((void *)0))
255 return (EBADF9);
256 error = vfs_busy(mp, 0);
257 vfs_rel(mp);
258 if (error != 0)
259 return (error);
260#ifdef MAC1
261 error = mac_mount_check_stat(td->td_ucred, mp);
262 if (error != 0)
263 goto out;
264#endif
265 /*
266 * Set these in case the underlying filesystem fails to do so.
267 */
268 sp = &mp->mnt_stat;
269 sp->f_version = STATFS_VERSION0x20140518;
270 sp->f_namemax = NAME_MAX255;
271 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK(0x0000000000000001ULL | 0x0000000000000002ULL | 0x0000000000000004ULL
| 0x0000000000000008ULL | 0x0000000000000020ULL | 0x0000000100000000ULL
| 0x0000000000000040ULL | 0x0000000000000080ULL | 0x0000000000000100ULL
| 0x0000000000000200ULL | 0x0000000000000400ULL| 0x0000000000000800ULL
| 0x0000000000001000ULL | 0x0000000000008000ULL | 0x0000000000002000ULL
| 0x0000000000004000ULL | 0x0000000010000000ULL | 0x0000000040000000ULL
| 0x0000000080000000ULL | 0x0000000000100000ULL | 0x0000000000200000ULL
| 0x0000000000800000ULL | 0x0000000020000000ULL | 0x0000000000400000ULL
| 0x0000000002000000ULL | 0x0000000004000000ULL | 0x0000000008000000ULL
| 0x0000000000000010ULL | 0x0000000200000000ULL | 0x0000000400000000ULL
)
;
272 error = VFS_STATFS(mp, sp)({ int _rc; _rc = __vfs_statfs((mp), (sp)); _rc; });
273 if (error != 0)
274 goto out;
275 *buf = *sp;
276 if (priv_check(td, PRIV_VFS_GENERATION326)) {
277 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
278 prison_enforce_statfs(td->td_ucred, mp, buf);
279 }
280out:
281 vfs_unbusy(mp);
282 return (error);
283}
284
285/*
286 * Get filesystem statistics.
287 */
288#ifndef _SYS_SYSPROTO_H_
289struct statfs_args {
290 char *path;
291 struct statfs *buf;
292};
293#endif
294int
295sys_statfs(struct thread *td, struct statfs_args *uap)
296{
297 struct statfs *sfp;
298 int error;
299
300 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
301 error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
302 if (error == 0)
303 error = copyout(sfp, uap->buf, sizeof(struct statfs));
304 free(sfp, M_STATFS);
305 return (error);
306}
307
308int
309kern_statfs(struct thread *td, const char *path, enum uio_seg pathseg,
310 struct statfs *buf)
311{
312 struct mount *mp;
313 struct nameidata nd;
314 int error;
315
316 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, -100, ((void *)0), 0, td)
317 pathseg, path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, -100, ((void *)0), 0, td)
;
318 error = namei(&nd);
319 if (error != 0)
320 return (error);
321 mp = nd.ni_vp->v_mount;
322 vfs_ref(mp);
323 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
324 vput(nd.ni_vp);
325 return (kern_do_statfs(td, mp, buf));
326}
327
328/*
329 * Get filesystem statistics.
330 */
331#ifndef _SYS_SYSPROTO_H_
332struct fstatfs_args {
333 int fd;
334 struct statfs *buf;
335};
336#endif
337int
338sys_fstatfs(struct thread *td, struct fstatfs_args *uap)
339{
340 struct statfs *sfp;
341 int error;
342
343 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
344 error = kern_fstatfs(td, uap->fd, sfp);
345 if (error == 0)
346 error = copyout(sfp, uap->buf, sizeof(struct statfs));
347 free(sfp, M_STATFS);
348 return (error);
349}
350
351int
352kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
353{
354 struct file *fp;
355 struct mount *mp;
356 struct vnode *vp;
357 int error;
358
359 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
360 error = getvnode(td, fd, &cap_fstatfs_rights, &fp);
361 if (error != 0)
362 return (error);
363 vp = fp->f_vnode;
364 vn_lock(vp, LK_SHARED | LK_RETRY)_vn_lock(vp, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 364)
;
365#ifdef AUDIT1
366 AUDIT_ARG_VNODE1(vp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((vp)); } while (0)
;
367#endif
368 mp = vp->v_mount;
369 if (mp != NULL((void *)0))
370 vfs_ref(mp);
371 VOP_UNLOCK(vp, 0);
372 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
373 return (kern_do_statfs(td, mp, buf));
374}
375
376/*
377 * Get statistics on all filesystems.
378 */
379#ifndef _SYS_SYSPROTO_H_
380struct getfsstat_args {
381 struct statfs *buf;
382 long bufsize;
383 int mode;
384};
385#endif
386int
387sys_getfsstat(struct thread *td, struct getfsstat_args *uap)
388{
389 size_t count;
390 int error;
391
392 if (uap->bufsize < 0 || uap->bufsize > SIZE_MAX0xffffffffffffffff)
393 return (EINVAL22);
394 error = kern_getfsstat(td, &uap->buf, uap->bufsize, &count,
395 UIO_USERSPACE, uap->mode);
396 if (error == 0)
397 td->td_retvaltd_uretoff.tdu_retval[0] = count;
398 return (error);
399}
400
401/*
402 * If (bufsize > 0 && bufseg == UIO_SYSSPACE)
403 * The caller is responsible for freeing memory which will be allocated
404 * in '*buf'.
405 */
406int
407kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
408 size_t *countp, enum uio_seg bufseg, int mode)
409{
410 struct mount *mp, *nmp;
411 struct statfs *sfsp, *sp, *sptmp, *tofree;
412 size_t count, maxcount;
413 int error;
414
415 switch (mode) {
416 case MNT_WAIT1:
417 case MNT_NOWAIT2:
418 break;
419 default:
420 if (bufseg == UIO_SYSSPACE)
421 *buf = NULL((void *)0);
422 return (EINVAL22);
423 }
424restart:
425 maxcount = bufsize / sizeof(struct statfs);
426 if (bufsize == 0) {
427 sfsp = NULL((void *)0);
428 tofree = NULL((void *)0);
429 } else if (bufseg == UIO_USERSPACE) {
430 sfsp = *buf;
431 tofree = NULL((void *)0);
432 } else /* if (bufseg == UIO_SYSSPACE) */ {
433 count = 0;
434 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (434))
;
435 TAILQ_FOREACH(mp, &mountlist, mnt_list)for ((mp) = (((&mountlist))->tqh_first); (mp); (mp) = (
((mp))->mnt_list.tqe_next))
{
436 count++;
437 }
438 mtx_unlock(&mountlist_mtx)__mtx_unlock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (438))
;
439 if (maxcount > count)
440 maxcount = count;
441 tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs),
442 M_STATFS, M_WAITOK0x0002);
443 }
444 count = 0;
445 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (445))
;
446 for (mp = TAILQ_FIRST(&mountlist)((&mountlist)->tqh_first); mp != NULL((void *)0); mp = nmp) {
447 if (prison_canseemount(td->td_ucred, mp) != 0) {
448 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
449 continue;
450 }
451#ifdef MAC1
452 if (mac_mount_check_stat(td->td_ucred, mp) != 0) {
453 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
454 continue;
455 }
456#endif
457 if (mode == MNT_WAIT1) {
458 if (vfs_busy(mp, MBF_MNTLSTLOCK0x02) != 0) {
459 /*
460 * If vfs_busy() failed, and MBF_NOWAIT
461 * wasn't passed, then the mp is gone.
462 * Furthermore, because of MBF_MNTLSTLOCK,
463 * the mountlist_mtx was dropped. We have
464 * no other choice than to start over.
465 */
466 mtx_unlock(&mountlist_mtx)__mtx_unlock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (466))
;
467 free(tofree, M_STATFS);
468 goto restart;
469 }
470 } else {
471 if (vfs_busy(mp, MBF_NOWAIT0x01 | MBF_MNTLSTLOCK0x02) != 0) {
472 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
473 continue;
474 }
475 }
476 if (sfsp != NULL((void *)0) && count < maxcount) {
477 sp = &mp->mnt_stat;
478 /*
479 * Set these in case the underlying filesystem
480 * fails to do so.
481 */
482 sp->f_version = STATFS_VERSION0x20140518;
483 sp->f_namemax = NAME_MAX255;
484 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK(0x0000000000000001ULL | 0x0000000000000002ULL | 0x0000000000000004ULL
| 0x0000000000000008ULL | 0x0000000000000020ULL | 0x0000000100000000ULL
| 0x0000000000000040ULL | 0x0000000000000080ULL | 0x0000000000000100ULL
| 0x0000000000000200ULL | 0x0000000000000400ULL| 0x0000000000000800ULL
| 0x0000000000001000ULL | 0x0000000000008000ULL | 0x0000000000002000ULL
| 0x0000000000004000ULL | 0x0000000010000000ULL | 0x0000000040000000ULL
| 0x0000000080000000ULL | 0x0000000000100000ULL | 0x0000000000200000ULL
| 0x0000000000800000ULL | 0x0000000020000000ULL | 0x0000000000400000ULL
| 0x0000000002000000ULL | 0x0000000004000000ULL | 0x0000000008000000ULL
| 0x0000000000000010ULL | 0x0000000200000000ULL | 0x0000000400000000ULL
)
;
485 /*
486 * If MNT_NOWAIT is specified, do not refresh
487 * the fsstat cache.
488 */
489 if (mode != MNT_NOWAIT2) {
490 error = VFS_STATFS(mp, sp)({ int _rc; _rc = __vfs_statfs((mp), (sp)); _rc; });
491 if (error != 0) {
492 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (492))
;
493 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
494 vfs_unbusy(mp);
495 continue;
496 }
497 }
498 if (priv_check(td, PRIV_VFS_GENERATION326)) {
499 sptmp = malloc(sizeof(struct statfs), M_STATFS,
500 M_WAITOK0x0002);
501 *sptmp = *sp;
502 sptmp->f_fsid.val[0] = sptmp->f_fsid.val[1] = 0;
503 prison_enforce_statfs(td->td_ucred, mp, sptmp);
504 sp = sptmp;
505 } else
506 sptmp = NULL((void *)0);
507 if (bufseg == UIO_SYSSPACE) {
508 bcopy(sp, sfsp, sizeof(*sp))__builtin_memmove((sfsp), (sp), (sizeof(*sp)));
509 free(sptmp, M_STATFS);
510 } else /* if (bufseg == UIO_USERSPACE) */ {
511 error = copyout(sp, sfsp, sizeof(*sp));
512 free(sptmp, M_STATFS);
513 if (error != 0) {
514 vfs_unbusy(mp);
515 return (error);
516 }
517 }
518 sfsp++;
519 }
520 count++;
521 mtx_lock(&mountlist_mtx)__mtx_lock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (521))
;
522 nmp = TAILQ_NEXT(mp, mnt_list)((mp)->mnt_list.tqe_next);
523 vfs_unbusy(mp);
524 }
525 mtx_unlock(&mountlist_mtx)__mtx_unlock_flags(&((((&mountlist_mtx))))->mtx_lock
, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"), (525))
;
526 if (sfsp != NULL((void *)0) && count > maxcount)
527 *countp = maxcount;
528 else
529 *countp = count;
530 return (0);
531}
532
533#ifdef COMPAT_FREEBSD41
534/*
535 * Get old format filesystem statistics.
536 */
537static void freebsd4_cvtstatfs(struct statfs *, struct ostatfs *);
538
539#ifndef _SYS_SYSPROTO_H_
540struct freebsd4_statfs_args {
541 char *path;
542 struct ostatfs *buf;
543};
544#endif
545int
546freebsd4_statfs(struct thread *td, struct freebsd4_statfs_args *uap)
547{
548 struct ostatfs osb;
549 struct statfs *sfp;
550 int error;
551
552 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
553 error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
554 if (error == 0) {
555 freebsd4_cvtstatfs(sfp, &osb);
556 error = copyout(&osb, uap->buf, sizeof(osb));
557 }
558 free(sfp, M_STATFS);
559 return (error);
560}
561
562/*
563 * Get filesystem statistics.
564 */
565#ifndef _SYS_SYSPROTO_H_
566struct freebsd4_fstatfs_args {
567 int fd;
568 struct ostatfs *buf;
569};
570#endif
571int
572freebsd4_fstatfs(struct thread *td, struct freebsd4_fstatfs_args *uap)
573{
574 struct ostatfs osb;
575 struct statfs *sfp;
576 int error;
577
578 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
579 error = kern_fstatfs(td, uap->fd, sfp);
580 if (error == 0) {
1
Taking true branch
581 freebsd4_cvtstatfs(sfp, &osb);
582 error = copyout(&osb, uap->buf, sizeof(osb));
2
Copies out a struct with uncleared padding (>= 4 bytes)
583 }
584 free(sfp, M_STATFS);
585 return (error);
586}
587
588/*
589 * Get statistics on all filesystems.
590 */
591#ifndef _SYS_SYSPROTO_H_
592struct freebsd4_getfsstat_args {
593 struct ostatfs *buf;
594 long bufsize;
595 int mode;
596};
597#endif
598int
599freebsd4_getfsstat(struct thread *td, struct freebsd4_getfsstat_args *uap)
600{
601 struct statfs *buf, *sp;
602 struct ostatfs osb;
603 size_t count, size;
604 int error;
605
606 if (uap->bufsize < 0)
607 return (EINVAL22);
608 count = uap->bufsize / sizeof(struct ostatfs);
609 if (count > SIZE_MAX0xffffffffffffffff / sizeof(struct statfs))
610 return (EINVAL22);
611 size = count * sizeof(struct statfs);
612 error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
613 uap->mode);
614 if (error == 0)
615 td->td_retvaltd_uretoff.tdu_retval[0] = count;
616 if (size != 0) {
617 sp = buf;
618 while (count != 0 && error == 0) {
619 freebsd4_cvtstatfs(sp, &osb);
620 error = copyout(&osb, uap->buf, sizeof(osb));
621 sp++;
622 uap->buf++;
623 count--;
624 }
625 free(buf, M_STATFS);
626 }
627 return (error);
628}
629
630/*
631 * Implement fstatfs() for (NFS) file handles.
632 */
633#ifndef _SYS_SYSPROTO_H_
634struct freebsd4_fhstatfs_args {
635 struct fhandle *u_fhp;
636 struct ostatfs *buf;
637};
638#endif
639int
640freebsd4_fhstatfs(struct thread *td, struct freebsd4_fhstatfs_args *uap)
641{
642 struct ostatfs osb;
643 struct statfs *sfp;
644 fhandle_t fh;
645 int error;
646
647 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
648 if (error != 0)
649 return (error);
650 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
651 error = kern_fhstatfs(td, fh, sfp);
652 if (error == 0) {
653 freebsd4_cvtstatfs(sfp, &osb);
654 error = copyout(&osb, uap->buf, sizeof(osb));
655 }
656 free(sfp, M_STATFS);
657 return (error);
658}
659
660/*
661 * Convert a new format statfs structure to an old format statfs structure.
662 */
663static void
664freebsd4_cvtstatfs(struct statfs *nsp, struct ostatfs *osp)
665{
666
667 statfs_scale_blocks(nsp, LONG_MAX0x7fffffffffffffff);
668 bzero(osp, sizeof(*osp))__builtin_memset((osp), 0, (sizeof(*osp)));
669 osp->f_bsize = nsp->f_bsize;
670 osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX)(((nsp->f_iosize)<(0x7fffffffffffffff))?(nsp->f_iosize
):(0x7fffffffffffffff))
;
671 osp->f_blocks = nsp->f_blocks;
672 osp->f_bfree = nsp->f_bfree;
673 osp->f_bavail = nsp->f_bavail;
674 osp->f_files = MIN(nsp->f_files, LONG_MAX)(((nsp->f_files)<(0x7fffffffffffffff))?(nsp->f_files
):(0x7fffffffffffffff))
;
675 osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX)(((nsp->f_ffree)<(0x7fffffffffffffff))?(nsp->f_ffree
):(0x7fffffffffffffff))
;
676 osp->f_owner = nsp->f_owner;
677 osp->f_type = nsp->f_type;
678 osp->f_flags = nsp->f_flags;
679 osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX)(((nsp->f_syncwrites)<(0x7fffffffffffffff))?(nsp->f_syncwrites
):(0x7fffffffffffffff))
;
680 osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX)(((nsp->f_asyncwrites)<(0x7fffffffffffffff))?(nsp->f_asyncwrites
):(0x7fffffffffffffff))
;
681 osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX)(((nsp->f_syncreads)<(0x7fffffffffffffff))?(nsp->f_syncreads
):(0x7fffffffffffffff))
;
682 osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX)(((nsp->f_asyncreads)<(0x7fffffffffffffff))?(nsp->f_asyncreads
):(0x7fffffffffffffff))
;
683 strlcpy(osp->f_fstypename, nsp->f_fstypename,
684 MIN(MFSNAMELEN, OMFSNAMELEN)(((16)<(16))?(16):(16)));
685 strlcpy(osp->f_mntonname, nsp->f_mntonname,
686 MIN(MNAMELEN, OMNAMELEN)(((1024)<((88 - 2 * sizeof(long))))?(1024):((88 - 2 * sizeof
(long))))
);
687 strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
688 MIN(MNAMELEN, OMNAMELEN)(((1024)<((88 - 2 * sizeof(long))))?(1024):((88 - 2 * sizeof
(long))))
);
689 osp->f_fsid = nsp->f_fsid;
690}
691#endif /* COMPAT_FREEBSD4 */
692
693#if defined(COMPAT_FREEBSD111)
694/*
695 * Get old format filesystem statistics.
696 */
697static void freebsd11_cvtstatfs(struct statfs *, struct freebsd11_statfs *);
698
699int
700freebsd11_statfs(struct thread *td, struct freebsd11_statfs_args *uap)
701{
702 struct freebsd11_statfs osb;
703 struct statfs *sfp;
704 int error;
705
706 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
707 error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
708 if (error == 0) {
709 freebsd11_cvtstatfs(sfp, &osb);
710 error = copyout(&osb, uap->buf, sizeof(osb));
711 }
712 free(sfp, M_STATFS);
713 return (error);
714}
715
716/*
717 * Get filesystem statistics.
718 */
719int
720freebsd11_fstatfs(struct thread *td, struct freebsd11_fstatfs_args *uap)
721{
722 struct freebsd11_statfs osb;
723 struct statfs *sfp;
724 int error;
725
726 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
727 error = kern_fstatfs(td, uap->fd, sfp);
728 if (error == 0) {
729 freebsd11_cvtstatfs(sfp, &osb);
730 error = copyout(&osb, uap->buf, sizeof(osb));
731 }
732 free(sfp, M_STATFS);
733 return (error);
734}
735
736/*
737 * Get statistics on all filesystems.
738 */
739int
740freebsd11_getfsstat(struct thread *td, struct freebsd11_getfsstat_args *uap)
741{
742 struct freebsd11_statfs osb;
743 struct statfs *buf, *sp;
744 size_t count, size;
745 int error;
746
747 count = uap->bufsize / sizeof(struct ostatfs);
748 size = count * sizeof(struct statfs);
749 error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
750 uap->mode);
751 if (error == 0)
752 td->td_retvaltd_uretoff.tdu_retval[0] = count;
753 if (size > 0) {
754 sp = buf;
755 while (count > 0 && error == 0) {
756 freebsd11_cvtstatfs(sp, &osb);
757 error = copyout(&osb, uap->buf, sizeof(osb));
758 sp++;
759 uap->buf++;
760 count--;
761 }
762 free(buf, M_STATFS);
763 }
764 return (error);
765}
766
767/*
768 * Implement fstatfs() for (NFS) file handles.
769 */
770int
771freebsd11_fhstatfs(struct thread *td, struct freebsd11_fhstatfs_args *uap)
772{
773 struct freebsd11_statfs osb;
774 struct statfs *sfp;
775 fhandle_t fh;
776 int error;
777
778 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
779 if (error)
780 return (error);
781 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
782 error = kern_fhstatfs(td, fh, sfp);
783 if (error == 0) {
784 freebsd11_cvtstatfs(sfp, &osb);
785 error = copyout(&osb, uap->buf, sizeof(osb));
786 }
787 free(sfp, M_STATFS);
788 return (error);
789}
790
791/*
792 * Convert a new format statfs structure to an old format statfs structure.
793 */
794static void
795freebsd11_cvtstatfs(struct statfs *nsp, struct freebsd11_statfs *osp)
796{
797
798 bzero(osp, sizeof(*osp))__builtin_memset((osp), 0, (sizeof(*osp)));
799 osp->f_version = FREEBSD11_STATFS_VERSION0x20030518;
800 osp->f_type = nsp->f_type;
801 osp->f_flags = nsp->f_flags;
802 osp->f_bsize = nsp->f_bsize;
803 osp->f_iosize = nsp->f_iosize;
804 osp->f_blocks = nsp->f_blocks;
805 osp->f_bfree = nsp->f_bfree;
806 osp->f_bavail = nsp->f_bavail;
807 osp->f_files = nsp->f_files;
808 osp->f_ffree = nsp->f_ffree;
809 osp->f_syncwrites = nsp->f_syncwrites;
810 osp->f_asyncwrites = nsp->f_asyncwrites;
811 osp->f_syncreads = nsp->f_syncreads;
812 osp->f_asyncreads = nsp->f_asyncreads;
813 osp->f_namemax = nsp->f_namemax;
814 osp->f_owner = nsp->f_owner;
815 osp->f_fsid = nsp->f_fsid;
816 strlcpy(osp->f_fstypename, nsp->f_fstypename,
817 MIN(MFSNAMELEN, sizeof(osp->f_fstypename))(((16)<(sizeof(osp->f_fstypename)))?(16):(sizeof(osp->
f_fstypename)))
);
818 strlcpy(osp->f_mntonname, nsp->f_mntonname,
819 MIN(MNAMELEN, sizeof(osp->f_mntonname))(((1024)<(sizeof(osp->f_mntonname)))?(1024):(sizeof(osp
->f_mntonname)))
);
820 strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
821 MIN(MNAMELEN, sizeof(osp->f_mntfromname))(((1024)<(sizeof(osp->f_mntfromname)))?(1024):(sizeof(osp
->f_mntfromname)))
);
822}
823#endif /* COMPAT_FREEBSD11 */
824
825/*
826 * Change current working directory to a given file descriptor.
827 */
828#ifndef _SYS_SYSPROTO_H_
829struct fchdir_args {
830 int fd;
831};
832#endif
833int
834sys_fchdir(struct thread *td, struct fchdir_args *uap)
835{
836 struct vnode *vp, *tdp;
837 struct mount *mp;
838 struct file *fp;
839 int error;
840
841 AUDIT_ARG_FD(uap->fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->fd)); } while (0)
;
842 error = getvnode(td, uap->fd, &cap_fchdir_rights,
843 &fp);
844 if (error != 0)
845 return (error);
846 vp = fp->f_vnode;
847 vrefact(vp);
848 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
849 vn_lock(vp, LK_SHARED | LK_RETRY)_vn_lock(vp, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 849)
;
850 AUDIT_ARG_VNODE1(vp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((vp)); } while (0)
;
851 error = change_dir(vp, td);
852 while (!error && (mp = vp->v_mountedhere) != NULL((void *)0)) {
853 if (vfs_busy(mp, 0))
854 continue;
855 error = VFS_ROOT(mp, LK_SHARED, &tdp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_root)(mp, 0x200000
, &tdp); _rc; })
;
856 vfs_unbusy(mp);
857 if (error != 0)
858 break;
859 vput(vp);
860 vp = tdp;
861 }
862 if (error != 0) {
863 vput(vp);
864 return (error);
865 }
866 VOP_UNLOCK(vp, 0);
867 pwd_chdir(td, vp);
868 return (0);
869}
870
871/*
872 * Change current working directory (``.'').
873 */
874#ifndef _SYS_SYSPROTO_H_
875struct chdir_args {
876 char *path;
877};
878#endif
879int
880sys_chdir(struct thread *td, struct chdir_args *uap)
881{
882
883 return (kern_chdir(td, uap->path, UIO_USERSPACE));
884}
885
886int
887kern_chdir(struct thread *td, const char *path, enum uio_seg pathseg)
888{
889 struct nameidata nd;
890 int error;
891
892 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, -100, ((void *)0), 0, td)
893 pathseg, path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, -100, ((void *)0), 0, td)
;
894 if ((error = namei(&nd)) != 0)
895 return (error);
896 if ((error = change_dir(nd.ni_vp, td)) != 0) {
897 vput(nd.ni_vp);
898 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
899 return (error);
900 }
901 VOP_UNLOCK(nd.ni_vp, 0);
902 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
903 pwd_chdir(td, nd.ni_vp);
904 return (0);
905}
906
907/*
908 * Change notion of root (``/'') directory.
909 */
910#ifndef _SYS_SYSPROTO_H_
911struct chroot_args {
912 char *path;
913};
914#endif
915int
916sys_chroot(struct thread *td, struct chroot_args *uap)
917{
918 struct nameidata nd;
919 int error;
920
921 error = priv_check(td, PRIV_VFS_CHROOT318);
922 if (error != 0)
923 return (error);
924 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
UIO_USERSPACE, uap->path, -100, ((void *)0), 0, td)
925 UIO_USERSPACE, uap->path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000,
UIO_USERSPACE, uap->path, -100, ((void *)0), 0, td)
;
926 error = namei(&nd);
927 if (error != 0)
928 goto error;
929 error = change_dir(nd.ni_vp, td);
930 if (error != 0)
931 goto e_vunlock;
932#ifdef MAC1
933 error = mac_vnode_check_chroot(td->td_ucred, nd.ni_vp);
934 if (error != 0)
935 goto e_vunlock;
936#endif
937 VOP_UNLOCK(nd.ni_vp, 0);
938 error = pwd_chroot(td, nd.ni_vp);
939 vrele(nd.ni_vp);
940 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
941 return (error);
942e_vunlock:
943 vput(nd.ni_vp);
944error:
945 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
946 return (error);
947}
948
949/*
950 * Common routine for chroot and chdir. Callers must provide a locked vnode
951 * instance.
952 */
953int
954change_dir(struct vnode *vp, struct thread *td)
955{
956#ifdef MAC1
957 int error;
958#endif
959
960 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked")((void)0);
961 if (vp->v_type != VDIR)
962 return (ENOTDIR20);
963#ifdef MAC1
964 error = mac_vnode_check_chdir(td->td_ucred, vp);
965 if (error != 0)
966 return (error);
967#endif
968 return (VOP_ACCESS(vp, VEXEC000000000100, td->td_ucred, td));
969}
970
971static __inline void
972flags_to_rights(int flags, cap_rights_t *rightsp)
973{
974
975 if (flags & O_EXEC0x00040000) {
976 cap_rights_set(rightsp, CAP_FEXECVE)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000080ULL
)), 0ULL)
;
977 } else {
978 switch ((flags & O_ACCMODE0x0003)) {
979 case O_RDONLY0x0000:
980 cap_rights_set(rightsp, CAP_READ)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000001ULL
)), 0ULL)
;
981 break;
982 case O_RDWR0x0002:
983 cap_rights_set(rightsp, CAP_READ)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000001ULL
)), 0ULL)
;
984 /* FALLTHROUGH */
985 case O_WRONLY0x0001:
986 cap_rights_set(rightsp, CAP_WRITE)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000002ULL
)), 0ULL)
;
987 if (!(flags & (O_APPEND0x0008 | O_TRUNC0x0400)))
988 cap_rights_set(rightsp, CAP_SEEK)__cap_rights_set(rightsp, (((1ULL << (57 + (0))) | (0x0000000000000004ULL
)) | 0x0000000000000008ULL), 0ULL)
;
989 break;
990 }
991 }
992
993 if (flags & O_CREAT0x0200)
994 cap_rights_set(rightsp, CAP_CREATE)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000040ULL
)), 0ULL)
;
995
996 if (flags & O_TRUNC0x0400)
997 cap_rights_set(rightsp, CAP_FTRUNCATE)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000200ULL
)), 0ULL)
;
998
999 if (flags & (O_SYNC0x0080 | O_FSYNC0x0080))
1000 cap_rights_set(rightsp, CAP_FSYNC)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000000100ULL
)), 0ULL)
;
1001
1002 if (flags & (O_EXLOCK0x0020 | O_SHLOCK0x0010))
1003 cap_rights_set(rightsp, CAP_FLOCK)__cap_rights_set(rightsp, ((1ULL << (57 + (0))) | (0x0000000000010000ULL
)), 0ULL)
;
1004}
1005
1006/*
1007 * Check permissions, allocate an open file structure, and call the device
1008 * open routine if any.
1009 */
1010#ifndef _SYS_SYSPROTO_H_
1011struct open_args {
1012 char *path;
1013 int flags;
1014 int mode;
1015};
1016#endif
1017int
1018sys_open(struct thread *td, struct open_args *uap)
1019{
1020
1021 return (kern_openat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
1022 uap->flags, uap->mode));
1023}
1024
1025#ifndef _SYS_SYSPROTO_H_
1026struct openat_args {
1027 int fd;
1028 char *path;
1029 int flag;
1030 int mode;
1031};
1032#endif
1033int
1034sys_openat(struct thread *td, struct openat_args *uap)
1035{
1036
1037 AUDIT_ARG_FD(uap->fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->fd)); } while (0)
;
1038 return (kern_openat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag,
1039 uap->mode));
1040}
1041
1042int
1043kern_openat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
1044 int flags, int mode)
1045{
1046 struct proc *p = td->td_proc;
1047 struct filedesc *fdp = p->p_fd;
1048 struct file *fp;
1049 struct vnode *vp;
1050 struct nameidata nd;
1051 cap_rights_t rights;
1052 int cmode, error, indx;
1053
1054 indx = -1;
1055
1056 AUDIT_ARG_FFLAGS(flags)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fflags((flags)); } while (0)
;
1057 AUDIT_ARG_MODE(mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((mode)); } while (0)
;
1058 cap_rights_init(&rights, CAP_LOOKUP)__cap_rights_init(0, &rights, ((1ULL << (57 + (0)))
| (0x0000000000000400ULL)), 0ULL)
;
1059 flags_to_rights(flags, &rights);
1060 /*
1061 * Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags
1062 * may be specified.
1063 */
1064 if (flags & O_EXEC0x00040000) {
1065 if (flags & O_ACCMODE0x0003)
1066 return (EINVAL22);
1067 } else if ((flags & O_ACCMODE0x0003) == O_ACCMODE0x0003) {
1068 return (EINVAL22);
1069 } else {
1070 flags = FFLAGS(flags)((flags) & 0x00040000 ? (flags) : (flags) + 1);
1071 }
1072
1073 /*
1074 * Allocate a file structure. The descriptor to reference it
1075 * is allocated and set by finstall() below.
1076 */
1077 error = falloc_noinstall(td, &fp);
1078 if (error != 0)
1079 return (error);
1080 /*
1081 * An extra reference on `fp' has been held for us by
1082 * falloc_noinstall().
1083 */
1084 /* Set the flags early so the finit in devfs can pick them up. */
1085 fp->f_flag = flags & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004|0x00010000|0x00040000
)
;
1086 cmode = ((mode & ~fdp->fd_cmask) & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) & ~S_ISTXT0001000;
1087 NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, 0x0040 | 0x04000000, pathseg, path, fd
, ((void *)0), &rights, td)
1088 &rights, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x04000000, pathseg, path, fd
, ((void *)0), &rights, td)
;
1089 td->td_dupfd = -1; /* XXX check for fdopen */
1090 error = vn_open(&nd, &flags, cmode, fp);
1091 if (error != 0) {
1092 /*
1093 * If the vn_open replaced the method vector, something
1094 * wonderous happened deep below and we just pass it up
1095 * pretending we know what we do.
1096 */
1097 if (error == ENXIO6 && fp->f_ops != &badfileops)
1098 goto success;
1099
1100 /*
1101 * Handle special fdopen() case. bleh.
1102 *
1103 * Don't do this for relative (capability) lookups; we don't
1104 * understand exactly what would happen, and we don't think
1105 * that it ever should.
1106 */
1107 if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE0x0001) == 0 &&
1108 (error == ENODEV19 || error == ENXIO6) &&
1109 td->td_dupfd >= 0) {
1110 error = dupfdopen(td, fdp, td->td_dupfd, flags, error,
1111 &indx);
1112 if (error == 0)
1113 goto success;
1114 }
1115
1116 goto bad;
1117 }
1118 td->td_dupfd = 0;
1119 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1120 vp = nd.ni_vp;
1121
1122 /*
1123 * Store the vnode, for any f_type. Typically, the vnode use
1124 * count is decremented by direct call to vn_closefile() for
1125 * files that switched type in the cdevsw fdopen() method.
1126 */
1127 fp->f_vnode = vp;
1128 /*
1129 * If the file wasn't claimed by devfs bind it to the normal
1130 * vnode operations here.
1131 */
1132 if (fp->f_ops == &badfileops) {
1133 KASSERT(vp->v_type != VFIFO, ("Unexpected fifo."))do { if (__builtin_expect((!(vp->v_type != VFIFO)), 0)) panic
("Unexpected fifo."); } while (0)
;
1134 fp->f_seqcount = 1;
1135 finit(fp, (flags & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004|0x00010000|0x00040000
)
) | (fp->f_flag & FHASLOCK0x4000),
1136 DTYPE_VNODE1, vp, &vnops);
1137 }
1138
1139 VOP_UNLOCK(vp, 0);
1140 if (flags & O_TRUNC0x0400) {
1141 error = fo_truncate(fp, 0, td->td_ucred, td);
1142 if (error != 0)
1143 goto bad;
1144 }
1145success:
1146 /*
1147 * If we haven't already installed the FD (for dupfdopen), do so now.
1148 */
1149 if (indx == -1) {
1150 struct filecaps *fcaps;
1151
1152#ifdef CAPABILITIES1
1153 if ((nd.ni_lcf & NI_LCF_STRICTRELATIVE0x0001) != 0)
1154 fcaps = &nd.ni_filecaps;
1155 else
1156#endif
1157 fcaps = NULL((void *)0);
1158 error = finstall(td, fp, &indx, flags, fcaps);
1159 /* On success finstall() consumes fcaps. */
1160 if (error != 0) {
1161 filecaps_free(&nd.ni_filecaps);
1162 goto bad;
1163 }
1164 } else {
1165 filecaps_free(&nd.ni_filecaps);
1166 }
1167
1168 /*
1169 * Release our private reference, leaving the one associated with
1170 * the descriptor table intact.
1171 */
1172 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
1173 td->td_retvaltd_uretoff.tdu_retval[0] = indx;
1174 return (0);
1175bad:
1176 KASSERT(indx == -1, ("indx=%d, should be -1", indx))do { if (__builtin_expect((!(indx == -1)), 0)) panic ("indx=%d, should be -1"
, indx); } while (0)
;
1177 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
1178 return (error);
1179}
1180
1181#ifdef COMPAT_43
1182/*
1183 * Create a file.
1184 */
1185#ifndef _SYS_SYSPROTO_H_
1186struct ocreat_args {
1187 char *path;
1188 int mode;
1189};
1190#endif
1191int
1192ocreat(struct thread *td, struct ocreat_args *uap)
1193{
1194
1195 return (kern_openat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
1196 O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400, uap->mode));
1197}
1198#endif /* COMPAT_43 */
1199
1200/*
1201 * Create a special file.
1202 */
1203#ifndef _SYS_SYSPROTO_H_
1204struct mknodat_args {
1205 int fd;
1206 char *path;
1207 mode_t mode;
1208 dev_t dev;
1209};
1210#endif
1211int
1212sys_mknodat(struct thread *td, struct mknodat_args *uap)
1213{
1214
1215 return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
1216 uap->dev));
1217}
1218
1219#if defined(COMPAT_FREEBSD111)
1220int
1221freebsd11_mknod(struct thread *td,
1222 struct freebsd11_mknod_args *uap)
1223{
1224
1225 return (kern_mknodat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
1226 uap->mode, uap->dev));
1227}
1228
1229int
1230freebsd11_mknodat(struct thread *td,
1231 struct freebsd11_mknodat_args *uap)
1232{
1233
1234 return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
1235 uap->dev));
1236}
1237#endif /* COMPAT_FREEBSD11 */
1238
1239int
1240kern_mknodat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
1241 int mode, dev_t dev)
1242{
1243 struct vnode *vp;
1244 struct mount *mp;
1245 struct vattr vattr;
1246 struct nameidata nd;
1247 int error, whiteout = 0;
1248
1249 AUDIT_ARG_MODE(mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((mode)); } while (0)
;
1250 AUDIT_ARG_DEV(dev)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_dev((dev)); } while (0)
;
1251 switch (mode & S_IFMT0170000) {
1252 case S_IFCHR0020000:
1253 case S_IFBLK0060000:
1254 error = priv_check(td, PRIV_VFS_MKNOD_DEV331);
1255 if (error == 0 && dev == VNOVAL(-1))
1256 error = EINVAL22;
1257 break;
1258 case S_IFWHT0160000:
1259 error = priv_check(td, PRIV_VFS_MKNOD_WHT332);
1260 break;
1261 case S_IFIFO0010000:
1262 if (dev == 0)
1263 return (kern_mkfifoat(td, fd, path, pathseg, mode));
1264 /* FALLTHROUGH */
1265 default:
1266 error = EINVAL22;
1267 break;
1268 }
1269 if (error != 0)
1270 return (error);
1271restart:
1272 bwillwrite();
1273 NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mknodat_rights, td
)
1274 NOCACHE, pathseg, path, fd, &cap_mknodat_rights,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mknodat_rights, td
)
1275 td)NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mknodat_rights, td
)
;
1276 if ((error = namei(&nd)) != 0)
1277 return (error);
1278 vp = nd.ni_vp;
1279 if (vp != NULL((void *)0)) {
1280 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1281 if (vp == nd.ni_dvp)
1282 vrele(nd.ni_dvp);
1283 else
1284 vput(nd.ni_dvp);
1285 vrele(vp);
1286 return (EEXIST17);
1287 } else {
1288 VATTR_NULL(&vattr)(*(&vattr) = va_null);
1289 vattr.va_mode = (mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) &
1290 ~td->td_proc->p_fd->fd_cmask;
1291 vattr.va_rdev = dev;
1292 whiteout = 0;
1293
1294 switch (mode & S_IFMT0170000) {
1295 case S_IFCHR0020000:
1296 vattr.va_type = VCHR;
1297 break;
1298 case S_IFBLK0060000:
1299 vattr.va_type = VBLK;
1300 break;
1301 case S_IFWHT0160000:
1302 whiteout = 1;
1303 break;
1304 default:
1305 panic("kern_mknod: invalid mode");
1306 }
1307 }
1308 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
1309 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1310 vput(nd.ni_dvp);
1311 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
1312 return (error);
1313 goto restart;
1314 }
1315#ifdef MAC1
1316 if (error == 0 && !whiteout)
1317 error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp,
1318 &nd.ni_cnd, &vattr);
1319#endif
1320 if (error == 0) {
1321 if (whiteout)
1322 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE1);
1323 else {
1324 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1325 &nd.ni_cnd, &vattr);
1326 if (error == 0)
1327 vput(nd.ni_vp);
1328 }
1329 }
1330 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1331 vput(nd.ni_dvp);
1332 vn_finished_write(mp);
1333 return (error);
1334}
1335
1336/*
1337 * Create a named pipe.
1338 */
1339#ifndef _SYS_SYSPROTO_H_
1340struct mkfifo_args {
1341 char *path;
1342 int mode;
1343};
1344#endif
1345int
1346sys_mkfifo(struct thread *td, struct mkfifo_args *uap)
1347{
1348
1349 return (kern_mkfifoat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
1350 uap->mode));
1351}
1352
1353#ifndef _SYS_SYSPROTO_H_
1354struct mkfifoat_args {
1355 int fd;
1356 char *path;
1357 mode_t mode;
1358};
1359#endif
1360int
1361sys_mkfifoat(struct thread *td, struct mkfifoat_args *uap)
1362{
1363
1364 return (kern_mkfifoat(td, uap->fd, uap->path, UIO_USERSPACE,
1365 uap->mode));
1366}
1367
1368int
1369kern_mkfifoat(struct thread *td, int fd, const char *path,
1370 enum uio_seg pathseg, int mode)
1371{
1372 struct mount *mp;
1373 struct vattr vattr;
1374 struct nameidata nd;
1375 int error;
1376
1377 AUDIT_ARG_MODE(mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((mode)); } while (0)
;
1378restart:
1379 bwillwrite();
1380 NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mkfifoat_rights, td
)
1381 NOCACHE, pathseg, path, fd, &cap_mkfifoat_rights,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mkfifoat_rights, td
)
1382 td)NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, pathseg, path, fd, ((void *)0), &cap_mkfifoat_rights, td
)
;
1383 if ((error = namei(&nd)) != 0)
1384 return (error);
1385 if (nd.ni_vp != NULL((void *)0)) {
1386 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1387 if (nd.ni_vp == nd.ni_dvp)
1388 vrele(nd.ni_dvp);
1389 else
1390 vput(nd.ni_dvp);
1391 vrele(nd.ni_vp);
1392 return (EEXIST17);
1393 }
1394 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
1395 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1396 vput(nd.ni_dvp);
1397 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
1398 return (error);
1399 goto restart;
1400 }
1401 VATTR_NULL(&vattr)(*(&vattr) = va_null);
1402 vattr.va_type = VFIFO;
1403 vattr.va_mode = (mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007)) & ~td->td_proc->p_fd->fd_cmask;
1404#ifdef MAC1
1405 error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1406 &vattr);
1407 if (error != 0)
1408 goto out;
1409#endif
1410 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1411 if (error == 0)
1412 vput(nd.ni_vp);
1413#ifdef MAC1
1414out:
1415#endif
1416 vput(nd.ni_dvp);
1417 vn_finished_write(mp);
1418 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1419 return (error);
1420}
1421
1422/*
1423 * Make a hard file link.
1424 */
1425#ifndef _SYS_SYSPROTO_H_
1426struct link_args {
1427 char *path;
1428 char *link;
1429};
1430#endif
1431int
1432sys_link(struct thread *td, struct link_args *uap)
1433{
1434
1435 return (kern_linkat(td, AT_FDCWD-100, AT_FDCWD-100, uap->path, uap->link,
1436 UIO_USERSPACE, FOLLOW0x0040));
1437}
1438
1439#ifndef _SYS_SYSPROTO_H_
1440struct linkat_args {
1441 int fd1;
1442 char *path1;
1443 int fd2;
1444 char *path2;
1445 int flag;
1446};
1447#endif
1448int
1449sys_linkat(struct thread *td, struct linkat_args *uap)
1450{
1451 int flag;
1452
1453 flag = uap->flag;
1454 if ((flag & ~(AT_SYMLINK_FOLLOW0x0400 | AT_BENEATH0x1000)) != 0)
1455 return (EINVAL22);
1456
1457 return (kern_linkat(td, uap->fd1, uap->fd2, uap->path1, uap->path2,
1458 UIO_USERSPACE, ((flag & AT_SYMLINK_FOLLOW0x0400) != 0 ? FOLLOW0x0040 :
1459 NOFOLLOW0x0000) | ((flag & AT_BENEATH0x1000) != 0 ? BENEATH0x0080 : 0)));
1460}
1461
1462int hardlink_check_uid = 0;
1463SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,static struct sysctl_oid sysctl___security_bsd_hardlink_check_uid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_uid), .oid_arg2 = (0), .oid_name = ("hardlink_check_uid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"users", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_uid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_uid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_uid)), "compile-time assertion failed"
)
1464 &hardlink_check_uid, 0,static struct sysctl_oid sysctl___security_bsd_hardlink_check_uid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_uid), .oid_arg2 = (0), .oid_name = ("hardlink_check_uid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"users", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_uid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_uid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_uid)), "compile-time assertion failed"
)
1465 "Unprivileged processes cannot create hard links to files owned by other "static struct sysctl_oid sysctl___security_bsd_hardlink_check_uid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_uid), .oid_arg2 = (0), .oid_name = ("hardlink_check_uid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"users", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_uid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_uid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_uid)), "compile-time assertion failed"
)
1466 "users")static struct sysctl_oid sysctl___security_bsd_hardlink_check_uid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_uid), .oid_arg2 = (0), .oid_name = ("hardlink_check_uid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"users", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_uid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_uid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_uid)), "compile-time assertion failed"
)
;
1467static int hardlink_check_gid = 0;
1468SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,static struct sysctl_oid sysctl___security_bsd_hardlink_check_gid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_gid), .oid_arg2 = (0), .oid_name = ("hardlink_check_gid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"groups", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_gid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_gid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_gid)), "compile-time assertion failed"
)
1469 &hardlink_check_gid, 0,static struct sysctl_oid sysctl___security_bsd_hardlink_check_gid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_gid), .oid_arg2 = (0), .oid_name = ("hardlink_check_gid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"groups", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_gid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_gid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_gid)), "compile-time assertion failed"
)
1470 "Unprivileged processes cannot create hard links to files owned by other "static struct sysctl_oid sysctl___security_bsd_hardlink_check_gid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_gid), .oid_arg2 = (0), .oid_name = ("hardlink_check_gid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"groups", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_gid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_gid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_gid)), "compile-time assertion failed"
)
1471 "groups")static struct sysctl_oid sysctl___security_bsd_hardlink_check_gid
= { .oid_parent = ((&(&sysctl___security_bsd)->oid_children
)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&hardlink_check_gid), .oid_arg2 = (0), .oid_name = ("hardlink_check_gid"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Unprivileged processes cannot create hard links to files owned by other "
"groups", .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___security_bsd_hardlink_check_gid
__attribute__((__section__("set_" "sysctl_set"))) __attribute__
((__used__)) = &(sysctl___security_bsd_hardlink_check_gid
); _Static_assert(((((0x80000000|0x40000000)) & 0xf) == 0
|| (((0x80000000|0x40000000)) & 0) == 2) && sizeof
(int) == sizeof(*(&hardlink_check_gid)), "compile-time assertion failed"
)
;
1472
1473static int
1474can_hardlink(struct vnode *vp, struct ucred *cred)
1475{
1476 struct vattr va;
1477 int error;
1478
1479 if (!hardlink_check_uid && !hardlink_check_gid)
1480 return (0);
1481
1482 error = VOP_GETATTR(vp, &va, cred);
1483 if (error != 0)
1484 return (error);
1485
1486 if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
1487 error = priv_check_cred(cred, PRIV_VFS_LINK329);
1488 if (error != 0)
1489 return (error);
1490 }
1491
1492 if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
1493 error = priv_check_cred(cred, PRIV_VFS_LINK329);
1494 if (error != 0)
1495 return (error);
1496 }
1497
1498 return (0);
1499}
1500
1501int
1502kern_linkat(struct thread *td, int fd1, int fd2, const char *path1,
1503 const char *path2, enum uio_seg segflag, int follow)
1504{
1505 struct nameidata nd;
1506 int error;
1507
1508 do {
1509 bwillwrite();
1510 NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflag,NDINIT_ALL(&nd, 0, follow | 0x04000000, segflag, path1, fd1
, ((void *)0), &cap_linkat_source_rights, td)
1511 path1, fd1, &cap_linkat_source_rights, td)NDINIT_ALL(&nd, 0, follow | 0x04000000, segflag, path1, fd1
, ((void *)0), &cap_linkat_source_rights, td)
;
1512 if ((error = namei(&nd)) != 0)
1513 return (error);
1514 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1515 error = kern_linkat_vp(td, nd.ni_vp, fd2, path2, segflag);
1516 } while (error == EAGAIN35);
1517 return (error);
1518}
1519
1520static int
1521kern_linkat_vp(struct thread *td, struct vnode *vp, int fd, const char *path,
1522 enum uio_seg segflag)
1523{
1524 struct nameidata nd;
1525 struct mount *mp;
1526 int error;
1527
1528 if (vp->v_type == VDIR) {
1529 vrele(vp);
1530 return (EPERM1); /* POSIX */
1531 }
1532 NDINIT_ATRIGHTS(&nd, CREATE,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x08000000 | 0x0020
, segflag, path, fd, ((void *)0), &cap_linkat_target_rights
, td)
1533 LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x08000000 | 0x0020
, segflag, path, fd, ((void *)0), &cap_linkat_target_rights
, td)
1534 &cap_linkat_target_rights, td)NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x08000000 | 0x0020
, segflag, path, fd, ((void *)0), &cap_linkat_target_rights
, td)
;
1535 if ((error = namei(&nd)) == 0) {
1536 if (nd.ni_vp != NULL((void *)0)) {
1537 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1538 if (nd.ni_dvp == nd.ni_vp)
1539 vrele(nd.ni_dvp);
1540 else
1541 vput(nd.ni_dvp);
1542 vrele(nd.ni_vp);
1543 vrele(vp);
1544 return (EEXIST17);
1545 } else if (nd.ni_dvp->v_mount != vp->v_mount) {
1546 /*
1547 * Cross-device link. No need to recheck
1548 * vp->v_type, since it cannot change, except
1549 * to VBAD.
1550 */
1551 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1552 vput(nd.ni_dvp);
1553 vrele(vp);
1554 return (EXDEV18);
1555 } else if ((error = vn_lock(vp, LK_EXCLUSIVE)_vn_lock(vp, 0x080000, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 1555)
) == 0) {
1556 error = can_hardlink(vp, td->td_ucred);
1557#ifdef MAC1
1558 if (error == 0)
1559 error = mac_vnode_check_link(td->td_ucred,
1560 nd.ni_dvp, vp, &nd.ni_cnd);
1561#endif
1562 if (error != 0) {
1563 vput(vp);
1564 vput(nd.ni_dvp);
1565 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1566 return (error);
1567 }
1568 error = vn_start_write(vp, &mp, V_NOWAIT0x0002);
1569 if (error != 0) {
1570 vput(vp);
1571 vput(nd.ni_dvp);
1572 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1573 error = vn_start_write(NULL((void *)0), &mp,
1574 V_XSLEEP0x0004 | PCATCH0x100);
1575 if (error != 0)
1576 return (error);
1577 return (EAGAIN35);
1578 }
1579 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1580 VOP_UNLOCK(vp, 0);
1581 vput(nd.ni_dvp);
1582 vn_finished_write(mp);
1583 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1584 } else {
1585 vput(nd.ni_dvp);
1586 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1587 vrele(vp);
1588 return (EAGAIN35);
1589 }
1590 }
1591 vrele(vp);
1592 return (error);
1593}
1594
1595/*
1596 * Make a symbolic link.
1597 */
1598#ifndef _SYS_SYSPROTO_H_
1599struct symlink_args {
1600 char *path;
1601 char *link;
1602};
1603#endif
1604int
1605sys_symlink(struct thread *td, struct symlink_args *uap)
1606{
1607
1608 return (kern_symlinkat(td, uap->path, AT_FDCWD-100, uap->link,
1609 UIO_USERSPACE));
1610}
1611
1612#ifndef _SYS_SYSPROTO_H_
1613struct symlinkat_args {
1614 char *path;
1615 int fd;
1616 char *path2;
1617};
1618#endif
1619int
1620sys_symlinkat(struct thread *td, struct symlinkat_args *uap)
1621{
1622
1623 return (kern_symlinkat(td, uap->path1, uap->fd, uap->path2,
1624 UIO_USERSPACE));
1625}
1626
1627int
1628kern_symlinkat(struct thread *td, const char *path1, int fd, const char *path2,
1629 enum uio_seg segflg)
1630{
1631 struct mount *mp;
1632 struct vattr vattr;
1633 const char *syspath;
1634 char *tmppath;
1635 struct nameidata nd;
1636 int error;
1637
1638 if (segflg == UIO_SYSSPACE) {
1639 syspath = path1;
1640 } else {
1641 tmppath = uma_zalloc(namei_zone, M_WAITOK0x0002);
1642 if ((error = copyinstr(path1, tmppath, MAXPATHLEN1024, NULL((void *)0))) != 0)
1643 goto out;
1644 syspath = tmppath;
1645 }
1646 AUDIT_ARG_TEXT(syspath)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_text((syspath)); } while (0)
;
1647restart:
1648 bwillwrite();
1649 NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path2, fd, ((void *)0), &cap_symlinkat_rights, td
)
1650 NOCACHE, segflg, path2, fd, &cap_symlinkat_rights,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path2, fd, ((void *)0), &cap_symlinkat_rights, td
)
1651 td)NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path2, fd, ((void *)0), &cap_symlinkat_rights, td
)
;
1652 if ((error = namei(&nd)) != 0)
1653 goto out;
1654 if (nd.ni_vp) {
1655 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1656 if (nd.ni_vp == nd.ni_dvp)
1657 vrele(nd.ni_dvp);
1658 else
1659 vput(nd.ni_dvp);
1660 vrele(nd.ni_vp);
1661 error = EEXIST17;
1662 goto out;
1663 }
1664 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
1665 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1666 vput(nd.ni_dvp);
1667 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
1668 goto out;
1669 goto restart;
1670 }
1671 VATTR_NULL(&vattr)(*(&vattr) = va_null);
1672 vattr.va_mode = ACCESSPERMS(0000700|0000070|0000007) &~ td->td_proc->p_fd->fd_cmask;
1673#ifdef MAC1
1674 vattr.va_type = VLNK;
1675 error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1676 &vattr);
1677 if (error != 0)
1678 goto out2;
1679#endif
1680 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1681 if (error == 0)
1682 vput(nd.ni_vp);
1683#ifdef MAC1
1684out2:
1685#endif
1686 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1687 vput(nd.ni_dvp);
1688 vn_finished_write(mp);
1689out:
1690 if (segflg != UIO_SYSSPACE)
1691 uma_zfree(namei_zone, tmppath);
1692 return (error);
1693}
1694
1695/*
1696 * Delete a whiteout from the filesystem.
1697 */
1698#ifndef _SYS_SYSPROTO_H_
1699struct undelete_args {
1700 char *path;
1701};
1702#endif
1703int
1704sys_undelete(struct thread *td, struct undelete_args *uap)
1705{
1706 struct mount *mp;
1707 struct nameidata nd;
1708 int error;
1709
1710restart:
1711 bwillwrite();
1712 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | AUDITVNODE1,NDINIT_ALL(&nd, 2, 0x0008 | 0x00040000 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
1713 UIO_USERSPACE, uap->path, td)NDINIT_ALL(&nd, 2, 0x0008 | 0x00040000 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
;
1714 error = namei(&nd);
1715 if (error != 0)
1716 return (error);
1717
1718 if (nd.ni_vp != NULLVP((struct vnode *)((void *)0)) || !(nd.ni_cnd.cn_flags & ISWHITEOUT0x00020000)) {
1719 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1720 if (nd.ni_vp == nd.ni_dvp)
1721 vrele(nd.ni_dvp);
1722 else
1723 vput(nd.ni_dvp);
1724 if (nd.ni_vp)
1725 vrele(nd.ni_vp);
1726 return (EEXIST17);
1727 }
1728 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
1729 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1730 vput(nd.ni_dvp);
1731 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
1732 return (error);
1733 goto restart;
1734 }
1735 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE2);
1736 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1737 vput(nd.ni_dvp);
1738 vn_finished_write(mp);
1739 return (error);
1740}
1741
1742/*
1743 * Delete a name from the filesystem.
1744 */
1745#ifndef _SYS_SYSPROTO_H_
1746struct unlink_args {
1747 char *path;
1748};
1749#endif
1750int
1751sys_unlink(struct thread *td, struct unlink_args *uap)
1752{
1753
1754 return (kern_unlinkat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE, 0, 0));
1755}
1756
1757#ifndef _SYS_SYSPROTO_H_
1758struct unlinkat_args {
1759 int fd;
1760 char *path;
1761 int flag;
1762};
1763#endif
1764int
1765sys_unlinkat(struct thread *td, struct unlinkat_args *uap)
1766{
1767 int fd, flag;
1768 const char *path;
1769
1770 flag = uap->flag;
1771 fd = uap->fd;
1772 path = uap->path;
1773
1774 if ((flag & ~(AT_REMOVEDIR0x0800 | AT_BENEATH0x1000)) != 0)
1775 return (EINVAL22);
1776
1777 if ((uap->flag & AT_REMOVEDIR0x0800) != 0)
1778 return (kern_rmdirat(td, fd, path, UIO_USERSPACE, flag));
1779 else
1780 return (kern_unlinkat(td, fd, path, UIO_USERSPACE, flag, 0));
1781}
1782
1783int
1784kern_unlinkat(struct thread *td, int fd, const char *path,
1785 enum uio_seg pathseg, int flag, ino_t oldinum)
1786{
1787 struct mount *mp;
1788 struct vnode *vp;
1789 struct nameidata nd;
1790 struct stat sb;
1791 int error;
1792
1793restart:
1794 bwillwrite();
1795 NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
1796 ((flag & AT_BENEATH) != 0 ? BENEATH : 0),NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
1797 pathseg, path, fd, &cap_unlinkat_rights, td)NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
;
1798 if ((error = namei(&nd)) != 0)
1799 return (error == EINVAL22 ? EPERM1 : error);
1800 vp = nd.ni_vp;
1801 if (vp->v_type == VDIR && oldinum == 0) {
1802 error = EPERM1; /* POSIX */
1803 } else if (oldinum != 0 &&
1804 ((error = vn_stat(vp, &sb, td->td_ucred, NOCRED((struct ucred *)0), td)) == 0) &&
1805 sb.st_ino != oldinum) {
1806 error = EIDRM82; /* Identifier removed */
1807 } else {
1808 /*
1809 * The root of a mounted filesystem cannot be deleted.
1810 *
1811 * XXX: can this only be a VDIR case?
1812 */
1813 if (vp->v_vflag & VV_ROOT0x0001)
1814 error = EBUSY16;
1815 }
1816 if (error == 0) {
1817 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
1818 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1819 vput(nd.ni_dvp);
1820 if (vp == nd.ni_dvp)
1821 vrele(vp);
1822 else
1823 vput(vp);
1824 if ((error = vn_start_write(NULL((void *)0), &mp,
1825 V_XSLEEP0x0004 | PCATCH0x100)) != 0)
1826 return (error);
1827 goto restart;
1828 }
1829#ifdef MAC1
1830 error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
1831 &nd.ni_cnd);
1832 if (error != 0)
1833 goto out;
1834#endif
1835 vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK2);
1836 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1837#ifdef MAC1
1838out:
1839#endif
1840 vn_finished_write(mp);
1841 }
1842 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
1843 vput(nd.ni_dvp);
1844 if (vp == nd.ni_dvp)
1845 vrele(vp);
1846 else
1847 vput(vp);
1848 return (error);
1849}
1850
1851/*
1852 * Reposition read/write file offset.
1853 */
1854#ifndef _SYS_SYSPROTO_H_
1855struct lseek_args {
1856 int fd;
1857 int pad;
1858 off_t offset;
1859 int whence;
1860};
1861#endif
1862int
1863sys_lseek(struct thread *td, struct lseek_args *uap)
1864{
1865
1866 return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
1867}
1868
1869int
1870kern_lseek(struct thread *td, int fd, off_t offset, int whence)
1871{
1872 struct file *fp;
1873 int error;
1874
1875 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
1876 error = fget(td, fd, &cap_seek_rights, &fp);
1877 if (error != 0)
1878 return (error);
1879 error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE0x02) != 0 ?
1880 fo_seek(fp, offset, whence, td) : ESPIPE29;
1881 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
1882 return (error);
1883}
1884
1885#if defined(COMPAT_43)
1886/*
1887 * Reposition read/write file offset.
1888 */
1889#ifndef _SYS_SYSPROTO_H_
1890struct olseek_args {
1891 int fd;
1892 long offset;
1893 int whence;
1894};
1895#endif
1896int
1897olseek(struct thread *td, struct olseek_args *uap)
1898{
1899
1900 return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
1901}
1902#endif /* COMPAT_43 */
1903
1904#if defined(COMPAT_FREEBSD61)
1905/* Version with the 'pad' argument */
1906int
1907freebsd6_lseek(struct thread *td, struct freebsd6_lseek_args *uap)
1908{
1909
1910 return (kern_lseek(td, uap->fd, uap->offset, uap->whence));
1911}
1912#endif
1913
1914/*
1915 * Check access permissions using passed credentials.
1916 */
1917static int
1918vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
1919 struct thread *td)
1920{
1921 accmode_t accmode;
1922 int error;
1923
1924 /* Flags == 0 means only check for existence. */
1925 if (user_flags == 0)
1926 return (0);
1927
1928 accmode = 0;
1929 if (user_flags & R_OK0x04)
1930 accmode |= VREAD000000000400;
1931 if (user_flags & W_OK0x02)
1932 accmode |= VWRITE000000000200;
1933 if (user_flags & X_OK0x01)
1934 accmode |= VEXEC000000000100;
1935#ifdef MAC1
1936 error = mac_vnode_check_access(cred, vp, accmode);
1937 if (error != 0)
1938 return (error);
1939#endif
1940 if ((accmode & VWRITE000000000200) == 0 || (error = vn_writechk(vp)) == 0)
1941 error = VOP_ACCESS(vp, accmode, cred, td);
1942 return (error);
1943}
1944
1945/*
1946 * Check access permissions using "real" credentials.
1947 */
1948#ifndef _SYS_SYSPROTO_H_
1949struct access_args {
1950 char *path;
1951 int amode;
1952};
1953#endif
1954int
1955sys_access(struct thread *td, struct access_args *uap)
1956{
1957
1958 return (kern_accessat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
1959 0, uap->amode));
1960}
1961
1962#ifndef _SYS_SYSPROTO_H_
1963struct faccessat_args {
1964 int dirfd;
1965 char *path;
1966 int amode;
1967 int flag;
1968}
1969#endif
1970int
1971sys_faccessat(struct thread *td, struct faccessat_args *uap)
1972{
1973
1974 return (kern_accessat(td, uap->fd, uap->path, UIO_USERSPACE, uap->flag,
1975 uap->amode));
1976}
1977
1978int
1979kern_accessat(struct thread *td, int fd, const char *path,
1980 enum uio_seg pathseg, int flag, int amode)
1981{
1982 struct ucred *cred, *usecred;
1983 struct vnode *vp;
1984 struct nameidata nd;
1985 int error;
1986
1987 if ((flag & ~(AT_EACCESS0x0100 | AT_BENEATH0x1000)) != 0)
1988 return (EINVAL22);
1989 if (amode != F_OK0 && (amode & ~(R_OK0x04 | W_OK0x02 | X_OK0x01)) != 0)
1990 return (EINVAL22);
1991
1992 /*
1993 * Create and modify a temporary credential instead of one that
1994 * is potentially shared (if we need one).
1995 */
1996 cred = td->td_ucred;
1997 if ((flag & AT_EACCESS0x0100) == 0 &&
1998 ((cred->cr_uid != cred->cr_ruid ||
1999 cred->cr_rgid != cred->cr_groups[0]))) {
2000 usecred = crdup(cred);
2001 usecred->cr_uid = cred->cr_ruid;
2002 usecred->cr_groups[0] = cred->cr_rgid;
2003 td->td_ucred = usecred;
2004 } else
2005 usecred = cred;
2006 AUDIT_ARG_VALUE(amode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_value((amode)); } while (0)
;
2007 NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000 |
((flag & 0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, (
(void *)0), &cap_fstat_rights, td)
2008 AUDITVNODE1 | ((flag & AT_BENEATH) != 0 ? BENEATH : 0),NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000 |
((flag & 0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, (
(void *)0), &cap_fstat_rights, td)
2009 pathseg, path, fd, &cap_fstat_rights, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0100 | 0x0004 | 0x04000000 |
((flag & 0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, (
(void *)0), &cap_fstat_rights, td)
;
2010 if ((error = namei(&nd)) != 0)
2011 goto out;
2012 vp = nd.ni_vp;
2013
2014 error = vn_access(vp, amode, usecred, td);
2015 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2016 vput(vp);
2017out:
2018 if (usecred != cred) {
2019 td->td_ucred = cred;
2020 crfree(usecred);
2021 }
2022 return (error);
2023}
2024
2025/*
2026 * Check access permissions using "effective" credentials.
2027 */
2028#ifndef _SYS_SYSPROTO_H_
2029struct eaccess_args {
2030 char *path;
2031 int amode;
2032};
2033#endif
2034int
2035sys_eaccess(struct thread *td, struct eaccess_args *uap)
2036{
2037
2038 return (kern_accessat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2039 AT_EACCESS0x0100, uap->amode));
2040}
2041
2042#if defined(COMPAT_43)
2043/*
2044 * Get file status; this version follows links.
2045 */
2046#ifndef _SYS_SYSPROTO_H_
2047struct ostat_args {
2048 char *path;
2049 struct ostat *ub;
2050};
2051#endif
2052int
2053ostat(struct thread *td, struct ostat_args *uap)
2054{
2055 struct stat sb;
2056 struct ostat osb;
2057 int error;
2058
2059 error = kern_statat(td, 0, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2060 &sb, NULL((void *)0));
2061 if (error != 0)
2062 return (error);
2063 cvtstat(&sb, &osb);
2064 return (copyout(&osb, uap->ub, sizeof (osb)));
2065}
2066
2067/*
2068 * Get file status; this version does not follow links.
2069 */
2070#ifndef _SYS_SYSPROTO_H_
2071struct olstat_args {
2072 char *path;
2073 struct ostat *ub;
2074};
2075#endif
2076int
2077olstat(struct thread *td, struct olstat_args *uap)
2078{
2079 struct stat sb;
2080 struct ostat osb;
2081 int error;
2082
2083 error = kern_statat(td, AT_SYMLINK_NOFOLLOW0x0200, AT_FDCWD-100, uap->path,
2084 UIO_USERSPACE, &sb, NULL((void *)0));
2085 if (error != 0)
2086 return (error);
2087 cvtstat(&sb, &osb);
2088 return (copyout(&osb, uap->ub, sizeof (osb)));
2089}
2090
2091/*
2092 * Convert from an old to a new stat structure.
2093 * XXX: many values are blindly truncated.
2094 */
2095void
2096cvtstat(struct stat *st, struct ostat *ost)
2097{
2098
2099 bzero(ost, sizeof(*ost))__builtin_memset((ost), 0, (sizeof(*ost)));
2100 ost->st_dev = st->st_dev;
2101 ost->st_ino = st->st_ino;
2102 ost->st_mode = st->st_mode;
2103 ost->st_nlink = st->st_nlink;
2104 ost->st_uid = st->st_uid;
2105 ost->st_gid = st->st_gid;
2106 ost->st_rdev = st->st_rdev;
2107 ost->st_size = MIN(st->st_size, INT32_MAX)(((st->st_size)<(0x7fffffff))?(st->st_size):(0x7fffffff
))
;
2108 ost->st_atim = st->st_atim;
2109 ost->st_mtim = st->st_mtim;
2110 ost->st_ctim = st->st_ctim;
2111 ost->st_blksize = st->st_blksize;
2112 ost->st_blocks = st->st_blocks;
2113 ost->st_flags = st->st_flags;
2114 ost->st_gen = st->st_gen;
2115}
2116#endif /* COMPAT_43 */
2117
2118#if defined(COMPAT_43) || defined(COMPAT_FREEBSD111)
2119int ino64_trunc_error;
2120SYSCTL_INT(_vfs, OID_AUTO, ino64_trunc_error, CTLFLAG_RW,static struct sysctl_oid sysctl___vfs_ino64_trunc_error = { .
oid_parent = ((&(&sysctl___vfs)->oid_children)), .
oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&ino64_trunc_error), .oid_arg2 = (0), .oid_name = ("ino64_trunc_error"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Error on truncation of device, file or inode number, or link count"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___vfs_ino64_trunc_error __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___vfs_ino64_trunc_error); _Static_assert((((
(0x80000000|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000
)) & 0) == 2) && sizeof(int) == sizeof(*(&ino64_trunc_error
)), "compile-time assertion failed")
2121 &ino64_trunc_error, 0,static struct sysctl_oid sysctl___vfs_ino64_trunc_error = { .
oid_parent = ((&(&sysctl___vfs)->oid_children)), .
oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&ino64_trunc_error), .oid_arg2 = (0), .oid_name = ("ino64_trunc_error"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Error on truncation of device, file or inode number, or link count"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___vfs_ino64_trunc_error __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___vfs_ino64_trunc_error); _Static_assert((((
(0x80000000|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000
)) & 0) == 2) && sizeof(int) == sizeof(*(&ino64_trunc_error
)), "compile-time assertion failed")
2122 "Error on truncation of device, file or inode number, or link count")static struct sysctl_oid sysctl___vfs_ino64_trunc_error = { .
oid_parent = ((&(&sysctl___vfs)->oid_children)), .
oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind
= (2 | 0x00040000 | ((0x80000000|0x40000000))), .oid_arg1 = (
&ino64_trunc_error), .oid_arg2 = (0), .oid_name = ("ino64_trunc_error"
), .oid_handler = (sysctl_handle_int), .oid_fmt = ("I"), .oid_descr
= "Error on truncation of device, file or inode number, or link count"
, .oid_label = (((void *)0)), }; __asm__(".globl " "__start_set_sysctl_set"
); __asm__(".globl " "__stop_set_sysctl_set"); static void const
* const __set_sysctl_set_sym_sysctl___vfs_ino64_trunc_error __attribute__
((__section__("set_" "sysctl_set"))) __attribute__((__used__)
) = &(sysctl___vfs_ino64_trunc_error); _Static_assert((((
(0x80000000|0x40000000)) & 0xf) == 0 || (((0x80000000|0x40000000
)) & 0) == 2) && sizeof(int) == sizeof(*(&ino64_trunc_error
)), "compile-time assertion failed")
;
2123
2124int
2125freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost)
2126{
2127
2128 ost->st_dev = st->st_dev;
2129 if (ost->st_dev != st->st_dev) {
2130 switch (ino64_trunc_error) {
2131 default:
2132 /*
2133 * Since dev_t is almost raw, don't clamp to the
2134 * maximum for case 2, but ignore the error.
2135 */
2136 break;
2137 case 1:
2138 return (EOVERFLOW84);
2139 }
2140 }
2141 ost->st_ino = st->st_ino;
2142 if (ost->st_ino != st->st_ino) {
2143 switch (ino64_trunc_error) {
2144 default:
2145 case 0:
2146 break;
2147 case 1:
2148 return (EOVERFLOW84);
2149 case 2:
2150 ost->st_ino = UINT32_MAX0xffffffffU;
2151 break;
2152 }
2153 }
2154 ost->st_mode = st->st_mode;
2155 ost->st_nlink = st->st_nlink;
2156 if (ost->st_nlink != st->st_nlink) {
2157 switch (ino64_trunc_error) {
2158 default:
2159 case 0:
2160 break;
2161 case 1:
2162 return (EOVERFLOW84);
2163 case 2:
2164 ost->st_nlink = UINT16_MAX0xffff;
2165 break;
2166 }
2167 }
2168 ost->st_uid = st->st_uid;
2169 ost->st_gid = st->st_gid;
2170 ost->st_rdev = st->st_rdev;
2171 if (ost->st_rdev != st->st_rdev) {
2172 switch (ino64_trunc_error) {
2173 default:
2174 break;
2175 case 1:
2176 return (EOVERFLOW84);
2177 }
2178 }
2179 ost->st_atim = st->st_atim;
2180 ost->st_mtim = st->st_mtim;
2181 ost->st_ctim = st->st_ctim;
2182 ost->st_size = st->st_size;
2183 ost->st_blocks = st->st_blocks;
2184 ost->st_blksize = st->st_blksize;
2185 ost->st_flags = st->st_flags;
2186 ost->st_gen = st->st_gen;
2187 ost->st_lspare = 0;
2188 ost->st_birthtim = st->st_birthtim;
2189 bzero((char *)&ost->st_birthtim + sizeof(ost->st_birthtim),__builtin_memset(((char *)&ost->st_birthtim + sizeof(ost
->st_birthtim)), 0, (sizeof(*ost) - __builtin_offsetof(struct
freebsd11_stat, st_birthtim) - sizeof(ost->st_birthtim)))
2190 sizeof(*ost) - offsetof(struct freebsd11_stat,__builtin_memset(((char *)&ost->st_birthtim + sizeof(ost
->st_birthtim)), 0, (sizeof(*ost) - __builtin_offsetof(struct
freebsd11_stat, st_birthtim) - sizeof(ost->st_birthtim)))
2191 st_birthtim) - sizeof(ost->st_birthtim))__builtin_memset(((char *)&ost->st_birthtim + sizeof(ost
->st_birthtim)), 0, (sizeof(*ost) - __builtin_offsetof(struct
freebsd11_stat, st_birthtim) - sizeof(ost->st_birthtim)))
;
2192 return (0);
2193}
2194
2195int
2196freebsd11_stat(struct thread *td, struct freebsd11_stat_args* uap)
2197{
2198 struct stat sb;
2199 struct freebsd11_stat osb;
2200 int error;
2201
2202 error = kern_statat(td, 0, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2203 &sb, NULL((void *)0));
2204 if (error != 0)
2205 return (error);
2206 error = freebsd11_cvtstat(&sb, &osb);
2207 if (error == 0)
2208 error = copyout(&osb, uap->ub, sizeof(osb));
2209 return (error);
2210}
2211
2212int
2213freebsd11_lstat(struct thread *td, struct freebsd11_lstat_args* uap)
2214{
2215 struct stat sb;
2216 struct freebsd11_stat osb;
2217 int error;
2218
2219 error = kern_statat(td, AT_SYMLINK_NOFOLLOW0x0200, AT_FDCWD-100, uap->path,
2220 UIO_USERSPACE, &sb, NULL((void *)0));
2221 if (error != 0)
2222 return (error);
2223 error = freebsd11_cvtstat(&sb, &osb);
2224 if (error == 0)
2225 error = copyout(&osb, uap->ub, sizeof(osb));
2226 return (error);
2227}
2228
2229int
2230freebsd11_fhstat(struct thread *td, struct freebsd11_fhstat_args* uap)
2231{
2232 struct fhandle fh;
2233 struct stat sb;
2234 struct freebsd11_stat osb;
2235 int error;
2236
2237 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
2238 if (error != 0)
2239 return (error);
2240 error = kern_fhstat(td, fh, &sb);
2241 if (error != 0)
2242 return (error);
2243 error = freebsd11_cvtstat(&sb, &osb);
2244 if (error == 0)
2245 error = copyout(&osb, uap->sb, sizeof(osb));
2246 return (error);
2247}
2248
2249int
2250freebsd11_fstatat(struct thread *td, struct freebsd11_fstatat_args* uap)
2251{
2252 struct stat sb;
2253 struct freebsd11_stat osb;
2254 int error;
2255
2256 error = kern_statat(td, uap->flag, uap->fd, uap->path,
2257 UIO_USERSPACE, &sb, NULL((void *)0));
2258 if (error != 0)
2259 return (error);
2260 error = freebsd11_cvtstat(&sb, &osb);
2261 if (error == 0)
2262 error = copyout(&osb, uap->buf, sizeof(osb));
2263 return (error);
2264}
2265#endif /* COMPAT_FREEBSD11 */
2266
2267/*
2268 * Get file status
2269 */
2270#ifndef _SYS_SYSPROTO_H_
2271struct fstatat_args {
2272 int fd;
2273 char *path;
2274 struct stat *buf;
2275 int flag;
2276}
2277#endif
2278int
2279sys_fstatat(struct thread *td, struct fstatat_args *uap)
2280{
2281 struct stat sb;
2282 int error;
2283
2284 error = kern_statat(td, uap->flag, uap->fd, uap->path,
2285 UIO_USERSPACE, &sb, NULL((void *)0));
2286 if (error == 0)
2287 error = copyout(&sb, uap->buf, sizeof (sb));
2288 return (error);
2289}
2290
2291int
2292kern_statat(struct thread *td, int flag, int fd, const char *path,
2293 enum uio_seg pathseg, struct stat *sbp,
2294 void (*hook)(struct vnode *vp, struct stat *sbp))
2295{
2296 struct nameidata nd;
2297 int error;
2298
2299 if ((flag & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
2300 return (EINVAL22);
2301
2302 NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) != 0 ?NDINIT_ALL(&nd, 0, ((flag & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x0100 | 0x0004
| 0x04000000, pathseg, path, fd, ((void *)0), &cap_fstat_rights
, td)
2303 NOFOLLOW : FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) |NDINIT_ALL(&nd, 0, ((flag & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x0100 | 0x0004
| 0x04000000, pathseg, path, fd, ((void *)0), &cap_fstat_rights
, td)
2304 LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, ((flag & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x0100 | 0x0004
| 0x04000000, pathseg, path, fd, ((void *)0), &cap_fstat_rights
, td)
2305 &cap_fstat_rights, td)NDINIT_ALL(&nd, 0, ((flag & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x0100 | 0x0004
| 0x04000000, pathseg, path, fd, ((void *)0), &cap_fstat_rights
, td)
;
2306
2307 if ((error = namei(&nd)) != 0)
2308 return (error);
2309 error = vn_stat(nd.ni_vp, sbp, td->td_ucred, NOCRED((struct ucred *)0), td);
2310 if (error == 0) {
2311 SDT_PROBE2(vfs, , stat, mode, path, sbp->st_mode)do { if (__builtin_expect((sdt_probes_enabled), 0)) { if (__builtin_expect
((sdt_vfs__stat_mode->id), 0)) (*sdt_probe_func)(sdt_vfs__stat_mode
->id, (uintptr_t) path, (uintptr_t) sbp->st_mode, (uintptr_t
) 0, (uintptr_t) 0, (uintptr_t) 0); } } while (0)
;
2312 if (S_ISREG(sbp->st_mode)(((sbp->st_mode) & 0170000) == 0100000))
2313 SDT_PROBE2(vfs, , stat, reg, path, pathseg)do { if (__builtin_expect((sdt_probes_enabled), 0)) { if (__builtin_expect
((sdt_vfs__stat_reg->id), 0)) (*sdt_probe_func)(sdt_vfs__stat_reg
->id, (uintptr_t) path, (uintptr_t) pathseg, (uintptr_t) 0
, (uintptr_t) 0, (uintptr_t) 0); } } while (0)
;
2314 if (__predict_false(hook != NULL)__builtin_expect((hook != ((void *)0)), 0))
2315 hook(nd.ni_vp, sbp);
2316 }
2317 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2318 vput(nd.ni_vp);
2319 if (error != 0)
2320 return (error);
2321#ifdef __STAT_TIME_T_EXT
2322 sbp->st_atim_ext = 0;
2323 sbp->st_mtim_ext = 0;
2324 sbp->st_ctim_ext = 0;
2325 sbp->st_btim_ext = 0;
2326#endif
2327#ifdef KTRACE1
2328 if (KTRPOINT(td, KTR_STRUCT)(__builtin_expect(((((td))->td_proc->p_traceflag & (
1 << (8)))), 0))
)
2329 ktrstat(sbp)ktrstruct("stat", (sbp), sizeof(struct stat));
2330#endif
2331 return (0);
2332}
2333
2334#if defined(COMPAT_FREEBSD111)
2335/*
2336 * Implementation of the NetBSD [l]stat() functions.
2337 */
2338void
2339freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb)
2340{
2341
2342 bzero(nsb, sizeof(*nsb))__builtin_memset((nsb), 0, (sizeof(*nsb)));
2343 nsb->st_dev = sb->st_dev;
2344 nsb->st_ino = sb->st_ino;
2345 nsb->st_mode = sb->st_mode;
2346 nsb->st_nlink = sb->st_nlink;
2347 nsb->st_uid = sb->st_uid;
2348 nsb->st_gid = sb->st_gid;
2349 nsb->st_rdev = sb->st_rdev;
2350 nsb->st_atim = sb->st_atim;
2351 nsb->st_mtim = sb->st_mtim;
2352 nsb->st_ctim = sb->st_ctim;
2353 nsb->st_size = sb->st_size;
2354 nsb->st_blocks = sb->st_blocks;
2355 nsb->st_blksize = sb->st_blksize;
2356 nsb->st_flags = sb->st_flags;
2357 nsb->st_gen = sb->st_gen;
2358 nsb->st_birthtim = sb->st_birthtim;
2359}
2360
2361#ifndef _SYS_SYSPROTO_H_
2362struct freebsd11_nstat_args {
2363 char *path;
2364 struct nstat *ub;
2365};
2366#endif
2367int
2368freebsd11_nstat(struct thread *td, struct freebsd11_nstat_args *uap)
2369{
2370 struct stat sb;
2371 struct nstat nsb;
2372 int error;
2373
2374 error = kern_statat(td, 0, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2375 &sb, NULL((void *)0));
2376 if (error != 0)
2377 return (error);
2378 freebsd11_cvtnstat(&sb, &nsb);
2379 return (copyout(&nsb, uap->ub, sizeof (nsb)));
2380}
2381
2382/*
2383 * NetBSD lstat. Get file status; this version does not follow links.
2384 */
2385#ifndef _SYS_SYSPROTO_H_
2386struct freebsd11_nlstat_args {
2387 char *path;
2388 struct nstat *ub;
2389};
2390#endif
2391int
2392freebsd11_nlstat(struct thread *td, struct freebsd11_nlstat_args *uap)
2393{
2394 struct stat sb;
2395 struct nstat nsb;
2396 int error;
2397
2398 error = kern_statat(td, AT_SYMLINK_NOFOLLOW0x0200, AT_FDCWD-100, uap->path,
2399 UIO_USERSPACE, &sb, NULL((void *)0));
2400 if (error != 0)
2401 return (error);
2402 freebsd11_cvtnstat(&sb, &nsb);
2403 return (copyout(&nsb, uap->ub, sizeof (nsb)));
2404}
2405#endif /* COMPAT_FREEBSD11 */
2406
2407/*
2408 * Get configurable pathname variables.
2409 */
2410#ifndef _SYS_SYSPROTO_H_
2411struct pathconf_args {
2412 char *path;
2413 int name;
2414};
2415#endif
2416int
2417sys_pathconf(struct thread *td, struct pathconf_args *uap)
2418{
2419 long value;
2420 int error;
2421
2422 error = kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, FOLLOW0x0040,
2423 &value);
2424 if (error == 0)
2425 td->td_retvaltd_uretoff.tdu_retval[0] = value;
2426 return (error);
2427}
2428
2429#ifndef _SYS_SYSPROTO_H_
2430struct lpathconf_args {
2431 char *path;
2432 int name;
2433};
2434#endif
2435int
2436sys_lpathconf(struct thread *td, struct lpathconf_args *uap)
2437{
2438 long value;
2439 int error;
2440
2441 error = kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name,
2442 NOFOLLOW0x0000, &value);
2443 if (error == 0)
2444 td->td_retvaltd_uretoff.tdu_retval[0] = value;
2445 return (error);
2446}
2447
2448int
2449kern_pathconf(struct thread *td, const char *path, enum uio_seg pathseg,
2450 int name, u_long flags, long *valuep)
2451{
2452 struct nameidata nd;
2453 int error;
2454
2455 NDINIT(&nd, LOOKUP, LOCKSHARED | LOCKLEAF | AUDITVNODE1 | flags,NDINIT_ALL(&nd, 0, 0x0100 | 0x0004 | 0x04000000 | flags, pathseg
, path, -100, ((void *)0), 0, td)
2456 pathseg, path, td)NDINIT_ALL(&nd, 0, 0x0100 | 0x0004 | 0x04000000 | flags, pathseg
, path, -100, ((void *)0), 0, td)
;
2457 if ((error = namei(&nd)) != 0)
2458 return (error);
2459 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2460
2461 error = VOP_PATHCONF(nd.ni_vp, name, valuep);
2462 vput(nd.ni_vp);
2463 return (error);
2464}
2465
2466/*
2467 * Return target name of a symbolic link.
2468 */
2469#ifndef _SYS_SYSPROTO_H_
2470struct readlink_args {
2471 char *path;
2472 char *buf;
2473 size_t count;
2474};
2475#endif
2476int
2477sys_readlink(struct thread *td, struct readlink_args *uap)
2478{
2479
2480 return (kern_readlinkat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2481 uap->buf, UIO_USERSPACE, uap->count));
2482}
2483#ifndef _SYS_SYSPROTO_H_
2484struct readlinkat_args {
2485 int fd;
2486 char *path;
2487 char *buf;
2488 size_t bufsize;
2489};
2490#endif
2491int
2492sys_readlinkat(struct thread *td, struct readlinkat_args *uap)
2493{
2494
2495 return (kern_readlinkat(td, uap->fd, uap->path, UIO_USERSPACE,
2496 uap->buf, UIO_USERSPACE, uap->bufsize));
2497}
2498
2499int
2500kern_readlinkat(struct thread *td, int fd, const char *path,
2501 enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count)
2502{
2503 struct vnode *vp;
2504 struct nameidata nd;
2505 int error;
2506
2507 if (count > IOSIZE_MAXiosize_max())
2508 return (EINVAL22);
2509
2510 NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,NDINIT_ALL(&nd, 0, 0x0000 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, fd, ((void *)0), 0, td)
2511 pathseg, path, fd, td)NDINIT_ALL(&nd, 0, 0x0000 | 0x0100 | 0x0004 | 0x04000000,
pathseg, path, fd, ((void *)0), 0, td)
;
2512
2513 if ((error = namei(&nd)) != 0)
2514 return (error);
2515 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2516 vp = nd.ni_vp;
2517
2518 error = kern_readlink_vp(vp, buf, bufseg, count, td);
2519 vput(vp);
2520
2521 return (error);
2522}
2523
2524/*
2525 * Helper function to readlink from a vnode
2526 */
2527static int
2528kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg, size_t count,
2529 struct thread *td)
2530{
2531 struct iovec aiov;
2532 struct uio auio;
2533 int error;
2534
2535 ASSERT_VOP_LOCKED(vp, "kern_readlink_vp(): vp not locked")((void)0);
2536#ifdef MAC1
2537 error = mac_vnode_check_readlink(td->td_ucred, vp);
2538 if (error != 0)
2539 return (error);
2540#endif
2541 if (vp->v_type != VLNK && (vp->v_vflag & VV_READLINK0x2000) == 0)
2542 return (EINVAL22);
2543
2544 aiov.iov_base = buf;
2545 aiov.iov_len = count;
2546 auio.uio_iov = &aiov;
2547 auio.uio_iovcnt = 1;
2548 auio.uio_offset = 0;
2549 auio.uio_rw = UIO_READ;
2550 auio.uio_segflg = bufseg;
2551 auio.uio_td = td;
2552 auio.uio_resid = count;
2553 error = VOP_READLINK(vp, &auio, td->td_ucred);
2554 td->td_retvaltd_uretoff.tdu_retval[0] = count - auio.uio_resid;
2555 return (error);
2556}
2557
2558/*
2559 * Common implementation code for chflags() and fchflags().
2560 */
2561static int
2562setfflags(struct thread *td, struct vnode *vp, u_long flags)
2563{
2564 struct mount *mp;
2565 struct vattr vattr;
2566 int error;
2567
2568 /* We can't support the value matching VNOVAL. */
2569 if (flags == VNOVAL(-1))
2570 return (EOPNOTSUPP45);
2571
2572 /*
2573 * Prevent non-root users from setting flags on devices. When
2574 * a device is reused, users can retain ownership of the device
2575 * if they are allowed to set flags and programs assume that
2576 * chown can't fail when done as root.
2577 */
2578 if (vp->v_type == VCHR || vp->v_type == VBLK) {
2579 error = priv_check(td, PRIV_VFS_CHFLAGS_DEV316);
2580 if (error != 0)
2581 return (error);
2582 }
2583
2584 if ((error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100)) != 0)
2585 return (error);
2586 VATTR_NULL(&vattr)(*(&vattr) = va_null);
2587 vattr.va_flags = flags;
2588 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)_vn_lock(vp, 0x080000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 2588)
;
2589#ifdef MAC1
2590 error = mac_vnode_check_setflags(td->td_ucred, vp, vattr.va_flags);
2591 if (error == 0)
2592#endif
2593 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
2594 VOP_UNLOCK(vp, 0);
2595 vn_finished_write(mp);
2596 return (error);
2597}
2598
2599/*
2600 * Change flags of a file given a path name.
2601 */
2602#ifndef _SYS_SYSPROTO_H_
2603struct chflags_args {
2604 const char *path;
2605 u_long flags;
2606};
2607#endif
2608int
2609sys_chflags(struct thread *td, struct chflags_args *uap)
2610{
2611
2612 return (kern_chflagsat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2613 uap->flags, 0));
2614}
2615
2616#ifndef _SYS_SYSPROTO_H_
2617struct chflagsat_args {
2618 int fd;
2619 const char *path;
2620 u_long flags;
2621 int atflag;
2622}
2623#endif
2624int
2625sys_chflagsat(struct thread *td, struct chflagsat_args *uap)
2626{
2627
2628 if ((uap->atflag & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
2629 return (EINVAL22);
2630
2631 return (kern_chflagsat(td, uap->fd, uap->path, UIO_USERSPACE,
2632 uap->flags, uap->atflag));
2633}
2634
2635/*
2636 * Same as chflags() but doesn't follow symlinks.
2637 */
2638#ifndef _SYS_SYSPROTO_H_
2639struct lchflags_args {
2640 const char *path;
2641 u_long flags;
2642};
2643#endif
2644int
2645sys_lchflags(struct thread *td, struct lchflags_args *uap)
2646{
2647
2648 return (kern_chflagsat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2649 uap->flags, AT_SYMLINK_NOFOLLOW0x0200));
2650}
2651
2652static int
2653kern_chflagsat(struct thread *td, int fd, const char *path,
2654 enum uio_seg pathseg, u_long flags, int atflag)
2655{
2656 struct nameidata nd;
2657 int error, follow;
2658
2659 AUDIT_ARG_FFLAGS(flags)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fflags((flags)); } while (0)
;
2660 follow = (atflag & AT_SYMLINK_NOFOLLOW0x0200) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2661 follow |= (atflag & AT_BENEATH0x1000) != 0 ? BENEATH0x0080 : 0;
2662 NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchflags_rights, td)
2663 &cap_fchflags_rights, td)NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchflags_rights, td)
;
2664 if ((error = namei(&nd)) != 0)
2665 return (error);
2666 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2667 error = setfflags(td, nd.ni_vp, flags);
2668 vrele(nd.ni_vp);
2669 return (error);
2670}
2671
2672/*
2673 * Change flags of a file given a file descriptor.
2674 */
2675#ifndef _SYS_SYSPROTO_H_
2676struct fchflags_args {
2677 int fd;
2678 u_long flags;
2679};
2680#endif
2681int
2682sys_fchflags(struct thread *td, struct fchflags_args *uap)
2683{
2684 struct file *fp;
2685 int error;
2686
2687 AUDIT_ARG_FD(uap->fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->fd)); } while (0)
;
2688 AUDIT_ARG_FFLAGS(uap->flags)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fflags((uap->flags)); } while
(0)
;
2689 error = getvnode(td, uap->fd, &cap_fchflags_rights,
2690 &fp);
2691 if (error != 0)
2692 return (error);
2693#ifdef AUDIT1
2694 vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY)_vn_lock(fp->f_vnode, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 2694)
;
2695 AUDIT_ARG_VNODE1(fp->f_vnode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((fp->f_vnode)); } while
(0)
;
2696 VOP_UNLOCK(fp->f_vnode, 0);
2697#endif
2698 error = setfflags(td, fp->f_vnode, uap->flags);
2699 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2700 return (error);
2701}
2702
2703/*
2704 * Common implementation code for chmod(), lchmod() and fchmod().
2705 */
2706int
2707setfmode(struct thread *td, struct ucred *cred, struct vnode *vp, int mode)
2708{
2709 struct mount *mp;
2710 struct vattr vattr;
2711 int error;
2712
2713 if ((error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100)) != 0)
2714 return (error);
2715 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)_vn_lock(vp, 0x080000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 2715)
;
2716 VATTR_NULL(&vattr)(*(&vattr) = va_null);
2717 vattr.va_mode = mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007);
2718#ifdef MAC1
2719 error = mac_vnode_check_setmode(cred, vp, vattr.va_mode);
2720 if (error == 0)
2721#endif
2722 error = VOP_SETATTR(vp, &vattr, cred);
2723 VOP_UNLOCK(vp, 0);
2724 vn_finished_write(mp);
2725 return (error);
2726}
2727
2728/*
2729 * Change mode of a file given path name.
2730 */
2731#ifndef _SYS_SYSPROTO_H_
2732struct chmod_args {
2733 char *path;
2734 int mode;
2735};
2736#endif
2737int
2738sys_chmod(struct thread *td, struct chmod_args *uap)
2739{
2740
2741 return (kern_fchmodat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2742 uap->mode, 0));
2743}
2744
2745#ifndef _SYS_SYSPROTO_H_
2746struct fchmodat_args {
2747 int dirfd;
2748 char *path;
2749 mode_t mode;
2750 int flag;
2751}
2752#endif
2753int
2754sys_fchmodat(struct thread *td, struct fchmodat_args *uap)
2755{
2756
2757 if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
2758 return (EINVAL22);
2759
2760 return (kern_fchmodat(td, uap->fd, uap->path, UIO_USERSPACE,
2761 uap->mode, uap->flag));
2762}
2763
2764/*
2765 * Change mode of a file given path name (don't follow links.)
2766 */
2767#ifndef _SYS_SYSPROTO_H_
2768struct lchmod_args {
2769 char *path;
2770 int mode;
2771};
2772#endif
2773int
2774sys_lchmod(struct thread *td, struct lchmod_args *uap)
2775{
2776
2777 return (kern_fchmodat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2778 uap->mode, AT_SYMLINK_NOFOLLOW0x0200));
2779}
2780
2781int
2782kern_fchmodat(struct thread *td, int fd, const char *path,
2783 enum uio_seg pathseg, mode_t mode, int flag)
2784{
2785 struct nameidata nd;
2786 int error, follow;
2787
2788 AUDIT_ARG_MODE(mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((mode)); } while (0)
;
2789 follow = (flag & AT_SYMLINK_NOFOLLOW0x0200) != 0 ? NOFOLLOW0x0000 : FOLLOW0x0040;
2790 follow |= (flag & AT_BENEATH0x1000) != 0 ? BENEATH0x0080 : 0;
2791 NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchmod_rights, td)
2792 &cap_fchmod_rights, td)NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchmod_rights, td)
;
2793 if ((error = namei(&nd)) != 0)
2794 return (error);
2795 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2796 error = setfmode(td, td->td_ucred, nd.ni_vp, mode);
2797 vrele(nd.ni_vp);
2798 return (error);
2799}
2800
2801/*
2802 * Change mode of a file given a file descriptor.
2803 */
2804#ifndef _SYS_SYSPROTO_H_
2805struct fchmod_args {
2806 int fd;
2807 int mode;
2808};
2809#endif
2810int
2811sys_fchmod(struct thread *td, struct fchmod_args *uap)
2812{
2813 struct file *fp;
2814 int error;
2815
2816 AUDIT_ARG_FD(uap->fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->fd)); } while (0)
;
2817 AUDIT_ARG_MODE(uap->mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((uap->mode)); } while (0
)
;
2818
2819 error = fget(td, uap->fd, &cap_fchmod_rights, &fp);
2820 if (error != 0)
2821 return (error);
2822 error = fo_chmod(fp, uap->mode, td->td_ucred, td);
2823 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2824 return (error);
2825}
2826
2827/*
2828 * Common implementation for chown(), lchown(), and fchown()
2829 */
2830int
2831setfown(struct thread *td, struct ucred *cred, struct vnode *vp, uid_t uid,
2832 gid_t gid)
2833{
2834 struct mount *mp;
2835 struct vattr vattr;
2836 int error;
2837
2838 if ((error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100)) != 0)
2839 return (error);
2840 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)_vn_lock(vp, 0x080000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 2840)
;
2841 VATTR_NULL(&vattr)(*(&vattr) = va_null);
2842 vattr.va_uid = uid;
2843 vattr.va_gid = gid;
2844#ifdef MAC1
2845 error = mac_vnode_check_setowner(cred, vp, vattr.va_uid,
2846 vattr.va_gid);
2847 if (error == 0)
2848#endif
2849 error = VOP_SETATTR(vp, &vattr, cred);
2850 VOP_UNLOCK(vp, 0);
2851 vn_finished_write(mp);
2852 return (error);
2853}
2854
2855/*
2856 * Set ownership given a path name.
2857 */
2858#ifndef _SYS_SYSPROTO_H_
2859struct chown_args {
2860 char *path;
2861 int uid;
2862 int gid;
2863};
2864#endif
2865int
2866sys_chown(struct thread *td, struct chown_args *uap)
2867{
2868
2869 return (kern_fchownat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE, uap->uid,
2870 uap->gid, 0));
2871}
2872
2873#ifndef _SYS_SYSPROTO_H_
2874struct fchownat_args {
2875 int fd;
2876 const char * path;
2877 uid_t uid;
2878 gid_t gid;
2879 int flag;
2880};
2881#endif
2882int
2883sys_fchownat(struct thread *td, struct fchownat_args *uap)
2884{
2885
2886 if ((uap->flag & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
2887 return (EINVAL22);
2888
2889 return (kern_fchownat(td, uap->fd, uap->path, UIO_USERSPACE, uap->uid,
2890 uap->gid, uap->flag));
2891}
2892
2893int
2894kern_fchownat(struct thread *td, int fd, const char *path,
2895 enum uio_seg pathseg, int uid, int gid, int flag)
2896{
2897 struct nameidata nd;
2898 int error, follow;
2899
2900 AUDIT_ARG_OWNER(uid, gid)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_owner((uid), (gid)); } while (0)
;
2901 follow = (flag & AT_SYMLINK_NOFOLLOW0x0200) ? NOFOLLOW0x0000 : FOLLOW0x0040;
2902 follow |= (flag & AT_BENEATH0x1000) != 0 ? BENEATH0x0080 : 0;
2903 NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchown_rights, td)
2904 &cap_fchown_rights, td)NDINIT_ALL(&nd, 0, follow | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_fchown_rights, td)
;
2905
2906 if ((error = namei(&nd)) != 0)
2907 return (error);
2908 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
2909 error = setfown(td, td->td_ucred, nd.ni_vp, uid, gid);
2910 vrele(nd.ni_vp);
2911 return (error);
2912}
2913
2914/*
2915 * Set ownership given a path name, do not cross symlinks.
2916 */
2917#ifndef _SYS_SYSPROTO_H_
2918struct lchown_args {
2919 char *path;
2920 int uid;
2921 int gid;
2922};
2923#endif
2924int
2925sys_lchown(struct thread *td, struct lchown_args *uap)
2926{
2927
2928 return (kern_fchownat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
2929 uap->uid, uap->gid, AT_SYMLINK_NOFOLLOW0x0200));
2930}
2931
2932/*
2933 * Set ownership given a file descriptor.
2934 */
2935#ifndef _SYS_SYSPROTO_H_
2936struct fchown_args {
2937 int fd;
2938 int uid;
2939 int gid;
2940};
2941#endif
2942int
2943sys_fchown(struct thread *td, struct fchown_args *uap)
2944{
2945 struct file *fp;
2946 int error;
2947
2948 AUDIT_ARG_FD(uap->fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((uap->fd)); } while (0)
;
2949 AUDIT_ARG_OWNER(uap->uid, uap->gid)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_owner((uap->uid), (uap->gid
)); } while (0)
;
2950 error = fget(td, uap->fd, &cap_fchown_rights, &fp);
2951 if (error != 0)
2952 return (error);
2953 error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td);
2954 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
2955 return (error);
2956}
2957
2958/*
2959 * Common implementation code for utimes(), lutimes(), and futimes().
2960 */
2961static int
2962getutimes(const struct timeval *usrtvp, enum uio_seg tvpseg,
2963 struct timespec *tsp)
2964{
2965 struct timeval tv[2];
2966 const struct timeval *tvp;
2967 int error;
2968
2969 if (usrtvp == NULL((void *)0)) {
2970 vfs_timestamp(&tsp[0]);
2971 tsp[1] = tsp[0];
2972 } else {
2973 if (tvpseg == UIO_SYSSPACE) {
2974 tvp = usrtvp;
2975 } else {
2976 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2977 return (error);
2978 tvp = tv;
2979 }
2980
2981 if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 ||
2982 tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
2983 return (EINVAL22);
2984 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0])do { (&tsp[0])->tv_sec = (&tvp[0])->tv_sec; (&
tsp[0])->tv_nsec = (&tvp[0])->tv_usec * 1000; } while
(0)
;
2985 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1])do { (&tsp[1])->tv_sec = (&tvp[1])->tv_sec; (&
tsp[1])->tv_nsec = (&tvp[1])->tv_usec * 1000; } while
(0)
;
2986 }
2987 return (0);
2988}
2989
2990/*
2991 * Common implementation code for futimens(), utimensat().
2992 */
2993#define UTIMENS_NULL0x1 0x1
2994#define UTIMENS_EXIT0x2 0x2
2995static int
2996getutimens(const struct timespec *usrtsp, enum uio_seg tspseg,
2997 struct timespec *tsp, int *retflags)
2998{
2999 struct timespec tsnow;
3000 int error;
3001
3002 vfs_timestamp(&tsnow);
3003 *retflags = 0;
3004 if (usrtsp == NULL((void *)0)) {
3005 tsp[0] = tsnow;
3006 tsp[1] = tsnow;
3007 *retflags |= UTIMENS_NULL0x1;
3008 return (0);
3009 }
3010 if (tspseg == UIO_SYSSPACE) {
3011 tsp[0] = usrtsp[0];
3012 tsp[1] = usrtsp[1];
3013 } else if ((error = copyin(usrtsp, tsp, sizeof(*tsp) * 2)) != 0)
3014 return (error);
3015 if (tsp[0].tv_nsec == UTIME_OMIT-2 && tsp[1].tv_nsec == UTIME_OMIT-2)
3016 *retflags |= UTIMENS_EXIT0x2;
3017 if (tsp[0].tv_nsec == UTIME_NOW-1 && tsp[1].tv_nsec == UTIME_NOW-1)
3018 *retflags |= UTIMENS_NULL0x1;
3019 if (tsp[0].tv_nsec == UTIME_OMIT-2)
3020 tsp[0].tv_sec = VNOVAL(-1);
3021 else if (tsp[0].tv_nsec == UTIME_NOW-1)
3022 tsp[0] = tsnow;
3023 else if (tsp[0].tv_nsec < 0 || tsp[0].tv_nsec >= 1000000000L)
3024 return (EINVAL22);
3025 if (tsp[1].tv_nsec == UTIME_OMIT-2)
3026 tsp[1].tv_sec = VNOVAL(-1);
3027 else if (tsp[1].tv_nsec == UTIME_NOW-1)
3028 tsp[1] = tsnow;
3029 else if (tsp[1].tv_nsec < 0 || tsp[1].tv_nsec >= 1000000000L)
3030 return (EINVAL22);
3031
3032 return (0);
3033}
3034
3035/*
3036 * Common implementation code for utimes(), lutimes(), futimes(), futimens(),
3037 * and utimensat().
3038 */
3039static int
3040setutimes(struct thread *td, struct vnode *vp, const struct timespec *ts,
3041 int numtimes, int nullflag)
3042{
3043 struct mount *mp;
3044 struct vattr vattr;
3045 int error, setbirthtime;
3046
3047 if ((error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100)) != 0)
3048 return (error);
3049 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)_vn_lock(vp, 0x080000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 3049)
;
3050 setbirthtime = 0;
3051 if (numtimes < 3 && !VOP_GETATTR(vp, &vattr, td->td_ucred) &&
3052 timespeccmp(&ts[1], &vattr.va_birthtime, < )(((&ts[1])->tv_sec == (&vattr.va_birthtime)->tv_sec
) ? ((&ts[1])->tv_nsec < (&vattr.va_birthtime)->
tv_nsec) : ((&ts[1])->tv_sec < (&vattr.va_birthtime
)->tv_sec))
)
3053 setbirthtime = 1;
3054 VATTR_NULL(&vattr)(*(&vattr) = va_null);
3055 vattr.va_atime = ts[0];
3056 vattr.va_mtime = ts[1];
3057 if (setbirthtime)
3058 vattr.va_birthtime = ts[1];
3059 if (numtimes > 2)
3060 vattr.va_birthtime = ts[2];
3061 if (nullflag)
3062 vattr.va_vaflags |= VA_UTIMES_NULL0x01;
3063#ifdef MAC1
3064 error = mac_vnode_check_setutimes(td->td_ucred, vp, vattr.va_atime,
3065 vattr.va_mtime);
3066#endif
3067 if (error == 0)
3068 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3069 VOP_UNLOCK(vp, 0);
3070 vn_finished_write(mp);
3071 return (error);
3072}
3073
3074/*
3075 * Set the access and modification times of a file.
3076 */
3077#ifndef _SYS_SYSPROTO_H_
3078struct utimes_args {
3079 char *path;
3080 struct timeval *tptr;
3081};
3082#endif
3083int
3084sys_utimes(struct thread *td, struct utimes_args *uap)
3085{
3086
3087 return (kern_utimesat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
3088 uap->tptr, UIO_USERSPACE));
3089}
3090
3091#ifndef _SYS_SYSPROTO_H_
3092struct futimesat_args {
3093 int fd;
3094 const char * path;
3095 const struct timeval * times;
3096};
3097#endif
3098int
3099sys_futimesat(struct thread *td, struct futimesat_args *uap)
3100{
3101
3102 return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
3103 uap->times, UIO_USERSPACE));
3104}
3105
3106int
3107kern_utimesat(struct thread *td, int fd, const char *path,
3108 enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg)
3109{
3110 struct nameidata nd;
3111 struct timespec ts[2];
3112 int error;
3113
3114 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
3115 return (error);
3116 NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,NDINIT_ALL(&nd, 0, 0x0040 | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_futimes_rights, td)
3117 &cap_futimes_rights, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x04000000, pathseg, path, fd
, ((void *)0), &cap_futimes_rights, td)
;
3118
3119 if ((error = namei(&nd)) != 0)
3120 return (error);
3121 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3122 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL((void *)0));
3123 vrele(nd.ni_vp);
3124 return (error);
3125}
3126
3127/*
3128 * Set the access and modification times of a file.
3129 */
3130#ifndef _SYS_SYSPROTO_H_
3131struct lutimes_args {
3132 char *path;
3133 struct timeval *tptr;
3134};
3135#endif
3136int
3137sys_lutimes(struct thread *td, struct lutimes_args *uap)
3138{
3139
3140 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
3141 UIO_USERSPACE));
3142}
3143
3144int
3145kern_lutimes(struct thread *td, const char *path, enum uio_seg pathseg,
3146 struct timeval *tptr, enum uio_seg tptrseg)
3147{
3148 struct timespec ts[2];
3149 struct nameidata nd;
3150 int error;
3151
3152 if ((error = getutimes(tptr, tptrseg, ts)) != 0)
3153 return (error);
3154 NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, pathseg, path, td)NDINIT_ALL(&nd, 0, 0x0000 | 0x04000000, pathseg, path, -100
, ((void *)0), 0, td)
;
3155 if ((error = namei(&nd)) != 0)
3156 return (error);
3157 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3158 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL((void *)0));
3159 vrele(nd.ni_vp);
3160 return (error);
3161}
3162
3163/*
3164 * Set the access and modification times of a file.
3165 */
3166#ifndef _SYS_SYSPROTO_H_
3167struct futimes_args {
3168 int fd;
3169 struct timeval *tptr;
3170};
3171#endif
3172int
3173sys_futimes(struct thread *td, struct futimes_args *uap)
3174{
3175
3176 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
3177}
3178
3179int
3180kern_futimes(struct thread *td, int fd, struct timeval *tptr,
3181 enum uio_seg tptrseg)
3182{
3183 struct timespec ts[2];
3184 struct file *fp;
3185 int error;
3186
3187 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
3188 error = getutimes(tptr, tptrseg, ts);
3189 if (error != 0)
3190 return (error);
3191 error = getvnode(td, fd, &cap_futimes_rights, &fp);
3192 if (error != 0)
3193 return (error);
3194#ifdef AUDIT1
3195 vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY)_vn_lock(fp->f_vnode, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 3195)
;
3196 AUDIT_ARG_VNODE1(fp->f_vnode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((fp->f_vnode)); } while
(0)
;
3197 VOP_UNLOCK(fp->f_vnode, 0);
3198#endif
3199 error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL((void *)0));
3200 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
3201 return (error);
3202}
3203
3204int
3205sys_futimens(struct thread *td, struct futimens_args *uap)
3206{
3207
3208 return (kern_futimens(td, uap->fd, uap->times, UIO_USERSPACE));
3209}
3210
3211int
3212kern_futimens(struct thread *td, int fd, struct timespec *tptr,
3213 enum uio_seg tptrseg)
3214{
3215 struct timespec ts[2];
3216 struct file *fp;
3217 int error, flags;
3218
3219 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
3220 error = getutimens(tptr, tptrseg, ts, &flags);
3221 if (error != 0)
3222 return (error);
3223 if (flags & UTIMENS_EXIT0x2)
3224 return (0);
3225 error = getvnode(td, fd, &cap_futimes_rights, &fp);
3226 if (error != 0)
3227 return (error);
3228#ifdef AUDIT1
3229 vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY)_vn_lock(fp->f_vnode, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 3229)
;
3230 AUDIT_ARG_VNODE1(fp->f_vnode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((fp->f_vnode)); } while
(0)
;
3231 VOP_UNLOCK(fp->f_vnode, 0);
3232#endif
3233 error = setutimes(td, fp->f_vnode, ts, 2, flags & UTIMENS_NULL0x1);
3234 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
3235 return (error);
3236}
3237
3238int
3239sys_utimensat(struct thread *td, struct utimensat_args *uap)
3240{
3241
3242 return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,
3243 uap->times, UIO_USERSPACE, uap->flag));
3244}
3245
3246int
3247kern_utimensat(struct thread *td, int fd, const char *path,
3248 enum uio_seg pathseg, struct timespec *tptr, enum uio_seg tptrseg,
3249 int flag)
3250{
3251 struct nameidata nd;
3252 struct timespec ts[2];
3253 int error, flags;
3254
3255 if ((flag & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
3256 return (EINVAL22);
3257
3258 if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0)
3259 return (error);
3260 NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :NDINIT_ALL(&nd, 0, ((flag & 0x0200) ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x04000000, pathseg
, path, fd, ((void *)0), &cap_futimes_rights, td)
3261 FOLLOW) | ((flag & AT_BENEATH) != 0 ? BENEATH : 0) | AUDITVNODE1,NDINIT_ALL(&nd, 0, ((flag & 0x0200) ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x04000000, pathseg
, path, fd, ((void *)0), &cap_futimes_rights, td)
3262 pathseg, path, fd, &cap_futimes_rights, td)NDINIT_ALL(&nd, 0, ((flag & 0x0200) ? 0x0000 : 0x0040
) | ((flag & 0x1000) != 0 ? 0x0080 : 0) | 0x04000000, pathseg
, path, fd, ((void *)0), &cap_futimes_rights, td)
;
3263 if ((error = namei(&nd)) != 0)
3264 return (error);
3265 /*
3266 * We are allowed to call namei() regardless of 2xUTIME_OMIT.
3267 * POSIX states:
3268 * "If both tv_nsec fields are UTIME_OMIT... EACCESS may be detected."
3269 * "Search permission is denied by a component of the path prefix."
3270 */
3271 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3272 if ((flags & UTIMENS_EXIT0x2) == 0)
3273 error = setutimes(td, nd.ni_vp, ts, 2, flags & UTIMENS_NULL0x1);
3274 vrele(nd.ni_vp);
3275 return (error);
3276}
3277
3278/*
3279 * Truncate a file given its path name.
3280 */
3281#ifndef _SYS_SYSPROTO_H_
3282struct truncate_args {
3283 char *path;
3284 int pad;
3285 off_t length;
3286};
3287#endif
3288int
3289sys_truncate(struct thread *td, struct truncate_args *uap)
3290{
3291
3292 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3293}
3294
3295int
3296kern_truncate(struct thread *td, const char *path, enum uio_seg pathseg,
3297 off_t length)
3298{
3299 struct mount *mp;
3300 struct vnode *vp;
3301 void *rl_cookie;
3302 struct vattr vattr;
3303 struct nameidata nd;
3304 int error;
3305
3306 if (length < 0)
3307 return(EINVAL22);
3308 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x04000000, pathseg, path, -100
, ((void *)0), 0, td)
;
3309 if ((error = namei(&nd)) != 0)
3310 return (error);
3311 vp = nd.ni_vp;
3312 rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX)rangelock_wlock(&(vp)->v_rl, (0), (0x7fffffffffffffff)
, (&(vp)->v_interlock))
;
3313 if ((error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100)) != 0) {
3314 vn_rangelock_unlock(vp, rl_cookie)rangelock_unlock(&(vp)->v_rl, (rl_cookie), (&(vp)->
v_interlock))
;
3315 vrele(vp);
3316 return (error);
3317 }
3318 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3319 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)_vn_lock(vp, 0x080000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 3319)
;
3320 if (vp->v_type == VDIR)
3321 error = EISDIR21;
3322#ifdef MAC1
3323 else if ((error = mac_vnode_check_write(td->td_ucred, NOCRED((struct ucred *)0), vp))) {
3324 }
3325#endif
3326 else if ((error = vn_writechk(vp)) == 0 &&
3327 (error = VOP_ACCESS(vp, VWRITE000000000200, td->td_ucred, td)) == 0) {
3328 VATTR_NULL(&vattr)(*(&vattr) = va_null);
3329 vattr.va_size = length;
3330 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3331 }
3332 VOP_UNLOCK(vp, 0);
3333 vn_finished_write(mp);
3334 vn_rangelock_unlock(vp, rl_cookie)rangelock_unlock(&(vp)->v_rl, (rl_cookie), (&(vp)->
v_interlock))
;
3335 vrele(vp);
3336 return (error);
3337}
3338
3339#if defined(COMPAT_43)
3340/*
3341 * Truncate a file given its path name.
3342 */
3343#ifndef _SYS_SYSPROTO_H_
3344struct otruncate_args {
3345 char *path;
3346 long length;
3347};
3348#endif
3349int
3350otruncate(struct thread *td, struct otruncate_args *uap)
3351{
3352
3353 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3354}
3355#endif /* COMPAT_43 */
3356
3357#if defined(COMPAT_FREEBSD61)
3358/* Versions with the pad argument */
3359int
3360freebsd6_truncate(struct thread *td, struct freebsd6_truncate_args *uap)
3361{
3362
3363 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3364}
3365
3366int
3367freebsd6_ftruncate(struct thread *td, struct freebsd6_ftruncate_args *uap)
3368{
3369
3370 return (kern_ftruncate(td, uap->fd, uap->length));
3371}
3372#endif
3373
3374int
3375kern_fsync(struct thread *td, int fd, bool fullsync)
3376{
3377 struct vnode *vp;
3378 struct mount *mp;
3379 struct file *fp;
3380 int error, lock_flags;
3381
3382 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
3383 error = getvnode(td, fd, &cap_fsync_rights, &fp);
3384 if (error != 0)
3385 return (error);
3386 vp = fp->f_vnode;
3387#if 0
3388 if (!fullsync)
3389 /* XXXKIB: compete outstanding aio writes */;
3390#endif
3391 error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100);
3392 if (error != 0)
3393 goto drop;
3394 if (MNT_SHARED_WRITES(mp) ||
3395 ((mp == NULL((void *)0)) && MNT_SHARED_WRITES(vp->v_mount))) {
3396 lock_flags = LK_SHARED0x200000;
3397 } else {
3398 lock_flags = LK_EXCLUSIVE0x080000;
3399 }
3400 vn_lock(vp, lock_flags | LK_RETRY)_vn_lock(vp, lock_flags | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 3400)
;
3401 AUDIT_ARG_VNODE1(vp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((vp)); } while (0)
;
3402 if (vp->v_objectv_bufobj.bo_object != NULL((void *)0)) {
3403 VM_OBJECT_WLOCK(vp->v_object)_rw_wlock_cookie(&((&(vp->v_bufobj.bo_object)->
lock))->rw_lock, "/root/freebsd/sys/kern/vfs_syscalls.c", 3403
)
;
3404 vm_object_page_clean(vp->v_objectv_bufobj.bo_object, 0, 0, 0);
3405 VM_OBJECT_WUNLOCK(vp->v_object)_rw_wunlock_cookie(&((&(vp->v_bufobj.bo_object)->
lock))->rw_lock, "/root/freebsd/sys/kern/vfs_syscalls.c", 3405
)
;
3406 }
3407 error = fullsync ? VOP_FSYNC(vp, MNT_WAIT1, td) : VOP_FDATASYNC(vp, td);
3408 VOP_UNLOCK(vp, 0);
3409 vn_finished_write(mp);
3410drop:
3411 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
3412 return (error);
3413}
3414
3415/*
3416 * Sync an open file.
3417 */
3418#ifndef _SYS_SYSPROTO_H_
3419struct fsync_args {
3420 int fd;
3421};
3422#endif
3423int
3424sys_fsync(struct thread *td, struct fsync_args *uap)
3425{
3426
3427 return (kern_fsync(td, uap->fd, true1));
3428}
3429
3430int
3431sys_fdatasync(struct thread *td, struct fdatasync_args *uap)
3432{
3433
3434 return (kern_fsync(td, uap->fd, false0));
3435}
3436
3437/*
3438 * Rename files. Source and destination must either both be directories, or
3439 * both not be directories. If target is a directory, it must be empty.
3440 */
3441#ifndef _SYS_SYSPROTO_H_
3442struct rename_args {
3443 char *from;
3444 char *to;
3445};
3446#endif
3447int
3448sys_rename(struct thread *td, struct rename_args *uap)
3449{
3450
3451 return (kern_renameat(td, AT_FDCWD-100, uap->from, AT_FDCWD-100,
3452 uap->to, UIO_USERSPACE));
3453}
3454
3455#ifndef _SYS_SYSPROTO_H_
3456struct renameat_args {
3457 int oldfd;
3458 char *old;
3459 int newfd;
3460 char *new;
3461};
3462#endif
3463int
3464sys_renameat(struct thread *td, struct renameat_args *uap)
3465{
3466
3467 return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new,
3468 UIO_USERSPACE));
3469}
3470
3471int
3472kern_renameat(struct thread *td, int oldfd, const char *old, int newfd,
3473 const char *new, enum uio_seg pathseg)
3474{
3475 struct mount *mp = NULL((void *)0);
3476 struct vnode *tvp, *fvp, *tdvp;
3477 struct nameidata fromnd, tond;
3478 int error;
3479
3480again:
3481 bwillwrite();
3482#ifdef MAC1
3483 NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |NDINIT_ALL(&fromnd, 2, 0x0008 | 0x0004 | 0x00001000 | 0x04000000
, pathseg, old, oldfd, ((void *)0), &cap_renameat_source_rights
, td)
3484 AUDITVNODE1, pathseg, old, oldfd,NDINIT_ALL(&fromnd, 2, 0x0008 | 0x0004 | 0x00001000 | 0x04000000
, pathseg, old, oldfd, ((void *)0), &cap_renameat_source_rights
, td)
3485 &cap_renameat_source_rights, td)NDINIT_ALL(&fromnd, 2, 0x0008 | 0x0004 | 0x00001000 | 0x04000000
, pathseg, old, oldfd, ((void *)0), &cap_renameat_source_rights
, td)
;
3486#else
3487 NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,NDINIT_ALL(&fromnd, 2, 0x0010 | 0x00001000 | 0x04000000, pathseg
, old, oldfd, ((void *)0), &cap_renameat_source_rights, td
)
3488 pathseg, old, oldfd,NDINIT_ALL(&fromnd, 2, 0x0010 | 0x00001000 | 0x04000000, pathseg
, old, oldfd, ((void *)0), &cap_renameat_source_rights, td
)
3489 &cap_renameat_source_rights, td)NDINIT_ALL(&fromnd, 2, 0x0010 | 0x00001000 | 0x04000000, pathseg
, old, oldfd, ((void *)0), &cap_renameat_source_rights, td
)
;
3490#endif
3491
3492 if ((error = namei(&fromnd)) != 0)
3493 return (error);
3494#ifdef MAC1
3495 error = mac_vnode_check_rename_from(td->td_ucred, fromnd.ni_dvp,
3496 fromnd.ni_vp, &fromnd.ni_cnd);
3497 VOP_UNLOCK(fromnd.ni_dvp, 0);
3498 if (fromnd.ni_dvp != fromnd.ni_vp)
3499 VOP_UNLOCK(fromnd.ni_vp, 0);
3500#endif
3501 fvp = fromnd.ni_vp;
3502 NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |NDINIT_ALL(&tond, 3, 0x0008 | 0x0004 | 0x0020 | 0x00001000
| 0x08000000, pathseg, new, newfd, ((void *)0), &cap_renameat_target_rights
, td)
3503 SAVESTART | AUDITVNODE2, pathseg, new, newfd,NDINIT_ALL(&tond, 3, 0x0008 | 0x0004 | 0x0020 | 0x00001000
| 0x08000000, pathseg, new, newfd, ((void *)0), &cap_renameat_target_rights
, td)
3504 &cap_renameat_target_rights, td)NDINIT_ALL(&tond, 3, 0x0008 | 0x0004 | 0x0020 | 0x00001000
| 0x08000000, pathseg, new, newfd, ((void *)0), &cap_renameat_target_rights
, td)
;
3505 if (fromnd.ni_vp->v_type == VDIR)
3506 tond.ni_cnd.cn_flags |= WILLBEDIR0x00080000;
3507 if ((error = namei(&tond)) != 0) {
3508 /* Translate error code for rename("dir1", "dir2/."). */
3509 if (error == EISDIR21 && fvp->v_type == VDIR)
3510 error = EINVAL22;
3511 NDFREE(&fromnd, NDF_ONLY_PNBUF(~0x00000020));
3512 vrele(fromnd.ni_dvp);
3513 vrele(fvp);
3514 goto out1;
3515 }
3516 tdvp = tond.ni_dvp;
3517 tvp = tond.ni_vp;
3518 error = vn_start_write(fvp, &mp, V_NOWAIT0x0002);
3519 if (error != 0) {
3520 NDFREE(&fromnd, NDF_ONLY_PNBUF(~0x00000020));
3521 NDFREE(&tond, NDF_ONLY_PNBUF(~0x00000020));
3522 if (tvp != NULL((void *)0))
3523 vput(tvp);
3524 if (tdvp == tvp)
3525 vrele(tdvp);
3526 else
3527 vput(tdvp);
3528 vrele(fromnd.ni_dvp);
3529 vrele(fvp);
3530 vrele(tond.ni_startdir);
3531 if (fromnd.ni_startdir != NULL((void *)0))
3532 vrele(fromnd.ni_startdir);
3533 error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100);
3534 if (error != 0)
3535 return (error);
3536 goto again;
3537 }
3538 if (tvp != NULL((void *)0)) {
3539 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3540 error = ENOTDIR20;
3541 goto out;
3542 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3543 error = EISDIR21;
3544 goto out;
3545 }
3546#ifdef CAPABILITIES1
3547 if (newfd != AT_FDCWD-100) {
3548 /*
3549 * If the target already exists we require CAP_UNLINKAT
3550 * from 'newfd'.
3551 */
3552 error = cap_check(&tond.ni_filecaps.fc_rights,
3553 &cap_unlinkat_rights);
3554 if (error != 0)
3555 goto out;
3556 }
3557#endif
3558 }
3559 if (fvp == tdvp) {
3560 error = EINVAL22;
3561 goto out;
3562 }
3563 /*
3564 * If the source is the same as the destination (that is, if they
3565 * are links to the same vnode), then there is nothing to do.
3566 */
3567 if (fvp == tvp)
3568 error = -1;
3569#ifdef MAC1
3570 else
3571 error = mac_vnode_check_rename_to(td->td_ucred, tdvp,
3572 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3573#endif
3574out:
3575 if (error == 0) {
3576 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3577 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3578 NDFREE(&fromnd, NDF_ONLY_PNBUF(~0x00000020));
3579 NDFREE(&tond, NDF_ONLY_PNBUF(~0x00000020));
3580 } else {
3581 NDFREE(&fromnd, NDF_ONLY_PNBUF(~0x00000020));
3582 NDFREE(&tond, NDF_ONLY_PNBUF(~0x00000020));
3583 if (tvp != NULL((void *)0))
3584 vput(tvp);
3585 if (tdvp == tvp)
3586 vrele(tdvp);
3587 else
3588 vput(tdvp);
3589 vrele(fromnd.ni_dvp);
3590 vrele(fvp);
3591 }
3592 vrele(tond.ni_startdir);
3593 vn_finished_write(mp);
3594out1:
3595 if (fromnd.ni_startdir)
3596 vrele(fromnd.ni_startdir);
3597 if (error == -1)
3598 return (0);
3599 return (error);
3600}
3601
3602/*
3603 * Make a directory file.
3604 */
3605#ifndef _SYS_SYSPROTO_H_
3606struct mkdir_args {
3607 char *path;
3608 int mode;
3609};
3610#endif
3611int
3612sys_mkdir(struct thread *td, struct mkdir_args *uap)
3613{
3614
3615 return (kern_mkdirat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE,
3616 uap->mode));
3617}
3618
3619#ifndef _SYS_SYSPROTO_H_
3620struct mkdirat_args {
3621 int fd;
3622 char *path;
3623 mode_t mode;
3624};
3625#endif
3626int
3627sys_mkdirat(struct thread *td, struct mkdirat_args *uap)
3628{
3629
3630 return (kern_mkdirat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode));
3631}
3632
3633int
3634kern_mkdirat(struct thread *td, int fd, const char *path, enum uio_seg segflg,
3635 int mode)
3636{
3637 struct mount *mp;
3638 struct vnode *vp;
3639 struct vattr vattr;
3640 struct nameidata nd;
3641 int error;
3642
3643 AUDIT_ARG_MODE(mode)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_mode((mode)); } while (0)
;
3644restart:
3645 bwillwrite();
3646 NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path, fd, ((void *)0), &cap_mkdirat_rights, td)
3647 NOCACHE, segflg, path, fd, &cap_mkdirat_rights,NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path, fd, ((void *)0), &cap_mkdirat_rights, td)
3648 td)NDINIT_ALL(&nd, 1, 0x0008 | 0x00000800 | 0x04000000 | 0x0020
, segflg, path, fd, ((void *)0), &cap_mkdirat_rights, td)
;
3649 nd.ni_cnd.cn_flags |= WILLBEDIR0x00080000;
3650 if ((error = namei(&nd)) != 0)
3651 return (error);
3652 vp = nd.ni_vp;
3653 if (vp != NULL((void *)0)) {
3654 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3655 /*
3656 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3657 * the strange behaviour of leaving the vnode unlocked
3658 * if the target is the same vnode as the parent.
3659 */
3660 if (vp == nd.ni_dvp)
3661 vrele(nd.ni_dvp);
3662 else
3663 vput(nd.ni_dvp);
3664 vrele(vp);
3665 return (EEXIST17);
3666 }
3667 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
3668 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3669 vput(nd.ni_dvp);
3670 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
3671 return (error);
3672 goto restart;
3673 }
3674 VATTR_NULL(&vattr)(*(&vattr) = va_null);
3675 vattr.va_type = VDIR;
3676 vattr.va_mode = (mode & ACCESSPERMS(0000700|0000070|0000007)) &~ td->td_proc->p_fd->fd_cmask;
3677#ifdef MAC1
3678 error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3679 &vattr);
3680 if (error != 0)
3681 goto out;
3682#endif
3683 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3684#ifdef MAC1
3685out:
3686#endif
3687 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3688 vput(nd.ni_dvp);
3689 if (error == 0)
3690 vput(nd.ni_vp);
3691 vn_finished_write(mp);
3692 return (error);
3693}
3694
3695/*
3696 * Remove a directory file.
3697 */
3698#ifndef _SYS_SYSPROTO_H_
3699struct rmdir_args {
3700 char *path;
3701};
3702#endif
3703int
3704sys_rmdir(struct thread *td, struct rmdir_args *uap)
3705{
3706
3707 return (kern_rmdirat(td, AT_FDCWD-100, uap->path, UIO_USERSPACE, 0));
3708}
3709
3710int
3711kern_rmdirat(struct thread *td, int fd, const char *path, enum uio_seg pathseg,
3712 int flag)
3713{
3714 struct mount *mp;
3715 struct vnode *vp;
3716 struct nameidata nd;
3717 int error;
3718
3719restart:
3720 bwillwrite();
3721 NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
3722 ((flag & AT_BENEATH) != 0 ? BENEATH : 0),NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
3723 pathseg, path, fd, &cap_unlinkat_rights, td)NDINIT_ALL(&nd, 2, 0x0008 | 0x0004 | 0x04000000 | ((flag &
0x1000) != 0 ? 0x0080 : 0), pathseg, path, fd, ((void *)0), &
cap_unlinkat_rights, td)
;
3724 if ((error = namei(&nd)) != 0)
3725 return (error);
3726 vp = nd.ni_vp;
3727 if (vp->v_type != VDIR) {
3728 error = ENOTDIR20;
3729 goto out;
3730 }
3731 /*
3732 * No rmdir "." please.
3733 */
3734 if (nd.ni_dvp == vp) {
3735 error = EINVAL22;
3736 goto out;
3737 }
3738 /*
3739 * The root of a mounted filesystem cannot be deleted.
3740 */
3741 if (vp->v_vflag & VV_ROOT0x0001) {
3742 error = EBUSY16;
3743 goto out;
3744 }
3745#ifdef MAC1
3746 error = mac_vnode_check_unlink(td->td_ucred, nd.ni_dvp, vp,
3747 &nd.ni_cnd);
3748 if (error != 0)
3749 goto out;
3750#endif
3751 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT0x0002) != 0) {
3752 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3753 vput(vp);
3754 if (nd.ni_dvp == vp)
3755 vrele(nd.ni_dvp);
3756 else
3757 vput(nd.ni_dvp);
3758 if ((error = vn_start_write(NULL((void *)0), &mp, V_XSLEEP0x0004 | PCATCH0x100)) != 0)
3759 return (error);
3760 goto restart;
3761 }
3762 vfs_notify_upper(vp, VFS_NOTIFY_UPPER_UNLINK2);
3763 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3764 vn_finished_write(mp);
3765out:
3766 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
3767 vput(vp);
3768 if (nd.ni_dvp == vp)
3769 vrele(nd.ni_dvp);
3770 else
3771 vput(nd.ni_dvp);
3772 return (error);
3773}
3774
3775#if defined(COMPAT_43) || defined(COMPAT_FREEBSD111)
3776int
3777freebsd11_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count,
3778 long *basep, void (*func)(struct freebsd11_dirent *))
3779{
3780 struct freebsd11_dirent dstdp;
3781 struct dirent *dp, *edp;
3782 char *dirbuf;
3783 off_t base;
3784 ssize_t resid, ucount;
3785 int error;
3786
3787 /* XXX arbitrary sanity limit on `count'. */
3788 count = min(count, 64 * 1024);
3789
3790 dirbuf = malloc(count, M_TEMP, M_WAITOK0x0002);
3791
3792 error = kern_getdirentries(td, fd, dirbuf, count, &base, &resid,
3793 UIO_SYSSPACE);
3794 if (error != 0)
3795 goto done;
3796 if (basep != NULL((void *)0))
3797 *basep = base;
3798
3799 ucount = 0;
3800 for (dp = (struct dirent *)dirbuf,
3801 edp = (struct dirent *)&dirbuf[count - resid];
3802 ucount < count && dp < edp; ) {
3803 if (dp->d_reclen == 0)
3804 break;
3805 MPASS(dp->d_reclen >= _GENERIC_DIRLEN(0))do { if (__builtin_expect((!((dp->d_reclen >= ((__builtin_offsetof
(struct dirent, d_name) + (0) + 1 + 7) & ~7)))), 0)) panic
("Assertion %s failed at %s:%d", "dp->d_reclen >= _GENERIC_DIRLEN(0)"
, "/root/freebsd/sys/kern/vfs_syscalls.c", 3805); } while (0)
;
3806 if (dp->d_namlen >= sizeof(dstdp.d_name))
3807 continue;
3808 dstdp.d_type = dp->d_type;
3809 dstdp.d_namlen = dp->d_namlen;
3810 dstdp.d_fileno = dp->d_fileno; /* truncate */
3811 if (dstdp.d_fileno != dp->d_fileno) {
3812 switch (ino64_trunc_error) {
3813 default:
3814 case 0:
3815 break;
3816 case 1:
3817 error = EOVERFLOW84;
3818 goto done;
3819 case 2:
3820 dstdp.d_fileno = UINT32_MAX0xffffffffU;
3821 break;
3822 }
3823 }
3824 dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) +
3825 ((dp->d_namlen + 1 + 3) &~ 3);
3826 bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen)__builtin_memmove((dstdp.d_name), (dp->d_name), (dstdp.d_namlen
))
;
3827 bzero(dstdp.d_name + dstdp.d_namlen,__builtin_memset((dstdp.d_name + dstdp.d_namlen), 0, (dstdp.d_reclen
- __builtin_offsetof(struct freebsd11_dirent, d_name) - dstdp
.d_namlen))
3828 dstdp.d_reclen - offsetof(struct freebsd11_dirent, d_name) -__builtin_memset((dstdp.d_name + dstdp.d_namlen), 0, (dstdp.d_reclen
- __builtin_offsetof(struct freebsd11_dirent, d_name) - dstdp
.d_namlen))
3829 dstdp.d_namlen)__builtin_memset((dstdp.d_name + dstdp.d_namlen), 0, (dstdp.d_reclen
- __builtin_offsetof(struct freebsd11_dirent, d_name) - dstdp
.d_namlen))
;
3830 MPASS(dstdp.d_reclen <= dp->d_reclen)do { if (__builtin_expect((!((dstdp.d_reclen <= dp->d_reclen
))), 0)) panic ("Assertion %s failed at %s:%d", "dstdp.d_reclen <= dp->d_reclen"
, "/root/freebsd/sys/kern/vfs_syscalls.c", 3830); } while (0)
;
3831 MPASS(ucount + dstdp.d_reclen <= count)do { if (__builtin_expect((!((ucount + dstdp.d_reclen <= count
))), 0)) panic ("Assertion %s failed at %s:%d", "ucount + dstdp.d_reclen <= count"
, "/root/freebsd/sys/kern/vfs_syscalls.c", 3831); } while (0)
;
3832 if (func != NULL((void *)0))
3833 func(&dstdp);
3834 error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen);
3835 if (error != 0)
3836 break;
3837 dp = (struct dirent *)((char *)dp + dp->d_reclen);
3838 ucount += dstdp.d_reclen;
3839 }
3840
3841done:
3842 free(dirbuf, M_TEMP);
3843 if (error == 0)
3844 td->td_retvaltd_uretoff.tdu_retval[0] = ucount;
3845 return (error);
3846}
3847#endif /* COMPAT */
3848
3849#ifdef COMPAT_43
3850static void
3851ogetdirentries_cvt(struct freebsd11_dirent *dp)
3852{
3853#if (BYTE_ORDER1234 == LITTLE_ENDIAN1234)
3854 /*
3855 * The expected low byte of dp->d_namlen is our dp->d_type.
3856 * The high MBZ byte of dp->d_namlen is our dp->d_namlen.
3857 */
3858 dp->d_type = dp->d_namlen;
3859 dp->d_namlen = 0;
3860#else
3861 /*
3862 * The dp->d_type is the high byte of the expected dp->d_namlen,
3863 * so must be zero'ed.
3864 */
3865 dp->d_type = 0;
3866#endif
3867}
3868
3869/*
3870 * Read a block of directory entries in a filesystem independent format.
3871 */
3872#ifndef _SYS_SYSPROTO_H_
3873struct ogetdirentries_args {
3874 int fd;
3875 char *buf;
3876 u_int count;
3877 long *basep;
3878};
3879#endif
3880int
3881ogetdirentries(struct thread *td, struct ogetdirentries_args *uap)
3882{
3883 long loff;
3884 int error;
3885
3886 error = kern_ogetdirentries(td, uap, &loff);
3887 if (error == 0)
3888 error = copyout(&loff, uap->basep, sizeof(long));
3889 return (error);
3890}
3891
3892int
3893kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
3894 long *ploff)
3895{
3896 long base;
3897 int error;
3898
3899 /* XXX arbitrary sanity limit on `count'. */
3900 if (uap->count > 64 * 1024)
3901 return (EINVAL22);
3902
3903 error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
3904 &base, ogetdirentries_cvt);
3905
3906 if (error == 0 && uap->basep != NULL((void *)0))
3907 error = copyout(&base, uap->basep, sizeof(long));
3908
3909 return (error);
3910}
3911#endif /* COMPAT_43 */
3912
3913#if defined(COMPAT_FREEBSD111)
3914#ifndef _SYS_SYSPROTO_H_
3915struct freebsd11_getdirentries_args {
3916 int fd;
3917 char *buf;
3918 u_int count;
3919 long *basep;
3920};
3921#endif
3922int
3923freebsd11_getdirentries(struct thread *td,
3924 struct freebsd11_getdirentries_args *uap)
3925{
3926 long base;
3927 int error;
3928
3929 error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
3930 &base, NULL((void *)0));
3931
3932 if (error == 0 && uap->basep != NULL((void *)0))
3933 error = copyout(&base, uap->basep, sizeof(long));
3934 return (error);
3935}
3936
3937int
3938freebsd11_getdents(struct thread *td, struct freebsd11_getdents_args *uap)
3939{
3940 struct freebsd11_getdirentries_args ap;
3941
3942 ap.fd = uap->fd;
3943 ap.buf = uap->buf;
3944 ap.count = uap->count;
3945 ap.basep = NULL((void *)0);
3946 return (freebsd11_getdirentries(td, &ap));
3947}
3948#endif /* COMPAT_FREEBSD11 */
3949
3950/*
3951 * Read a block of directory entries in a filesystem independent format.
3952 */
3953int
3954sys_getdirentries(struct thread *td, struct getdirentries_args *uap)
3955{
3956 off_t base;
3957 int error;
3958
3959 error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base,
3960 NULL((void *)0), UIO_USERSPACE);
3961 if (error != 0)
3962 return (error);
3963 if (uap->basep != NULL((void *)0))
3964 error = copyout(&base, uap->basep, sizeof(off_t));
3965 return (error);
3966}
3967
3968int
3969kern_getdirentries(struct thread *td, int fd, char *buf, size_t count,
3970 off_t *basep, ssize_t *residp, enum uio_seg bufseg)
3971{
3972 struct vnode *vp;
3973 struct file *fp;
3974 struct uio auio;
3975 struct iovec aiov;
3976 off_t loff;
3977 int error, eofflag;
3978 off_t foffset;
3979
3980 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
3981 if (count > IOSIZE_MAXiosize_max())
3982 return (EINVAL22);
3983 auio.uio_resid = count;
3984 error = getvnode(td, fd, &cap_read_rights, &fp);
3985 if (error != 0)
3986 return (error);
3987 if ((fp->f_flag & FREAD0x0001) == 0) {
3988 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
3989 return (EBADF9);
3990 }
3991 vp = fp->f_vnode;
3992 foffset = foffset_lock(fp, 0);
3993unionread:
3994 if (vp->v_type != VDIR) {
3995 error = EINVAL22;
3996 goto fail;
3997 }
3998 aiov.iov_base = buf;
3999 aiov.iov_len = count;
4000 auio.uio_iov = &aiov;
4001 auio.uio_iovcnt = 1;
4002 auio.uio_rw = UIO_READ;
4003 auio.uio_segflg = bufseg;
4004 auio.uio_td = td;
4005 vn_lock(vp, LK_SHARED | LK_RETRY)_vn_lock(vp, 0x200000 | 0x000400, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 4005)
;
4006 AUDIT_ARG_VNODE1(vp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((vp)); } while (0)
;
4007 loff = auio.uio_offset = foffset;
4008#ifdef MAC1
4009 error = mac_vnode_check_readdir(td->td_ucred, vp);
4010 if (error == 0)
4011#endif
4012 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL((void *)0),
4013 NULL((void *)0));
4014 foffset = auio.uio_offset;
4015 if (error != 0) {
4016 VOP_UNLOCK(vp, 0);
4017 goto fail;
4018 }
4019 if (count == auio.uio_resid &&
4020 (vp->v_vflag & VV_ROOT0x0001) &&
4021 (vp->v_mount->mnt_flag & MNT_UNION0x0000000000000020ULL)) {
4022 struct vnode *tvp = vp;
4023
4024 vp = vp->v_mount->mnt_vnodecovered;
4025 VREF(vp)vref(vp);
4026 fp->f_vnode = vp;
4027 fp->f_data = vp;
4028 foffset = 0;
4029 vput(tvp);
4030 goto unionread;
4031 }
4032 VOP_UNLOCK(vp, 0);
4033 *basep = loff;
4034 if (residp != NULL((void *)0))
4035 *residp = auio.uio_resid;
4036 td->td_retvaltd_uretoff.tdu_retval[0] = count - auio.uio_resid;
4037fail:
4038 foffset_unlock(fp, foffset, 0);
4039 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
4040 return (error);
4041}
4042
4043/*
4044 * Set the mode mask for creation of filesystem nodes.
4045 */
4046#ifndef _SYS_SYSPROTO_H_
4047struct umask_args {
4048 int newmask;
4049};
4050#endif
4051int
4052sys_umask(struct thread *td, struct umask_args *uap)
4053{
4054 struct filedesc *fdp;
4055
4056 fdp = td->td_proc->p_fd;
4057 FILEDESC_XLOCK(fdp)(void)_sx_xlock(((&(fdp)->fd_sx)), 0, ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4057))
;
4058 td->td_retvaltd_uretoff.tdu_retval[0] = fdp->fd_cmask;
4059 fdp->fd_cmask = uap->newmask & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007);
4060 FILEDESC_XUNLOCK(fdp)_sx_xunlock(((&(fdp)->fd_sx)), ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4060))
;
4061 return (0);
4062}
4063
4064/*
4065 * Void all references to file by ripping underlying filesystem away from
4066 * vnode.
4067 */
4068#ifndef _SYS_SYSPROTO_H_
4069struct revoke_args {
4070 char *path;
4071};
4072#endif
4073int
4074sys_revoke(struct thread *td, struct revoke_args *uap)
4075{
4076 struct vnode *vp;
4077 struct vattr vattr;
4078 struct nameidata nd;
4079 int error;
4080
4081 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,NDINIT_ALL(&nd, 0, 0x0040 | 0x0004 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
4082 uap->path, td)NDINIT_ALL(&nd, 0, 0x0040 | 0x0004 | 0x04000000, UIO_USERSPACE
, uap->path, -100, ((void *)0), 0, td)
;
4083 if ((error = namei(&nd)) != 0)
4084 return (error);
4085 vp = nd.ni_vp;
4086 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
4087 if (vp->v_type != VCHR || vp->v_rdev == NULL((void *)0)) {
4088 error = EINVAL22;
4089 goto out;
4090 }
4091#ifdef MAC1
4092 error = mac_vnode_check_revoke(td->td_ucred, vp);
4093 if (error != 0)
4094 goto out;
4095#endif
4096 error = VOP_GETATTR(vp, &vattr, td->td_ucred);
4097 if (error != 0)
4098 goto out;
4099 if (td->td_ucred->cr_uid != vattr.va_uid) {
4100 error = priv_check(td, PRIV_VFS_ADMIN312);
4101 if (error != 0)
4102 goto out;
4103 }
4104 if (vcount(vp) > 1)
4105 VOP_REVOKE(vp, REVOKEALL0x0001);
4106out:
4107 vput(vp);
4108 return (error);
4109}
4110
4111/*
4112 * Convert a user file descriptor to a kernel file entry and check that, if it
4113 * is a capability, the correct rights are present. A reference on the file
4114 * entry is held upon returning.
4115 */
4116int
4117getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
4118{
4119 struct file *fp;
4120 int error;
4121
4122 error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL((void *)0));
4123 if (error != 0)
4124 return (error);
4125
4126 /*
4127 * The file could be not of the vnode type, or it may be not
4128 * yet fully initialized, in which case the f_vnode pointer
4129 * may be set, but f_ops is still badfileops. E.g.,
4130 * devfs_open() transiently create such situation to
4131 * facilitate csw d_fdopen().
4132 *
4133 * Dupfdopen() handling in kern_openat() installs the
4134 * half-baked file into the process descriptor table, allowing
4135 * other thread to dereference it. Guard against the race by
4136 * checking f_ops.
4137 */
4138 if (fp->f_vnode == NULL((void *)0) || fp->f_ops == &badfileops) {
4139 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
4140 return (EINVAL22);
4141 }
4142 *fpp = fp;
4143 return (0);
4144}
4145
4146
4147/*
4148 * Get an (NFS) file handle.
4149 */
4150#ifndef _SYS_SYSPROTO_H_
4151struct lgetfh_args {
4152 char *fname;
4153 fhandle_t *fhp;
4154};
4155#endif
4156int
4157sys_lgetfh(struct thread *td, struct lgetfh_args *uap)
4158{
4159
4160 return (kern_getfhat(td, AT_SYMLINK_NOFOLLOW0x0200, AT_FDCWD-100, uap->fname,
4161 UIO_USERSPACE, uap->fhp));
4162}
4163
4164#ifndef _SYS_SYSPROTO_H_
4165struct getfh_args {
4166 char *fname;
4167 fhandle_t *fhp;
4168};
4169#endif
4170int
4171sys_getfh(struct thread *td, struct getfh_args *uap)
4172{
4173
4174 return (kern_getfhat(td, 0, AT_FDCWD-100, uap->fname, UIO_USERSPACE,
4175 uap->fhp));
4176}
4177
4178/*
4179 * syscall for the rpc.lockd to use to translate an open descriptor into
4180 * a NFS file handle.
4181 *
4182 * warning: do not remove the priv_check() call or this becomes one giant
4183 * security hole.
4184 */
4185#ifndef _SYS_SYSPROTO_H_
4186struct getfhat_args {
4187 int fd;
4188 char *path;
4189 fhandle_t *fhp;
4190 int flags;
4191};
4192#endif
4193int
4194sys_getfhat(struct thread *td, struct getfhat_args *uap)
4195{
4196
4197 if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW0x0200 | AT_BENEATH0x1000)) != 0)
4198 return (EINVAL22);
4199 return (kern_getfhat(td, uap->flags, uap->fd, uap->path, UIO_USERSPACE,
4200 uap->fhp));
4201}
4202
4203static int
4204kern_getfhat(struct thread *td, int flags, int fd, const char *path,
4205 enum uio_seg pathseg, fhandle_t *fhp)
4206{
4207 struct nameidata nd;
4208 fhandle_t fh;
4209 struct vnode *vp;
4210 int error;
4211
4212 error = priv_check(td, PRIV_VFS_GETFH327);
4213 if (error != 0)
4214 return (error);
4215 NDINIT_AT(&nd, LOOKUP, ((flags & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW :NDINIT_ALL(&nd, 0, ((flags & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flags & 0x1000) != 0 ? 0x0080 : 0) | 0x0004 | 0x04000000
, pathseg, path, fd, ((void *)0), 0, td)
4216 FOLLOW) | ((flags & AT_BENEATH) != 0 ? BENEATH : 0) | LOCKLEAF |NDINIT_ALL(&nd, 0, ((flags & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flags & 0x1000) != 0 ? 0x0080 : 0) | 0x0004 | 0x04000000
, pathseg, path, fd, ((void *)0), 0, td)
4217 AUDITVNODE1, pathseg, path, fd, td)NDINIT_ALL(&nd, 0, ((flags & 0x0200) != 0 ? 0x0000 : 0x0040
) | ((flags & 0x1000) != 0 ? 0x0080 : 0) | 0x0004 | 0x04000000
, pathseg, path, fd, ((void *)0), 0, td)
;
4218 error = namei(&nd);
4219 if (error != 0)
4220 return (error);
4221 NDFREE(&nd, NDF_ONLY_PNBUF(~0x00000020));
4222 vp = nd.ni_vp;
4223 bzero(&fh, sizeof(fh))__builtin_memset((&fh), 0, (sizeof(fh)));
4224 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
4225 error = VOP_VPTOFH(vp, &fh.fh_fid);
4226 vput(vp);
4227 if (error == 0)
4228 error = copyout(&fh, fhp, sizeof (fh));
4229 return (error);
4230}
4231
4232#ifndef _SYS_SYSPROTO_H_
4233struct fhlink_args {
4234 fhandle_t *fhp;
4235 const char *to;
4236};
4237#endif
4238int
4239sys_fhlink(struct thread *td, struct fhlink_args *uap)
4240{
4241
4242 return (kern_fhlinkat(td, AT_FDCWD-100, uap->to, UIO_USERSPACE, uap->fhp));
4243}
4244
4245#ifndef _SYS_SYSPROTO_H_
4246struct fhlinkat_args {
4247 fhandle_t *fhp;
4248 int tofd;
4249 const char *to;
4250};
4251#endif
4252int
4253sys_fhlinkat(struct thread *td, struct fhlinkat_args *uap)
4254{
4255
4256 return (kern_fhlinkat(td, uap->tofd, uap->to, UIO_USERSPACE, uap->fhp));
4257}
4258
4259static int
4260kern_fhlinkat(struct thread *td, int fd, const char *path,
4261 enum uio_seg pathseg, fhandle_t *fhp)
4262{
4263 fhandle_t fh;
4264 struct mount *mp;
4265 struct vnode *vp;
4266 int error;
4267
4268 error = priv_check(td, PRIV_VFS_GETFH327);
4269 if (error != 0)
4270 return (error);
4271 error = copyin(fhp, &fh, sizeof(fh));
4272 if (error != 0)
4273 return (error);
4274 do {
4275 bwillwrite();
4276 if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL((void *)0))
4277 return (ESTALE70);
4278 error = VFS_FHTOVP(mp, &fh.fh_fid, LK_SHARED, &vp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_fhtovp)(mp, &
fh.fh_fid, 0x200000, &vp); _rc; })
;
4279 vfs_unbusy(mp);
4280 if (error != 0)
4281 return (error);
4282 VOP_UNLOCK(vp, 0);
4283 } while ((error = kern_linkat_vp(td, vp, fd, path, pathseg)) == EAGAIN35);
4284 return (error);
4285}
4286
4287#ifndef _SYS_SYSPROTO_H_
4288struct fhreadlink_args {
4289 fhandle_t *fhp;
4290 char *buf;
4291 size_t bufsize;
4292};
4293#endif
4294int
4295sys_fhreadlink(struct thread *td, struct fhreadlink_args *uap)
4296{
4297 fhandle_t fh;
4298 struct mount *mp;
4299 struct vnode *vp;
4300 int error;
4301
4302 error = priv_check(td, PRIV_VFS_GETFH327);
4303 if (error != 0)
4304 return (error);
4305 if (uap->bufsize > IOSIZE_MAXiosize_max())
4306 return (EINVAL22);
4307 error = copyin(uap->fhp, &fh, sizeof(fh));
4308 if (error != 0)
4309 return (error);
4310 if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL((void *)0))
4311 return (ESTALE70);
4312 error = VFS_FHTOVP(mp, &fh.fh_fid, LK_SHARED, &vp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_fhtovp)(mp, &
fh.fh_fid, 0x200000, &vp); _rc; })
;
4313 vfs_unbusy(mp);
4314 if (error != 0)
4315 return (error);
4316 error = kern_readlink_vp(vp, uap->buf, UIO_USERSPACE, uap->bufsize, td);
4317 vput(vp);
4318 return (error);
4319}
4320
4321/*
4322 * syscall for the rpc.lockd to use to translate a NFS file handle into an
4323 * open descriptor.
4324 *
4325 * warning: do not remove the priv_check() call or this becomes one giant
4326 * security hole.
4327 */
4328#ifndef _SYS_SYSPROTO_H_
4329struct fhopen_args {
4330 const struct fhandle *u_fhp;
4331 int flags;
4332};
4333#endif
4334int
4335sys_fhopen(struct thread *td, struct fhopen_args *uap)
4336{
4337 struct mount *mp;
4338 struct vnode *vp;
4339 struct fhandle fhp;
4340 struct file *fp;
4341 int fmode, error;
4342 int indx;
4343
4344 error = priv_check(td, PRIV_VFS_FHOPEN323);
4345 if (error != 0)
4346 return (error);
4347 indx = -1;
4348 fmode = FFLAGS(uap->flags)((uap->flags) & 0x00040000 ? (uap->flags) : (uap->
flags) + 1)
;
4349 /* why not allow a non-read/write open for our lockd? */
4350 if (((fmode & (FREAD0x0001 | FWRITE0x0002)) == 0) || (fmode & O_CREAT0x0200))
4351 return (EINVAL22);
4352 error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4353 if (error != 0)
4354 return(error);
4355 /* find the mount point */
4356 mp = vfs_busyfs(&fhp.fh_fsid);
4357 if (mp == NULL((void *)0))
4358 return (ESTALE70);
4359 /* now give me my vnode, it gets returned to me locked */
4360 error = VFS_FHTOVP(mp, &fhp.fh_fid, LK_EXCLUSIVE, &vp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_fhtovp)(mp, &
fhp.fh_fid, 0x080000, &vp); _rc; })
;
4361 vfs_unbusy(mp);
4362 if (error != 0)
4363 return (error);
4364
4365 error = falloc_noinstall(td, &fp);
4366 if (error != 0) {
4367 vput(vp);
4368 return (error);
4369 }
4370 /*
4371 * An extra reference on `fp' has been held for us by
4372 * falloc_noinstall().
4373 */
4374
4375#ifdef INVARIANTS1
4376 td->td_dupfd = -1;
4377#endif
4378 error = vn_open_vnode(vp, fmode, td->td_ucred, td, fp);
4379 if (error != 0) {
4380 KASSERT(fp->f_ops == &badfileops,do { if (__builtin_expect((!(fp->f_ops == &badfileops)
), 0)) panic ("VOP_OPEN in fhopen() set f_ops"); } while (0)
4381 ("VOP_OPEN in fhopen() set f_ops"))do { if (__builtin_expect((!(fp->f_ops == &badfileops)
), 0)) panic ("VOP_OPEN in fhopen() set f_ops"); } while (0)
;
4382 KASSERT(td->td_dupfd < 0,do { if (__builtin_expect((!(td->td_dupfd < 0)), 0)) panic
("fhopen() encountered fdopen()"); } while (0)
4383 ("fhopen() encountered fdopen()"))do { if (__builtin_expect((!(td->td_dupfd < 0)), 0)) panic
("fhopen() encountered fdopen()"); } while (0)
;
4384
4385 vput(vp);
4386 goto bad;
4387 }
4388#ifdef INVARIANTS1
4389 td->td_dupfd = 0;
4390#endif
4391 fp->f_vnode = vp;
4392 fp->f_seqcount = 1;
4393 finit(fp, (fmode & FMASK(0x0001|0x0002|0x0008|0x0040|0x0080|0x0004|0x00010000|0x00040000
)
) | (fp->f_flag & FHASLOCK0x4000), DTYPE_VNODE1, vp,
4394 &vnops);
4395 VOP_UNLOCK(vp, 0);
4396 if ((fmode & O_TRUNC0x0400) != 0) {
4397 error = fo_truncate(fp, 0, td->td_ucred, td);
4398 if (error != 0)
4399 goto bad;
4400 }
4401
4402 error = finstall(td, fp, &indx, fmode, NULL((void *)0));
4403bad:
4404 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
4405 td->td_retvaltd_uretoff.tdu_retval[0] = indx;
4406 return (error);
4407}
4408
4409/*
4410 * Stat an (NFS) file handle.
4411 */
4412#ifndef _SYS_SYSPROTO_H_
4413struct fhstat_args {
4414 struct fhandle *u_fhp;
4415 struct stat *sb;
4416};
4417#endif
4418int
4419sys_fhstat(struct thread *td, struct fhstat_args *uap)
4420{
4421 struct stat sb;
4422 struct fhandle fh;
4423 int error;
4424
4425 error = copyin(uap->u_fhp, &fh, sizeof(fh));
4426 if (error != 0)
4427 return (error);
4428 error = kern_fhstat(td, fh, &sb);
4429 if (error == 0)
4430 error = copyout(&sb, uap->sb, sizeof(sb));
4431 return (error);
4432}
4433
4434int
4435kern_fhstat(struct thread *td, struct fhandle fh, struct stat *sb)
4436{
4437 struct mount *mp;
4438 struct vnode *vp;
4439 int error;
4440
4441 error = priv_check(td, PRIV_VFS_FHSTAT324);
4442 if (error != 0)
4443 return (error);
4444 if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL((void *)0))
4445 return (ESTALE70);
4446 error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_fhtovp)(mp, &
fh.fh_fid, 0x080000, &vp); _rc; })
;
4447 vfs_unbusy(mp);
4448 if (error != 0)
4449 return (error);
4450 error = vn_stat(vp, sb, td->td_ucred, NOCRED((struct ucred *)0), td);
4451 vput(vp);
4452 return (error);
4453}
4454
4455/*
4456 * Implement fstatfs() for (NFS) file handles.
4457 */
4458#ifndef _SYS_SYSPROTO_H_
4459struct fhstatfs_args {
4460 struct fhandle *u_fhp;
4461 struct statfs *buf;
4462};
4463#endif
4464int
4465sys_fhstatfs(struct thread *td, struct fhstatfs_args *uap)
4466{
4467 struct statfs *sfp;
4468 fhandle_t fh;
4469 int error;
4470
4471 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4472 if (error != 0)
4473 return (error);
4474 sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK0x0002);
4475 error = kern_fhstatfs(td, fh, sfp);
4476 if (error == 0)
4477 error = copyout(sfp, uap->buf, sizeof(*sfp));
4478 free(sfp, M_STATFS);
4479 return (error);
4480}
4481
4482int
4483kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4484{
4485 struct statfs *sp;
4486 struct mount *mp;
4487 struct vnode *vp;
4488 int error;
4489
4490 error = priv_check(td, PRIV_VFS_FHSTATFS325);
4491 if (error != 0)
4492 return (error);
4493 if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL((void *)0))
4494 return (ESTALE70);
4495 error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp)({ int _rc; _rc = (*(mp)->mnt_op->vfs_fhtovp)(mp, &
fh.fh_fid, 0x080000, &vp); _rc; })
;
4496 if (error != 0) {
4497 vfs_unbusy(mp);
4498 return (error);
4499 }
4500 vput(vp);
4501 error = prison_canseemount(td->td_ucred, mp);
4502 if (error != 0)
4503 goto out;
4504#ifdef MAC1
4505 error = mac_mount_check_stat(td->td_ucred, mp);
4506 if (error != 0)
4507 goto out;
4508#endif
4509 /*
4510 * Set these in case the underlying filesystem fails to do so.
4511 */
4512 sp = &mp->mnt_stat;
4513 sp->f_version = STATFS_VERSION0x20140518;
4514 sp->f_namemax = NAME_MAX255;
4515 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK(0x0000000000000001ULL | 0x0000000000000002ULL | 0x0000000000000004ULL
| 0x0000000000000008ULL | 0x0000000000000020ULL | 0x0000000100000000ULL
| 0x0000000000000040ULL | 0x0000000000000080ULL | 0x0000000000000100ULL
| 0x0000000000000200ULL | 0x0000000000000400ULL| 0x0000000000000800ULL
| 0x0000000000001000ULL | 0x0000000000008000ULL | 0x0000000000002000ULL
| 0x0000000000004000ULL | 0x0000000010000000ULL | 0x0000000040000000ULL
| 0x0000000080000000ULL | 0x0000000000100000ULL | 0x0000000000200000ULL
| 0x0000000000800000ULL | 0x0000000020000000ULL | 0x0000000000400000ULL
| 0x0000000002000000ULL | 0x0000000004000000ULL | 0x0000000008000000ULL
| 0x0000000000000010ULL | 0x0000000200000000ULL | 0x0000000400000000ULL
)
;
4516 error = VFS_STATFS(mp, sp)({ int _rc; _rc = __vfs_statfs((mp), (sp)); _rc; });
4517 if (error == 0)
4518 *buf = *sp;
4519out:
4520 vfs_unbusy(mp);
4521 return (error);
4522}
4523
4524int
4525kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
4526{
4527 struct file *fp;
4528 struct mount *mp;
4529 struct vnode *vp;
4530 off_t olen, ooffset;
4531 int error;
4532#ifdef AUDIT1
4533 int audited_vnode1 = 0;
4534#endif
4535
4536 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
4537 if (offset < 0 || len <= 0)
4538 return (EINVAL22);
4539 /* Check for wrap. */
4540 if (offset > OFF_MAX0x7fffffffffffffff - len)
4541 return (EFBIG27);
4542 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
4543 error = fget(td, fd, &cap_pwrite_rights, &fp);
4544 if (error != 0)
4545 return (error);
4546 AUDIT_ARG_FILE(td->td_proc, fp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_file((td->td_proc), (fp)); } while
(0)
;
4547 if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE0x02) == 0) {
4548 error = ESPIPE29;
4549 goto out;
4550 }
4551 if ((fp->f_flag & FWRITE0x0002) == 0) {
4552 error = EBADF9;
4553 goto out;
4554 }
4555 if (fp->f_type != DTYPE_VNODE1) {
4556 error = ENODEV19;
4557 goto out;
4558 }
4559 vp = fp->f_vnode;
4560 if (vp->v_type != VREG) {
4561 error = ENODEV19;
4562 goto out;
4563 }
4564
4565 /* Allocating blocks may take a long time, so iterate. */
4566 for (;;) {
4567 olen = len;
4568 ooffset = offset;
4569
4570 bwillwrite();
4571 mp = NULL((void *)0);
4572 error = vn_start_write(vp, &mp, V_WAIT0x0001 | PCATCH0x100);
4573 if (error != 0)
4574 break;
4575 error = vn_lock(vp, LK_EXCLUSIVE)_vn_lock(vp, 0x080000, "/root/freebsd/sys/kern/vfs_syscalls.c"
, 4575)
;
4576 if (error != 0) {
4577 vn_finished_write(mp);
4578 break;
4579 }
4580#ifdef AUDIT1
4581 if (!audited_vnode1) {
4582 AUDIT_ARG_VNODE1(vp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_vnode1((vp)); } while (0)
;
4583 audited_vnode1 = 1;
4584 }
4585#endif
4586#ifdef MAC1
4587 error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp);
4588 if (error == 0)
4589#endif
4590 error = VOP_ALLOCATE(vp, &offset, &len);
4591 VOP_UNLOCK(vp, 0);
4592 vn_finished_write(mp);
4593
4594 if (olen + ooffset != offset + len) {
4595 panic("offset + len changed from %jx/%jx to %jx/%jx",
4596 ooffset, olen, offset, len);
4597 }
4598 if (error != 0 || len == 0)
4599 break;
4600 KASSERT(olen > len, ("Iteration did not make progress?"))do { if (__builtin_expect((!(olen > len)), 0)) panic ("Iteration did not make progress?"
); } while (0)
;
4601 maybe_yield();
4602 }
4603 out:
4604 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
4605 return (error);
4606}
4607
4608int
4609sys_posix_fallocate(struct thread *td, struct posix_fallocate_args *uap)
4610{
4611 int error;
4612
4613 error = kern_posix_fallocate(td, uap->fd, uap->offset, uap->len);
4614 return (kern_posix_error(td, error));
4615}
4616
4617/*
4618 * Unlike madvise(2), we do not make a best effort to remember every
4619 * possible caching hint. Instead, we remember the last setting with
4620 * the exception that we will allow POSIX_FADV_NORMAL to adjust the
4621 * region of any current setting.
4622 */
4623int
4624kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
4625 int advice)
4626{
4627 struct fadvise_info *fa, *new;
4628 struct file *fp;
4629 struct vnode *vp;
4630 off_t end;
4631 int error;
4632
4633 if (offset < 0 || len < 0 || offset > OFF_MAX0x7fffffffffffffff - len)
4634 return (EINVAL22);
4635 AUDIT_ARG_VALUE(advice)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_value((advice)); } while (0)
;
4636 switch (advice) {
4637 case POSIX_FADV_SEQUENTIAL2:
4638 case POSIX_FADV_RANDOM1:
4639 case POSIX_FADV_NOREUSE5:
4640 new = malloc(sizeof(*fa), M_FADVISE, M_WAITOK0x0002);
4641 break;
4642 case POSIX_FADV_NORMAL0:
4643 case POSIX_FADV_WILLNEED3:
4644 case POSIX_FADV_DONTNEED4:
4645 new = NULL((void *)0);
4646 break;
4647 default:
4648 return (EINVAL22);
4649 }
4650 /* XXX: CAP_POSIX_FADVISE? */
4651 AUDIT_ARG_FD(fd)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_fd((fd)); } while (0)
;
4652 error = fget(td, fd, &cap_no_rights, &fp);
4653 if (error != 0)
4654 goto out;
4655 AUDIT_ARG_FILE(td->td_proc, fp)do { if ((__builtin_expect((((__curthread()))->td_pflags &
0x01000000), 0))) audit_arg_file((td->td_proc), (fp)); } while
(0)
;
4656 if ((fp->f_ops->fo_flags & DFLAG_SEEKABLE0x02) == 0) {
4657 error = ESPIPE29;
4658 goto out;
4659 }
4660 if (fp->f_type != DTYPE_VNODE1) {
4661 error = ENODEV19;
4662 goto out;
4663 }
4664 vp = fp->f_vnode;
4665 if (vp->v_type != VREG) {
4666 error = ENODEV19;
4667 goto out;
4668 }
4669 if (len == 0)
4670 end = OFF_MAX0x7fffffffffffffff;
4671 else
4672 end = offset + len - 1;
4673 switch (advice) {
4674 case POSIX_FADV_SEQUENTIAL2:
4675 case POSIX_FADV_RANDOM1:
4676 case POSIX_FADV_NOREUSE5:
4677 /*
4678 * Try to merge any existing non-standard region with
4679 * this new region if possible, otherwise create a new
4680 * non-standard region for this request.
4681 */
4682 mtx_pool_lock(mtxpool_sleep, fp)__mtx_lock_flags(&((((mtx_pool_find((mtxpool_sleep), (fp)
)))))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4682))
;
4683 fa = fp->f_advicef_vnun.fvn_advice;
4684 if (fa != NULL((void *)0) && fa->fa_advice == advice &&
4685 ((fa->fa_start <= end && fa->fa_end >= offset) ||
4686 (end != OFF_MAX0x7fffffffffffffff && fa->fa_start == end + 1) ||
4687 (fa->fa_end != OFF_MAX0x7fffffffffffffff && fa->fa_end + 1 == offset))) {
4688 if (offset < fa->fa_start)
4689 fa->fa_start = offset;
4690 if (end > fa->fa_end)
4691 fa->fa_end = end;
4692 } else {
4693 new->fa_advice = advice;
4694 new->fa_start = offset;
4695 new->fa_end = end;
4696 fp->f_advicef_vnun.fvn_advice = new;
4697 new = fa;
4698 }
4699 mtx_pool_unlock(mtxpool_sleep, fp)__mtx_unlock_flags(&((((mtx_pool_find((mtxpool_sleep), (fp
))))))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4699))
;
4700 break;
4701 case POSIX_FADV_NORMAL0:
4702 /*
4703 * If a the "normal" region overlaps with an existing
4704 * non-standard region, trim or remove the
4705 * non-standard region.
4706 */
4707 mtx_pool_lock(mtxpool_sleep, fp)__mtx_lock_flags(&((((mtx_pool_find((mtxpool_sleep), (fp)
)))))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4707))
;
4708 fa = fp->f_advicef_vnun.fvn_advice;
4709 if (fa != NULL((void *)0)) {
4710 if (offset <= fa->fa_start && end >= fa->fa_end) {
4711 new = fa;
4712 fp->f_advicef_vnun.fvn_advice = NULL((void *)0);
4713 } else if (offset <= fa->fa_start &&
4714 end >= fa->fa_start)
4715 fa->fa_start = end + 1;
4716 else if (offset <= fa->fa_end && end >= fa->fa_end)
4717 fa->fa_end = offset - 1;
4718 else if (offset >= fa->fa_start && end <= fa->fa_end) {
4719 /*
4720 * If the "normal" region is a middle
4721 * portion of the existing
4722 * non-standard region, just remove
4723 * the whole thing rather than picking
4724 * one side or the other to
4725 * preserve.
4726 */
4727 new = fa;
4728 fp->f_advicef_vnun.fvn_advice = NULL((void *)0);
4729 }
4730 }
4731 mtx_pool_unlock(mtxpool_sleep, fp)__mtx_unlock_flags(&((((mtx_pool_find((mtxpool_sleep), (fp
))))))->mtx_lock, ((0)), ("/root/freebsd/sys/kern/vfs_syscalls.c"
), (4731))
;
4732 break;
4733 case POSIX_FADV_WILLNEED3:
4734 case POSIX_FADV_DONTNEED4:
4735 error = VOP_ADVISE(vp, offset, end, advice);
4736 break;
4737 }
4738out:
4739 if (fp != NULL((void *)0))
4740 fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td))
: _fnoop())
;
4741 free(new, M_FADVISE);
4742 return (error);
4743}
4744
4745int
4746sys_posix_fadvise(struct thread *td, struct posix_fadvise_args *uap)
4747{
4748 int error;
4749
4750 error = kern_posix_fadvise(td, uap->fd, uap->offset, uap->len,
4751 uap->advice);
4752 return (kern_posix_error(td, error));
4753}