Re: [PATCH v3] media: v4l2-ioctl: fix function types for IOCTL_INFO_STD
On 05/08/2018 07:35 PM, Sami Tolvanen wrote: > This change fixes indirect call mismatches with Control-Flow Integrity > checking, which are caused by calling standard ioctls using a function > pointer that doesn't match the type of the actual function. I really like the patch, but we've drifted away quite a bit from the original patch, and I think the commit message needs to be updated a bit. Just mention that IOCTL_INFO_STD has been removed, we now always call a function and that DEFINE_V4L_STUB_FUNC is used to create stub functions where needed. Basically the current message describes the problem (good), but it doesn't describe the chosen solution (bad). Sorry for asking for a v4, but this is core v4l2 code, so we're more careful about this. Regards, Hans > > Signed-off-by: Sami Tolvanen> --- > drivers/media/v4l2-core/v4l2-ioctl.c | 245 ++- > 1 file changed, 130 insertions(+), 115 deletions(-) > > diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c > b/drivers/media/v4l2-core/v4l2-ioctl.c > index de5d96dbe69e0..a40dbec271f1d 100644 > --- a/drivers/media/v4l2-core/v4l2-ioctl.c > +++ b/drivers/media/v4l2-core/v4l2-ioctl.c > @@ -2489,11 +2489,8 @@ struct v4l2_ioctl_info { > unsigned int ioctl; > u32 flags; > const char * const name; > - union { > - u32 offset; > - int (*func)(const struct v4l2_ioctl_ops *ops, > - struct file *file, void *fh, void *p); > - } u; > + int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, > + void *fh, void *p); > void (*debug)(const void *arg, bool write_only); > }; > > @@ -2501,121 +2498,145 @@ struct v4l2_ioctl_info { > #define INFO_FL_PRIO (1 << 0) > /* This control can be valid if the filehandle passes a control handler. */ > #define INFO_FL_CTRL (1 << 1) > -/* This is a standard ioctl, no need for special code */ > -#define INFO_FL_STD (1 << 2) > -/* This is ioctl has its own function */ > -#define INFO_FL_FUNC (1 << 3) > /* Queuing ioctl */ > -#define INFO_FL_QUEUE(1 << 4) > +#define INFO_FL_QUEUE(1 << 2) > /* Always copy back result, even on error */ > -#define INFO_FL_ALWAYS_COPY (1 << 5) > +#define INFO_FL_ALWAYS_COPY (1 << 3) > /* Zero struct from after the field to the end */ > #define INFO_FL_CLEAR(v4l2_struct, field)\ > ((offsetof(struct v4l2_struct, field) + \ > sizeof(((struct v4l2_struct *)0)->field)) << 16) > #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) > > -#define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) > \ > - [_IOC_NR(_ioctl)] = { \ > - .ioctl = _ioctl,\ > - .flags = _flags | INFO_FL_STD, \ > - .name = #_ioctl,\ > - .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ > - .debug = _debug,\ > +#define DEFINE_V4L_STUB_FUNC(_vidioc)\ > + static int v4l_stub_ ## _vidioc(\ > + const struct v4l2_ioctl_ops *ops, \ > + struct file *file, void *fh, void *p) \ > + { \ > + return ops->vidioc_ ## _vidioc(file, fh, p);\ > } > > -#define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) > \ > - [_IOC_NR(_ioctl)] = { \ > - .ioctl = _ioctl,\ > - .flags = _flags | INFO_FL_FUNC, \ > - .name = #_ioctl,\ > - .u.func = _func,\ > - .debug = _debug,\ > +#define IOCTL_INFO(_ioctl, _func, _debug, _flags)\ > + [_IOC_NR(_ioctl)] = { \ > + .ioctl = _ioctl,\ > + .flags = _flags,\ > + .name = #_ioctl,\ > + .func = _func, \ > + .debug = _debug,\ > } > > +DEFINE_V4L_STUB_FUNC(g_fbuf) > +DEFINE_V4L_STUB_FUNC(s_fbuf) > +DEFINE_V4L_STUB_FUNC(expbuf) > +DEFINE_V4L_STUB_FUNC(g_std) > +DEFINE_V4L_STUB_FUNC(g_audio) > +DEFINE_V4L_STUB_FUNC(s_audio) > +DEFINE_V4L_STUB_FUNC(g_input) > +DEFINE_V4L_STUB_FUNC(g_edid) > +DEFINE_V4L_STUB_FUNC(s_edid) > +DEFINE_V4L_STUB_FUNC(g_output) > +DEFINE_V4L_STUB_FUNC(g_audout) >
Re: [PATCH v3] media: v4l2-ioctl: fix function types for IOCTL_INFO_STD
On 05/08/2018 07:35 PM, Sami Tolvanen wrote: > This change fixes indirect call mismatches with Control-Flow Integrity > checking, which are caused by calling standard ioctls using a function > pointer that doesn't match the type of the actual function. I really like the patch, but we've drifted away quite a bit from the original patch, and I think the commit message needs to be updated a bit. Just mention that IOCTL_INFO_STD has been removed, we now always call a function and that DEFINE_V4L_STUB_FUNC is used to create stub functions where needed. Basically the current message describes the problem (good), but it doesn't describe the chosen solution (bad). Sorry for asking for a v4, but this is core v4l2 code, so we're more careful about this. Regards, Hans > > Signed-off-by: Sami Tolvanen > --- > drivers/media/v4l2-core/v4l2-ioctl.c | 245 ++- > 1 file changed, 130 insertions(+), 115 deletions(-) > > diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c > b/drivers/media/v4l2-core/v4l2-ioctl.c > index de5d96dbe69e0..a40dbec271f1d 100644 > --- a/drivers/media/v4l2-core/v4l2-ioctl.c > +++ b/drivers/media/v4l2-core/v4l2-ioctl.c > @@ -2489,11 +2489,8 @@ struct v4l2_ioctl_info { > unsigned int ioctl; > u32 flags; > const char * const name; > - union { > - u32 offset; > - int (*func)(const struct v4l2_ioctl_ops *ops, > - struct file *file, void *fh, void *p); > - } u; > + int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, > + void *fh, void *p); > void (*debug)(const void *arg, bool write_only); > }; > > @@ -2501,121 +2498,145 @@ struct v4l2_ioctl_info { > #define INFO_FL_PRIO (1 << 0) > /* This control can be valid if the filehandle passes a control handler. */ > #define INFO_FL_CTRL (1 << 1) > -/* This is a standard ioctl, no need for special code */ > -#define INFO_FL_STD (1 << 2) > -/* This is ioctl has its own function */ > -#define INFO_FL_FUNC (1 << 3) > /* Queuing ioctl */ > -#define INFO_FL_QUEUE(1 << 4) > +#define INFO_FL_QUEUE(1 << 2) > /* Always copy back result, even on error */ > -#define INFO_FL_ALWAYS_COPY (1 << 5) > +#define INFO_FL_ALWAYS_COPY (1 << 3) > /* Zero struct from after the field to the end */ > #define INFO_FL_CLEAR(v4l2_struct, field)\ > ((offsetof(struct v4l2_struct, field) + \ > sizeof(((struct v4l2_struct *)0)->field)) << 16) > #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) > > -#define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) > \ > - [_IOC_NR(_ioctl)] = { \ > - .ioctl = _ioctl,\ > - .flags = _flags | INFO_FL_STD, \ > - .name = #_ioctl,\ > - .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ > - .debug = _debug,\ > +#define DEFINE_V4L_STUB_FUNC(_vidioc)\ > + static int v4l_stub_ ## _vidioc(\ > + const struct v4l2_ioctl_ops *ops, \ > + struct file *file, void *fh, void *p) \ > + { \ > + return ops->vidioc_ ## _vidioc(file, fh, p);\ > } > > -#define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) > \ > - [_IOC_NR(_ioctl)] = { \ > - .ioctl = _ioctl,\ > - .flags = _flags | INFO_FL_FUNC, \ > - .name = #_ioctl,\ > - .u.func = _func,\ > - .debug = _debug,\ > +#define IOCTL_INFO(_ioctl, _func, _debug, _flags)\ > + [_IOC_NR(_ioctl)] = { \ > + .ioctl = _ioctl,\ > + .flags = _flags,\ > + .name = #_ioctl,\ > + .func = _func, \ > + .debug = _debug,\ > } > > +DEFINE_V4L_STUB_FUNC(g_fbuf) > +DEFINE_V4L_STUB_FUNC(s_fbuf) > +DEFINE_V4L_STUB_FUNC(expbuf) > +DEFINE_V4L_STUB_FUNC(g_std) > +DEFINE_V4L_STUB_FUNC(g_audio) > +DEFINE_V4L_STUB_FUNC(s_audio) > +DEFINE_V4L_STUB_FUNC(g_input) > +DEFINE_V4L_STUB_FUNC(g_edid) > +DEFINE_V4L_STUB_FUNC(s_edid) > +DEFINE_V4L_STUB_FUNC(g_output) > +DEFINE_V4L_STUB_FUNC(g_audout) > +DEFINE_V4L_STUB_FUNC(s_audout) >
[PATCH v3] media: v4l2-ioctl: fix function types for IOCTL_INFO_STD
This change fixes indirect call mismatches with Control-Flow Integrity checking, which are caused by calling standard ioctls using a function pointer that doesn't match the type of the actual function. Signed-off-by: Sami Tolvanen--- drivers/media/v4l2-core/v4l2-ioctl.c | 245 ++- 1 file changed, 130 insertions(+), 115 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index de5d96dbe69e0..a40dbec271f1d 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2489,11 +2489,8 @@ struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; const char * const name; - union { - u32 offset; - int (*func)(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *p); - } u; + int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, + void *fh, void *p); void (*debug)(const void *arg, bool write_only); }; @@ -2501,121 +2498,145 @@ struct v4l2_ioctl_info { #define INFO_FL_PRIO (1 << 0) /* This control can be valid if the filehandle passes a control handler. */ #define INFO_FL_CTRL (1 << 1) -/* This is a standard ioctl, no need for special code */ -#define INFO_FL_STD(1 << 2) -/* This is ioctl has its own function */ -#define INFO_FL_FUNC (1 << 3) /* Queuing ioctl */ -#define INFO_FL_QUEUE (1 << 4) +#define INFO_FL_QUEUE (1 << 2) /* Always copy back result, even on error */ -#define INFO_FL_ALWAYS_COPY(1 << 5) +#define INFO_FL_ALWAYS_COPY(1 << 3) /* Zero struct from after the field to the end */ #define INFO_FL_CLEAR(v4l2_struct, field) \ ((offsetof(struct v4l2_struct, field) + \ sizeof(((struct v4l2_struct *)0)->field)) << 16) #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) -#define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ - [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl,\ - .flags = _flags | INFO_FL_STD, \ - .name = #_ioctl,\ - .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ - .debug = _debug,\ +#define DEFINE_V4L_STUB_FUNC(_vidioc) \ + static int v4l_stub_ ## _vidioc(\ + const struct v4l2_ioctl_ops *ops, \ + struct file *file, void *fh, void *p) \ + { \ + return ops->vidioc_ ## _vidioc(file, fh, p);\ } -#define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ - [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl,\ - .flags = _flags | INFO_FL_FUNC, \ - .name = #_ioctl,\ - .u.func = _func,\ - .debug = _debug,\ +#define IOCTL_INFO(_ioctl, _func, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl,\ + .flags = _flags,\ + .name = #_ioctl,\ + .func = _func, \ + .debug = _debug,\ } +DEFINE_V4L_STUB_FUNC(g_fbuf) +DEFINE_V4L_STUB_FUNC(s_fbuf) +DEFINE_V4L_STUB_FUNC(expbuf) +DEFINE_V4L_STUB_FUNC(g_std) +DEFINE_V4L_STUB_FUNC(g_audio) +DEFINE_V4L_STUB_FUNC(s_audio) +DEFINE_V4L_STUB_FUNC(g_input) +DEFINE_V4L_STUB_FUNC(g_edid) +DEFINE_V4L_STUB_FUNC(s_edid) +DEFINE_V4L_STUB_FUNC(g_output) +DEFINE_V4L_STUB_FUNC(g_audout) +DEFINE_V4L_STUB_FUNC(s_audout) +DEFINE_V4L_STUB_FUNC(g_jpegcomp) +DEFINE_V4L_STUB_FUNC(s_jpegcomp) +DEFINE_V4L_STUB_FUNC(enumaudio) +DEFINE_V4L_STUB_FUNC(enumaudout) +DEFINE_V4L_STUB_FUNC(enum_framesizes) +DEFINE_V4L_STUB_FUNC(enum_frameintervals) +DEFINE_V4L_STUB_FUNC(g_enc_index) +DEFINE_V4L_STUB_FUNC(encoder_cmd) +DEFINE_V4L_STUB_FUNC(try_encoder_cmd) +DEFINE_V4L_STUB_FUNC(decoder_cmd) +DEFINE_V4L_STUB_FUNC(try_decoder_cmd) +DEFINE_V4L_STUB_FUNC(s_dv_timings) +DEFINE_V4L_STUB_FUNC(g_dv_timings) +DEFINE_V4L_STUB_FUNC(enum_dv_timings) +DEFINE_V4L_STUB_FUNC(query_dv_timings) +DEFINE_V4L_STUB_FUNC(dv_timings_cap) + static struct v4l2_ioctl_info v4l2_ioctls[] = { - IOCTL_INFO_FNC(VIDIOC_QUERYCAP,
[PATCH v3] media: v4l2-ioctl: fix function types for IOCTL_INFO_STD
This change fixes indirect call mismatches with Control-Flow Integrity checking, which are caused by calling standard ioctls using a function pointer that doesn't match the type of the actual function. Signed-off-by: Sami Tolvanen --- drivers/media/v4l2-core/v4l2-ioctl.c | 245 ++- 1 file changed, 130 insertions(+), 115 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index de5d96dbe69e0..a40dbec271f1d 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2489,11 +2489,8 @@ struct v4l2_ioctl_info { unsigned int ioctl; u32 flags; const char * const name; - union { - u32 offset; - int (*func)(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *p); - } u; + int (*func)(const struct v4l2_ioctl_ops *ops, struct file *file, + void *fh, void *p); void (*debug)(const void *arg, bool write_only); }; @@ -2501,121 +2498,145 @@ struct v4l2_ioctl_info { #define INFO_FL_PRIO (1 << 0) /* This control can be valid if the filehandle passes a control handler. */ #define INFO_FL_CTRL (1 << 1) -/* This is a standard ioctl, no need for special code */ -#define INFO_FL_STD(1 << 2) -/* This is ioctl has its own function */ -#define INFO_FL_FUNC (1 << 3) /* Queuing ioctl */ -#define INFO_FL_QUEUE (1 << 4) +#define INFO_FL_QUEUE (1 << 2) /* Always copy back result, even on error */ -#define INFO_FL_ALWAYS_COPY(1 << 5) +#define INFO_FL_ALWAYS_COPY(1 << 3) /* Zero struct from after the field to the end */ #define INFO_FL_CLEAR(v4l2_struct, field) \ ((offsetof(struct v4l2_struct, field) + \ sizeof(((struct v4l2_struct *)0)->field)) << 16) #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) -#define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ - [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl,\ - .flags = _flags | INFO_FL_STD, \ - .name = #_ioctl,\ - .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ - .debug = _debug,\ +#define DEFINE_V4L_STUB_FUNC(_vidioc) \ + static int v4l_stub_ ## _vidioc(\ + const struct v4l2_ioctl_ops *ops, \ + struct file *file, void *fh, void *p) \ + { \ + return ops->vidioc_ ## _vidioc(file, fh, p);\ } -#define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ - [_IOC_NR(_ioctl)] = { \ - .ioctl = _ioctl,\ - .flags = _flags | INFO_FL_FUNC, \ - .name = #_ioctl,\ - .u.func = _func,\ - .debug = _debug,\ +#define IOCTL_INFO(_ioctl, _func, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl,\ + .flags = _flags,\ + .name = #_ioctl,\ + .func = _func, \ + .debug = _debug,\ } +DEFINE_V4L_STUB_FUNC(g_fbuf) +DEFINE_V4L_STUB_FUNC(s_fbuf) +DEFINE_V4L_STUB_FUNC(expbuf) +DEFINE_V4L_STUB_FUNC(g_std) +DEFINE_V4L_STUB_FUNC(g_audio) +DEFINE_V4L_STUB_FUNC(s_audio) +DEFINE_V4L_STUB_FUNC(g_input) +DEFINE_V4L_STUB_FUNC(g_edid) +DEFINE_V4L_STUB_FUNC(s_edid) +DEFINE_V4L_STUB_FUNC(g_output) +DEFINE_V4L_STUB_FUNC(g_audout) +DEFINE_V4L_STUB_FUNC(s_audout) +DEFINE_V4L_STUB_FUNC(g_jpegcomp) +DEFINE_V4L_STUB_FUNC(s_jpegcomp) +DEFINE_V4L_STUB_FUNC(enumaudio) +DEFINE_V4L_STUB_FUNC(enumaudout) +DEFINE_V4L_STUB_FUNC(enum_framesizes) +DEFINE_V4L_STUB_FUNC(enum_frameintervals) +DEFINE_V4L_STUB_FUNC(g_enc_index) +DEFINE_V4L_STUB_FUNC(encoder_cmd) +DEFINE_V4L_STUB_FUNC(try_encoder_cmd) +DEFINE_V4L_STUB_FUNC(decoder_cmd) +DEFINE_V4L_STUB_FUNC(try_decoder_cmd) +DEFINE_V4L_STUB_FUNC(s_dv_timings) +DEFINE_V4L_STUB_FUNC(g_dv_timings) +DEFINE_V4L_STUB_FUNC(enum_dv_timings) +DEFINE_V4L_STUB_FUNC(query_dv_timings) +DEFINE_V4L_STUB_FUNC(dv_timings_cap) + static struct v4l2_ioctl_info v4l2_ioctls[] = { - IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap,