summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-08-16 20:07:47 +0000
committerkib <kib@FreeBSD.org>2011-08-16 20:07:47 +0000
commit011f42054d1f861cd2435866ba646fa0cf752103 (patch)
tree368bd0d481caa3081d9e36be04c87a458ccd8975 /sys/kern
parenta5a39a26b2ea8ab4d283505d58396a5e76d38c7a (diff)
downloadFreeBSD-src-011f42054d1f861cd2435866ba646fa0cf752103.zip
FreeBSD-src-011f42054d1f861cd2435866ba646fa0cf752103.tar.gz
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)
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c33
-rw-r--r--sys/kern/kern_event.c2
-rw-r--r--sys/kern/sys_capability.c22
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/sys_socket.c2
-rw-r--r--sys/kern/tty_pts.c2
-rw-r--r--sys/kern/uipc_mqueue.c49
-rw-r--r--sys/kern/uipc_sem.c64
-rw-r--r--sys/kern/uipc_shm.c77
-rw-r--r--sys/kern/vfs_syscalls.c60
-rw-r--r--sys/kern/vfs_vnops.c41
11 files changed, 308 insertions, 46 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index cf4eced..85f866c 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -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);
+}
/*-------------------------------------------------------------------*/
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index e282cd5..c512b0a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -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);
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index 0eb27f3..318ffe4 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -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 */
/*
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 50b0389..14e1207 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -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
};
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index c9b0534..cd6f655 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -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
};
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index a3db59b..cf9f94d 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -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,
};
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 0ca4161..fbd78c1 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -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,10 +2477,56 @@ 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)
{
struct mqueue *mq = FPTOMQ(fp);
@@ -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
};
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 82a4622..95c29c0 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -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,19 +224,75 @@ 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_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)
{
struct ksem *ks;
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 0414f12..45989cf 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -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_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);
+}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 35d1aee..c0ae0a7 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -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);
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index e8bcc91..a8f1bf1 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -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);
+}
OpenPOWER on IntegriCloud