/** * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "../includes/common.h" //This PoC is only for 32-bit builds #if _32_BIT #include #include #include #define MAX_STRLEN 256 #define LOOP_COUNT 10 #define LIB_NAME "/system/lib/libandroid.so" int runDlopenDlcloseLibraryLoop(char *libName, unsigned char count) { while (count) { void *lib_handle = dlopen(libName, RTLD_NOW); if (!lib_handle) { return EXIT_FAILURE; } if (dlclose(lib_handle)) { return EXIT_FAILURE; } count--; } return EXIT_SUCCESS; } int getMemoryUsage(unsigned long *memUsage) { char cmd[MAX_STRLEN]; char buf[MAX_STRLEN]; memset(cmd, 0, MAX_STRLEN); memset(buf, 0, MAX_STRLEN); sprintf(cmd, "cat /proc/%d/maps | grep anon:linker_alloc]", getpid()); FILE *fpMem = popen(cmd, "r"); if (!fpMem) { return EXIT_FAILURE; } unsigned long totalMemUsage = 0; while (fgets(buf, MAX_STRLEN, fpMem) != NULL) { unsigned long mem1 = 0; unsigned long mem2 = 0; int numOfItemsRead = sscanf(buf, "%lx-%lx", &mem1, &mem2); if (numOfItemsRead < 2) { pclose(fpMem); return EXIT_FAILURE; } totalMemUsage += mem2 - mem1; } pclose(fpMem); *memUsage = totalMemUsage; return EXIT_SUCCESS; } #endif /* _32_BIT */ int main() { //This PoC is only for 32-bit builds #if _32_BIT /* Memory usage is expected to rise during first few dlopen-dlcose pairs */ /* due to linker initializations. Hence memory is not tracked during */ /* first few dlopen-dlcose pairs. */ if (runDlopenDlcloseLibraryLoop(LIB_NAME, LOOP_COUNT)) { return EXIT_FAILURE; } /* The linker specific initializations should be complete. Hence Memory */ /* usage is tracked from this point onwards. Further dlopen-dlcose pairs */ /* are not expected to increase memory usage */ unsigned long memUsageBefore = 0; if (getMemoryUsage(&memUsageBefore)) { return EXIT_FAILURE; } if (runDlopenDlcloseLibraryLoop(LIB_NAME, LOOP_COUNT)) { return EXIT_FAILURE; } unsigned long memUsageAfter = 0; if (getMemoryUsage(&memUsageAfter)) { return EXIT_FAILURE; } if (memUsageBefore != memUsageAfter) { return EXIT_VULNERABLE; } #endif /* _32_BIT */ return EXIT_SUCCESS; }