Skip to content

Commit c90fad3

Browse files
Jacopo MondiHans Verkuil
authored andcommitted
media: ivtv: Fix invalid access to file *
Since commit 9ba9d11 ("media: ivtv: Access v4l2_fh from file") all ioctl handlers have been ported to operate on the file * first function argument. The ivtv DVB layer calls ivtv_init_on_first_open() when the driver needs to start streaming. This function calls the s_input() and s_frequency() ioctl handlers directly, but being called from the driver context, it doesn't have a valid file * to pass them. This causes the ioctl handlers to deference an invalid pointer. Fix this by moving the implementation of those ioctls to two helper functions. The ivtv_do_s_input() helper accepts a struct ivtv * as first argument, which is easily accessible in ivtv_init_on_first_open() as well as from the file * argument of the ioctl handler. The ivtv_s_frequency() takes an ivtv_stream * instead. The stream * can safely be accessed in ivtv_init_on_first_open() where it is hard-coded to the IVTV_ENC_STREAM_TYPE_MPG stream type, as well as from the ioctl handler as a valid stream type is associated to each open file handle depending on which video device node has been opened in the ivtv_open() file operation. The bug has been reported by Smatch. Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/all/aKL4OMWsESUdX8KQ@stanley.mountain/ Fixes: 9ba9d11 ("media: ivtv: Access v4l2_fh from file") Cc: stable@vger.kernel.org Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Hans Verkuil <hverkuil+cisco@kernel.org> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
1 parent 512f0b7 commit c90fad3

3 files changed

Lines changed: 25 additions & 14 deletions

File tree

drivers/media/pci/ivtv/ivtv-driver.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,15 +1247,12 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
12471247

12481248
int ivtv_init_on_first_open(struct ivtv *itv)
12491249
{
1250-
struct v4l2_frequency vf;
12511250
/* Needed to call ioctls later */
1252-
struct ivtv_open_id fh;
1251+
struct ivtv_stream *s = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
1252+
struct v4l2_frequency vf;
12531253
int fw_retry_count = 3;
12541254
int video_input;
12551255

1256-
fh.itv = itv;
1257-
fh.type = IVTV_ENC_STREAM_TYPE_MPG;
1258-
12591256
if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
12601257
return -ENXIO;
12611258

@@ -1297,13 +1294,13 @@ int ivtv_init_on_first_open(struct ivtv *itv)
12971294

12981295
video_input = itv->active_input;
12991296
itv->active_input++; /* Force update of input */
1300-
ivtv_s_input(NULL, &fh, video_input);
1297+
ivtv_do_s_input(itv, video_input);
13011298

13021299
/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
13031300
in one place. */
13041301
itv->std++; /* Force full standard initialization */
13051302
itv->std_out = itv->std;
1306-
ivtv_s_frequency(NULL, &fh, &vf);
1303+
ivtv_do_s_frequency(s, &vf);
13071304

13081305
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
13091306
/* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes

drivers/media/pci/ivtv/ivtv-ioctl.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,8 @@ static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
974974
return 0;
975975
}
976976

977-
int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
977+
int ivtv_do_s_input(struct ivtv *itv, unsigned int inp)
978978
{
979-
struct ivtv *itv = file2id(file)->itv;
980979
v4l2_std_id std;
981980
int i;
982981

@@ -1017,6 +1016,11 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
10171016
return 0;
10181017
}
10191018

1019+
static int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
1020+
{
1021+
return ivtv_do_s_input(file2id(file)->itv, inp);
1022+
}
1023+
10201024
static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
10211025
{
10221026
struct ivtv *itv = file2id(file)->itv;
@@ -1065,10 +1069,9 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
10651069
return 0;
10661070
}
10671071

1068-
int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf)
1072+
int ivtv_do_s_frequency(struct ivtv_stream *s, const struct v4l2_frequency *vf)
10691073
{
1070-
struct ivtv *itv = file2id(file)->itv;
1071-
struct ivtv_stream *s = &itv->streams[file2id(file)->type];
1074+
struct ivtv *itv = s->itv;
10721075

10731076
if (s->vdev.vfl_dir)
10741077
return -ENOTTY;
@@ -1082,6 +1085,15 @@ int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *v
10821085
return 0;
10831086
}
10841087

1088+
static int ivtv_s_frequency(struct file *file, void *fh,
1089+
const struct v4l2_frequency *vf)
1090+
{
1091+
struct ivtv_open_id *id = file2id(file);
1092+
struct ivtv *itv = id->itv;
1093+
1094+
return ivtv_do_s_frequency(&itv->streams[id->type], vf);
1095+
}
1096+
10851097
static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
10861098
{
10871099
struct ivtv *itv = file2id(file)->itv;

drivers/media/pci/ivtv/ivtv-ioctl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef IVTV_IOCTL_H
1010
#define IVTV_IOCTL_H
1111

12+
struct ivtv;
13+
1214
u16 ivtv_service2vbi(int type);
1315
void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
1416
u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
@@ -17,7 +19,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed);
1719
void ivtv_set_funcs(struct video_device *vdev);
1820
void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id std);
1921
void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id std);
20-
int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *vf);
21-
int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
22+
int ivtv_do_s_frequency(struct ivtv_stream *s, const struct v4l2_frequency *vf);
23+
int ivtv_do_s_input(struct ivtv *itv, unsigned int inp);
2224

2325
#endif

0 commit comments

Comments
 (0)