| 1366 | } |
| 1367 | |
| 1368 | static int |
| 1369 | vn_io_fault(struct file *fp, struct uio *uio, struct ucred *active_cred, |
| 1370 | int flags, struct thread *td) |
| 1371 | { |
| 1372 | fo_rdwr_t *doio; |
| 1373 | struct vnode *vp; |
| 1374 | void *rl_cookie; |
| 1375 | struct vn_io_fault_args args; |
| 1376 | int error; |
| 1377 | |
| 1378 | doio = uio->uio_rw == UIO_READ ? vn_read : vn_write; |
| 1379 | vp = fp->f_vnode; |
| 1380 | |
| 1381 | /* |
| 1382 | * The ability to read(2) on a directory has historically been |
| 1383 | * allowed for all users, but this can and has been the source of |
| 1384 | * at least one security issue in the past. As such, it is now hidden |
| 1385 | * away behind a sysctl for those that actually need it to use it, and |
| 1386 | * restricted to root when it's turned on to make it relatively safe to |
| 1387 | * leave on for longer sessions of need. |
| 1388 | */ |
| 1389 | if (vp->v_type == VDIR) { |
| 1390 | KASSERT(uio->uio_rw == UIO_READ, |
| 1391 | ("illegal write attempted on a directory")); |
| 1392 | if (!vfs_allow_read_dir) |
| 1393 | return (EISDIR); |
| 1394 | if ((error = priv_check(td, PRIV_VFS_READ_DIR)) != 0) |
| 1395 | return (EISDIR); |
| 1396 | } |
| 1397 | |
| 1398 | foffset_lock_uio(fp, uio, flags); |
| 1399 | if (do_vn_io_fault(vp, uio)) { |
| 1400 | args.kind = VN_IO_FAULT_FOP; |
| 1401 | args.args.fop_args.fp = fp; |
| 1402 | args.args.fop_args.doio = doio; |
| 1403 | args.cred = active_cred; |
| 1404 | args.flags = flags | FOF_OFFSET; |
| 1405 | if (uio->uio_rw == UIO_READ) { |
| 1406 | rl_cookie = vn_rangelock_rlock(vp, uio->uio_offset, |
| 1407 | uio->uio_offset + uio->uio_resid); |
| 1408 | } else if ((fp->f_flag & O_APPEND) != 0 || |
| 1409 | (flags & FOF_OFFSET) == 0) { |
| 1410 | /* For appenders, punt and lock the whole range. */ |
| 1411 | rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX); |
| 1412 | } else { |
| 1413 | rl_cookie = vn_rangelock_wlock(vp, uio->uio_offset, |
| 1414 | uio->uio_offset + uio->uio_resid); |
| 1415 | } |
| 1416 | error = vn_io_fault1(vp, uio, &args, td); |
| 1417 | vn_rangelock_unlock(vp, rl_cookie); |
| 1418 | } else { |
| 1419 | error = doio(fp, uio, active_cred, flags | FOF_OFFSET, td); |
| 1420 | } |
| 1421 | foffset_unlock_uio(fp, uio, flags); |
| 1422 | return (error); |
| 1423 | } |
| 1424 | |
| 1425 | /* |
nothing calls this directly
no test coverage detected