All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
To: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: kexec@lists.infradead.org,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>,
	linux-security-module <linux-security-module@vger.kernel.org>,
	"Eric W.	Biederman" <ebiederm@xmission.com>,
	linux-ima-devel <linux-ima-devel@lists.sourceforge.net>,
	Andrew Morton <akpm@linux-foundation.org>,
	linuxppc-dev@lists.ozlabs.org
Subject: Re: [Linux-ima-devel] [PATCH v6 02/10] ima: on soft reboot, restore the measurement list
Date: Thu, 10 Nov 2016 08:12:32 -0500	[thread overview]
Message-ID: <1478783552.31015.34.camel@linux.vnet.ibm.com> (raw)
In-Reply-To: <1478638078.2879.205.camel@linux.vnet.ibm.com>

On Tue, 2016-11-08 at 15:47 -0500, Mimi Zohar wrote:
> On Tue, 2016-11-08 at 21:46 +0200, Dmitry Kasatkin wrote:
> > On Fri, Oct 21, 2016 at 5:44 AM, Thiago Jung Bauermann

> > > +/* Restore the serialized binary measurement list without extending PCRs. */
> > > +int ima_restore_measurement_list(loff_t size, void *buf)
> > > +{
> > > +       struct binary_hdr_v1 {
> > > +               u32 pcr;
> > > +               u8 digest[TPM_DIGEST_SIZE];
> > > +               u32 template_name_len;
> > > +               char template_name[0];
> > > +       } __packed;
> > > +       char template_name[MAX_TEMPLATE_NAME_LEN];
> > > +
> > > +       struct binary_data_v1 {
> > > +               u32 template_data_size;
> > > +               char template_data[0];
> > > +       } __packed;
> > > +
> > > +       struct ima_kexec_hdr *khdr = buf;
> > > +       struct binary_hdr_v1 *hdr_v1;
> > > +       struct binary_data_v1 *data_v1;
> > > +
> > > +       void *bufp = buf + sizeof(*khdr);
> > > +       void *bufendp = buf + khdr->buffer_size;
> > > +       struct ima_template_entry *entry;
> > > +       struct ima_template_desc *template_desc;
> > > +       unsigned long count = 0;
> > > +       int ret = 0;
> > > +
> > > +       if (!buf || size < sizeof(*khdr))
> > > +               return 0;
> > > +
> > > +       if (khdr->version != 1) {
> > > +               pr_err("attempting to restore a incompatible measurement list");
> > > +               return 0;
> > > +       }
> > > +
> > > +       /*
> > > +        * ima kexec buffer prefix: version, buffer size, count
> > > +        * v1 format: pcr, digest, template-name-len, template-name,
> > > +        *            template-data-size, template-data
> > > +        */
> > > +       while ((bufp < bufendp) && (count++ < khdr->count)) {
> > > +               if (count > ULONG_MAX - 1) {
> > > +                       pr_err("attempting to restore too many measurements");
> > > +                       ret = -EINVAL;
> > > +               }
> > > +
> > > +               hdr_v1 = bufp;
> > > +               if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) ||
> > > +                   ((bufp + hdr_v1->template_name_len) > bufendp)) {
> > 
> > based on following code  template_name_len does not include header
> > (sizeof(*hdr_v1))?
> > If so the check is wrong???
> 
> Yes, good catch.  In addition, before assigning hdr_v1 there should be a
> size check as well. 
> 
> > 
> > > +                       pr_err("attempting to restore a template name \
> > > +                               that is too long\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               bufp += sizeof(*hdr_v1);

This line should have been before the test above.

> > > +
> > > +               /* template name is not null terminated */
> > > +               memcpy(template_name, bufp, hdr_v1->template_name_len);
> > > +               template_name[hdr_v1->template_name_len] = 0;
> > > +
> > > +               if (strcmp(template_name, "ima") == 0) {
> > > +                       pr_err("attempting to restore an unsupported \
> > > +                               template \"%s\" failed\n", template_name);
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len;
> > > +
> > > +               /* get template format */
> > > +               template_desc = lookup_template_desc(template_name);
> > > +               if (!template_desc) {
> > > +                       pr_err("template \"%s\" not found\n", template_name);
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +
> > > +               if (bufp > (bufendp - sizeof(data_v1->template_data_size))) {
> > > +                       pr_err("restoring the template data size failed\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               bufp += (u_int8_t) sizeof(data_v1->template_data_size);
> > > +
> > > +               if (bufp > (bufendp - data_v1->template_data_size)) {
> > > +                       pr_err("restoring the template data failed\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +
> > 
> > It looks like a similar problem... sizeof(struct binary_data_v1) is
> > missing in the check...
> 
> Following the template name, is the template data length and the
> template data. 
> 
> > > +               ret = ima_restore_template_data(template_desc,
> > > +                                               data_v1->template_data,
> > > +                                               data_v1->template_data_size,
> > > +                                               &entry);
> > > +               if (ret < 0)
> > > +                       break;
> > > +
> > > +               memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE);
> > > +               entry->pcr = hdr_v1->pcr;
> > > +               ret = ima_restore_measurement_entry(entry);
> > > +               if (ret < 0)
> > > +                       break;
> > > +
> > > +               bufp += data_v1->template_data_size;
> > > +       }
> > > +       return ret;
> > > +}
> > > --
> > > 2.7.4
> > >
> > 
> > In overall it is a bit hard to read this function somehow..
> 
> Ok, I'll see if there is any way of simplifying/cleaning up walking the
> measurement list some more.

I moved some code around so that the bufp pointer update is immediately
after the  buffer overflow tests and moved one check outside the while
loop.  I tried defining a buffer overflow macro, but that didn't seem to
help.

The updated patches are available in the next-kexec-restore branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

Mimi


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

WARNING: multiple messages have this Message-ID (diff)
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
To: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: kexec@lists.infradead.org,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	linux-ima-devel <linux-ima-devel@lists.sourceforge.net>,
	linux-security-module <linux-security-module@vger.kernel.org>,
	"Eric W.	Biederman" <ebiederm@xmission.com>,
	Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	linuxppc-dev@lists.ozlabs.org
Subject: Re: [Linux-ima-devel] [PATCH v6 02/10] ima: on soft reboot, restore the measurement list
Date: Thu, 10 Nov 2016 08:12:32 -0500	[thread overview]
Message-ID: <1478783552.31015.34.camel@linux.vnet.ibm.com> (raw)
In-Reply-To: <1478638078.2879.205.camel@linux.vnet.ibm.com>

On Tue, 2016-11-08 at 15:47 -0500, Mimi Zohar wrote:
> On Tue, 2016-11-08 at 21:46 +0200, Dmitry Kasatkin wrote:
> > On Fri, Oct 21, 2016 at 5:44 AM, Thiago Jung Bauermann

> > > +/* Restore the serialized binary measurement list without extending PCRs. */
> > > +int ima_restore_measurement_list(loff_t size, void *buf)
> > > +{
> > > +       struct binary_hdr_v1 {
> > > +               u32 pcr;
> > > +               u8 digest[TPM_DIGEST_SIZE];
> > > +               u32 template_name_len;
> > > +               char template_name[0];
> > > +       } __packed;
> > > +       char template_name[MAX_TEMPLATE_NAME_LEN];
> > > +
> > > +       struct binary_data_v1 {
> > > +               u32 template_data_size;
> > > +               char template_data[0];
> > > +       } __packed;
> > > +
> > > +       struct ima_kexec_hdr *khdr = buf;
> > > +       struct binary_hdr_v1 *hdr_v1;
> > > +       struct binary_data_v1 *data_v1;
> > > +
> > > +       void *bufp = buf + sizeof(*khdr);
> > > +       void *bufendp = buf + khdr->buffer_size;
> > > +       struct ima_template_entry *entry;
> > > +       struct ima_template_desc *template_desc;
> > > +       unsigned long count = 0;
> > > +       int ret = 0;
> > > +
> > > +       if (!buf || size < sizeof(*khdr))
> > > +               return 0;
> > > +
> > > +       if (khdr->version != 1) {
> > > +               pr_err("attempting to restore a incompatible measurement list");
> > > +               return 0;
> > > +       }
> > > +
> > > +       /*
> > > +        * ima kexec buffer prefix: version, buffer size, count
> > > +        * v1 format: pcr, digest, template-name-len, template-name,
> > > +        *            template-data-size, template-data
> > > +        */
> > > +       while ((bufp < bufendp) && (count++ < khdr->count)) {
> > > +               if (count > ULONG_MAX - 1) {
> > > +                       pr_err("attempting to restore too many measurements");
> > > +                       ret = -EINVAL;
> > > +               }
> > > +
> > > +               hdr_v1 = bufp;
> > > +               if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) ||
> > > +                   ((bufp + hdr_v1->template_name_len) > bufendp)) {
> > 
> > based on following code  template_name_len does not include header
> > (sizeof(*hdr_v1))?
> > If so the check is wrong???
> 
> Yes, good catch.  In addition, before assigning hdr_v1 there should be a
> size check as well. 
> 
> > 
> > > +                       pr_err("attempting to restore a template name \
> > > +                               that is too long\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               bufp += sizeof(*hdr_v1);

This line should have been before the test above.

> > > +
> > > +               /* template name is not null terminated */
> > > +               memcpy(template_name, bufp, hdr_v1->template_name_len);
> > > +               template_name[hdr_v1->template_name_len] = 0;
> > > +
> > > +               if (strcmp(template_name, "ima") == 0) {
> > > +                       pr_err("attempting to restore an unsupported \
> > > +                               template \"%s\" failed\n", template_name);
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len;
> > > +
> > > +               /* get template format */
> > > +               template_desc = lookup_template_desc(template_name);
> > > +               if (!template_desc) {
> > > +                       pr_err("template \"%s\" not found\n", template_name);
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +
> > > +               if (bufp > (bufendp - sizeof(data_v1->template_data_size))) {
> > > +                       pr_err("restoring the template data size failed\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +               bufp += (u_int8_t) sizeof(data_v1->template_data_size);
> > > +
> > > +               if (bufp > (bufendp - data_v1->template_data_size)) {
> > > +                       pr_err("restoring the template data failed\n");
> > > +                       ret = -EINVAL;
> > > +                       break;
> > > +               }
> > > +
> > 
> > It looks like a similar problem... sizeof(struct binary_data_v1) is
> > missing in the check...
> 
> Following the template name, is the template data length and the
> template data. 
> 
> > > +               ret = ima_restore_template_data(template_desc,
> > > +                                               data_v1->template_data,
> > > +                                               data_v1->template_data_size,
> > > +                                               &entry);
> > > +               if (ret < 0)
> > > +                       break;
> > > +
> > > +               memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE);
> > > +               entry->pcr = hdr_v1->pcr;
> > > +               ret = ima_restore_measurement_entry(entry);
> > > +               if (ret < 0)
> > > +                       break;
> > > +
> > > +               bufp += data_v1->template_data_size;
> > > +       }
> > > +       return ret;
> > > +}
> > > --
> > > 2.7.4
> > >
> > 
> > In overall it is a bit hard to read this function somehow..
> 
> Ok, I'll see if there is any way of simplifying/cleaning up walking the
> measurement list some more.

I moved some code around so that the bufp pointer update is immediately
after the  buffer overflow tests and moved one check outside the while
loop.  I tried defining a buffer overflow macro, but that didn't seem to
help.

The updated patches are available in the next-kexec-restore branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

Mimi

  reply	other threads:[~2016-11-10 13:13 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-21  2:44 [PATCH v6 00/10] ima: carry the measurement list across kexec Thiago Jung Bauermann
2016-10-21  2:44 ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 01/10] powerpc: ima: Get the kexec buffer passed by the previous kernel Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 02/10] ima: on soft reboot, restore the measurement list Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-11-08 19:46   ` [Linux-ima-devel] " Dmitry Kasatkin
2016-11-08 19:46     ` Dmitry Kasatkin
2016-11-08 20:47     ` Mimi Zohar
2016-11-08 20:47       ` Mimi Zohar
2016-11-10 13:12       ` Mimi Zohar [this message]
2016-11-10 13:12         ` Mimi Zohar
2016-10-21  2:44 ` [PATCH v6 03/10] ima: permit duplicate measurement list entries Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-11-08 19:47   ` [Linux-ima-devel] " Dmitry Kasatkin
2016-11-08 19:47     ` Dmitry Kasatkin
2016-10-21  2:44 ` [PATCH v6 04/10] ima: maintain memory size needed for serializing the measurement list Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-11-08 20:05   ` [Linux-ima-devel] " Dmitry Kasatkin
2016-11-08 20:05     ` Dmitry Kasatkin
2016-11-08 21:03     ` Mimi Zohar
2016-11-08 21:03       ` Mimi Zohar
2016-10-21  2:44 ` [PATCH v6 05/10] powerpc: ima: Send the kexec buffer to the next kernel Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 06/10] ima: on soft reboot, save the measurement list Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 07/10] ima: store the builtin/custom template definitions in a list Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-11-08 23:40   ` [Linux-ima-devel] " Dmitry Kasatkin
2016-11-08 23:40     ` Dmitry Kasatkin
2016-10-21  2:44 ` [PATCH v6 08/10] ima: support restoring multiple template formats Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 09/10] ima: define a canonical binary_runtime_measurements list format Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann
2016-10-21  2:44 ` [PATCH v6 10/10] ima: platform-independent hash value Thiago Jung Bauermann
2016-10-21  2:44   ` Thiago Jung Bauermann

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=1478783552.31015.34.camel@linux.vnet.ibm.com \
    --to=zohar@linux.vnet.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=bauerman@linux.vnet.ibm.com \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=ebiederm@xmission.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-ima-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.