1*2d543d20SAndroid Build Coastguard Worker #include <sys/syscall.h>
2*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
3*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
4*2d543d20SAndroid Build Coastguard Worker #include <pthread.h>
5*2d543d20SAndroid Build Coastguard Worker #include <string.h>
6*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
8*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
9*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
10*2d543d20SAndroid Build Coastguard Worker #include "policy.h"
11*2d543d20SAndroid Build Coastguard Worker
12*2d543d20SAndroid Build Coastguard Worker #define UNSET (char *) -1
13*2d543d20SAndroid Build Coastguard Worker
14*2d543d20SAndroid Build Coastguard Worker /* Cached values so that when a thread calls set*con() then gen*con(), the value
15*2d543d20SAndroid Build Coastguard Worker * which was set is directly returned.
16*2d543d20SAndroid Build Coastguard Worker */
17*2d543d20SAndroid Build Coastguard Worker static __thread char *prev_current = UNSET;
18*2d543d20SAndroid Build Coastguard Worker static __thread char *prev_exec = UNSET;
19*2d543d20SAndroid Build Coastguard Worker static __thread char *prev_fscreate = UNSET;
20*2d543d20SAndroid Build Coastguard Worker static __thread char *prev_keycreate = UNSET;
21*2d543d20SAndroid Build Coastguard Worker static __thread char *prev_sockcreate = UNSET;
22*2d543d20SAndroid Build Coastguard Worker
23*2d543d20SAndroid Build Coastguard Worker static pthread_once_t once = PTHREAD_ONCE_INIT;
24*2d543d20SAndroid Build Coastguard Worker static pthread_key_t destructor_key;
25*2d543d20SAndroid Build Coastguard Worker static int destructor_key_initialized = 0;
26*2d543d20SAndroid Build Coastguard Worker static __thread char destructor_initialized;
27*2d543d20SAndroid Build Coastguard Worker
28*2d543d20SAndroid Build Coastguard Worker /* Bionic and glibc >= 2.30 declare gettid() system call wrapper in unistd.h and
29*2d543d20SAndroid Build Coastguard Worker * has a definition for it */
30*2d543d20SAndroid Build Coastguard Worker #ifdef __BIONIC__
31*2d543d20SAndroid Build Coastguard Worker #define HAVE_GETTID 1
32*2d543d20SAndroid Build Coastguard Worker #elif !defined(__GLIBC_PREREQ)
33*2d543d20SAndroid Build Coastguard Worker #define HAVE_GETTID 0
34*2d543d20SAndroid Build Coastguard Worker #elif !__GLIBC_PREREQ(2,30)
35*2d543d20SAndroid Build Coastguard Worker #define HAVE_GETTID 0
36*2d543d20SAndroid Build Coastguard Worker #else
37*2d543d20SAndroid Build Coastguard Worker #define HAVE_GETTID 1
38*2d543d20SAndroid Build Coastguard Worker #endif
39*2d543d20SAndroid Build Coastguard Worker
selinux_gettid(void)40*2d543d20SAndroid Build Coastguard Worker static pid_t selinux_gettid(void)
41*2d543d20SAndroid Build Coastguard Worker {
42*2d543d20SAndroid Build Coastguard Worker #if HAVE_GETTID
43*2d543d20SAndroid Build Coastguard Worker return gettid();
44*2d543d20SAndroid Build Coastguard Worker #else
45*2d543d20SAndroid Build Coastguard Worker return syscall(__NR_gettid);
46*2d543d20SAndroid Build Coastguard Worker #endif
47*2d543d20SAndroid Build Coastguard Worker }
48*2d543d20SAndroid Build Coastguard Worker
procattr_thread_destructor(void * unused)49*2d543d20SAndroid Build Coastguard Worker static void procattr_thread_destructor(void __attribute__((unused)) *unused)
50*2d543d20SAndroid Build Coastguard Worker {
51*2d543d20SAndroid Build Coastguard Worker if (prev_current != UNSET)
52*2d543d20SAndroid Build Coastguard Worker free(prev_current);
53*2d543d20SAndroid Build Coastguard Worker if (prev_exec != UNSET)
54*2d543d20SAndroid Build Coastguard Worker free(prev_exec);
55*2d543d20SAndroid Build Coastguard Worker if (prev_fscreate != UNSET)
56*2d543d20SAndroid Build Coastguard Worker free(prev_fscreate);
57*2d543d20SAndroid Build Coastguard Worker if (prev_keycreate != UNSET)
58*2d543d20SAndroid Build Coastguard Worker free(prev_keycreate);
59*2d543d20SAndroid Build Coastguard Worker if (prev_sockcreate != UNSET)
60*2d543d20SAndroid Build Coastguard Worker free(prev_sockcreate);
61*2d543d20SAndroid Build Coastguard Worker }
62*2d543d20SAndroid Build Coastguard Worker
63*2d543d20SAndroid Build Coastguard Worker void __attribute__((destructor)) procattr_destructor(void);
64*2d543d20SAndroid Build Coastguard Worker
procattr_destructor(void)65*2d543d20SAndroid Build Coastguard Worker void __attribute__((destructor)) procattr_destructor(void)
66*2d543d20SAndroid Build Coastguard Worker {
67*2d543d20SAndroid Build Coastguard Worker if (destructor_key_initialized)
68*2d543d20SAndroid Build Coastguard Worker __selinux_key_delete(destructor_key);
69*2d543d20SAndroid Build Coastguard Worker }
70*2d543d20SAndroid Build Coastguard Worker
init_thread_destructor(void)71*2d543d20SAndroid Build Coastguard Worker static inline void init_thread_destructor(void)
72*2d543d20SAndroid Build Coastguard Worker {
73*2d543d20SAndroid Build Coastguard Worker if (destructor_initialized == 0) {
74*2d543d20SAndroid Build Coastguard Worker __selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size);
75*2d543d20SAndroid Build Coastguard Worker destructor_initialized = 1;
76*2d543d20SAndroid Build Coastguard Worker }
77*2d543d20SAndroid Build Coastguard Worker }
78*2d543d20SAndroid Build Coastguard Worker
init_procattr(void)79*2d543d20SAndroid Build Coastguard Worker static void init_procattr(void)
80*2d543d20SAndroid Build Coastguard Worker {
81*2d543d20SAndroid Build Coastguard Worker if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) {
82*2d543d20SAndroid Build Coastguard Worker destructor_key_initialized = 1;
83*2d543d20SAndroid Build Coastguard Worker }
84*2d543d20SAndroid Build Coastguard Worker }
85*2d543d20SAndroid Build Coastguard Worker
openattr(pid_t pid,const char * attr,int flags)86*2d543d20SAndroid Build Coastguard Worker static int openattr(pid_t pid, const char *attr, int flags)
87*2d543d20SAndroid Build Coastguard Worker {
88*2d543d20SAndroid Build Coastguard Worker int fd, rc;
89*2d543d20SAndroid Build Coastguard Worker char *path;
90*2d543d20SAndroid Build Coastguard Worker pid_t tid;
91*2d543d20SAndroid Build Coastguard Worker
92*2d543d20SAndroid Build Coastguard Worker if (pid > 0) {
93*2d543d20SAndroid Build Coastguard Worker rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
94*2d543d20SAndroid Build Coastguard Worker } else if (pid == 0) {
95*2d543d20SAndroid Build Coastguard Worker rc = asprintf(&path, "/proc/thread-self/attr/%s", attr);
96*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
97*2d543d20SAndroid Build Coastguard Worker return -1;
98*2d543d20SAndroid Build Coastguard Worker fd = open(path, flags | O_CLOEXEC);
99*2d543d20SAndroid Build Coastguard Worker if (fd >= 0 || errno != ENOENT)
100*2d543d20SAndroid Build Coastguard Worker goto out;
101*2d543d20SAndroid Build Coastguard Worker free(path);
102*2d543d20SAndroid Build Coastguard Worker tid = selinux_gettid();
103*2d543d20SAndroid Build Coastguard Worker rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
104*2d543d20SAndroid Build Coastguard Worker } else {
105*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
106*2d543d20SAndroid Build Coastguard Worker return -1;
107*2d543d20SAndroid Build Coastguard Worker }
108*2d543d20SAndroid Build Coastguard Worker if (rc < 0)
109*2d543d20SAndroid Build Coastguard Worker return -1;
110*2d543d20SAndroid Build Coastguard Worker
111*2d543d20SAndroid Build Coastguard Worker fd = open(path, flags | O_CLOEXEC);
112*2d543d20SAndroid Build Coastguard Worker out:
113*2d543d20SAndroid Build Coastguard Worker free(path);
114*2d543d20SAndroid Build Coastguard Worker return fd;
115*2d543d20SAndroid Build Coastguard Worker }
116*2d543d20SAndroid Build Coastguard Worker
getprocattrcon_raw(char ** context,pid_t pid,const char * attr,const char * prev_context)117*2d543d20SAndroid Build Coastguard Worker static int getprocattrcon_raw(char **context, pid_t pid, const char *attr,
118*2d543d20SAndroid Build Coastguard Worker const char *prev_context)
119*2d543d20SAndroid Build Coastguard Worker {
120*2d543d20SAndroid Build Coastguard Worker char *buf;
121*2d543d20SAndroid Build Coastguard Worker size_t size;
122*2d543d20SAndroid Build Coastguard Worker int fd;
123*2d543d20SAndroid Build Coastguard Worker ssize_t ret;
124*2d543d20SAndroid Build Coastguard Worker int errno_hold;
125*2d543d20SAndroid Build Coastguard Worker
126*2d543d20SAndroid Build Coastguard Worker __selinux_once(once, init_procattr);
127*2d543d20SAndroid Build Coastguard Worker init_thread_destructor();
128*2d543d20SAndroid Build Coastguard Worker
129*2d543d20SAndroid Build Coastguard Worker if (prev_context && prev_context != UNSET) {
130*2d543d20SAndroid Build Coastguard Worker *context = strdup(prev_context);
131*2d543d20SAndroid Build Coastguard Worker if (!(*context)) {
132*2d543d20SAndroid Build Coastguard Worker return -1;
133*2d543d20SAndroid Build Coastguard Worker }
134*2d543d20SAndroid Build Coastguard Worker return 0;
135*2d543d20SAndroid Build Coastguard Worker }
136*2d543d20SAndroid Build Coastguard Worker
137*2d543d20SAndroid Build Coastguard Worker fd = openattr(pid, attr, O_RDONLY | O_CLOEXEC);
138*2d543d20SAndroid Build Coastguard Worker if (fd < 0)
139*2d543d20SAndroid Build Coastguard Worker return -1;
140*2d543d20SAndroid Build Coastguard Worker
141*2d543d20SAndroid Build Coastguard Worker size = selinux_page_size;
142*2d543d20SAndroid Build Coastguard Worker buf = malloc(size);
143*2d543d20SAndroid Build Coastguard Worker if (!buf) {
144*2d543d20SAndroid Build Coastguard Worker ret = -1;
145*2d543d20SAndroid Build Coastguard Worker goto out;
146*2d543d20SAndroid Build Coastguard Worker }
147*2d543d20SAndroid Build Coastguard Worker memset(buf, 0, size);
148*2d543d20SAndroid Build Coastguard Worker
149*2d543d20SAndroid Build Coastguard Worker do {
150*2d543d20SAndroid Build Coastguard Worker ret = read(fd, buf, size - 1);
151*2d543d20SAndroid Build Coastguard Worker } while (ret < 0 && errno == EINTR);
152*2d543d20SAndroid Build Coastguard Worker if (ret < 0)
153*2d543d20SAndroid Build Coastguard Worker goto out2;
154*2d543d20SAndroid Build Coastguard Worker
155*2d543d20SAndroid Build Coastguard Worker if (ret == 0) {
156*2d543d20SAndroid Build Coastguard Worker *context = NULL;
157*2d543d20SAndroid Build Coastguard Worker goto out2;
158*2d543d20SAndroid Build Coastguard Worker }
159*2d543d20SAndroid Build Coastguard Worker
160*2d543d20SAndroid Build Coastguard Worker *context = strdup(buf);
161*2d543d20SAndroid Build Coastguard Worker if (!(*context)) {
162*2d543d20SAndroid Build Coastguard Worker ret = -1;
163*2d543d20SAndroid Build Coastguard Worker goto out2;
164*2d543d20SAndroid Build Coastguard Worker }
165*2d543d20SAndroid Build Coastguard Worker ret = 0;
166*2d543d20SAndroid Build Coastguard Worker out2:
167*2d543d20SAndroid Build Coastguard Worker free(buf);
168*2d543d20SAndroid Build Coastguard Worker out:
169*2d543d20SAndroid Build Coastguard Worker errno_hold = errno;
170*2d543d20SAndroid Build Coastguard Worker close(fd);
171*2d543d20SAndroid Build Coastguard Worker errno = errno_hold;
172*2d543d20SAndroid Build Coastguard Worker return ret;
173*2d543d20SAndroid Build Coastguard Worker }
174*2d543d20SAndroid Build Coastguard Worker
getprocattrcon(char ** context,pid_t pid,const char * attr,const char * prev_context)175*2d543d20SAndroid Build Coastguard Worker static int getprocattrcon(char **context, pid_t pid, const char *attr,
176*2d543d20SAndroid Build Coastguard Worker const char *prev_context)
177*2d543d20SAndroid Build Coastguard Worker {
178*2d543d20SAndroid Build Coastguard Worker int ret;
179*2d543d20SAndroid Build Coastguard Worker char * rcontext;
180*2d543d20SAndroid Build Coastguard Worker
181*2d543d20SAndroid Build Coastguard Worker ret = getprocattrcon_raw(&rcontext, pid, attr, prev_context);
182*2d543d20SAndroid Build Coastguard Worker
183*2d543d20SAndroid Build Coastguard Worker if (!ret) {
184*2d543d20SAndroid Build Coastguard Worker ret = selinux_raw_to_trans_context(rcontext, context);
185*2d543d20SAndroid Build Coastguard Worker freecon(rcontext);
186*2d543d20SAndroid Build Coastguard Worker }
187*2d543d20SAndroid Build Coastguard Worker
188*2d543d20SAndroid Build Coastguard Worker return ret;
189*2d543d20SAndroid Build Coastguard Worker }
190*2d543d20SAndroid Build Coastguard Worker
setprocattrcon_raw(const char * context,const char * attr,char ** prev_context)191*2d543d20SAndroid Build Coastguard Worker static int setprocattrcon_raw(const char *context, const char *attr,
192*2d543d20SAndroid Build Coastguard Worker char **prev_context)
193*2d543d20SAndroid Build Coastguard Worker {
194*2d543d20SAndroid Build Coastguard Worker int fd;
195*2d543d20SAndroid Build Coastguard Worker ssize_t ret;
196*2d543d20SAndroid Build Coastguard Worker int errno_hold;
197*2d543d20SAndroid Build Coastguard Worker char *context2 = NULL;
198*2d543d20SAndroid Build Coastguard Worker
199*2d543d20SAndroid Build Coastguard Worker __selinux_once(once, init_procattr);
200*2d543d20SAndroid Build Coastguard Worker init_thread_destructor();
201*2d543d20SAndroid Build Coastguard Worker
202*2d543d20SAndroid Build Coastguard Worker if (!context && !*prev_context)
203*2d543d20SAndroid Build Coastguard Worker return 0;
204*2d543d20SAndroid Build Coastguard Worker if (context && *prev_context && *prev_context != UNSET
205*2d543d20SAndroid Build Coastguard Worker && !strcmp(context, *prev_context))
206*2d543d20SAndroid Build Coastguard Worker return 0;
207*2d543d20SAndroid Build Coastguard Worker
208*2d543d20SAndroid Build Coastguard Worker fd = openattr(0, attr, O_RDWR | O_CLOEXEC);
209*2d543d20SAndroid Build Coastguard Worker if (fd < 0)
210*2d543d20SAndroid Build Coastguard Worker return -1;
211*2d543d20SAndroid Build Coastguard Worker if (context) {
212*2d543d20SAndroid Build Coastguard Worker ret = -1;
213*2d543d20SAndroid Build Coastguard Worker context2 = strdup(context);
214*2d543d20SAndroid Build Coastguard Worker if (!context2)
215*2d543d20SAndroid Build Coastguard Worker goto out;
216*2d543d20SAndroid Build Coastguard Worker do {
217*2d543d20SAndroid Build Coastguard Worker ret = write(fd, context2, strlen(context2) + 1);
218*2d543d20SAndroid Build Coastguard Worker } while (ret < 0 && errno == EINTR);
219*2d543d20SAndroid Build Coastguard Worker } else {
220*2d543d20SAndroid Build Coastguard Worker do {
221*2d543d20SAndroid Build Coastguard Worker ret = write(fd, NULL, 0); /* clear */
222*2d543d20SAndroid Build Coastguard Worker } while (ret < 0 && errno == EINTR);
223*2d543d20SAndroid Build Coastguard Worker }
224*2d543d20SAndroid Build Coastguard Worker out:
225*2d543d20SAndroid Build Coastguard Worker errno_hold = errno;
226*2d543d20SAndroid Build Coastguard Worker close(fd);
227*2d543d20SAndroid Build Coastguard Worker errno = errno_hold;
228*2d543d20SAndroid Build Coastguard Worker if (ret < 0) {
229*2d543d20SAndroid Build Coastguard Worker free(context2);
230*2d543d20SAndroid Build Coastguard Worker return -1;
231*2d543d20SAndroid Build Coastguard Worker } else {
232*2d543d20SAndroid Build Coastguard Worker if (*prev_context != UNSET)
233*2d543d20SAndroid Build Coastguard Worker free(*prev_context);
234*2d543d20SAndroid Build Coastguard Worker *prev_context = context2;
235*2d543d20SAndroid Build Coastguard Worker return 0;
236*2d543d20SAndroid Build Coastguard Worker }
237*2d543d20SAndroid Build Coastguard Worker }
238*2d543d20SAndroid Build Coastguard Worker
setprocattrcon(const char * context,const char * attr,char ** prev_context)239*2d543d20SAndroid Build Coastguard Worker static int setprocattrcon(const char *context, const char *attr,
240*2d543d20SAndroid Build Coastguard Worker char **prev_context)
241*2d543d20SAndroid Build Coastguard Worker {
242*2d543d20SAndroid Build Coastguard Worker int ret;
243*2d543d20SAndroid Build Coastguard Worker char * rcontext;
244*2d543d20SAndroid Build Coastguard Worker
245*2d543d20SAndroid Build Coastguard Worker if (selinux_trans_to_raw_context(context, &rcontext))
246*2d543d20SAndroid Build Coastguard Worker return -1;
247*2d543d20SAndroid Build Coastguard Worker
248*2d543d20SAndroid Build Coastguard Worker ret = setprocattrcon_raw(rcontext, attr, prev_context);
249*2d543d20SAndroid Build Coastguard Worker
250*2d543d20SAndroid Build Coastguard Worker freecon(rcontext);
251*2d543d20SAndroid Build Coastguard Worker
252*2d543d20SAndroid Build Coastguard Worker return ret;
253*2d543d20SAndroid Build Coastguard Worker }
254*2d543d20SAndroid Build Coastguard Worker
255*2d543d20SAndroid Build Coastguard Worker #define getselfattr_def(fn, attr, prev_context) \
256*2d543d20SAndroid Build Coastguard Worker int get##fn##_raw(char **c) \
257*2d543d20SAndroid Build Coastguard Worker { \
258*2d543d20SAndroid Build Coastguard Worker return getprocattrcon_raw(c, 0, attr, prev_context); \
259*2d543d20SAndroid Build Coastguard Worker } \
260*2d543d20SAndroid Build Coastguard Worker int get##fn(char **c) \
261*2d543d20SAndroid Build Coastguard Worker { \
262*2d543d20SAndroid Build Coastguard Worker return getprocattrcon(c, 0, attr, prev_context); \
263*2d543d20SAndroid Build Coastguard Worker }
264*2d543d20SAndroid Build Coastguard Worker
265*2d543d20SAndroid Build Coastguard Worker #define setselfattr_def(fn, attr, prev_context) \
266*2d543d20SAndroid Build Coastguard Worker int set##fn##_raw(const char * c) \
267*2d543d20SAndroid Build Coastguard Worker { \
268*2d543d20SAndroid Build Coastguard Worker return setprocattrcon_raw(c, attr, &prev_context); \
269*2d543d20SAndroid Build Coastguard Worker } \
270*2d543d20SAndroid Build Coastguard Worker int set##fn(const char * c) \
271*2d543d20SAndroid Build Coastguard Worker { \
272*2d543d20SAndroid Build Coastguard Worker return setprocattrcon(c, attr, &prev_context); \
273*2d543d20SAndroid Build Coastguard Worker }
274*2d543d20SAndroid Build Coastguard Worker
275*2d543d20SAndroid Build Coastguard Worker #define all_selfattr_def(fn, attr, prev_context) \
276*2d543d20SAndroid Build Coastguard Worker getselfattr_def(fn, attr, prev_context) \
277*2d543d20SAndroid Build Coastguard Worker setselfattr_def(fn, attr, prev_context)
278*2d543d20SAndroid Build Coastguard Worker
279*2d543d20SAndroid Build Coastguard Worker all_selfattr_def(con, "current", prev_current)
280*2d543d20SAndroid Build Coastguard Worker getselfattr_def(prevcon, "prev", NULL)
281*2d543d20SAndroid Build Coastguard Worker all_selfattr_def(execcon, "exec", prev_exec)
282*2d543d20SAndroid Build Coastguard Worker all_selfattr_def(fscreatecon, "fscreate", prev_fscreate)
283*2d543d20SAndroid Build Coastguard Worker all_selfattr_def(sockcreatecon, "sockcreate", prev_sockcreate)
284*2d543d20SAndroid Build Coastguard Worker all_selfattr_def(keycreatecon, "keycreate", prev_keycreate)
285*2d543d20SAndroid Build Coastguard Worker
getpidcon_raw(pid_t pid,char ** c)286*2d543d20SAndroid Build Coastguard Worker int getpidcon_raw(pid_t pid, char **c)
287*2d543d20SAndroid Build Coastguard Worker {
288*2d543d20SAndroid Build Coastguard Worker if (pid <= 0) {
289*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
290*2d543d20SAndroid Build Coastguard Worker return -1;
291*2d543d20SAndroid Build Coastguard Worker }
292*2d543d20SAndroid Build Coastguard Worker return getprocattrcon_raw(c, pid, "current", NULL);
293*2d543d20SAndroid Build Coastguard Worker }
294*2d543d20SAndroid Build Coastguard Worker
getpidcon(pid_t pid,char ** c)295*2d543d20SAndroid Build Coastguard Worker int getpidcon(pid_t pid, char **c)
296*2d543d20SAndroid Build Coastguard Worker {
297*2d543d20SAndroid Build Coastguard Worker if (pid <= 0) {
298*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
299*2d543d20SAndroid Build Coastguard Worker return -1;
300*2d543d20SAndroid Build Coastguard Worker }
301*2d543d20SAndroid Build Coastguard Worker return getprocattrcon(c, pid, "current", NULL);
302*2d543d20SAndroid Build Coastguard Worker }
303*2d543d20SAndroid Build Coastguard Worker
getpidprevcon_raw(pid_t pid,char ** c)304*2d543d20SAndroid Build Coastguard Worker int getpidprevcon_raw(pid_t pid, char **c)
305*2d543d20SAndroid Build Coastguard Worker {
306*2d543d20SAndroid Build Coastguard Worker if (pid <= 0) {
307*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
308*2d543d20SAndroid Build Coastguard Worker return -1;
309*2d543d20SAndroid Build Coastguard Worker }
310*2d543d20SAndroid Build Coastguard Worker return getprocattrcon_raw(c, pid, "prev", NULL);
311*2d543d20SAndroid Build Coastguard Worker }
312*2d543d20SAndroid Build Coastguard Worker
getpidprevcon(pid_t pid,char ** c)313*2d543d20SAndroid Build Coastguard Worker int getpidprevcon(pid_t pid, char **c)
314*2d543d20SAndroid Build Coastguard Worker {
315*2d543d20SAndroid Build Coastguard Worker if (pid <= 0) {
316*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
317*2d543d20SAndroid Build Coastguard Worker return -1;
318*2d543d20SAndroid Build Coastguard Worker }
319*2d543d20SAndroid Build Coastguard Worker return getprocattrcon(c, pid, "prev", NULL);
320*2d543d20SAndroid Build Coastguard Worker }
321