• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "Zygote"
18 
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <utils/misc.h>
23 #include <errno.h>
24 #include <sys/select.h>
25 
26 #include "jni.h"
27 #include <JNIHelp.h>
28 #include "android_runtime/AndroidRuntime.h"
29 
30 #ifdef HAVE_ANDROID_OS
31 #include <linux/capability.h>
32 #include <linux/prctl.h>
33 #include <sys/prctl.h>
34 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
35 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
36 #endif
37 
38 
39 namespace android {
40 
41 /*
42  * In class com.android.internal.os.ZygoteInit:
43  * private static native boolean setreuid(int ruid, int euid)
44  */
com_android_internal_os_ZygoteInit_setreuid(JNIEnv * env,jobject clazz,jint ruid,jint euid)45 static jint com_android_internal_os_ZygoteInit_setreuid(
46     JNIEnv* env, jobject clazz, jint ruid, jint euid)
47 {
48     int err;
49 
50     errno = 0;
51     err = setreuid(ruid, euid);
52 
53     //LOGI("setreuid(%d,%d) err %d errno %d", ruid, euid, err, errno);
54 
55     return errno;
56 }
57 
58 /*
59  * In class com.android.internal.os.ZygoteInit:
60  * private static native int setregid(int rgid, int egid)
61  */
com_android_internal_os_ZygoteInit_setregid(JNIEnv * env,jobject clazz,jint rgid,jint egid)62 static jint com_android_internal_os_ZygoteInit_setregid(
63     JNIEnv* env, jobject clazz, jint rgid, jint egid)
64 {
65     int err;
66 
67     errno = 0;
68     err = setregid(rgid, egid);
69 
70     //LOGI("setregid(%d,%d) err %d errno %d", rgid, egid, err, errno);
71 
72     return errno;
73 }
74 
75 /*
76  * In class com.android.internal.os.ZygoteInit:
77  * private static native int setpgid(int rgid, int egid)
78  */
com_android_internal_os_ZygoteInit_setpgid(JNIEnv * env,jobject clazz,jint pid,jint pgid)79 static jint com_android_internal_os_ZygoteInit_setpgid(
80     JNIEnv* env, jobject clazz, jint pid, jint pgid)
81 {
82     int err;
83 
84     errno = 0;
85 
86     err = setpgid(pid, pgid);
87 
88     return errno;
89 }
90 
91 /*
92  * In class com.android.internal.os.ZygoteInit:
93  * private static native int getpgid(int pid)
94  */
com_android_internal_os_ZygoteInit_getpgid(JNIEnv * env,jobject clazz,jint pid)95 static jint com_android_internal_os_ZygoteInit_getpgid(
96     JNIEnv* env, jobject clazz, jint pid)
97 {
98     pid_t ret;
99     ret = getpgid(pid);
100 
101     if (ret < 0) {
102         jniThrowIOException(env, errno);
103     }
104 
105     return ret;
106 }
107 
com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv * env,jobject clazz,jobject in,jobject out,jobject errfd)108 static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
109         jobject clazz, jobject in, jobject out, jobject errfd)
110 {
111     int fd;
112     int err;
113 
114     fd = jniGetFDFromFileDescriptor(env, in);
115 
116     if  (env->ExceptionOccurred() != NULL) {
117         return;
118     }
119 
120     do {
121         err = dup2(fd, STDIN_FILENO);
122     } while (err < 0 && errno == EINTR);
123 
124     fd = jniGetFDFromFileDescriptor(env, out);
125 
126     if  (env->ExceptionOccurred() != NULL) {
127         return;
128     }
129 
130     do {
131         err = dup2(fd, STDOUT_FILENO);
132     } while (err < 0 && errno == EINTR);
133 
134     fd = jniGetFDFromFileDescriptor(env, errfd);
135 
136     if  (env->ExceptionOccurred() != NULL) {
137         return;
138     }
139 
140     do {
141         err = dup2(fd, STDERR_FILENO);
142     } while (err < 0 && errno == EINTR);
143 }
144 
com_android_internal_os_ZygoteInit_closeDescriptor(JNIEnv * env,jobject clazz,jobject descriptor)145 static void com_android_internal_os_ZygoteInit_closeDescriptor(JNIEnv* env,
146         jobject clazz, jobject descriptor)
147 {
148     int fd;
149     int err;
150 
151     fd = jniGetFDFromFileDescriptor(env, descriptor);
152 
153     if  (env->ExceptionOccurred() != NULL) {
154         return;
155     }
156 
157     do {
158         err = close(fd);
159     } while (err < 0 && errno == EINTR);
160 
161     if (err < 0) {
162         jniThrowIOException(env, errno);
163         return;
164     }
165 }
166 
com_android_internal_os_ZygoteInit_setCloseOnExec(JNIEnv * env,jobject clazz,jobject descriptor,jboolean flag)167 static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env,
168     jobject clazz, jobject descriptor, jboolean flag)
169 {
170     int fd;
171     int err;
172     int fdFlags;
173 
174     fd = jniGetFDFromFileDescriptor(env, descriptor);
175 
176     if  (env->ExceptionOccurred() != NULL) {
177         return;
178     }
179 
180     fdFlags = fcntl(fd, F_GETFD);
181 
182     if (fdFlags < 0) {
183         jniThrowIOException(env, errno);
184         return;
185     }
186 
187     if (flag) {
188         fdFlags |= FD_CLOEXEC;
189     } else {
190         fdFlags &= ~FD_CLOEXEC;
191     }
192 
193     err = fcntl(fd, F_SETFD, fdFlags);
194 
195     if (err < 0) {
196         jniThrowIOException(env, errno);
197         return;
198     }
199 }
200 
com_android_internal_os_ZygoteInit_setCapabilities(JNIEnv * env,jobject clazz,jlong permitted,jlong effective)201 static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
202     jobject clazz, jlong permitted, jlong effective)
203 {
204 #ifdef HAVE_ANDROID_OS
205     struct __user_cap_header_struct capheader;
206     struct __user_cap_data_struct capdata;
207     int err;
208 
209     memset (&capheader, 0, sizeof(capheader));
210     memset (&capdata, 0, sizeof(capdata));
211 
212     capheader.version = _LINUX_CAPABILITY_VERSION;
213     capheader.pid = 0;
214 
215     // As of this writing, capdata is __u32, but that's expected
216     // to change...
217     capdata.effective = effective;
218     capdata.permitted = permitted;
219 
220     err = capset (&capheader, &capdata);
221 
222     if (err < 0) {
223         jniThrowIOException(env, errno);
224         return;
225     }
226 #endif /* HAVE_ANDROID_OS */
227 }
228 
com_android_internal_os_ZygoteInit_capgetPermitted(JNIEnv * env,jobject clazz,jint pid)229 static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
230     jobject clazz, jint pid)
231 {
232 #ifndef HAVE_ANDROID_OS
233     return (jlong)0;
234 #else
235     struct __user_cap_header_struct capheader;
236     struct __user_cap_data_struct capdata;
237     int err;
238 
239     memset (&capheader, 0, sizeof(capheader));
240     memset (&capdata, 0, sizeof(capdata));
241 
242     capheader.version = _LINUX_CAPABILITY_VERSION;
243     capheader.pid = pid;
244 
245     err = capget (&capheader, &capdata);
246 
247     if (err < 0) {
248         jniThrowIOException(env, errno);
249         return 0;
250     }
251 
252     return (jlong) capdata.permitted;
253 #endif /* HAVE_ANDROID_OS */
254 }
255 
com_android_internal_os_ZygoteInit_selectReadable(JNIEnv * env,jobject clazz,jobjectArray fds)256 static jint com_android_internal_os_ZygoteInit_selectReadable (
257         JNIEnv *env, jobject clazz, jobjectArray fds)
258 {
259     if (fds == NULL) {
260         jniThrowException(env, "java/lang/NullPointerException",
261             "fds == null");
262         return -1;
263     }
264 
265     jsize length = env->GetArrayLength(fds);
266     fd_set fdset;
267 
268     if (env->ExceptionOccurred() != NULL) {
269         return -1;
270     }
271 
272     FD_ZERO(&fdset);
273 
274     int nfds = 0;
275     for (jsize i = 0; i < length; i++) {
276         jobject fdObj = env->GetObjectArrayElement(fds, i);
277         if  (env->ExceptionOccurred() != NULL) {
278             return -1;
279         }
280         if (fdObj == NULL) {
281             continue;
282         }
283         int fd = jniGetFDFromFileDescriptor(env, fdObj);
284         if  (env->ExceptionOccurred() != NULL) {
285             return -1;
286         }
287 
288         FD_SET(fd, &fdset);
289 
290         if (fd >= nfds) {
291             nfds = fd + 1;
292         }
293     }
294 
295     int err;
296     do {
297         err = select (nfds, &fdset, NULL, NULL, NULL);
298     } while (err < 0 && errno == EINTR);
299 
300     if (err < 0) {
301         jniThrowIOException(env, errno);
302         return -1;
303     }
304 
305     for (jsize i = 0; i < length; i++) {
306         jobject fdObj = env->GetObjectArrayElement(fds, i);
307         if  (env->ExceptionOccurred() != NULL) {
308             return -1;
309         }
310         if (fdObj == NULL) {
311             continue;
312         }
313         int fd = jniGetFDFromFileDescriptor(env, fdObj);
314         if  (env->ExceptionOccurred() != NULL) {
315             return -1;
316         }
317         if (FD_ISSET(fd, &fdset)) {
318             return (jint)i;
319         }
320     }
321     return -1;
322 }
323 
com_android_internal_os_ZygoteInit_createFileDescriptor(JNIEnv * env,jobject clazz,jint fd)324 static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
325         JNIEnv *env, jobject clazz, jint fd)
326 {
327     return jniCreateFileDescriptor(env, fd);
328 }
329 
330 /*
331  * JNI registration.
332  */
333 static JNINativeMethod gMethods[] = {
334     /* name, signature, funcPtr */
335     { "setreuid", "(II)I",
336       (void*) com_android_internal_os_ZygoteInit_setreuid },
337     { "setregid", "(II)I",
338       (void*) com_android_internal_os_ZygoteInit_setregid },
339     { "setpgid", "(II)I",
340       (void *) com_android_internal_os_ZygoteInit_setpgid },
341     { "getpgid", "(I)I",
342       (void *) com_android_internal_os_ZygoteInit_getpgid },
343     { "reopenStdio",
344         "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
345         "Ljava/io/FileDescriptor;)V",
346             (void *) com_android_internal_os_ZygoteInit_reopenStdio},
347     { "closeDescriptor", "(Ljava/io/FileDescriptor;)V",
348         (void *) com_android_internal_os_ZygoteInit_closeDescriptor},
349     { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
350         (void *)  com_android_internal_os_ZygoteInit_setCloseOnExec},
351     { "setCapabilities", "(JJ)V",
352         (void *) com_android_internal_os_ZygoteInit_setCapabilities },
353     { "capgetPermitted", "(I)J",
354         (void *) com_android_internal_os_ZygoteInit_capgetPermitted },
355     { "selectReadable", "([Ljava/io/FileDescriptor;)I",
356         (void *) com_android_internal_os_ZygoteInit_selectReadable },
357     { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
358         (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
359 };
register_com_android_internal_os_ZygoteInit(JNIEnv * env)360 int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
361 {
362     return AndroidRuntime::registerNativeMethods(env,
363             "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods));
364 }
365 
366 }; // namespace android
367 
368