The following reply was made to PR kern/148546; it has been noted by GNATS.

From: dfil...@freebsd.org (dfilter service)
To: bug-follo...@freebsd.org
Cc:  
Subject: Re: kern/148546: commit references a PR
Date: Wed, 14 Jul 2010 18:08:33 +0000 (UTC)

 Author: jhb
 Date: Wed Jul 14 18:06:21 2010
 New Revision: 210066
 URL: http://svn.freebsd.org/changeset/base/210066
 
 Log:
   Rework the SMBIOS table walker to make it operate like other table walkers
   and remove a buffer overflow:
   - Remove the array of per-type dispatch functions.  Instead, pass each
     structure to a single callback.  The callback should check the type of
     each table entry to take appropriate action.  This matches the behavior
     of other table walkers such as for the MP Table and MADT.
   - Don't attempt to save an array of string pointers for each structure
     entry.  Instead, just skip the strings.  If this code is reused to
     provide a generic SMBIOS table walker in the future we could provide
     a method that looks up a specific string N for a given structure record
     instead of pre-populating an array of pointers.  This fixes a buffer
     overflow for structure entries with more than 20 strings.
   
   PR:          kern/148546
   Reported by: Spencer Minear @ McAfee
   MFC after:   3 days
 
 Modified:
   head/sys/dev/ipmi/ipmi_smbios.c
 
 Modified: head/sys/dev/ipmi/ipmi_smbios.c
 ==============================================================================
 --- head/sys/dev/ipmi/ipmi_smbios.c    Wed Jul 14 17:46:44 2010        
(r210065)
 +++ head/sys/dev/ipmi/ipmi_smbios.c    Wed Jul 14 18:06:21 2010        
