blob: 44452f00109097b16dcb76d958d7931193d67402 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Nick Kralevichb3c4a0b2013-02-28 16:49:43 -080030#include <sys/capability.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031#include <sys/prctl.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
33namespace android {
34
35/*
36 * In class com.android.internal.os.ZygoteInit:
37 * private static native boolean setreuid(int ruid, int euid)
38 */
39static jint com_android_internal_os_ZygoteInit_setreuid(
40 JNIEnv* env, jobject clazz, jint ruid, jint euid)
41{
Andy McFadden05554a42011-01-10 11:22:43 -080042 if (setreuid(ruid, euid) < 0) {
43 return errno;
44 }
45 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046}
47
48/*
49 * In class com.android.internal.os.ZygoteInit:
50 * private static native int setregid(int rgid, int egid)
51 */
52static jint com_android_internal_os_ZygoteInit_setregid(
53 JNIEnv* env, jobject clazz, jint rgid, jint egid)
54{
Andy McFadden05554a42011-01-10 11:22:43 -080055 if (setregid(rgid, egid) < 0) {
56 return errno;
57 }
58 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059}
60
61/*
62 * In class com.android.internal.os.ZygoteInit:
63 * private static native int setpgid(int rgid, int egid)
64 */
65static jint com_android_internal_os_ZygoteInit_setpgid(
66 JNIEnv* env, jobject clazz, jint pid, jint pgid)
67{
Andy McFadden05554a42011-01-10 11:22:43 -080068 if (setpgid(pid, pgid) < 0) {
69 return errno;
70 }
71 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072}
73
74/*
75 * In class com.android.internal.os.ZygoteInit:
76 * private static native int getpgid(int pid)
77 */
78static jint com_android_internal_os_ZygoteInit_getpgid(
79 JNIEnv* env, jobject clazz, jint pid)
80{
81 pid_t ret;
82 ret = getpgid(pid);
83
84 if (ret < 0) {
85 jniThrowIOException(env, errno);
86 }
87
88 return ret;
89}
90
Elliott Hughes69a017b2011-04-08 14:10:28 -070091static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 jobject clazz, jobject in, jobject out, jobject errfd)
93{
94 int fd;
95 int err;
96
97 fd = jniGetFDFromFileDescriptor(env, in);
98
99 if (env->ExceptionOccurred() != NULL) {
100 return;
101 }
102
103 do {
104 err = dup2(fd, STDIN_FILENO);
105 } while (err < 0 && errno == EINTR);
106
107 fd = jniGetFDFromFileDescriptor(env, out);
108
109 if (env->ExceptionOccurred() != NULL) {
110 return;
111 }
112
113 do {
114 err = dup2(fd, STDOUT_FILENO);
115 } while (err < 0 && errno == EINTR);
116
117 fd = jniGetFDFromFileDescriptor(env, errfd);
118
119 if (env->ExceptionOccurred() != NULL) {
120 return;
121 }
122
123 do {
124 err = dup2(fd, STDERR_FILENO);
125 } while (err < 0 && errno == EINTR);
126}
127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env,
129 jobject clazz, jobject descriptor, jboolean flag)
130{
131 int fd;
132 int err;
133 int fdFlags;
134
135 fd = jniGetFDFromFileDescriptor(env, descriptor);
136
137 if (env->ExceptionOccurred() != NULL) {
138 return;
139 }
140
141 fdFlags = fcntl(fd, F_GETFD);
142
143 if (fdFlags < 0) {
144 jniThrowIOException(env, errno);
145 return;
146 }
147
148 if (flag) {
149 fdFlags |= FD_CLOEXEC;
150 } else {
151 fdFlags &= ~FD_CLOEXEC;
152 }
153
154 err = fcntl(fd, F_SETFD, fdFlags);
155
156 if (err < 0) {
157 jniThrowIOException(env, errno);
158 return;
159 }
160}
161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
163 jobject clazz, jint pid)
164{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 struct __user_cap_header_struct capheader;
166 struct __user_cap_data_struct capdata;
167 int err;
168
169 memset (&capheader, 0, sizeof(capheader));
170 memset (&capdata, 0, sizeof(capdata));
171
172 capheader.version = _LINUX_CAPABILITY_VERSION;
173 capheader.pid = pid;
174
Elliott Hughes69a017b2011-04-08 14:10:28 -0700175 err = capget (&capheader, &capdata);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176
177 if (err < 0) {
178 jniThrowIOException(env, errno);
179 return 0;
180 }
181
182 return (jlong) capdata.permitted;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183}
184
185static jint com_android_internal_os_ZygoteInit_selectReadable (
Elliott Hughes69a017b2011-04-08 14:10:28 -0700186 JNIEnv *env, jobject clazz, jobjectArray fds)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187{
188 if (fds == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700189 jniThrowNullPointerException(env, "fds == null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 return -1;
191 }
192
193 jsize length = env->GetArrayLength(fds);
194 fd_set fdset;
195
196 if (env->ExceptionOccurred() != NULL) {
197 return -1;
198 }
199
200 FD_ZERO(&fdset);
201
202 int nfds = 0;
203 for (jsize i = 0; i < length; i++) {
204 jobject fdObj = env->GetObjectArrayElement(fds, i);
205 if (env->ExceptionOccurred() != NULL) {
206 return -1;
207 }
208 if (fdObj == NULL) {
209 continue;
210 }
211 int fd = jniGetFDFromFileDescriptor(env, fdObj);
212 if (env->ExceptionOccurred() != NULL) {
213 return -1;
214 }
215
216 FD_SET(fd, &fdset);
217
218 if (fd >= nfds) {
219 nfds = fd + 1;
220 }
221 }
222
223 int err;
224 do {
225 err = select (nfds, &fdset, NULL, NULL, NULL);
226 } while (err < 0 && errno == EINTR);
227
228 if (err < 0) {
229 jniThrowIOException(env, errno);
230 return -1;
231 }
232
233 for (jsize i = 0; i < length; i++) {
234 jobject fdObj = env->GetObjectArrayElement(fds, i);
235 if (env->ExceptionOccurred() != NULL) {
236 return -1;
237 }
238 if (fdObj == NULL) {
239 continue;
240 }
241 int fd = jniGetFDFromFileDescriptor(env, fdObj);
242 if (env->ExceptionOccurred() != NULL) {
243 return -1;
244 }
245 if (FD_ISSET(fd, &fdset)) {
246 return (jint)i;
247 }
248 }
249 return -1;
250}
251
252static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
Elliott Hughes69a017b2011-04-08 14:10:28 -0700253 JNIEnv *env, jobject clazz, jint fd)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254{
255 return jniCreateFileDescriptor(env, fd);
256}
257
258/*
259 * JNI registration.
260 */
261static JNINativeMethod gMethods[] = {
262 /* name, signature, funcPtr */
263 { "setreuid", "(II)I",
264 (void*) com_android_internal_os_ZygoteInit_setreuid },
265 { "setregid", "(II)I",
266 (void*) com_android_internal_os_ZygoteInit_setregid },
267 { "setpgid", "(II)I",
268 (void *) com_android_internal_os_ZygoteInit_setpgid },
269 { "getpgid", "(I)I",
270 (void *) com_android_internal_os_ZygoteInit_getpgid },
Elliott Hughes69a017b2011-04-08 14:10:28 -0700271 { "reopenStdio",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
Elliott Hughes69a017b2011-04-08 14:10:28 -0700273 "Ljava/io/FileDescriptor;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 (void *) com_android_internal_os_ZygoteInit_reopenStdio},
Elliott Hughes69a017b2011-04-08 14:10:28 -0700275 { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
Elliott Hughes69a017b2011-04-08 14:10:28 -0700277 { "capgetPermitted", "(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 (void *) com_android_internal_os_ZygoteInit_capgetPermitted },
279 { "selectReadable", "([Ljava/io/FileDescriptor;)I",
280 (void *) com_android_internal_os_ZygoteInit_selectReadable },
281 { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
282 (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
283};
284int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
285{
286 return AndroidRuntime::registerNativeMethods(env,
287 "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods));
288}
289
290}; // namespace android