Loading core/jni/android_os_SELinux.cpp +331 −352 Original line number Diff line number Diff line Loading @@ -23,16 +23,20 @@ #include "selinux/selinux.h" #include "selinux/android.h" #include <errno.h> #include <ScopedLocalRef.h> #include <ScopedUtfChars.h> #include <UniquePtr.h> namespace android { static jboolean isSELinuxDisabled = true; static void throw_NullPointerException(JNIEnv *env, const char* msg) { jclass clazz; clazz = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(clazz, msg); struct SecurityContext_Delete { void operator()(security_context_t p) const { freecon(p); } }; typedef UniquePtr<char[], SecurityContext_Delete> Unique_SecurityContext; static jboolean isSELinuxDisabled = true; /* * Function: isSELinuxEnabled Loading @@ -41,8 +45,7 @@ namespace android { * Return value : true (enabled) or false (disabled) * Exceptions: none */ static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) { static jboolean isSELinuxEnabled(JNIEnv *env, jobject) { return !isSELinuxDisabled; } Loading @@ -53,7 +56,7 @@ namespace android { * Return value: true (enforcing) or false (permissive) * Exceptions: none */ static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) { static jboolean isSELinuxEnforced(JNIEnv *env, jobject) { return (security_getenforce() == 1) ? true : false; } Loading @@ -64,11 +67,12 @@ namespace android { * Return value: true (success) or false (fail) * Exceptions: none */ static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) { if (isSELinuxDisabled) static jboolean setSELinuxEnforce(JNIEnv *env, jobject, jboolean value) { if (isSELinuxDisabled) { return false; } int enforce = (value) ? 1 : 0; int enforce = value ? 1 : 0; return (security_setenforce(enforce) != -1) ? true : false; } Loading @@ -81,37 +85,34 @@ namespace android { * Returns: jstring representing the security_context of socket or NULL if error * Exceptions: NullPointerException if fileDescriptor object is NULL */ static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) { if (isSELinuxDisabled) static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) { if (isSELinuxDisabled) { return NULL; } if (fileDescriptor == NULL) { throw_NullPointerException(env, "Trying to check security context of a null peer socket."); jniThrowNullPointerException(env, "Trying to check security context of a null peer socket."); return NULL; } security_context_t context = NULL; jstring securityString = NULL; int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionOccurred() != NULL) { ALOGE("There was an issue with retrieving the file descriptor"); goto bail; ALOGE("getPeerCon => getFD for %p failed", fileDescriptor); return NULL; } if (getpeercon(fd, &context) == -1) goto bail; ALOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getpeercon(fd, &tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> contextStr(env, NULL); if (ret != -1) { contextStr.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getPeerCon(%d) => %s", fd, contextStr.get()); return contextStr.release(); } /* Loading @@ -123,29 +124,24 @@ namespace android { * Returns: true on success, false on error * Exception: none */ static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) { if (isSELinuxDisabled) static jboolean setFSCreateCon(JNIEnv *env, jobject, jstring contextStr) { if (isSELinuxDisabled) { return false; char * securityContext = NULL; const char *constant_securityContext = NULL; if (context != NULL) { constant_securityContext = env->GetStringUTFChars(context, NULL); // GetStringUTFChars returns const char * yet setfscreatecon needs char * securityContext = const_cast<char *>(constant_securityContext); } int ret; if ((ret = setfscreatecon(securityContext)) == -1) goto bail; UniquePtr<ScopedUtfChars> context; const char* context_c_str = NULL; if (contextStr != NULL) { context.reset(new ScopedUtfChars(env, contextStr)); context_c_str = context->c_str(); if (context_c_str == NULL) { return false; } } ALOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context); int ret = setfscreatecon(const_cast<char *>(context_c_str)); bail: if (constant_securityContext != NULL) env->ReleaseStringUTFChars(context, constant_securityContext); ALOGV("setFSCreateCon(%s) => %d", context_c_str, ret); return (ret == 0) ? true : false; } Loading @@ -155,39 +151,30 @@ namespace android { * Purpose: set the security context of a file object * Parameters: * path: the location of the file system object * con: the new security context of the file system object * context: the new security context of the file system object * Returns: true on success, false on error * Exception: NullPointerException is thrown if either path or context strign are NULL */ static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) { if (isSELinuxDisabled) static jboolean setFileCon(JNIEnv *env, jobject, jstring pathStr, jstring contextStr) { if (isSELinuxDisabled) { return false; } if (path == NULL) { throw_NullPointerException(env, "Trying to change the security context of a NULL file object."); ScopedUtfChars path(env, pathStr); if (path.c_str() == NULL) { return false; } if (con == NULL) { throw_NullPointerException(env, "Trying to set the security context of a file object with NULL."); ScopedUtfChars context(env, contextStr); if (context.c_str() == NULL) { return false; } const char *objectPath = env->GetStringUTFChars(path, NULL); const char *constant_con = env->GetStringUTFChars(con, NULL); // GetStringUTFChars returns const char * yet setfilecon needs char * char *newCon = const_cast<char *>(constant_con); int ret; if ((ret = setfilecon(objectPath, newCon)) == -1) goto bail; ALOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath); char *tmp = const_cast<char *>(context.c_str()); int ret = setfilecon(path.c_str(), tmp); bail: env->ReleaseStringUTFChars(path, objectPath); env->ReleaseStringUTFChars(con, constant_con); ALOGV("setFileCon(%s, %s) => %d", path.c_str(), context.c_str(), ret); return (ret == 0) ? true : false; } Loading @@ -201,34 +188,27 @@ namespace android { * the string may be NULL if an error occured * Exceptions: NullPointerException if the path object is null */ static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) { if (isSELinuxDisabled) static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { if (isSELinuxDisabled) { return NULL; } if (path == NULL) { throw_NullPointerException(env, "Trying to check security context of a null path."); ScopedUtfChars path(env, pathStr); if (path.c_str() == NULL) { return NULL; } const char *objectPath = env->GetStringUTFChars(path, NULL); security_context_t context = NULL; jstring securityString = NULL; if (getfilecon(objectPath, &context) == -1) goto bail; ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath); security_context_t tmp; int ret = getfilecon(path.c_str(), &tmp); Unique_SecurityContext context(tmp); securityString = env->NewStringUTF(context); bail: if (context != NULL) freecon(context); env->ReleaseStringUTFChars(path, objectPath); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getFileCon(%s) => %s", path.c_str(), context.get()); return securityString.release(); } /* Loading @@ -239,25 +219,22 @@ namespace android { * the jstring may be NULL if there was an error * Exceptions: none */ static jstring getCon(JNIEnv *env, jobject clazz) { if (isSELinuxDisabled) static jstring getCon(JNIEnv *env, jobject) { if (isSELinuxDisabled) { return NULL; } security_context_t context = NULL; jstring securityString = NULL; if (getcon(&context) == -1) goto bail; ALOGV("getCon: Successfully retrieved context '%s'", context); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getcon(&tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getCon() => %s", context.get()); return securityString.release(); } /* Loading @@ -269,27 +246,22 @@ namespace android { * the jstring may be NULL if there was an error * Exceptions: none */ static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) { if (isSELinuxDisabled) static jstring getPidCon(JNIEnv *env, jobject, jint pid) { if (isSELinuxDisabled) { return NULL; } security_context_t context = NULL; jstring securityString = NULL; pid_t checkPid = (pid_t)pid; if (getpidcon(checkPid, &context) == -1) goto bail; ALOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getpidcon(static_cast<pid_t>(pid), &tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getPidCon(%d) => %s", pid, context.get()); return securityString.release(); } /* Loading @@ -300,25 +272,22 @@ namespace android { * returns NULL string on error * Exceptions: None */ static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) { if (isSELinuxDisabled) static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv) { if (isSELinuxDisabled) { return NULL; } char **list; int i, len, ret; jclass stringClass; jobjectArray stringArray = NULL; if (security_get_boolean_names(&list, &len) == -1) int len; if (security_get_boolean_names(&list, &len) == -1) { return NULL; } stringClass = env->FindClass("java/lang/String"); stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF("")); for (i = 0; i < len; i++) { jstring obj; obj = env->NewStringUTF(list[i]); env->SetObjectArrayElement(stringArray, i, obj); env->DeleteLocalRef(obj); jclass stringClass = env->FindClass("java/lang/String"); jobjectArray stringArray = env->NewObjectArray(len, stringClass, NULL); for (int i = 0; i < len; i++) { ScopedLocalRef<jstring> obj(env, env->NewStringUTF(list[i])); env->SetObjectArrayElement(stringArray, i, obj.get()); free(list[i]); } free(list); Loading @@ -334,18 +303,19 @@ namespace android { * Returns: a boolean: (true) boolean is set or (false) it is not. * Exceptions: None */ static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) { if (isSELinuxDisabled) static jboolean getBooleanValue(JNIEnv *env, jobject, jstring nameStr) { if (isSELinuxDisabled) { return false; } const char *boolean_name; int ret; if (name == NULL) if (nameStr == NULL) { return false; boolean_name = env->GetStringUTFChars(name, NULL); ret = security_get_boolean_active(boolean_name); env->ReleaseStringUTFChars(name, boolean_name); } ScopedUtfChars name(env, nameStr); int ret = security_get_boolean_active(name.c_str()); ALOGV("getBooleanValue(%s) => %d", name.c_str(), ret); return (ret == 1) ? true : false; } Loading @@ -358,23 +328,24 @@ namespace android { * Returns: a boolean indicating whether or not the operation succeeded. * Exceptions: None */ static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) { if (isSELinuxDisabled) static jboolean setBooleanValue(JNIEnv *env, jobject, jstring nameStr, jboolean value) { if (isSELinuxDisabled) { return false; } const char *boolean_name = NULL; int ret; if (name == NULL) if (nameStr == NULL) { return false; boolean_name = env->GetStringUTFChars(name, NULL); ret = security_set_boolean(boolean_name, (value) ? 1 : 0); env->ReleaseStringUTFChars(name, boolean_name); if (ret) } ScopedUtfChars name(env, nameStr); int ret = security_set_boolean(name.c_str(), value ? 1 : 0); if (ret) { return false; } if (security_commit_booleans() == -1) if (security_commit_booleans() == -1) { return false; } return true; } Loading @@ -382,44 +353,47 @@ namespace android { /* * Function: checkSELinuxAccess * Purpose: Check permissions between two security contexts. * Parameters: scon: subject security context as a string * tcon: object security context as a string * tclass: object's security class name as a string * perm: permission name as a string * Parameters: subjectContextStr: subject security context as a string * objectContextStr: object security context as a string * objectClassStr: object's security class name as a string * permissionStr: permission name as a string * Returns: boolean: (true) if permission was granted, (false) otherwise * Exceptions: None */ static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) { if (isSELinuxDisabled) static jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextStr, jstring objectContextStr, jstring objectClassStr, jstring permissionStr) { if (isSELinuxDisabled) { return true; } int accessGranted = -1; const char *const_scon, *const_tcon, *mytclass, *myperm; char *myscon, *mytcon; if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL) goto bail; ScopedUtfChars subjectContext(env, subjectContextStr); if (subjectContext.c_str() == NULL) { return false; } const_scon = env->GetStringUTFChars(scon, NULL); const_tcon = env->GetStringUTFChars(tcon, NULL); mytclass = env->GetStringUTFChars(tclass, NULL); myperm = env->GetStringUTFChars(perm, NULL); ScopedUtfChars objectContext(env, objectContextStr); if (objectContext.c_str() == NULL) { return false; } // selinux_check_access needs char* for some myscon = const_cast<char *>(const_scon); mytcon = const_cast<char *>(const_tcon); ScopedUtfChars objectClass(env, objectClassStr); if (objectClass.c_str() == NULL) { return false; } accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL); ScopedUtfChars permission(env, permissionStr); if (permission.c_str() == NULL) { return false; } ALOGV("selinux_check_access returned %d", accessGranted); char *tmp1 = const_cast<char *>(subjectContext.c_str()); char *tmp2 = const_cast<char *>(objectContext.c_str()); int accessGranted = selinux_check_access(tmp1, tmp2, objectClass.c_str(), permission.c_str(), NULL); env->ReleaseStringUTFChars(scon, const_scon); env->ReleaseStringUTFChars(tcon, const_tcon); env->ReleaseStringUTFChars(tclass, mytclass); env->ReleaseStringUTFChars(perm, myperm); ALOGV("checkSELinuxAccess(%s, %s, %s, %s) => %d", subjectContext.c_str(), objectContext.c_str(), objectClass.c_str(), permission.c_str(), accessGranted); bail: return (accessGranted == 0) ? true : false; } Loading @@ -430,13 +404,19 @@ namespace android { * Returns: boolean: (true) file label successfully restored, (false) otherwise * Exceptions: none */ static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) { if (isSELinuxDisabled) static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) { if (isSELinuxDisabled) { return true; } const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL)); int ret = selinux_android_restorecon(file); env->ReleaseStringUTFChars(pathname, file); ScopedUtfChars pathname(env, pathnameStr); if (pathname.c_str() == NULL) { ALOGV("restorecon(%p) => threw exception", pathname); return false; } int ret = selinux_android_restorecon(pathname.c_str()); ALOGV("restorecon(%s) => %d", pathname.c_str(), ret); return (ret == 0); } Loading @@ -444,7 +424,6 @@ namespace android { * JNI registration. */ static JNINativeMethod method_table[] = { /* name, signature, funcPtr */ { "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess }, { "getBooleanNames" , "()[Ljava/lang/String;" , (void*)getBooleanNames }, Loading Loading @@ -477,8 +456,8 @@ namespace android { isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false; return AndroidRuntime::registerNativeMethods( env, "android/os/SELinux", method_table, NELEM(method_table)); return AndroidRuntime::registerNativeMethods(env, "android/os/SELinux", method_table, NELEM(method_table)); } } Loading
core/jni/android_os_SELinux.cpp +331 −352 Original line number Diff line number Diff line Loading @@ -23,16 +23,20 @@ #include "selinux/selinux.h" #include "selinux/android.h" #include <errno.h> #include <ScopedLocalRef.h> #include <ScopedUtfChars.h> #include <UniquePtr.h> namespace android { static jboolean isSELinuxDisabled = true; static void throw_NullPointerException(JNIEnv *env, const char* msg) { jclass clazz; clazz = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(clazz, msg); struct SecurityContext_Delete { void operator()(security_context_t p) const { freecon(p); } }; typedef UniquePtr<char[], SecurityContext_Delete> Unique_SecurityContext; static jboolean isSELinuxDisabled = true; /* * Function: isSELinuxEnabled Loading @@ -41,8 +45,7 @@ namespace android { * Return value : true (enabled) or false (disabled) * Exceptions: none */ static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) { static jboolean isSELinuxEnabled(JNIEnv *env, jobject) { return !isSELinuxDisabled; } Loading @@ -53,7 +56,7 @@ namespace android { * Return value: true (enforcing) or false (permissive) * Exceptions: none */ static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) { static jboolean isSELinuxEnforced(JNIEnv *env, jobject) { return (security_getenforce() == 1) ? true : false; } Loading @@ -64,11 +67,12 @@ namespace android { * Return value: true (success) or false (fail) * Exceptions: none */ static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) { if (isSELinuxDisabled) static jboolean setSELinuxEnforce(JNIEnv *env, jobject, jboolean value) { if (isSELinuxDisabled) { return false; } int enforce = (value) ? 1 : 0; int enforce = value ? 1 : 0; return (security_setenforce(enforce) != -1) ? true : false; } Loading @@ -81,37 +85,34 @@ namespace android { * Returns: jstring representing the security_context of socket or NULL if error * Exceptions: NullPointerException if fileDescriptor object is NULL */ static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) { if (isSELinuxDisabled) static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) { if (isSELinuxDisabled) { return NULL; } if (fileDescriptor == NULL) { throw_NullPointerException(env, "Trying to check security context of a null peer socket."); jniThrowNullPointerException(env, "Trying to check security context of a null peer socket."); return NULL; } security_context_t context = NULL; jstring securityString = NULL; int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (env->ExceptionOccurred() != NULL) { ALOGE("There was an issue with retrieving the file descriptor"); goto bail; ALOGE("getPeerCon => getFD for %p failed", fileDescriptor); return NULL; } if (getpeercon(fd, &context) == -1) goto bail; ALOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getpeercon(fd, &tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> contextStr(env, NULL); if (ret != -1) { contextStr.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getPeerCon(%d) => %s", fd, contextStr.get()); return contextStr.release(); } /* Loading @@ -123,29 +124,24 @@ namespace android { * Returns: true on success, false on error * Exception: none */ static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) { if (isSELinuxDisabled) static jboolean setFSCreateCon(JNIEnv *env, jobject, jstring contextStr) { if (isSELinuxDisabled) { return false; char * securityContext = NULL; const char *constant_securityContext = NULL; if (context != NULL) { constant_securityContext = env->GetStringUTFChars(context, NULL); // GetStringUTFChars returns const char * yet setfscreatecon needs char * securityContext = const_cast<char *>(constant_securityContext); } int ret; if ((ret = setfscreatecon(securityContext)) == -1) goto bail; UniquePtr<ScopedUtfChars> context; const char* context_c_str = NULL; if (contextStr != NULL) { context.reset(new ScopedUtfChars(env, contextStr)); context_c_str = context->c_str(); if (context_c_str == NULL) { return false; } } ALOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context); int ret = setfscreatecon(const_cast<char *>(context_c_str)); bail: if (constant_securityContext != NULL) env->ReleaseStringUTFChars(context, constant_securityContext); ALOGV("setFSCreateCon(%s) => %d", context_c_str, ret); return (ret == 0) ? true : false; } Loading @@ -155,39 +151,30 @@ namespace android { * Purpose: set the security context of a file object * Parameters: * path: the location of the file system object * con: the new security context of the file system object * context: the new security context of the file system object * Returns: true on success, false on error * Exception: NullPointerException is thrown if either path or context strign are NULL */ static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) { if (isSELinuxDisabled) static jboolean setFileCon(JNIEnv *env, jobject, jstring pathStr, jstring contextStr) { if (isSELinuxDisabled) { return false; } if (path == NULL) { throw_NullPointerException(env, "Trying to change the security context of a NULL file object."); ScopedUtfChars path(env, pathStr); if (path.c_str() == NULL) { return false; } if (con == NULL) { throw_NullPointerException(env, "Trying to set the security context of a file object with NULL."); ScopedUtfChars context(env, contextStr); if (context.c_str() == NULL) { return false; } const char *objectPath = env->GetStringUTFChars(path, NULL); const char *constant_con = env->GetStringUTFChars(con, NULL); // GetStringUTFChars returns const char * yet setfilecon needs char * char *newCon = const_cast<char *>(constant_con); int ret; if ((ret = setfilecon(objectPath, newCon)) == -1) goto bail; ALOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath); char *tmp = const_cast<char *>(context.c_str()); int ret = setfilecon(path.c_str(), tmp); bail: env->ReleaseStringUTFChars(path, objectPath); env->ReleaseStringUTFChars(con, constant_con); ALOGV("setFileCon(%s, %s) => %d", path.c_str(), context.c_str(), ret); return (ret == 0) ? true : false; } Loading @@ -201,34 +188,27 @@ namespace android { * the string may be NULL if an error occured * Exceptions: NullPointerException if the path object is null */ static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) { if (isSELinuxDisabled) static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { if (isSELinuxDisabled) { return NULL; } if (path == NULL) { throw_NullPointerException(env, "Trying to check security context of a null path."); ScopedUtfChars path(env, pathStr); if (path.c_str() == NULL) { return NULL; } const char *objectPath = env->GetStringUTFChars(path, NULL); security_context_t context = NULL; jstring securityString = NULL; if (getfilecon(objectPath, &context) == -1) goto bail; ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath); security_context_t tmp; int ret = getfilecon(path.c_str(), &tmp); Unique_SecurityContext context(tmp); securityString = env->NewStringUTF(context); bail: if (context != NULL) freecon(context); env->ReleaseStringUTFChars(path, objectPath); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getFileCon(%s) => %s", path.c_str(), context.get()); return securityString.release(); } /* Loading @@ -239,25 +219,22 @@ namespace android { * the jstring may be NULL if there was an error * Exceptions: none */ static jstring getCon(JNIEnv *env, jobject clazz) { if (isSELinuxDisabled) static jstring getCon(JNIEnv *env, jobject) { if (isSELinuxDisabled) { return NULL; } security_context_t context = NULL; jstring securityString = NULL; if (getcon(&context) == -1) goto bail; ALOGV("getCon: Successfully retrieved context '%s'", context); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getcon(&tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getCon() => %s", context.get()); return securityString.release(); } /* Loading @@ -269,27 +246,22 @@ namespace android { * the jstring may be NULL if there was an error * Exceptions: none */ static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) { if (isSELinuxDisabled) static jstring getPidCon(JNIEnv *env, jobject, jint pid) { if (isSELinuxDisabled) { return NULL; } security_context_t context = NULL; jstring securityString = NULL; pid_t checkPid = (pid_t)pid; if (getpidcon(checkPid, &context) == -1) goto bail; ALOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid); securityString = env->NewStringUTF(context); security_context_t tmp; int ret = getpidcon(static_cast<pid_t>(pid), &tmp); Unique_SecurityContext context(tmp); bail: if (context != NULL) freecon(context); ScopedLocalRef<jstring> securityString(env, NULL); if (ret != -1) { securityString.reset(env->NewStringUTF(context.get())); } return securityString; ALOGV("getPidCon(%d) => %s", pid, context.get()); return securityString.release(); } /* Loading @@ -300,25 +272,22 @@ namespace android { * returns NULL string on error * Exceptions: None */ static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) { if (isSELinuxDisabled) static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv) { if (isSELinuxDisabled) { return NULL; } char **list; int i, len, ret; jclass stringClass; jobjectArray stringArray = NULL; if (security_get_boolean_names(&list, &len) == -1) int len; if (security_get_boolean_names(&list, &len) == -1) { return NULL; } stringClass = env->FindClass("java/lang/String"); stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF("")); for (i = 0; i < len; i++) { jstring obj; obj = env->NewStringUTF(list[i]); env->SetObjectArrayElement(stringArray, i, obj); env->DeleteLocalRef(obj); jclass stringClass = env->FindClass("java/lang/String"); jobjectArray stringArray = env->NewObjectArray(len, stringClass, NULL); for (int i = 0; i < len; i++) { ScopedLocalRef<jstring> obj(env, env->NewStringUTF(list[i])); env->SetObjectArrayElement(stringArray, i, obj.get()); free(list[i]); } free(list); Loading @@ -334,18 +303,19 @@ namespace android { * Returns: a boolean: (true) boolean is set or (false) it is not. * Exceptions: None */ static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) { if (isSELinuxDisabled) static jboolean getBooleanValue(JNIEnv *env, jobject, jstring nameStr) { if (isSELinuxDisabled) { return false; } const char *boolean_name; int ret; if (name == NULL) if (nameStr == NULL) { return false; boolean_name = env->GetStringUTFChars(name, NULL); ret = security_get_boolean_active(boolean_name); env->ReleaseStringUTFChars(name, boolean_name); } ScopedUtfChars name(env, nameStr); int ret = security_get_boolean_active(name.c_str()); ALOGV("getBooleanValue(%s) => %d", name.c_str(), ret); return (ret == 1) ? true : false; } Loading @@ -358,23 +328,24 @@ namespace android { * Returns: a boolean indicating whether or not the operation succeeded. * Exceptions: None */ static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) { if (isSELinuxDisabled) static jboolean setBooleanValue(JNIEnv *env, jobject, jstring nameStr, jboolean value) { if (isSELinuxDisabled) { return false; } const char *boolean_name = NULL; int ret; if (name == NULL) if (nameStr == NULL) { return false; boolean_name = env->GetStringUTFChars(name, NULL); ret = security_set_boolean(boolean_name, (value) ? 1 : 0); env->ReleaseStringUTFChars(name, boolean_name); if (ret) } ScopedUtfChars name(env, nameStr); int ret = security_set_boolean(name.c_str(), value ? 1 : 0); if (ret) { return false; } if (security_commit_booleans() == -1) if (security_commit_booleans() == -1) { return false; } return true; } Loading @@ -382,44 +353,47 @@ namespace android { /* * Function: checkSELinuxAccess * Purpose: Check permissions between two security contexts. * Parameters: scon: subject security context as a string * tcon: object security context as a string * tclass: object's security class name as a string * perm: permission name as a string * Parameters: subjectContextStr: subject security context as a string * objectContextStr: object security context as a string * objectClassStr: object's security class name as a string * permissionStr: permission name as a string * Returns: boolean: (true) if permission was granted, (false) otherwise * Exceptions: None */ static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) { if (isSELinuxDisabled) static jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextStr, jstring objectContextStr, jstring objectClassStr, jstring permissionStr) { if (isSELinuxDisabled) { return true; } int accessGranted = -1; const char *const_scon, *const_tcon, *mytclass, *myperm; char *myscon, *mytcon; if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL) goto bail; ScopedUtfChars subjectContext(env, subjectContextStr); if (subjectContext.c_str() == NULL) { return false; } const_scon = env->GetStringUTFChars(scon, NULL); const_tcon = env->GetStringUTFChars(tcon, NULL); mytclass = env->GetStringUTFChars(tclass, NULL); myperm = env->GetStringUTFChars(perm, NULL); ScopedUtfChars objectContext(env, objectContextStr); if (objectContext.c_str() == NULL) { return false; } // selinux_check_access needs char* for some myscon = const_cast<char *>(const_scon); mytcon = const_cast<char *>(const_tcon); ScopedUtfChars objectClass(env, objectClassStr); if (objectClass.c_str() == NULL) { return false; } accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL); ScopedUtfChars permission(env, permissionStr); if (permission.c_str() == NULL) { return false; } ALOGV("selinux_check_access returned %d", accessGranted); char *tmp1 = const_cast<char *>(subjectContext.c_str()); char *tmp2 = const_cast<char *>(objectContext.c_str()); int accessGranted = selinux_check_access(tmp1, tmp2, objectClass.c_str(), permission.c_str(), NULL); env->ReleaseStringUTFChars(scon, const_scon); env->ReleaseStringUTFChars(tcon, const_tcon); env->ReleaseStringUTFChars(tclass, mytclass); env->ReleaseStringUTFChars(perm, myperm); ALOGV("checkSELinuxAccess(%s, %s, %s, %s) => %d", subjectContext.c_str(), objectContext.c_str(), objectClass.c_str(), permission.c_str(), accessGranted); bail: return (accessGranted == 0) ? true : false; } Loading @@ -430,13 +404,19 @@ namespace android { * Returns: boolean: (true) file label successfully restored, (false) otherwise * Exceptions: none */ static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) { if (isSELinuxDisabled) static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) { if (isSELinuxDisabled) { return true; } const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL)); int ret = selinux_android_restorecon(file); env->ReleaseStringUTFChars(pathname, file); ScopedUtfChars pathname(env, pathnameStr); if (pathname.c_str() == NULL) { ALOGV("restorecon(%p) => threw exception", pathname); return false; } int ret = selinux_android_restorecon(pathname.c_str()); ALOGV("restorecon(%s) => %d", pathname.c_str(), ret); return (ret == 0); } Loading @@ -444,7 +424,6 @@ namespace android { * JNI registration. */ static JNINativeMethod method_table[] = { /* name, signature, funcPtr */ { "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess }, { "getBooleanNames" , "()[Ljava/lang/String;" , (void*)getBooleanNames }, Loading Loading @@ -477,8 +456,8 @@ namespace android { isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false; return AndroidRuntime::registerNativeMethods( env, "android/os/SELinux", method_table, NELEM(method_table)); return AndroidRuntime::registerNativeMethods(env, "android/os/SELinux", method_table, NELEM(method_table)); } }