From ea3c16aba2bdc9a0a4357d2153037d2892bb7bfc Mon Sep 17 00:00:00 2001
From: Ann Priestman <apriestman@basistech.com>
Date: Thu, 6 Feb 2020 10:25:49 -0500
Subject: [PATCH] Moved addUnallocatedPoolBlocksToDb to addUnallocSpaceToDb.
 Added pool check to addUnallocVsSpaceToDb.

---
 tsk/auto/auto.cpp      |   9 +++-
 tsk/auto/auto_db.cpp   | 102 ++++++++++++++++++++++++++++-------------
 tsk/auto/tsk_auto.h    |   3 +-
 tsk/auto/tsk_case_db.h |   9 +++-
 4 files changed, 87 insertions(+), 36 deletions(-)

diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp
index 39775dd6c..4e927ad48 100755
--- a/tsk/auto/auto.cpp
+++ b/tsk/auto/auto.cpp
@@ -146,6 +146,10 @@ uint8_t TskAuto::openImageHandle(TSK_IMG_INFO * a_img_info)
 void
  TskAuto::closeImage()
 {
+    for (int i = 0; i < m_poolInfos.size(); i++) {
+        tsk_pool_close(m_poolInfos[i]);
+    }
+
     if ((m_img_info) && (m_internalOpen)) {
         tsk_img_close(m_img_info);
     }
@@ -493,7 +497,10 @@ TskAuto::findFilesInPool(TSK_OFF_T start, TSK_POOL_TYPE_ENUM ptype)
         registerError();
         return TSK_ERR;
     }
-    pool->close(pool);
+
+    // Store the pool_info for later use. It will be closed at the end of the add image process.
+    m_poolInfos.push_back(pool);
+
     return TSK_OK;
 }
 
diff --git a/tsk/auto/auto_db.cpp b/tsk/auto/auto_db.cpp
index 9d37865f8..49ba92602 100755
--- a/tsk/auto/auto_db.cpp
+++ b/tsk/auto/auto_db.cpp
@@ -316,6 +316,8 @@ TskAutoDb::filterPool(const TSK_POOL_INFO * pool_info)
             registerError();
             return TSK_FILTER_STOP;
         }
+        // Save the parent obj ID for the pool
+        m_poolOffsetToParentId[pool_info->img_offset] = m_curVolId;
     }
     else {
         // pool doesn't live in a volume, use image as parent
@@ -323,48 +325,69 @@ TskAutoDb::filterPool(const TSK_POOL_INFO * pool_info)
             registerError();
             return TSK_FILTER_STOP;
         }
+        // Save the parent obj ID for the pool
+        m_poolOffsetToParentId[pool_info->img_offset] = m_curImgId;
     }
 
-    if (addUnallocatedPoolBlocksToDb(pool_info, poolObjId)) {
-        registerError();
-        return TSK_FILTER_STOP;
-    }
+    // Store the volume system object ID for later use
+    m_poolOffsetToVsId[pool_info->img_offset] = m_curPoolVs;
 
     return TSK_FILTER_CONT;
 }
 
