Message ID | 20210816072721.GA10534@kili (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2,RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() | expand |
On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > The bounds checking in avc_ca_pmt() is not strict enough. It should > be checking "read_pos + 4" because it's reading 5 bytes. If the > "es_info_length" is non-zero then it reads a 6th byte so there needs to > be an additional check for that. > > I also added checks for the "write_pos". I don't think these are > required because "read_pos" and "write_pos" are tied together so > checking one ought to be enough. But they make the code easier to > understand for me. The check on write_pos is: > > if (write_pos + 4 >= sizeof(c->operand) - 4) { > > The first "+ 4" is because we're writing 5 bytes and the last " - 4" > is to leave space for the CRC. > > The other problem is that "length" can be invalid. It comes from > "data_length" in fdtv_ca_pmt(). Added a check in fdtv_ca_pmt() to > prevent that. > > Cc: stable@vger.kernel.org > Reported-by: Luo Likang <luolikang@nsfocus.com> > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> > --- > RESEND: this patch got lost somehow. > What the heck? Someone on patchwork just marked this patch as obsolete again!!! Mauro can you figure out who's doing that and what's going on? The first time it was marked as obsolete then I asked about it twice, Greg asked about it, and Salvatore Bonaccorso asked about it. But all we get are anonymous notifications from patchwork. It's a bit frustrating. regards, dan carpenter
Hi, [linux-distros list dropped as not anymore relevant for embargo] On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > > The bounds checking in avc_ca_pmt() is not strict enough. It should > > be checking "read_pos + 4" because it's reading 5 bytes. If the > > "es_info_length" is non-zero then it reads a 6th byte so there needs to > > be an additional check for that. > > > > I also added checks for the "write_pos". I don't think these are > > required because "read_pos" and "write_pos" are tied together so > > checking one ought to be enough. But they make the code easier to > > understand for me. The check on write_pos is: > > > > if (write_pos + 4 >= sizeof(c->operand) - 4) { > > > > The first "+ 4" is because we're writing 5 bytes and the last " - 4" > > is to leave space for the CRC. > > > > The other problem is that "length" can be invalid. It comes from > > "data_length" in fdtv_ca_pmt(). Added a check in fdtv_ca_pmt() to > > prevent that. > > > > Cc: stable@vger.kernel.org > > Reported-by: Luo Likang <luolikang@nsfocus.com> > > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> > > --- > > RESEND: this patch got lost somehow. > > > > What the heck? Someone on patchwork just marked this patch as obsolete > again!!! > > Mauro can you figure out who's doing that and what's going on? The > first time it was marked as obsolete then I asked about it twice, Greg > asked about it, and Salvatore Bonaccorso asked about it. But all we > get are anonymous notifications from patchwork. It's a bit frustrating. Someone knows what is going on here, i.e. what is the problem? Regards, Salvatore
On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote: > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > > > The bounds checking in avc_ca_pmt() is not strict enough. It should > > > be checking "read_pos + 4" because it's reading 5 bytes. If the > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to > > > be an additional check for that. > > > > > > I also added checks for the "write_pos". I don't think these are > > > required because "read_pos" and "write_pos" are tied together so > > > checking one ought to be enough. They may be in sync at a fixed offset, but the buffer length of the read ("int length") is not in sync with the buffer length for the write ("sizeof(c->operand)"). So I do think the write pos limit checking is actually necessary and needed. > > > RESEND: this patch got lost somehow. > > > > What the heck? Someone on patchwork just marked this patch as obsolete > > again!!! Can we please make sure patchwork has some logging so that that kind of thing shows _who_ did this? > Someone knows what is going on here, i.e. what is the problem? Dan, can you just send that fix to me directly, with the fixed commit message (see above), and we can close this. That still leaves the "who closes things on patchwork" question, but that's something I can't do anything about. Linus
Linus Torvalds <torvalds@linuxfoundation.org> writes: > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote: >> >> On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: >> > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: >> > > The bounds checking in avc_ca_pmt() is not strict enough. It should >> > > be checking "read_pos + 4" because it's reading 5 bytes. If the >> > > "es_info_length" is non-zero then it reads a 6th byte so there needs to >> > > be an additional check for that. >> > > >> > > I also added checks for the "write_pos". I don't think these are >> > > required because "read_pos" and "write_pos" are tied together so >> > > checking one ought to be enough. > > They may be in sync at a fixed offset, but the buffer length of the > read ("int length") is not in sync with the buffer length for the > write ("sizeof(c->operand)"). > > So I do think the write pos limit checking is actually necessary and needed. > >> > > RESEND: this patch got lost somehow. >> > >> > What the heck? Someone on patchwork just marked this patch as obsolete >> > again!!! > > Can we please make sure patchwork has some logging so that that kind > of thing shows _who_ did this? It's not easily visible in the web UI, but patchwork does log that sort of info. The v2 RESEND is: https://patchwork.linuxtv.org/project/linux-media/patch/20210816072721.GA10534@kili/ In the top right is the patch id (76352), you can then get the list of events for that patch at: https://patchwork.linuxtv.org/api/events/?patch=76352 Which shows that hverkuil changed it to obsolete on 2021-09-01T10:16:43. Presumably because they picked up the non-resend version, which was marked as under-review around the same time: https://patchwork.linuxtv.org/api/events/?patch=74849 And then also visible on the above page, it was marked as accepted by mchehab on 2021-09-03T13:06:16. But I don't see the patch in linux-next, or in linux-media.git, so I'm not sure where it's been accepted to? cheers
Em Sun, 12 Sep 2021 11:26:10 -0700 Linus Torvalds <torvalds@linuxfoundation.org> escreveu: > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote: > > > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: > > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > > > > The bounds checking in avc_ca_pmt() is not strict enough. It should > > > > be checking "read_pos + 4" because it's reading 5 bytes. If the > > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to > > > > be an additional check for that. > > > > > > > > I also added checks for the "write_pos". I don't think these are > > > > required because "read_pos" and "write_pos" are tied together so > > > > checking one ought to be enough. > > They may be in sync at a fixed offset, but the buffer length of the > read ("int length") is not in sync with the buffer length for the > write ("sizeof(c->operand)"). > > So I do think the write pos limit checking is actually necessary and needed. > > > > > RESEND: this patch got lost somehow. > > > > > > What the heck? Someone on patchwork just marked this patch as obsolete > > > again!!! > > Can we please make sure patchwork has some logging so that that kind > of thing shows _who_ did this? I've been wanting a feature like that on patchwork for years. Basically, when there's more then a single person capable of accessing a patchwork instance, there's no way to log who changed the status, nor to control who can delegate a patch to someone else or not. At least for me, touching patchwork is very hard, as the the entire login logic, as well as the database model itself, is abstracted by Django. So, I can't simply change a SQL insert clause there to add something else to their logs nor to change the sent email that it is pushed when a patch status changed. I ended adding an internal log to indicate when I do some changes on my patchwork instance via script a couple of years ago. > > Someone knows what is going on here, i.e. what is the problem? > > Dan, can you just send that fix to me directly, with the fixed commit > message (see above), and we can close this. Feel free to add my: Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> > > That still leaves the "who closes things on patchwork" question, but > that's something I can't do anything about. I'll double-check my scripts in order to identify if this came from my side, and if so, fix them. Thanks, Mauro
Hi Dan, On Mon, Sep 13, 2021 at 03:23:02PM +0200, Mauro Carvalho Chehab wrote: > Em Sun, 12 Sep 2021 11:26:10 -0700 > Linus Torvalds <torvalds@linuxfoundation.org> escreveu: > > > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote: > > > > > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: > > > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > > > > > The bounds checking in avc_ca_pmt() is not strict enough. It should > > > > > be checking "read_pos + 4" because it's reading 5 bytes. If the > > > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to > > > > > be an additional check for that. > > > > > > > > > > I also added checks for the "write_pos". I don't think these are > > > > > required because "read_pos" and "write_pos" are tied together so > > > > > checking one ought to be enough. > > > > They may be in sync at a fixed offset, but the buffer length of the > > read ("int length") is not in sync with the buffer length for the > > write ("sizeof(c->operand)"). > > > > So I do think the write pos limit checking is actually necessary and needed. > > > > > > > RESEND: this patch got lost somehow. > > > > > > > > What the heck? Someone on patchwork just marked this patch as obsolete > > > > again!!! > > > > Can we please make sure patchwork has some logging so that that kind > > of thing shows _who_ did this? > > I've been wanting a feature like that on patchwork for years. Basically, > when there's more then a single person capable of accessing a patchwork > instance, there's no way to log who changed the status, nor to control who > can delegate a patch to someone else or not. > > At least for me, touching patchwork is very hard, as the the entire login > logic, as well as the database model itself, is abstracted by Django. So, > I can't simply change a SQL insert clause there to add something else to > their logs nor to change the sent email that it is pushed when a patch > status changed. > > I ended adding an internal log to indicate when I do some changes on my > patchwork instance via script a couple of years ago. > > > > Someone knows what is going on here, i.e. what is the problem? > > > > Dan, can you just send that fix to me directly, with the fixed commit > > message (see above), and we can close this. > > Feel free to add my: > > Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> I'm sorry for prodding again, I guess I'm becoming a bit annoying :-/ Dan, could you sent the patch with the above to Linus directly so it can show up in at least 5.15-rc3? I guess it's now to late for 5.15-rc2. Regards, Salvatore
Hi, On Sun, Sep 19, 2021 at 08:45:42PM +0200, Salvatore Bonaccorso wrote: > Hi Dan, > > On Mon, Sep 13, 2021 at 03:23:02PM +0200, Mauro Carvalho Chehab wrote: > > Em Sun, 12 Sep 2021 11:26:10 -0700 > > Linus Torvalds <torvalds@linuxfoundation.org> escreveu: > > > > > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote: > > > > > > > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote: > > > > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote: > > > > > > The bounds checking in avc_ca_pmt() is not strict enough. It should > > > > > > be checking "read_pos + 4" because it's reading 5 bytes. If the > > > > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to > > > > > > be an additional check for that. > > > > > > > > > > > > I also added checks for the "write_pos". I don't think these are > > > > > > required because "read_pos" and "write_pos" are tied together so > > > > > > checking one ought to be enough. > > > > > > They may be in sync at a fixed offset, but the buffer length of the > > > read ("int length") is not in sync with the buffer length for the > > > write ("sizeof(c->operand)"). > > > > > > So I do think the write pos limit checking is actually necessary and needed. > > > > > > > > > RESEND: this patch got lost somehow. > > > > > > > > > > What the heck? Someone on patchwork just marked this patch as obsolete > > > > > again!!! > > > > > > Can we please make sure patchwork has some logging so that that kind > > > of thing shows _who_ did this? > > > > I've been wanting a feature like that on patchwork for years. Basically, > > when there's more then a single person capable of accessing a patchwork > > instance, there's no way to log who changed the status, nor to control who > > can delegate a patch to someone else or not. > > > > At least for me, touching patchwork is very hard, as the the entire login > > logic, as well as the database model itself, is abstracted by Django. So, > > I can't simply change a SQL insert clause there to add something else to > > their logs nor to change the sent email that it is pushed when a patch > > status changed. > > > > I ended adding an internal log to indicate when I do some changes on my > > patchwork instance via script a couple of years ago. > > > > > > Someone knows what is going on here, i.e. what is the problem? > > > > > > Dan, can you just send that fix to me directly, with the fixed commit > > > message (see above), and we can close this. > > > > Feel free to add my: > > > > Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> > > I'm sorry for prodding again, I guess I'm becoming a bit annoying :-/ > > Dan, could you sent the patch with the above to Linus directly so it > can show up in at least 5.15-rc3? I guess it's now to late for > 5.15-rc2. It looks this is still not yet applied up to 5.15-rc5, if I'm not mistaken. Regards, Salvatore
diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c index 2bf9467b917d..71991f8638e6 100644 --- a/drivers/media/firewire/firedtv-avc.c +++ b/drivers/media/firewire/firedtv-avc.c @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) read_pos += program_info_length; write_pos += program_info_length; } - while (read_pos < length) { + while (read_pos + 4 < length) { + if (write_pos + 4 >= sizeof(c->operand) - 4) { + ret = -EINVAL; + goto out; + } c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++]; @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) c->operand[write_pos++] = es_info_length >> 8; c->operand[write_pos++] = es_info_length & 0xff; if (es_info_length > 0) { + if (read_pos >= length) { + ret = -EINVAL; + goto out; + } pmt_cmd_id = msg[read_pos++]; if (pmt_cmd_id != 1 && pmt_cmd_id != 4) dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n", pmt_cmd_id); - if (es_info_length > sizeof(c->operand) - 4 - - write_pos) { + if (es_info_length > sizeof(c->operand) - 4 - write_pos || + es_info_length > length - read_pos) { ret = -EINVAL; goto out; } diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index 9363d005e2b6..2d6992ac5dd6 100644 --- a/drivers/media/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) } else { data_length = msg->msg[3]; } + if (data_length > sizeof(msg->msg) - data_pos) + return -EINVAL; return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); }
The bounds checking in avc_ca_pmt() is not strict enough. It should be checking "read_pos + 4" because it's reading 5 bytes. If the "es_info_length" is non-zero then it reads a 6th byte so there needs to be an additional check for that. I also added checks for the "write_pos". I don't think these are required because "read_pos" and "write_pos" are tied together so checking one ought to be enough. But they make the code easier to understand for me. The check on write_pos is: if (write_pos + 4 >= sizeof(c->operand) - 4) { The first "+ 4" is because we're writing 5 bytes and the last " - 4" is to leave space for the CRC. The other problem is that "length" can be invalid. It comes from "data_length" in fdtv_ca_pmt(). Added a check in fdtv_ca_pmt() to prevent that. Cc: stable@vger.kernel.org Reported-by: Luo Likang <luolikang@nsfocus.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> --- RESEND: this patch got lost somehow. v2: Change the limit in fdtv_ca_pmt() from "sizeof(msg->msg) - 4" to "sizeof(msg->msg) - data_pos". Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems very suspicous. Reading more than 4 bytes in the loop will lead to shift wrapping. drivers/media/firewire/firedtv-avc.c | 14 +++++++++++--- drivers/media/firewire/firedtv-ci.c | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-)