(r210066)
 @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
  #define       pmap_unmapbios          pmap_unmapdev
  #endif
  
 -struct smbios_table_entry {
 +struct smbios_table {
        uint8_t         anchor_string[4];
        uint8_t         checksum;
        uint8_t         length;
 @@ -108,27 +108,30 @@ struct ipmi_entry {
  #define       SMBIOS_LEN              4
  #define       SMBIOS_SIG              "_SM_"
  
 -typedef void (*dispatchproc_t)(uint8_t *p, char **table,
 -    struct ipmi_get_info *info);
 +typedef void (*smbios_callback_t)(struct structure_header *, void *);
  
  static struct ipmi_get_info ipmi_info;
  static int ipmi_probed;
  static struct mtx ipmi_info_mtx;
  MTX_SYSINIT(ipmi_info, &ipmi_info_mtx, "ipmi info", MTX_DEF);
  
 -static char   *get_strings(char *, char **);
  static void   ipmi_smbios_probe(struct ipmi_get_info *);
 -static int    smbios_cksum    (struct smbios_table_entry *);
 -static void   smbios_run_table(uint8_t *, int, dispatchproc_t *,
 -                  struct ipmi_get_info *);
 -static void   smbios_t38_proc_info(uint8_t *, char **,
 -                  struct ipmi_get_info *);
 +static int    smbios_cksum(struct smbios_table *);
 +static void   smbios_walk_table(uint8_t *, int, smbios_callback_t,
 +                  void *);
 +static void   smbios_ipmi_info(struct structure_header *, void *);
  
  static void
 -smbios_t38_proc_info(uint8_t *p, char **table, struct ipmi_get_info *info)
 +smbios_ipmi_info(struct structure_header *h, void *arg)
  {
 -      struct ipmi_entry *s = (struct ipmi_entry *)p;
 +      struct ipmi_get_info *info;
 +      struct ipmi_entry *s;
  
 +      if (h->type != 38 || h->length <
 +          offsetof(struct ipmi_entry, interrupt_number))
 +              return;
 +      s = (struct ipmi_entry *)h;
 +      info = arg;
        bzero(info, sizeof(struct ipmi_get_info));
        switch (s->interface_type) {
        case KCS_MODE:
 @@ -172,44 +175,28 @@ smbios_t38_proc_info(uint8_t *p, char **
        info->iface_type = s->interface_type;
  }
  
 -static char *
 -get_strings(char *p, char **table)
 -{
 -      /* Scan for strings, stoping at a single null byte */
 -      while (*p != 0) {
 -              *table++ = p;
 -              p += strlen(p) + 1;
 -      }
 -      *table = 0;
 -
 -      /* Skip past terminating null byte */
 -      return (p + 1);
 -}
 -
 -
  static void
 -smbios_run_table(uint8_t *p, int entries, dispatchproc_t *dispatchstatus,
 -    struct ipmi_get_info *info)
 +smbios_walk_table(uint8_t *p, int entries, smbios_callback_t cb, void *arg)
  {
        struct structure_header *s;
 -      char *table[20];
 -      uint8_t *nextp;
  
 -      while(entries--) {
 -              s = (struct structure_header *) p;
 -              nextp = get_strings(p + s->length, table);
 +      while (entries--) {
 +              s = (struct structure_header *)p;
 +              cb(s, arg);
  
                /*
 -               * No strings still has a double-null at the end,
 -               * skip over it
 +               * Look for a double-nul after the end of the
 +               * formatted area of this structure.
                 */
 -              if (table[0] == 0)
 -                      nextp++;
 +              p += s->length;
 +              while (p[0] != 0 && p[1] != 0)
 +                      p++;
  
 -              if (dispatchstatus[*p]) {
 -                      (dispatchstatus[*p])(p, table, info);
 -              }
 -              p = nextp;
 +              /*
 +               * Skip over the double-nul to the start of the next
 +               * structure.
 +               */
 +              p += 2;
        }
  }
  
 @@ -221,8 +208,7 @@ smbios_run_table(uint8_t *p, int entries
  static void
  ipmi_smbios_probe(struct ipmi_get_info *info)
  {
 -      dispatchproc_t dispatch_smbios_ipmi[256];
 -      struct smbios_table_entry *header;
 +      struct smbios_table *header;
        void *table;
        u_int32_t addr;
  
 @@ -239,9 +225,9 @@ ipmi_smbios_probe(struct ipmi_get_info *
         * length and then map it a second time with the actual length so
         * we can verify the checksum.
         */
 -      header = pmap_mapbios(addr, sizeof(struct smbios_table_entry));
 +      header = pmap_mapbios(addr, sizeof(struct smbios_table));
        table = pmap_mapbios(addr, header->length);
 -      pmap_unmapbios((vm_offset_t)header, sizeof(struct smbios_table_entry));
 +      pmap_unmapbios((vm_offset_t)header, sizeof(struct smbios_table));
        header = table;
        if (smbios_cksum(header) != 0) {
                pmap_unmapbios((vm_offset_t)header, header->length);
 @@ -251,9 +237,7 @@ ipmi_smbios_probe(struct ipmi_get_info *
        /* Now map the actual table and walk it looking for an IPMI entry. */
        table = pmap_mapbios(header->structure_table_address,
            header->structure_table_length);
 -      bzero((void *)dispatch_smbios_ipmi, sizeof(dispatch_smbios_ipmi));
 -      dispatch_smbios_ipmi[38] = (void *)smbios_t38_proc_info;
 -      smbios_run_table(table, header->number_structures, dispatch_smbios_ipmi,
 +      smbios_walk_table(table, header->number_structures, smbios_ipmi_info,
            info);
  
        /* Unmap everything. */
 @@ -298,7 +282,7 @@ ipmi_smbios_identify(struct ipmi_get_inf
  }
  
  static int
 -smbios_cksum (struct smbios_table_entry *e)
 +smbios_cksum(struct smbios_table *e)
  {
        u_int8_t *ptr;
        u_int8_t cksum;
 _______________________________________________
 svn-src-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to