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