-TSK_FILTER_ENUM
-TskAutoDb::addUnallocatedPoolBlocksToDb(const TSK_POOL_INFO * pool_info, int64_t poolObjId) {
-    /* Only APFS pools are currently supported */
-    if (pool_info->ctype != TSK_POOL_TYPE_APFS) {
-        return TSK_FILTER_CONT;
-    }
+TSK_RETVAL_ENUM
+TskAutoDb::addUnallocatedPoolBlocksToDb(size_t & numPool) {
 
-    // Create the volume
-    int64_t unallocVolObjId;
-    m_db->addUnallocatedPoolVolume(pool_info->num_vols, poolObjId, unallocVolObjId);
+    for (int i = 0; i < m_poolInfos.size(); i++) {
+        const TSK_POOL_INFO * pool_info = m_poolInfos[i];
+        if (m_poolOffsetToVsId.find(pool_info->img_offset) == m_poolOffsetToVsId.end()) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_AUTO_DB);
+            tsk_error_set_errstr("Error addUnallocatedPoolBlocksToDb() - could not find volume system object ID for pool at offset %lld", pool_info->img_offset);
+            return TSK_ERR;
+        }
+        int64_t curPoolVs = m_poolOffsetToVsId[pool_info->img_offset];
 
-    TSK_FS_ATTR_RUN * unalloc_runs = tsk_pool_unallocated_runs(pool_info);
-    TSK_FS_ATTR_RUN * current_run = unalloc_runs;
-    vector<TSK_DB_FILE_LAYOUT_RANGE> ranges;
-    while (current_run != NULL) {
+        /* Make sure  the pool_info is still allocated */
+        if (pool_info->tag != TSK_POOL_INFO_TAG) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_AUTO_DB);
+            tsk_error_set_errstr("Error addUnallocatedPoolBlocksToDb() - pool_info is not allocated");
+            return TSK_ERR;
+        }
 
-        TSK_DB_FILE_LAYOUT_RANGE tempRange(current_run->addr * pool_info->block_size, current_run->len * pool_info->block_size, 0);
-        
-        ranges.push_back(tempRange);
-        int64_t fileObjId = 0;
-        if (m_db->addUnallocBlockFile(unallocVolObjId, NULL, current_run->len * pool_info->block_size, ranges, fileObjId, m_curImgId)) {
-            registerError();
-            tsk_fs_attr_run_free(unalloc_runs);
-            return TSK_FILTER_STOP;
+        /* Only APFS pools are currently supported */
+        if (pool_info->ctype != TSK_POOL_TYPE_APFS) {
+            continue;
         }
+        numPool++;
+
+        // Create the volume
+        int64_t unallocVolObjId;
+        m_db->addUnallocatedPoolVolume(pool_info->num_vols, curPoolVs, unallocVolObjId);
+
+        TSK_FS_ATTR_RUN * unalloc_runs = tsk_pool_unallocated_runs(pool_info);
+        TSK_FS_ATTR_RUN * current_run = unalloc_runs;
+        vector<TSK_DB_FILE_LAYOUT_RANGE> ranges;
+        while (current_run != NULL) {
 
-        current_run = current_run->next;
-        ranges.clear();
+            TSK_DB_FILE_LAYOUT_RANGE tempRange(current_run->addr * pool_info->block_size, current_run->len * pool_info->block_size, 0);
+
+            ranges.push_back(tempRange);
+            int64_t fileObjId = 0;
+            if (m_db->addUnallocBlockFile(unallocVolObjId, NULL, current_run->len * pool_info->block_size, ranges, fileObjId, m_curImgId)) {
+                registerError();
+                tsk_fs_attr_run_free(unalloc_runs);
+                return TSK_ERR;
+            }
+
+            current_run = current_run->next;
+            ranges.clear();
+        }
+        tsk_fs_attr_run_free(unalloc_runs);
     }
-    tsk_fs_attr_run_free(unalloc_runs);
 
-    return TSK_FILTER_CONT;
+    return TSK_OK;
 }
 
 TSK_FILTER_ENUM
