]> git.sur5r.net Git - bacula/bacula/commitdiff
Prevent a Volume that is being swapped from being freed from
authorKern Sibbald <kern@sibbald.com>
Thu, 1 May 2008 20:04:33 +0000 (20:04 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 1 May 2008 20:04:33 +0000 (20:04 +0000)
     the volume list. This will most likely fix, at least partially,
     bug #1083.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6871 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/patches/2.2.8-strippath.patch [new file with mode: 0644]
bacula/src/stored/reserve.c
bacula/technotes-2.3

diff --git a/bacula/patches/2.2.8-strippath.patch b/bacula/patches/2.2.8-strippath.patch
new file mode 100644 (file)
index 0000000..0aae252
--- /dev/null
@@ -0,0 +1,103 @@
+  This patch fixes the strippath bug that created a buffer overrun and thus
+  a crash in the FD.  It fixes bug #1078.
+
+  Apply it to version 2.2.8 or higher with:
+
+  cd <bacula-source>
+  patch -p0 <2.2.8-strippath.patch
+  ./configure <your options>
+  make
+  ...
+  make install
+
+
+Index: src/filed/backup.c
+===================================================================
+--- src/filed/backup.c (revision 6843)
++++ src/filed/backup.c (working copy)
+@@ -1102,9 +1102,9 @@
+    /* Copy to first path separator -- Win32 might have c: ... */
+    while (*in && !IsPathSeparator(*in)) {    
+-      *out++ = *in++;
++      out++; in++;
+    }
+-   *out++ = *in++;
++   out++; in++;
+    numsep++;                     /* one separator seen */
+    for (stripped=0; stripped<count && *in; stripped++) {
+       while (*in && !IsPathSeparator(*in)) {
+@@ -1129,7 +1129,11 @@
+ }
+ /*
+- * If requested strip leading components of the path
++ * If requested strip leading components of the path so that we can
++ *   save file as if it came from a subdirectory.  This is most useful
++ *   for dealing with snapshots, by removing the snapshot directory, or
++ *   in handling vendor migrations where files have been restored with
++ *   a vendor product into a subdirectory.
+  */
+ static void strip_path(FF_PKT *ff_pkt)
+ {
+@@ -1142,27 +1146,35 @@
+      ff_pkt->link_save = get_pool_memory(PM_FNAME);
+    }
+    pm_strcpy(ff_pkt->fname_save, ff_pkt->fname);
++   if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
++      pm_strcpy(ff_pkt->link_save, ff_pkt->link);
++      Dmsg2(500, "strcpy link_save=%d link=%d\n", strlen(ff_pkt->link_save),
++         strlen(ff_pkt->link));
++      sm_check(__FILE__, __LINE__, true);
++   }
+    /* 
+     * Strip path.  If it doesn't succeed put it back.  If
+     *  it does, and there is a different link string,
+     *  attempt to strip the link. If it fails, back them
+     *  both back.
+-    * Don't strip symlinks.
++    * Do not strip symlinks.
+     * I.e. if either stripping fails don't strip anything.
+     */
+-   if (do_strip(ff_pkt->strip_path, ff_pkt->fname)) {
+-      if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
+-         pm_strcpy(ff_pkt->link_save, ff_pkt->link);
+-         if (!do_strip(ff_pkt->strip_path, ff_pkt->link)) {
+-            strcpy(ff_pkt->link, ff_pkt->link_save);
+-            strcpy(ff_pkt->fname, ff_pkt->fname_save);
+-         }
++   if (!do_strip(ff_pkt->strip_path, ff_pkt->fname)) {
++      unstrip_path(ff_pkt);
++      goto rtn;
++   } 
++   /* Strip links but not symlinks */
++   if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
++      if (!do_strip(ff_pkt->strip_path, ff_pkt->link)) {
++         unstrip_path(ff_pkt);
+       }
+-   } else {
+-      strcpy(ff_pkt->fname, ff_pkt->fname_save);
+-   } 
+-   Dmsg2(200, "fname=%s stripped=%s\n", ff_pkt->fname_save, ff_pkt->fname);
++   }
++
++rtn:
++   Dmsg3(100, "fname=%s stripped=%s link=%s\n", ff_pkt->fname_save, ff_pkt->fname, 
++       ff_pkt->link);
+ }
+ static void unstrip_path(FF_PKT *ff_pkt)
+@@ -1172,6 +1184,11 @@
+    }
+    strcpy(ff_pkt->fname, ff_pkt->fname_save);
+    if (ff_pkt->type != FT_LNK && ff_pkt->fname != ff_pkt->link) {
++      Dmsg2(500, "strcpy link=%s link_save=%s\n", ff_pkt->link,
++          ff_pkt->link_save);
+       strcpy(ff_pkt->link, ff_pkt->link_save);
++      Dmsg2(500, "strcpy link=%d link_save=%d\n", strlen(ff_pkt->link),
++          strlen(ff_pkt->link_save));
++      sm_check(__FILE__, __LINE__, true);
+    }
+ }
index 8d92efc5346fbac06e0395cdbc03f89f9ebb0c68..fc580bc0e5b744b2dfb96a5355cb8878cef9f7eb 100644 (file)
@@ -386,22 +386,24 @@ VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
       nvol->dev = NULL;                  /* don't zap dev entry */
       free_vol_item(nvol);
 
