From owner-svn-src-all@FreeBSD.ORG Tue Aug 16 20:07:48 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7E97F1065670; Tue, 16 Aug 2011 20:07:48 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6AD0B8FC1A; Tue, 16 Aug 2011 20:07:48 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p7GK7mP7071540; Tue, 16 Aug 2011 20:07:48 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p7GK7muH071515; Tue, 16 Aug 2011 20:07:48 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201108162007.p7GK7muH071515@svn.freebsd.org> From: Konstantin Belousov Date: Tue, 16 Aug 2011 20:07:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: 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 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Aug 2011 20:07:48 -0000 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 #include #include +#include #include #include #include @@ -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 #include +#include #include 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 ***