Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Aug 2011 13:20:11 GMT
From:      Kostik Belousov <kostikbel@gmail.com>
To:        freebsd-standards@FreeBSD.org
Subject:   Re: standards/159679: [patch] [standards] fchmod(2) fails on descriptor referencing shared memory
Message-ID:  <201108111320.p7BDKB8T015741@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR standards/159679; it has been noted by GNATS.

From: Kostik Belousov <kostikbel@gmail.com>
To: Gleb Smirnoff <glebius@freebsd.org>
Cc: FreeBSD-gnats-submit@freebsd.org, Roland Olbricht <roland.olbricht@gmx.de>
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--



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