Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <000001d73588$9b95a920$d2c0fb60$@nsfocus.com>
Date: Tue, 20 Apr 2021 09:58:05 +0800
From: "Luo Likang" <luolikang@...ocus.com>
To: <oss-security@...ts.openwall.com>
Subject: Linux kernel:  a heap buffer overflow in firedtv driver

I found a buffer overflow vulnerability in function
avc_ca_pmt(drivers/media/fireware/firedtv-avc.c). 

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.

 

a)      static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)

{

       struct ca_msg *msg = arg;

       int data_pos;

       int data_length;

       int i;

 

       data_pos = 4;

       if (msg->msg[3] & 0x80) { 

              data_length = 0;

              for (i = 0; i < (msg->msg[3] & 0x7f); i++)

                     data_length = (data_length << 8) +
msg->msg[data_pos++];

       } else {

              data_length = msg->msg[3];

       }

 

       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); <== setp
in

}

In this function, the content of `arg` is still the original data passed in
by the user. If msg->msg[3] = 0x84, msg->[4] = 0xff, msg->msg[5]=0xff,
msg->msg[6]=0xff, msg->msg[7]=0xff , will enter the for loop four times, and
data_length will be equal to 0xffffffff, and then call avc_ca_pmt(fdtv,
&msg->msg[8], 0xffffffff)

 

b)      int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

{

       ..

       int program_info_length;

       int pmt_cmd_id;

       int read_pos;

       int write_pos;

       int es_info_length;

       int crc32_csum;

       int ret;

 

       ..

       program_info_length = ((msg[4] & 0x0f) << 8) + msg[5]; /////////////
[0]

       if (program_info_length > 0)

              program_info_length--; /* Remove pmt_cmd_id */

       pmt_cmd_id = msg[6];                             //////////////[1]

 

       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;

       ..

       c->operand[23] = (program_info_length & 0xff);

 

       /* CA descriptors at programme level */

       read_pos = 6;

       write_pos = 24;

       if (program_info_length > 0) {

              pmt_cmd_id = msg[read_pos++];

              if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
////////////[2]

                     dev_err(fdtv->device,

                            "invalid pmt_cmd_id %d\n", pmt_cmd_id);

              if (program_info_length > sizeof(c->operand) - 4 - write_pos)
{  ///[3]

                     ret = -EINVAL;

                     goto out;

              }

 

              memcpy(&c->operand[write_pos], &msg[read_pos], 

                     program_info_length);

              read_pos += program_info_length;

              write_pos += program_info_length;             //////[4]

       }

       while (read_pos < length) {                      ////////[5]

              c->operand[write_pos++] = msg[read_pos++]; ///[6]

              c->operand[write_pos++] = msg[read_pos++];

              c->operand[write_pos++] = msg[read_pos++];

..

              }

       }

In [0] and [1] : We can full control the program_info_length and pmt_cmd_id
;

In [2] : for bypass it, pmt_cmd_id must be 1 or 4 ;

In [3] : program_info_length > sizeof(c->operand) - 4 - write_pos)

==> program_info_length <= 509 - 4 - 24 = 0x1e1, so you can control its
value to be 0x1e1 .

           In [4] : write_pos will be updated to 24+0x1e1 = 505

           In [5]: at this time, length=0xffffffff, read_pos is much smaller
than it, so in[6] will overwrite the c->oprand many bytes.

 

Patch : https://lore.kernel.org/linux-media/YHaulytonFcW+lyZ@mwanda/

 

Credit :

LuoLikang @ NSFOCUS SECURITY TEAM

 


Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.