mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
For interrupts from badly behaved hardware (as emulated by Syzbot), it is possible for the Comedi core functions that manage the progress of asynchronous data acquisition to be called from driver ISRs while no asynchronous command has been set up, which can cause problems such as invalid pointer dereferencing or dividing by zero. Change those functions in the Comedi core to use this pattern: if `comedi_get_is_subdevice_running(s)` returns `true` then call a safe version of the function with the same name prefixed with an underscore, followed by a call to `comedi_put_is_subdevice_running(s)`, otherwise take some default action. `comedi_get_is_subdevice_running(s)` returning `true` ensures that the details of the asynchronous command will not be destroyed before the matching call to `comedi_put_is_subdevice_running(s)`. Replace calls to those functions from elsewhere in the Comedi core with calls to the safe versions of the functions. The modified functions are: `comedi_buf_read_alloc()`, `comedi_buf_read_free()`, `comedi_buf_read_n_available()`, `comedi_buf_read_samples()`, `comedi_buf_write_alloc()`, `comedi_buf_write_free()`, `comedi_buf_write_samples()`, `comedi_bytes_per_scan()`, `comedi_event()`, `comedi_handle_events()`, `comedi_inc_scan_progress()`, `comedi_nsamples_left()`, `comedi_nscans_left()`. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Link: https://patch.msgid.link/20251023133001.8439-3-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
87 lines
2.8 KiB
C
87 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _COMEDI_INTERNAL_H
|
|
#define _COMEDI_INTERNAL_H
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/types.h>
|
|
|
|
/*
|
|
* various internal comedi stuff
|
|
*/
|
|
|
|
struct comedi_buf_map;
|
|
struct comedi_devconfig;
|
|
struct comedi_device;
|
|
struct comedi_insn;
|
|
struct comedi_rangeinfo;
|
|
struct comedi_subdevice;
|
|
struct device;
|
|
|
|
int do_rangeinfo_ioctl(struct comedi_device *dev,
|
|
struct comedi_rangeinfo *it);
|
|
struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device);
|
|
void comedi_release_hardware_device(struct device *hardware_device);
|
|
int comedi_alloc_subdevice_minor(struct comedi_subdevice *s);
|
|
void comedi_free_subdevice_minor(struct comedi_subdevice *s);
|
|
|
|
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
unsigned long new_size);
|
|
void comedi_buf_reset(struct comedi_subdevice *s);
|
|
bool comedi_buf_is_mmapped(struct comedi_subdevice *s);
|
|
void comedi_buf_map_get(struct comedi_buf_map *bm);
|
|
int comedi_buf_map_put(struct comedi_buf_map *bm);
|
|
int comedi_buf_map_access(struct comedi_buf_map *bm, unsigned long offset,
|
|
void *buf, int len, int write);
|
|
struct comedi_buf_map *
|
|
comedi_buf_map_from_subdev_get(struct comedi_subdevice *s);
|
|
unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s);
|
|
unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s);
|
|
unsigned int _comedi_buf_write_alloc(struct comedi_subdevice *s,
|
|
unsigned int nbytes);
|
|
unsigned int _comedi_buf_write_free(struct comedi_subdevice *s,
|
|
unsigned int nbytes);
|
|
unsigned int _comedi_buf_read_n_available(struct comedi_subdevice *s);
|
|
unsigned int _comedi_buf_read_alloc(struct comedi_subdevice *s,
|
|
unsigned int nbytes);
|
|
unsigned int _comedi_buf_read_free(struct comedi_subdevice *s,
|
|
unsigned int nbytes);
|
|
void _comedi_inc_scan_progress(struct comedi_subdevice *s,
|
|
unsigned int num_bytes);
|
|
void _comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
|
|
void comedi_device_cancel_all(struct comedi_device *dev);
|
|
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s);
|
|
|
|
extern unsigned int comedi_default_buf_size_kb;
|
|
extern unsigned int comedi_default_buf_maxsize_kb;
|
|
|
|
/* drivers.c */
|
|
|
|
extern struct comedi_driver *comedi_drivers;
|
|
extern struct mutex comedi_drivers_list_lock;
|
|
|
|
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
|
|
struct comedi_insn *insn, unsigned int *data);
|
|
|
|
void comedi_device_detach_locked(struct comedi_device *dev);
|
|
void comedi_device_detach(struct comedi_device *dev);
|
|
int comedi_device_attach(struct comedi_device *dev,
|
|
struct comedi_devconfig *it);
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
/* proc.c */
|
|
|
|
void comedi_proc_init(void);
|
|
void comedi_proc_cleanup(void);
|
|
#else
|
|
static inline void comedi_proc_init(void)
|
|
{
|
|
}
|
|
|
|
static inline void comedi_proc_cleanup(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#endif /* _COMEDI_INTERNAL_H */
|