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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 }; 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