mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
Fix various issues with invalid file operations:
- Add invfo_rdwr() (for read and write), invfo_ioctl(), invfo_poll(), and invfo_kqfilter() for use by file types that do not support the respective operations. Home-grown versions of invfo_poll() were universally broken (they returned an errno value, invfo_poll() uses poll_no_poll() to return an appropriate event mask). Home-grown ioctl routines also tended to return an incorrect errno (invfo_ioctl returns ENOTTY). - Use the invfo_*() functions instead of local versions for unsupported file operations. - Reorder fileops members to match the order in the structure definition to make it easier to spot missing members. - Add several missing methods to linuxfileops used by the OFED shim layer: fo_write(), fo_truncate(), fo_kqfilter(), and fo_stat(). Most of these used invfo_*(), but a dummy fo_stat() implementation was added.
This commit is contained in:
parent
cd550b9b52
commit
2d69d0dcc2
10 changed files with 79 additions and 282 deletions
|
|
@ -3940,6 +3940,14 @@ struct fileops badfileops = {
|
|||
.fo_sendfile = badfo_sendfile,
|
||||
};
|
||||
|
||||
int
|
||||
invfo_rdwr(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
invfo_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
@ -3948,6 +3956,29 @@ invfo_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
|||
return (EINVAL);
|
||||
}
|
||||
|
||||
int
|
||||
invfo_ioctl(struct file *fp, u_long com, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
int
|
||||
invfo_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (poll_no_poll(events));
|
||||
}
|
||||
|
||||
int
|
||||
invfo_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
int
|
||||
invfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ static void kqueue_wakeup(struct kqueue *kq);
|
|||
static struct filterops *kqueue_fo_find(int filt);
|
||||
static void kqueue_fo_release(int filt);
|
||||
|
||||
static fo_rdwr_t kqueue_read;
|
||||
static fo_rdwr_t kqueue_write;
|
||||
static fo_truncate_t kqueue_truncate;
|
||||
static fo_ioctl_t kqueue_ioctl;
|
||||
static fo_poll_t kqueue_poll;
|
||||
static fo_kqfilter_t kqueue_kqfilter;
|
||||
|
|
@ -119,9 +116,9 @@ static fo_stat_t kqueue_stat;
|
|||
static fo_close_t kqueue_close;
|
||||
|
||||
static struct fileops kqueueops = {
|
||||
.fo_read = kqueue_read,
|
||||
.fo_write = kqueue_write,
|
||||
.fo_truncate = kqueue_truncate,
|
||||
.fo_read = invfo_rdwr,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = kqueue_ioctl,
|
||||
.fo_poll = kqueue_poll,
|
||||
.fo_kqfilter = kqueue_kqfilter,
|
||||
|
|
@ -1602,35 +1599,6 @@ done_nl:
|
|||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* This could be expanded to call kqueue_scan, if desired.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
kqueue_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
kqueue_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
kqueue_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
kqueue_ioctl(struct file *fp, u_long cmd, void *data,
|
||||
|
|
|
|||
|
|
@ -87,28 +87,22 @@ FEATURE(process_descriptors, "Process Descriptors");
|
|||
|
||||
static uma_zone_t procdesc_zone;
|
||||
|
||||
static fo_rdwr_t procdesc_read;
|
||||
static fo_rdwr_t procdesc_write;
|
||||
static fo_truncate_t procdesc_truncate;
|
||||
static fo_ioctl_t procdesc_ioctl;
|
||||
static fo_poll_t procdesc_poll;
|
||||
static fo_kqfilter_t procdesc_kqfilter;
|
||||
static fo_stat_t procdesc_stat;
|
||||
static fo_close_t procdesc_close;
|
||||
static fo_chmod_t procdesc_chmod;
|
||||
static fo_chown_t procdesc_chown;
|
||||
|
||||
static struct fileops procdesc_ops = {
|
||||
.fo_read = procdesc_read,
|
||||
.fo_write = procdesc_write,
|
||||
.fo_truncate = procdesc_truncate,
|
||||
.fo_ioctl = procdesc_ioctl,
|
||||
.fo_read = invfo_rdwr,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = invfo_ioctl,
|
||||
.fo_poll = procdesc_poll,
|
||||
.fo_kqfilter = procdesc_kqfilter,
|
||||
.fo_stat = procdesc_stat,
|
||||
.fo_close = procdesc_close,
|
||||
.fo_chmod = procdesc_chmod,
|
||||
.fo_chown = procdesc_chown,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_sendfile = invfo_sendfile,
|
||||
.fo_flags = DFLAG_PASSABLE,
|
||||
};
|
||||
|
|
@ -412,38 +406,6 @@ procdesc_close(struct file *fp, struct thread *td)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_ioctl(struct file *fp, u_long com, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
@ -569,18 +531,3 @@ procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
procdesc_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,14 +252,6 @@ done: ttydisc_rint_done(tp);
|
|||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ptsdev_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
ptsdev_ioctl(struct file *fp, u_long cmd, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
|
|
@ -591,7 +583,7 @@ ptsdev_close(struct file *fp, struct thread *td)
|
|||
static struct fileops ptsdev_ops = {
|
||||
.fo_read = ptsdev_read,
|
||||
.fo_write = ptsdev_write,
|
||||
.fo_truncate = ptsdev_truncate,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = ptsdev_ioctl,
|
||||
.fo_poll = ptsdev_poll,
|
||||
.fo_kqfilter = ptsdev_kqfilter,
|
||||
|
|
|
|||
|
|
@ -2417,35 +2417,6 @@ mq_proc_exit(void *arg __unused, struct proc *p)
|
|||
KASSERT(LIST_EMPTY(&p->p_mqnotifier), ("mq notifiers left"));
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_ioctl(struct file *fp, u_long cmd, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
static int
|
||||
mqf_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
@ -2601,16 +2572,16 @@ filt_mqwrite(struct knote *kn, long hint)
|
|||
}
|
||||
|
||||
static struct fileops mqueueops = {
|
||||
.fo_read = mqf_read,
|
||||
.fo_write = mqf_write,
|
||||
.fo_truncate = mqf_truncate,
|
||||
.fo_ioctl = mqf_ioctl,
|
||||
.fo_read = invfo_rdwr,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = invfo_ioctl,
|
||||
.fo_poll = mqf_poll,
|
||||
.fo_kqfilter = mqf_kqfilter,
|
||||
.fo_stat = mqf_stat,
|
||||
.fo_close = mqf_close,
|
||||
.fo_chmod = mqf_chmod,
|
||||
.fo_chown = mqf_chown,
|
||||
.fo_close = mqf_close,
|
||||
.fo_sendfile = invfo_sendfile,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -126,12 +126,6 @@ static int ksem_module_init(void);
|
|||
static int ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred);
|
||||
static int sem_modload(struct module *module, int cmd, void *arg);
|
||||
|
||||
static fo_rdwr_t ksem_read;
|
||||
static fo_rdwr_t ksem_write;
|
||||
static fo_truncate_t ksem_truncate;
|
||||
static fo_ioctl_t ksem_ioctl;
|
||||
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;
|
||||
|
|
@ -139,12 +133,12 @@ static fo_chown_t ksem_chown;
|
|||
|
||||
/* File descriptor operations. */
|
||||
static struct fileops ksem_ops = {
|
||||
.fo_read = ksem_read,
|
||||
.fo_write = ksem_write,
|
||||
.fo_truncate = ksem_truncate,
|
||||
.fo_ioctl = ksem_ioctl,
|
||||
.fo_poll = ksem_poll,
|
||||
.fo_kqfilter = ksem_kqfilter,
|
||||
.fo_read = invfo_rdwr,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = invfo_ioctl,
|
||||
.fo_poll = invfo_poll,
|
||||
.fo_kqfilter = invfo_kqfilter,
|
||||
.fo_stat = ksem_stat,
|
||||
.fo_close = ksem_closef,
|
||||
.fo_chmod = ksem_chmod,
|
||||
|
|
@ -155,53 +149,6 @@ static struct fileops ksem_ops = {
|
|||
|
||||
FEATURE(posix_sem, "POSIX semaphores");
|
||||
|
||||
static int
|
||||
ksem_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
||||
int flags, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_ioctl(struct file *fp, u_long com, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
ksem_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
|
|||
|
|
@ -120,9 +120,6 @@ static int shm_dotruncate(struct shmfd *shmfd, off_t length);
|
|||
static fo_rdwr_t shm_read;
|
||||
static fo_rdwr_t shm_write;
|
||||
static fo_truncate_t shm_truncate;
|
||||
static fo_ioctl_t shm_ioctl;
|
||||
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;
|
||||
|
|
@ -134,9 +131,9 @@ static struct fileops shm_ops = {
|
|||
.fo_read = shm_read,
|
||||
.fo_write = shm_write,
|
||||
.fo_truncate = shm_truncate,
|
||||
.fo_ioctl = shm_ioctl,
|
||||
.fo_poll = shm_poll,
|
||||
.fo_kqfilter = shm_kqfilter,
|
||||
.fo_ioctl = invfo_ioctl,
|
||||
.fo_poll = invfo_poll,
|
||||
.fo_kqfilter = invfo_kqfilter,
|
||||
.fo_stat = shm_stat,
|
||||
.fo_close = shm_close,
|
||||
.fo_chmod = shm_chmod,
|
||||
|
|
@ -354,29 +351,6 @@ shm_truncate(struct file *fp, off_t length, struct ucred *active_cred,
|
|||
return (shm_dotruncate(shmfd, length));
|
||||
}
|
||||
|
||||
static int
|
||||
shm_ioctl(struct file *fp, u_long com, void *data,
|
||||
struct ucred *active_cred, struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_poll(struct file *fp, int events, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static int
|
||||
shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
|
|
|
|||
|
|
@ -568,11 +568,23 @@ linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred,
|
|||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
linux_file_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
struct fileops linuxfileops = {
|
||||
.fo_read = linux_file_read,
|
||||
.fo_poll = linux_file_poll,
|
||||
.fo_close = linux_file_close,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = linux_file_ioctl,
|
||||
.fo_poll = linux_file_poll,
|
||||
.fo_kqfilter = invfo_kqfilter,
|
||||
.fo_stat = linux_file_stat,
|
||||
.fo_close = linux_file_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
.fo_chown = invfo_chown,
|
||||
.fo_sendfile = invfo_sendfile,
|
||||
|
|
|
|||
|
|
@ -281,25 +281,19 @@ struct fcrypt {
|
|||
int sesn;
|
||||
};
|
||||
|
||||
static int cryptof_rw(struct file *fp, struct uio *uio,
|
||||
struct ucred *cred, int flags, struct thread *);
|
||||
static int cryptof_truncate(struct file *, off_t, struct ucred *,
|
||||
struct thread *);
|
||||
static int cryptof_ioctl(struct file *, u_long, void *,
|
||||
struct ucred *, struct thread *);
|
||||
static int cryptof_poll(struct file *, int, struct ucred *, struct thread *);
|
||||
static int cryptof_kqfilter(struct file *, struct knote *);
|
||||
static int cryptof_stat(struct file *, struct stat *,
|
||||
struct ucred *, struct thread *);
|
||||
static int cryptof_close(struct file *, struct thread *);
|
||||
|
||||
static struct fileops cryptofops = {
|
||||
.fo_read = cryptof_rw,
|
||||
.fo_write = cryptof_rw,
|
||||
.fo_truncate = cryptof_truncate,
|
||||
.fo_read = invfo_rdwr,
|
||||
.fo_write = invfo_rdwr,
|
||||
.fo_truncate = invfo_truncate,
|
||||
.fo_ioctl = cryptof_ioctl,
|
||||
.fo_poll = cryptof_poll,
|
||||
.fo_kqfilter = cryptof_kqfilter,
|
||||
.fo_poll = invfo_poll,
|
||||
.fo_kqfilter = invfo_kqfilter,
|
||||
.fo_stat = cryptof_stat,
|
||||
.fo_close = cryptof_close,
|
||||
.fo_chmod = invfo_chmod,
|
||||
|
|
@ -320,29 +314,6 @@ static int cryptodev_op(struct csession *, struct crypt_op *,
|
|||
static int cryptodev_key(struct crypt_kop *);
|
||||
static int cryptodev_find(struct crypt_find_op *);
|
||||
|
||||
static int
|
||||
cryptof_rw(
|
||||
struct file *fp,
|
||||
struct uio *uio,
|
||||
struct ucred *active_cred,
|
||||
int flags,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
static int
|
||||
cryptof_truncate(
|
||||
struct file *fp,
|
||||
off_t length,
|
||||
struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a crypto identifier to see if it requested
|
||||
* a software device/driver. This can be done either
|
||||
|
|
@ -959,26 +930,6 @@ cryptodev_find(struct crypt_find_op *find)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cryptof_poll(
|
||||
struct file *fp,
|
||||
int events,
|
||||
struct ucred *active_cred,
|
||||
struct thread *td)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cryptof_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cryptof_stat(
|
||||
|
|
|
|||
|
|
@ -231,10 +231,14 @@ int fget_write(struct thread *td, int fd, cap_rights_t *rightsp,
|
|||
struct file **fpp);
|
||||
int _fdrop(struct file *fp, struct thread *td);
|
||||
|
||||
fo_rdwr_t invfo_rdwr;
|
||||
fo_truncate_t invfo_truncate;
|
||||
fo_ioctl_t invfo_ioctl;
|
||||
fo_poll_t invfo_poll;
|
||||
fo_kqfilter_t invfo_kqfilter;
|
||||
fo_chmod_t invfo_chmod;
|
||||
fo_chown_t invfo_chown;
|
||||
fo_sendfile_t invfo_sendfile;
|
||||
fo_truncate_t invfo_truncate;
|
||||
|
||||
fo_sendfile_t vn_sendfile;
|
||||
fo_seek_t vn_seek;
|
||||
|
|
|
|||
Loading…
Reference in a new issue