com_android_internal_os_ZygoteInit.cpp revision ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3
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_setCloseOnExec (JNIEnv *env, 135 jobject clazz, jobject descriptor, jboolean flag) 136{ 137 int fd; 138 int err; 139 int fdFlags; 140 141 fd = jniGetFDFromFileDescriptor(env, descriptor); 142 143 if (env->ExceptionOccurred() != NULL) { 144 return; 145 } 146 147 fdFlags = fcntl(fd, F_GETFD); 148 149 if (fdFlags < 0) { 150 jniThrowIOException(env, errno); 151 return; 152 } 153 154 if (flag) { 155 fdFlags |= FD_CLOEXEC; 156 } else { 157 fdFlags &= ~FD_CLOEXEC; 158 } 159 160 err = fcntl(fd, F_SETFD, fdFlags); 161 162 if (err < 0) { 163 jniThrowIOException(env, errno); 164 return; 165 } 166} 167 168static void com_android_internal_os_ZygoteInit_setCapabilities (JNIEnv *env, 169 jobject clazz, jlong permitted, jlong effective) 170{ 171#ifdef HAVE_ANDROID_OS 172 struct __user_cap_header_struct capheader; 173 struct __user_cap_data_struct capdata; 174 int err; 175 176 memset (&capheader, 0, sizeof(capheader)); 177 memset (&capdata, 0, sizeof(capdata)); 178 179 capheader.version = _LINUX_CAPABILITY_VERSION; 180 capheader.pid = 0; 181 182 // As of this writing, capdata is __u32, but that's expected 183 // to change... 184 capdata.effective = effective; 185 capdata.permitted = permitted; 186 187 err = capset (&capheader, &capdata); 188 189 if (err < 0) { 190 jniThrowIOException(env, errno); 191 return; 192 } 193#endif /* HAVE_ANDROID_OS */ 194} 195 196static jlong com_android_internal_os_ZygoteInit_capgetPermitted (JNIEnv *env, 197 jobject clazz, jint pid) 198{ 199#ifndef HAVE_ANDROID_OS 200 return (jlong)0; 201#else 202 struct __user_cap_header_struct capheader; 203 struct __user_cap_data_struct capdata; 204 int err; 205 206 memset (&capheader, 0, sizeof(capheader)); 207 memset (&capdata, 0, sizeof(capdata)); 208 209 capheader.version = _LINUX_CAPABILITY_VERSION; 210 capheader.pid = pid; 211 212 err = capget (&capheader, &capdata); 213 214 if (err < 0) { 215 jniThrowIOException(env, errno); 216 return 0; 217 } 218 219 return (jlong) capdata.permitted; 220#endif /* HAVE_ANDROID_OS */ 221} 222 223static jint com_android_internal_os_ZygoteInit_selectReadable ( 224 JNIEnv *env, jobject clazz, jobjectArray fds) 225{ 226 if (fds == NULL) { 227 jniThrowNullPointerException(env, "fds == null"); 228 return -1; 229 } 230 231 jsize length = env->GetArrayLength(fds); 232 fd_set fdset; 233 234 if (env->ExceptionOccurred() != NULL) { 235 return -1; 236 } 237 238 FD_ZERO(&fdset); 239 240 int nfds = 0; 241 for (jsize i = 0; i < length; i++) { 242 jobject fdObj = env->GetObjectArrayElement(fds, i); 243 if (env->ExceptionOccurred() != NULL) { 244 return -1; 245 } 246 if (fdObj == NULL) { 247 continue; 248 } 249 int fd = jniGetFDFromFileDescriptor(env, fdObj); 250 if (env->ExceptionOccurred() != NULL) { 251 return -1; 252 } 253 254 FD_SET(fd, &fdset); 255 256 if (fd >= nfds) { 257 nfds = fd + 1; 258 } 259 } 260 261 int err; 262 do { 263 err = select (nfds, &fdset, NULL, NULL, NULL); 264 } while (err < 0 && errno == EINTR); 265 266 if (err < 0) { 267 jniThrowIOException(env, errno); 268 return -1; 269 } 270 271 for (jsize i = 0; i < length; i++) { 272 jobject fdObj = env->GetObjectArrayElement(fds, i); 273 if (env->ExceptionOccurred() != NULL) { 274 return -1; 275 } 276 if (fdObj == NULL) { 277 continue; 278 } 279 int fd = jniGetFDFromFileDescriptor(env, fdObj); 280 if (env->ExceptionOccurred() != NULL) { 281 return -1; 282 } 283 if (FD_ISSET(fd, &fdset)) { 284 return (jint)i; 285 } 286 } 287 return -1; 288} 289 290static jobject com_android_internal_os_ZygoteInit_createFileDescriptor ( 291 JNIEnv *env, jobject clazz, jint fd) 292{ 293 return jniCreateFileDescriptor(env, fd); 294} 295 296/* 297 * JNI registration. 298 */ 299static JNINativeMethod gMethods[] = { 300 /* name, signature, funcPtr */ 301 { "setreuid", "(II)I", 302 (void*) com_android_internal_os_ZygoteInit_setreuid }, 303 { "setregid", "(II)I", 304 (void*) com_android_internal_os_ZygoteInit_setregid }, 305 { "setpgid", "(II)I", 306 (void *) com_android_internal_os_ZygoteInit_setpgid }, 307 { "getpgid", "(I)I", 308 (void *) com_android_internal_os_ZygoteInit_getpgid }, 309 { "reopenStdio", 310 "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;" 311 "Ljava/io/FileDescriptor;)V", 312 (void *) com_android_internal_os_ZygoteInit_reopenStdio}, 313 { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V", 314 (void *) com_android_internal_os_ZygoteInit_setCloseOnExec}, 315 { "setCapabilities", "(JJ)V", 316 (void *) com_android_internal_os_ZygoteInit_setCapabilities }, 317 { "capgetPermitted", "(I)J", 318 (void *) com_android_internal_os_ZygoteInit_capgetPermitted }, 319 { "selectReadable", "([Ljava/io/FileDescriptor;)I", 320 (void *) com_android_internal_os_ZygoteInit_selectReadable }, 321 { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;", 322 (void *) com_android_internal_os_ZygoteInit_createFileDescriptor } 323}; 324int register_com_android_internal_os_ZygoteInit(JNIEnv* env) 325{ 326 return AndroidRuntime::registerNativeMethods(env, 327 "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods)); 328} 329 330}; // namespace android 331