standards/159679: [patch] [standards] fchmod(2) fails on
descriptor referencing shared memory
Kostik Belousov
kostikbel at gmail.com
Thu Aug 11 13:20:11 UTC 2011
The following reply was made to PR standards/159679; it has been noted by GNATS.
From: Kostik Belousov <kostikbel at gmail.com>
To: Gleb Smirnoff <glebius at freebsd.org>
Cc: FreeBSD-gnats-submit at freebsd.org, Roland Olbricht <roland.olbricht at 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--
More information about the freebsd-standards
mailing list