Fix use after free 99/267599/4
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 9 Dec 2021 10:42:08 +0000 (19:42 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 9 Dec 2021 10:56:27 +0000 (19:56 +0900)
When the table existence check step is failed, the function closes the db.
And then, the _recover_db() function closes the db with the same handle.
In this time, the double free occurs. This patch fixes it.

+--------------------------------------------------------------------------+
| ERROR: AddressSanitizer: heap-use-after-free on address 0x47c033e8 at    |
|        pc 0x412dd2d5 bp 0x40812174 sp 0x40812164                         |
| READ of size 4 at 0x47c033e8 thread T0                                   |
| #0 0x412dd2d2 in sqlite3SafetyCheckSickOrOk /usr/src/debug/              |
|    sqlite-3.33.0-2.34.arm/sqlite3.c:32567                                |
| #1 0x412dd2d2 in sqlite3Close /usr/src/debug/sqlite-3.33.0-2.34.arm/     |
|    sqlite3.c:162204                                                      |
| #2 0x40db45ea in _recover_db /usr/src/debug/                             |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:319               |
| #3 0x40db4c06 in _check_db_integrity /usr/src/debug/                     |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:435               |
| #4 0x40dba2ec in widget_service_check_db_integrity /usr/src/debug/       |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:447               |
| #5 0x400009d8 in main /usr/src/debug/libwidget_service-1.2.63-1.arm/tool/|
|    widget_recovery.c:45                                                  |
| #6 0x40e24c88 in __libc_start_main /usr/src/debug/glibc-2.30-2.9.arm/csu/|
|    libc-start.c:308                                                      |
+--------------------------------------------------------------------------+
| 0x47c033e8 is located 104 bytes inside of 520-byte region                |
| [0x47c03380,0x47c03588)                                                  |
| freed by thread T0 here:                                                 |
| #0 0x408f4092 in __interceptor_free (/lib/libasan.so.6+0xa1092)          |
| #1 0x41192bbc in sqlite3StatusDown /usr/src/debug/sqlite-3.33.0-2.34.arm/|
|    sqlite3.c:21425                                                       |
| #2 0x41192bbc in sqlite3_free /usr/src/debug/sqlite-3.33.0-2.34.arm/     |
|    sqlite3.c:27703                                                       |
| #3 0x41192bbc in sqlite3_free /usr/src/debug/sqlite-3.33.0-2.34.arm/     |
|    sqlite3.c:27697                                                       |
| #4 0x412dd1ae in sqlite3Close /usr/src/debug/sqlite-3.33.0-2.34.arm/     |
|    sqlite3.c:162244                                                      |
| #5 0x40db4d04 in _check_table_exist /usr/src/debug/                      |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:397               |
| #6 0x40db4d04 in _check_db_integrity /usr/src/debug/                     |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:433               |
| #7 0x40dba2ec in widget_service_check_db_integrity /usr/src/debug/       |
|    libwidget_service-1.2.63-1.arm/src/widget_service.c:447               |
| #8 0x400009d8 in main /usr/src/debug/libwidget_service-1.2.63-1.arm/tool/|
|    widget_recovery.c:45                                                  |
| #9 0x40e24c88 in __libc_start_main /usr/src/debug/glibc-2.30-2.9.arm/csu/|
|    libc-start.c:308                                                      |
+--------------------------------------------------------------------------+

Change-Id: Ic0bfb7fd4738ac0caa4d7c88e860b0eb2362f535
Signed-off-by: SukhyungKang <shine.kang@samsung.com>
src/widget_service.c

index bb69d15..d055538 100644 (file)
@@ -309,27 +309,28 @@ static int __change_own(uid_t uid, const char *path)
        return WIDGET_ERROR_NONE;
 }
 
-static int _recover_db(sqlite3 *db, const char *path, uid_t uid, bool is_init)
+static int _recover_db(const char *path, uid_t uid, bool is_init)
 {
+       sqlite3 *db;
        int ret;
        char *errmsg = NULL;
 
        _I("DB recovery process start");
-       if (db)
-               sqlite3_close(db);
-       unlink(path);
+       if (access(path, F_OK) == 0)
+               unlink(path);
 
        ret = sqlite3_open_v2(path, &db,
                        SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
                        NULL);
        if (ret != SQLITE_OK) {
                _E("Failed to open db[%d]", ret);
+               sqlite3_close_v2(db);
                unlink(path);
                return WIDGET_ERROR_FAULT;
        }
 
        ret = sqlite3_exec(db, CREATE_WIDGET_TABLE, NULL, NULL, &errmsg);
-       sqlite3_close(db);
+       sqlite3_close_v2(db);
        if (ret != SQLITE_OK) {
                _E("Failed to exec query[%d][%s]", ret, errmsg);
                sqlite3_free(errmsg);
@@ -356,8 +357,7 @@ static int _integrity_check(sqlite3 *db)
                               _check_integrity_cb, NULL, &errmsg);
        if (ret != SQLITE_OK || _is_corrupted) {
                _E("Failed to exec query[%d][%s]", ret, errmsg);
-               if (errmsg)
-                       sqlite3_free(errmsg);
+               sqlite3_free(errmsg);
                return WIDGET_ERROR_FAULT;
        }
 
@@ -378,7 +378,6 @@ static int _check_table_exist(sqlite3 *db)
        if (ret != SQLITE_OK) {
                /* LCOV_EXCL_START */
                _E("prepare error: %s", sqlite3_errmsg(db));
-               sqlite3_close_v2(db);
                return WIDGET_ERROR_FAULT;
                /* LCOV_EXCL_STOP */
        }
@@ -394,7 +393,6 @@ static int _check_table_exist(sqlite3 *db)
        sqlite3_finalize(stmt);
        if (idx != WIDGET_TBL_COUNT) {
                _E("wrong table count");
-               sqlite3_close_v2(db);
                return WIDGET_ERROR_FAULT;
        }
 
@@ -417,25 +415,23 @@ static int _check_db_integrity(uid_t uid, bool is_init)
        ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL);
        if (ret != SQLITE_OK) {
                /* LCOV_EXCL_START */
-               ret = _recover_db(db, path, uid, is_init);
-               return ret;
+               sqlite3_close_v2(db);
+               return _recover_db(path, uid, is_init);
                /* LCOV_EXCL_STOP */
        }
 
        /* check integrity */
        ret = _integrity_check(db);
        if (ret != WIDGET_ERROR_NONE) {
-               ret = _recover_db(db, path, uid, is_init);
-               return ret;
+               sqlite3_close_v2(db);
+               return _recover_db(path, uid, is_init);
        }
 
        /* check table exist */
        ret = _check_table_exist(db);
-       if (ret != WIDGET_ERROR_NONE) {
-               ret = _recover_db(db, path, uid, is_init);
-               return ret;
-       }
-       sqlite3_close(db);
+       sqlite3_close_v2(db);
+       if (ret != WIDGET_ERROR_NONE)
+               return _recover_db(path, uid, is_init);
 
        return WIDGET_ERROR_NONE;
 }