Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_vnops.c
Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
static fo_rdwr_t vn_read; | static fo_rdwr_t vn_read; | ||||
static fo_rdwr_t vn_write; | static fo_rdwr_t vn_write; | ||||
static fo_rdwr_t vn_io_fault; | static fo_rdwr_t vn_io_fault; | ||||
static fo_truncate_t vn_truncate; | static fo_truncate_t vn_truncate; | ||||
static fo_ioctl_t vn_ioctl; | static fo_ioctl_t vn_ioctl; | ||||
static fo_poll_t vn_poll; | static fo_poll_t vn_poll; | ||||
static fo_kqfilter_t vn_kqfilter; | static fo_kqfilter_t vn_kqfilter; | ||||
static fo_stat_t vn_statfile; | |||||
static fo_close_t vn_closefile; | static fo_close_t vn_closefile; | ||||
static fo_mmap_t vn_mmap; | static fo_mmap_t vn_mmap; | ||||
static fo_fallocate_t vn_fallocate; | static fo_fallocate_t vn_fallocate; | ||||
struct fileops vnops = { | struct fileops vnops = { | ||||
.fo_read = vn_io_fault, | .fo_read = vn_io_fault, | ||||
.fo_write = vn_io_fault, | .fo_write = vn_io_fault, | ||||
.fo_truncate = vn_truncate, | .fo_truncate = vn_truncate, | ||||
▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred, | vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred, | ||||
struct thread *td, struct file *fp) | struct thread *td, struct file *fp) | ||||
{ | { | ||||
accmode_t accmode; | accmode_t accmode; | ||||
int error; | int error; | ||||
if (vp->v_type == VLNK) | if (vp->v_type == VLNK) { | ||||
if ((fmode & O_PATH) == 0 || (fmode & FEXEC) != 0) | |||||
return (EMLINK); | return (EMLINK); | ||||
} | |||||
if (vp->v_type == VSOCK) | if (vp->v_type == VSOCK) | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
if (vp->v_type != VDIR && fmode & O_DIRECTORY) | if (vp->v_type != VDIR && fmode & O_DIRECTORY) | ||||
return (ENOTDIR); | return (ENOTDIR); | ||||
accmode = 0; | accmode = 0; | ||||
if (fmode & (FWRITE | O_TRUNC)) { | if ((fmode & O_PATH) == 0) { | ||||
if ((fmode & (FWRITE | O_TRUNC)) != 0) { | |||||
if (vp->v_type == VDIR) | if (vp->v_type == VDIR) | ||||
return (EISDIR); | return (EISDIR); | ||||
accmode |= VWRITE; | accmode |= VWRITE; | ||||
} | } | ||||
if (fmode & FREAD) | if ((fmode & FREAD) != 0) | ||||
accmode |= VREAD; | accmode |= VREAD; | ||||
if (fmode & FEXEC) | |||||
accmode |= VEXEC; | |||||
if ((fmode & O_APPEND) && (fmode & FWRITE)) | if ((fmode & O_APPEND) && (fmode & FWRITE)) | ||||
accmode |= VAPPEND; | accmode |= VAPPEND; | ||||
#ifdef MAC | #ifdef MAC | ||||
if (fmode & O_CREAT) | if ((fmode & O_CREAT) != 0) | ||||
accmode |= VCREAT; | accmode |= VCREAT; | ||||
if (fmode & O_VERIFY) | #endif | ||||
} | |||||
if ((fmode & FEXEC) != 0) | |||||
accmode |= VEXEC; | |||||
#ifdef MAC | |||||
if ((fmode & O_VERIFY) != 0) | |||||
accmode |= VVERIFY; | accmode |= VVERIFY; | ||||
error = mac_vnode_check_open(cred, vp, accmode); | error = mac_vnode_check_open(cred, vp, accmode); | ||||
markj: I am not sure that we want to bypass MAC for O_PATH opens, especially since VEXEC access is… | |||||
Done Inline ActionsThen O_VERIFY should be accepted as well, and VOP_ACCESS needs to be performed. I restructured the introductory part of vn_open_vnode() to handle all this. kib: Then O_VERIFY should be accepted as well, and VOP_ACCESS needs to be performed.
I restructured… | |||||
if (error) | if (error != 0) | ||||
return (error); | return (error); | ||||
accmode &= ~(VCREAT | VVERIFY); | accmode &= ~(VCREAT | VVERIFY); | ||||
#endif | #endif | ||||
if ((fmode & O_CREAT) == 0 && accmode != 0) { | if ((fmode & O_CREAT) == 0 && accmode != 0) { | ||||
error = VOP_ACCESS(vp, accmode, cred, td); | error = VOP_ACCESS(vp, accmode, cred, td); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
} | } | ||||
if ((fmode & O_PATH) != 0) { | |||||
error = VOP_ACCESS(vp, VREAD, cred, td); | |||||
if (error == 0) | |||||
fp->f_flag |= FKQALLOWED; | |||||
return (0); | |||||
} | |||||
if (vp->v_type == VFIFO && VOP_ISLOCKED(vp) != LK_EXCLUSIVE) | if (vp->v_type == VFIFO && VOP_ISLOCKED(vp) != LK_EXCLUSIVE) | ||||
vn_lock(vp, LK_UPGRADE | LK_RETRY); | vn_lock(vp, LK_UPGRADE | LK_RETRY); | ||||
error = VOP_OPEN(vp, fmode, cred, td, fp); | error = VOP_OPEN(vp, fmode, cred, td, fp); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = vn_open_vnode_advlock(vp, fmode, fp); | error = vn_open_vnode_advlock(vp, fmode, fp); | ||||
if (error == 0 && (fmode & FWRITE) != 0) { | if (error == 0 && (fmode & FWRITE) != 0) { | ||||
▲ Show 20 Lines • Show All 1,180 Lines • ▼ Show 20 Lines | if (error == 0) { | ||||
VOP_ADD_WRITECOUNT_CHECKED(vp, -1); | VOP_ADD_WRITECOUNT_CHECKED(vp, -1); | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* File table vnode stat routine. | * File table vnode stat routine. | ||||
*/ | */ | ||||
static int | int | ||||
vn_statfile(struct file *fp, struct stat *sb, struct ucred *active_cred, | vn_statfile(struct file *fp, struct stat *sb, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
struct vnode *vp = fp->f_vnode; | struct vnode *vp = fp->f_vnode; | ||||
int error; | int error; | ||||
vn_lock(vp, LK_SHARED | LK_RETRY); | vn_lock(vp, LK_SHARED | LK_RETRY); | ||||
error = VOP_STAT(vp, sb, active_cred, fp->f_cred, td); | error = VOP_STAT(vp, sb, active_cred, fp->f_cred, td); | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct flock lf; | struct flock lf; | ||||
int error; | int error; | ||||
bool ref; | bool ref; | ||||
vp = fp->f_vnode; | vp = fp->f_vnode; | ||||
fp->f_ops = &badfileops; | fp->f_ops = &badfileops; | ||||
ref= (fp->f_flag & FHASLOCK) != 0 && fp->f_type == DTYPE_VNODE; | ref = (fp->f_flag & FHASLOCK) != 0 && fp->f_type == DTYPE_VNODE; | ||||
error = vn_close1(vp, fp->f_flag, fp->f_cred, td, ref); | error = vn_close1(vp, fp->f_flag, fp->f_cred, td, ref); | ||||
if (__predict_false(ref)) { | if (__predict_false(ref)) { | ||||
lf.l_whence = SEEK_SET; | lf.l_whence = SEEK_SET; | ||||
lf.l_start = 0; | lf.l_start = 0; | ||||
lf.l_len = 0; | lf.l_len = 0; | ||||
lf.l_type = F_UNLCK; | lf.l_type = F_UNLCK; | ||||
▲ Show 20 Lines • Show All 336 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Implement kqueues for files by translating it to vnode operation. | * Implement kqueues for files by translating it to vnode operation. | ||||
*/ | */ | ||||
static int | static int | ||||
vn_kqfilter(struct file *fp, struct knote *kn) | vn_kqfilter(struct file *fp, struct knote *kn) | ||||
{ | { | ||||
return (VOP_KQFILTER(fp->f_vnode, kn)); | return (VOP_KQFILTER(fp->f_vnode, kn)); | ||||
} | |||||
int | |||||
vn_kqfilter_opath(struct file *fp, struct knote *kn) | |||||
{ | |||||
if ((fp->f_flag & FKQALLOWED) == 0) | |||||
return (EBADF); | |||||
return (vn_kqfilter(fp, kn)); | |||||
} | } | ||||
/* | /* | ||||
* Simplified in-kernel wrapper calls for extended attribute access. | * Simplified in-kernel wrapper calls for extended attribute access. | ||||
* Both calls pass in a NULL credential, authorizing as "kernel" access. | * Both calls pass in a NULL credential, authorizing as "kernel" access. | ||||
* Set IO_NODELOCKED in ioflg if the vnode is already locked. | * Set IO_NODELOCKED in ioflg if the vnode is already locked. | ||||
*/ | */ | ||||
int | int | ||||
▲ Show 20 Lines • Show All 1,313 Lines • Show Last 20 Lines |
I am not sure that we want to bypass MAC for O_PATH opens, especially since VEXEC access is possible.