Thu Oct 28 20:32:45 2010 UTC ()
Zero entire stat structure before filling in contents to avoid
leaking kernel memory -- the elements are no longer packed now that
dev_t is 64bit.

from pgoyette


(pooka)
diff -r1.178 -r1.179 src/sys/kern/vfs_vnops.c

cvs diff -r1.178 -r1.179 src/sys/kern/vfs_vnops.c (switch to unified diff)

--- src/sys/kern/vfs_vnops.c 2010/09/21 19:26:19 1.178
+++ src/sys/kern/vfs_vnops.c 2010/10/28 20:32:45 1.179
@@ -1,945 +1,945 @@ @@ -1,945 +1,945 @@
1/* $NetBSD: vfs_vnops.c,v 1.178 2010/09/21 19:26:19 chs Exp $ */ 1/* $NetBSD: vfs_vnops.c,v 1.179 2010/10/28 20:32:45 pooka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 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) 1982, 1986, 1989, 1993 33 * Copyright (c) 1982, 1986, 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_vnops.c 8.14 (Berkeley) 6/15/95 65 * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95
66 */ 66 */
67 67
68#include <sys/cdefs.h> 68#include <sys/cdefs.h>
69__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.178 2010/09/21 19:26:19 chs Exp $"); 69__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.179 2010/10/28 20:32:45 pooka Exp $");
70 70
71#include "veriexec.h" 71#include "veriexec.h"
72 72
73#include <sys/param.h> 73#include <sys/param.h>
74#include <sys/systm.h> 74#include <sys/systm.h>
75#include <sys/kernel.h> 75#include <sys/kernel.h>
76#include <sys/file.h> 76#include <sys/file.h>
77#include <sys/stat.h> 77#include <sys/stat.h>
78#include <sys/buf.h> 78#include <sys/buf.h>
79#include <sys/proc.h> 79#include <sys/proc.h>
80#include <sys/mount.h> 80#include <sys/mount.h>
81#include <sys/namei.h> 81#include <sys/namei.h>
82#include <sys/vnode.h> 82#include <sys/vnode.h>
83#include <sys/ioctl.h> 83#include <sys/ioctl.h>
84#include <sys/tty.h> 84#include <sys/tty.h>
85#include <sys/poll.h> 85#include <sys/poll.h>
86#include <sys/kauth.h> 86#include <sys/kauth.h>
87#include <sys/syslog.h> 87#include <sys/syslog.h>
88#include <sys/fstrans.h> 88#include <sys/fstrans.h>
89#include <sys/atomic.h> 89#include <sys/atomic.h>
90#include <sys/filedesc.h> 90#include <sys/filedesc.h>
91#include <sys/wapbl.h> 91#include <sys/wapbl.h>
92 92
93#include <miscfs/specfs/specdev.h> 93#include <miscfs/specfs/specdev.h>
94#include <miscfs/fifofs/fifo.h> 94#include <miscfs/fifofs/fifo.h>
95 95
96#include <uvm/uvm_extern.h> 96#include <uvm/uvm_extern.h>
97#include <uvm/uvm_readahead.h> 97#include <uvm/uvm_readahead.h>
98 98
99#ifdef UNION 99#ifdef UNION
100#include <fs/union/union.h> 100#include <fs/union/union.h>
101#endif 101#endif
102 102
103int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct lwp *); 103int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct lwp *);
104 104
105#include <sys/verified_exec.h> 105#include <sys/verified_exec.h>
106 106
107static int vn_read(file_t *fp, off_t *offset, struct uio *uio, 107static int vn_read(file_t *fp, off_t *offset, struct uio *uio,
108 kauth_cred_t cred, int flags); 108 kauth_cred_t cred, int flags);
109static int vn_write(file_t *fp, off_t *offset, struct uio *uio, 109static int vn_write(file_t *fp, off_t *offset, struct uio *uio,
110 kauth_cred_t cred, int flags); 110 kauth_cred_t cred, int flags);
111static int vn_closefile(file_t *fp); 111static int vn_closefile(file_t *fp);
112static int vn_poll(file_t *fp, int events); 112static int vn_poll(file_t *fp, int events);
113static int vn_fcntl(file_t *fp, u_int com, void *data); 113static int vn_fcntl(file_t *fp, u_int com, void *data);
114static int vn_statfile(file_t *fp, struct stat *sb); 114static int vn_statfile(file_t *fp, struct stat *sb);
115static int vn_ioctl(file_t *fp, u_long com, void *data); 115static int vn_ioctl(file_t *fp, u_long com, void *data);
116 116
117const struct fileops vnops = { 117const struct fileops vnops = {
118 .fo_read = vn_read, 118 .fo_read = vn_read,
119 .fo_write = vn_write, 119 .fo_write = vn_write,
120 .fo_ioctl = vn_ioctl, 120 .fo_ioctl = vn_ioctl,
121 .fo_fcntl = vn_fcntl, 121 .fo_fcntl = vn_fcntl,
122 .fo_poll = vn_poll, 122 .fo_poll = vn_poll,
123 .fo_stat = vn_statfile, 123 .fo_stat = vn_statfile,
124 .fo_close = vn_closefile, 124 .fo_close = vn_closefile,
125 .fo_kqfilter = vn_kqfilter, 125 .fo_kqfilter = vn_kqfilter,
126 .fo_restart = fnullop_restart, 126 .fo_restart = fnullop_restart,
127}; 127};
128 128
129/* 129/*
130 * Common code for vnode open operations. 130 * Common code for vnode open operations.
131 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 131 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
132 */ 132 */
133int 133int
134vn_open(struct nameidata *ndp, int fmode, int cmode) 134vn_open(struct nameidata *ndp, int fmode, int cmode)
135{ 135{
136 struct vnode *vp; 136 struct vnode *vp;
137 struct lwp *l = curlwp; 137 struct lwp *l = curlwp;
138 kauth_cred_t cred = l->l_cred; 138 kauth_cred_t cred = l->l_cred;
139 struct vattr va; 139 struct vattr va;
140 int error; 140 int error;
141 char *path; 141 char *path;
142 142
143 if ((fmode & (O_CREAT | O_DIRECTORY)) == (O_CREAT | O_DIRECTORY)) 143 if ((fmode & (O_CREAT | O_DIRECTORY)) == (O_CREAT | O_DIRECTORY))
144 return EINVAL; 144 return EINVAL;
145 145
146 ndp->ni_cnd.cn_flags &= TRYEMULROOT | NOCHROOT; 146 ndp->ni_cnd.cn_flags &= TRYEMULROOT | NOCHROOT;
147 147
148 if (fmode & O_CREAT) { 148 if (fmode & O_CREAT) {
149 ndp->ni_cnd.cn_nameiop = CREATE; 149 ndp->ni_cnd.cn_nameiop = CREATE;
150 ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF; 150 ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF;
151 if ((fmode & O_EXCL) == 0 && 151 if ((fmode & O_EXCL) == 0 &&
152 ((fmode & O_NOFOLLOW) == 0)) 152 ((fmode & O_NOFOLLOW) == 0))
153 ndp->ni_cnd.cn_flags |= FOLLOW; 153 ndp->ni_cnd.cn_flags |= FOLLOW;
154 } else { 154 } else {
155 ndp->ni_cnd.cn_nameiop = LOOKUP; 155 ndp->ni_cnd.cn_nameiop = LOOKUP;
156 ndp->ni_cnd.cn_flags |= LOCKLEAF; 156 ndp->ni_cnd.cn_flags |= LOCKLEAF;
157 if ((fmode & O_NOFOLLOW) == 0) 157 if ((fmode & O_NOFOLLOW) == 0)
158 ndp->ni_cnd.cn_flags |= FOLLOW; 158 ndp->ni_cnd.cn_flags |= FOLLOW;
159 } 159 }
160 160
161 VERIEXEC_PATH_GET(ndp->ni_dirp, ndp->ni_segflg, ndp->ni_dirp, path); 161 VERIEXEC_PATH_GET(ndp->ni_dirp, ndp->ni_segflg, ndp->ni_dirp, path);
162 162
163 error = namei(ndp); 163 error = namei(ndp);
164 if (error) 164 if (error)
165 goto out; 165 goto out;
166 166
167 vp = ndp->ni_vp; 167 vp = ndp->ni_vp;
168 168
169#if NVERIEXEC > 0 169#if NVERIEXEC > 0
170 error = veriexec_openchk(l, ndp->ni_vp, ndp->ni_dirp, fmode); 170 error = veriexec_openchk(l, ndp->ni_vp, ndp->ni_dirp, fmode);
171 if (error) 171 if (error)
172 goto bad; 172 goto bad;
173#endif /* NVERIEXEC > 0 */ 173#endif /* NVERIEXEC > 0 */
174 174
175 if (fmode & O_CREAT) { 175 if (fmode & O_CREAT) {
176 if (ndp->ni_vp == NULL) { 176 if (ndp->ni_vp == NULL) {
177 vattr_null(&va); 177 vattr_null(&va);
178 va.va_type = VREG; 178 va.va_type = VREG;
179 va.va_mode = cmode; 179 va.va_mode = cmode;
180 if (fmode & O_EXCL) 180 if (fmode & O_EXCL)
181 va.va_vaflags |= VA_EXCLUSIVE; 181 va.va_vaflags |= VA_EXCLUSIVE;
182 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 182 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
183 &ndp->ni_cnd, &va); 183 &ndp->ni_cnd, &va);
184 if (error) 184 if (error)
185 goto out; 185 goto out;
186 fmode &= ~O_TRUNC; 186 fmode &= ~O_TRUNC;
187 vp = ndp->ni_vp; 187 vp = ndp->ni_vp;
188 } else { 188 } else {
189 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 189 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
190 if (ndp->ni_dvp == ndp->ni_vp) 190 if (ndp->ni_dvp == ndp->ni_vp)
191 vrele(ndp->ni_dvp); 191 vrele(ndp->ni_dvp);
192 else 192 else
193 vput(ndp->ni_dvp); 193 vput(ndp->ni_dvp);
194 ndp->ni_dvp = NULL; 194 ndp->ni_dvp = NULL;
195 vp = ndp->ni_vp; 195 vp = ndp->ni_vp;
196 if (fmode & O_EXCL) { 196 if (fmode & O_EXCL) {
197 error = EEXIST; 197 error = EEXIST;
198 goto bad; 198 goto bad;
199 } 199 }
200 fmode &= ~O_CREAT; 200 fmode &= ~O_CREAT;
201 } 201 }
202 } else { 202 } else {
203 vp = ndp->ni_vp; 203 vp = ndp->ni_vp;
204 } 204 }
205 if (vp->v_type == VSOCK) { 205 if (vp->v_type == VSOCK) {
206 error = EOPNOTSUPP; 206 error = EOPNOTSUPP;
207 goto bad; 207 goto bad;
208 } 208 }
209 if (ndp->ni_vp->v_type == VLNK) { 209 if (ndp->ni_vp->v_type == VLNK) {
210 error = EFTYPE; 210 error = EFTYPE;
211 goto bad; 211 goto bad;
212 } 212 }
213 213
214 if ((fmode & O_CREAT) == 0) { 214 if ((fmode & O_CREAT) == 0) {
215 error = vn_openchk(vp, cred, fmode); 215 error = vn_openchk(vp, cred, fmode);
216 if (error != 0) 216 if (error != 0)
217 goto bad; 217 goto bad;
218 } 218 }
219 219
220 if (fmode & O_TRUNC) { 220 if (fmode & O_TRUNC) {
221 vattr_null(&va); 221 vattr_null(&va);
222 va.va_size = 0; 222 va.va_size = 0;
223 error = VOP_SETATTR(vp, &va, cred); 223 error = VOP_SETATTR(vp, &va, cred);
224 if (error != 0) 224 if (error != 0)
225 goto bad; 225 goto bad;
226 } 226 }
227 if ((error = VOP_OPEN(vp, fmode, cred)) != 0) 227 if ((error = VOP_OPEN(vp, fmode, cred)) != 0)
228 goto bad; 228 goto bad;
229 if (fmode & FWRITE) { 229 if (fmode & FWRITE) {
230 mutex_enter(&vp->v_interlock); 230 mutex_enter(&vp->v_interlock);
231 vp->v_writecount++; 231 vp->v_writecount++;
232 mutex_exit(&vp->v_interlock); 232 mutex_exit(&vp->v_interlock);
233 } 233 }
234 234
235bad: 235bad:
236 if (error) 236 if (error)
237 vput(vp); 237 vput(vp);
238out: 238out:
239 VERIEXEC_PATH_PUT(path); 239 VERIEXEC_PATH_PUT(path);
240 return (error); 240 return (error);
241} 241}
242 242
243/* 243/*
244 * Check for write permissions on the specified vnode. 244 * Check for write permissions on the specified vnode.
245 * Prototype text segments cannot be written. 245 * Prototype text segments cannot be written.
246 */ 246 */
247int 247int
248vn_writechk(struct vnode *vp) 248vn_writechk(struct vnode *vp)
249{ 249{
250 250
251 /* 251 /*
252 * If the vnode is in use as a process's text, 252 * If the vnode is in use as a process's text,
253 * we can't allow writing. 253 * we can't allow writing.
254 */ 254 */
255 if (vp->v_iflag & VI_TEXT) 255 if (vp->v_iflag & VI_TEXT)
256 return (ETXTBSY); 256 return (ETXTBSY);
257 return (0); 257 return (0);
258} 258}
259 259
260int 260int
261vn_openchk(struct vnode *vp, kauth_cred_t cred, int fflags) 261vn_openchk(struct vnode *vp, kauth_cred_t cred, int fflags)
262{ 262{
263 int permbits = 0; 263 int permbits = 0;
264 int error; 264 int error;
265 265
266 if ((fflags & O_DIRECTORY) != 0 && vp->v_type != VDIR) 266 if ((fflags & O_DIRECTORY) != 0 && vp->v_type != VDIR)
267 return ENOTDIR; 267 return ENOTDIR;
268 268
269 if ((fflags & FREAD) != 0) { 269 if ((fflags & FREAD) != 0) {
270 permbits = VREAD; 270 permbits = VREAD;
271 } 271 }
272 if ((fflags & (FWRITE | O_TRUNC)) != 0) { 272 if ((fflags & (FWRITE | O_TRUNC)) != 0) {
273 permbits |= VWRITE; 273 permbits |= VWRITE;
274 if (vp->v_type == VDIR) { 274 if (vp->v_type == VDIR) {
275 error = EISDIR; 275 error = EISDIR;
276 goto bad; 276 goto bad;
277 } 277 }
278 error = vn_writechk(vp); 278 error = vn_writechk(vp);
279 if (error != 0) 279 if (error != 0)
280 goto bad; 280 goto bad;
281 } 281 }
282 error = VOP_ACCESS(vp, permbits, cred); 282 error = VOP_ACCESS(vp, permbits, cred);
283bad: 283bad:
284 return error; 284 return error;
285} 285}
286 286
287/* 287/*
288 * Mark a vnode as having executable mappings. 288 * Mark a vnode as having executable mappings.
289 */ 289 */
290void 290void
291vn_markexec(struct vnode *vp) 291vn_markexec(struct vnode *vp)
292{ 292{
293 293
294 if ((vp->v_iflag & VI_EXECMAP) != 0) { 294 if ((vp->v_iflag & VI_EXECMAP) != 0) {
295 /* Safe unlocked, as long as caller holds a reference. */ 295 /* Safe unlocked, as long as caller holds a reference. */
296 return; 296 return;
297 } 297 }
298 298
299 mutex_enter(&vp->v_interlock); 299 mutex_enter(&vp->v_interlock);
300 if ((vp->v_iflag & VI_EXECMAP) == 0) { 300 if ((vp->v_iflag & VI_EXECMAP) == 0) {
301 atomic_add_int(&uvmexp.filepages, -vp->v_uobj.uo_npages); 301 atomic_add_int(&uvmexp.filepages, -vp->v_uobj.uo_npages);
302 atomic_add_int(&uvmexp.execpages, vp->v_uobj.uo_npages); 302 atomic_add_int(&uvmexp.execpages, vp->v_uobj.uo_npages);
303 vp->v_iflag |= VI_EXECMAP; 303 vp->v_iflag |= VI_EXECMAP;
304 } 304 }
305 mutex_exit(&vp->v_interlock); 305 mutex_exit(&vp->v_interlock);
306} 306}
307 307
308/* 308/*
309 * Mark a vnode as being the text of a process. 309 * Mark a vnode as being the text of a process.
310 * Fail if the vnode is currently writable. 310 * Fail if the vnode is currently writable.
311 */ 311 */
312int 312int
313vn_marktext(struct vnode *vp) 313vn_marktext(struct vnode *vp)
314{ 314{
315 315
316 if ((vp->v_iflag & (VI_TEXT|VI_EXECMAP)) == (VI_TEXT|VI_EXECMAP)) { 316 if ((vp->v_iflag & (VI_TEXT|VI_EXECMAP)) == (VI_TEXT|VI_EXECMAP)) {
317 /* Safe unlocked, as long as caller holds a reference. */ 317 /* Safe unlocked, as long as caller holds a reference. */
318 return (0); 318 return (0);
319 } 319 }
320 320
321 mutex_enter(&vp->v_interlock); 321 mutex_enter(&vp->v_interlock);
322 if (vp->v_writecount != 0) { 322 if (vp->v_writecount != 0) {
323 KASSERT((vp->v_iflag & VI_TEXT) == 0); 323 KASSERT((vp->v_iflag & VI_TEXT) == 0);
324 mutex_exit(&vp->v_interlock); 324 mutex_exit(&vp->v_interlock);
325 return (ETXTBSY); 325 return (ETXTBSY);
326 } 326 }
327 if ((vp->v_iflag & VI_EXECMAP) == 0) { 327 if ((vp->v_iflag & VI_EXECMAP) == 0) {
328 atomic_add_int(&uvmexp.filepages, -vp->v_uobj.uo_npages); 328 atomic_add_int(&uvmexp.filepages, -vp->v_uobj.uo_npages);
329 atomic_add_int(&uvmexp.execpages, vp->v_uobj.uo_npages); 329 atomic_add_int(&uvmexp.execpages, vp->v_uobj.uo_npages);
330 } 330 }
331 vp->v_iflag |= (VI_TEXT | VI_EXECMAP); 331 vp->v_iflag |= (VI_TEXT | VI_EXECMAP);
332 mutex_exit(&vp->v_interlock); 332 mutex_exit(&vp->v_interlock);
333 return (0); 333 return (0);
334} 334}
335 335
336/* 336/*
337 * Vnode close call 337 * Vnode close call
338 * 338 *
339 * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node. 339 * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node.
340 */ 340 */
341int 341int
342vn_close(struct vnode *vp, int flags, kauth_cred_t cred) 342vn_close(struct vnode *vp, int flags, kauth_cred_t cred)
343{ 343{
344 int error; 344 int error;
345 345
346 if (flags & FWRITE) { 346 if (flags & FWRITE) {
347 mutex_enter(&vp->v_interlock); 347 mutex_enter(&vp->v_interlock);
348 vp->v_writecount--; 348 vp->v_writecount--;
349 mutex_exit(&vp->v_interlock); 349 mutex_exit(&vp->v_interlock);
350 } 350 }
351 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 351 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
352 error = VOP_CLOSE(vp, flags, cred); 352 error = VOP_CLOSE(vp, flags, cred);
353 vput(vp); 353 vput(vp);
354 return (error); 354 return (error);
355} 355}
356 356
357static int 357static int
358enforce_rlimit_fsize(struct vnode *vp, struct uio *uio, int ioflag) 358enforce_rlimit_fsize(struct vnode *vp, struct uio *uio, int ioflag)
359{ 359{
360 struct lwp *l = curlwp; 360 struct lwp *l = curlwp;
361 off_t testoff; 361 off_t testoff;
362 362
363 if (uio->uio_rw != UIO_WRITE || vp->v_type != VREG) 363 if (uio->uio_rw != UIO_WRITE || vp->v_type != VREG)
364 return 0; 364 return 0;
365 365
366 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 366 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
367 if (ioflag & IO_APPEND) 367 if (ioflag & IO_APPEND)
368 testoff = vp->v_size; 368 testoff = vp->v_size;
369 else 369 else
370 testoff = uio->uio_offset; 370 testoff = uio->uio_offset;
371 371
372 if (testoff + uio->uio_resid > 372 if (testoff + uio->uio_resid >
373 l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 373 l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
374 mutex_enter(proc_lock); 374 mutex_enter(proc_lock);
375 psignal(l->l_proc, SIGXFSZ); 375 psignal(l->l_proc, SIGXFSZ);
376 mutex_exit(proc_lock); 376 mutex_exit(proc_lock);
377 return EFBIG; 377 return EFBIG;
378 } 378 }
379 379
380 return 0; 380 return 0;
381} 381}
382 382
383/* 383/*
384 * Package up an I/O request on a vnode into a uio and do it. 384 * Package up an I/O request on a vnode into a uio and do it.
385 */ 385 */
386int 386int
387vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, 387vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset,
388 enum uio_seg segflg, int ioflg, kauth_cred_t cred, size_t *aresid, 388 enum uio_seg segflg, int ioflg, kauth_cred_t cred, size_t *aresid,
389 struct lwp *l) 389 struct lwp *l)
390{ 390{
391 struct uio auio; 391 struct uio auio;
392 struct iovec aiov; 392 struct iovec aiov;
393 int error; 393 int error;
394 394
395 if ((ioflg & IO_NODELOCKED) == 0) { 395 if ((ioflg & IO_NODELOCKED) == 0) {
396 if (rw == UIO_READ) { 396 if (rw == UIO_READ) {
397 vn_lock(vp, LK_SHARED | LK_RETRY); 397 vn_lock(vp, LK_SHARED | LK_RETRY);
398 } else /* UIO_WRITE */ { 398 } else /* UIO_WRITE */ {
399 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 399 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
400 } 400 }
401 } 401 }
402 auio.uio_iov = &aiov; 402 auio.uio_iov = &aiov;
403 auio.uio_iovcnt = 1; 403 auio.uio_iovcnt = 1;
404 aiov.iov_base = base; 404 aiov.iov_base = base;
405 aiov.iov_len = len; 405 aiov.iov_len = len;
406 auio.uio_resid = len; 406 auio.uio_resid = len;
407 auio.uio_offset = offset; 407 auio.uio_offset = offset;
408 auio.uio_rw = rw; 408 auio.uio_rw = rw;
409 if (segflg == UIO_SYSSPACE) { 409 if (segflg == UIO_SYSSPACE) {
410 UIO_SETUP_SYSSPACE(&auio); 410 UIO_SETUP_SYSSPACE(&auio);
411 } else { 411 } else {
412 auio.uio_vmspace = l->l_proc->p_vmspace; 412 auio.uio_vmspace = l->l_proc->p_vmspace;
413 } 413 }
414 414
415 if ((error = enforce_rlimit_fsize(vp, &auio, ioflg)) != 0) 415 if ((error = enforce_rlimit_fsize(vp, &auio, ioflg)) != 0)
416 goto out; 416 goto out;
417 417
418 if (rw == UIO_READ) { 418 if (rw == UIO_READ) {
419 error = VOP_READ(vp, &auio, ioflg, cred); 419 error = VOP_READ(vp, &auio, ioflg, cred);
420 } else { 420 } else {
421 error = VOP_WRITE(vp, &auio, ioflg, cred); 421 error = VOP_WRITE(vp, &auio, ioflg, cred);
422 } 422 }
423 423
424 if (aresid) 424 if (aresid)
425 *aresid = auio.uio_resid; 425 *aresid = auio.uio_resid;
426 else 426 else
427 if (auio.uio_resid && error == 0) 427 if (auio.uio_resid && error == 0)
428 error = EIO; 428 error = EIO;
429 429
430 out: 430 out:
431 if ((ioflg & IO_NODELOCKED) == 0) { 431 if ((ioflg & IO_NODELOCKED) == 0) {
432 VOP_UNLOCK(vp); 432 VOP_UNLOCK(vp);
433 } 433 }
434 return (error); 434 return (error);
435} 435}
436 436
437int 437int
438vn_readdir(file_t *fp, char *bf, int segflg, u_int count, int *done, 438vn_readdir(file_t *fp, char *bf, int segflg, u_int count, int *done,
439 struct lwp *l, off_t **cookies, int *ncookies) 439 struct lwp *l, off_t **cookies, int *ncookies)
440{ 440{
441 struct vnode *vp = (struct vnode *)fp->f_data; 441 struct vnode *vp = (struct vnode *)fp->f_data;
442 struct iovec aiov; 442 struct iovec aiov;
443 struct uio auio; 443 struct uio auio;
444 int error, eofflag; 444 int error, eofflag;
445 445
446 /* Limit the size on any kernel buffers used by VOP_READDIR */ 446 /* Limit the size on any kernel buffers used by VOP_READDIR */
447 count = min(MAXBSIZE, count); 447 count = min(MAXBSIZE, count);
448 448
449unionread: 449unionread:
450 if (vp->v_type != VDIR) 450 if (vp->v_type != VDIR)
451 return (EINVAL); 451 return (EINVAL);
452 aiov.iov_base = bf; 452 aiov.iov_base = bf;
453 aiov.iov_len = count; 453 aiov.iov_len = count;
454 auio.uio_iov = &aiov; 454 auio.uio_iov = &aiov;
455 auio.uio_iovcnt = 1; 455 auio.uio_iovcnt = 1;
456 auio.uio_rw = UIO_READ; 456 auio.uio_rw = UIO_READ;
457 if (segflg == UIO_SYSSPACE) { 457 if (segflg == UIO_SYSSPACE) {
458 UIO_SETUP_SYSSPACE(&auio); 458 UIO_SETUP_SYSSPACE(&auio);
459 } else { 459 } else {
460 KASSERT(l == curlwp); 460 KASSERT(l == curlwp);
461 auio.uio_vmspace = l->l_proc->p_vmspace; 461 auio.uio_vmspace = l->l_proc->p_vmspace;
462 } 462 }
463 auio.uio_resid = count; 463 auio.uio_resid = count;
464 vn_lock(vp, LK_SHARED | LK_RETRY); 464 vn_lock(vp, LK_SHARED | LK_RETRY);
465 auio.uio_offset = fp->f_offset; 465 auio.uio_offset = fp->f_offset;
466 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies, 466 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies,
467 ncookies); 467 ncookies);
468 mutex_enter(&fp->f_lock); 468 mutex_enter(&fp->f_lock);
469 fp->f_offset = auio.uio_offset; 469 fp->f_offset = auio.uio_offset;
470 mutex_exit(&fp->f_lock); 470 mutex_exit(&fp->f_lock);
471 VOP_UNLOCK(vp); 471 VOP_UNLOCK(vp);
472 if (error) 472 if (error)
473 return (error); 473 return (error);
474 474
475 if (count == auio.uio_resid && vn_union_readdir_hook) { 475 if (count == auio.uio_resid && vn_union_readdir_hook) {
476 struct vnode *ovp = vp; 476 struct vnode *ovp = vp;
477 477
478 error = (*vn_union_readdir_hook)(&vp, fp, l); 478 error = (*vn_union_readdir_hook)(&vp, fp, l);
479 if (error) 479 if (error)
480 return (error); 480 return (error);
481 if (vp != ovp) 481 if (vp != ovp)
482 goto unionread; 482 goto unionread;
483 } 483 }
484 484
485 if (count == auio.uio_resid && (vp->v_vflag & VV_ROOT) && 485 if (count == auio.uio_resid && (vp->v_vflag & VV_ROOT) &&
486 (vp->v_mount->mnt_flag & MNT_UNION)) { 486 (vp->v_mount->mnt_flag & MNT_UNION)) {
487 struct vnode *tvp = vp; 487 struct vnode *tvp = vp;
488 vp = vp->v_mount->mnt_vnodecovered; 488 vp = vp->v_mount->mnt_vnodecovered;
489 vref(vp); 489 vref(vp);
490 mutex_enter(&fp->f_lock); 490 mutex_enter(&fp->f_lock);
491 fp->f_data = vp; 491 fp->f_data = vp;
492 fp->f_offset = 0; 492 fp->f_offset = 0;
493 mutex_exit(&fp->f_lock); 493 mutex_exit(&fp->f_lock);
494 vrele(tvp); 494 vrele(tvp);
495 goto unionread; 495 goto unionread;
496 } 496 }
497 *done = count - auio.uio_resid; 497 *done = count - auio.uio_resid;
498 return error; 498 return error;
499} 499}
500 500
501/* 501/*
502 * File table vnode read routine. 502 * File table vnode read routine.
503 */ 503 */
504static int 504static int
505vn_read(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred, 505vn_read(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
506 int flags) 506 int flags)
507{ 507{
508 struct vnode *vp = (struct vnode *)fp->f_data; 508 struct vnode *vp = (struct vnode *)fp->f_data;
509 int count, error, ioflag, fflag; 509 int count, error, ioflag, fflag;
510 510
511 ioflag = IO_ADV_ENCODE(fp->f_advice); 511 ioflag = IO_ADV_ENCODE(fp->f_advice);
512 fflag = fp->f_flag; 512 fflag = fp->f_flag;
513 if (fflag & FNONBLOCK) 513 if (fflag & FNONBLOCK)
514 ioflag |= IO_NDELAY; 514 ioflag |= IO_NDELAY;
515 if ((fflag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC)) 515 if ((fflag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC))
516 ioflag |= IO_SYNC; 516 ioflag |= IO_SYNC;
517 if (fflag & FALTIO) 517 if (fflag & FALTIO)
518 ioflag |= IO_ALTSEMANTICS; 518 ioflag |= IO_ALTSEMANTICS;
519 if (fflag & FDIRECT) 519 if (fflag & FDIRECT)
520 ioflag |= IO_DIRECT; 520 ioflag |= IO_DIRECT;
521 vn_lock(vp, LK_SHARED | LK_RETRY); 521 vn_lock(vp, LK_SHARED | LK_RETRY);
522 uio->uio_offset = *offset; 522 uio->uio_offset = *offset;
523 count = uio->uio_resid; 523 count = uio->uio_resid;
524 error = VOP_READ(vp, uio, ioflag, cred); 524 error = VOP_READ(vp, uio, ioflag, cred);
525 if (flags & FOF_UPDATE_OFFSET) 525 if (flags & FOF_UPDATE_OFFSET)
526 *offset += count - uio->uio_resid; 526 *offset += count - uio->uio_resid;
527 VOP_UNLOCK(vp); 527 VOP_UNLOCK(vp);
528 return (error); 528 return (error);
529} 529}
530 530
531/* 531/*
532 * File table vnode write routine. 532 * File table vnode write routine.
533 */ 533 */
534static int 534static int
535vn_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred, 535vn_write(file_t *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
536 int flags) 536 int flags)
537{ 537{
538 struct vnode *vp = (struct vnode *)fp->f_data; 538 struct vnode *vp = (struct vnode *)fp->f_data;
539 int count, error, ioflag, fflag; 539 int count, error, ioflag, fflag;
540 540
541 ioflag = IO_ADV_ENCODE(fp->f_advice) | IO_UNIT; 541 ioflag = IO_ADV_ENCODE(fp->f_advice) | IO_UNIT;
542 fflag = fp->f_flag; 542 fflag = fp->f_flag;
543 if (vp->v_type == VREG && (fflag & O_APPEND)) 543 if (vp->v_type == VREG && (fflag & O_APPEND))
544 ioflag |= IO_APPEND; 544 ioflag |= IO_APPEND;
545 if (fflag & FNONBLOCK) 545 if (fflag & FNONBLOCK)
546 ioflag |= IO_NDELAY; 546 ioflag |= IO_NDELAY;
547 if (fflag & FFSYNC || 547 if (fflag & FFSYNC ||
548 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) 548 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
549 ioflag |= IO_SYNC; 549 ioflag |= IO_SYNC;
550 else if (fflag & FDSYNC) 550 else if (fflag & FDSYNC)
551 ioflag |= IO_DSYNC; 551 ioflag |= IO_DSYNC;
552 if (fflag & FALTIO) 552 if (fflag & FALTIO)
553 ioflag |= IO_ALTSEMANTICS; 553 ioflag |= IO_ALTSEMANTICS;
554 if (fflag & FDIRECT) 554 if (fflag & FDIRECT)
555 ioflag |= IO_DIRECT; 555 ioflag |= IO_DIRECT;
556 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 556 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
557 uio->uio_offset = *offset; 557 uio->uio_offset = *offset;
558 count = uio->uio_resid; 558 count = uio->uio_resid;
559 559
560 if ((error = enforce_rlimit_fsize(vp, uio, ioflag)) != 0) 560 if ((error = enforce_rlimit_fsize(vp, uio, ioflag)) != 0)
561 goto out; 561 goto out;
562 562
563 error = VOP_WRITE(vp, uio, ioflag, cred); 563 error = VOP_WRITE(vp, uio, ioflag, cred);
564 564
565 if (flags & FOF_UPDATE_OFFSET) { 565 if (flags & FOF_UPDATE_OFFSET) {
566 if (ioflag & IO_APPEND) { 566 if (ioflag & IO_APPEND) {
567 /* 567 /*
568 * SUSv3 describes behaviour for count = 0 as following: 568 * SUSv3 describes behaviour for count = 0 as following:
569 * "Before any action ... is taken, and if nbyte is zero 569 * "Before any action ... is taken, and if nbyte is zero
570 * and the file is a regular file, the write() function 570 * and the file is a regular file, the write() function
571 * ... in the absence of errors ... shall return zero 571 * ... in the absence of errors ... shall return zero
572 * and have no other results." 572 * and have no other results."
573 */  573 */
574 if (count) 574 if (count)
575 *offset = uio->uio_offset; 575 *offset = uio->uio_offset;
576 } else 576 } else
577 *offset += count - uio->uio_resid; 577 *offset += count - uio->uio_resid;
578 } 578 }
579 579
580 out: 580 out:
581 VOP_UNLOCK(vp); 581 VOP_UNLOCK(vp);
582 return (error); 582 return (error);
583} 583}
584 584
585/* 585/*
586 * File table vnode stat routine. 586 * File table vnode stat routine.
587 */ 587 */
588static int 588static int
589vn_statfile(file_t *fp, struct stat *sb) 589vn_statfile(file_t *fp, struct stat *sb)
590{ 590{
591 struct vnode *vp = fp->f_data; 591 struct vnode *vp = fp->f_data;
592 int error; 592 int error;
593 593
594 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 594 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
595 error = vn_stat(vp, sb); 595 error = vn_stat(vp, sb);
596 VOP_UNLOCK(vp); 596 VOP_UNLOCK(vp);
597 return error; 597 return error;
598} 598}
599 599
600int 600int
601vn_stat(struct vnode *vp, struct stat *sb) 601vn_stat(struct vnode *vp, struct stat *sb)
602{ 602{
603 struct vattr va; 603 struct vattr va;
604 int error; 604 int error;
605 mode_t mode; 605 mode_t mode;
606 606
607 memset(&va, 0, sizeof(va)); 607 memset(&va, 0, sizeof(va));
608 error = VOP_GETATTR(vp, &va, kauth_cred_get()); 608 error = VOP_GETATTR(vp, &va, kauth_cred_get());
609 if (error) 609 if (error)
610 return (error); 610 return (error);
611 /* 611 /*
612 * Copy from vattr table 612 * Copy from vattr table
613 */ 613 */
 614 memset(sb, 0, sizeof(*sb));
614 sb->st_dev = va.va_fsid; 615 sb->st_dev = va.va_fsid;
615 sb->st_ino = va.va_fileid; 616 sb->st_ino = va.va_fileid;
616 mode = va.va_mode; 617 mode = va.va_mode;
617 switch (vp->v_type) { 618 switch (vp->v_type) {
618 case VREG: 619 case VREG:
619 mode |= S_IFREG; 620 mode |= S_IFREG;
620 break; 621 break;
621 case VDIR: 622 case VDIR:
622 mode |= S_IFDIR; 623 mode |= S_IFDIR;
623 break; 624 break;
624 case VBLK: 625 case VBLK:
625 mode |= S_IFBLK; 626 mode |= S_IFBLK;
626 break; 627 break;
627 case VCHR: 628 case VCHR:
628 mode |= S_IFCHR; 629 mode |= S_IFCHR;
629 break; 630 break;
630 case VLNK: 631 case VLNK:
631 mode |= S_IFLNK; 632 mode |= S_IFLNK;
632 break; 633 break;
633 case VSOCK: 634 case VSOCK:
634 mode |= S_IFSOCK; 635 mode |= S_IFSOCK;
635 break; 636 break;
636 case VFIFO: 637 case VFIFO:
637 mode |= S_IFIFO; 638 mode |= S_IFIFO;
638 break; 639 break;
639 default: 640 default:
640 return (EBADF); 641 return (EBADF);
641 }; 642 };
642 sb->st_mode = mode; 643 sb->st_mode = mode;
643 sb->st_nlink = va.va_nlink; 644 sb->st_nlink = va.va_nlink;
644 sb->st_uid = va.va_uid; 645 sb->st_uid = va.va_uid;
645 sb->st_gid = va.va_gid; 646 sb->st_gid = va.va_gid;
646 sb->st_rdev = va.va_rdev; 647 sb->st_rdev = va.va_rdev;
647 sb->st_size = va.va_size; 648 sb->st_size = va.va_size;
648 sb->st_atimespec = va.va_atime; 649 sb->st_atimespec = va.va_atime;
649 sb->st_mtimespec = va.va_mtime; 650 sb->st_mtimespec = va.va_mtime;
650 sb->st_ctimespec = va.va_ctime; 651 sb->st_ctimespec = va.va_ctime;
651 sb->st_birthtimespec = va.va_birthtime; 652 sb->st_birthtimespec = va.va_birthtime;
652 sb->st_blksize = va.va_blocksize; 653 sb->st_blksize = va.va_blocksize;
653 sb->st_flags = va.va_flags; 654 sb->st_flags = va.va_flags;
654 sb->st_gen = 0; 655 sb->st_gen = 0;
655 sb->st_blocks = va.va_bytes / S_BLKSIZE; 656 sb->st_blocks = va.va_bytes / S_BLKSIZE;
656 memset(sb->st_spare, 0, sizeof(sb->st_spare)); 
657 return (0); 657 return (0);
658} 658}
659 659
660/* 660/*
661 * File table vnode fcntl routine. 661 * File table vnode fcntl routine.
662 */ 662 */
663static int 663static int
664vn_fcntl(file_t *fp, u_int com, void *data) 664vn_fcntl(file_t *fp, u_int com, void *data)
665{ 665{
666 struct vnode *vp = fp->f_data; 666 struct vnode *vp = fp->f_data;
667 int error; 667 int error;
668 668
669 error = VOP_FCNTL(vp, com, data, fp->f_flag, kauth_cred_get()); 669 error = VOP_FCNTL(vp, com, data, fp->f_flag, kauth_cred_get());
670 return (error); 670 return (error);
671} 671}
672 672
673/* 673/*
674 * File table vnode ioctl routine. 674 * File table vnode ioctl routine.
675 */ 675 */
676static int 676static int
677vn_ioctl(file_t *fp, u_long com, void *data) 677vn_ioctl(file_t *fp, u_long com, void *data)
678{ 678{
679 struct vnode *vp = fp->f_data, *ovp; 679 struct vnode *vp = fp->f_data, *ovp;
680 struct vattr vattr; 680 struct vattr vattr;
681 int error; 681 int error;
682 682
683 switch (vp->v_type) { 683 switch (vp->v_type) {
684 684
685 case VREG: 685 case VREG:
686 case VDIR: 686 case VDIR:
687 if (com == FIONREAD) { 687 if (com == FIONREAD) {
688 error = VOP_GETATTR(vp, &vattr, 688 error = VOP_GETATTR(vp, &vattr,
689 kauth_cred_get()); 689 kauth_cred_get());
690 if (error) 690 if (error)
691 return (error); 691 return (error);
692 *(int *)data = vattr.va_size - fp->f_offset; 692 *(int *)data = vattr.va_size - fp->f_offset;
693 return (0); 693 return (0);
694 } 694 }
695 if ((com == FIONWRITE) || (com == FIONSPACE)) { 695 if ((com == FIONWRITE) || (com == FIONSPACE)) {
696 /* 696 /*
697 * Files don't have send queues, so there never 697 * Files don't have send queues, so there never
698 * are any bytes in them, nor is there any 698 * are any bytes in them, nor is there any
699 * open space in them. 699 * open space in them.
700 */ 700 */
701 *(int *)data = 0; 701 *(int *)data = 0;
702 return (0); 702 return (0);
703 } 703 }
704 if (com == FIOGETBMAP) { 704 if (com == FIOGETBMAP) {
705 daddr_t *block; 705 daddr_t *block;
706 706
707 if (*(daddr_t *)data < 0) 707 if (*(daddr_t *)data < 0)
708 return (EINVAL); 708 return (EINVAL);
709 block = (daddr_t *)data; 709 block = (daddr_t *)data;
710 return (VOP_BMAP(vp, *block, NULL, block, NULL)); 710 return (VOP_BMAP(vp, *block, NULL, block, NULL));
711 } 711 }
712 if (com == OFIOGETBMAP) { 712 if (com == OFIOGETBMAP) {
713 daddr_t ibn, obn; 713 daddr_t ibn, obn;
714 714
715 if (*(int32_t *)data < 0) 715 if (*(int32_t *)data < 0)
716 return (EINVAL); 716 return (EINVAL);
717 ibn = (daddr_t)*(int32_t *)data; 717 ibn = (daddr_t)*(int32_t *)data;
718 error = VOP_BMAP(vp, ibn, NULL, &obn, NULL); 718 error = VOP_BMAP(vp, ibn, NULL, &obn, NULL);
719 *(int32_t *)data = (int32_t)obn; 719 *(int32_t *)data = (int32_t)obn;
720 return error; 720 return error;
721 } 721 }
722 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 722 if (com == FIONBIO || com == FIOASYNC) /* XXX */
723 return (0); /* XXX */ 723 return (0); /* XXX */
724 /* fall into ... */ 724 /* fall into ... */
725 case VFIFO: 725 case VFIFO:
726 case VCHR: 726 case VCHR:
727 case VBLK: 727 case VBLK:
728 error = VOP_IOCTL(vp, com, data, fp->f_flag, 728 error = VOP_IOCTL(vp, com, data, fp->f_flag,
729 kauth_cred_get()); 729 kauth_cred_get());
730 if (error == 0 && com == TIOCSCTTY) { 730 if (error == 0 && com == TIOCSCTTY) {
731 vref(vp); 731 vref(vp);
732 mutex_enter(proc_lock); 732 mutex_enter(proc_lock);
733 ovp = curproc->p_session->s_ttyvp; 733 ovp = curproc->p_session->s_ttyvp;
734 curproc->p_session->s_ttyvp = vp; 734 curproc->p_session->s_ttyvp = vp;
735 mutex_exit(proc_lock); 735 mutex_exit(proc_lock);
736 if (ovp != NULL) 736 if (ovp != NULL)
737 vrele(ovp); 737 vrele(ovp);
738 } 738 }
739 return (error); 739 return (error);
740 740
741 default: 741 default:
742 return (EPASSTHROUGH); 742 return (EPASSTHROUGH);
743 } 743 }
744} 744}
745 745
746/* 746/*
747 * File table vnode poll routine. 747 * File table vnode poll routine.
748 */ 748 */
749static int 749static int
750vn_poll(file_t *fp, int events) 750vn_poll(file_t *fp, int events)
751{ 751{
752 752
753 return (VOP_POLL(fp->f_data, events)); 753 return (VOP_POLL(fp->f_data, events));
754} 754}
755 755
756/* 756/*
757 * File table vnode kqfilter routine. 757 * File table vnode kqfilter routine.
758 */ 758 */
759int 759int
760vn_kqfilter(file_t *fp, struct knote *kn) 760vn_kqfilter(file_t *fp, struct knote *kn)
761{ 761{
762 762
763 return (VOP_KQFILTER(fp->f_data, kn)); 763 return (VOP_KQFILTER(fp->f_data, kn));
764} 764}
765 765
766/* 766/*
767 * Check that the vnode is still valid, and if so 767 * Check that the vnode is still valid, and if so
768 * acquire requested lock. 768 * acquire requested lock.
769 */ 769 */
770int 770int
771vn_lock(struct vnode *vp, int flags) 771vn_lock(struct vnode *vp, int flags)
772{ 772{
773 int error; 773 int error;
774 774
775#if 0 775#if 0
776 KASSERT(vp->v_usecount > 0 || (vp->v_iflag & VI_ONWORKLST) != 0); 776 KASSERT(vp->v_usecount > 0 || (vp->v_iflag & VI_ONWORKLST) != 0);
777#endif 777#endif
778 KASSERT((flags & ~(LK_SHARED|LK_EXCLUSIVE|LK_NOWAIT|LK_RETRY)) == 0); 778 KASSERT((flags & ~(LK_SHARED|LK_EXCLUSIVE|LK_NOWAIT|LK_RETRY)) == 0);
779 KASSERT(!mutex_owned(&vp->v_interlock)); 779 KASSERT(!mutex_owned(&vp->v_interlock));
780 780
781#ifdef DIAGNOSTIC 781#ifdef DIAGNOSTIC
782 if (wapbl_vphaswapbl(vp)) 782 if (wapbl_vphaswapbl(vp))
783 WAPBL_JUNLOCK_ASSERT(wapbl_vptomp(vp)); 783 WAPBL_JUNLOCK_ASSERT(wapbl_vptomp(vp));
784#endif 784#endif
785 785
786 do { 786 do {
787 /* 787 /*
788 * XXX PR 37706 forced unmount of file systems is unsafe. 788 * XXX PR 37706 forced unmount of file systems is unsafe.
789 * Race between vclean() and this the remaining problem. 789 * Race between vclean() and this the remaining problem.
790 */ 790 */
791 mutex_enter(&vp->v_interlock); 791 mutex_enter(&vp->v_interlock);
792 if (vp->v_iflag & VI_XLOCK) { 792 if (vp->v_iflag & VI_XLOCK) {
793 if (flags & LK_NOWAIT) { 793 if (flags & LK_NOWAIT) {
794 mutex_exit(&vp->v_interlock); 794 mutex_exit(&vp->v_interlock);
795 return EBUSY; 795 return EBUSY;
796 } 796 }
797 vwait(vp, VI_XLOCK); 797 vwait(vp, VI_XLOCK);
798 mutex_exit(&vp->v_interlock); 798 mutex_exit(&vp->v_interlock);
799 error = ENOENT; 799 error = ENOENT;
800 } else { 800 } else {
801 mutex_exit(&vp->v_interlock); 801 mutex_exit(&vp->v_interlock);
802 error = VOP_LOCK(vp, (flags & ~LK_RETRY)); 802 error = VOP_LOCK(vp, (flags & ~LK_RETRY));
803 if (error == 0 || error == EDEADLK || error == EBUSY) 803 if (error == 0 || error == EDEADLK || error == EBUSY)
804 return (error); 804 return (error);
805 } 805 }
806 } while (flags & LK_RETRY); 806 } while (flags & LK_RETRY);
807 return (error); 807 return (error);
808} 808}
809 809
810/* 810/*
811 * File table vnode close routine. 811 * File table vnode close routine.
812 */ 812 */
813static int 813static int
814vn_closefile(file_t *fp) 814vn_closefile(file_t *fp)
815{ 815{
816 816
817 return vn_close(fp->f_data, fp->f_flag, fp->f_cred); 817 return vn_close(fp->f_data, fp->f_flag, fp->f_cred);
818} 818}
819 819
820/* 820/*
821 * Simplified in-kernel wrapper calls for extended attribute access. 821 * Simplified in-kernel wrapper calls for extended attribute access.
822 * Both calls pass in a NULL credential, authorizing a "kernel" access. 822 * Both calls pass in a NULL credential, authorizing a "kernel" access.
823 * Set IO_NODELOCKED in ioflg if the vnode is already locked. 823 * Set IO_NODELOCKED in ioflg if the vnode is already locked.
824 */ 824 */
825int 825int
826vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace, 826vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace,
827 const char *attrname, size_t *buflen, void *bf, struct lwp *l) 827 const char *attrname, size_t *buflen, void *bf, struct lwp *l)
828{ 828{
829 struct uio auio; 829 struct uio auio;
830 struct iovec aiov; 830 struct iovec aiov;
831 int error; 831 int error;
832 832
833 aiov.iov_len = *buflen; 833 aiov.iov_len = *buflen;
834 aiov.iov_base = bf; 834 aiov.iov_base = bf;
835 835
836 auio.uio_iov = &aiov; 836 auio.uio_iov = &aiov;
837 auio.uio_iovcnt = 1; 837 auio.uio_iovcnt = 1;
838 auio.uio_rw = UIO_READ; 838 auio.uio_rw = UIO_READ;
839 auio.uio_offset = 0; 839 auio.uio_offset = 0;
840 auio.uio_resid = *buflen; 840 auio.uio_resid = *buflen;
841 UIO_SETUP_SYSSPACE(&auio); 841 UIO_SETUP_SYSSPACE(&auio);
842 842
843 if ((ioflg & IO_NODELOCKED) == 0) 843 if ((ioflg & IO_NODELOCKED) == 0)
844 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 844 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
845 845
846 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, NULL); 846 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, NULL);
847 847
848 if ((ioflg & IO_NODELOCKED) == 0) 848 if ((ioflg & IO_NODELOCKED) == 0)
849 VOP_UNLOCK(vp); 849 VOP_UNLOCK(vp);
850 850
851 if (error == 0) 851 if (error == 0)
852 *buflen = *buflen - auio.uio_resid; 852 *buflen = *buflen - auio.uio_resid;
853 853
854 return (error); 854 return (error);
855} 855}
856 856
857/* 857/*
858 * XXX Failure mode if partially written? 858 * XXX Failure mode if partially written?
859 */ 859 */
860int 860int
861vn_extattr_set(struct vnode *vp, int ioflg, int attrnamespace, 861vn_extattr_set(struct vnode *vp, int ioflg, int attrnamespace,
862 const char *attrname, size_t buflen, const void *bf, struct lwp *l) 862 const char *attrname, size_t buflen, const void *bf, struct lwp *l)
863{ 863{
864 struct uio auio; 864 struct uio auio;
865 struct iovec aiov; 865 struct iovec aiov;
866 int error; 866 int error;
867 867
868 aiov.iov_len = buflen; 868 aiov.iov_len = buflen;
869 aiov.iov_base = __UNCONST(bf); /* XXXUNCONST kills const */ 869 aiov.iov_base = __UNCONST(bf); /* XXXUNCONST kills const */
870 870
871 auio.uio_iov = &aiov; 871 auio.uio_iov = &aiov;
872 auio.uio_iovcnt = 1; 872 auio.uio_iovcnt = 1;
873 auio.uio_rw = UIO_WRITE; 873 auio.uio_rw = UIO_WRITE;
874 auio.uio_offset = 0; 874 auio.uio_offset = 0;
875 auio.uio_resid = buflen; 875 auio.uio_resid = buflen;
876 UIO_SETUP_SYSSPACE(&auio); 876 UIO_SETUP_SYSSPACE(&auio);
877 877
878 if ((ioflg & IO_NODELOCKED) == 0) { 878 if ((ioflg & IO_NODELOCKED) == 0) {
879 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 879 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
880 } 880 }
881 881
882 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, NULL); 882 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, NULL);
883 883
884 if ((ioflg & IO_NODELOCKED) == 0) { 884 if ((ioflg & IO_NODELOCKED) == 0) {
885 VOP_UNLOCK(vp); 885 VOP_UNLOCK(vp);
886 } 886 }
887 887
888 return (error); 888 return (error);
889} 889}
890 890
891int 891int
892vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace, 892vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
893 const char *attrname, struct lwp *l) 893 const char *attrname, struct lwp *l)
894{ 894{
895 int error; 895 int error;
896 896
897 if ((ioflg & IO_NODELOCKED) == 0) { 897 if ((ioflg & IO_NODELOCKED) == 0) {
898 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 898 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
899 } 899 }
900 900
901 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, NULL); 901 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, NULL);
902 if (error == EOPNOTSUPP) 902 if (error == EOPNOTSUPP)
903 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, NULL); 903 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, NULL);
904 904
905 if ((ioflg & IO_NODELOCKED) == 0) { 905 if ((ioflg & IO_NODELOCKED) == 0) {
906 VOP_UNLOCK(vp); 906 VOP_UNLOCK(vp);
907 } 907 }
908 908
909 return (error); 909 return (error);
910} 910}
911 911
912void 912void
913vn_ra_allocctx(struct vnode *vp) 913vn_ra_allocctx(struct vnode *vp)
914{ 914{
915 struct uvm_ractx *ra = NULL; 915 struct uvm_ractx *ra = NULL;
916 916
917 KASSERT(mutex_owned(&vp->v_interlock)); 917 KASSERT(mutex_owned(&vp->v_interlock));
918 918
919 if (vp->v_type != VREG) { 919 if (vp->v_type != VREG) {
920 return; 920 return;
921 } 921 }
922 if (vp->v_ractx != NULL) { 922 if (vp->v_ractx != NULL) {
923 return; 923 return;
924 } 924 }
925 if (vp->v_ractx == NULL) { 925 if (vp->v_ractx == NULL) {
926 mutex_exit(&vp->v_interlock); 926 mutex_exit(&vp->v_interlock);
927 ra = uvm_ra_allocctx(); 927 ra = uvm_ra_allocctx();
928 mutex_enter(&vp->v_interlock); 928 mutex_enter(&vp->v_interlock);
929 if (ra != NULL && vp->v_ractx == NULL) { 929 if (ra != NULL && vp->v_ractx == NULL) {
930 vp->v_ractx = ra; 930 vp->v_ractx = ra;
931 ra = NULL; 931 ra = NULL;
932 } 932 }
933 } 933 }
934 if (ra != NULL) { 934 if (ra != NULL) {
935 uvm_ra_freectx(ra); 935 uvm_ra_freectx(ra);
936 } 936 }
937} 937}
938 938
939int 939int
940vn_fifo_bypass(void *v) 940vn_fifo_bypass(void *v)
941{ 941{
942 struct vop_generic_args *ap = v; 942 struct vop_generic_args *ap = v;
943 943
944 return VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, v); 944 return VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, v);
945} 945}