Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Aug 2011 20:07:48 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r224914 - in head/sys: dev/streams fs/devfs fs/fifofs kern ofed/include/linux opencrypto security/mac security/mac_stub security/mac_test sys
Message-ID:  <201108162007.p7GK7muH071515@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Aug 16 20:07:47 2011
New Revision: 224914
URL: http://svn.freebsd.org/changeset/base/224914

Log:
  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)

Modified:
  head/sys/dev/streams/streams.c
  head/sys/fs/devfs/devfs_vnops.c
  head/sys/fs/fifofs/fifo_vnops.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_event.c
  head/sys/kern/sys_capability.c
  head/sys/kern/sys_pipe.c
  head/sys/kern/sys_socket.c
  head/sys/kern/tty_pts.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/uipc_sem.c
  head/sys/kern/uipc_shm.c
  head/sys/kern/vfs_syscalls.c
  head/sys/kern/vfs_vnops.c
  head/sys/ofed/include/linux/linux_compat.c
  head/sys/opencrypto/cryptodev.c
  head/sys/security/mac/mac_framework.h
  head/sys/security/mac/mac_policy.h
  head/sys/security/mac/mac_posix_sem.c
  head/sys/security/mac/mac_posix_shm.c
  head/sys/security/mac_stub/mac_stub.c
  head/sys/security/mac_test/mac_test.c
  head/sys/sys/file.h
  head/sys/sys/vnode.h

Modified: head/sys/dev/streams/streams.c
==============================================================================
--- head/sys/dev/streams/streams.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/dev/streams/streams.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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 = {

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/fs/devfs/devfs_vnops.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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
 };
 

Modified: head/sys/fs/fifofs/fifo_vnops.c
==============================================================================
--- head/sys/fs/fifofs/fifo_vnops.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/fs/fifofs/fifo_vnops.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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
 };
 

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/kern_descrip.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -3774,6 +3774,22 @@ badfo_close(struct file *fp, struct thre
 	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);
+}
 
 /*-------------------------------------------------------------------*/
 

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/kern_event.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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);

Modified: head/sys/kern/sys_capability.c
==============================================================================
--- head/sys/kern/sys_capability.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/sys_capability.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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_unp
 	.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 
 	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 */
 
 /*

Modified: head/sys/kern/sys_pipe.c
==============================================================================
--- head/sys/kern/sys_pipe.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/sys_pipe.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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
 };
 

Modified: head/sys/kern/sys_socket.c
==============================================================================
--- head/sys/kern/sys_socket.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/sys_socket.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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
 };
 

Modified: head/sys/kern/tty_pts.c
==============================================================================
--- head/sys/kern/tty_pts.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/tty_pts.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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,
 };
 

Modified: head/sys/kern/uipc_mqueue.c
==============================================================================
--- head/sys/kern/uipc_mqueue.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/uipc_mqueue.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -2469,6 +2469,7 @@ mqf_stat(struct file *fp, struct stat *s
 	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 *s
 	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
 };
 

Modified: head/sys/kern/uipc_sem.c
==============================================================================
--- head/sys/kern/uipc_sem.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/uipc_sem.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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 *
 	 * 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;

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/uipc_shm.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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 *s
 	 * 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 
 	*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);
+}

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/vfs_syscalls.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -96,8 +96,6 @@ SDT_PROBE_ARGTYPE(vfs, , stat, reg, 1, "
 
 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,
 		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,
 		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);
 }

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/kern/vfs_vnops.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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, 
 	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);
+}

Modified: head/sys/ofed/include/linux/linux_compat.c
==============================================================================
--- head/sys/ofed/include/linux/linux_compat.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/ofed/include/linux/linux_compat.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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,
 };
 
 /*

Modified: head/sys/opencrypto/cryptodev.c
==============================================================================
--- head/sys/opencrypto/cryptodev.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/opencrypto/cryptodev.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -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);

Modified: head/sys/security/mac/mac_framework.h
==============================================================================
--- head/sys/security/mac/mac_framework.h	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac/mac_framework.h	Tue Aug 16 20:07:47 2011	(r224914)
@@ -225,6 +225,10 @@ int	mac_posixsem_check_getvalue(struct u
 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,

Modified: head/sys/security/mac/mac_policy.h
==============================================================================
--- head/sys/security/mac/mac_policy.h	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac/mac_policy.h	Tue Aug 16 20:07:47 2011	(r224914)
@@ -336,6 +336,12 @@ typedef int	(*mpo_posixsem_check_open_t)
 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)
 		    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;

Modified: head/sys/security/mac/mac_posix_sem.c
==============================================================================
--- head/sys/security/mac/mac_posix_sem.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac/mac_posix_sem.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -198,3 +198,35 @@ mac_posixsem_check_wait(struct ucred *ac
 
 	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);
+}

Modified: head/sys/security/mac/mac_posix_shm.c
==============================================================================
--- head/sys/security/mac/mac_posix_shm.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac/mac_posix_shm.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -181,3 +181,35 @@ mac_posixshm_check_unlink(struct ucred *
 
 	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);
+}

Modified: head/sys/security/mac_stub/mac_stub.c
==============================================================================
--- head/sys/security/mac_stub/mac_stub.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac_stub/mac_stub.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -687,6 +687,22 @@ stub_posixsem_check_post(struct ucred *a
 }
 
 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)
 {
@@ -734,6 +750,22 @@ stub_posixshm_check_open(struct ucred *c
 }
 
 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,

Modified: head/sys/security/mac_test/mac_test.c
==============================================================================
--- head/sys/security/mac_test/mac_test.c	Tue Aug 16 19:46:13 2011	(r224913)
+++ head/sys/security/mac_test/mac_test.c	Tue Aug 16 20:07:47 2011	(r224914)
@@ -1297,6 +1297,30 @@ test_posixsem_check_post(struct ucred *a
 	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 *c
 	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,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108162007.p7GK7muH071515>