[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 12/15] ipmi: Add an SMBus IPMI interface
From: |
Peter Maydell |
Subject: |
Re: [PATCH 12/15] ipmi: Add an SMBus IPMI interface |
Date: |
Fri, 29 Jul 2022 16:34:44 +0100 |
On Tue, 28 Jun 2022 at 17:21, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Thu, 19 Sept 2019 at 22:39, <minyard@acm.org> wrote:
> >
> > From: Corey Minyard <cminyard@mvista.com>
> >
> > Signed-off-by: Corey Minyard <cminyard@mvista.com>
> > ---
>
> Very old patch, but Coverity has decided it doesn't like something
> in this function that's still basically the same in the current codebase
> (CID 1487146):
Ping ?
> > +static int ipmi_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len)
> > +{
> > + SMBusIPMIDevice *sid = SMBUS_IPMI(dev);
> > + bool send = false;
> > + uint8_t cmd;
> > + int ret = 0;
> > +
> > + /* length is guaranteed to be >= 1. */
> > + cmd = *buf++;
> > + len--;
> > +
> > + /* Handle read request, which don't have any data in the write part. */
> > + switch (cmd) {
> > + case SSIF_IPMI_RESPONSE:
> > + sid->currblk = 0;
> > + ret = ipmi_load_readbuf(sid);
> > + break;
> > +
> > + case SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE:
> > + sid->currblk++;
> > + ret = ipmi_load_readbuf(sid);
> > + break;
> > +
> > + case SSIF_IPMI_MULTI_PART_RETRY:
> > + if (len >= 1) {
> > + sid->currblk = buf[0];
> > + ret = ipmi_load_readbuf(sid);
> > + } else {
> > + ret = -1;
> > + }
> > + break;
> > +
> > + default:
> > + break;
> > + }
> > +
> > + /* This should be a message write, make the length is there and
> > correct. */
> > + if (len >= 1) {
> > + if (*buf != len - 1 || *buf > MAX_SSIF_IPMI_MSG_CHUNK) {
> > + return -1; /* Bogus message */
> > + }
> > + buf++;
> > + len--;
> > + }
>
> After all of this preamble, len can be zero...
>
> > +
> > + switch (cmd) {
> > + case SSIF_IPMI_REQUEST:
> > + send = true;
> > + /* FALLTHRU */
> > + case SSIF_IPMI_MULTI_PART_REQUEST_START:
> > + if (len < 2) {
> > + return -1; /* Bogus. */
> > + }
> > + memcpy(sid->inmsg, buf, len);
> > + sid->inlen = len;
> > + break;
> > +
> > + case SSIF_IPMI_MULTI_PART_REQUEST_END:
> > + send = true;
> > + /* FALLTHRU */
> > + case SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE:
> > + if (!sid->inlen) {
> > + return -1; /* Bogus. */
> > + }
> > + if (sid->inlen + len > MAX_SSIF_IPMI_MSG_SIZE) {
> > + sid->inlen = 0; /* Discard the message. */
> > + return -1; /* Bogus. */
> > + }
>
> ...this error checking on the values of the 'middle' request
> means that after one 'middle' request we can end up with
> sid->inlen == MAX_SSIF_IPMI_MSG_SIZE (ie we filled the
> entire sid->inmsg[] array).
>
> But then if we get another 'middle' request with len == 0,
> that will pass this error checking because (sid->inlen + len == MSG_SIZE)
> and fall through into...
>
> > + if (len < 32) {
> > + /*
> > + * Special hack, a multi-part middle that is less than 32 bytes
> > + * marks the end of a message. The specification is fairly
> > + * confusing, so some systems to this, even sending a zero
> > + * length end message to mark the end.
> > + */
> > + send = true;
> > + }
> > + memcpy(sid->inmsg + sid->inlen, buf, len);
>
> ...calling memcpy() with argument 1 being a pointer that points
> one past the end of the array. Even though len will be 0 and
> we won't memcpy() anything, this is (depending on how you choose
> to intepret things the C standard doesn't come right out and state
> explicitly) undefined behaviour, because memcpy() wants to be passed
> valid pointers, even if you ask it to do no work with a zero len.
>
> This isn't going to be a visible bug in practical terms, but it would
> make Coverity happy if we either (a) rejected a request with an empty
> length or else (b) skipped the memcpy(). I don't know enough about
> IPMI to know which is better.
thanks
-- PMM
- Re: [PATCH 12/15] ipmi: Add an SMBus IPMI interface,
Peter Maydell <=