Fri Dec 2 12:30:14 2011 UTC ()
fix an indent an unwarp a short line.


(yamt)
diff -r1.441 -r1.442 src/sys/kern/vfs_syscalls.c

cvs diff -r1.441 -r1.442 src/sys/kern/vfs_syscalls.c (switch to unified diff)

--- src/sys/kern/vfs_syscalls.c 2011/11/18 21:17:45 1.441
+++ src/sys/kern/vfs_syscalls.c 2011/12/02 12:30:14 1.442
@@ -1,1072 +1,1072 @@ @@ -1,1072 +1,1072 @@
1/* $NetBSD: vfs_syscalls.c,v 1.441 2011/11/18 21:17:45 christos Exp $ */ 1/* $NetBSD: vfs_syscalls.c,v 1.442 2011/12/02 12:30:14 yamt Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1989, 1993 33 * Copyright (c) 1989, 1993
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * (c) UNIX System Laboratories, Inc. 35 * (c) UNIX System Laboratories, Inc.
36 * All or some portions of this file are derived from material licensed 36 * All or some portions of this file are derived from material licensed
37 * to the University of California by American Telephone and Telegraph 37 * to the University of California by American Telephone and Telegraph
38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39 * the permission of UNIX System Laboratories, Inc. 39 * the permission of UNIX System Laboratories, Inc.
40 * 40 *
41 * Redistribution and use in source and binary forms, with or without 41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions 42 * modification, are permitted provided that the following conditions
43 * are met: 43 * are met:
44 * 1. Redistributions of source code must retain the above copyright 44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer. 45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright 46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the 47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution. 48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors 49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software 50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission. 51 * without specific prior written permission.
52 * 52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 65 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95
66 */ 66 */
67 67
68/* 68/*
69 * Virtual File System System Calls 69 * Virtual File System System Calls
70 */ 70 */
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.441 2011/11/18 21:17:45 christos Exp $"); 73__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.442 2011/12/02 12:30:14 yamt Exp $");
74 74
75#ifdef _KERNEL_OPT 75#ifdef _KERNEL_OPT
76#include "opt_fileassoc.h" 76#include "opt_fileassoc.h"
77#include "veriexec.h" 77#include "veriexec.h"
78#endif 78#endif
79 79
80#include <sys/param.h> 80#include <sys/param.h>
81#include <sys/systm.h> 81#include <sys/systm.h>
82#include <sys/namei.h> 82#include <sys/namei.h>
83#include <sys/filedesc.h> 83#include <sys/filedesc.h>
84#include <sys/kernel.h> 84#include <sys/kernel.h>
85#include <sys/file.h> 85#include <sys/file.h>
86#include <sys/fcntl.h> 86#include <sys/fcntl.h>
87#include <sys/stat.h> 87#include <sys/stat.h>
88#include <sys/vnode.h> 88#include <sys/vnode.h>
89#include <sys/mount.h> 89#include <sys/mount.h>
90#include <sys/proc.h> 90#include <sys/proc.h>
91#include <sys/uio.h> 91#include <sys/uio.h>
92#include <sys/kmem.h> 92#include <sys/kmem.h>
93#include <sys/dirent.h> 93#include <sys/dirent.h>
94#include <sys/sysctl.h> 94#include <sys/sysctl.h>
95#include <sys/syscallargs.h> 95#include <sys/syscallargs.h>
96#include <sys/vfs_syscalls.h> 96#include <sys/vfs_syscalls.h>
97#include <sys/ktrace.h> 97#include <sys/ktrace.h>
98#ifdef FILEASSOC 98#ifdef FILEASSOC
99#include <sys/fileassoc.h> 99#include <sys/fileassoc.h>
100#endif /* FILEASSOC */ 100#endif /* FILEASSOC */
101#include <sys/extattr.h> 101#include <sys/extattr.h>
102#include <sys/verified_exec.h> 102#include <sys/verified_exec.h>
103#include <sys/kauth.h> 103#include <sys/kauth.h>
104#include <sys/atomic.h> 104#include <sys/atomic.h>
105#include <sys/module.h> 105#include <sys/module.h>
106#include <sys/buf.h> 106#include <sys/buf.h>
107 107
108#include <miscfs/genfs/genfs.h> 108#include <miscfs/genfs/genfs.h>
109#include <miscfs/syncfs/syncfs.h> 109#include <miscfs/syncfs/syncfs.h>
110#include <miscfs/specfs/specdev.h> 110#include <miscfs/specfs/specdev.h>
111 111
112#include <nfs/rpcv2.h> 112#include <nfs/rpcv2.h>
113#include <nfs/nfsproto.h> 113#include <nfs/nfsproto.h>
114#include <nfs/nfs.h> 114#include <nfs/nfs.h>
115#include <nfs/nfs_var.h> 115#include <nfs/nfs_var.h>
116 116
117static int change_flags(struct vnode *, u_long, struct lwp *); 117static int change_flags(struct vnode *, u_long, struct lwp *);
118static int change_mode(struct vnode *, int, struct lwp *l); 118static int change_mode(struct vnode *, int, struct lwp *l);
119static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int); 119static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int);
120 120
121/* 121/*
122 * This table is used to maintain compatibility with 4.3BSD 122 * This table is used to maintain compatibility with 4.3BSD
123 * and NetBSD 0.9 mount syscalls - and possibly other systems. 123 * and NetBSD 0.9 mount syscalls - and possibly other systems.
124 * Note, the order is important! 124 * Note, the order is important!
125 * 125 *
126 * Do not modify this table. It should only contain filesystems 126 * Do not modify this table. It should only contain filesystems
127 * supported by NetBSD 0.9 and 4.3BSD. 127 * supported by NetBSD 0.9 and 4.3BSD.
128 */ 128 */
129const char * const mountcompatnames[] = { 129const char * const mountcompatnames[] = {
130 NULL, /* 0 = MOUNT_NONE */ 130 NULL, /* 0 = MOUNT_NONE */
131 MOUNT_FFS, /* 1 = MOUNT_UFS */ 131 MOUNT_FFS, /* 1 = MOUNT_UFS */
132 MOUNT_NFS, /* 2 */ 132 MOUNT_NFS, /* 2 */
133 MOUNT_MFS, /* 3 */ 133 MOUNT_MFS, /* 3 */
134 MOUNT_MSDOS, /* 4 */ 134 MOUNT_MSDOS, /* 4 */
135 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */ 135 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */
136 MOUNT_FDESC, /* 6 */ 136 MOUNT_FDESC, /* 6 */
137 MOUNT_KERNFS, /* 7 */ 137 MOUNT_KERNFS, /* 7 */
138 NULL, /* 8 = MOUNT_DEVFS */ 138 NULL, /* 8 = MOUNT_DEVFS */
139 MOUNT_AFS, /* 9 */ 139 MOUNT_AFS, /* 9 */
140}; 140};
141 141
142const int nmountcompatnames = __arraycount(mountcompatnames); 142const int nmountcompatnames = __arraycount(mountcompatnames);
143 143
144static int 144static int
145open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags) 145open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags)
146{ 146{
147 int error; 147 int error;
148 148
149 fp->f_flag = flags & FMASK; 149 fp->f_flag = flags & FMASK;
150 fp->f_type = DTYPE_VNODE; 150 fp->f_type = DTYPE_VNODE;
151 fp->f_ops = &vnops; 151 fp->f_ops = &vnops;
152 fp->f_data = vp; 152 fp->f_data = vp;
153 153
154 if (flags & (O_EXLOCK | O_SHLOCK)) { 154 if (flags & (O_EXLOCK | O_SHLOCK)) {
155 struct flock lf; 155 struct flock lf;
156 int type; 156 int type;
157 157
158 lf.l_whence = SEEK_SET; 158 lf.l_whence = SEEK_SET;
159 lf.l_start = 0; 159 lf.l_start = 0;
160 lf.l_len = 0; 160 lf.l_len = 0;
161 if (flags & O_EXLOCK) 161 if (flags & O_EXLOCK)
162 lf.l_type = F_WRLCK; 162 lf.l_type = F_WRLCK;
163 else 163 else
164 lf.l_type = F_RDLCK; 164 lf.l_type = F_RDLCK;
165 type = F_FLOCK; 165 type = F_FLOCK;
166 if ((flags & FNONBLOCK) == 0) 166 if ((flags & FNONBLOCK) == 0)
167 type |= F_WAIT; 167 type |= F_WAIT;
168 VOP_UNLOCK(vp); 168 VOP_UNLOCK(vp);
169 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 169 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type);
170 if (error) { 170 if (error) {
171 (void) vn_close(vp, fp->f_flag, fp->f_cred); 171 (void) vn_close(vp, fp->f_flag, fp->f_cred);
172 fd_abort(l->l_proc, fp, indx); 172 fd_abort(l->l_proc, fp, indx);
173 return error; 173 return error;
174 } 174 }
175 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 175 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
176 atomic_or_uint(&fp->f_flag, FHASLOCK); 176 atomic_or_uint(&fp->f_flag, FHASLOCK);
177 } 177 }
178 if (flags & O_CLOEXEC) 178 if (flags & O_CLOEXEC)
179 fd_set_exclose(l, indx, true); 179 fd_set_exclose(l, indx, true);
180 return 0; 180 return 0;
181} 181}
182 182
183static int 183static int
184mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags, 184mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags,
185 void *data, size_t *data_len) 185 void *data, size_t *data_len)
186{ 186{
187 struct mount *mp; 187 struct mount *mp;
188 int error = 0, saved_flags; 188 int error = 0, saved_flags;
189 189
190 mp = vp->v_mount; 190 mp = vp->v_mount;
191 saved_flags = mp->mnt_flag; 191 saved_flags = mp->mnt_flag;
192 192
193 /* We can operate only on VV_ROOT nodes. */ 193 /* We can operate only on VV_ROOT nodes. */
194 if ((vp->v_vflag & VV_ROOT) == 0) { 194 if ((vp->v_vflag & VV_ROOT) == 0) {
195 error = EINVAL; 195 error = EINVAL;
196 goto out; 196 goto out;
197 } 197 }
198 198
199 /* 199 /*
200 * We only allow the filesystem to be reloaded if it 200 * We only allow the filesystem to be reloaded if it
201 * is currently mounted read-only. Additionally, we 201 * is currently mounted read-only. Additionally, we
202 * prevent read-write to read-only downgrades. 202 * prevent read-write to read-only downgrades.
203 */ 203 */
204 if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 && 204 if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 &&
205 (mp->mnt_flag & MNT_RDONLY) == 0 && 205 (mp->mnt_flag & MNT_RDONLY) == 0 &&
206 (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) { 206 (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) {
207 error = EOPNOTSUPP; /* Needs translation */ 207 error = EOPNOTSUPP; /* Needs translation */
208 goto out; 208 goto out;
209 } 209 }
210 210
211 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 211 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
212 KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data); 212 KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data);
213 if (error) 213 if (error)
214 goto out; 214 goto out;
215 215
216 if (vfs_busy(mp, NULL)) { 216 if (vfs_busy(mp, NULL)) {
217 error = EPERM; 217 error = EPERM;
218 goto out; 218 goto out;
219 } 219 }
220 220
221 mutex_enter(&mp->mnt_updating); 221 mutex_enter(&mp->mnt_updating);
222 222
223 mp->mnt_flag &= ~MNT_OP_FLAGS; 223 mp->mnt_flag &= ~MNT_OP_FLAGS;
224 mp->mnt_flag |= flags & MNT_OP_FLAGS; 224 mp->mnt_flag |= flags & MNT_OP_FLAGS;
225 225
226 /* 226 /*
227 * Set the mount level flags. 227 * Set the mount level flags.
228 */ 228 */
229 if (flags & MNT_RDONLY) 229 if (flags & MNT_RDONLY)
230 mp->mnt_flag |= MNT_RDONLY; 230 mp->mnt_flag |= MNT_RDONLY;
231 else if (mp->mnt_flag & MNT_RDONLY) 231 else if (mp->mnt_flag & MNT_RDONLY)
232 mp->mnt_iflag |= IMNT_WANTRDWR; 232 mp->mnt_iflag |= IMNT_WANTRDWR;
233 mp->mnt_flag &= ~MNT_BASIC_FLAGS; 233 mp->mnt_flag &= ~MNT_BASIC_FLAGS;
234 mp->mnt_flag |= flags & MNT_BASIC_FLAGS; 234 mp->mnt_flag |= flags & MNT_BASIC_FLAGS;
235 error = VFS_MOUNT(mp, path, data, data_len); 235 error = VFS_MOUNT(mp, path, data, data_len);
236 236
237 if (error && data != NULL) { 237 if (error && data != NULL) {
238 int error2; 238 int error2;
239 239
240 /* 240 /*
241 * Update failed; let's try and see if it was an 241 * Update failed; let's try and see if it was an
242 * export request. For compat with 3.0 and earlier. 242 * export request. For compat with 3.0 and earlier.
243 */ 243 */
244 error2 = vfs_hooks_reexport(mp, path, data); 244 error2 = vfs_hooks_reexport(mp, path, data);
245 245
246 /* 246 /*
247 * Only update error code if the export request was 247 * Only update error code if the export request was
248 * understood but some problem occurred while 248 * understood but some problem occurred while
249 * processing it. 249 * processing it.
250 */ 250 */
251 if (error2 != EJUSTRETURN) 251 if (error2 != EJUSTRETURN)
252 error = error2; 252 error = error2;
253 } 253 }
254 254
255 if (mp->mnt_iflag & IMNT_WANTRDWR) 255 if (mp->mnt_iflag & IMNT_WANTRDWR)
256 mp->mnt_flag &= ~MNT_RDONLY; 256 mp->mnt_flag &= ~MNT_RDONLY;
257 if (error) 257 if (error)
258 mp->mnt_flag = saved_flags; 258 mp->mnt_flag = saved_flags;
259 mp->mnt_flag &= ~MNT_OP_FLAGS; 259 mp->mnt_flag &= ~MNT_OP_FLAGS;
260 mp->mnt_iflag &= ~IMNT_WANTRDWR; 260 mp->mnt_iflag &= ~IMNT_WANTRDWR;
261 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) { 261 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
262 if (mp->mnt_syncer == NULL) 262 if (mp->mnt_syncer == NULL)
263 error = vfs_allocate_syncvnode(mp); 263 error = vfs_allocate_syncvnode(mp);
264 } else { 264 } else {
265 if (mp->mnt_syncer != NULL) 265 if (mp->mnt_syncer != NULL)
266 vfs_deallocate_syncvnode(mp); 266 vfs_deallocate_syncvnode(mp);
267 } 267 }
268 mutex_exit(&mp->mnt_updating); 268 mutex_exit(&mp->mnt_updating);
269 vfs_unbusy(mp, false, NULL); 269 vfs_unbusy(mp, false, NULL);
270 270
271 if ((error == 0) && !(saved_flags & MNT_EXTATTR) &&  271 if ((error == 0) && !(saved_flags & MNT_EXTATTR) &&
272 (flags & MNT_EXTATTR)) { 272 (flags & MNT_EXTATTR)) {
273 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START,  273 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START,
274 NULL, 0, NULL) != 0) { 274 NULL, 0, NULL) != 0) {
275 printf("%s: failed to start extattr, error = %d", 275 printf("%s: failed to start extattr, error = %d",
276 vp->v_mount->mnt_stat.f_mntonname, error); 276 vp->v_mount->mnt_stat.f_mntonname, error);
277 mp->mnt_flag &= ~MNT_EXTATTR; 277 mp->mnt_flag &= ~MNT_EXTATTR;
278 } 278 }
279 } 279 }
280 280
281 if ((error == 0) && (saved_flags & MNT_EXTATTR) &&  281 if ((error == 0) && (saved_flags & MNT_EXTATTR) &&
282 !(flags & MNT_EXTATTR)) { 282 !(flags & MNT_EXTATTR)) {
283 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_STOP,  283 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_STOP,
284 NULL, 0, NULL) != 0) { 284 NULL, 0, NULL) != 0) {
285 printf("%s: failed to stop extattr, error = %d", 285 printf("%s: failed to stop extattr, error = %d",
286 vp->v_mount->mnt_stat.f_mntonname, error); 286 vp->v_mount->mnt_stat.f_mntonname, error);
287 mp->mnt_flag |= MNT_RDONLY; 287 mp->mnt_flag |= MNT_RDONLY;
288 } 288 }
289 } 289 }
290 out: 290 out:
291 return (error); 291 return (error);
292} 292}
293 293
294static int 294static int
295mount_get_vfsops(const char *fstype, struct vfsops **vfsops) 295mount_get_vfsops(const char *fstype, struct vfsops **vfsops)
296{ 296{
297 char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)]; 297 char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)];
298 int error; 298 int error;
299 299
300 /* Copy file-system type from userspace. */ 300 /* Copy file-system type from userspace. */
301 error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL); 301 error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL);
302 if (error) { 302 if (error) {
303 /* 303 /*
304 * Historically, filesystem types were identified by numbers. 304 * Historically, filesystem types were identified by numbers.
305 * If we get an integer for the filesystem type instead of a 305 * If we get an integer for the filesystem type instead of a
306 * string, we check to see if it matches one of the historic 306 * string, we check to see if it matches one of the historic
307 * filesystem types. 307 * filesystem types.
308 */ 308 */
309 u_long fsindex = (u_long)fstype; 309 u_long fsindex = (u_long)fstype;
310 if (fsindex >= nmountcompatnames || 310 if (fsindex >= nmountcompatnames ||
311 mountcompatnames[fsindex] == NULL) 311 mountcompatnames[fsindex] == NULL)
312 return ENODEV; 312 return ENODEV;
313 strlcpy(fstypename, mountcompatnames[fsindex], 313 strlcpy(fstypename, mountcompatnames[fsindex],
314 sizeof(fstypename)); 314 sizeof(fstypename));
315 } 315 }
316 316
317 /* Accept `ufs' as an alias for `ffs', for compatibility. */ 317 /* Accept `ufs' as an alias for `ffs', for compatibility. */
318 if (strcmp(fstypename, "ufs") == 0) 318 if (strcmp(fstypename, "ufs") == 0)
319 fstypename[0] = 'f'; 319 fstypename[0] = 'f';
320 320
321 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 321 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
322 return 0; 322 return 0;
323 323
324 /* If we can autoload a vfs module, try again */ 324 /* If we can autoload a vfs module, try again */
325 (void)module_autoload(fstypename, MODULE_CLASS_VFS); 325 (void)module_autoload(fstypename, MODULE_CLASS_VFS);
326 326
327 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 327 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL)
328 return 0; 328 return 0;
329 329
330 return ENODEV; 330 return ENODEV;
331} 331}
332 332
333static int 333static int
334mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags, 334mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags,
335 void *data, size_t *data_len) 335 void *data, size_t *data_len)
336{ 336{
337 struct mount *mp; 337 struct mount *mp;
338 int error; 338 int error;
339 339
340 /* If MNT_GETARGS is specified, it should be the only flag. */ 340 /* If MNT_GETARGS is specified, it should be the only flag. */
341 if (flags & ~MNT_GETARGS) 341 if (flags & ~MNT_GETARGS)
342 return EINVAL; 342 return EINVAL;
343 343
344 mp = vp->v_mount; 344 mp = vp->v_mount;
345 345
346 /* XXX: probably some notion of "can see" here if we want isolation. */  346 /* XXX: probably some notion of "can see" here if we want isolation. */
347 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 347 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
348 KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL); 348 KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL);
349 if (error) 349 if (error)
350 return error; 350 return error;
351 351
352 if ((vp->v_vflag & VV_ROOT) == 0) 352 if ((vp->v_vflag & VV_ROOT) == 0)
353 return EINVAL; 353 return EINVAL;
354 354
355 if (vfs_busy(mp, NULL)) 355 if (vfs_busy(mp, NULL))
356 return EPERM; 356 return EPERM;
357 357
358 mutex_enter(&mp->mnt_updating); 358 mutex_enter(&mp->mnt_updating);
359 mp->mnt_flag &= ~MNT_OP_FLAGS; 359 mp->mnt_flag &= ~MNT_OP_FLAGS;
360 mp->mnt_flag |= MNT_GETARGS; 360 mp->mnt_flag |= MNT_GETARGS;
361 error = VFS_MOUNT(mp, path, data, data_len); 361 error = VFS_MOUNT(mp, path, data, data_len);
362 mp->mnt_flag &= ~MNT_OP_FLAGS; 362 mp->mnt_flag &= ~MNT_OP_FLAGS;
363 mutex_exit(&mp->mnt_updating); 363 mutex_exit(&mp->mnt_updating);
364 364
365 vfs_unbusy(mp, false, NULL); 365 vfs_unbusy(mp, false, NULL);
366 return (error); 366 return (error);
367} 367}
368 368
369int 369int
370sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval) 370sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval)
371{ 371{
372 /* { 372 /* {
373 syscallarg(const char *) type; 373 syscallarg(const char *) type;
374 syscallarg(const char *) path; 374 syscallarg(const char *) path;
375 syscallarg(int) flags; 375 syscallarg(int) flags;
376 syscallarg(void *) data; 376 syscallarg(void *) data;
377 syscallarg(size_t) data_len; 377 syscallarg(size_t) data_len;
378 } */ 378 } */
379 379
380 return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path), 380 return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path),
381 SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 381 SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE,
382 SCARG(uap, data_len), retval); 382 SCARG(uap, data_len), retval);
383} 383}
384 384
385int 385int
386do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type, 386do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type,
387 const char *path, int flags, void *data, enum uio_seg data_seg, 387 const char *path, int flags, void *data, enum uio_seg data_seg,
388 size_t data_len, register_t *retval) 388 size_t data_len, register_t *retval)
389{ 389{
390 struct vnode *vp; 390 struct vnode *vp;
391 void *data_buf = data; 391 void *data_buf = data;
392 bool vfsopsrele = false; 392 bool vfsopsrele = false;
393 int error; 393 int error;
394 394
395 /* XXX: The calling convention of this routine is totally bizarre */ 395 /* XXX: The calling convention of this routine is totally bizarre */
396 if (vfsops) 396 if (vfsops)
397 vfsopsrele = true; 397 vfsopsrele = true;
398 398
399 /* 399 /*
400 * Get vnode to be covered 400 * Get vnode to be covered
401 */ 401 */
402 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp); 402 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
403 if (error != 0) { 403 if (error != 0) {
404 vp = NULL; 404 vp = NULL;
405 goto done; 405 goto done;
406 } 406 }
407 407
408 if (vfsops == NULL) { 408 if (vfsops == NULL) {
409 if (flags & (MNT_GETARGS | MNT_UPDATE)) { 409 if (flags & (MNT_GETARGS | MNT_UPDATE)) {
410 vfsops = vp->v_mount->mnt_op; 410 vfsops = vp->v_mount->mnt_op;
411 } else { 411 } else {
412 /* 'type' is userspace */ 412 /* 'type' is userspace */
413 error = mount_get_vfsops(type, &vfsops); 413 error = mount_get_vfsops(type, &vfsops);
414 if (error != 0) 414 if (error != 0)
415 goto done; 415 goto done;
416 vfsopsrele = true; 416 vfsopsrele = true;
417 } 417 }
418 } 418 }
419 419
420 if (data != NULL && data_seg == UIO_USERSPACE) { 420 if (data != NULL && data_seg == UIO_USERSPACE) {
421 if (data_len == 0) { 421 if (data_len == 0) {
422 /* No length supplied, use default for filesystem */ 422 /* No length supplied, use default for filesystem */
423 data_len = vfsops->vfs_min_mount_data; 423 data_len = vfsops->vfs_min_mount_data;
424 if (data_len > VFS_MAX_MOUNT_DATA) { 424 if (data_len > VFS_MAX_MOUNT_DATA) {
425 error = EINVAL; 425 error = EINVAL;
426 goto done; 426 goto done;
427 } 427 }
428 /* 428 /*
429 * Hopefully a longer buffer won't make copyin() fail. 429 * Hopefully a longer buffer won't make copyin() fail.
430 * For compatibility with 3.0 and earlier. 430 * For compatibility with 3.0 and earlier.
431 */ 431 */
432 if (flags & MNT_UPDATE 432 if (flags & MNT_UPDATE
433 && data_len < sizeof (struct mnt_export_args30)) 433 && data_len < sizeof (struct mnt_export_args30))
434 data_len = sizeof (struct mnt_export_args30); 434 data_len = sizeof (struct mnt_export_args30);
435 } 435 }
436 data_buf = kmem_alloc(data_len, KM_SLEEP); 436 data_buf = kmem_alloc(data_len, KM_SLEEP);
437 437
438 /* NFS needs the buffer even for mnt_getargs .... */ 438 /* NFS needs the buffer even for mnt_getargs .... */
439 error = copyin(data, data_buf, data_len); 439 error = copyin(data, data_buf, data_len);
440 if (error != 0) 440 if (error != 0)
441 goto done; 441 goto done;
442 } 442 }
443 443
444 if (flags & MNT_GETARGS) { 444 if (flags & MNT_GETARGS) {
445 if (data_len == 0) { 445 if (data_len == 0) {
446 error = EINVAL; 446 error = EINVAL;
447 goto done; 447 goto done;
448 } 448 }
449 error = mount_getargs(l, vp, path, flags, data_buf, &data_len); 449 error = mount_getargs(l, vp, path, flags, data_buf, &data_len);
450 if (error != 0) 450 if (error != 0)
451 goto done; 451 goto done;
452 if (data_seg == UIO_USERSPACE) 452 if (data_seg == UIO_USERSPACE)
453 error = copyout(data_buf, data, data_len); 453 error = copyout(data_buf, data, data_len);
454 *retval = data_len; 454 *retval = data_len;
455 } else if (flags & MNT_UPDATE) { 455 } else if (flags & MNT_UPDATE) {
456 error = mount_update(l, vp, path, flags, data_buf, &data_len); 456 error = mount_update(l, vp, path, flags, data_buf, &data_len);
457 } else { 457 } else {
458 /* Locking is handled internally in mount_domount(). */ 458 /* Locking is handled internally in mount_domount(). */
459 KASSERT(vfsopsrele == true); 459 KASSERT(vfsopsrele == true);
460 error = mount_domount(l, &vp, vfsops, path, flags, data_buf, 460 error = mount_domount(l, &vp, vfsops, path, flags, data_buf,
461 &data_len); 461 &data_len);
462 vfsopsrele = false; 462 vfsopsrele = false;
463 463
464 if ((error == 0) && (flags & MNT_EXTATTR)) { 464 if ((error == 0) && (flags & MNT_EXTATTR)) {
465 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START,  465 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START,
466 NULL, 0, NULL) != 0) 466 NULL, 0, NULL) != 0)
467 printf("%s: failed to start extattr", 467 printf("%s: failed to start extattr",
468 vp->v_mount->mnt_stat.f_mntonname); 468 vp->v_mount->mnt_stat.f_mntonname);
469 /* XXX remove flag */ 469 /* XXX remove flag */
470 } 470 }
471 } 471 }
472 472
473 done: 473 done:
474 if (vfsopsrele) 474 if (vfsopsrele)
475 vfs_delref(vfsops); 475 vfs_delref(vfsops);
476 if (vp != NULL) { 476 if (vp != NULL) {
477 vrele(vp); 477 vrele(vp);
478 } 478 }
479 if (data_buf != data) 479 if (data_buf != data)
480 kmem_free(data_buf, data_len); 480 kmem_free(data_buf, data_len);
481 return (error); 481 return (error);
482} 482}
483 483
484/* 484/*
485 * Unmount a file system. 485 * Unmount a file system.
486 * 486 *
487 * Note: unmount takes a path to the vnode mounted on as argument, 487 * Note: unmount takes a path to the vnode mounted on as argument,
488 * not special file (as before). 488 * not special file (as before).
489 */ 489 */
490/* ARGSUSED */ 490/* ARGSUSED */
491int 491int
492sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval) 492sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval)
493{ 493{
494 /* { 494 /* {
495 syscallarg(const char *) path; 495 syscallarg(const char *) path;
496 syscallarg(int) flags; 496 syscallarg(int) flags;
497 } */ 497 } */
498 struct vnode *vp; 498 struct vnode *vp;
499 struct mount *mp; 499 struct mount *mp;
500 int error; 500 int error;
501 struct pathbuf *pb; 501 struct pathbuf *pb;
502 struct nameidata nd; 502 struct nameidata nd;
503 503
504 error = pathbuf_copyin(SCARG(uap, path), &pb); 504 error = pathbuf_copyin(SCARG(uap, path), &pb);
505 if (error) { 505 if (error) {
506 return error; 506 return error;
507 } 507 }
508 508
509 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 509 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
510 if ((error = namei(&nd)) != 0) { 510 if ((error = namei(&nd)) != 0) {
511 pathbuf_destroy(pb); 511 pathbuf_destroy(pb);
512 return error; 512 return error;
513 } 513 }
514 vp = nd.ni_vp; 514 vp = nd.ni_vp;
515 pathbuf_destroy(pb); 515 pathbuf_destroy(pb);
516 516
517 mp = vp->v_mount; 517 mp = vp->v_mount;
518 atomic_inc_uint(&mp->mnt_refcnt); 518 atomic_inc_uint(&mp->mnt_refcnt);
519 VOP_UNLOCK(vp); 519 VOP_UNLOCK(vp);
520 520
521 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 521 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
522 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL); 522 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL);
523 if (error) { 523 if (error) {
524 vrele(vp); 524 vrele(vp);
525 vfs_destroy(mp); 525 vfs_destroy(mp);
526 return (error); 526 return (error);
527 } 527 }
528 528
529 /* 529 /*
530 * Don't allow unmounting the root file system. 530 * Don't allow unmounting the root file system.
531 */ 531 */
532 if (mp->mnt_flag & MNT_ROOTFS) { 532 if (mp->mnt_flag & MNT_ROOTFS) {
533 vrele(vp); 533 vrele(vp);
534 vfs_destroy(mp); 534 vfs_destroy(mp);
535 return (EINVAL); 535 return (EINVAL);
536 } 536 }
537 537
538 /* 538 /*
539 * Must be the root of the filesystem 539 * Must be the root of the filesystem
540 */ 540 */
541 if ((vp->v_vflag & VV_ROOT) == 0) { 541 if ((vp->v_vflag & VV_ROOT) == 0) {
542 vrele(vp); 542 vrele(vp);
543 vfs_destroy(mp); 543 vfs_destroy(mp);
544 return (EINVAL); 544 return (EINVAL);
545 } 545 }
546 546
547 vrele(vp); 547 vrele(vp);
548 error = dounmount(mp, SCARG(uap, flags), l); 548 error = dounmount(mp, SCARG(uap, flags), l);
549 vfs_destroy(mp); 549 vfs_destroy(mp);
550 return error; 550 return error;
551} 551}
552 552
553/* 553/*
554 * Sync each mounted filesystem. 554 * Sync each mounted filesystem.
555 */ 555 */
556#ifdef DEBUG 556#ifdef DEBUG
557int syncprt = 0; 557int syncprt = 0;
558struct ctldebug debug0 = { "syncprt", &syncprt }; 558struct ctldebug debug0 = { "syncprt", &syncprt };
559#endif 559#endif
560 560
561void 561void
562do_sys_sync(struct lwp *l) 562do_sys_sync(struct lwp *l)
563{ 563{
564 struct mount *mp, *nmp; 564 struct mount *mp, *nmp;
565 int asyncflag; 565 int asyncflag;
566 566
567 mutex_enter(&mountlist_lock); 567 mutex_enter(&mountlist_lock);
568 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 568 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
569 mp = nmp) { 569 mp = nmp) {
570 if (vfs_busy(mp, &nmp)) { 570 if (vfs_busy(mp, &nmp)) {
571 continue; 571 continue;
572 } 572 }
573 mutex_enter(&mp->mnt_updating); 573 mutex_enter(&mp->mnt_updating);
574 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 574 if ((mp->mnt_flag & MNT_RDONLY) == 0) {
575 asyncflag = mp->mnt_flag & MNT_ASYNC; 575 asyncflag = mp->mnt_flag & MNT_ASYNC;
576 mp->mnt_flag &= ~MNT_ASYNC; 576 mp->mnt_flag &= ~MNT_ASYNC;
577 VFS_SYNC(mp, MNT_NOWAIT, l->l_cred); 577 VFS_SYNC(mp, MNT_NOWAIT, l->l_cred);
578 if (asyncflag) 578 if (asyncflag)
579 mp->mnt_flag |= MNT_ASYNC; 579 mp->mnt_flag |= MNT_ASYNC;
580 } 580 }
581 mutex_exit(&mp->mnt_updating); 581 mutex_exit(&mp->mnt_updating);
582 vfs_unbusy(mp, false, &nmp); 582 vfs_unbusy(mp, false, &nmp);
583 } 583 }
584 mutex_exit(&mountlist_lock); 584 mutex_exit(&mountlist_lock);
585#ifdef DEBUG 585#ifdef DEBUG
586 if (syncprt) 586 if (syncprt)
587 vfs_bufstats(); 587 vfs_bufstats();
588#endif /* DEBUG */ 588#endif /* DEBUG */
589} 589}
590 590
591/* ARGSUSED */ 591/* ARGSUSED */
592int 592int
593sys_sync(struct lwp *l, const void *v, register_t *retval) 593sys_sync(struct lwp *l, const void *v, register_t *retval)
594{ 594{
595 do_sys_sync(l); 595 do_sys_sync(l);
596 return (0); 596 return (0);
597} 597}
598 598
599 599
600/* 600/*
601 * Change filesystem quotas. 601 * Change filesystem quotas.
602 */ 602 */
603/* ARGSUSED */ 603/* ARGSUSED */
604int 604int
605sys___quotactl50(struct lwp *l, const struct sys___quotactl50_args *uap, 605sys___quotactl50(struct lwp *l, const struct sys___quotactl50_args *uap,
606 register_t *retval) 606 register_t *retval)
607{ 607{
608 /* { 608 /* {
609 syscallarg(const char *) path; 609 syscallarg(const char *) path;
610 syscallarg(struct plistref *) pref; 610 syscallarg(struct plistref *) pref;
611 } */ 611 } */
612 struct mount *mp; 612 struct mount *mp;
613 int error; 613 int error;
614 struct vnode *vp; 614 struct vnode *vp;
615 prop_dictionary_t dict; 615 prop_dictionary_t dict;
616 struct plistref pref; 616 struct plistref pref;
617 617
618 error = namei_simple_user(SCARG(uap, path), 618 error = namei_simple_user(SCARG(uap, path),
619 NSM_FOLLOW_TRYEMULROOT, &vp); 619 NSM_FOLLOW_TRYEMULROOT, &vp);
620 if (error != 0) 620 if (error != 0)
621 return (error); 621 return (error);
622 mp = vp->v_mount; 622 mp = vp->v_mount;
623 error = copyin(SCARG(uap, pref), &pref, sizeof(pref)); 623 error = copyin(SCARG(uap, pref), &pref, sizeof(pref));
624 if (error) 624 if (error)
625 return error; 625 return error;
626 error = prop_dictionary_copyin(&pref, &dict); 626 error = prop_dictionary_copyin(&pref, &dict);
627 if (error) 627 if (error)
628 return error; 628 return error;
629 error = VFS_QUOTACTL(mp, dict); 629 error = VFS_QUOTACTL(mp, dict);
630 vrele(vp); 630 vrele(vp);
631 if (!error) 631 if (!error)
632 error = prop_dictionary_copyout(&pref, dict); 632 error = prop_dictionary_copyout(&pref, dict);
633 if (!error) 633 if (!error)
634 error = copyout(&pref, SCARG(uap, pref), sizeof(pref)); 634 error = copyout(&pref, SCARG(uap, pref), sizeof(pref));
635 prop_object_release(dict); 635 prop_object_release(dict);
636 return (error); 636 return (error);
637} 637}
638 638
639int 639int
640dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags, 640dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags,
641 int root) 641 int root)
642{ 642{
643 struct cwdinfo *cwdi = l->l_proc->p_cwdi; 643 struct cwdinfo *cwdi = l->l_proc->p_cwdi;
644 int error = 0; 644 int error = 0;
645 645
646 /* 646 /*
647 * If MNT_NOWAIT or MNT_LAZY is specified, do not 647 * If MNT_NOWAIT or MNT_LAZY is specified, do not
648 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY 648 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY
649 * overrides MNT_NOWAIT. 649 * overrides MNT_NOWAIT.
650 */ 650 */
651 if (flags == MNT_NOWAIT || flags == MNT_LAZY || 651 if (flags == MNT_NOWAIT || flags == MNT_LAZY ||
652 (flags != MNT_WAIT && flags != 0)) { 652 (flags != MNT_WAIT && flags != 0)) {
653 memcpy(sp, &mp->mnt_stat, sizeof(*sp)); 653 memcpy(sp, &mp->mnt_stat, sizeof(*sp));
654 goto done; 654 goto done;
655 } 655 }
656 656
657 /* Get the filesystem stats now */ 657 /* Get the filesystem stats now */
658 memset(sp, 0, sizeof(*sp)); 658 memset(sp, 0, sizeof(*sp));
659 if ((error = VFS_STATVFS(mp, sp)) != 0) { 659 if ((error = VFS_STATVFS(mp, sp)) != 0) {
660 return error; 660 return error;
661 } 661 }
662 662
663 if (cwdi->cwdi_rdir == NULL) 663 if (cwdi->cwdi_rdir == NULL)
664 (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat)); 664 (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
665done: 665done:
666 if (cwdi->cwdi_rdir != NULL) { 666 if (cwdi->cwdi_rdir != NULL) {
667 size_t len; 667 size_t len;
668 char *bp; 668 char *bp;
669 char c; 669 char c;
670 char *path = PNBUF_GET(); 670 char *path = PNBUF_GET();
671 671
672 bp = path + MAXPATHLEN; 672 bp = path + MAXPATHLEN;
673 *--bp = '\0'; 673 *--bp = '\0';
674 rw_enter(&cwdi->cwdi_lock, RW_READER); 674 rw_enter(&cwdi->cwdi_lock, RW_READER);
675 error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path, 675 error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path,
676 MAXPATHLEN / 2, 0, l); 676 MAXPATHLEN / 2, 0, l);
677 rw_exit(&cwdi->cwdi_lock); 677 rw_exit(&cwdi->cwdi_lock);
678 if (error) { 678 if (error) {
679 PNBUF_PUT(path); 679 PNBUF_PUT(path);
680 return error; 680 return error;
681 } 681 }
682 len = strlen(bp); 682 len = strlen(bp);
683 if (len != 1) { 683 if (len != 1) {
684 /* 684 /*
685 * for mount points that are below our root, we can see 685 * for mount points that are below our root, we can see
686 * them, so we fix up the pathname and return them. The 686 * them, so we fix up the pathname and return them. The
687 * rest we cannot see, so we don't allow viewing the 687 * rest we cannot see, so we don't allow viewing the
688 * data. 688 * data.
689 */ 689 */
690 if (strncmp(bp, sp->f_mntonname, len) == 0 && 690 if (strncmp(bp, sp->f_mntonname, len) == 0 &&
691 ((c = sp->f_mntonname[len]) == '/' || c == '\0')) { 691 ((c = sp->f_mntonname[len]) == '/' || c == '\0')) {
692 (void)strlcpy(sp->f_mntonname, 692 (void)strlcpy(sp->f_mntonname,
693 c == '\0' ? "/" : &sp->f_mntonname[len], 693 c == '\0' ? "/" : &sp->f_mntonname[len],
694 sizeof(sp->f_mntonname)); 694 sizeof(sp->f_mntonname));
695 } else { 695 } else {
696 if (root) 696 if (root)
697 (void)strlcpy(sp->f_mntonname, "/", 697 (void)strlcpy(sp->f_mntonname, "/",
698 sizeof(sp->f_mntonname)); 698 sizeof(sp->f_mntonname));
699 else 699 else
700 error = EPERM; 700 error = EPERM;
701 } 701 }
702 } 702 }
703 PNBUF_PUT(path); 703 PNBUF_PUT(path);
704 } 704 }
705 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 705 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
706 return error; 706 return error;
707} 707}
708 708
709/* 709/*
710 * Get filesystem statistics by path. 710 * Get filesystem statistics by path.
711 */ 711 */
712int 712int
713do_sys_pstatvfs(struct lwp *l, const char *path, int flags, struct statvfs *sb) 713do_sys_pstatvfs(struct lwp *l, const char *path, int flags, struct statvfs *sb)
714{ 714{
715 struct mount *mp; 715 struct mount *mp;
716 int error; 716 int error;
717 struct vnode *vp; 717 struct vnode *vp;
718 718
719 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp); 719 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
720 if (error != 0) 720 if (error != 0)
721 return error; 721 return error;
722 mp = vp->v_mount; 722 mp = vp->v_mount;
723 error = dostatvfs(mp, sb, l, flags, 1); 723 error = dostatvfs(mp, sb, l, flags, 1);
724 vrele(vp); 724 vrele(vp);
725 return error; 725 return error;
726} 726}
727 727
728/* ARGSUSED */ 728/* ARGSUSED */
729int 729int
730sys_statvfs1(struct lwp *l, const struct sys_statvfs1_args *uap, register_t *retval) 730sys_statvfs1(struct lwp *l, const struct sys_statvfs1_args *uap, register_t *retval)
731{ 731{
732 /* { 732 /* {
733 syscallarg(const char *) path; 733 syscallarg(const char *) path;
734 syscallarg(struct statvfs *) buf; 734 syscallarg(struct statvfs *) buf;
735 syscallarg(int) flags; 735 syscallarg(int) flags;
736 } */ 736 } */
737 struct statvfs *sb; 737 struct statvfs *sb;
738 int error; 738 int error;
739 739
740 sb = STATVFSBUF_GET(); 740 sb = STATVFSBUF_GET();
741 error = do_sys_pstatvfs(l, SCARG(uap, path), SCARG(uap, flags), sb); 741 error = do_sys_pstatvfs(l, SCARG(uap, path), SCARG(uap, flags), sb);
742 if (error == 0) 742 if (error == 0)
743 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 743 error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
744 STATVFSBUF_PUT(sb); 744 STATVFSBUF_PUT(sb);
745 return error; 745 return error;
746} 746}
747 747
748/* 748/*
749 * Get filesystem statistics by fd. 749 * Get filesystem statistics by fd.
750 */ 750 */
751int 751int
752do_sys_fstatvfs(struct lwp *l, int fd, int flags, struct statvfs *sb) 752do_sys_fstatvfs(struct lwp *l, int fd, int flags, struct statvfs *sb)
753{ 753{
754 file_t *fp; 754 file_t *fp;
755 struct mount *mp; 755 struct mount *mp;
756 int error; 756 int error;
757 757
758 /* fd_getvnode() will use the descriptor for us */ 758 /* fd_getvnode() will use the descriptor for us */
759 if ((error = fd_getvnode(fd, &fp)) != 0) 759 if ((error = fd_getvnode(fd, &fp)) != 0)
760 return (error); 760 return (error);
761 mp = ((struct vnode *)fp->f_data)->v_mount; 761 mp = ((struct vnode *)fp->f_data)->v_mount;
762 error = dostatvfs(mp, sb, curlwp, flags, 1); 762 error = dostatvfs(mp, sb, curlwp, flags, 1);
763 fd_putfile(fd); 763 fd_putfile(fd);
764 return error; 764 return error;
765} 765}
766 766
767/* ARGSUSED */ 767/* ARGSUSED */
768int 768int
769sys_fstatvfs1(struct lwp *l, const struct sys_fstatvfs1_args *uap, register_t *retval) 769sys_fstatvfs1(struct lwp *l, const struct sys_fstatvfs1_args *uap, register_t *retval)
770{ 770{
771 /* { 771 /* {
772 syscallarg(int) fd; 772 syscallarg(int) fd;
773 syscallarg(struct statvfs *) buf; 773 syscallarg(struct statvfs *) buf;
774 syscallarg(int) flags; 774 syscallarg(int) flags;
775 } */ 775 } */
776 struct statvfs *sb; 776 struct statvfs *sb;
777 int error; 777 int error;
778 778
779 sb = STATVFSBUF_GET(); 779 sb = STATVFSBUF_GET();
780 error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb); 780 error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb);
781 if (error == 0) 781 if (error == 0)
782 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 782 error = copyout(sb, SCARG(uap, buf), sizeof(*sb));
783 STATVFSBUF_PUT(sb); 783 STATVFSBUF_PUT(sb);
784 return error; 784 return error;
785} 785}
786 786
787 787
788/* 788/*
789 * Get statistics on all filesystems. 789 * Get statistics on all filesystems.
790 */ 790 */
791int 791int
792do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags, 792do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags,
793 int (*copyfn)(const void *, void *, size_t), size_t entry_sz, 793 int (*copyfn)(const void *, void *, size_t), size_t entry_sz,
794 register_t *retval) 794 register_t *retval)
795{ 795{
796 int root = 0; 796 int root = 0;
797 struct proc *p = l->l_proc; 797 struct proc *p = l->l_proc;
798 struct mount *mp, *nmp; 798 struct mount *mp, *nmp;
799 struct statvfs *sb; 799 struct statvfs *sb;
800 size_t count, maxcount; 800 size_t count, maxcount;
801 int error = 0; 801 int error = 0;
802 802
803 sb = STATVFSBUF_GET(); 803 sb = STATVFSBUF_GET();
804 maxcount = bufsize / entry_sz; 804 maxcount = bufsize / entry_sz;
805 mutex_enter(&mountlist_lock); 805 mutex_enter(&mountlist_lock);
806 count = 0; 806 count = 0;
807 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 807 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
808 mp = nmp) { 808 mp = nmp) {
809 if (vfs_busy(mp, &nmp)) { 809 if (vfs_busy(mp, &nmp)) {
810 continue; 810 continue;
811 } 811 }
812 if (sfsp && count < maxcount) { 812 if (sfsp && count < maxcount) {
813 error = dostatvfs(mp, sb, l, flags, 0); 813 error = dostatvfs(mp, sb, l, flags, 0);
814 if (error) { 814 if (error) {
815 vfs_unbusy(mp, false, &nmp); 815 vfs_unbusy(mp, false, &nmp);
816 error = 0; 816 error = 0;
817 continue; 817 continue;
818 } 818 }
819 error = copyfn(sb, sfsp, entry_sz); 819 error = copyfn(sb, sfsp, entry_sz);
820 if (error) { 820 if (error) {
821 vfs_unbusy(mp, false, NULL); 821 vfs_unbusy(mp, false, NULL);
822 goto out; 822 goto out;
823 } 823 }
824 sfsp = (char *)sfsp + entry_sz; 824 sfsp = (char *)sfsp + entry_sz;
825 root |= strcmp(sb->f_mntonname, "/") == 0; 825 root |= strcmp(sb->f_mntonname, "/") == 0;
826 } 826 }
827 count++; 827 count++;
828 vfs_unbusy(mp, false, &nmp); 828 vfs_unbusy(mp, false, &nmp);
829 } 829 }
830 mutex_exit(&mountlist_lock); 830 mutex_exit(&mountlist_lock);
831 831
832 if (root == 0 && p->p_cwdi->cwdi_rdir) { 832 if (root == 0 && p->p_cwdi->cwdi_rdir) {
833 /* 833 /*
834 * fake a root entry 834 * fake a root entry
835 */ 835 */
836 error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, 836 error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount,
837 sb, l, flags, 1); 837 sb, l, flags, 1);
838 if (error != 0) 838 if (error != 0)
839 goto out; 839 goto out;
840 if (sfsp) { 840 if (sfsp) {
841 error = copyfn(sb, sfsp, entry_sz); 841 error = copyfn(sb, sfsp, entry_sz);
842 if (error != 0) 842 if (error != 0)
843 goto out; 843 goto out;
844 } 844 }
845 count++; 845 count++;
846 } 846 }
847 if (sfsp && count > maxcount) 847 if (sfsp && count > maxcount)
848 *retval = maxcount; 848 *retval = maxcount;
849 else 849 else
850 *retval = count; 850 *retval = count;
851out: 851out:
852 STATVFSBUF_PUT(sb); 852 STATVFSBUF_PUT(sb);
853 return error; 853 return error;
854} 854}
855 855
856int 856int
857sys_getvfsstat(struct lwp *l, const struct sys_getvfsstat_args *uap, register_t *retval) 857sys_getvfsstat(struct lwp *l, const struct sys_getvfsstat_args *uap, register_t *retval)
858{ 858{
859 /* { 859 /* {
860 syscallarg(struct statvfs *) buf; 860 syscallarg(struct statvfs *) buf;
861 syscallarg(size_t) bufsize; 861 syscallarg(size_t) bufsize;
862 syscallarg(int) flags; 862 syscallarg(int) flags;
863 } */ 863 } */
864 864
865 return do_sys_getvfsstat(l, SCARG(uap, buf), SCARG(uap, bufsize), 865 return do_sys_getvfsstat(l, SCARG(uap, buf), SCARG(uap, bufsize),
866 SCARG(uap, flags), copyout, sizeof (struct statvfs), retval); 866 SCARG(uap, flags), copyout, sizeof (struct statvfs), retval);
867} 867}
868 868
869/* 869/*
870 * Change current working directory to a given file descriptor. 870 * Change current working directory to a given file descriptor.
871 */ 871 */
872/* ARGSUSED */ 872/* ARGSUSED */
873int 873int
874sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval) 874sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
875{ 875{
876 /* { 876 /* {
877 syscallarg(int) fd; 877 syscallarg(int) fd;
878 } */ 878 } */
879 struct proc *p = l->l_proc; 879 struct proc *p = l->l_proc;
880 struct cwdinfo *cwdi; 880 struct cwdinfo *cwdi;
881 struct vnode *vp, *tdp; 881 struct vnode *vp, *tdp;
882 struct mount *mp; 882 struct mount *mp;
883 file_t *fp; 883 file_t *fp;
884 int error, fd; 884 int error, fd;
885 885
886 /* fd_getvnode() will use the descriptor for us */ 886 /* fd_getvnode() will use the descriptor for us */
887 fd = SCARG(uap, fd); 887 fd = SCARG(uap, fd);
888 if ((error = fd_getvnode(fd, &fp)) != 0) 888 if ((error = fd_getvnode(fd, &fp)) != 0)
889 return (error); 889 return (error);
890 vp = fp->f_data; 890 vp = fp->f_data;
891 891
892 vref(vp); 892 vref(vp);
893 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 893 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
894 if (vp->v_type != VDIR) 894 if (vp->v_type != VDIR)
895 error = ENOTDIR; 895 error = ENOTDIR;
896 else 896 else
897 error = VOP_ACCESS(vp, VEXEC, l->l_cred); 897 error = VOP_ACCESS(vp, VEXEC, l->l_cred);
898 if (error) { 898 if (error) {
899 vput(vp); 899 vput(vp);
900 goto out; 900 goto out;
901 } 901 }
902 while ((mp = vp->v_mountedhere) != NULL) { 902 while ((mp = vp->v_mountedhere) != NULL) {
903 error = vfs_busy(mp, NULL); 903 error = vfs_busy(mp, NULL);
904 vput(vp); 904 vput(vp);
905 if (error != 0) 905 if (error != 0)
906 goto out; 906 goto out;
907 error = VFS_ROOT(mp, &tdp); 907 error = VFS_ROOT(mp, &tdp);
908 vfs_unbusy(mp, false, NULL); 908 vfs_unbusy(mp, false, NULL);
909 if (error) 909 if (error)
910 goto out; 910 goto out;
911 vp = tdp; 911 vp = tdp;
912 } 912 }
913 VOP_UNLOCK(vp); 913 VOP_UNLOCK(vp);
914 914
915 /* 915 /*
916 * Disallow changing to a directory not under the process's 916 * Disallow changing to a directory not under the process's
917 * current root directory (if there is one). 917 * current root directory (if there is one).
918 */ 918 */
919 cwdi = p->p_cwdi; 919 cwdi = p->p_cwdi;
920 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 920 rw_enter(&cwdi->cwdi_lock, RW_WRITER);
921 if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) { 921 if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) {
922 vrele(vp); 922 vrele(vp);
923 error = EPERM; /* operation not permitted */ 923 error = EPERM; /* operation not permitted */
924 } else { 924 } else {
925 vrele(cwdi->cwdi_cdir); 925 vrele(cwdi->cwdi_cdir);
926 cwdi->cwdi_cdir = vp; 926 cwdi->cwdi_cdir = vp;
927 } 927 }
928 rw_exit(&cwdi->cwdi_lock); 928 rw_exit(&cwdi->cwdi_lock);
929 929
930 out: 930 out:
931 fd_putfile(fd); 931 fd_putfile(fd);
932 return (error); 932 return (error);
933} 933}
934 934
935/* 935/*
936 * Change this process's notion of the root directory to a given file 936 * Change this process's notion of the root directory to a given file
937 * descriptor. 937 * descriptor.
938 */ 938 */
939int 939int
940sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retval) 940sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retval)
941{ 941{
942 struct proc *p = l->l_proc; 942 struct proc *p = l->l_proc;
943 struct vnode *vp; 943 struct vnode *vp;
944 file_t *fp; 944 file_t *fp;
945 int error, fd = SCARG(uap, fd); 945 int error, fd = SCARG(uap, fd);
946 946
947 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT, 947 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
948 KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, NULL, NULL, NULL)) != 0) 948 KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, NULL, NULL, NULL)) != 0)
949 return error; 949 return error;
950 /* fd_getvnode() will use the descriptor for us */ 950 /* fd_getvnode() will use the descriptor for us */
951 if ((error = fd_getvnode(fd, &fp)) != 0) 951 if ((error = fd_getvnode(fd, &fp)) != 0)
952 return error; 952 return error;
953 vp = fp->f_data; 953 vp = fp->f_data;
954 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 954 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
955 if (vp->v_type != VDIR) 955 if (vp->v_type != VDIR)
956 error = ENOTDIR; 956 error = ENOTDIR;
957 else 957 else
958 error = VOP_ACCESS(vp, VEXEC, l->l_cred); 958 error = VOP_ACCESS(vp, VEXEC, l->l_cred);
959 VOP_UNLOCK(vp); 959 VOP_UNLOCK(vp);
960 if (error) 960 if (error)
961 goto out; 961 goto out;
962 vref(vp); 962 vref(vp);
963 963
964 change_root(p->p_cwdi, vp, l); 964 change_root(p->p_cwdi, vp, l);
965 965
966 out: 966 out:
967 fd_putfile(fd); 967 fd_putfile(fd);
968 return (error); 968 return (error);
969} 969}
970 970
971/* 971/*
972 * Change current working directory (``.''). 972 * Change current working directory (``.'').
973 */ 973 */
974/* ARGSUSED */ 974/* ARGSUSED */
975int 975int
976sys_chdir(struct lwp *l, const struct sys_chdir_args *uap, register_t *retval) 976sys_chdir(struct lwp *l, const struct sys_chdir_args *uap, register_t *retval)
977{ 977{
978 /* { 978 /* {
979 syscallarg(const char *) path; 979 syscallarg(const char *) path;
980 } */ 980 } */
981 struct proc *p = l->l_proc; 981 struct proc *p = l->l_proc;
982 struct cwdinfo *cwdi; 982 struct cwdinfo *cwdi;
983 int error; 983 int error;
984 struct vnode *vp; 984 struct vnode *vp;
985 985
986 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, 986 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
987 &vp, l)) != 0) 987 &vp, l)) != 0)
988 return (error); 988 return (error);
989 cwdi = p->p_cwdi; 989 cwdi = p->p_cwdi;
990 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 990 rw_enter(&cwdi->cwdi_lock, RW_WRITER);
991 vrele(cwdi->cwdi_cdir); 991 vrele(cwdi->cwdi_cdir);
992 cwdi->cwdi_cdir = vp; 992 cwdi->cwdi_cdir = vp;
993 rw_exit(&cwdi->cwdi_lock); 993 rw_exit(&cwdi->cwdi_lock);
994 return (0); 994 return (0);
995} 995}
996 996
997/* 997/*
998 * Change notion of root (``/'') directory. 998 * Change notion of root (``/'') directory.
999 */ 999 */
1000/* ARGSUSED */ 1000/* ARGSUSED */
1001int 1001int
1002sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval) 1002sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval)
1003{ 1003{
1004 /* { 1004 /* {
1005 syscallarg(const char *) path; 1005 syscallarg(const char *) path;
1006 } */ 1006 } */
1007 struct proc *p = l->l_proc; 1007 struct proc *p = l->l_proc;
1008 int error; 1008 int error;
1009 struct vnode *vp; 1009 struct vnode *vp;
1010 1010
1011 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT, 1011 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT,
1012 KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0) 1012 KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0)
1013 return (error); 1013 return (error);
1014 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, 1014 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE,
1015 &vp, l)) != 0) 1015 &vp, l)) != 0)
1016 return (error); 1016 return (error);
1017 1017
1018 change_root(p->p_cwdi, vp, l); 1018 change_root(p->p_cwdi, vp, l);
1019 1019
1020 return (0); 1020 return (0);
1021} 1021}
1022 1022
1023/* 1023/*
1024 * Common routine for chroot and fchroot. 1024 * Common routine for chroot and fchroot.
1025 * NB: callers need to properly authorize the change root operation. 1025 * NB: callers need to properly authorize the change root operation.
1026 */ 1026 */
1027void 1027void
1028change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l) 1028change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l)
1029{ 1029{
1030 1030
1031 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 1031 rw_enter(&cwdi->cwdi_lock, RW_WRITER);
1032 if (cwdi->cwdi_rdir != NULL) 1032 if (cwdi->cwdi_rdir != NULL)
1033 vrele(cwdi->cwdi_rdir); 1033 vrele(cwdi->cwdi_rdir);
1034 cwdi->cwdi_rdir = vp; 1034 cwdi->cwdi_rdir = vp;
1035 1035
1036 /* 1036 /*
1037 * Prevent escaping from chroot by putting the root under 1037 * Prevent escaping from chroot by putting the root under
1038 * the working directory. Silently chdir to / if we aren't 1038 * the working directory. Silently chdir to / if we aren't
1039 * already there. 1039 * already there.
1040 */ 1040 */
1041 if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) { 1041 if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) {
1042 /* 1042 /*
1043 * XXX would be more failsafe to change directory to a 1043 * XXX would be more failsafe to change directory to a
1044 * deadfs node here instead 1044 * deadfs node here instead
1045 */ 1045 */
1046 vrele(cwdi->cwdi_cdir); 1046 vrele(cwdi->cwdi_cdir);
1047 vref(vp); 1047 vref(vp);
1048 cwdi->cwdi_cdir = vp; 1048 cwdi->cwdi_cdir = vp;
1049 } 1049 }
1050 rw_exit(&cwdi->cwdi_lock); 1050 rw_exit(&cwdi->cwdi_lock);
1051} 1051}
1052 1052
1053/* 1053/*
1054 * Common routine for chroot and chdir. 1054 * Common routine for chroot and chdir.
1055 * XXX "where" should be enum uio_seg 1055 * XXX "where" should be enum uio_seg
1056 */ 1056 */
1057int 1057int
1058chdir_lookup(const char *path, int where, struct vnode **vpp, struct lwp *l) 1058chdir_lookup(const char *path, int where, struct vnode **vpp, struct lwp *l)
1059{ 1059{
1060 struct pathbuf *pb; 1060 struct pathbuf *pb;
1061 struct nameidata nd; 1061 struct nameidata nd;
1062 int error; 1062 int error;
1063 1063
1064 error = pathbuf_maybe_copyin(path, where, &pb); 1064 error = pathbuf_maybe_copyin(path, where, &pb);
1065 if (error) { 1065 if (error) {
1066 return error; 1066 return error;
1067 } 1067 }
1068 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 1068 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb);
1069 if ((error = namei(&nd)) != 0) { 1069 if ((error = namei(&nd)) != 0) {
1070 pathbuf_destroy(pb); 1070 pathbuf_destroy(pb);
1071 return error; 1071 return error;
1072 } 1072 }
@@ -2573,1285 +2573,1284 @@ sys_chflags(struct lwp *l, const struct  @@ -2573,1285 +2573,1284 @@ sys_chflags(struct lwp *l, const struct
2573 error = namei_simple_user(SCARG(uap, path), 2573 error = namei_simple_user(SCARG(uap, path),
2574 NSM_FOLLOW_TRYEMULROOT, &vp); 2574 NSM_FOLLOW_TRYEMULROOT, &vp);
2575 if (error != 0) 2575 if (error != 0)
2576 return (error); 2576 return (error);
2577 error = change_flags(vp, SCARG(uap, flags), l); 2577 error = change_flags(vp, SCARG(uap, flags), l);
2578 vput(vp); 2578 vput(vp);
2579 return (error); 2579 return (error);
2580} 2580}
2581 2581
2582/* 2582/*
2583 * Change flags of a file given a file descriptor. 2583 * Change flags of a file given a file descriptor.
2584 */ 2584 */
2585/* ARGSUSED */ 2585/* ARGSUSED */
2586int 2586int
2587sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval) 2587sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval)
2588{ 2588{
2589 /* { 2589 /* {
2590 syscallarg(int) fd; 2590 syscallarg(int) fd;
2591 syscallarg(u_long) flags; 2591 syscallarg(u_long) flags;
2592 } */ 2592 } */
2593 struct vnode *vp; 2593 struct vnode *vp;
2594 file_t *fp; 2594 file_t *fp;
2595 int error; 2595 int error;
2596 2596
2597 /* fd_getvnode() will use the descriptor for us */ 2597 /* fd_getvnode() will use the descriptor for us */
2598 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 2598 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
2599 return (error); 2599 return (error);
2600 vp = fp->f_data; 2600 vp = fp->f_data;
2601 error = change_flags(vp, SCARG(uap, flags), l); 2601 error = change_flags(vp, SCARG(uap, flags), l);
2602 VOP_UNLOCK(vp); 2602 VOP_UNLOCK(vp);
2603 fd_putfile(SCARG(uap, fd)); 2603 fd_putfile(SCARG(uap, fd));
2604 return (error); 2604 return (error);
2605} 2605}
2606 2606
2607/* 2607/*
2608 * Change flags of a file given a path name; this version does 2608 * Change flags of a file given a path name; this version does
2609 * not follow links. 2609 * not follow links.
2610 */ 2610 */
2611int 2611int
2612sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval) 2612sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval)
2613{ 2613{
2614 /* { 2614 /* {
2615 syscallarg(const char *) path; 2615 syscallarg(const char *) path;
2616 syscallarg(u_long) flags; 2616 syscallarg(u_long) flags;
2617 } */ 2617 } */
2618 struct vnode *vp; 2618 struct vnode *vp;
2619 int error; 2619 int error;
2620 2620
2621 error = namei_simple_user(SCARG(uap, path), 2621 error = namei_simple_user(SCARG(uap, path),
2622 NSM_NOFOLLOW_TRYEMULROOT, &vp); 2622 NSM_NOFOLLOW_TRYEMULROOT, &vp);
2623 if (error != 0) 2623 if (error != 0)
2624 return (error); 2624 return (error);
2625 error = change_flags(vp, SCARG(uap, flags), l); 2625 error = change_flags(vp, SCARG(uap, flags), l);
2626 vput(vp); 2626 vput(vp);
2627 return (error); 2627 return (error);
2628} 2628}
2629 2629
2630/* 2630/*
2631 * Common routine to change flags of a file. 2631 * Common routine to change flags of a file.
2632 */ 2632 */
2633int 2633int
2634change_flags(struct vnode *vp, u_long flags, struct lwp *l) 2634change_flags(struct vnode *vp, u_long flags, struct lwp *l)
2635{ 2635{
2636 struct vattr vattr; 2636 struct vattr vattr;
2637 int error; 2637 int error;
2638 2638
2639 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2639 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2640 /* 2640 /*
2641 * Non-superusers cannot change the flags on devices, even if they 2641 * Non-superusers cannot change the flags on devices, even if they
2642 * own them. 2642 * own them.
2643 */ 2643 */
2644 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) { 2644 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) {
2645 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) 2645 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
2646 goto out; 2646 goto out;
2647 if (vattr.va_type == VCHR || vattr.va_type == VBLK) { 2647 if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
2648 error = EINVAL; 2648 error = EINVAL;
2649 goto out; 2649 goto out;
2650 } 2650 }
2651 } 2651 }
2652 vattr_null(&vattr); 2652 vattr_null(&vattr);
2653 vattr.va_flags = flags; 2653 vattr.va_flags = flags;
2654 error = VOP_SETATTR(vp, &vattr, l->l_cred); 2654 error = VOP_SETATTR(vp, &vattr, l->l_cred);
2655out: 2655out:
2656 return (error); 2656 return (error);
2657} 2657}
2658 2658
2659/* 2659/*
2660 * Change mode of a file given path name; this version follows links. 2660 * Change mode of a file given path name; this version follows links.
2661 */ 2661 */
2662/* ARGSUSED */ 2662/* ARGSUSED */
2663int 2663int
2664sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval) 2664sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval)
2665{ 2665{
2666 /* { 2666 /* {
2667 syscallarg(const char *) path; 2667 syscallarg(const char *) path;
2668 syscallarg(int) mode; 2668 syscallarg(int) mode;
2669 } */ 2669 } */
2670 int error; 2670 int error;
2671 struct vnode *vp; 2671 struct vnode *vp;
2672 2672
2673 error = namei_simple_user(SCARG(uap, path), 2673 error = namei_simple_user(SCARG(uap, path),
2674 NSM_FOLLOW_TRYEMULROOT, &vp); 2674 NSM_FOLLOW_TRYEMULROOT, &vp);
2675 if (error != 0) 2675 if (error != 0)
2676 return (error); 2676 return (error);
2677 2677
2678 error = change_mode(vp, SCARG(uap, mode), l); 2678 error = change_mode(vp, SCARG(uap, mode), l);
2679 2679
2680 vrele(vp); 2680 vrele(vp);
2681 return (error); 2681 return (error);
2682} 2682}
2683 2683
2684/* 2684/*
2685 * Change mode of a file given a file descriptor. 2685 * Change mode of a file given a file descriptor.
2686 */ 2686 */
2687/* ARGSUSED */ 2687/* ARGSUSED */
2688int 2688int
2689sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval) 2689sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval)
2690{ 2690{
2691 /* { 2691 /* {
2692 syscallarg(int) fd; 2692 syscallarg(int) fd;
2693 syscallarg(int) mode; 2693 syscallarg(int) mode;
2694 } */ 2694 } */
2695 file_t *fp; 2695 file_t *fp;
2696 int error; 2696 int error;
2697 2697
2698 /* fd_getvnode() will use the descriptor for us */ 2698 /* fd_getvnode() will use the descriptor for us */
2699 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 2699 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
2700 return (error); 2700 return (error);
2701 error = change_mode(fp->f_data, SCARG(uap, mode), l); 2701 error = change_mode(fp->f_data, SCARG(uap, mode), l);
2702 fd_putfile(SCARG(uap, fd)); 2702 fd_putfile(SCARG(uap, fd));
2703 return (error); 2703 return (error);
2704} 2704}
2705 2705
2706int 2706int
2707sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap, 2707sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap,
2708 register_t *retval) 2708 register_t *retval)
2709{ 2709{
2710 /* { 2710 /* {
2711 syscallarg(int) fd; 2711 syscallarg(int) fd;
2712 syscallarg(const char *) path; 2712 syscallarg(const char *) path;
2713 syscallarg(int) mode; 2713 syscallarg(int) mode;
2714 syscallarg(int) flag; 2714 syscallarg(int) flag;
2715 } */ 2715 } */
2716 2716
2717 return ENOSYS; 2717 return ENOSYS;
2718} 2718}
2719 2719
2720/* 2720/*
2721 * Change mode of a file given path name; this version does not follow links. 2721 * Change mode of a file given path name; this version does not follow links.
2722 */ 2722 */
2723/* ARGSUSED */ 2723/* ARGSUSED */
2724int 2724int
2725sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval) 2725sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval)
2726{ 2726{
2727 /* { 2727 /* {
2728 syscallarg(const char *) path; 2728 syscallarg(const char *) path;
2729 syscallarg(int) mode; 2729 syscallarg(int) mode;
2730 } */ 2730 } */
2731 int error; 2731 int error;
2732 struct vnode *vp; 2732 struct vnode *vp;
2733 2733
2734 error = namei_simple_user(SCARG(uap, path), 2734 error = namei_simple_user(SCARG(uap, path),
2735 NSM_NOFOLLOW_TRYEMULROOT, &vp); 2735 NSM_NOFOLLOW_TRYEMULROOT, &vp);
2736 if (error != 0) 2736 if (error != 0)
2737 return (error); 2737 return (error);
2738 2738
2739 error = change_mode(vp, SCARG(uap, mode), l); 2739 error = change_mode(vp, SCARG(uap, mode), l);
2740 2740
2741 vrele(vp); 2741 vrele(vp);
2742 return (error); 2742 return (error);
2743} 2743}
2744 2744
2745/* 2745/*
2746 * Common routine to set mode given a vnode. 2746 * Common routine to set mode given a vnode.
2747 */ 2747 */
2748static int 2748static int
2749change_mode(struct vnode *vp, int mode, struct lwp *l) 2749change_mode(struct vnode *vp, int mode, struct lwp *l)
2750{ 2750{
2751 struct vattr vattr; 2751 struct vattr vattr;
2752 int error; 2752 int error;
2753 2753
2754 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2754 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2755 vattr_null(&vattr); 2755 vattr_null(&vattr);
2756 vattr.va_mode = mode & ALLPERMS; 2756 vattr.va_mode = mode & ALLPERMS;
2757 error = VOP_SETATTR(vp, &vattr, l->l_cred); 2757 error = VOP_SETATTR(vp, &vattr, l->l_cred);
2758 VOP_UNLOCK(vp); 2758 VOP_UNLOCK(vp);
2759 return (error); 2759 return (error);
2760} 2760}
2761 2761
2762/* 2762/*
2763 * Set ownership given a path name; this version follows links. 2763 * Set ownership given a path name; this version follows links.
2764 */ 2764 */
2765/* ARGSUSED */ 2765/* ARGSUSED */
2766int 2766int
2767sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval) 2767sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval)
2768{ 2768{
2769 /* { 2769 /* {
2770 syscallarg(const char *) path; 2770 syscallarg(const char *) path;
2771 syscallarg(uid_t) uid; 2771 syscallarg(uid_t) uid;
2772 syscallarg(gid_t) gid; 2772 syscallarg(gid_t) gid;
2773 } */ 2773 } */
2774 int error; 2774 int error;
2775 struct vnode *vp; 2775 struct vnode *vp;
2776 2776
2777 error = namei_simple_user(SCARG(uap, path), 2777 error = namei_simple_user(SCARG(uap, path),
2778 NSM_FOLLOW_TRYEMULROOT, &vp); 2778 NSM_FOLLOW_TRYEMULROOT, &vp);
2779 if (error != 0) 2779 if (error != 0)
2780 return (error); 2780 return (error);
2781 2781
2782 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 2782 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
2783 2783
2784 vrele(vp); 2784 vrele(vp);
2785 return (error); 2785 return (error);
2786} 2786}
2787 2787
2788/* 2788/*
2789 * Set ownership given a path name; this version follows links. 2789 * Set ownership given a path name; this version follows links.
2790 * Provides POSIX semantics. 2790 * Provides POSIX semantics.
2791 */ 2791 */
2792/* ARGSUSED */ 2792/* ARGSUSED */
2793int 2793int
2794sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval) 2794sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval)
2795{ 2795{
2796 /* { 2796 /* {
2797 syscallarg(const char *) path; 2797 syscallarg(const char *) path;
2798 syscallarg(uid_t) uid; 2798 syscallarg(uid_t) uid;
2799 syscallarg(gid_t) gid; 2799 syscallarg(gid_t) gid;
2800 } */ 2800 } */
2801 int error; 2801 int error;
2802 struct vnode *vp; 2802 struct vnode *vp;
2803 2803
2804 error = namei_simple_user(SCARG(uap, path), 2804 error = namei_simple_user(SCARG(uap, path),
2805 NSM_FOLLOW_TRYEMULROOT, &vp); 2805 NSM_FOLLOW_TRYEMULROOT, &vp);
2806 if (error != 0) 2806 if (error != 0)
2807 return (error); 2807 return (error);
2808 2808
2809 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 2809 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
2810 2810
2811 vrele(vp); 2811 vrele(vp);
2812 return (error); 2812 return (error);
2813} 2813}
2814 2814
2815/* 2815/*
2816 * Set ownership given a file descriptor. 2816 * Set ownership given a file descriptor.
2817 */ 2817 */
2818/* ARGSUSED */ 2818/* ARGSUSED */
2819int 2819int
2820sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval) 2820sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval)
2821{ 2821{
2822 /* { 2822 /* {
2823 syscallarg(int) fd; 2823 syscallarg(int) fd;
2824 syscallarg(uid_t) uid; 2824 syscallarg(uid_t) uid;
2825 syscallarg(gid_t) gid; 2825 syscallarg(gid_t) gid;
2826 } */ 2826 } */
2827 int error; 2827 int error;
2828 file_t *fp; 2828 file_t *fp;
2829 2829
2830 /* fd_getvnode() will use the descriptor for us */ 2830 /* fd_getvnode() will use the descriptor for us */
2831 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 2831 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
2832 return (error); 2832 return (error);
2833 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid), 2833 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid),
2834 l, 0); 2834 l, 0);
2835 fd_putfile(SCARG(uap, fd)); 2835 fd_putfile(SCARG(uap, fd));
2836 return (error); 2836 return (error);
2837} 2837}
2838 2838
2839int 2839int
2840sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap, 2840sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap,
2841 register_t *retval) 2841 register_t *retval)
2842{ 2842{
2843 /* { 2843 /* {
2844 syscallarg(int) fd; 2844 syscallarg(int) fd;
2845 syscallarg(const char *) path; 2845 syscallarg(const char *) path;
2846 syscallarg(uid_t) uid; 2846 syscallarg(uid_t) uid;
2847 syscallarg(gid_t) gid; 2847 syscallarg(gid_t) gid;
2848 syscallarg(int) flag; 2848 syscallarg(int) flag;
2849 } */ 2849 } */
2850 2850
2851 return ENOSYS; 2851 return ENOSYS;
2852} 2852}
2853 2853
2854/* 2854/*
2855 * Set ownership given a file descriptor, providing POSIX/XPG semantics. 2855 * Set ownership given a file descriptor, providing POSIX/XPG semantics.
2856 */ 2856 */
2857/* ARGSUSED */ 2857/* ARGSUSED */
2858int 2858int
2859sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval) 2859sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval)
2860{ 2860{
2861 /* { 2861 /* {
2862 syscallarg(int) fd; 2862 syscallarg(int) fd;
2863 syscallarg(uid_t) uid; 2863 syscallarg(uid_t) uid;
2864 syscallarg(gid_t) gid; 2864 syscallarg(gid_t) gid;
2865 } */ 2865 } */
2866 int error; 2866 int error;
2867 file_t *fp; 2867 file_t *fp;
2868 2868
2869 /* fd_getvnode() will use the descriptor for us */ 2869 /* fd_getvnode() will use the descriptor for us */
2870 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 2870 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
2871 return (error); 2871 return (error);
2872 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid), 2872 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid),
2873 l, 1); 2873 l, 1);
2874 fd_putfile(SCARG(uap, fd)); 2874 fd_putfile(SCARG(uap, fd));
2875 return (error); 2875 return (error);
2876} 2876}
2877 2877
2878/* 2878/*
2879 * Set ownership given a path name; this version does not follow links. 2879 * Set ownership given a path name; this version does not follow links.
2880 */ 2880 */
2881/* ARGSUSED */ 2881/* ARGSUSED */
2882int 2882int
2883sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval) 2883sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval)
2884{ 2884{
2885 /* { 2885 /* {
2886 syscallarg(const char *) path; 2886 syscallarg(const char *) path;
2887 syscallarg(uid_t) uid; 2887 syscallarg(uid_t) uid;
2888 syscallarg(gid_t) gid; 2888 syscallarg(gid_t) gid;
2889 } */ 2889 } */
2890 int error; 2890 int error;
2891 struct vnode *vp; 2891 struct vnode *vp;
2892 2892
2893 error = namei_simple_user(SCARG(uap, path), 2893 error = namei_simple_user(SCARG(uap, path),
2894 NSM_NOFOLLOW_TRYEMULROOT, &vp); 2894 NSM_NOFOLLOW_TRYEMULROOT, &vp);
2895 if (error != 0) 2895 if (error != 0)
2896 return (error); 2896 return (error);
2897 2897
2898 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 2898 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0);
2899 2899
2900 vrele(vp); 2900 vrele(vp);
2901 return (error); 2901 return (error);
2902} 2902}
2903 2903
2904/* 2904/*
2905 * Set ownership given a path name; this version does not follow links. 2905 * Set ownership given a path name; this version does not follow links.
2906 * Provides POSIX/XPG semantics. 2906 * Provides POSIX/XPG semantics.
2907 */ 2907 */
2908/* ARGSUSED */ 2908/* ARGSUSED */
2909int 2909int
2910sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval) 2910sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval)
2911{ 2911{
2912 /* { 2912 /* {
2913 syscallarg(const char *) path; 2913 syscallarg(const char *) path;
2914 syscallarg(uid_t) uid; 2914 syscallarg(uid_t) uid;
2915 syscallarg(gid_t) gid; 2915 syscallarg(gid_t) gid;
2916 } */ 2916 } */
2917 int error; 2917 int error;
2918 struct vnode *vp; 2918 struct vnode *vp;
2919 2919
2920 error = namei_simple_user(SCARG(uap, path), 2920 error = namei_simple_user(SCARG(uap, path),
2921 NSM_NOFOLLOW_TRYEMULROOT, &vp); 2921 NSM_NOFOLLOW_TRYEMULROOT, &vp);
2922 if (error != 0) 2922 if (error != 0)
2923 return (error); 2923 return (error);
2924 2924
2925 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 2925 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1);
2926 2926
2927 vrele(vp); 2927 vrele(vp);
2928 return (error); 2928 return (error);
2929} 2929}
2930 2930
2931/* 2931/*
2932 * Common routine to set ownership given a vnode. 2932 * Common routine to set ownership given a vnode.
2933 */ 2933 */
2934static int 2934static int
2935change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l, 2935change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l,
2936 int posix_semantics) 2936 int posix_semantics)
2937{ 2937{
2938 struct vattr vattr; 2938 struct vattr vattr;
2939 mode_t newmode; 2939 mode_t newmode;
2940 int error; 2940 int error;
2941 2941
2942 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2942 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2943 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) 2943 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0)
2944 goto out; 2944 goto out;
2945 2945
2946#define CHANGED(x) ((int)(x) != -1) 2946#define CHANGED(x) ((int)(x) != -1)
2947 newmode = vattr.va_mode; 2947 newmode = vattr.va_mode;
2948 if (posix_semantics) { 2948 if (posix_semantics) {
2949 /* 2949 /*
2950 * POSIX/XPG semantics: if the caller is not the super-user, 2950 * POSIX/XPG semantics: if the caller is not the super-user,
2951 * clear set-user-id and set-group-id bits. Both POSIX and 2951 * clear set-user-id and set-group-id bits. Both POSIX and
2952 * the XPG consider the behaviour for calls by the super-user 2952 * the XPG consider the behaviour for calls by the super-user
2953 * implementation-defined; we leave the set-user-id and set- 2953 * implementation-defined; we leave the set-user-id and set-
2954 * group-id settings intact in that case. 2954 * group-id settings intact in that case.
2955 */ 2955 */
2956 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, 2956 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
2957 NULL) != 0) 2957 NULL) != 0)
2958 newmode &= ~(S_ISUID | S_ISGID); 2958 newmode &= ~(S_ISUID | S_ISGID);
2959 } else { 2959 } else {
2960 /* 2960 /*
2961 * NetBSD semantics: when changing owner and/or group, 2961 * NetBSD semantics: when changing owner and/or group,
2962 * clear the respective bit(s). 2962 * clear the respective bit(s).
2963 */ 2963 */
2964 if (CHANGED(uid)) 2964 if (CHANGED(uid))
2965 newmode &= ~S_ISUID; 2965 newmode &= ~S_ISUID;
2966 if (CHANGED(gid)) 2966 if (CHANGED(gid))
2967 newmode &= ~S_ISGID; 2967 newmode &= ~S_ISGID;
2968 } 2968 }
2969 /* Update va_mode iff altered. */ 2969 /* Update va_mode iff altered. */
2970 if (vattr.va_mode == newmode) 2970 if (vattr.va_mode == newmode)
2971 newmode = VNOVAL; 2971 newmode = VNOVAL;
2972 2972
2973 vattr_null(&vattr); 2973 vattr_null(&vattr);
2974 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL; 2974 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL;
2975 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL; 2975 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL;
2976 vattr.va_mode = newmode; 2976 vattr.va_mode = newmode;
2977 error = VOP_SETATTR(vp, &vattr, l->l_cred); 2977 error = VOP_SETATTR(vp, &vattr, l->l_cred);
2978#undef CHANGED 2978#undef CHANGED
2979 2979
2980out: 2980out:
2981 VOP_UNLOCK(vp); 2981 VOP_UNLOCK(vp);
2982 return (error); 2982 return (error);
2983} 2983}
2984 2984
2985/* 2985/*
2986 * Set the access and modification times given a path name; this 2986 * Set the access and modification times given a path name; this
2987 * version follows links. 2987 * version follows links.
2988 */ 2988 */
2989/* ARGSUSED */ 2989/* ARGSUSED */
2990int 2990int
2991sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap, 2991sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap,
2992 register_t *retval) 2992 register_t *retval)
2993{ 2993{
2994 /* { 2994 /* {
2995 syscallarg(const char *) path; 2995 syscallarg(const char *) path;
2996 syscallarg(const struct timeval *) tptr; 2996 syscallarg(const struct timeval *) tptr;
2997 } */ 2997 } */
2998 2998
2999 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 2999 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
3000 SCARG(uap, tptr), UIO_USERSPACE); 3000 SCARG(uap, tptr), UIO_USERSPACE);
3001} 3001}
3002 3002
3003/* 3003/*
3004 * Set the access and modification times given a file descriptor. 3004 * Set the access and modification times given a file descriptor.
3005 */ 3005 */
3006/* ARGSUSED */ 3006/* ARGSUSED */
3007int 3007int
3008sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap, 3008sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap,
3009 register_t *retval) 3009 register_t *retval)
3010{ 3010{
3011 /* { 3011 /* {
3012 syscallarg(int) fd; 3012 syscallarg(int) fd;
3013 syscallarg(const struct timeval *) tptr; 3013 syscallarg(const struct timeval *) tptr;
3014 } */ 3014 } */
3015 int error; 3015 int error;
3016 file_t *fp; 3016 file_t *fp;
3017 3017
3018 /* fd_getvnode() will use the descriptor for us */ 3018 /* fd_getvnode() will use the descriptor for us */
3019 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3019 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3020 return (error); 3020 return (error);
3021 error = do_sys_utimes(l, fp->f_data, NULL, 0, SCARG(uap, tptr), 3021 error = do_sys_utimes(l, fp->f_data, NULL, 0, SCARG(uap, tptr),
3022 UIO_USERSPACE); 3022 UIO_USERSPACE);
3023 fd_putfile(SCARG(uap, fd)); 3023 fd_putfile(SCARG(uap, fd));
3024 return (error); 3024 return (error);
3025} 3025}
3026 3026
3027int 3027int
3028sys_futimens(struct lwp *l, const struct sys_futimens_args *uap, 3028sys_futimens(struct lwp *l, const struct sys_futimens_args *uap,
3029 register_t *retval) 3029 register_t *retval)
3030{ 3030{
3031 /* { 3031 /* {
3032 syscallarg(int) fd; 3032 syscallarg(int) fd;
3033 syscallarg(const struct timespec *) tptr; 3033 syscallarg(const struct timespec *) tptr;
3034 } */ 3034 } */
3035 int error; 3035 int error;
3036 file_t *fp; 3036 file_t *fp;
3037 3037
3038 /* fd_getvnode() will use the descriptor for us */ 3038 /* fd_getvnode() will use the descriptor for us */
3039 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3039 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3040 return (error); 3040 return (error);
3041 error = do_sys_utimens(l, fp->f_data, NULL, 0, SCARG(uap, tptr), 3041 error = do_sys_utimens(l, fp->f_data, NULL, 0, SCARG(uap, tptr),
3042 UIO_USERSPACE); 3042 UIO_USERSPACE);
3043 fd_putfile(SCARG(uap, fd)); 3043 fd_putfile(SCARG(uap, fd));
3044 return (error); 3044 return (error);
3045} 3045}
3046 3046
3047/* 3047/*
3048 * Set the access and modification times given a path name; this 3048 * Set the access and modification times given a path name; this
3049 * version does not follow links. 3049 * version does not follow links.
3050 */ 3050 */
3051int 3051int
3052sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap, 3052sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap,
3053 register_t *retval) 3053 register_t *retval)
3054{ 3054{
3055 /* { 3055 /* {
3056 syscallarg(const char *) path; 3056 syscallarg(const char *) path;
3057 syscallarg(const struct timeval *) tptr; 3057 syscallarg(const struct timeval *) tptr;
3058 } */ 3058 } */
3059 3059
3060 return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 3060 return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW,
3061 SCARG(uap, tptr), UIO_USERSPACE); 3061 SCARG(uap, tptr), UIO_USERSPACE);
3062} 3062}
3063 3063
3064int 3064int
3065sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap, 3065sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap,
3066 register_t *retval) 3066 register_t *retval)
3067{ 3067{
3068 /* { 3068 /* {
3069 syscallarg(int) fd; 3069 syscallarg(int) fd;
3070 syscallarg(const char *) path; 3070 syscallarg(const char *) path;
3071 syscallarg(const struct timespec *) tptr; 3071 syscallarg(const struct timespec *) tptr;
3072 syscallarg(int) flag; 3072 syscallarg(int) flag;
3073 } */ 3073 } */
3074 int follow; 3074 int follow;
3075 const struct timespec *tptr; 3075 const struct timespec *tptr;
3076 3076
3077 /* 3077 /*
3078 * Specified fd is not yet implemented 3078 * Specified fd is not yet implemented
3079 */  3079 */
3080 if (SCARG(uap, fd) != AT_FDCWD) 3080 if (SCARG(uap, fd) != AT_FDCWD)
3081 return ENOSYS; 3081 return ENOSYS;
3082 3082
3083 tptr = SCARG(uap, tptr); 3083 tptr = SCARG(uap, tptr);
3084 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 3084 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
3085 3085
3086 return do_sys_utimens(l, NULL, SCARG(uap, path), follow, 3086 return do_sys_utimens(l, NULL, SCARG(uap, path), follow,
3087 tptr, UIO_USERSPACE); 3087 tptr, UIO_USERSPACE);
3088} 3088}
3089 3089
3090/* 3090/*
3091 * Common routine to set access and modification times given a vnode. 3091 * Common routine to set access and modification times given a vnode.
3092 */ 3092 */
3093int 3093int
3094do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag, 3094do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag,
3095 const struct timespec *tptr, enum uio_seg seg) 3095 const struct timespec *tptr, enum uio_seg seg)
3096{ 3096{
3097 struct vattr vattr; 3097 struct vattr vattr;
3098 int error, dorele = 0; 3098 int error, dorele = 0;
3099 namei_simple_flags_t sflags; 3099 namei_simple_flags_t sflags;
3100 3100
3101 bool vanull, setbirthtime; 3101 bool vanull, setbirthtime;
3102 struct timespec ts[2]; 3102 struct timespec ts[2];
3103 3103
3104 /*  3104 /*
3105 * I have checked all callers and they pass either FOLLOW, 3105 * I have checked all callers and they pass either FOLLOW,
3106 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW 3106 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW
3107 * is 0. More to the point, they don't pass anything else. 3107 * is 0. More to the point, they don't pass anything else.
3108 * Let's keep it that way at least until the namei interfaces 3108 * Let's keep it that way at least until the namei interfaces
3109 * are fully sanitized. 3109 * are fully sanitized.
3110 */ 3110 */
3111 KASSERT(flag == NOFOLLOW || flag == FOLLOW); 3111 KASSERT(flag == NOFOLLOW || flag == FOLLOW);
3112 sflags = (flag == FOLLOW) ?  3112 sflags = (flag == FOLLOW) ?
3113 NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT; 3113 NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT;
3114 3114
3115 if (tptr == NULL) { 3115 if (tptr == NULL) {
3116 vanull = true; 3116 vanull = true;
3117 nanotime(&ts[0]); 3117 nanotime(&ts[0]);
3118 ts[1] = ts[0]; 3118 ts[1] = ts[0];
3119 } else { 3119 } else {
3120 vanull = false; 3120 vanull = false;
3121 if (seg != UIO_SYSSPACE) { 3121 if (seg != UIO_SYSSPACE) {
3122 error = copyin(tptr, ts, sizeof (ts)); 3122 error = copyin(tptr, ts, sizeof (ts));
3123 if (error != 0) 3123 if (error != 0)
3124 return error; 3124 return error;
3125 } else { 3125 } else {
3126 ts[0] = tptr[0]; 3126 ts[0] = tptr[0];
3127 ts[1] = tptr[1]; 3127 ts[1] = tptr[1];
3128 } 3128 }
3129 } 3129 }
3130 3130
3131 if (ts[0].tv_nsec == UTIME_NOW) { 3131 if (ts[0].tv_nsec == UTIME_NOW) {
3132 nanotime(&ts[0]); 3132 nanotime(&ts[0]);
3133 if (ts[1].tv_nsec == UTIME_NOW) { 3133 if (ts[1].tv_nsec == UTIME_NOW) {
3134 vanull = true; 3134 vanull = true;
3135 ts[1] = ts[0]; 3135 ts[1] = ts[0];
3136 } 3136 }
3137 } else if (ts[1].tv_nsec == UTIME_NOW) 3137 } else if (ts[1].tv_nsec == UTIME_NOW)
3138 nanotime(&ts[1]); 3138 nanotime(&ts[1]);
3139 3139
3140 if (vp == NULL) { 3140 if (vp == NULL) {
3141 /* note: SEG describes TPTR, not PATH; PATH is always user */ 3141 /* note: SEG describes TPTR, not PATH; PATH is always user */
3142 error = namei_simple_user(path, sflags, &vp); 3142 error = namei_simple_user(path, sflags, &vp);
3143 if (error != 0) 3143 if (error != 0)
3144 return error; 3144 return error;
3145 dorele = 1; 3145 dorele = 1;
3146 } 3146 }
3147 3147
3148 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3148 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3149 setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 && 3149 setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 &&
3150 timespeccmp(&ts[1], &vattr.va_birthtime, <)); 3150 timespeccmp(&ts[1], &vattr.va_birthtime, <));
3151 vattr_null(&vattr); 3151 vattr_null(&vattr);
3152 3152
3153 if (ts[0].tv_nsec != UTIME_OMIT) 3153 if (ts[0].tv_nsec != UTIME_OMIT)
3154 vattr.va_atime = ts[0]; 3154 vattr.va_atime = ts[0];
3155 3155
3156 if (ts[1].tv_nsec != UTIME_OMIT) { 3156 if (ts[1].tv_nsec != UTIME_OMIT) {
3157 vattr.va_mtime = ts[1]; 3157 vattr.va_mtime = ts[1];
3158 if (setbirthtime) 3158 if (setbirthtime)
3159 vattr.va_birthtime = ts[1]; 3159 vattr.va_birthtime = ts[1];
3160 } 3160 }
3161 3161
3162 if (vanull) 3162 if (vanull)
3163 vattr.va_vaflags |= VA_UTIMES_NULL; 3163 vattr.va_vaflags |= VA_UTIMES_NULL;
3164 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3164 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3165 VOP_UNLOCK(vp); 3165 VOP_UNLOCK(vp);
3166 3166
3167 if (dorele != 0) 3167 if (dorele != 0)
3168 vrele(vp); 3168 vrele(vp);
3169 3169
3170 return error; 3170 return error;
3171} 3171}
3172 3172
3173int 3173int
3174do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag, 3174do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag,
3175 const struct timeval *tptr, enum uio_seg seg) 3175 const struct timeval *tptr, enum uio_seg seg)
3176{ 3176{
3177 struct timespec ts[2]; 3177 struct timespec ts[2];
3178 struct timespec *tsptr = NULL; 3178 struct timespec *tsptr = NULL;
3179 int error; 3179 int error;
3180  3180
3181 if (tptr != NULL) { 3181 if (tptr != NULL) {
3182 struct timeval tv[2]; 3182 struct timeval tv[2];
3183 3183
3184 if (seg != UIO_SYSSPACE) { 3184 if (seg != UIO_SYSSPACE) {
3185 error = copyin(tptr, tv, sizeof (tv)); 3185 error = copyin(tptr, tv, sizeof (tv));
3186 if (error != 0) 3186 if (error != 0)
3187 return error; 3187 return error;
3188 tptr = tv; 3188 tptr = tv;
3189 } 3189 }
3190 3190
3191 if ((tv[0].tv_usec == UTIME_NOW) ||  3191 if ((tv[0].tv_usec == UTIME_NOW) ||
3192 (tv[0].tv_usec == UTIME_OMIT)) 3192 (tv[0].tv_usec == UTIME_OMIT))
3193 ts[0].tv_nsec = tv[0].tv_usec; 3193 ts[0].tv_nsec = tv[0].tv_usec;
3194 else 3194 else
3195 TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]); 3195 TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]);
3196 3196
3197 if ((tv[1].tv_usec == UTIME_NOW) ||  3197 if ((tv[1].tv_usec == UTIME_NOW) ||
3198 (tv[1].tv_usec == UTIME_OMIT)) 3198 (tv[1].tv_usec == UTIME_OMIT))
3199 ts[1].tv_nsec = tv[1].tv_usec; 3199 ts[1].tv_nsec = tv[1].tv_usec;
3200 else 3200 else
3201 TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]); 3201 TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]);
3202 3202
3203 tsptr = &ts[0];  3203 tsptr = &ts[0];
3204 } 3204 }
3205 3205
3206 return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE); 3206 return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE);
3207} 3207}
3208 3208
3209/* 3209/*
3210 * Truncate a file given its path name. 3210 * Truncate a file given its path name.
3211 */ 3211 */
3212/* ARGSUSED */ 3212/* ARGSUSED */
3213int 3213int
3214sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval) 3214sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval)
3215{ 3215{
3216 /* { 3216 /* {
3217 syscallarg(const char *) path; 3217 syscallarg(const char *) path;
3218 syscallarg(int) pad; 3218 syscallarg(int) pad;
3219 syscallarg(off_t) length; 3219 syscallarg(off_t) length;
3220 } */ 3220 } */
3221 struct vnode *vp; 3221 struct vnode *vp;
3222 struct vattr vattr; 3222 struct vattr vattr;
3223 int error; 3223 int error;
3224 3224
3225 error = namei_simple_user(SCARG(uap, path), 3225 error = namei_simple_user(SCARG(uap, path),
3226 NSM_FOLLOW_TRYEMULROOT, &vp); 3226 NSM_FOLLOW_TRYEMULROOT, &vp);
3227 if (error != 0) 3227 if (error != 0)
3228 return (error); 3228 return (error);
3229 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3229 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3230 if (vp->v_type == VDIR) 3230 if (vp->v_type == VDIR)
3231 error = EISDIR; 3231 error = EISDIR;
3232 else if ((error = vn_writechk(vp)) == 0 && 3232 else if ((error = vn_writechk(vp)) == 0 &&
3233 (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) { 3233 (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) {
3234 vattr_null(&vattr); 3234 vattr_null(&vattr);
3235 vattr.va_size = SCARG(uap, length); 3235 vattr.va_size = SCARG(uap, length);
3236 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3236 error = VOP_SETATTR(vp, &vattr, l->l_cred);
3237 } 3237 }
3238 vput(vp); 3238 vput(vp);
3239 return (error); 3239 return (error);
3240} 3240}
3241 3241
3242/* 3242/*
3243 * Truncate a file given a file descriptor. 3243 * Truncate a file given a file descriptor.
3244 */ 3244 */
3245/* ARGSUSED */ 3245/* ARGSUSED */
3246int 3246int
3247sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval) 3247sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval)
3248{ 3248{
3249 /* { 3249 /* {
3250 syscallarg(int) fd; 3250 syscallarg(int) fd;
3251 syscallarg(int) pad; 3251 syscallarg(int) pad;
3252 syscallarg(off_t) length; 3252 syscallarg(off_t) length;
3253 } */ 3253 } */
3254 struct vattr vattr; 3254 struct vattr vattr;
3255 struct vnode *vp; 3255 struct vnode *vp;
3256 file_t *fp; 3256 file_t *fp;
3257 int error; 3257 int error;
3258 3258
3259 /* fd_getvnode() will use the descriptor for us */ 3259 /* fd_getvnode() will use the descriptor for us */
3260 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3260 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3261 return (error); 3261 return (error);
3262 if ((fp->f_flag & FWRITE) == 0) { 3262 if ((fp->f_flag & FWRITE) == 0) {
3263 error = EINVAL; 3263 error = EINVAL;
3264 goto out; 3264 goto out;
3265 } 3265 }
3266 vp = fp->f_data; 3266 vp = fp->f_data;
3267 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3267 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3268 if (vp->v_type == VDIR) 3268 if (vp->v_type == VDIR)
3269 error = EISDIR; 3269 error = EISDIR;
3270 else if ((error = vn_writechk(vp)) == 0) { 3270 else if ((error = vn_writechk(vp)) == 0) {
3271 vattr_null(&vattr); 3271 vattr_null(&vattr);
3272 vattr.va_size = SCARG(uap, length); 3272 vattr.va_size = SCARG(uap, length);
3273 error = VOP_SETATTR(vp, &vattr, fp->f_cred); 3273 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
3274 } 3274 }
3275 VOP_UNLOCK(vp); 3275 VOP_UNLOCK(vp);
3276 out: 3276 out:
3277 fd_putfile(SCARG(uap, fd)); 3277 fd_putfile(SCARG(uap, fd));
3278 return (error); 3278 return (error);
3279} 3279}
3280 3280
3281/* 3281/*
3282 * Sync an open file. 3282 * Sync an open file.
3283 */ 3283 */
3284/* ARGSUSED */ 3284/* ARGSUSED */
3285int 3285int
3286sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval) 3286sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval)
3287{ 3287{
3288 /* { 3288 /* {
3289 syscallarg(int) fd; 3289 syscallarg(int) fd;
3290 } */ 3290 } */
3291 struct vnode *vp; 3291 struct vnode *vp;
3292 file_t *fp; 3292 file_t *fp;
3293 int error; 3293 int error;
3294 3294
3295 /* fd_getvnode() will use the descriptor for us */ 3295 /* fd_getvnode() will use the descriptor for us */
3296 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3296 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3297 return (error); 3297 return (error);
3298 vp = fp->f_data; 3298 vp = fp->f_data;
3299 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3299 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3300 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0); 3300 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0);
3301 VOP_UNLOCK(vp); 3301 VOP_UNLOCK(vp);
3302 fd_putfile(SCARG(uap, fd)); 3302 fd_putfile(SCARG(uap, fd));
3303 return (error); 3303 return (error);
3304} 3304}
3305 3305
3306/* 3306/*
3307 * Sync a range of file data. API modeled after that found in AIX. 3307 * Sync a range of file data. API modeled after that found in AIX.
3308 * 3308 *
3309 * FDATASYNC indicates that we need only save enough metadata to be able 3309 * FDATASYNC indicates that we need only save enough metadata to be able
3310 * to re-read the written data. Note we duplicate AIX's requirement that 3310 * to re-read the written data. Note we duplicate AIX's requirement that
3311 * the file be open for writing. 3311 * the file be open for writing.
3312 */ 3312 */
3313/* ARGSUSED */ 3313/* ARGSUSED */
3314int 3314int
3315sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval) 3315sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval)
3316{ 3316{
3317 /* { 3317 /* {
3318 syscallarg(int) fd; 3318 syscallarg(int) fd;
3319 syscallarg(int) flags; 3319 syscallarg(int) flags;
3320 syscallarg(off_t) start; 3320 syscallarg(off_t) start;
3321 syscallarg(off_t) length; 3321 syscallarg(off_t) length;
3322 } */ 3322 } */
3323 struct vnode *vp; 3323 struct vnode *vp;
3324 file_t *fp; 3324 file_t *fp;
3325 int flags, nflags; 3325 int flags, nflags;
3326 off_t s, e, len; 3326 off_t s, e, len;
3327 int error; 3327 int error;
3328 3328
3329 /* fd_getvnode() will use the descriptor for us */ 3329 /* fd_getvnode() will use the descriptor for us */
3330 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3330 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3331 return (error); 3331 return (error);
3332 3332
3333 if ((fp->f_flag & FWRITE) == 0) { 3333 if ((fp->f_flag & FWRITE) == 0) {
3334 error = EBADF; 3334 error = EBADF;
3335 goto out; 3335 goto out;
3336 } 3336 }
3337 3337
3338 flags = SCARG(uap, flags); 3338 flags = SCARG(uap, flags);
3339 if (((flags & (FDATASYNC | FFILESYNC)) == 0) || 3339 if (((flags & (FDATASYNC | FFILESYNC)) == 0) ||
3340 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) { 3340 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) {
3341 error = EINVAL; 3341 error = EINVAL;
3342 goto out; 3342 goto out;
3343 } 3343 }
3344 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */ 3344 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */
3345 if (flags & FDATASYNC) 3345 if (flags & FDATASYNC)
3346 nflags = FSYNC_DATAONLY | FSYNC_WAIT; 3346 nflags = FSYNC_DATAONLY | FSYNC_WAIT;
3347 else 3347 else
3348 nflags = FSYNC_WAIT; 3348 nflags = FSYNC_WAIT;
3349 if (flags & FDISKSYNC) 3349 if (flags & FDISKSYNC)
3350 nflags |= FSYNC_CACHE; 3350 nflags |= FSYNC_CACHE;
3351 3351
3352 len = SCARG(uap, length); 3352 len = SCARG(uap, length);
3353 /* If length == 0, we do the whole file, and s = e = 0 will do that */ 3353 /* If length == 0, we do the whole file, and s = e = 0 will do that */
3354 if (len) { 3354 if (len) {
3355 s = SCARG(uap, start); 3355 s = SCARG(uap, start);
3356 e = s + len; 3356 e = s + len;
3357 if (e < s) { 3357 if (e < s) {
3358 error = EINVAL; 3358 error = EINVAL;
3359 goto out; 3359 goto out;
3360 } 3360 }
3361 } else { 3361 } else {
3362 e = 0; 3362 e = 0;
3363 s = 0; 3363 s = 0;
3364 } 3364 }
3365 3365
3366 vp = fp->f_data; 3366 vp = fp->f_data;
3367 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3367 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3368 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e); 3368 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e);
3369 VOP_UNLOCK(vp); 3369 VOP_UNLOCK(vp);
3370out: 3370out:
3371 fd_putfile(SCARG(uap, fd)); 3371 fd_putfile(SCARG(uap, fd));
3372 return (error); 3372 return (error);
3373} 3373}
3374 3374
3375/* 3375/*
3376 * Sync the data of an open file. 3376 * Sync the data of an open file.
3377 */ 3377 */
3378/* ARGSUSED */ 3378/* ARGSUSED */
3379int 3379int
3380sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval) 3380sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval)
3381{ 3381{
3382 /* { 3382 /* {
3383 syscallarg(int) fd; 3383 syscallarg(int) fd;
3384 } */ 3384 } */
3385 struct vnode *vp; 3385 struct vnode *vp;
3386 file_t *fp; 3386 file_t *fp;
3387 int error; 3387 int error;
3388 3388
3389 /* fd_getvnode() will use the descriptor for us */ 3389 /* fd_getvnode() will use the descriptor for us */
3390 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3390 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3391 return (error); 3391 return (error);
3392 if ((fp->f_flag & FWRITE) == 0) { 3392 if ((fp->f_flag & FWRITE) == 0) {
3393 fd_putfile(SCARG(uap, fd)); 3393 fd_putfile(SCARG(uap, fd));
3394 return (EBADF); 3394 return (EBADF);
3395 } 3395 }
3396 vp = fp->f_data; 3396 vp = fp->f_data;
3397 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3397 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3398 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0); 3398 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0);
3399 VOP_UNLOCK(vp); 3399 VOP_UNLOCK(vp);
3400 fd_putfile(SCARG(uap, fd)); 3400 fd_putfile(SCARG(uap, fd));
3401 return (error); 3401 return (error);
3402} 3402}
3403 3403
3404/* 3404/*
3405 * Rename files, (standard) BSD semantics frontend. 3405 * Rename files, (standard) BSD semantics frontend.
3406 */ 3406 */
3407/* ARGSUSED */ 3407/* ARGSUSED */
3408int 3408int
3409sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval) 3409sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval)
3410{ 3410{
3411 /* { 3411 /* {
3412 syscallarg(const char *) from; 3412 syscallarg(const char *) from;
3413 syscallarg(const char *) to; 3413 syscallarg(const char *) to;
3414 } */ 3414 } */
3415 3415
3416 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 0)); 3416 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 0));
3417} 3417}
3418 3418
3419int 3419int
3420sys_renameat(struct lwp *l, const struct sys_renameat_args *uap,  3420sys_renameat(struct lwp *l, const struct sys_renameat_args *uap,
3421 register_t *retval) 3421 register_t *retval)
3422{ 3422{
3423 /* { 3423 /* {
3424 syscallarg(int) fromfd; 3424 syscallarg(int) fromfd;
3425 syscallarg(const char *) from; 3425 syscallarg(const char *) from;
3426 syscallarg(int) tofd; 3426 syscallarg(int) tofd;
3427 syscallarg(const char *) to; 3427 syscallarg(const char *) to;
3428 } */ 3428 } */
3429 3429
3430 return ENOSYS; 3430 return ENOSYS;
3431} 3431}
3432 3432
3433/* 3433/*
3434 * Rename files, POSIX semantics frontend. 3434 * Rename files, POSIX semantics frontend.
3435 */ 3435 */
3436/* ARGSUSED */ 3436/* ARGSUSED */
3437int 3437int
3438sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval) 3438sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval)
3439{ 3439{
3440 /* { 3440 /* {
3441 syscallarg(const char *) from; 3441 syscallarg(const char *) from;
3442 syscallarg(const char *) to; 3442 syscallarg(const char *) to;
3443 } */ 3443 } */
3444 3444
3445 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 1)); 3445 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 1));
3446} 3446}
3447 3447
3448/* 3448/*
3449 * Rename files. Source and destination must either both be directories, 3449 * Rename files. Source and destination must either both be directories,
3450 * or both not be directories. If target is a directory, it must be empty. 3450 * or both not be directories. If target is a directory, it must be empty.
3451 * If `from' and `to' refer to the same object, the value of the `retain' 3451 * If `from' and `to' refer to the same object, the value of the `retain'
3452 * argument is used to determine whether `from' will be 3452 * argument is used to determine whether `from' will be
3453 * 3453 *
3454 * (retain == 0) deleted unless `from' and `to' refer to the same 3454 * (retain == 0) deleted unless `from' and `to' refer to the same
3455 * object in the file system's name space (BSD). 3455 * object in the file system's name space (BSD).
3456 * (retain == 1) always retained (POSIX). 3456 * (retain == 1) always retained (POSIX).
3457 */ 3457 */
3458int 3458int
3459do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain) 3459do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain)
3460{ 3460{
3461 struct vnode *tvp, *fvp, *tdvp; 3461 struct vnode *tvp, *fvp, *tdvp;
3462 struct pathbuf *frompb, *topb; 3462 struct pathbuf *frompb, *topb;
3463 struct nameidata fromnd, tond; 3463 struct nameidata fromnd, tond;
3464 struct mount *fs; 3464 struct mount *fs;
3465 int error; 3465 int error;
3466 3466
3467 error = pathbuf_maybe_copyin(from, seg, &frompb); 3467 error = pathbuf_maybe_copyin(from, seg, &frompb);
3468 if (error) { 3468 if (error) {
3469 return error; 3469 return error;
3470 } 3470 }
3471 error = pathbuf_maybe_copyin(to, seg, &topb); 3471 error = pathbuf_maybe_copyin(to, seg, &topb);
3472 if (error) { 3472 if (error) {
3473 pathbuf_destroy(frompb); 3473 pathbuf_destroy(frompb);
3474 return error; 3474 return error;
3475 } 3475 }
3476 3476
3477 NDINIT(&fromnd, DELETE, LOCKPARENT | TRYEMULROOT | INRENAME, 3477 NDINIT(&fromnd, DELETE, LOCKPARENT | TRYEMULROOT | INRENAME,
3478 frompb); 3478 frompb);
3479 if ((error = namei(&fromnd)) != 0) { 3479 if ((error = namei(&fromnd)) != 0) {
3480 pathbuf_destroy(frompb); 3480 pathbuf_destroy(frompb);
3481 pathbuf_destroy(topb); 3481 pathbuf_destroy(topb);
3482 return (error); 3482 return (error);
3483 } 3483 }
3484 if (fromnd.ni_dvp != fromnd.ni_vp) 3484 if (fromnd.ni_dvp != fromnd.ni_vp)
3485 VOP_UNLOCK(fromnd.ni_dvp); 3485 VOP_UNLOCK(fromnd.ni_dvp);
3486 fvp = fromnd.ni_vp; 3486 fvp = fromnd.ni_vp;
3487 3487
3488 fs = fvp->v_mount; 3488 fs = fvp->v_mount;
3489 error = VFS_RENAMELOCK_ENTER(fs); 3489 error = VFS_RENAMELOCK_ENTER(fs);
3490 if (error) { 3490 if (error) {
3491 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3491 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3492 vrele(fromnd.ni_dvp); 3492 vrele(fromnd.ni_dvp);
3493 vrele(fvp); 3493 vrele(fvp);
3494 goto out1; 3494 goto out1;
3495 } 3495 }
3496 3496
3497 /* 3497 /*
3498 * close, partially, yet another race - ideally we should only 3498 * close, partially, yet another race - ideally we should only
3499 * go as far as getting fromnd.ni_dvp before getting the per-fs 3499 * go as far as getting fromnd.ni_dvp before getting the per-fs
3500 * lock, and then continue to get fromnd.ni_vp, but we can't do 3500 * lock, and then continue to get fromnd.ni_vp, but we can't do
3501 * that with namei as it stands. 3501 * that with namei as it stands.
3502 * 3502 *
3503 * This still won't prevent rmdir from nuking fromnd.ni_vp 3503 * This still won't prevent rmdir from nuking fromnd.ni_vp
3504 * under us. The real fix is to get the locks in the right 3504 * under us. The real fix is to get the locks in the right
3505 * order and do the lookups in the right places, but that's a 3505 * order and do the lookups in the right places, but that's a
3506 * major rototill. 3506 * major rototill.
3507 * 3507 *
3508 * Note: this logic (as well as this whole function) is cloned 3508 * Note: this logic (as well as this whole function) is cloned
3509 * in nfs_serv.c. Proceed accordingly. 3509 * in nfs_serv.c. Proceed accordingly.
3510 */ 3510 */
3511 vrele(fvp); 3511 vrele(fvp);
3512 if ((fromnd.ni_cnd.cn_namelen == 1 &&  3512 if ((fromnd.ni_cnd.cn_namelen == 1 &&
3513 fromnd.ni_cnd.cn_nameptr[0] == '.') || 3513 fromnd.ni_cnd.cn_nameptr[0] == '.') ||
3514 (fromnd.ni_cnd.cn_namelen == 2 &&  3514 (fromnd.ni_cnd.cn_namelen == 2 &&
3515 fromnd.ni_cnd.cn_nameptr[0] == '.' && 3515 fromnd.ni_cnd.cn_nameptr[0] == '.' &&
3516 fromnd.ni_cnd.cn_nameptr[1] == '.')) { 3516 fromnd.ni_cnd.cn_nameptr[1] == '.')) {
3517 error = EINVAL; 3517 error = EINVAL;
3518 VFS_RENAMELOCK_EXIT(fs); 3518 VFS_RENAMELOCK_EXIT(fs);
3519 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3519 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3520 vrele(fromnd.ni_dvp); 3520 vrele(fromnd.ni_dvp);
3521 goto out1; 3521 goto out1;
3522 } 3522 }
3523 vn_lock(fromnd.ni_dvp, LK_EXCLUSIVE | LK_RETRY); 3523 vn_lock(fromnd.ni_dvp, LK_EXCLUSIVE | LK_RETRY);
3524 error = relookup(fromnd.ni_dvp, &fromnd.ni_vp, &fromnd.ni_cnd, 0); 3524 error = relookup(fromnd.ni_dvp, &fromnd.ni_vp, &fromnd.ni_cnd, 0);
3525 if (error) { 3525 if (error) {
3526 VOP_UNLOCK(fromnd.ni_dvp); 3526 VOP_UNLOCK(fromnd.ni_dvp);
3527 VFS_RENAMELOCK_EXIT(fs); 3527 VFS_RENAMELOCK_EXIT(fs);
3528 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3528 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3529 vrele(fromnd.ni_dvp); 3529 vrele(fromnd.ni_dvp);
3530 goto out1; 3530 goto out1;
3531 } 3531 }
3532 VOP_UNLOCK(fromnd.ni_vp); 3532 VOP_UNLOCK(fromnd.ni_vp);
3533 if (fromnd.ni_dvp != fromnd.ni_vp) 3533 if (fromnd.ni_dvp != fromnd.ni_vp)
3534 VOP_UNLOCK(fromnd.ni_dvp); 3534 VOP_UNLOCK(fromnd.ni_dvp);
3535 fvp = fromnd.ni_vp; 3535 fvp = fromnd.ni_vp;
3536 3536
3537 NDINIT(&tond, RENAME, 3537 NDINIT(&tond, RENAME,
3538 LOCKPARENT | LOCKLEAF | NOCACHE | TRYEMULROOT 3538 LOCKPARENT | LOCKLEAF | NOCACHE | TRYEMULROOT
3539 | INRENAME | (fvp->v_type == VDIR ? CREATEDIR : 0), 3539 | INRENAME | (fvp->v_type == VDIR ? CREATEDIR : 0),
3540 topb); 3540 topb);
3541 if ((error = namei(&tond)) != 0) { 3541 if ((error = namei(&tond)) != 0) {
3542 VFS_RENAMELOCK_EXIT(fs); 3542 VFS_RENAMELOCK_EXIT(fs);
3543 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3543 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3544 vrele(fromnd.ni_dvp); 3544 vrele(fromnd.ni_dvp);
3545 vrele(fvp); 3545 vrele(fvp);
3546 goto out1; 3546 goto out1;
3547 } 3547 }
3548 tdvp = tond.ni_dvp; 3548 tdvp = tond.ni_dvp;
3549 tvp = tond.ni_vp; 3549 tvp = tond.ni_vp;
3550 3550
3551 if (tvp != NULL) { 3551 if (tvp != NULL) {
3552 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3552 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3553 error = ENOTDIR; 3553 error = ENOTDIR;
3554 goto out; 3554 goto out;
3555 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3555 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3556 error = EISDIR; 3556 error = EISDIR;
3557 goto out; 3557 goto out;
3558 } 3558 }
3559 } 3559 }
3560 3560
3561 if (fvp == tdvp) 3561 if (fvp == tdvp)
3562 error = EINVAL; 3562 error = EINVAL;
3563 3563
3564 /* 3564 /*
3565 * Source and destination refer to the same object. 3565 * Source and destination refer to the same object.
3566 */ 3566 */
3567 if (fvp == tvp) { 3567 if (fvp == tvp) {
3568 if (retain) 3568 if (retain)
3569 error = -1; 3569 error = -1;
3570 else if (fromnd.ni_dvp == tdvp && 3570 else if (fromnd.ni_dvp == tdvp &&
3571 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 3571 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
3572 !memcmp(fromnd.ni_cnd.cn_nameptr, 3572 !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
3573 tond.ni_cnd.cn_nameptr, 
3574 fromnd.ni_cnd.cn_namelen)) 3573 fromnd.ni_cnd.cn_namelen))
3575 error = -1; 3574 error = -1;
3576 } 3575 }
3577 /* 3576 /*
3578 * Prevent cross-mount operation. 3577 * Prevent cross-mount operation.
3579 */ 3578 */
3580 if (error == 0) { 3579 if (error == 0) {
3581 if (tond.ni_dvp->v_mount != fromnd.ni_dvp->v_mount) { 3580 if (tond.ni_dvp->v_mount != fromnd.ni_dvp->v_mount) {
3582 error = EXDEV; 3581 error = EXDEV;
3583 } 3582 }
3584 } 3583 }
3585#if NVERIEXEC > 0 3584#if NVERIEXEC > 0
3586 if (!error) { 3585 if (!error) {
3587 char *f1, *f2; 3586 char *f1, *f2;
3588 size_t f1_len; 3587 size_t f1_len;
3589 size_t f2_len; 3588 size_t f2_len;
3590 3589
3591 f1_len = fromnd.ni_cnd.cn_namelen + 1; 3590 f1_len = fromnd.ni_cnd.cn_namelen + 1;
3592 f1 = kmem_alloc(f1_len, KM_SLEEP); 3591 f1 = kmem_alloc(f1_len, KM_SLEEP);
3593 strlcpy(f1, fromnd.ni_cnd.cn_nameptr, f1_len); 3592 strlcpy(f1, fromnd.ni_cnd.cn_nameptr, f1_len);
3594 3593
3595 f2_len = tond.ni_cnd.cn_namelen + 1; 3594 f2_len = tond.ni_cnd.cn_namelen + 1;
3596 f2 = kmem_alloc(f2_len, KM_SLEEP); 3595 f2 = kmem_alloc(f2_len, KM_SLEEP);
3597 strlcpy(f2, tond.ni_cnd.cn_nameptr, f2_len); 3596 strlcpy(f2, tond.ni_cnd.cn_nameptr, f2_len);
3598 3597
3599 error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2); 3598 error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2);
3600 3599
3601 kmem_free(f1, f1_len); 3600 kmem_free(f1, f1_len);
3602 kmem_free(f2, f2_len); 3601 kmem_free(f2, f2_len);
3603 } 3602 }
3604#endif /* NVERIEXEC > 0 */ 3603#endif /* NVERIEXEC > 0 */
3605 3604
3606out: 3605out:
3607 if (!error) { 3606 if (!error) {
3608 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 3607 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3609 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 3608 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3610 VFS_RENAMELOCK_EXIT(fs); 3609 VFS_RENAMELOCK_EXIT(fs);
3611 } else { 3610 } else {
3612 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 3611 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
3613 if (tdvp == tvp) 3612 if (tdvp == tvp)
3614 vrele(tdvp); 3613 vrele(tdvp);
3615 else 3614 else
3616 vput(tdvp); 3615 vput(tdvp);
3617 if (tvp) 3616 if (tvp)
3618 vput(tvp); 3617 vput(tvp);
3619 VFS_RENAMELOCK_EXIT(fs); 3618 VFS_RENAMELOCK_EXIT(fs);
3620 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3619 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
3621 vrele(fromnd.ni_dvp); 3620 vrele(fromnd.ni_dvp);
3622 vrele(fvp); 3621 vrele(fvp);
3623 } 3622 }
3624out1: 3623out1:
3625 pathbuf_destroy(frompb); 3624 pathbuf_destroy(frompb);
3626 pathbuf_destroy(topb); 3625 pathbuf_destroy(topb);
3627 return (error == -1 ? 0 : error); 3626 return (error == -1 ? 0 : error);
3628} 3627}
3629 3628
3630/* 3629/*
3631 * Make a directory file. 3630 * Make a directory file.
3632 */ 3631 */
3633/* ARGSUSED */ 3632/* ARGSUSED */
3634int 3633int
3635sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval) 3634sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval)
3636{ 3635{
3637 /* { 3636 /* {
3638 syscallarg(const char *) path; 3637 syscallarg(const char *) path;
3639 syscallarg(int) mode; 3638 syscallarg(int) mode;
3640 } */ 3639 } */
3641 3640
3642 return do_sys_mkdir(SCARG(uap, path), SCARG(uap, mode), UIO_USERSPACE); 3641 return do_sys_mkdir(SCARG(uap, path), SCARG(uap, mode), UIO_USERSPACE);
3643} 3642}
3644 3643
3645int 3644int
3646sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap, 3645sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap,
3647 register_t *retval) 3646 register_t *retval)
3648{ 3647{
3649 /* { 3648 /* {
3650 syscallarg(int) fd; 3649 syscallarg(int) fd;
3651 syscallarg(const char *) path; 3650 syscallarg(const char *) path;
3652 syscallarg(int) mode; 3651 syscallarg(int) mode;
3653 } */ 3652 } */
3654 3653
3655 return ENOSYS; 3654 return ENOSYS;
3656} 3655}
3657 3656
3658 3657
3659int 3658int
3660do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg) 3659do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg)
3661{ 3660{
3662 struct proc *p = curlwp->l_proc; 3661 struct proc *p = curlwp->l_proc;
3663 struct vnode *vp; 3662 struct vnode *vp;
3664 struct vattr vattr; 3663 struct vattr vattr;
3665 int error; 3664 int error;
3666 struct pathbuf *pb; 3665 struct pathbuf *pb;
3667 struct nameidata nd; 3666 struct nameidata nd;
3668 3667
3669 /* XXX bollocks, should pass in a pathbuf */ 3668 /* XXX bollocks, should pass in a pathbuf */
3670 error = pathbuf_maybe_copyin(path, seg, &pb); 3669 error = pathbuf_maybe_copyin(path, seg, &pb);
3671 if (error) { 3670 if (error) {
3672 return error; 3671 return error;
3673 } 3672 }
3674 3673
3675 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb); 3674 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb);
3676 if ((error = namei(&nd)) != 0) { 3675 if ((error = namei(&nd)) != 0) {
3677 pathbuf_destroy(pb); 3676 pathbuf_destroy(pb);
3678 return (error); 3677 return (error);
3679 } 3678 }
3680 vp = nd.ni_vp; 3679 vp = nd.ni_vp;
3681 if (vp != NULL) { 3680 if (vp != NULL) {
3682 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3681 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
3683 if (nd.ni_dvp == vp) 3682 if (nd.ni_dvp == vp)
3684 vrele(nd.ni_dvp); 3683 vrele(nd.ni_dvp);
3685 else 3684 else
3686 vput(nd.ni_dvp); 3685 vput(nd.ni_dvp);
3687 vrele(vp); 3686 vrele(vp);
3688 pathbuf_destroy(pb); 3687 pathbuf_destroy(pb);
3689 return (EEXIST); 3688 return (EEXIST);
3690 } 3689 }
3691 vattr_null(&vattr); 3690 vattr_null(&vattr);
3692 vattr.va_type = VDIR; 3691 vattr.va_type = VDIR;
3693 /* We will read cwdi->cwdi_cmask unlocked. */ 3692 /* We will read cwdi->cwdi_cmask unlocked. */
3694 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask; 3693 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
3695 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3694 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3696 if (!error) 3695 if (!error)
3697 vput(nd.ni_vp); 3696 vput(nd.ni_vp);
3698 pathbuf_destroy(pb); 3697 pathbuf_destroy(pb);
3699 return (error); 3698 return (error);
3700} 3699}
3701 3700
3702/* 3701/*
3703 * Remove a directory file. 3702 * Remove a directory file.
3704 */ 3703 */
3705/* ARGSUSED */ 3704/* ARGSUSED */
3706int 3705int
3707sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval) 3706sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval)
3708{ 3707{
3709 /* { 3708 /* {
3710 syscallarg(const char *) path; 3709 syscallarg(const char *) path;
3711 } */ 3710 } */
3712 struct vnode *vp; 3711 struct vnode *vp;
3713 int error; 3712 int error;
3714 struct pathbuf *pb; 3713 struct pathbuf *pb;
3715 struct nameidata nd; 3714 struct nameidata nd;
3716 3715
3717 error = pathbuf_copyin(SCARG(uap, path), &pb); 3716 error = pathbuf_copyin(SCARG(uap, path), &pb);
3718 if (error) { 3717 if (error) {
3719 return error; 3718 return error;
3720 } 3719 }
3721 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb); 3720 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb);
3722 if ((error = namei(&nd)) != 0) { 3721 if ((error = namei(&nd)) != 0) {
3723 pathbuf_destroy(pb); 3722 pathbuf_destroy(pb);
3724 return error; 3723 return error;
3725 } 3724 }
3726 vp = nd.ni_vp; 3725 vp = nd.ni_vp;
3727 if (vp->v_type != VDIR) { 3726 if (vp->v_type != VDIR) {
3728 error = ENOTDIR; 3727 error = ENOTDIR;
3729 goto out; 3728 goto out;
3730 } 3729 }
3731 /* 3730 /*
3732 * No rmdir "." please. 3731 * No rmdir "." please.
3733 */ 3732 */
3734 if (nd.ni_dvp == vp) { 3733 if (nd.ni_dvp == vp) {
3735 error = EINVAL; 3734 error = EINVAL;
3736 goto out; 3735 goto out;
3737 } 3736 }
3738 /* 3737 /*
3739 * The root of a mounted filesystem cannot be deleted. 3738 * The root of a mounted filesystem cannot be deleted.
3740 */ 3739 */
3741 if ((vp->v_vflag & VV_ROOT) != 0 || vp->v_mountedhere != NULL) { 3740 if ((vp->v_vflag & VV_ROOT) != 0 || vp->v_mountedhere != NULL) {
3742 error = EBUSY; 3741 error = EBUSY;
3743 goto out; 3742 goto out;
3744 } 3743 }
3745 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3744 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3746 pathbuf_destroy(pb); 3745 pathbuf_destroy(pb);
3747 return (error); 3746 return (error);
3748 3747
3749out: 3748out:
3750 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3749 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
3751 if (nd.ni_dvp == vp) 3750 if (nd.ni_dvp == vp)
3752 vrele(nd.ni_dvp); 3751 vrele(nd.ni_dvp);
3753 else 3752 else
3754 vput(nd.ni_dvp); 3753 vput(nd.ni_dvp);
3755 vput(vp); 3754 vput(vp);
3756 pathbuf_destroy(pb); 3755 pathbuf_destroy(pb);
3757 return (error); 3756 return (error);
3758} 3757}
3759 3758
3760/* 3759/*
3761 * Read a block of directory entries in a file system independent format. 3760 * Read a block of directory entries in a file system independent format.
3762 */ 3761 */
3763int 3762int
3764sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval) 3763sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval)
3765{ 3764{
3766 /* { 3765 /* {
3767 syscallarg(int) fd; 3766 syscallarg(int) fd;
3768 syscallarg(char *) buf; 3767 syscallarg(char *) buf;
3769 syscallarg(size_t) count; 3768 syscallarg(size_t) count;
3770 } */ 3769 } */
3771 file_t *fp; 3770 file_t *fp;
3772 int error, done; 3771 int error, done;
3773 3772
3774 /* fd_getvnode() will use the descriptor for us */ 3773 /* fd_getvnode() will use the descriptor for us */
3775 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3774 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
3776 return (error); 3775 return (error);
3777 if ((fp->f_flag & FREAD) == 0) { 3776 if ((fp->f_flag & FREAD) == 0) {
3778 error = EBADF; 3777 error = EBADF;
3779 goto out; 3778 goto out;
3780 } 3779 }
3781 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, 3780 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
3782 SCARG(uap, count), &done, l, 0, 0); 3781 SCARG(uap, count), &done, l, 0, 0);
3783 ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error); 3782 ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error);
3784 *retval = done; 3783 *retval = done;
3785 out: 3784 out:
3786 fd_putfile(SCARG(uap, fd)); 3785 fd_putfile(SCARG(uap, fd));
3787 return (error); 3786 return (error);
3788} 3787}
3789 3788
3790/* 3789/*
3791 * Set the mode mask for creation of filesystem nodes. 3790 * Set the mode mask for creation of filesystem nodes.
3792 */ 3791 */
3793int 3792int
3794sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval) 3793sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval)
3795{ 3794{
3796 /* { 3795 /* {
3797 syscallarg(mode_t) newmask; 3796 syscallarg(mode_t) newmask;
3798 } */ 3797 } */
3799 struct proc *p = l->l_proc; 3798 struct proc *p = l->l_proc;
3800 struct cwdinfo *cwdi; 3799 struct cwdinfo *cwdi;
3801 3800
3802 /* 3801 /*
3803 * cwdi->cwdi_cmask will be read unlocked elsewhere. What's 3802 * cwdi->cwdi_cmask will be read unlocked elsewhere. What's
3804 * important is that we serialize changes to the mask. The 3803 * important is that we serialize changes to the mask. The
3805 * rw_exit() will issue a write memory barrier on our behalf, 3804 * rw_exit() will issue a write memory barrier on our behalf,
3806 * and force the changes out to other CPUs (as it must use an 3805 * and force the changes out to other CPUs (as it must use an
3807 * atomic operation, draining the local CPU's store buffers). 3806 * atomic operation, draining the local CPU's store buffers).
3808 */ 3807 */
3809 cwdi = p->p_cwdi; 3808 cwdi = p->p_cwdi;
3810 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 3809 rw_enter(&cwdi->cwdi_lock, RW_WRITER);
3811 *retval = cwdi->cwdi_cmask; 3810 *retval = cwdi->cwdi_cmask;
3812 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS; 3811 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
3813 rw_exit(&cwdi->cwdi_lock); 3812 rw_exit(&cwdi->cwdi_lock);
3814 3813
3815 return (0); 3814 return (0);
3816} 3815}
3817 3816
3818int 3817int
3819dorevoke(struct vnode *vp, kauth_cred_t cred) 3818dorevoke(struct vnode *vp, kauth_cred_t cred)
3820{ 3819{
3821 struct vattr vattr; 3820 struct vattr vattr;
3822 int error; 3821 int error;
3823 3822
3824 vn_lock(vp, LK_SHARED | LK_RETRY); 3823 vn_lock(vp, LK_SHARED | LK_RETRY);
3825 error = VOP_GETATTR(vp, &vattr, cred); 3824 error = VOP_GETATTR(vp, &vattr, cred);
3826 VOP_UNLOCK(vp); 3825 VOP_UNLOCK(vp);
3827 if (error != 0) 3826 if (error != 0)
3828 return error; 3827 return error;
3829 if (kauth_cred_geteuid(cred) == vattr.va_uid || 3828 if (kauth_cred_geteuid(cred) == vattr.va_uid ||
3830 (error = kauth_authorize_generic(cred, 3829 (error = kauth_authorize_generic(cred,
3831 KAUTH_GENERIC_ISSUSER, NULL)) == 0) 3830 KAUTH_GENERIC_ISSUSER, NULL)) == 0)
3832 VOP_REVOKE(vp, REVOKEALL); 3831 VOP_REVOKE(vp, REVOKEALL);
3833 return (error); 3832 return (error);
3834} 3833}
3835 3834
3836/* 3835/*
3837 * Void all references to file by ripping underlying filesystem 3836 * Void all references to file by ripping underlying filesystem
3838 * away from vnode. 3837 * away from vnode.
3839 */ 3838 */
3840/* ARGSUSED */ 3839/* ARGSUSED */
3841int 3840int
3842sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval) 3841sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval)
3843{ 3842{
3844 /* { 3843 /* {
3845 syscallarg(const char *) path; 3844 syscallarg(const char *) path;
3846 } */ 3845 } */
3847 struct vnode *vp; 3846 struct vnode *vp;
3848 int error; 3847 int error;
3849 3848
3850 error = namei_simple_user(SCARG(uap, path), 3849 error = namei_simple_user(SCARG(uap, path),
3851 NSM_FOLLOW_TRYEMULROOT, &vp); 3850 NSM_FOLLOW_TRYEMULROOT, &vp);
3852 if (error != 0) 3851 if (error != 0)
3853 return (error); 3852 return (error);
3854 error = dorevoke(vp, l->l_cred); 3853 error = dorevoke(vp, l->l_cred);
3855 vrele(vp); 3854 vrele(vp);
3856 return (error); 3855 return (error);
3857} 3856}