From: Dan Carpenter <dan.carpenter@linaro.org>
To: Ricardo Ribalda <ribalda@chromium.org>
Cc: "Ezequiel García" <elezegarcia@gmail.com>,
"Ghanshyam Agrawal" <ghanshyam1898@gmail.com>,
"Ezequiel Garcia" <ezequiel@vanguardiasur.com.ar>,
"Mauro Carvalho Chehab" <mchehab@kernel.org>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] media: stk1160: fix bounds checking in stk1160_copy_video()
Date: Mon, 22 Apr 2024 14:22:54 +0300 [thread overview]
Message-ID: <f2e9cdcd-46e7-41ab-9d5f-c1237a0a6222@moroto.mountain> (raw)
In-Reply-To: <CANiDSCtjEPqEstuo92QeVK_rWkW9icsjKWakPyN19ETM+MJuuQ@mail.gmail.com>
On Mon, Apr 22, 2024 at 05:52:36PM +0800, Ricardo Ribalda wrote:
> Hi Dan
>
> On Mon, 22 Apr 2024 at 17:32, Dan Carpenter <dan.carpenter@linaro.org> wrote:
> >
> > The subtract in this condition is reversed. The ->length is the length
> > of the buffer. The ->bytesused is how many bytes we have copied thus
> > far. When the condition is reversed that means the result of the
> > subtraction is always negative but since it's unsigned then the result
> > is a very high positive value. That means the overflow check is never
> > true.
> >
> > Additionally, the ->bytesused doesn't actually work for this purpose
> > because we're not writing to "buf->mem + buf->bytesused". Instead, the
> > math to calculate the destination where we are writing is a bit
> > involved. You calculate the number of full lines already written,
> > multiply by two, skip a line if necessary so that we start on an odd
> > numbered line, and add the offset into the line.
> >
> > To fix this buffer overflow, just take the actual destination where we
> > are writing, if the offset is already out of bounds print an error and
> > return. Otherwise, write up to buf->length bytes.
> >
> > Fixes: 9cb2173e6ea8 ("[media] media: Add stk1160 new driver (easycap replacement)")
> > Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
> > ---
> > v2: My first patch just reversed the if statement but that wasn't the
> > correct fix.
> >
> > Ghanshyam Agrawal sent a patch last year to ratelimit the output from
> > this function because it was spamming dmesg. This patch should
> > hopefully fix the issue. Let me know if there are still problems.
> >
> > drivers/media/usb/stk1160/stk1160-video.c | 20 +++++++++++++++-----
> > 1 file changed, 15 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
> > index 366f0e4a5dc0..e79c45db60ab 100644
> > --- a/drivers/media/usb/stk1160/stk1160-video.c
> > +++ b/drivers/media/usb/stk1160/stk1160-video.c
> > @@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev)
> > static inline
> > void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
> > {
> > - int linesdone, lineoff, lencopy;
> > + int linesdone, lineoff, lencopy, offset;
> > int bytesperline = dev->width * 2;
> > struct stk1160_buffer *buf = dev->isoc_ctl.buf;
> > u8 *dst = buf->mem;
> > @@ -139,8 +139,13 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
> > * Check if we have enough space left in the buffer.
> > * In that case, we force loop exit after copy.
> > */
> > - if (lencopy > buf->bytesused - buf->length) {
> > - lencopy = buf->bytesused - buf->length;
> > + offset = dst - (u8 *)buf->mem;
> > + if (offset > buf->length) {
> Maybe you want offset >= buf->length.
>
The difference between > and >= is whether or not we print an error
message. In the original code, we didn't print an error message for
this and I feel like that's the correct behavior.
> And remember to add at the beginning of the function
>
> if (!len)
> return 0;
>
That's checked in the caller so it's fine.
260 /* Empty packet */
261 if (len <= 4)
262 continue;
Generally we don't add duplicate checks.
> And I would have done:
> len -= 4;
> src += 4;
>
> In the caller function
>
I don't really think it makes sense to move that into the caller and
anyway, doing cleanups like this is outside the scope of this patch.
Really, there is a lot that could be cleaned up here. People knew there
was a bug here but they didn't figure out what was causing it. We could
delete that code. Looking at it now, I think that code would actually
be enough to prevent a buffer overflow, although the correct behavior is
to write up to the end of the buffer instead of returning early.
Probably?
To be honest, I'm still concerned there is a read overflow in
stk1160_buffer_done(). I'd prefer to do:
len = buf->bytesused;
if (len > buf->length) {
dev_warn_ratelimited(dev->dev, "buf->bytesused invalid %u\n", len);
len = buf->length;
}
vb2_set_plane_payload(&buf->vb.vb2_buf, 0, len);
regards,
dan carpenter
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index ed261f0241da..f7977b07c066 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -112,16 +112,6 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
u8 *dst = buf->mem;
int remain;
- /*
- * TODO: These stk1160_dbg are very spammy!
- * We should check why we are getting them.
- *
- * UPDATE: One of the reasons (the only one?) for getting these
- * is incorrect standard (mismatch between expected and configured).
- * So perhaps, we could add a counter for errors. When the counter
- * reaches some value, we simply stop streaming.
- */
-
len -= 4;
src += 4;
@@ -160,18 +150,6 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
if (lencopy == 0 || remain == 0)
return;
- /* Let the bug hunt begin! sanity checks! */
- if (lencopy < 0) {
- printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n");
- return;
- }
-
- if ((unsigned long)dst + lencopy >
- (unsigned long)buf->mem + buf->length) {
- printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
- return;
- }
-
memcpy(dst, src, lencopy);
buf->bytesused += lencopy;
@@ -208,17 +186,6 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
if (lencopy == 0 || remain == 0)
return;
- if (lencopy < 0) {
- printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n");
- return;
- }
-
- if ((unsigned long)dst + lencopy >
- (unsigned long)buf->mem + buf->length) {
- printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
- return;
- }
-
memcpy(dst, src, lencopy);
remain -= lencopy;
next prev parent reply other threads:[~2024-04-22 11:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-22 9:32 Dan Carpenter
2024-04-22 9:52 ` Ricardo Ribalda
2024-04-22 11:22 ` Dan Carpenter [this message]
2024-04-22 14:39 ` Ricardo Ribalda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f2e9cdcd-46e7-41ab-9d5f-c1237a0a6222@moroto.mountain \
--to=dan.carpenter@linaro.org \
--cc=elezegarcia@gmail.com \
--cc=ezequiel@vanguardiasur.com.ar \
--cc=ghanshyam1898@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=ribalda@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®