]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix bug #1355 Director crashes with double free in Accurate SQL query
authorEric Bollengier <eric@eb.homelinux.org>
Thu, 10 Sep 2009 12:50:45 +0000 (14:50 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Thu, 10 Sep 2009 12:50:45 +0000 (14:50 +0200)
bacula/src/cats/cats.h
bacula/src/cats/protos.h
bacula/src/cats/sql.c
bacula/src/cats/sql_get.c
bacula/src/dird/backup.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_restore.c
bacula/src/dird/vbackup.c

index 2ff803fbd24466408b31fcff1a05b2c746e4cd60..be07e84746399b3be4b110d24b2cfc8214e2a62f 100644 (file)
@@ -1037,6 +1037,16 @@ struct db_int64_ctx {
    int count;                         /* number of values seen */
 };
 
+/* Call back context for getting a list of comma separated strings from the database */
+class db_list_ctx {
+public:
+   POOLMEM *list;                     /* list */
+   int count;                         /* number of values seen */
+
+   db_list_ctx() { list = get_pool_memory(PM_FNAME); *list = 0; count = 0; }
+   ~db_list_ctx() { free_pool_memory(list); list = NULL; }
+};
+
 
 #include "protos.h"
 #include "jcr.h"
index ea03a3cc54fe9de35dd196ccc3636767a6ee81f0..565526ada9bbe845d2a19d18e4b99653e62dce30 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -57,6 +57,7 @@ bool db_sql_query(B_DB *mdb, const char *cmd, DB_RESULT_HANDLER *result_handler,
 void db_start_transaction(JCR *jcr, B_DB *mdb);
 void db_end_transaction(JCR *jcr, B_DB *mdb);
 int db_int64_handler(void *ctx, int num_fields, char **row);
+int db_list_handler(void *ctx, int num_fields, char **row);
 void db_thread_cleanup();
 void _dbg_print_db(JCR *jcr, FILE *fp);
 
@@ -106,8 +107,8 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr);
 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
 bool db_get_query_dbids(JCR *jcr, B_DB *mdb, POOL_MEM &query, dbid_list &ids);
 bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids, DB_RESULT_HANDLER *result_handler, void *ctx);
-bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *jobids);
-int db_get_int_handler(void *ctx, int num_fields, char **row);
+bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, JOB_DBR *jr, db_list_ctx *jobids);
+int db_get_int_handler(void *list, int num_fields, char **row);
 
 
 /* sql_list.c */
index 324d01760cdb9755cb6123e839ebfa6ebb22a0a9..e698b5a7279117530a5390e9aca7e1a7ff688748 100644 (file)
@@ -144,7 +144,21 @@ int db_int64_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-
+/*
+ * Use to build a comma separated list of values from a query. "10,20,30"
+ */
+int db_list_handler(void *ctx, int num_fields, char **row)
+{
+   db_list_ctx *lctx = (db_list_ctx *)ctx;
+   if (num_fields == 1 && row[0]) {
+      if (lctx->list[0]) {
+         pm_strcat(lctx->list, ",");
+      }
+      pm_strcat(lctx->list, row[0]);
+      lctx->count++;
+   }
+   return 0;
+}
 
 /* NOTE!!! The following routines expect that the
  *  calling subroutine sets and clears the mutex
index b9d25bbc11d71180a2d91f92956a847ba9b29a44..62cd07c9f6ff5c011e5b939312be25e11ffd197f 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -1100,7 +1100,7 @@ bool db_get_file_list(JCR *jcr, B_DB *mdb, char *jobids,
  * TODO: look and merge from ua_restore.c
  */
 bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, 
