com_android_internal_os_ZygoteInit.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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 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 */ 62static 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 */ 79static 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 */ 95static 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 108static 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 145static 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 167static 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 201static 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 229static 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 256static 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 324static 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 */ 333static 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}; 360int 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