• 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 #include <linux/capability.h>
31 #include <linux/prctl.h>
32 #include <sys/prctl.h>
33 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
34 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
35 
36 
37 namespace android {
38 
39 /*
40  * In class com.android.internal.os.ZygoteInit:
41  * private static native boolean setreuid(int ruid, int euid)
42  */
com_android_internal_os_ZygoteInit_setreuid(JNIEnv * env,jobject clazz,jint ruid,jint euid)43 static jint com_android_internal_os_ZygoteInit_setreuid(
44     JNIEnv* env, jobject clazz, jint ruid, jint euid)
45 {
46     if (setreuid(ruid, euid) < 0) {
47         return errno;
48     }
49     return 0;
50 }
51 
52 /*
53  * In class com.android.internal.os.ZygoteInit:
54  * private static native int setregid(int rgid, int egid)
55  */
com_android_internal_os_ZygoteInit_setregid(JNIEnv * env,jobject clazz,jint rgid,jint egid)56 static jint com_android_internal_os_ZygoteInit_setregid(
57     JNIEnv* env, jobject clazz, jint rgid, jint egid)
58 {
59     if (setregid(rgid, egid) < 0) {
60         return errno;
61     }
62     return 0;
63 }
64 
65 /*
66  * In class com.android.internal.os.ZygoteInit:
67  * private static native int setpgid(int rgid, int egid)
68  */
com_android_internal_os_ZygoteInit_setpgid(JNIEnv * env,jobject clazz,jint pid,jint pgid)69 static jint com_android_internal_os_ZygoteInit_setpgid(
70     JNIEnv* env, jobject clazz, jint pid, jint pgid)
71 {
72     if (setpgid(pid, pgid) < 0) {
73         return errno;
74     }
75     return 0;
76 }
77 
78 /*
79  * In class com.android.internal.os.ZygoteInit:
80  * private static native int getpgid(int pid)
81  */
com_android_internal_os_ZygoteInit_getpgid(JNIEnv * env,jobject clazz,jint pid)82 static 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 
com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv * env,jobject clazz,jobject in,jobject out,jobject errfd)95 static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
96         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 
com_android_internal_os_ZygoteInit_setCloseOnExec(JNIEnv * env,jobject clazz,jobject descriptor,jboolean flag)132 static 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 
com_android_internal_os_ZygoteInit_setCapabilities(JNIEnv * env,jobject clazz,jlong permitted,jlong effective)166 static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env,
167     jobject clazz, jlong permitted, jlong effective)
168 {
169     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 
184     err = capset (&capheader, &capdata);
185 
186     if (err < 0) {
187         jniThrowIOException(env, errno);
188         return;
189     }
190 }
191 
com_android_internal_os_ZygoteInit_capgetPermitted(JNIEnv * env,jobject clazz,jint pid)192 static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env,
193     jobject clazz, jint pid)
194 {
195     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 
205     err = capget (&capheader, &capdata);
206 
207     if (err < 0) {
208         jniThrowIOException(env, errno);
209         return 0;
210     }
211 
212     return (jlong) capdata.permitted;
213 }
214 
com_android_internal_os_ZygoteInit_selectReadable(JNIEnv * env,jobject clazz,jobjectArray fds)215 static jint com_android_internal_os_ZygoteInit_selectReadable (
216         JNIEnv *env, jobject clazz, jobjectArray fds)
217 {
218     if (fds == NULL) {
219         jniThrowNullPointerException(env, "fds == null");
220         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 
com_android_internal_os_ZygoteInit_createFileDescriptor(JNIEnv * env,jobject clazz,jint fd)282 static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
283         JNIEnv *env, jobject clazz, jint fd)
284 {
285     return jniCreateFileDescriptor(env, fd);
286 }
287 
288 /*
289  * JNI registration.
290  */
291 static 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 },
301     { "reopenStdio",
302         "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
303         "Ljava/io/FileDescriptor;)V",
304             (void *) com_android_internal_os_ZygoteInit_reopenStdio},
305     { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
306         (void *)  com_android_internal_os_ZygoteInit_setCloseOnExec},
307     { "setCapabilities", "(JJ)V",
308         (void *) com_android_internal_os_ZygoteInit_setCapabilities },
309     { "capgetPermitted", "(I)J",
310         (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 };
register_com_android_internal_os_ZygoteInit(JNIEnv * env)316 int 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
323