]> git.proxmox.com Git - grub2.git/commitdiff
Put symlink at the end of the node and fix a potential
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 10 Nov 2011 08:31:06 +0000 (09:31 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 10 Nov 2011 08:31:06 +0000 (09:31 +0100)
memory corruption.

* grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink.
Make symlink into an array.
(set_rockridge): Set have_symlink and alloc_dirents.
(grub_iso9660_read_symlink): Use new layout.
(grub_iso9660_iterate_dir): Fix memory corruption.
Use new layout.
(grub_iso9660_dir): Set have_symlink.
(grub_iso9660_open): Likewise.

ChangeLog
grub-core/fs/iso9660.c

index e60b4da9c7c277aadc1b9af098a9691ad89a417a..f293e07733dd807b804b7ca9847f15befad698dd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-11-10  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Put symlink at the end of the node and fix a potential
+       memory corruption.
+
+       * grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink.
+       Make symlink into an array.
+       (set_rockridge): Set have_symlink and alloc_dirents.
+       (grub_iso9660_read_symlink): Use new layout.
+       (grub_iso9660_iterate_dir): Fix memory corruption.
+       Use new layout.
+       (grub_iso9660_dir): Set have_symlink.
+       (grub_iso9660_open): Likewise.
+
 2011-11-10  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Remove local keyword.
index 5e2f7824abc0ae4751a16c6f6f106f79e738cfab..7b1e32f7cdbbfe2cb3f5cc44d5393314bfa4bf55 100644 (file)
@@ -159,8 +159,9 @@ struct grub_fshelp_node
 {
   struct grub_iso9660_data *data;
   grub_size_t have_dirents, alloc_dirents;
-  char *symlink;
+  int have_symlink;
   struct grub_iso9660_dir dirents[8];
+  char symlink[0];
 };
 
 enum
@@ -408,9 +409,9 @@ set_rockridge (struct grub_iso9660_data *data)
       struct grub_fshelp_node rootnode;
 
       rootnode.data = data;
-      rootnode.alloc_dirents = 0;
+      rootnode.alloc_dirents = ARRAY_SIZE (rootnode.dirents);
       rootnode.have_dirents = 1;
-      rootnode.symlink = 0;
+      rootnode.have_symlink = 0;
       rootnode.dirents[0] = data->voldesc.rootdir;
 
       /* The 2nd data byte stored how many bytes are skipped every time
@@ -500,7 +501,10 @@ grub_iso9660_mount (grub_disk_t disk)
 static char *
 grub_iso9660_read_symlink (grub_fshelp_node_t node)
 {
-  return node->symlink ? grub_strdup (node->symlink) : grub_strdup ("");
+  return node->have_symlink 
+    ? grub_strdup (node->symlink
+                  + (node->have_dirents) * sizeof (node->dirents[0])
+                  - sizeof (node->dirents)) : grub_strdup ("");
 }
 
 static grub_off_t
@@ -703,7 +707,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
 
        /* Setup a new node.  */
        node->data = dir->data;
-       node->symlink = symlink;
+       node->have_symlink = 0;
 
        /* If the filetype was not stored using rockridge, use
           whatever is stored in the iso9660 filesystem.  */
@@ -767,10 +771,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
              {
                struct grub_fshelp_node *new_node;
                node->alloc_dirents *= 2;
-               new_node = grub_malloc (sizeof (struct grub_fshelp_node)
-                                   + ((node->alloc_dirents
-                                      - ARRAY_SIZE (node->dirents))
-                                      * sizeof (node->dirents[0])));
+               new_node = grub_realloc (node, 
+                                        sizeof (struct grub_fshelp_node)
+                                        + ((node->alloc_dirents
+                                            - ARRAY_SIZE (node->dirents))
+                                           * sizeof (node->dirents[0])));
                if (!new_node)
                  {
                    if (filename_alloc)
@@ -778,9 +783,37 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
                    grub_free (node);
                    return 0;
                  }
+               node = new_node;
              }
            node->dirents[node->have_dirents++] = dirent;
          }
+       if (symlink)
+         {
+           if ((node->alloc_dirents - node->have_dirents)
+               * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1)
+             {
+               struct grub_fshelp_node *new_node;
+               new_node = grub_realloc (node,
+                                        sizeof (struct grub_fshelp_node)
+                                        + ((node->alloc_dirents
+                                            - ARRAY_SIZE (node->dirents))
+                                           * sizeof (node->dirents[0]))
+                                        + grub_strlen (symlink) + 1);
+               if (!new_node)
+                 {
+                   if (filename_alloc)
+                     grub_free (filename);
+                   grub_free (node);
+                   return 0;
+                 }
+               node = new_node;
+             }
+           node->have_symlink = 1;
+           grub_strcpy (node->symlink
+                        + node->have_dirents * sizeof (node->dirents[0])
+                        - sizeof (node->dirents), symlink);
+           grub_free (symlink);
+         }
        if (hook (filename, type, node))
          {
            if (filename_alloc)
@@ -832,7 +865,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
   rootnode.data = data;
   rootnode.alloc_dirents = 0;
   rootnode.have_dirents = 1;
-  rootnode.symlink = 0;
+  rootnode.have_symlink = 0;
   rootnode.dirents[0] = data->voldesc.rootdir;
 
   /* Use the fshelp function to traverse the path.  */
@@ -875,7 +908,7 @@ grub_iso9660_open (struct grub_file *file, const char *name)
   rootnode.data = data;
   rootnode.alloc_dirents = 0;
   rootnode.have_dirents = 1;
-  rootnode.symlink = 0;
+  rootnode.have_symlink = 0;
   rootnode.dirents[0] = data->voldesc.rootdir;
 
   /* Use the fshelp function to traverse the path.  */