@@ -1141,18 +1164,20 @@ TSK_RETVAL_ENUM TskAutoDb::addUnallocSpaceToDb() {
 
     size_t numVsP = 0;
     size_t numFs = 0;
+    size_t numPool = 0;
 
     TSK_RETVAL_ENUM retFsSpace = addUnallocFsSpaceToDb(numFs);
     TSK_RETVAL_ENUM retVsSpace = addUnallocVsSpaceToDb(numVsP);
+    TSK_RETVAL_ENUM retPoolSpace = addUnallocatedPoolBlocksToDb(numPool);
 
-    //handle case when no fs and no vs partitions
+    //handle case when no fs and no vs partitions or pools
     TSK_RETVAL_ENUM retImgFile = TSK_OK;
-    if (numVsP == 0 && numFs == 0) {
+    if (numVsP == 0 && numFs == 0 && numPool == 0) {
         retImgFile = addUnallocImageSpaceToDb();
     }
     
     
-    if (retFsSpace == TSK_ERR || retVsSpace == TSK_ERR || retImgFile == TSK_ERR)
+    if (retFsSpace == TSK_ERR || retVsSpace == TSK_ERR || retPoolSpace == TSK_ERR || retImgFile == TSK_ERR)
         return TSK_ERR;
     else
         return TSK_OK;
@@ -1255,6 +1280,19 @@ TSK_RETVAL_ENUM TskAutoDb::addUnallocVsSpaceToDb(size_t & numVsP) {
                 //skip processing this vspart
                 continue;
             }
+
+            // Check if the volume contains a pool
+            bool hasPool = false;
+            for (std::map<int64_t, int64_t>::iterator iter = m_poolOffsetToParentId.begin(); iter != m_poolOffsetToParentId.end(); ++iter) {
+                if (iter->second == vsPart.objId) {
+                    hasPool = true;
+                }
+            }
+            if (hasPool) {
+                // Skip processing this vspart
+                continue;
+            }
+
         } //end checking vspart flags
 
         //get sector size and image offset from parent vs info
diff --git a/tsk/auto/tsk_auto.h b/tsk/auto/tsk_auto.h
index 4929854fd..0839e8360 100644
--- a/tsk/auto/tsk_auto.h
+++ b/tsk/auto/tsk_auto.h
@@ -262,10 +262,11 @@ class TskAuto {
 
   protected:
     TSK_IMG_INFO * m_img_info;
+    std::vector<const TSK_POOL_INFO*> m_poolInfos;
+
     bool m_internalOpen;        ///< True if m_img_info was opened in TskAuto and false if passed in
     bool m_stopAllProcessing;   ///< True if no further processing should occur
 
-
     uint8_t isNtfsSystemFiles(TSK_FS_FILE * fs_file, const char *path);
     uint8_t isFATSystemFiles(TSK_FS_FILE * fs_file);
     uint8_t isDotDir(TSK_FS_FILE * fs_file);
diff --git a/tsk/auto/tsk_case_db.h b/tsk/auto/tsk_case_db.h
index 25df18e09..422ca330d 100644
--- a/tsk/auto/tsk_case_db.h
+++ b/tsk/auto/tsk_case_db.h
@@ -154,6 +154,12 @@ class TskAutoDb:public TskAuto {
     bool m_foundStructure;  ///< Set to true when we find either a volume or file system
     bool m_attributeAdded; ///< Set to true when an attribute was added by processAttributes
 
+    // These are used to write unallocated blocks for pools at the end of the add image
+    // process. We can't load the pool_info objects directly from the database so we will
+    // store info about them here.
+    std::map<int64_t, int64_t> m_poolOffsetToParentId;
+    std::map<int64_t, int64_t> m_poolOffsetToVsId;
+
     // prevent copying until we add proper logic to handle it
     TskAutoDb(const TskAutoDb&);
     TskAutoDb & operator=(const TskAutoDb&);
@@ -186,8 +192,7 @@ class TskAutoDb:public TskAuto {
         TSK_OFF_T offset, TSK_DADDR_T addr, char *buf, size_t size,
         TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr);
     int md5HashAttr(unsigned char md5Hash[16], const TSK_FS_ATTR * fs_attr);
-    TSK_FILTER_ENUM addUnallocatedPoolBlocksToDb(const TSK_POOL_INFO * pool_info, int64_t poolObjId);
-
+    TSK_RETVAL_ENUM addUnallocatedPoolBlocksToDb(size_t & numPool);
     static TSK_WALK_RET_ENUM fsWalkUnallocBlocksCb(const TSK_FS_BLOCK *a_block, void *a_ptr);
     TSK_RETVAL_ENUM addFsInfoUnalloc(const TSK_DB_FS_INFO & dbFsInfo);
     TSK_RETVAL_ENUM addUnallocFsSpaceToDb(size_t & numFs);
-- 
GitLab