-      /* Check if we are trying to use the Volume on a different drive */
+      /*
+       * Check if we are trying to use the Volume on a different drive
+       *  dev      is our device
+       *  vol->dev is where the Volume we want is
+       */
       if (dev != vol->dev) {
          /* Caller wants to switch Volume to another device */
          if (!vol->dev->is_busy() && !vol->is_swapping()) {
             Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
             free_volume(dev);            /* free any volume attached to our drive */
-            vol->dev->set_unload();      /* unload our drive */
+            vol->dev->set_unload();      /* unload the other drive */
             vol->set_swapping();         /* swap from other drive */
             dev->swap_dev = vol->dev;    /* remember to get this vol */
             vol->dev->set_load();        /* then reload on our drive */
             vol->dev->vol = NULL;        /* remove volume from other drive */
-            vol->dev = dev;              /* point it at our drive */
-            dev->vol = vol;              /* point our drive at it */
-            Dmsg3(dbglvl, "==== Swap vol=%s from dev=%s to %s\n", 
-               VolumeName, vol->dev->print_name(), dev->print_name());
+            vol->dev = dev;              /* point the Volume at our drive */
+            dev->vol = vol;              /* point our drive at the Volume */
          } else {
             Dmsg3(dbglvl, "==== Swap not possible Vol busy vol=%s from dev=%s to %s\n", 
                VolumeName, vol->dev->print_name(), dev->print_name());
@@ -589,11 +591,14 @@ bool free_volume(DEVICE *dev)
    }
    lock_volumes();
    vol = dev->vol;
-   dev->vol = NULL;
-   vol_list->remove(vol);
-   Dmsg2(dbglvl, "=== free_volume %s dev=%s\n", vol->vol_name, dev->print_name());
-   free_vol_item(vol);
-   debug_list_volumes("free_volume");
+   /* Don't free a volume while it is being swapped */
+   if (!vol->is_swapping()) {
+      dev->vol = NULL;
+      vol_list->remove(vol);
+      Dmsg2(dbglvl, "=== free_volume %s dev=%s\n", vol->vol_name, dev->print_name());
+      free_vol_item(vol);
+      debug_list_volumes("free_volume");
+   }
    unlock_volumes();
    return true;
 }
index 658b1f51172bd85b0324cb96135469976719d060..7d93b5e0664dcb000aa247cd6825731663476e50 100644 (file)
@@ -25,6 +25,9 @@ Add long term statistics job table
 
 General:
 01May08
+kes  Prevent a Volume that is being swapped from being freed from
+     the volume list. This will most likely fix, at least partially,
+     bug #1083.
 kes  Fix strippath so that it does not get a buffer overrun and crash FD.
      This fixes bug #1078.
 kes  Remove 50 millisec wait in SD that broke debugger.