-                            JOB_DBR *jr, POOLMEM *jobids)
+                            JOB_DBR *jr, db_list_ctx *jobids)
 {
    bool ret=false;
    char clientid[50], jobid[50], filesetid[50];
@@ -1111,7 +1111,8 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb,
    time_t StartTime = (jr->StartTime)?jr->StartTime:time(NULL);
 
    bstrutime(date, sizeof(date),  StartTime + 1);
-   jobids[0]='\0';
+   jobids->list[0] = 0;
+   jobids->count = 0;
 
    /* First, find the last good Full backup for this job/client/fileset */
    Mmsg(query, 
@@ -1177,8 +1178,8 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb,
 
    /* build a jobid list ie: 1,2,3,4 */
    Mmsg(query, "SELECT JobId FROM btemp3%s ORDER by JobTDate", jobid);
-   db_sql_query(mdb, query.c_str(), db_get_int_handler, jobids);
-   Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids);
+   db_sql_query(mdb, query.c_str(), db_list_handler, jobids);
+   Dmsg1(1, "db_accurate_get_jobids=%s\n", jobids->list);
    ret = true;
 
 bail_out:
@@ -1188,19 +1189,4 @@ bail_out:
    return ret;
 }
 
-/*
- * Use to build a string of int list from a query. "10,20,30"
- */
-int db_get_int_handler(void *ctx, int num_fields, char **row)
-{
-   POOLMEM *ret = (POOLMEM *)ctx;
-   if (num_fields == 1) {
-      if (ret[0]) {
-         pm_strcat(ret, ",");
-      }
-      pm_strcat(ret, row[0]);
-   }
-   return 0;
-}
-
 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI */
index 029dfa0c89179ab8bb34bb8068062310be01394b..1837a6bebea745223cc600df5c71f7a07b8d4131 100644 (file)
@@ -131,42 +131,37 @@ static int accurate_list_handler(void *ctx, int num_fields, char **row)
 bool send_accurate_current_files(JCR *jcr)
 {
    POOL_MEM buf;
+   db_list_ctx jobids;
+   db_list_ctx nb;
 
    if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) {
       return true;
    }
-   POOLMEM *jobids = get_pool_memory(PM_FNAME);
 
-   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
-
-   if (*jobids == 0) {
-      free_pool_memory(jobids);
+   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
+   if (jobids.count == 0) {
       Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n"));
       return false;
    }
+
    if (jcr->JobId) {            /* display the message only for real jobs */
       Jmsg(jcr, M_INFO, 0, _("Sending Accurate information.\n"));
    }
    /* to be able to allocate the right size for htable */
-   POOLMEM *nb = get_pool_memory(PM_FNAME);
-   *nb = 0;                           /* clear buffer */
-   Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids);
-   db_sql_query(jcr->db, buf.c_str(), db_get_int_handler, nb);
-   Dmsg2(200, "jobids=%s nb=%s\n", jobids, nb);
-   jcr->file_bsock->fsend("accurate files=%s\n", nb); 
+   Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids.list);
+   db_sql_query(jcr->db, buf.c_str(), db_list_handler, &nb);
+   Dmsg2(200, "jobids=%s nb=%s\n", jobids.list, nb.list);
+   jcr->file_bsock->fsend("accurate files=%s\n", nb.list); 
 
    if (!db_open_batch_connexion(jcr, jcr->db)) {
       Jmsg0(jcr, M_FATAL, 0, "Can't get dedicate sql connexion");
       return false;
    }
 
-   db_get_file_list(jcr, jcr->db_batch, jobids, accurate_list_handler, (void *)jcr);
+   db_get_file_list(jcr, jcr->db_batch, jobids.list, accurate_list_handler, (void *)jcr);
 
    /* TODO: close the batch connexion ? (can be used very soon) */
 
-   free_pool_memory(jobids);
-   free_pool_memory(nb);
-
    jcr->file_bsock->signal(BNET_EOD);
 
    return true;
