blob: 7e5dedecbdc6402d466ab8fa63b8992ae85f88e5 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030#include <linux/capability.h>
31#include <linux/prctl.h>
32#include <sys/prctl.h>
33extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
34extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
36
37namespace android {
38
39/*
40 * In class com.android.internal.os.ZygoteInit:
41 * private static native boolean setreuid(int ruid, int euid)
42 */
43static jint com_android_internal_os_ZygoteInit_setreuid(
44 JNIEnv* env, jobject clazz, jint ruid, jint euid)
45{
Andy McFadden05554a42011-01-10 11:22:43 -080046 if (setreuid(ruid, euid) < 0) {
47 return errno;
48 }
49 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050}
51
52/*
53 * In class com.android.internal.os.ZygoteInit:
54 * private static native int setregid(int rgid, int egid)
55 */
56static jint com_android_internal_os_ZygoteInit_setregid(
57 JNIEnv* env, jobject clazz, jint rgid, jint egid)
58{
Andy McFadden05554a42011-01-10 11:22:43 -080059 if (setregid(rgid, egid) < 0) {
60 return errno;
61 }
62 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063}
64
65/*
66 * In class com.android.internal.os.ZygoteInit:
67 * private static native int setpgid(int rgid, int egid)
68 */
69static jint com_android_internal_os_ZygoteInit_setpgid(
70 JNIEnv* env, jobject clazz, jint pid, jint pgid)
71{
Andy McFadden05554a42011-01-10 11:22:43 -080072 if (setpgid(pid, pgid) < 0) {
73 return errno;
74 }
75 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076}
77
78/*
79 * In class com.android.internal.os.ZygoteInit:
80 * private static native int getpgid(int pid)
81 */
82static jint com_android_internal_os_ZygoteInit_getpgid(
83 JNIEnv* env, jobject clazz, jint pid)
84{
85 pid_t ret;
86 ret = getpgid(pid);
87
88 if (ret < 0) {
89 jniThrowIOException(env, errno);
90 }
91
92 return ret;
93}
94
Elliott Hughes69a017b2011-04-08 14:10:28 -070095static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 jobject clazz, jobject in, jobject out, jobject errfd)
97{
98 int fd;
99 int err;
100
101 fd = jniGetFDFromFileDescriptor(env, in);
102
103 if (env->ExceptionOccurred() != NULL) {
104 return;
105 }
106
107 do {
108 err = dup2(fd, STDIN_FILENO);
109 } while (err < 0 && errno == EINTR);
110
111 fd = jniGetFDFromFileDescriptor(env, out);
112
113 if (env->ExceptionOccurred() != NULL) {
114 return;
115 }
116
117 do {
118 err = dup2(fd, STDOUT_FILENO);
119 } while (err < 0 && errno == EINTR);
120
121 fd = jniGetFDFromFileDescriptor(env, errfd);
122
123 if (env->ExceptionOccurred() != NULL) {
124 return;
125 }
126
127 do {
128 err = dup2(fd, STDERR_FILENO);
129 } while (err < 0 && errno == EINTR);
130}
131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env,
133 jobject clazz, jobject descriptor, jboolean flag)
134{
135 int fd;
136 int err;
137 int fdFlags;
138
139 fd = jniGetFDFromFileDescriptor(env, descriptor);
140
141 if (env->ExceptionOccurred() != NULL) {
142 return;
143 }
144
145 fdFlags = fcntl(fd, F_GETFD);
146
147 if (fdFlags < 0) {
148 jniThrowIOException(env, errno);
149 return;
150 }
151
152 if (flag) {
153 fdFlags |= FD_CLOEXEC;
154 } else {
155 fdFlags &= ~FD_CLOEXEC;
156 }
157
158 err = fcntl(fd, F_SETFD, fdFlags);
159
160 if (err < 0) {
161 jniThrowIOException(env, errno);
162 return;
163 }
164}
165
166static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
167 jobject clazz, jlong permitted, jlong effective)
168{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 struct __user_cap_header_struct capheader;
170 struct __user_cap_data_struct capdata;
171 int err;
172
173 memset (&capheader, 0, sizeof(capheader));
174 memset (&capdata, 0, sizeof(capdata));
175
176 capheader.version = _LINUX_CAPABILITY_VERSION;
177 capheader.pid = 0;
178
179 // As of this writing, capdata is __u32, but that's expected
180 // to change...
181 capdata.effective = effective;
182 capdata.permitted = permitted;
183
Elliott Hughes69a017b2011-04-08 14:10:28 -0700184 err = capset (&capheader, &capdata);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
186 if (err < 0) {
187 jniThrowIOException(env, errno);
188 return;
189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190}
191
192static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
193 jobject clazz, jint pid)
194{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 struct __user_cap_header_struct capheader;
196 struct __user_cap_data_struct capdata;
197 int err;
198
199 memset (&capheader, 0, sizeof(capheader));
200 memset (&capdata, 0, sizeof(capdata));
201
202 capheader.version = _LINUX_CAPABILITY_VERSION;
203 capheader.pid = pid;
204
Elliott Hughes69a017b2011-04-08 14:10:28 -0700205 err = capget (&capheader, &capdata);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 if (err < 0) {
208 jniThrowIOException(env, errno);
209 return 0;
210 }
211
212 return (jlong) capdata.permitted;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213}
214
215static jint com_android_internal_os_ZygoteInit_selectReadable (
Elliott Hughes69a017b2011-04-08 14:10:28 -0700216 JNIEnv *env, jobject clazz, jobjectArray fds)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217{
218 if (fds == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700219 jniThrowNullPointerException(env, "fds == null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 return -1;
221 }
222
223 jsize length = env->GetArrayLength(fds);
224 fd_set fdset;
225
226 if (env->ExceptionOccurred() != NULL) {
227 return -1;
228 }
229
230 FD_ZERO(&fdset);
231
232 int nfds = 0;
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
246 FD_SET(fd, &fdset);
247
248 if (fd >= nfds) {
249 nfds = fd + 1;
250 }
251 }
252
253 int err;
254 do {
255 err = select (nfds, &fdset, NULL, NULL, NULL);
256 } while (err < 0 && errno == EINTR);
257
258 if (err < 0) {
259 jniThrowIOException(env, errno);
260 return -1;
261 }
262
263 for (jsize i = 0; i < length; i++) {
264 jobject fdObj = env->GetObjectArrayElement(fds, i);
265 if (env->ExceptionOccurred() != NULL) {
266 return -1;
267 }
268 if (fdObj == NULL) {
269 continue;
270 }
271 int fd = jniGetFDFromFileDescriptor(env, fdObj);
272 if (env->ExceptionOccurred() != NULL) {
273 return -1;
274 }
275 if (FD_ISSET(fd, &fdset)) {
276 return (jint)i;
277 }
278 }
279 return -1;
280}
281
282static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
Elliott Hughes69a017b2011-04-08 14:10:28 -0700283 JNIEnv *env, jobject clazz, jint fd)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284{
285 return jniCreateFileDescriptor(env, fd);
286}
287
288/*
289 * JNI registration.
290 */
291static JNINativeMethod gMethods[] = {
292 /* name, signature, funcPtr */
293 { "setreuid", "(II)I",
294 (void*) com_android_internal_os_ZygoteInit_setreuid },
295 { "setregid", "(II)I",
296 (void*) com_android_internal_os_ZygoteInit_setregid },
297 { "setpgid", "(II)I",
298 (void *) com_android_internal_os_ZygoteInit_setpgid },
299 { "getpgid", "(I)I",
300 (void *) com_android_internal_os_ZygoteInit_getpgid },
Elliott Hughes69a017b2011-04-08 14:10:28 -0700301 { "reopenStdio",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
Elliott Hughes69a017b2011-04-08 14:10:28 -0700303 "Ljava/io/FileDescriptor;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 (void *) com_android_internal_os_ZygoteInit_reopenStdio},
Elliott Hughes69a017b2011-04-08 14:10:28 -0700305 { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
Elliott Hughes69a017b2011-04-08 14:10:28 -0700307 { "setCapabilities", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 (void *) com_android_internal_os_ZygoteInit_setCapabilities },
Elliott Hughes69a017b2011-04-08 14:10:28 -0700309 { "capgetPermitted", "(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 (void *) com_android_internal_os_ZygoteInit_capgetPermitted },
311 { "selectReadable", "([Ljava/io/FileDescriptor;)I",
312 (void *) com_android_internal_os_ZygoteInit_selectReadable },
313 { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
314 (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
315};
316int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
317{
318 return AndroidRuntime::registerNativeMethods(env,
319 "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods));
320}
321
322}; // namespace android