com_android_internal_os_ZygoteInit.cpp revision 69a017bc1d1649350f830dfada5c6ed5eac0b770
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> 34extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap); 35extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap); 36#endif 37 38 39namespace android { 40 41/* 42 * In class com.android.internal.os.ZygoteInit: 43 * private static native boolean setreuid(int ruid, int euid) 44 */ 45static jint com_android_internal_os_ZygoteInit_setreuid( 46 JNIEnv* env, jobject clazz, jint ruid, jint euid) 47{ 48 if (setreuid(ruid, euid) < 0) { 49 return errno; 50 } 51 return 0; 52} 53 54/* 55 * In class com.android.internal.os.ZygoteInit: 56 * private static native int setregid(int rgid, int egid) 57 */ 58static jint com_android_internal_os_ZygoteInit_setregid( 59 JNIEnv* env, jobject clazz, jint rgid, jint egid) 60{ 61 if (setregid(rgid, egid) < 0) { 62 return errno; 63 } 64 return 0; 65} 66 67/* 68 * In class com.android.internal.os.ZygoteInit: 69 * private static native int setpgid(int rgid, int egid) 70 */ 71static jint com_android_internal_os_ZygoteInit_setpgid( 72 JNIEnv* env, jobject clazz, jint pid, jint pgid) 73{ 74 if (setpgid(pid, pgid) < 0) { 75 return errno; 76 } 77 return 0; 78} 79 80/* 81 * In class com.android.internal.os.ZygoteInit: 82 * private static native int getpgid(int pid) 83 */ 84static jint com_android_internal_os_ZygoteInit_getpgid( 85 JNIEnv* env, jobject clazz, jint pid) 86{ 87 pid_t ret; 88 ret = getpgid(pid); 89 90 if (ret < 0) { 91 jniThrowIOException(env, errno); 92 } 93 94 return ret; 95} 96 97static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env, 98 jobject clazz, jobject in, jobject out, jobject errfd) 99{ 100 int fd; 101 int err; 102 103 fd = jniGetFDFromFileDescriptor(env, in); 104 105 if (env->ExceptionOccurred() != NULL) { 106 return; 107 } 108 109 do { 110 err = dup2(fd, STDIN_FILENO); 111 } while (err < 0 && errno == EINTR); 112 113 fd = jniGetFDFromFileDescriptor(env, out); 114 115 if (env->ExceptionOccurred() != NULL) { 116 return; 117 } 118 119 do { 120 err = dup2(fd, STDOUT_FILENO); 121 } while (err < 0 && errno == EINTR); 122 123 fd = jniGetFDFromFileDescriptor(env, errfd); 124 125 if (env->ExceptionOccurred() != NULL) { 126 return; 127 } 128 129 do { 130 err = dup2(fd, STDERR_FILENO); 131 } while (err < 0 && errno == EINTR); 132} 133 134static void com_android_internal_os_ZygoteInit_closeDescriptor(JNIEnv* env, 135 jobject clazz, jobject descriptor) 136{ 137 int fd; 138 int err; 139 140 fd = jniGetFDFromFileDescriptor(env, descriptor); 141 142 if (env->ExceptionOccurred() != NULL) { 143 return; 144 } 145 146 do { 147 err = close(fd); 148 } while (err < 0 && errno == EINTR); 149 150 if (err < 0) { 151 jniThrowIOException(env, errno); 152 return; 153 } 154} 155 156static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env, 157 jobject clazz, jobject descriptor, jboolean flag) 158{ 159 int fd; 160 int err; 161 int fdFlags; 162 163 fd = jniGetFDFromFileDescriptor(env, descriptor); 164 165 if (env->ExceptionOccurred() != NULL) { 166 return; 167 } 168 169 fdFlags = fcntl(fd, F_GETFD); 170 171 if (fdFlags < 0) { 172 jniThrowIOException(env, errno); 173 return; 174 } 175 176 if (flag) { 177 fdFlags |= FD_CLOEXEC; 178 } else { 179 fdFlags &= ~FD_CLOEXEC; 180 } 181 182 err = fcntl(fd, F_SETFD, fdFlags); 183 184 if (err < 0) { 185 jniThrowIOException(env, errno); 186 return; 187 } 188} 189 190static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env, 191 jobject clazz, jlong permitted, jlong effective) 192{ 193#ifdef HAVE_ANDROID_OS 194 struct __user_cap_header_struct capheader; 195 struct __user_cap_data_struct capdata; 196 int err; 197 198 memset (&capheader, 0, sizeof(capheader)); 199 memset (&capdata, 0, sizeof(capdata)); 200 201 capheader.version = _LINUX_CAPABILITY_VERSION; 202 capheader.pid = 0; 203 204 // As of this writing, capdata is __u32, but that's expected 205 // to change... 206 capdata.effective = effective; 207 capdata.permitted = permitted; 208 209 err = capset (&capheader, &capdata); 210 211 if (err < 0) { 212 jniThrowIOException(env, errno); 213 return; 214 } 215#endif /* HAVE_ANDROID_OS */ 216} 217 218static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env, 219 jobject clazz, jint pid) 220{ 221#ifndef HAVE_ANDROID_OS 222 return (jlong)0; 223#else 224 struct __user_cap_header_struct capheader; 225 struct __user_cap_data_struct capdata; 226 int err; 227 228 memset (&capheader, 0, sizeof(capheader)); 229 memset (&capdata, 0, sizeof(capdata)); 230 231 capheader.version = _LINUX_CAPABILITY_VERSION; 232 capheader.pid = pid; 233 234 err = capget (&capheader, &capdata); 235 236 if (err < 0) { 237 jniThrowIOException(env, errno); 238 return 0; 239 } 240 241 return (jlong) capdata.permitted; 242#endif /* HAVE_ANDROID_OS */ 243} 244 245static jint com_android_internal_os_ZygoteInit_selectReadable ( 246 JNIEnv *env, jobject clazz, jobjectArray fds) 247{ 248 if (fds == NULL) { 249 jniThrowNullPointerException(env, "fds == null"); 250 return -1; 251 } 252 253 jsize length = env->GetArrayLength(fds); 254 fd_set fdset; 255 256 if (env->ExceptionOccurred() != NULL) { 257 return -1; 258 } 259 260 FD_ZERO(&fdset); 261 262 int nfds = 0; 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 276 FD_SET(fd, &fdset); 277 278 if (fd >= nfds) { 279 nfds = fd + 1; 280 } 281 } 282 283 int err; 284 do { 285 err = select (nfds, &fdset, NULL, NULL, NULL); 286 } while (err < 0 && errno == EINTR); 287 288 if (err < 0) { 289 jniThrowIOException(env, errno); 290 return -1; 291 } 292 293 for (jsize i = 0; i < length; i++) { 294 jobject fdObj = env->GetObjectArrayElement(fds, i); 295 if (env->ExceptionOccurred() != NULL) { 296 return -1; 297 } 298 if (fdObj == NULL) { 299 continue; 300 } 301 int fd = jniGetFDFromFileDescriptor(env, fdObj); 302 if (env->ExceptionOccurred() != NULL) { 303 return -1; 304 } 305 if (FD_ISSET(fd, &fdset)) { 306 return (jint)i; 307 } 308 } 309 return -1; 310} 311 312static jobject com_android_internal_os_ZygoteInit_createFileDescriptor ( 313 JNIEnv *env, jobject clazz, jint fd) 314{ 315 return jniCreateFileDescriptor(env, fd); 316} 317 318/* 319 * JNI registration. 320 */ 321static JNINativeMethod gMethods[] = { 322 /* name, signature, funcPtr */ 323 { "setreuid", "(II)I", 324 (void*) com_android_internal_os_ZygoteInit_setreuid }, 325 { "setregid", "(II)I", 326 (void*) com_android_internal_os_ZygoteInit_setregid }, 327 { "setpgid", "(II)I", 328 (void *) com_android_internal_os_ZygoteInit_setpgid }, 329 { "getpgid", "(I)I", 330 (void *) com_android_internal_os_ZygoteInit_getpgid }, 331 { "reopenStdio", 332 "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;" 333 "Ljava/io/FileDescriptor;)V", 334 (void *) com_android_internal_os_ZygoteInit_reopenStdio}, 335 { "closeDescriptor", "(Ljava/io/FileDescriptor;)V", 336 (void *) com_android_internal_os_ZygoteInit_closeDescriptor}, 337 { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V", 338 (void *) com_android_internal_os_ZygoteInit_setCloseOnExec}, 339 { "setCapabilities", "(JJ)V", 340 (void *) com_android_internal_os_ZygoteInit_setCapabilities }, 341 { "capgetPermitted", "(I)J", 342 (void *) com_android_internal_os_ZygoteInit_capgetPermitted }, 343 { "selectReadable", "([Ljava/io/FileDescriptor;)I", 344 (void *) com_android_internal_os_ZygoteInit_selectReadable }, 345 { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;", 346 (void *) com_android_internal_os_ZygoteInit_createFileDescriptor } 347}; 348int register_com_android_internal_os_ZygoteInit(JNIEnv* env) 349{ 350 return AndroidRuntime::registerNativeMethods(env, 351 "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods)); 352} 353 354}; // namespace android 355