From owner-freebsd-standards@FreeBSD.ORG Thu Aug 11 13:20:11 2011 Return-Path: Delivered-To: freebsd-standards@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 85055106566B for ; Thu, 11 Aug 2011 13:20:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 729E28FC16 for ; Thu, 11 Aug 2011 13:20:11 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p7BDKBbC015742 for ; Thu, 11 Aug 2011 13:20:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p7BDKB8T015741; Thu, 11 Aug 2011 13:20:11 GMT (envelope-from gnats) Date: Thu, 11 Aug 2011 13:20:11 GMT Message-Id: <201108111320.p7BDKB8T015741@freefall.freebsd.org> To: freebsd-standards@FreeBSD.org From: Kostik Belousov Cc: Subject: Re: standards/159679: [patch] [standards] fchmod(2) fails on descriptor referencing shared memory X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Kostik Belousov List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Aug 2011 13:20:11 -0000 The following reply was made to PR standards/159679; it has been noted by GNATS. From: Kostik Belousov To: Gleb Smirnoff Cc: FreeBSD-gnats-submit@freebsd.org, Roland Olbricht Subject: Re: standards/159679: [patch] [standards] fchmod(2) fails on descriptor referencing shared memory Date: Thu, 11 Aug 2011 16:15:28 +0300 --ja0vWYS1o1njzvo7 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Aug 11, 2011 at 02:36:08PM +0300, Kostik Belousov wrote: > I do not think the patch is the right thing to do. My opinion is that > struct fileops should grow another method, say fo_chmod, instead of > adding yet another switch on the f_type. I mean the following. diff --git a/sys/dev/streams/streams.c b/sys/dev/streams/streams.c index 00f65a3..4b47949 100644 --- a/sys/dev/streams/streams.c +++ b/sys/dev/streams/streams.c @@ -95,7 +95,8 @@ static struct fileops svr4_netops =3D { .fo_poll =3D soo_poll, .fo_kqfilter =3D soo_kqfilter, .fo_stat =3D soo_stat, - .fo_close =3D svr4_soo_close + .fo_close =3D svr4_soo_close, + .fo_chmod =3D badfo_chmod, }; =20 static struct cdevsw streams_cdevsw =3D { diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 955bd8b..ed6fb00 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -1665,6 +1665,7 @@ static struct fileops devfs_ops_f =3D { .fo_kqfilter =3D devfs_kqfilter_f, .fo_stat =3D devfs_stat_f, .fo_close =3D devfs_close_f, + .fo_chmod =3D vn_chmod, .fo_flags =3D DFLAG_PASSABLE | DFLAG_SEEKABLE }; =20 diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index e339a8a..8048f21 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -72,6 +72,7 @@ struct fileops fifo_ops_f =3D { .fo_kqfilter =3D fifo_kqfilter_f, .fo_stat =3D fifo_stat_f, .fo_close =3D fifo_close_f, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE }; =20 diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index f3f9cbc..d20c6d5 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -3725,6 +3725,13 @@ badfo_close(struct file *fp, struct thread *td) return (EBADF); } =20 +int +badfo_chmod(struct file *fp, mode_t mode, struct thread *td) +{ + + return (EINVAL); +} + struct fileops badfileops =3D { .fo_read =3D badfo_readwrite, .fo_write =3D badfo_readwrite, @@ -3734,6 +3741,7 @@ struct fileops badfileops =3D { .fo_kqfilter =3D badfo_kqfilter, .fo_stat =3D badfo_stat, .fo_close =3D badfo_close, + .fo_chmod =3D badfo_chmod, }; =20 =20 diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index e14ae02..1eef3b3 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -122,6 +122,7 @@ static struct fileops kqueueops =3D { .fo_kqfilter =3D kqueue_kqfilter, .fo_stat =3D kqueue_stat, .fo_close =3D kqueue_close, + .fo_chmod =3D badfo_chmod, }; =20 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 6ca9602..35e5564 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -154,6 +154,7 @@ static struct fileops capability_ops =3D { .fo_kqfilter =3D capability_kqfilter, .fo_stat =3D capability_stat, .fo_close =3D capability_close, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE, }; =20 @@ -166,6 +167,7 @@ static struct fileops capability_ops_unpassable =3D { .fo_kqfilter =3D capability_kqfilter, .fo_stat =3D capability_stat, .fo_close =3D capability_close, + .fo_chmod =3D badfo_chmod, .fo_flags =3D 0, }; =20 diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 50b0389..8ff5ed2 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -155,6 +155,7 @@ static struct fileops pipeops =3D { .fo_kqfilter =3D pipe_kqfilter, .fo_stat =3D pipe_stat, .fo_close =3D pipe_close, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE }; =20 diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index c9b0534..4ef8506 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -64,6 +64,7 @@ struct fileops socketops =3D { .fo_kqfilter =3D soo_kqfilter, .fo_stat =3D soo_stat, .fo_close =3D soo_close, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE }; =20 diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index a3db59b..51704cf 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -597,6 +597,7 @@ static struct fileops ptsdev_ops =3D { .fo_kqfilter =3D ptsdev_kqfilter, .fo_stat =3D ptsdev_stat, .fo_close =3D ptsdev_close, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE, }; =20 diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 9b334ac..cfb1db5 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2523,6 +2523,7 @@ static struct fileops mqueueops =3D { .fo_poll =3D mqf_poll, .fo_kqfilter =3D mqf_kqfilter, .fo_stat =3D mqf_stat, + .fo_chmod =3D badfo_chmod, .fo_close =3D mqf_close }; =20 diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 917c343..5bb1b1b 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -144,6 +144,7 @@ static struct fileops ksem_ops =3D { .fo_kqfilter =3D ksem_kqfilter, .fo_stat =3D ksem_stat, .fo_close =3D ksem_closef, + .fo_chmod =3D badfo_chmod, .fo_flags =3D DFLAG_PASSABLE }; =20 diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index 0414f12..2a6d0f2 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -123,6 +123,7 @@ 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; =20 /* File descriptor operations. */ static struct fileops shm_ops =3D { @@ -134,6 +135,7 @@ static struct fileops shm_ops =3D { .fo_kqfilter =3D shm_kqfilter, .fo_stat =3D shm_stat, .fo_close =3D shm_close, + .fo_chmod =3D shm_chmod, .fo_flags =3D DFLAG_PASSABLE }; =20 @@ -651,3 +653,13 @@ shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_oo= ffset_t foff, *obj =3D shmfd->shm_object; return (0); } + +static int +shm_chmod(struct file *fp, mode_t mode, struct thread *td) +{ + struct shmfd *shmfd; + + shmfd =3D fp->f_data; + shmfd->shm_mode =3D mode & ACCESSPERMS; + return (0); +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index b48c6e7..b0b3515 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -95,7 +95,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); @@ -2792,7 +2791,7 @@ fchflags(td, uap) /* * Common implementation code for chmod(), lchmod() and fchmod(). */ -static int +int setfmode(td, vp, mode) struct thread *td; struct vnode *vp; @@ -2922,30 +2921,18 @@ struct fchmod_args { int mode; }; #endif -int -fchmod(td, uap) - struct thread *td; - register struct fchmod_args /* { - int fd; - int mode; - } */ *uap; +int fchmod(struct thread *td, struct fchmod_args *uap) { struct file *fp; - int vfslocked; int error; =20 AUDIT_ARG_FD(uap->fd); AUDIT_ARG_MODE(uap->mode); - if ((error =3D getvnode(td->td_proc->p_fd, uap->fd, &fp)) !=3D 0) + + error =3D fget(td, uap->fd, &fp); + if (error !=3D 0) return (error); - vfslocked =3D 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 =3D setfmode(td, fp->f_vnode, uap->mode); - VFS_UNLOCK_GIANT(vfslocked); + error =3D fo_chmod(fp, uap->mode, td); fdrop(fp, td); return (error); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index e8bcc91..9f4f4ff 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -81,6 +81,7 @@ struct fileops vnops =3D { .fo_kqfilter =3D vn_kqfilter, .fo_stat =3D vn_statfile, .fo_close =3D vn_closefile, + .fo_chmod =3D vn_chmod, .fo_flags =3D DFLAG_PASSABLE | DFLAG_SEEKABLE }; =20 @@ -1357,3 +1358,20 @@ 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 thread *td) +{ + int vfslocked; + int error; + + vfslocked =3D 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 =3D setfmode(td, fp->f_vnode, mode); + VFS_UNLOCK_GIANT(vfslocked); + return (error); +} diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux= /linux_compat.c index 98ad807..394a7d0 100644 --- a/sys/ofed/include/linux/linux_compat.c +++ b/sys/ofed/include/linux/linux_compat.c @@ -559,7 +559,8 @@ struct fileops linuxfileops =3D { .fo_read =3D linux_file_read, .fo_poll =3D linux_file_poll, .fo_close =3D linux_file_close, - .fo_ioctl =3D linux_file_ioctl + .fo_ioctl =3D linux_file_ioctl, + .fo_chmod =3D badfo_chmod, }; =20 /* diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index 2c0c503..802a950 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -301,7 +301,8 @@ static struct fileops cryptofops =3D { .fo_poll =3D cryptof_poll, .fo_kqfilter =3D cryptof_kqfilter, .fo_stat =3D cryptof_stat, - .fo_close =3D cryptof_close + .fo_close =3D cryptof_close, + .fo_chmod =3D badfo_chmod, }; =20 static struct csession *csefind(struct fcrypt *, u_int); diff --git a/sys/sys/file.h b/sys/sys/file.h index eea2c00..4ad7abb 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -85,6 +85,7 @@ 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 thread *td); typedef int fo_flags_t; =20 struct fileops { @@ -96,6 +97,7 @@ struct fileops { fo_kqfilter_t *fo_kqfilter; fo_stat_t *fo_stat; fo_close_t *fo_close; + fo_chmod_t *fo_chmod; fo_flags_t fo_flags; /* DFLAG_* below */ }; =20 @@ -196,6 +198,8 @@ fo_kqfilter_t soo_kqfilter; fo_stat_t soo_stat; fo_close_t soo_close; =20 +fo_chmod_t badfo_chmod; + void finit(struct file *, u_int, short, void *, struct fileops *); int fgetvp(struct thread *td, int fd, struct vnode **vpp); int fgetvp_read(struct thread *td, int fd, struct vnode **vpp); @@ -224,6 +228,7 @@ 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; =20 static __inline int fo_read(struct file *fp, struct uio *uio, struct ucred *active_cred, @@ -287,6 +292,13 @@ fo_kqfilter(struct file *fp, struct knote *kn) return ((*fp->f_ops->fo_kqfilter)(fp, kn)); } =20 +static __inline int +fo_chmod(struct file *fp, mode_t mode, struct thread *td) +{ + + return ((*fp->f_ops->fo_chmod)(fp, mode, td)); +} + #endif /* _KERNEL */ =20 #endif /* !SYS_FILE_H */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 1c4c7b7..35a4133 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -778,7 +778,10 @@ void vfs_mark_atime(struct vnode *vp, struct ucred *cr= ed); struct dirent; int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t = off); =20 -int vfs_unixify_accmode(accmode_t *accmode); +int vfs_unixify_accmode(accmode_t *accmode); + +int setfmode(struct thread *td, struct vnode *, int); +int vn_chmod(struct file *fp, mode_t mode, struct thread *td); =20 #endif /* _KERNEL */ =20 --ja0vWYS1o1njzvo7 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (FreeBSD) iEYEARECAAYFAk5D1e8ACgkQC3+MBN1Mb4jZpQCbBPgnCYYp0jgZsA1zWxsU9Yw7 U5sAn2+eZ6fdKXRbWCcztFKhyuyG9EMh =LX6t -----END PGP SIGNATURE----- --ja0vWYS1o1njzvo7--