--- /dev/null
+
+ 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);
+ }
+ }
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());
}
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;
}