index 3d5fc1dfba81ddcd34896651524623516f13e570..028be52b3d6fcea6b811c486ec3f4627b823a5b1 100644 (file)
@@ -456,7 +456,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist)
          }
          list_nextvol(ua, n);
       } else if (strcasecmp(ua->argk[i], NT_("copies")) == 0) {
-         char *jobids=NULL;
+         char *jobids = NULL;
          uint32_t limit=0;
          for (j=i+1; j<ua->argc; j++) {
             if (strcasecmp(ua->argk[j], NT_("jobid")) == 0 && ua->argv[j]) {
index 366d9ed3705994c31c21b508061a432cccda8957..16f5215f9e6151e2bb62db317c0e0867e2791805 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -556,6 +556,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       char *fname;
       int len;
       bool gui_save;
+      db_list_ctx jobids;
 
       start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
       for (int i=0; list[i]; i++) {
@@ -752,9 +753,10 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
             return 0;
          }
          jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
-         if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, rx->JobIds)) {
+         if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &jobids)) {
             return 0;
          }
+         pm_strcpy(rx->JobIds, jobids.list);
          Dmsg1(30, "Item 12: jobids = %s\n", rx->JobIds);
          break;
       case 12:                        /* Cancel or quit */
index 45a1f7e06522e6bbe41fc02365ca9c16840ea3b2..e75d08d06c5e2a1948c2ad7f5be14543d88f8433 100644 (file)
@@ -50,7 +50,7 @@
 
 static const int dbglevel = 10;
 
-static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids);
+static bool create_bootstrap_file(JCR *jcr, char *jobids);
 void vbackup_cleanup(JCR *jcr, int TermCode);
 
 /* 
@@ -135,6 +135,7 @@ bool do_vbackup(JCR *jcr)
    char ed1[100];
    BSOCK *sd;
    char *p;
+   db_list_ctx jobids;
 
    Dmsg2(100, "rstorage=%p wstorage=%p\n", jcr->rstorage, jcr->wstorage);
    Dmsg2(100, "Read store=%s, write store=%s\n", 
@@ -157,28 +158,27 @@ bool do_vbackup(JCR *jcr)
 _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n"));
    }
 
-   POOLMEM *jobids = get_pool_memory(PM_FNAME);
    jcr->jr.JobLevel = L_VIRTUAL_FULL;
-   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids);
-   jcr->jr.JobLevel = L_FULL;
-   Dmsg1(10, "Accurate jobids=%s\n", jobids);
-   if (*jobids == 0) {
-      free_pool_memory(jobids);
+   db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, &jobids);
+   Dmsg1(10, "Accurate jobids=%s\n", jobids.list);
+   if (jobids.count == 0) {
       Jmsg(jcr, M_FATAL, 0, _("No previous Jobs found.\n"));
       return false;
    }
 
+   jcr->jr.JobLevel = L_FULL;
+
    /*
     * Now we find the last job that ran and store it's info in
     *  the previous_jr record.  We will set our times to the
     *  values from that job so that anything changed after that
     *  time will be picked up on the next backup.
     */
-   p = strrchr(jobids, ',');              /* find last jobid */
+   p = strrchr(jobids.list, ',');           /* find last jobid */
    if (p != NULL) {
       p++;
    } else {
-      p = jobids;
+      p = jobids.list;
    }
    memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr));
    jcr->previous_jr.JobId = str_to_int64(p);
@@ -189,12 +189,10 @@ _("This Job is not an Accurate backup so is not equivalent to a Full backup.\n")
       return false;
    }
 
-   if (!create_bootstrap_file(jcr, jobids)) {
+   if (!create_bootstrap_file(jcr, jobids.list)) {
       Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
-      free_pool_memory(jobids);
       return false;
    }
-   free_pool_memory(jobids);
 
    /*
     * Open a message channel connection with the Storage
@@ -476,7 +474,7 @@ int insert_bootstrap_handler(void *ctx, int num_fields, char **row)
 }
 
 
-static bool create_bootstrap_file(JCR *jcr, POOLMEM *jobids)
+static bool create_bootstrap_file(JCR *jcr, char *jobids)
 {
    RESTORE_CTX rx;
    UAContext *ua;