pseudofs_vnops.c (96886) | pseudofs_vnops.c (97940) |
---|---|
1/*- 2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * | 1/*- 2 * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * |
28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 96886 2002-05-19 00:14:50Z jhb $ | 28 * $FreeBSD: head/sys/fs/pseudofs/pseudofs_vnops.c 97940 2002-06-06 16:59:24Z des $ |
29 */ 30 31#include <sys/param.h> 32#include <sys/kernel.h> 33#include <sys/systm.h> 34#include <sys/ctype.h> 35#include <sys/dirent.h> 36#include <sys/fcntl.h> --- 33 unchanged lines hidden (view full) --- 70/* 71 * Returns non-zero if given file is visible to given process 72 */ 73static int 74pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid) 75{ 76 struct proc *proc; 77 int r; | 29 */ 30 31#include <sys/param.h> 32#include <sys/kernel.h> 33#include <sys/systm.h> 34#include <sys/ctype.h> 35#include <sys/dirent.h> 36#include <sys/fcntl.h> --- 33 unchanged lines hidden (view full) --- 70/* 71 * Returns non-zero if given file is visible to given process 72 */ 73static int 74pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid) 75{ 76 struct proc *proc; 77 int r; |
78 | 78 |
79 PFS_TRACE(("%s (pid: %d, req: %d)", 80 pn->pn_name, pid, td->td_proc->p_pid)); 81 82 if (pn->pn_flags & PFS_DISABLED) 83 PFS_RETURN (0); | 79 PFS_TRACE(("%s (pid: %d, req: %d)", 80 pn->pn_name, pid, td->td_proc->p_pid)); 81 82 if (pn->pn_flags & PFS_DISABLED) 83 PFS_RETURN (0); |
84 | 84 |
85 r = 1; 86 if (pid != NO_PID) { 87 if ((proc = pfind(pid)) == NULL) 88 PFS_RETURN (0); 89 if (p_cansee(td, proc) != 0 || 90 (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn))) 91 r = 0; 92 PROC_UNLOCK(proc); --- 5 unchanged lines hidden (view full) --- 98 * Verify permissions 99 */ 100static int 101pfs_access(struct vop_access_args *va) 102{ 103 struct vnode *vn = va->a_vp; 104 struct vattr vattr; 105 int error; | 85 r = 1; 86 if (pid != NO_PID) { 87 if ((proc = pfind(pid)) == NULL) 88 PFS_RETURN (0); 89 if (p_cansee(td, proc) != 0 || 90 (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn))) 91 r = 0; 92 PROC_UNLOCK(proc); --- 5 unchanged lines hidden (view full) --- 98 * Verify permissions 99 */ 100static int 101pfs_access(struct vop_access_args *va) 102{ 103 struct vnode *vn = va->a_vp; 104 struct vattr vattr; 105 int error; |
106 | 106 |
107 PFS_TRACE((((struct pfs_vdata *)vn->v_data)->pvd_pn->pn_name)); | 107 PFS_TRACE((((struct pfs_vdata *)vn->v_data)->pvd_pn->pn_name)); |
108 | 108 |
109 error = VOP_GETATTR(vn, &vattr, va->a_cred, va->a_td); 110 if (error) 111 PFS_RETURN (error); 112 error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid, 113 vattr.va_gid, va->a_mode, va->a_cred, NULL); 114 PFS_RETURN (error); 115} 116 --- 17 unchanged lines hidden (view full) --- 134 */ 135 if (vn->v_usecount > 1 || pn->pn_close == NULL) 136 PFS_RETURN (0); 137 138 if (pvd->pvd_pid != NO_PID) 139 proc = pfind(pvd->pvd_pid); 140 else 141 proc = NULL; | 109 error = VOP_GETATTR(vn, &vattr, va->a_cred, va->a_td); 110 if (error) 111 PFS_RETURN (error); 112 error = vaccess(vn->v_type, vattr.va_mode, vattr.va_uid, 113 vattr.va_gid, va->a_mode, va->a_cred, NULL); 114 PFS_RETURN (error); 115} 116 --- 17 unchanged lines hidden (view full) --- 134 */ 135 if (vn->v_usecount > 1 || pn->pn_close == NULL) 136 PFS_RETURN (0); 137 138 if (pvd->pvd_pid != NO_PID) 139 proc = pfind(pvd->pvd_pid); 140 else 141 proc = NULL; |
142 | 142 |
143 error = (pn->pn_close)(va->a_td, proc, pn); | 143 error = (pn->pn_close)(va->a_td, proc, pn); |
144 | 144 |
145 if (proc != NULL) 146 PROC_UNLOCK(proc); | 145 if (proc != NULL) 146 PROC_UNLOCK(proc); |
147 | 147 |
148 PFS_RETURN (error); 149} 150 151/* 152 * Get file attributes 153 */ 154static int 155pfs_getattr(struct vop_getattr_args *va) 156{ 157 struct vnode *vn = va->a_vp; 158 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 159 struct pfs_node *pn = pvd->pvd_pn; 160 struct vattr *vap = va->a_vap; 161 struct proc *proc; 162 int error = 0; 163 164 PFS_TRACE((pn->pn_name)); | 148 PFS_RETURN (error); 149} 150 151/* 152 * Get file attributes 153 */ 154static int 155pfs_getattr(struct vop_getattr_args *va) 156{ 157 struct vnode *vn = va->a_vp; 158 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 159 struct pfs_node *pn = pvd->pvd_pn; 160 struct vattr *vap = va->a_vap; 161 struct proc *proc; 162 int error = 0; 163 164 PFS_TRACE((pn->pn_name)); |
165 | 165 |
166 VATTR_NULL(vap); 167 vap->va_type = vn->v_type; 168 vap->va_fileid = pn->pn_fileno; 169 vap->va_flags = 0; 170 vap->va_blocksize = PAGE_SIZE; 171 vap->va_bytes = vap->va_size = 0; 172 vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0]; 173 vap->va_nlink = 1; --- 23 unchanged lines hidden (view full) --- 197 vap->va_gid = proc->p_ucred->cr_rgid; 198 if (pn->pn_attr != NULL) 199 error = (pn->pn_attr)(va->a_td, proc, pn, vap); 200 PROC_UNLOCK(proc); 201 } else { 202 vap->va_uid = 0; 203 vap->va_gid = 0; 204 } | 166 VATTR_NULL(vap); 167 vap->va_type = vn->v_type; 168 vap->va_fileid = pn->pn_fileno; 169 vap->va_flags = 0; 170 vap->va_blocksize = PAGE_SIZE; 171 vap->va_bytes = vap->va_size = 0; 172 vap->va_fsid = vn->v_mount->mnt_stat.f_fsid.val[0]; 173 vap->va_nlink = 1; --- 23 unchanged lines hidden (view full) --- 197 vap->va_gid = proc->p_ucred->cr_rgid; 198 if (pn->pn_attr != NULL) 199 error = (pn->pn_attr)(va->a_td, proc, pn, vap); 200 PROC_UNLOCK(proc); 201 } else { 202 vap->va_uid = 0; 203 vap->va_gid = 0; 204 } |
205 | 205 |
206 PFS_RETURN (error); 207} 208 209/* 210 * Perform an ioctl 211 */ 212static int 213pfs_ioctl(struct vop_ioctl_args *va) 214{ 215 struct vnode *vn = va->a_vp; 216 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 217 struct pfs_node *pn = pvd->pvd_pn; 218 struct proc *proc = NULL; 219 int error; 220 221 PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command)); | 206 PFS_RETURN (error); 207} 208 209/* 210 * Perform an ioctl 211 */ 212static int 213pfs_ioctl(struct vop_ioctl_args *va) 214{ 215 struct vnode *vn = va->a_vp; 216 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 217 struct pfs_node *pn = pvd->pvd_pn; 218 struct proc *proc = NULL; 219 int error; 220 221 PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command)); |
222 | 222 |
223 if (vn->v_type != VREG) 224 PFS_RETURN (EINVAL); 225 226 if (pn->pn_ioctl == NULL) 227 PFS_RETURN (ENOTTY); | 223 if (vn->v_type != VREG) 224 PFS_RETURN (EINVAL); 225 226 if (pn->pn_ioctl == NULL) 227 PFS_RETURN (ENOTTY); |
228 | 228 |
229 /* 230 * This is necessary because either process' privileges may 231 * have changed since the open() call. 232 */ 233 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 234 PFS_RETURN (EIO); | 229 /* 230 * This is necessary because either process' privileges may 231 * have changed since the open() call. 232 */ 233 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 234 PFS_RETURN (EIO); |
235 | 235 |
236 /* XXX duplicates bits of pfs_visible() */ 237 if (pvd->pvd_pid != NO_PID) { 238 if ((proc = pfind(pvd->pvd_pid)) == NULL) 239 PFS_RETURN (EIO); 240 _PHOLD(proc); 241 PROC_UNLOCK(proc); 242 } | 236 /* XXX duplicates bits of pfs_visible() */ 237 if (pvd->pvd_pid != NO_PID) { 238 if ((proc = pfind(pvd->pvd_pid)) == NULL) 239 PFS_RETURN (EIO); 240 _PHOLD(proc); 241 PROC_UNLOCK(proc); 242 } |
243 | 243 |
244 error = (pn->pn_ioctl)(curthread, proc, pn, va->a_command, va->a_data); 245 246 if (proc != NULL) 247 PRELE(proc); | 244 error = (pn->pn_ioctl)(curthread, proc, pn, va->a_command, va->a_data); 245 246 if (proc != NULL) 247 PRELE(proc); |
248 | 248 |
249 PFS_RETURN (error); 250} 251 252/* 253 * Perform getextattr 254 */ 255static int 256pfs_getextattr(struct vop_getextattr_args *va) 257{ 258 struct vnode *vn = va->a_vp; 259 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 260 struct pfs_node *pn = pvd->pvd_pn; 261 struct proc *proc = NULL; 262 int error; 263 264 PFS_TRACE((pd->pn_name)); 265 266 if (pn->pn_getextattr == NULL) 267 PFS_RETURN (EOPNOTSUPP); | 249 PFS_RETURN (error); 250} 251 252/* 253 * Perform getextattr 254 */ 255static int 256pfs_getextattr(struct vop_getextattr_args *va) 257{ 258 struct vnode *vn = va->a_vp; 259 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 260 struct pfs_node *pn = pvd->pvd_pn; 261 struct proc *proc = NULL; 262 int error; 263 264 PFS_TRACE((pd->pn_name)); 265 266 if (pn->pn_getextattr == NULL) 267 PFS_RETURN (EOPNOTSUPP); |
268 | 268 |
269 /* 270 * This is necessary because either process' privileges may 271 * have changed since the open() call. 272 */ 273 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 274 PFS_RETURN (EIO); | 269 /* 270 * This is necessary because either process' privileges may 271 * have changed since the open() call. 272 */ 273 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 274 PFS_RETURN (EIO); |
275 | 275 |
276 /* XXX duplicates bits of pfs_visible() */ 277 if (pvd->pvd_pid != NO_PID) { 278 if ((proc = pfind(pvd->pvd_pid)) == NULL) 279 PFS_RETURN (EIO); 280 _PHOLD(proc); 281 PROC_UNLOCK(proc); 282 } | 276 /* XXX duplicates bits of pfs_visible() */ 277 if (pvd->pvd_pid != NO_PID) { 278 if ((proc = pfind(pvd->pvd_pid)) == NULL) 279 PFS_RETURN (EIO); 280 _PHOLD(proc); 281 PROC_UNLOCK(proc); 282 } |
283 | 283 |
284 error = (pn->pn_getextattr)(curthread, proc, pn, va->a_attrnamespace, 285 va->a_name, va->a_uio, va->a_size, va->a_cred); 286 287 if (proc != NULL) 288 PRELE(proc); | 284 error = (pn->pn_getextattr)(curthread, proc, pn, va->a_attrnamespace, 285 va->a_name, va->a_uio, va->a_size, va->a_cred); 286 287 if (proc != NULL) 288 PRELE(proc); |
289 | 289 |
290 PFS_RETURN (error); 291} 292 293/* 294 * Look up a file or directory 295 * 296 * XXX NOTE! pfs_lookup() has been hooked into vop_lookup_desc! This 297 * will result in a lookup operation for a vnode which may already be --- 13 unchanged lines hidden (view full) --- 311 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 312 struct pfs_node *pd = pvd->pvd_pn; 313 struct pfs_node *pn, *pdn = NULL; 314 pid_t pid = pvd->pvd_pid; 315 char *pname; 316 int error, i, namelen; 317 318 PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr)); | 290 PFS_RETURN (error); 291} 292 293/* 294 * Look up a file or directory 295 * 296 * XXX NOTE! pfs_lookup() has been hooked into vop_lookup_desc! This 297 * will result in a lookup operation for a vnode which may already be --- 13 unchanged lines hidden (view full) --- 311 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 312 struct pfs_node *pd = pvd->pvd_pn; 313 struct pfs_node *pn, *pdn = NULL; 314 pid_t pid = pvd->pvd_pid; 315 char *pname; 316 int error, i, namelen; 317 318 PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr)); |
319 | 319 |
320 if (vn->v_type != VDIR) 321 PFS_RETURN (ENOTDIR); | 320 if (vn->v_type != VDIR) 321 PFS_RETURN (ENOTDIR); |
322 | 322 |
323 /* 324 * Don't support DELETE or RENAME. CREATE is supported so 325 * that O_CREAT will work, but the lookup will still fail if 326 * the file does not exist. 327 */ 328 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 329 PFS_RETURN (EOPNOTSUPP); 330 331 /* shortcut: check if the name is too long */ 332 if (cnp->cn_namelen >= PFS_NAMELEN) 333 PFS_RETURN (ENOENT); 334 335 /* check that parent directory is visisble... */ 336 if (!pfs_visible(curthread, pd, pvd->pvd_pid)) 337 PFS_RETURN (ENOENT); | 323 /* 324 * Don't support DELETE or RENAME. CREATE is supported so 325 * that O_CREAT will work, but the lookup will still fail if 326 * the file does not exist. 327 */ 328 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 329 PFS_RETURN (EOPNOTSUPP); 330 331 /* shortcut: check if the name is too long */ 332 if (cnp->cn_namelen >= PFS_NAMELEN) 333 PFS_RETURN (ENOENT); 334 335 /* check that parent directory is visisble... */ 336 if (!pfs_visible(curthread, pd, pvd->pvd_pid)) 337 PFS_RETURN (ENOENT); |
338 | 338 |
339 /* self */ 340 namelen = cnp->cn_namelen; 341 pname = cnp->cn_nameptr; 342 if (namelen == 1 && *pname == '.') { 343 pn = pd; 344 *vpp = vn; 345 VREF(vn); 346 PFS_RETURN (0); --- 31 unchanged lines hidden (view full) --- 378 if ((pn = pdn) != NULL) { 379 pid = 0; 380 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i) 381 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX) 382 break; 383 if (i == cnp->cn_namelen) 384 goto got_pnode; 385 } | 339 /* self */ 340 namelen = cnp->cn_namelen; 341 pname = cnp->cn_nameptr; 342 if (namelen == 1 && *pname == '.') { 343 pn = pd; 344 *vpp = vn; 345 VREF(vn); 346 PFS_RETURN (0); --- 31 unchanged lines hidden (view full) --- 378 if ((pn = pdn) != NULL) { 379 pid = 0; 380 for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i) 381 if ((pid = pid * 10 + pname[i] - '0') > PID_MAX) 382 break; 383 if (i == cnp->cn_namelen) 384 goto got_pnode; 385 } |
386 | 386 |
387 PFS_RETURN (ENOENT); 388 got_pnode: 389 if (pn != pd->pn_parent && !pn->pn_parent) 390 pn->pn_parent = pd; 391 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 392 PFS_RETURN (ENOENT); 393 error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid); 394 if (error) --- 18 unchanged lines hidden (view full) --- 413 int mode = va->a_mode; 414 415 PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode)); 416 417 /* 418 * check if the file is visible to the caller 419 * 420 * XXX Not sure if this is necessary, as the VFS system calls | 387 PFS_RETURN (ENOENT); 388 got_pnode: 389 if (pn != pd->pn_parent && !pn->pn_parent) 390 pn->pn_parent = pd; 391 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 392 PFS_RETURN (ENOENT); 393 error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid); 394 if (error) --- 18 unchanged lines hidden (view full) --- 413 int mode = va->a_mode; 414 415 PFS_TRACE(("%s (mode 0x%x)", pn->pn_name, mode)); 416 417 /* 418 * check if the file is visible to the caller 419 * 420 * XXX Not sure if this is necessary, as the VFS system calls |
421 * XXX pfs_lookup() and pfs_access() first, and pfs_lookup() 422 * XXX calls pfs_visible(). There's a race condition here, but | 421 * XXX pfs_lookup() and pfs_access() first, and pfs_lookup() 422 * XXX calls pfs_visible(). There's a race condition here, but |
423 * XXX calling pfs_visible() from here doesn't really close it, 424 * XXX and the only consequence of that race is an EIO further 425 * XXX down the line. 426 */ 427 if (!pfs_visible(va->a_td, pn, pvd->pvd_pid)) 428 PFS_RETURN (ENOENT); | 423 * XXX calling pfs_visible() from here doesn't really close it, 424 * XXX and the only consequence of that race is an EIO further 425 * XXX down the line. 426 */ 427 if (!pfs_visible(va->a_td, pn, pvd->pvd_pid)) 428 PFS_RETURN (ENOENT); |
429 | 429 |
430 /* check if the requested mode is permitted */ 431 if (((mode & FREAD) && !(mode & PFS_RD)) || 432 ((mode & FWRITE) && !(mode & PFS_WR))) 433 PFS_RETURN (EPERM); 434 435 /* we don't support locking */ 436 if ((mode & O_SHLOCK) || (mode & O_EXLOCK)) 437 PFS_RETURN (EOPNOTSUPP); | 430 /* check if the requested mode is permitted */ 431 if (((mode & FREAD) && !(mode & PFS_RD)) || 432 ((mode & FWRITE) && !(mode & PFS_WR))) 433 PFS_RETURN (EPERM); 434 435 /* we don't support locking */ 436 if ((mode & O_SHLOCK) || (mode & O_EXLOCK)) 437 PFS_RETURN (EOPNOTSUPP); |
438 | 438 |
439 PFS_RETURN (0); 440} 441 442/* 443 * Read from a file 444 */ 445static int 446pfs_read(struct vop_read_args *va) 447{ 448 struct vnode *vn = va->a_vp; 449 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 450 struct pfs_node *pn = pvd->pvd_pn; 451 struct uio *uio = va->a_uio; 452 struct proc *proc = NULL; 453 struct sbuf *sb = NULL; 454 char *ps; 455 int error, xlen; 456 457 PFS_TRACE((pn->pn_name)); | 439 PFS_RETURN (0); 440} 441 442/* 443 * Read from a file 444 */ 445static int 446pfs_read(struct vop_read_args *va) 447{ 448 struct vnode *vn = va->a_vp; 449 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 450 struct pfs_node *pn = pvd->pvd_pn; 451 struct uio *uio = va->a_uio; 452 struct proc *proc = NULL; 453 struct sbuf *sb = NULL; 454 char *ps; 455 int error, xlen; 456 457 PFS_TRACE((pn->pn_name)); |
458 | 458 |
459 if (vn->v_type != VREG) 460 PFS_RETURN (EINVAL); 461 462 if (!(pn->pn_flags & PFS_RD)) 463 PFS_RETURN (EBADF); 464 465 if (pn->pn_func == NULL) 466 PFS_RETURN (EIO); | 459 if (vn->v_type != VREG) 460 PFS_RETURN (EINVAL); 461 462 if (!(pn->pn_flags & PFS_RD)) 463 PFS_RETURN (EBADF); 464 465 if (pn->pn_func == NULL) 466 PFS_RETURN (EIO); |
467 | 467 |
468 /* 469 * This is necessary because either process' privileges may 470 * have changed since the open() call. 471 */ 472 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 473 PFS_RETURN (EIO); | 468 /* 469 * This is necessary because either process' privileges may 470 * have changed since the open() call. 471 */ 472 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 473 PFS_RETURN (EIO); |
474 | 474 |
475 /* XXX duplicates bits of pfs_visible() */ 476 if (pvd->pvd_pid != NO_PID) { 477 if ((proc = pfind(pvd->pvd_pid)) == NULL) 478 PFS_RETURN (EIO); 479 _PHOLD(proc); 480 PROC_UNLOCK(proc); 481 } 482 483 if (pn->pn_flags & PFS_RAWRD) { 484 error = (pn->pn_func)(curthread, proc, pn, NULL, uio); 485 if (proc != NULL) 486 PRELE(proc); 487 PFS_RETURN (error); 488 } | 475 /* XXX duplicates bits of pfs_visible() */ 476 if (pvd->pvd_pid != NO_PID) { 477 if ((proc = pfind(pvd->pvd_pid)) == NULL) 478 PFS_RETURN (EIO); 479 _PHOLD(proc); 480 PROC_UNLOCK(proc); 481 } 482 483 if (pn->pn_flags & PFS_RAWRD) { 484 error = (pn->pn_func)(curthread, proc, pn, NULL, uio); 485 if (proc != NULL) 486 PRELE(proc); 487 PFS_RETURN (error); 488 } |
489 | 489 |
490 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0); 491 if (sb == NULL) { 492 if (proc != NULL) 493 PRELE(proc); 494 PFS_RETURN (EIO); 495 } 496 497 error = (pn->pn_func)(curthread, proc, pn, sb, uio); 498 499 if (proc != NULL) 500 PRELE(proc); 501 502 if (error) { 503 sbuf_delete(sb); 504 PFS_RETURN (error); 505 } | 490 sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0); 491 if (sb == NULL) { 492 if (proc != NULL) 493 PRELE(proc); 494 PFS_RETURN (EIO); 495 } 496 497 error = (pn->pn_func)(curthread, proc, pn, sb, uio); 498 499 if (proc != NULL) 500 PRELE(proc); 501 502 if (error) { 503 sbuf_delete(sb); 504 PFS_RETURN (error); 505 } |
506 | 506 |
507 /* XXX we should possibly detect and handle overflows */ 508 sbuf_finish(sb); 509 ps = sbuf_data(sb) + uio->uio_offset; 510 xlen = sbuf_len(sb) - uio->uio_offset; 511 xlen = imin(xlen, uio->uio_resid); 512 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); 513 sbuf_delete(sb); 514 PFS_RETURN (error); 515} 516 517/* 518 * Iterate through directory entries 519 */ 520static int 521pfs_iterate(struct thread *td, pid_t pid, struct pfs_node *pd, | 507 /* XXX we should possibly detect and handle overflows */ 508 sbuf_finish(sb); 509 ps = sbuf_data(sb) + uio->uio_offset; 510 xlen = sbuf_len(sb) - uio->uio_offset; 511 xlen = imin(xlen, uio->uio_resid); 512 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); 513 sbuf_delete(sb); 514 PFS_RETURN (error); 515} 516 517/* 518 * Iterate through directory entries 519 */ 520static int 521pfs_iterate(struct thread *td, pid_t pid, struct pfs_node *pd, |
522 struct pfs_node **pn, struct proc **p) | 522 struct pfs_node **pn, struct proc **p) |
523{ 524 if ((*pn) == NULL) 525 *pn = pd->pn_nodes; 526 else 527 again: 528 if ((*pn)->pn_type != pfstype_procdir) 529 *pn = (*pn)->pn_next; | 523{ 524 if ((*pn) == NULL) 525 *pn = pd->pn_nodes; 526 else 527 again: 528 if ((*pn)->pn_type != pfstype_procdir) 529 *pn = (*pn)->pn_next; |
530 | 530 |
531 while (*pn != NULL && (*pn)->pn_type == pfstype_procdir) { 532 if (*p == NULL) 533 *p = LIST_FIRST(&allproc); 534 else 535 *p = LIST_NEXT(*p, p_list); 536 if (*p != NULL) 537 break; 538 *pn = (*pn)->pn_next; 539 } | 531 while (*pn != NULL && (*pn)->pn_type == pfstype_procdir) { 532 if (*p == NULL) 533 *p = LIST_FIRST(&allproc); 534 else 535 *p = LIST_NEXT(*p, p_list); 536 if (*p != NULL) 537 break; 538 *pn = (*pn)->pn_next; 539 } |
540 | 540 |
541 if ((*pn) == NULL) 542 return (-1); 543 544 if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid)) 545 goto again; | 541 if ((*pn) == NULL) 542 return (-1); 543 544 if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid)) 545 goto again; |
546 | 546 |
547 return (0); 548} 549 550/* 551 * Return directory entries. 552 */ 553static int 554pfs_readdir(struct vop_readdir_args *va) --- 6 unchanged lines hidden (view full) --- 561 struct pfs_node *pn; 562 struct dirent entry; 563 struct uio *uio; 564 struct proc *p; 565 off_t offset; 566 int error, i, resid; 567 568 PFS_TRACE((pd->pn_name)); | 547 return (0); 548} 549 550/* 551 * Return directory entries. 552 */ 553static int 554pfs_readdir(struct vop_readdir_args *va) --- 6 unchanged lines hidden (view full) --- 561 struct pfs_node *pn; 562 struct dirent entry; 563 struct uio *uio; 564 struct proc *p; 565 off_t offset; 566 int error, i, resid; 567 568 PFS_TRACE((pd->pn_name)); |
569 | 569 |
570 if (vn->v_type != VDIR) 571 PFS_RETURN (ENOTDIR); 572 uio = va->a_uio; 573 574 /* check if the directory is visible to the caller */ 575 if (!pfs_visible(curthread, pd, pid)) 576 PFS_RETURN (ENOENT); | 570 if (vn->v_type != VDIR) 571 PFS_RETURN (ENOTDIR); 572 uio = va->a_uio; 573 574 /* check if the directory is visible to the caller */ 575 if (!pfs_visible(curthread, pd, pid)) 576 PFS_RETURN (ENOENT); |
577 | 577 |
578 /* only allow reading entire entries */ 579 offset = uio->uio_offset; 580 resid = uio->uio_resid; 581 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN) 582 PFS_RETURN (EINVAL); 583 584 /* skip unwanted entries */ 585 sx_slock(&allproc_lock); 586 for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) 587 if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) { 588 /* nothing left... */ 589 sx_sunlock(&allproc_lock); 590 PFS_RETURN (0); 591 } | 578 /* only allow reading entire entries */ 579 offset = uio->uio_offset; 580 resid = uio->uio_resid; 581 if (offset < 0 || offset % PFS_DELEN != 0 || resid < PFS_DELEN) 582 PFS_RETURN (EINVAL); 583 584 /* skip unwanted entries */ 585 sx_slock(&allproc_lock); 586 for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) 587 if (pfs_iterate(curthread, pid, pd, &pn, &p) == -1) { 588 /* nothing left... */ 589 sx_sunlock(&allproc_lock); 590 PFS_RETURN (0); 591 } |
592 | 592 |
593 /* fill in entries */ 594 entry.d_reclen = PFS_DELEN; 595 while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && resid > 0) { 596 if (!pn->pn_parent) 597 pn->pn_parent = pd; 598 if (!pn->pn_fileno) 599 pfs_fileno_alloc(pi, pn); 600 if (pid != NO_PID) --- 54 unchanged lines hidden (view full) --- 655 struct pfs_node *pn = pvd->pvd_pn; 656 struct uio *uio = va->a_uio; 657 struct proc *proc = NULL; 658 char buf[MAXPATHLEN], *ps; 659 struct sbuf sb; 660 int error, xlen; 661 662 PFS_TRACE((pn->pn_name)); | 593 /* fill in entries */ 594 entry.d_reclen = PFS_DELEN; 595 while (pfs_iterate(curthread, pid, pd, &pn, &p) != -1 && resid > 0) { 596 if (!pn->pn_parent) 597 pn->pn_parent = pd; 598 if (!pn->pn_fileno) 599 pfs_fileno_alloc(pi, pn); 600 if (pid != NO_PID) --- 54 unchanged lines hidden (view full) --- 655 struct pfs_node *pn = pvd->pvd_pn; 656 struct uio *uio = va->a_uio; 657 struct proc *proc = NULL; 658 char buf[MAXPATHLEN], *ps; 659 struct sbuf sb; 660 int error, xlen; 661 662 PFS_TRACE((pn->pn_name)); |
663 | 663 |
664 if (vn->v_type != VLNK) 665 PFS_RETURN (EINVAL); 666 667 if (pn->pn_func == NULL) 668 PFS_RETURN (EIO); | 664 if (vn->v_type != VLNK) 665 PFS_RETURN (EINVAL); 666 667 if (pn->pn_func == NULL) 668 PFS_RETURN (EIO); |
669 | 669 |
670 if (pvd->pvd_pid != NO_PID) { 671 if ((proc = pfind(pvd->pvd_pid)) == NULL) 672 PFS_RETURN (EIO); 673 _PHOLD(proc); 674 PROC_UNLOCK(proc); 675 } | 670 if (pvd->pvd_pid != NO_PID) { 671 if ((proc = pfind(pvd->pvd_pid)) == NULL) 672 PFS_RETURN (EIO); 673 _PHOLD(proc); 674 PROC_UNLOCK(proc); 675 } |
676 | 676 |
677 /* sbuf_new() can't fail with a static buffer */ 678 sbuf_new(&sb, buf, sizeof buf, 0); 679 680 error = (pn->pn_func)(curthread, proc, pn, &sb, NULL); 681 682 if (proc != NULL) 683 PRELE(proc); | 677 /* sbuf_new() can't fail with a static buffer */ 678 sbuf_new(&sb, buf, sizeof buf, 0); 679 680 error = (pn->pn_func)(curthread, proc, pn, &sb, NULL); 681 682 if (proc != NULL) 683 PRELE(proc); |
684 | 684 |
685 if (error) { 686 sbuf_delete(&sb); 687 PFS_RETURN (error); 688 } | 685 if (error) { 686 sbuf_delete(&sb); 687 PFS_RETURN (error); 688 } |
689 | 689 |
690 /* XXX we should detect and handle overflows */ 691 sbuf_finish(&sb); 692 ps = sbuf_data(&sb) + uio->uio_offset; 693 xlen = sbuf_len(&sb) - uio->uio_offset; 694 xlen = imin(xlen, uio->uio_resid); 695 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); 696 sbuf_delete(&sb); 697 PFS_RETURN (error); --- 31 unchanged lines hidden (view full) --- 729 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 730 struct pfs_node *pn = pvd->pvd_pn; 731 struct uio *uio = va->a_uio; 732 struct proc *proc = NULL; 733 struct sbuf sb; 734 int error; 735 736 PFS_TRACE((pn->pn_name)); | 690 /* XXX we should detect and handle overflows */ 691 sbuf_finish(&sb); 692 ps = sbuf_data(&sb) + uio->uio_offset; 693 xlen = sbuf_len(&sb) - uio->uio_offset; 694 xlen = imin(xlen, uio->uio_resid); 695 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); 696 sbuf_delete(&sb); 697 PFS_RETURN (error); --- 31 unchanged lines hidden (view full) --- 729 struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; 730 struct pfs_node *pn = pvd->pvd_pn; 731 struct uio *uio = va->a_uio; 732 struct proc *proc = NULL; 733 struct sbuf sb; 734 int error; 735 736 PFS_TRACE((pn->pn_name)); |
737 | 737 |
738 if (vn->v_type != VREG) 739 PFS_RETURN (EINVAL); 740 741 if (!(pn->pn_flags & PFS_WR)) 742 PFS_RETURN (EBADF); 743 744 if (pn->pn_func == NULL) 745 PFS_RETURN (EIO); | 738 if (vn->v_type != VREG) 739 PFS_RETURN (EINVAL); 740 741 if (!(pn->pn_flags & PFS_WR)) 742 PFS_RETURN (EBADF); 743 744 if (pn->pn_func == NULL) 745 PFS_RETURN (EIO); |
746 | 746 |
747 /* 748 * This is necessary because either process' privileges may 749 * have changed since the open() call. 750 */ 751 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 752 PFS_RETURN (EIO); 753 754 /* XXX duplicates bits of pfs_visible() */ --- 9 unchanged lines hidden (view full) --- 764 if (proc != NULL) 765 PRELE(proc); 766 PFS_RETURN (error); 767 } 768 769 sbuf_uionew(&sb, uio, &error); 770 if (error) 771 PFS_RETURN (error); | 747 /* 748 * This is necessary because either process' privileges may 749 * have changed since the open() call. 750 */ 751 if (!pfs_visible(curthread, pn, pvd->pvd_pid)) 752 PFS_RETURN (EIO); 753 754 /* XXX duplicates bits of pfs_visible() */ --- 9 unchanged lines hidden (view full) --- 764 if (proc != NULL) 765 PRELE(proc); 766 PFS_RETURN (error); 767 } 768 769 sbuf_uionew(&sb, uio, &error); 770 if (error) 771 PFS_RETURN (error); |
772 | 772 |
773 error = (pn->pn_func)(curthread, proc, pn, &sb, uio); 774 775 if (proc != NULL) 776 PRELE(proc); | 773 error = (pn->pn_func)(curthread, proc, pn, &sb, uio); 774 775 if (proc != NULL) 776 PRELE(proc); |
777 | 777 |
778 sbuf_delete(&sb); 779 PFS_RETURN (error); 780} 781 782/* 783 * Vnode operations 784 */ 785vop_t **pfs_vnodeop_p; --- 31 unchanged lines hidden --- | 778 sbuf_delete(&sb); 779 PFS_RETURN (error); 780} 781 782/* 783 * Vnode operations 784 */ 785vop_t **pfs_vnodeop_p; --- 31 unchanged lines hidden --- |