Add the fo_chown and fo_chmod methods to struct fileops and use them
to implement fchown(2) and fchmod(2) support for several file types that previously lacked it. Add MAC entries for chown/chmod done on posix shared memory and (old) in-kernel posix semaphores. Based on the submission by: glebius Reviewed by: rwatson Approved by: re (bz)
This commit is contained in:
parent
985a88e2a6
commit
9c00bb9190
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=224914
@ -95,7 +95,9 @@ static struct fileops svr4_netops = {
|
||||
.fo_poll = soo_poll,
|
||||
.fo_kqfilter = soo_kqfilter,
|
||||
.fo_stat = soo_stat,
|
||||
.fo_close = svr4_soo_close
|
||||
.fo_close = svr4_soo_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
};
|
||||
|
||||
static struct cdevsw streams_cdevsw = {
|
||||
|
@ -1665,6 +1665,8 @@ static struct fileops devfs_ops_f = {
|
||||
.fo_kqfilter = devfs_kqfilter_f,
|
||||
.fo_stat = devfs_stat_f,
|
||||
.fo_close = devfs_close_f,
|
||||
.fo_chmod = vn_chmod,
|
||||
.fo_chown = vn_chown,
|
||||
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
|
||||
};
|
||||
|
||||
|
@ -72,6 +72,8 @@ struct fileops fifo_ops_f = {
|
||||
.fo_kqfilter = fifo_kqfilter_f,
|
||||
.fo_stat = fifo_stat_f,
|
||||
.fo_close = fifo_close_f,
|
||||
.fo_chmod = vn_chmod,
|
||||
.fo_chown = vn_chown,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
|
@ -3774,6 +3774,22 @@ badfo_close(struct file *fp, struct thread *td)
|
||||
return (EBADF);
|
||||
}
|
||||
|
||||
static int
|
||||
badfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EBADF);
|
||||
}
|
||||
|
||||
static int
|
||||
badfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EBADF);
|
||||
}
|
||||
|
||||
struct fileops badfileops = {
|
||||
.fo_read = badfo_readwrite,
|
||||
.fo_write = badfo_readwrite,
|
||||
@ -3783,8 +3799,25 @@ struct fileops badfileops = {
|
||||
.fo_kqfilter = badfo_kqfilter,
|
||||
.fo_stat = badfo_stat,
|
||||
.fo_close = badfo_close,
|
||||
.fo_chmod = badfo_chmod,
|
||||
.fo_chown = badfo_chown,
|
||||
};
|
||||
|
||||
int
|
||||
invfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
int
|
||||
invfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
|
@ -123,6 +123,8 @@ static struct fileops kqueueops = {
|
||||
.fo_kqfilter = kqueue_kqfilter,
|
||||
.fo_stat = kqueue_stat,
|
||||
.fo_close = kqueue_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
};
|
||||
|
||||
static int knote_attach(struct knote *kn, struct kqueue *kq);
|
||||
|
@ -161,6 +161,8 @@ static fo_poll_t capability_poll;
|
||||
static fo_kqfilter_t capability_kqfilter;
|
||||
static fo_stat_t capability_stat;
|
||||
static fo_close_t capability_close;
|
||||
static fo_chmod_t capability_chmod;
|
||||
static fo_chown_t capability_chown;
|
||||
|
||||
static struct fileops capability_ops = {
|
||||
.fo_read = capability_read,
|
||||
@ -171,6 +173,8 @@ static struct fileops capability_ops = {
|
||||
.fo_kqfilter = capability_kqfilter,
|
||||
.fo_stat = capability_stat,
|
||||
.fo_close = capability_close,
|
||||
.fo_chmod = capability_chmod,
|
||||
.fo_chown = capability_chown,
|
||||
.fo_flags = DFLAG_PASSABLE,
|
||||
};
|
||||
|
||||
@ -183,6 +187,8 @@ static struct fileops capability_ops_unpassable = {
|
||||
.fo_kqfilter = capability_kqfilter,
|
||||
.fo_stat = capability_stat,
|
||||
.fo_close = capability_close,
|
||||
.fo_chmod = capability_chmod,
|
||||
.fo_chown = capability_chown,
|
||||
.fo_flags = 0,
|
||||
};
|
||||
|
||||
@ -484,6 +490,22 @@ capability_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
panic("capability_stat");
|
||||
}
|
||||
|
||||
int
|
||||
capability_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
panic("capability_chmod");
|
||||
}
|
||||
|
||||
int
|
||||
capability_chown(struct file *fp, uid_t uid, gid_t gid,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
|
||||
panic("capability_chown");
|
||||
}
|
||||
|
||||
#else /* !CAPABILITIES */
|
||||
|
||||
/*
|
||||
|
@ -155,6 +155,8 @@ static struct fileops pipeops = {
|
||||
.fo_kqfilter = pipe_kqfilter,
|
||||
.fo_stat = pipe_stat,
|
||||
.fo_close = pipe_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
|
@ -64,6 +64,8 @@ struct fileops socketops = {
|
||||
.fo_kqfilter = soo_kqfilter,
|
||||
.fo_stat = soo_stat,
|
||||
.fo_close = soo_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
|
@ -597,6 +597,8 @@ static struct fileops ptsdev_ops = {
|
||||
.fo_kqfilter = ptsdev_kqfilter,
|
||||
.fo_stat = ptsdev_stat,
|
||||
.fo_close = ptsdev_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_flags = DFLAG_PASSABLE,
|
||||
};
|
||||
|
||||
|
@ -2469,6 +2469,7 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
|
||||
struct mqfs_node *pn = fp->f_data;
|
||||
|
||||
bzero(st, sizeof *st);
|
||||
sx_xlock(&mqfs_data.mi_lock);
|
||||
st->st_atim = pn->mn_atime;
|
||||
st->st_mtim = pn->mn_mtime;
|
||||
st->st_ctim = pn->mn_ctime;
|
||||
@ -2476,9 +2477,55 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
|
||||
st->st_uid = pn->mn_uid;
|
||||
st->st_gid = pn->mn_gid;
|
||||
st->st_mode = S_IFIFO | pn->mn_mode;
|
||||
sx_xunlock(&mqfs_data.mi_lock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct mqfs_node *pn;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
pn = fp->f_data;
|
||||
sx_xlock(&mqfs_data.mi_lock);
|
||||
error = vaccess(VREG, pn->mn_mode, pn->mn_uid, pn->mn_gid, VADMIN,
|
||||
active_cred, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
pn->mn_mode = mode & ACCESSPERMS;
|
||||
out:
|
||||
sx_xunlock(&mqfs_data.mi_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct mqfs_node *pn;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
pn = fp->f_data;
|
||||
sx_xlock(&mqfs_data.mi_lock);
|
||||
if (uid == (uid_t)-1)
|
||||
uid = pn->mn_uid;
|
||||
if (gid == (gid_t)-1)
|
||||
gid = pn->mn_gid;
|
||||
if (((uid != pn->mn_uid && uid != active_cred->cr_uid) ||
|
||||
(gid != pn->mn_gid && !groupmember(gid, active_cred))) &&
|
||||
(error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
|
||||
goto out;
|
||||
pn->mn_uid = uid;
|
||||
pn->mn_gid = gid;
|
||||
out:
|
||||
sx_xunlock(&mqfs_data.mi_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
@ -2535,6 +2582,8 @@ static struct fileops mqueueops = {
|
||||
.fo_poll = mqf_poll,
|
||||
.fo_kqfilter = mqf_kqfilter,
|
||||
.fo_stat = mqf_stat,
|
||||
.fo_chmod = mqf_chmod,
|
||||
.fo_chown = mqf_chown,
|
||||
.fo_close = mqf_close
|
||||
};
|
||||
|
||||
|
@ -135,6 +135,8 @@ static fo_poll_t ksem_poll;
|
||||
static fo_kqfilter_t ksem_kqfilter;
|
||||
static fo_stat_t ksem_stat;
|
||||
static fo_close_t ksem_closef;
|
||||
static fo_chmod_t ksem_chmod;
|
||||
static fo_chown_t ksem_chown;
|
||||
|
||||
/* File descriptor operations. */
|
||||
static struct fileops ksem_ops = {
|
||||
@ -146,6 +148,8 @@ static struct fileops ksem_ops = {
|
||||
.fo_kqfilter = ksem_kqfilter,
|
||||
.fo_stat = ksem_stat,
|
||||
.fo_close = ksem_closef,
|
||||
.fo_chmod = ksem_chmod,
|
||||
.fo_chown = ksem_chown,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
@ -220,18 +224,74 @@ ksem_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
* file descriptor.
|
||||
*/
|
||||
bzero(sb, sizeof(*sb));
|
||||
sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */
|
||||
|
||||
mtx_lock(&sem_lock);
|
||||
sb->st_atim = ks->ks_atime;
|
||||
sb->st_ctim = ks->ks_ctime;
|
||||
sb->st_mtim = ks->ks_mtime;
|
||||
sb->st_birthtim = ks->ks_birthtime;
|
||||
sb->st_uid = ks->ks_uid;
|
||||
sb->st_gid = ks->ks_gid;
|
||||
sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */
|
||||
mtx_unlock(&sem_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct ksem *ks;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
ks = fp->f_data;
|
||||
mtx_lock(&sem_lock);
|
||||
#ifdef MAC
|
||||
error = mac_posixsem_check_setmode(active_cred, ks, mode);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
error = vaccess(VREG, ks->ks_mode, ks->ks_uid, ks->ks_gid, VADMIN,
|
||||
active_cred, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
ks->ks_mode = mode & ACCESSPERMS;
|
||||
out:
|
||||
mtx_unlock(&sem_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct ksem *ks;
|
||||
int error;
|
||||
|
||||
ks = fp->f_data;
|
||||
mtx_lock(&sem_lock);
|
||||
#ifdef MAC
|
||||
error = mac_posixsem_check_setowner(active_cred, ks, uid, gid);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
if (uid == (uid_t)-1)
|
||||
uid = ks->ks_uid;
|
||||
if (gid == (gid_t)-1)
|
||||
gid = ks->ks_gid;
|
||||
if (((uid != ks->ks_uid && uid != active_cred->cr_uid) ||
|
||||
(gid != ks->ks_gid && !groupmember(gid, active_cred))) &&
|
||||
(error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
|
||||
goto out;
|
||||
ks->ks_uid = uid;
|
||||
ks->ks_gid = gid;
|
||||
out:
|
||||
mtx_unlock(&sem_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_closef(struct file *fp, struct thread *td)
|
||||
{
|
||||
|
@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/resourcevar.h>
|
||||
@ -123,6 +124,8 @@ static fo_poll_t shm_poll;
|
||||
static fo_kqfilter_t shm_kqfilter;
|
||||
static fo_stat_t shm_stat;
|
||||
static fo_close_t shm_close;
|
||||
static fo_chmod_t shm_chmod;
|
||||
static fo_chown_t shm_chown;
|
||||
|
||||
/* File descriptor operations. */
|
||||
static struct fileops shm_ops = {
|
||||
@ -134,6 +137,8 @@ static struct fileops shm_ops = {
|
||||
.fo_kqfilter = shm_kqfilter,
|
||||
.fo_stat = shm_stat,
|
||||
.fo_close = shm_close,
|
||||
.fo_chmod = shm_chmod,
|
||||
.fo_chown = shm_chown,
|
||||
.fo_flags = DFLAG_PASSABLE
|
||||
};
|
||||
|
||||
@ -218,16 +223,18 @@ shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
* descriptor.
|
||||
*/
|
||||
bzero(sb, sizeof(*sb));
|
||||
sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */
|
||||
sb->st_blksize = PAGE_SIZE;
|
||||
sb->st_size = shmfd->shm_size;
|
||||
sb->st_blocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize;
|
||||
mtx_lock(&shm_timestamp_lock);
|
||||
sb->st_atim = shmfd->shm_atime;
|
||||
sb->st_ctim = shmfd->shm_ctime;
|
||||
sb->st_mtim = shmfd->shm_mtime;
|
||||
sb->st_birthtim = shmfd->shm_birthtime;
|
||||
sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */
|
||||
sb->st_uid = shmfd->shm_uid;
|
||||
sb->st_gid = shmfd->shm_gid;
|
||||
mtx_unlock(&shm_timestamp_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -395,14 +402,18 @@ static int
|
||||
shm_access(struct shmfd *shmfd, struct ucred *ucred, int flags)
|
||||
{
|
||||
accmode_t accmode;
|
||||
int error;
|
||||
|
||||
accmode = 0;
|
||||
if (flags & FREAD)
|
||||
accmode |= VREAD;
|
||||
if (flags & FWRITE)
|
||||
accmode |= VWRITE;
|
||||
return (vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid, shmfd->shm_gid,
|
||||
accmode, ucred, NULL));
|
||||
mtx_lock(&shm_timestamp_lock);
|
||||
error = vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid, shmfd->shm_gid,
|
||||
accmode, ucred, NULL);
|
||||
mtx_unlock(&shm_timestamp_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -651,3 +662,61 @@ shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
|
||||
*obj = shmfd->shm_object;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct shmfd *shmfd;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
shmfd = fp->f_data;
|
||||
mtx_lock(&shm_timestamp_lock);
|
||||
/*
|
||||
* SUSv4 says that x bits of permission need not be affected.
|
||||
* Be consistent with our shm_open there.
|
||||
*/
|
||||
#ifdef MAC
|
||||
error = mac_posixshm_check_setmode(active_cred, shmfd, mode);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
error = vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid,
|
||||
shmfd->shm_gid, VADMIN, active_cred, NULL);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
shmfd->shm_mode = mode & ACCESSPERMS;
|
||||
out:
|
||||
mtx_unlock(&shm_timestamp_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct shmfd *shmfd;
|
||||
int error;
|
||||
|
||||
shmfd = fp->f_data;
|
||||
mtx_lock(&shm_timestamp_lock);
|
||||
#ifdef MAC
|
||||
error = mac_posixshm_check_setowner(active_cred, shmfd, uid, gid);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
if (uid == (uid_t)-1)
|
||||
uid = shmfd->shm_uid;
|
||||
if (gid == (gid_t)-1)
|
||||
gid = shmfd->shm_gid;
|
||||
if (((uid != shmfd->shm_uid && uid != active_cred->cr_uid) ||
|
||||
(gid != shmfd->shm_gid && !groupmember(gid, active_cred))) &&
|
||||
(error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
|
||||
goto out;
|
||||
shmfd->shm_uid = uid;
|
||||
shmfd->shm_gid = gid;
|
||||
out:
|
||||
mtx_unlock(&shm_timestamp_lock);
|
||||
return (error);
|
||||
}
|
||||
|
@ -96,8 +96,6 @@ SDT_PROBE_ARGTYPE(vfs, , stat, reg, 1, "int");
|
||||
|
||||
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
|
||||
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
|
||||
static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
|
||||
static int setfmode(struct thread *td, struct vnode *, int);
|
||||
static int setfflags(struct thread *td, struct vnode *, int);
|
||||
static int setutimes(struct thread *td, struct vnode *,
|
||||
const struct timespec *, int, int);
|
||||
@ -2865,9 +2863,10 @@ fchflags(td, uap)
|
||||
/*
|
||||
* Common implementation code for chmod(), lchmod() and fchmod().
|
||||
*/
|
||||
static int
|
||||
setfmode(td, vp, mode)
|
||||
int
|
||||
setfmode(td, cred, vp, mode)
|
||||
struct thread *td;
|
||||
struct ucred *cred;
|
||||
struct vnode *vp;
|
||||
int mode;
|
||||
{
|
||||
@ -2881,10 +2880,10 @@ setfmode(td, vp, mode)
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_mode = mode & ALLPERMS;
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_setmode(td->td_ucred, vp, vattr.va_mode);
|
||||
error = mac_vnode_check_setmode(cred, vp, vattr.va_mode);
|
||||
if (error == 0)
|
||||
#endif
|
||||
error = VOP_SETATTR(vp, &vattr, td->td_ucred);
|
||||
error = VOP_SETATTR(vp, &vattr, cred);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vn_finished_write(mp);
|
||||
return (error);
|
||||
@ -2980,7 +2979,7 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
|
||||
return (error);
|
||||
vfslocked = NDHASGIANT(&nd);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
error = setfmode(td, nd.ni_vp, mode);
|
||||
error = setfmode(td, td->td_ucred, nd.ni_vp, mode);
|
||||
vrele(nd.ni_vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
return (error);
|
||||
@ -2996,30 +2995,18 @@ struct fchmod_args {
|
||||
};
|
||||
#endif
|
||||
int
|
||||
fchmod(td, uap)
|
||||
struct thread *td;
|
||||
register struct fchmod_args /* {
|
||||
int fd;
|
||||
int mode;
|
||||
} */ *uap;
|
||||
fchmod(struct thread *td, struct fchmod_args *uap)
|
||||
{
|
||||
struct file *fp;
|
||||
int vfslocked;
|
||||
int error;
|
||||
|
||||
AUDIT_ARG_FD(uap->fd);
|
||||
AUDIT_ARG_MODE(uap->mode);
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FCHMOD,
|
||||
&fp)) != 0)
|
||||
|
||||
error = fget(td, uap->fd, CAP_FCHMOD, &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
|
||||
#ifdef AUDIT
|
||||
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
||||
AUDIT_ARG_VNODE1(fp->f_vnode);
|
||||
VOP_UNLOCK(fp->f_vnode, 0);
|
||||
#endif
|
||||
error = setfmode(td, fp->f_vnode, uap->mode);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
error = fo_chmod(fp, uap->mode, td->td_ucred, td);
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
@ -3027,9 +3014,10 @@ fchmod(td, uap)
|
||||
/*
|
||||
* Common implementation for chown(), lchown(), and fchown()
|
||||
*/
|
||||
static int
|
||||
setfown(td, vp, uid, gid)
|
||||
int
|
||||
setfown(td, cred, vp, uid, gid)
|
||||
struct thread *td;
|
||||
struct ucred *cred;
|
||||
struct vnode *vp;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
@ -3045,11 +3033,11 @@ setfown(td, vp, uid, gid)
|
||||
vattr.va_uid = uid;
|
||||
vattr.va_gid = gid;
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_setowner(td->td_ucred, vp, vattr.va_uid,
|
||||
error = mac_vnode_check_setowner(cred, vp, vattr.va_uid,
|
||||
vattr.va_gid);
|
||||
if (error == 0)
|
||||
#endif
|
||||
error = VOP_SETATTR(vp, &vattr, td->td_ucred);
|
||||
error = VOP_SETATTR(vp, &vattr, cred);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vn_finished_write(mp);
|
||||
return (error);
|
||||
@ -3124,7 +3112,7 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
|
||||
return (error);
|
||||
vfslocked = NDHASGIANT(&nd);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
error = setfown(td, nd.ni_vp, uid, gid);
|
||||
error = setfown(td, td->td_ucred, nd.ni_vp, uid, gid);
|
||||
vrele(nd.ni_vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
return (error);
|
||||
@ -3182,22 +3170,14 @@ fchown(td, uap)
|
||||
} */ *uap;
|
||||
{
|
||||
struct file *fp;
|
||||
int vfslocked;
|
||||
int error;
|
||||
|
||||
AUDIT_ARG_FD(uap->fd);
|
||||
AUDIT_ARG_OWNER(uap->uid, uap->gid);
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FCHOWN, &fp))
|
||||
!= 0)
|
||||
error = fget(td, uap->fd, CAP_FCHOWN, &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
|
||||
#ifdef AUDIT
|
||||
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
||||
AUDIT_ARG_VNODE1(fp->f_vnode);
|
||||
VOP_UNLOCK(fp->f_vnode, 0);
|
||||
#endif
|
||||
error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td);
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
#include <security/audit/audit.h>
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
static fo_rdwr_t vn_read;
|
||||
@ -81,6 +82,8 @@ struct fileops vnops = {
|
||||
.fo_kqfilter = vn_kqfilter,
|
||||
.fo_stat = vn_statfile,
|
||||
.fo_close = vn_closefile,
|
||||
.fo_chmod = vn_chmod,
|
||||
.fo_chown = vn_chown,
|
||||
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
|
||||
};
|
||||
|
||||
@ -1357,3 +1360,41 @@ vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio,
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct vnode *vp;
|
||||
int error, vfslocked;
|
||||
|
||||
vp = fp->f_vnode;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
#ifdef AUDIT
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
AUDIT_ARG_VNODE1(vp);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
#endif
|
||||
error = setfmode(td, active_cred, vp, mode);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
struct vnode *vp;
|
||||
int error, vfslocked;
|
||||
|
||||
vp = fp->f_vnode;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
#ifdef AUDIT
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
AUDIT_ARG_VNODE1(vp);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
#endif
|
||||
error = setfown(td, active_cred, vp, uid, gid);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
return (error);
|
||||
}
|
||||
|
@ -559,7 +559,9 @@ struct fileops linuxfileops = {
|
||||
.fo_read = linux_file_read,
|
||||
.fo_poll = linux_file_poll,
|
||||
.fo_close = linux_file_close,
|
||||
.fo_ioctl = linux_file_ioctl
|
||||
.fo_ioctl = linux_file_ioctl,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -301,7 +301,9 @@ static struct fileops cryptofops = {
|
||||
.fo_poll = cryptof_poll,
|
||||
.fo_kqfilter = cryptof_kqfilter,
|
||||
.fo_stat = cryptof_stat,
|
||||
.fo_close = cryptof_close
|
||||
.fo_close = cryptof_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
};
|
||||
|
||||
static struct csession *csefind(struct fcrypt *, u_int);
|
||||
|
@ -225,6 +225,10 @@ int mac_posixsem_check_getvalue(struct ucred *active_cred,
|
||||
int mac_posixsem_check_open(struct ucred *cred, struct ksem *ks);
|
||||
int mac_posixsem_check_post(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct ksem *ks);
|
||||
int mac_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
|
||||
mode_t mode);
|
||||
int mac_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
|
||||
uid_t uid, gid_t gid);
|
||||
int mac_posixsem_check_stat(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct ksem *ks);
|
||||
int mac_posixsem_check_unlink(struct ucred *cred, struct ksem *ks);
|
||||
@ -237,6 +241,10 @@ void mac_posixsem_init(struct ksem *);
|
||||
int mac_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
|
||||
int prot, int flags);
|
||||
int mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd);
|
||||
int mac_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
|
||||
mode_t mode);
|
||||
int mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
|
||||
uid_t uid, gid_t gid);
|
||||
int mac_posixshm_check_stat(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct shmfd *shmfd);
|
||||
int mac_posixshm_check_truncate(struct ucred *active_cred,
|
||||
|
@ -336,6 +336,12 @@ typedef int (*mpo_posixsem_check_open_t)(struct ucred *cred,
|
||||
typedef int (*mpo_posixsem_check_post_t)(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct ksem *ks,
|
||||
struct label *kslabel);
|
||||
typedef int (*mpo_posixsem_check_setmode_t)(struct ucred *cred,
|
||||
struct ksem *ks, struct label *shmlabel,
|
||||
mode_t mode);
|
||||
typedef int (*mpo_posixsem_check_setowner_t)(struct ucred *cred,
|
||||
struct ksem *ks, struct label *shmlabel,
|
||||
uid_t uid, gid_t gid);
|
||||
typedef int (*mpo_posixsem_check_stat_t)(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct ksem *ks,
|
||||
struct label *kslabel);
|
||||
@ -354,6 +360,12 @@ typedef int (*mpo_posixshm_check_mmap_t)(struct ucred *cred,
|
||||
int flags);
|
||||
typedef int (*mpo_posixshm_check_open_t)(struct ucred *cred,
|
||||
struct shmfd *shmfd, struct label *shmlabel);
|
||||
typedef int (*mpo_posixshm_check_setmode_t)(struct ucred *cred,
|
||||
struct shmfd *shmfd, struct label *shmlabel,
|
||||
mode_t mode);
|
||||
typedef int (*mpo_posixshm_check_setowner_t)(struct ucred *cred,
|
||||
struct shmfd *shmfd, struct label *shmlabel,
|
||||
uid_t uid, gid_t gid);
|
||||
typedef int (*mpo_posixshm_check_stat_t)(struct ucred *active_cred,
|
||||
struct ucred *file_cred, struct shmfd *shmfd,
|
||||
struct label *shmlabel);
|
||||
@ -791,6 +803,8 @@ struct mac_policy_ops {
|
||||
mpo_posixsem_check_getvalue_t mpo_posixsem_check_getvalue;
|
||||
mpo_posixsem_check_open_t mpo_posixsem_check_open;
|
||||
mpo_posixsem_check_post_t mpo_posixsem_check_post;
|
||||
mpo_posixsem_check_setmode_t mpo_posixsem_check_setmode;
|
||||
mpo_posixsem_check_setowner_t mpo_posixsem_check_setowner;
|
||||
mpo_posixsem_check_stat_t mpo_posixsem_check_stat;
|
||||
mpo_posixsem_check_unlink_t mpo_posixsem_check_unlink;
|
||||
mpo_posixsem_check_wait_t mpo_posixsem_check_wait;
|
||||
@ -800,6 +814,8 @@ struct mac_policy_ops {
|
||||
|
||||
mpo_posixshm_check_mmap_t mpo_posixshm_check_mmap;
|
||||
mpo_posixshm_check_open_t mpo_posixshm_check_open;
|
||||
mpo_posixshm_check_setmode_t mpo_posixshm_check_setmode;
|
||||
mpo_posixshm_check_setowner_t mpo_posixshm_check_setowner;
|
||||
mpo_posixshm_check_stat_t mpo_posixshm_check_stat;
|
||||
mpo_posixshm_check_truncate_t mpo_posixshm_check_truncate;
|
||||
mpo_posixshm_check_unlink_t mpo_posixshm_check_unlink;
|
||||
|
@ -198,3 +198,35 @@ mac_posixsem_check_wait(struct ucred *active_cred, struct ucred *file_cred,
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
MAC_CHECK_PROBE_DEFINE3(posixsem_check_setmode, "struct ucred *",
|
||||
"struct ksem *", "mode_t");
|
||||
|
||||
int
|
||||
mac_posixsem_check_setmode(struct ucred *cred, struct ksem *ks, mode_t mode)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK_NOSLEEP(posixsem_check_setmode, cred, ks,
|
||||
ks->ks_label, mode);
|
||||
MAC_CHECK_PROBE3(posixsem_check_setmode, error, cred, ks, mode);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
MAC_CHECK_PROBE_DEFINE4(posixsem_check_setowner, "struct ucred *",
|
||||
"struct ks *", "uid_t", "gid_t");
|
||||
|
||||
int
|
||||
mac_posixsem_check_setowner(struct ucred *cred, struct ksem *ks, uid_t uid,
|
||||
gid_t gid)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK_NOSLEEP(posixsem_check_setowner, cred, ks,
|
||||
ks->ks_label, uid, gid);
|
||||
MAC_CHECK_PROBE4(posixsem_check_setowner, error, cred, ks,
|
||||
uid, gid);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -181,3 +181,35 @@ mac_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd)
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
MAC_CHECK_PROBE_DEFINE3(posixshm_check_setmode, "struct ucred *",
|
||||
"struct shmfd *", "mode_t");
|
||||
|
||||
int
|
||||
mac_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd, mode_t mode)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK_NOSLEEP(posixshm_check_setmode, cred, shmfd,
|
||||
shmfd->shm_label, mode);
|
||||
MAC_CHECK_PROBE3(posixshm_check_setmode, error, cred, shmfd, mode);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
MAC_CHECK_PROBE_DEFINE4(posixshm_check_setowner, "struct ucred *",
|
||||
"struct shmfd *", "uid_t", "gid_t");
|
||||
|
||||
int
|
||||
mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd, uid_t uid,
|
||||
gid_t gid)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK_NOSLEEP(posixshm_check_setowner, cred, shmfd,
|
||||
shmfd->shm_label, uid, gid);
|
||||
MAC_CHECK_PROBE4(posixshm_check_setowner, error, cred, shmfd,
|
||||
uid, gid);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -686,6 +686,22 @@ stub_posixsem_check_post(struct ucred *active_cred, struct ucred *file_cred,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
|
||||
struct label *kslabel, mode_t mode)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
|
||||
struct label *kslabel, uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixsem_check_stat(struct ucred *active_cred, struct ucred *file_cred,
|
||||
struct ksem *ks, struct label *kslabel)
|
||||
@ -733,6 +749,22 @@ stub_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
|
||||
struct label *shmlabel, mode_t mode)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
|
||||
struct label *shmlabel, uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
stub_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
|
||||
struct shmfd *shmfd, struct label *shmlabel)
|
||||
@ -1731,6 +1763,8 @@ static struct mac_policy_ops stub_ops =
|
||||
.mpo_posixsem_check_getvalue = stub_posixsem_check_getvalue,
|
||||
.mpo_posixsem_check_open = stub_posixsem_check_open,
|
||||
.mpo_posixsem_check_post = stub_posixsem_check_post,
|
||||
.mpo_posixsem_check_setmode = stub_posixsem_check_setmode,
|
||||
.mpo_posixsem_check_setowner = stub_posixsem_check_setowner,
|
||||
.mpo_posixsem_check_stat = stub_posixsem_check_stat,
|
||||
.mpo_posixsem_check_unlink = stub_posixsem_check_unlink,
|
||||
.mpo_posixsem_check_wait = stub_posixsem_check_wait,
|
||||
@ -1740,6 +1774,8 @@ static struct mac_policy_ops stub_ops =
|
||||
|
||||
.mpo_posixshm_check_mmap = stub_posixshm_check_mmap,
|
||||
.mpo_posixshm_check_open = stub_posixshm_check_open,
|
||||
.mpo_posixshm_check_setmode = stub_posixshm_check_setmode,
|
||||
.mpo_posixshm_check_setowner = stub_posixshm_check_setowner,
|
||||
.mpo_posixshm_check_stat = stub_posixshm_check_stat,
|
||||
.mpo_posixshm_check_truncate = stub_posixshm_check_truncate,
|
||||
.mpo_posixshm_check_unlink = stub_posixshm_check_unlink,
|
||||
|
@ -1297,6 +1297,30 @@ test_posixsem_check_post(struct ucred *active_cred, struct ucred *file_cred,
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixsem_check_setmode);
|
||||
static int
|
||||
test_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
|
||||
struct label *kslabel, mode_t mode)
|
||||
{
|
||||
|
||||
LABEL_CHECK(cred->cr_label, MAGIC_CRED);
|
||||
LABEL_CHECK(kslabel, MAGIC_POSIX_SHM);
|
||||
COUNTER_INC(posixsem_check_setmode);
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixsem_check_setowner);
|
||||
static int
|
||||
test_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
|
||||
struct label *kslabel, uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
LABEL_CHECK(cred->cr_label, MAGIC_CRED);
|
||||
LABEL_CHECK(kslabel, MAGIC_POSIX_SHM);
|
||||
COUNTER_INC(posixsem_check_setowner);
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixsem_check_stat);
|
||||
static int
|
||||
test_posixsem_check_stat(struct ucred *active_cred,
|
||||
@ -1390,6 +1414,30 @@ test_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixshm_check_setmode);
|
||||
static int
|
||||
test_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
|
||||
struct label *shmfdlabel, mode_t mode)
|
||||
{
|
||||
|
||||
LABEL_CHECK(cred->cr_label, MAGIC_CRED);
|
||||
LABEL_CHECK(shmfdlabel, MAGIC_POSIX_SHM);
|
||||
COUNTER_INC(posixshm_check_setmode);
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixshm_check_setowner);
|
||||
static int
|
||||
test_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
|
||||
struct label *shmfdlabel, uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
LABEL_CHECK(cred->cr_label, MAGIC_CRED);
|
||||
LABEL_CHECK(shmfdlabel, MAGIC_POSIX_SHM);
|
||||
COUNTER_INC(posixshm_check_setowner);
|
||||
return (0);
|
||||
}
|
||||
|
||||
COUNTER_DECL(posixshm_check_stat);
|
||||
static int
|
||||
test_posixshm_check_stat(struct ucred *active_cred,
|
||||
@ -3045,6 +3093,8 @@ static struct mac_policy_ops test_ops =
|
||||
.mpo_posixsem_check_getvalue = test_posixsem_check_getvalue,
|
||||
.mpo_posixsem_check_open = test_posixsem_check_open,
|
||||
.mpo_posixsem_check_post = test_posixsem_check_post,
|
||||
.mpo_posixsem_check_setmode = test_posixsem_check_setmode,
|
||||
.mpo_posixsem_check_setowner = test_posixsem_check_setowner,
|
||||
.mpo_posixsem_check_stat = test_posixsem_check_stat,
|
||||
.mpo_posixsem_check_unlink = test_posixsem_check_unlink,
|
||||
.mpo_posixsem_check_wait = test_posixsem_check_wait,
|
||||
@ -3054,6 +3104,8 @@ static struct mac_policy_ops test_ops =
|
||||
|
||||
.mpo_posixshm_check_mmap = test_posixshm_check_mmap,
|
||||
.mpo_posixshm_check_open = test_posixshm_check_open,
|
||||
.mpo_posixshm_check_setmode = test_posixshm_check_setmode,
|
||||
.mpo_posixshm_check_setowner = test_posixshm_check_setowner,
|
||||
.mpo_posixshm_check_stat = test_posixshm_check_stat,
|
||||
.mpo_posixshm_check_truncate = test_posixshm_check_truncate,
|
||||
.mpo_posixshm_check_unlink = test_posixshm_check_unlink,
|
||||
|
@ -85,6 +85,10 @@ typedef int fo_kqfilter_t(struct file *fp, struct knote *kn);
|
||||
typedef int fo_stat_t(struct file *fp, struct stat *sb,
|
||||
struct ucred *active_cred, struct thread *td);
|
||||
typedef int fo_close_t(struct file *fp, struct thread *td);
|
||||
typedef int fo_chmod_t(struct file *fp, mode_t mode,
|
||||
struct ucred *active_cred, struct thread *td);
|
||||
typedef int fo_chown_t(struct file *fp, uid_t uid, gid_t gid,
|
||||
struct ucred *active_cred, struct thread *td);
|
||||
typedef int fo_flags_t;
|
||||
|
||||
struct fileops {
|
||||
@ -96,6 +100,8 @@ struct fileops {
|
||||
fo_kqfilter_t *fo_kqfilter;
|
||||
fo_stat_t *fo_stat;
|
||||
fo_close_t *fo_close;
|
||||
fo_chmod_t *fo_chmod;
|
||||
fo_chown_t *fo_chown;
|
||||
fo_flags_t fo_flags; /* DFLAG_* below */
|
||||
};
|
||||
|
||||
@ -200,6 +206,9 @@ fo_kqfilter_t soo_kqfilter;
|
||||
fo_stat_t soo_stat;
|
||||
fo_close_t soo_close;
|
||||
|
||||
fo_chmod_t invfo_chmod;
|
||||
fo_chown_t invfo_chown;
|
||||
|
||||
void finit(struct file *, u_int, short, void *, struct fileops *);
|
||||
int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
|
||||
int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
|
||||
@ -233,6 +242,8 @@ static __inline fo_poll_t fo_poll;
|
||||
static __inline fo_kqfilter_t fo_kqfilter;
|
||||
static __inline fo_stat_t fo_stat;
|
||||
static __inline fo_close_t fo_close;
|
||||
static __inline fo_chmod_t fo_chmod;
|
||||
static __inline fo_chown_t fo_chown;
|
||||
|
||||
static __inline int
|
||||
fo_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
@ -296,6 +307,22 @@ fo_kqfilter(struct file *fp, struct knote *kn)
|
||||
return ((*fp->f_ops->fo_kqfilter)(fp, kn));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return ((*fp->f_ops->fo_chmod)(fp, mode, active_cred, td));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
fo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return ((*fp->f_ops->fo_chown)(fp, uid, gid, active_cred, td));
|
||||
}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !SYS_FILE_H */
|
||||
|
@ -780,6 +780,14 @@ int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
|
||||
|
||||
int vfs_unixify_accmode(accmode_t *accmode);
|
||||
|
||||
int setfmode(struct thread *td, struct ucred *cred, struct vnode *vp, int mode);
|
||||
int setfown(struct thread *td, struct ucred *cred, struct vnode *vp, uid_t uid,
|
||||
gid_t gid);
|
||||
int vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td);
|
||||
int vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_VNODE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user