1554cb0c290406f5bba34908489db5382a69d0a9arpcraig/* 2554cb0c290406f5bba34908489db5382a69d0a9arpcraig * Copyright (C) 2012 The Android Open Source Project 3554cb0c290406f5bba34908489db5382a69d0a9arpcraig * 4554cb0c290406f5bba34908489db5382a69d0a9arpcraig * Licensed under the Apache License, Version 2.0 (the "License"); 5554cb0c290406f5bba34908489db5382a69d0a9arpcraig * you may not use this file except in compliance with the License. 6554cb0c290406f5bba34908489db5382a69d0a9arpcraig * You may obtain a copy of the License at 7554cb0c290406f5bba34908489db5382a69d0a9arpcraig * 8554cb0c290406f5bba34908489db5382a69d0a9arpcraig * http://www.apache.org/licenses/LICENSE-2.0 9554cb0c290406f5bba34908489db5382a69d0a9arpcraig * 10554cb0c290406f5bba34908489db5382a69d0a9arpcraig * Unless required by applicable law or agreed to in writing, software 11554cb0c290406f5bba34908489db5382a69d0a9arpcraig * distributed under the License is distributed on an "AS IS" BASIS, 12554cb0c290406f5bba34908489db5382a69d0a9arpcraig * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13554cb0c290406f5bba34908489db5382a69d0a9arpcraig * See the License for the specific language governing permissions and 14554cb0c290406f5bba34908489db5382a69d0a9arpcraig * limitations under the License. 15554cb0c290406f5bba34908489db5382a69d0a9arpcraig */ 16554cb0c290406f5bba34908489db5382a69d0a9arpcraig 17c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#define LOG_TAG "SELinuxJNI" 18c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include <utils/Log.h> 19c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 202279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/JNIHelp.h> 21c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "jni.h" 22ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 23c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "selinux/selinux.h" 24554cb0c290406f5bba34908489db5382a69d0a9arpcraig#include "selinux/android.h" 25c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include <errno.h> 2693bb56ef1525314707dafe5c849916b1d44d15eaElliott Hughes#include <memory> 272279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedLocalRef.h> 282279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedUtfChars.h> 29c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 30c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalleynamespace android { 31c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 32cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstruct SecurityContext_Delete { 33cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root void operator()(security_context_t p) const { 34cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root freecon(p); 35cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 36cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root}; 3793bb56ef1525314707dafe5c849916b1d44d15eaElliott Hughestypedef std::unique_ptr<char[], SecurityContext_Delete> Unique_SecurityContext; 38c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 39cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean isSELinuxDisabled = true; 40c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 41cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 42cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: isSELinuxEnabled 43cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: checks whether SELinux is enabled/disbaled 44cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: none 45cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Return value : true (enabled) or false (disabled) 46cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: none 47cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 48cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean isSELinuxEnabled(JNIEnv *env, jobject) { 49c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return !isSELinuxDisabled; 50cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 51cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root 52cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 53cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: isSELinuxEnforced 54cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: return the current SELinux enforce mode 55cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: none 56cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Return value: true (enforcing) or false (permissive) 57cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: none 58cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 59cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean isSELinuxEnforced(JNIEnv *env, jobject) { 60c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return (security_getenforce() == 1) ? true : false; 61cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 62c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 63cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 64cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: getPeerCon 65cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: retrieves security context of peer socket 66cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: 67cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * fileDescriptor: peer socket file as a FileDescriptor object 68cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: jstring representing the security_context of socket or NULL if error 69cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: NullPointerException if fileDescriptor object is NULL 70cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 71cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) { 72cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 73cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 74c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 75c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 76cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (fileDescriptor == NULL) { 77cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root jniThrowNullPointerException(env, 78cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root "Trying to check security context of a null peer socket."); 79cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 80cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 81c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 82c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 8398671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 84cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGE("getPeerCon => getFD for %p failed", fileDescriptor); 85cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 86c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 87c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 8881ad284517dc80818cd2f3912fbcf9a7b55df119Richard Haines security_context_t tmp = NULL; 89cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = getpeercon(fd, &tmp); 90cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root Unique_SecurityContext context(tmp); 91c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 92cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedLocalRef<jstring> contextStr(env, NULL); 93cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (ret != -1) { 94cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root contextStr.reset(env->NewStringUTF(context.get())); 95cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 96c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 9781ad284517dc80818cd2f3912fbcf9a7b55df119Richard Haines ALOGV("getPeerCon(%d) => %s", fd, context.get()); 98cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return contextStr.release(); 99cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 100c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 101cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 102cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: setFSCreateCon 103cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: set security context used for creating a new file system object 104cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: 105cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * context: security_context_t representing the new context of a file system object, 106cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * set to NULL to return to the default policy behavior 107cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: true on success, false on error 108cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exception: none 109cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 110cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean setFSCreateCon(JNIEnv *env, jobject, jstring contextStr) { 111cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 112cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 113c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 114c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 11593bb56ef1525314707dafe5c849916b1d44d15eaElliott Hughes std::unique_ptr<ScopedUtfChars> context; 116cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root const char* context_c_str = NULL; 117cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (contextStr != NULL) { 118cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root context.reset(new ScopedUtfChars(env, contextStr)); 119cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root context_c_str = context->c_str(); 120cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (context_c_str == NULL) { 121cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 122cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 123cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 124c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 125cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = setfscreatecon(const_cast<char *>(context_c_str)); 126c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 127cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("setFSCreateCon(%s) => %d", context_c_str, ret); 128c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 129c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return (ret == 0) ? true : false; 130cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 131c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 132cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 133cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: setFileCon 134cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: set the security context of a file object 135cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: 136cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * path: the location of the file system object 137cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * context: the new security context of the file system object 138cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: true on success, false on error 139cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exception: NullPointerException is thrown if either path or context strign are NULL 140cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 141cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean setFileCon(JNIEnv *env, jobject, jstring pathStr, jstring contextStr) { 142cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 143cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 144c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 145c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 146cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars path(env, pathStr); 147cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (path.c_str() == NULL) { 148cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 149c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 150c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 151cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars context(env, contextStr); 152cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (context.c_str() == NULL) { 153cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 154cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 155c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 156c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley // GetStringUTFChars returns const char * yet setfilecon needs char * 157cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root char *tmp = const_cast<char *>(context.c_str()); 158cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = setfilecon(path.c_str(), tmp); 159c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 160cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("setFileCon(%s, %s) => %d", path.c_str(), context.c_str(), ret); 161c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return (ret == 0) ? true : false; 162cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 163c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 164cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 165cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: getFileCon 166cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: retrieves the context associated with the given path in the file system 167cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: 168cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * path: given path in the file system 169cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: 170cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * string representing the security context string of the file object 171cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * the string may be NULL if an error occured 172cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: NullPointerException if the path object is null 173cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 174cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) { 175cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 176cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 177c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley } 178c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 179cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars path(env, pathStr); 180cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (path.c_str() == NULL) { 181cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 182cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 183c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 18481ad284517dc80818cd2f3912fbcf9a7b55df119Richard Haines security_context_t tmp = NULL; 185cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = getfilecon(path.c_str(), &tmp); 186cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root Unique_SecurityContext context(tmp); 187c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 188cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedLocalRef<jstring> securityString(env, NULL); 189cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (ret != -1) { 190cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root securityString.reset(env->NewStringUTF(context.get())); 191cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 192c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 193cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("getFileCon(%s) => %s", path.c_str(), context.get()); 194cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return securityString.release(); 195cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 196c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 197cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 198cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: getCon 199cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: Get the context of the current process. 200cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: none 201cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: a jstring representing the security context of the process, 202cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * the jstring may be NULL if there was an error 203cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: none 204cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 205cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jstring getCon(JNIEnv *env, jobject) { 206cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 207cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 208cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 209c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 21081ad284517dc80818cd2f3912fbcf9a7b55df119Richard Haines security_context_t tmp = NULL; 211cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = getcon(&tmp); 212cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root Unique_SecurityContext context(tmp); 213c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 214cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedLocalRef<jstring> securityString(env, NULL); 215cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (ret != -1) { 216cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root securityString.reset(env->NewStringUTF(context.get())); 217cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 218c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 219cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("getCon() => %s", context.get()); 220cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return securityString.release(); 221cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 222c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 223cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 224cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: getPidCon 225cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: Get the context of a process identified by its pid 226cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: 227cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * pid: a jint representing the process 228cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: a jstring representing the security context of the pid, 229cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * the jstring may be NULL if there was an error 230cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: none 231cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 232cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jstring getPidCon(JNIEnv *env, jobject, jint pid) { 233cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 234cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return NULL; 235cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 236c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 23781ad284517dc80818cd2f3912fbcf9a7b55df119Richard Haines security_context_t tmp = NULL; 238cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int ret = getpidcon(static_cast<pid_t>(pid), &tmp); 239cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root Unique_SecurityContext context(tmp); 240c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 241cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedLocalRef<jstring> securityString(env, NULL); 242cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (ret != -1) { 243cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root securityString.reset(env->NewStringUTF(context.get())); 244cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 245c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 246cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("getPidCon(%d) => %s", pid, context.get()); 247cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return securityString.release(); 248cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 249c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 250cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 251cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: checkSELinuxAccess 252cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: Check permissions between two security contexts. 253cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: subjectContextStr: subject security context as a string 254cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * objectContextStr: object security context as a string 255cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * objectClassStr: object's security class name as a string 256cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * permissionStr: permission name as a string 257cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: boolean: (true) if permission was granted, (false) otherwise 258cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: None 259cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 260cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextStr, 261cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root jstring objectContextStr, jstring objectClassStr, jstring permissionStr) { 262cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 263cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return true; 264cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 265c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 266cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars subjectContext(env, subjectContextStr); 267cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (subjectContext.c_str() == NULL) { 268cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 269cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 270c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 271cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars objectContext(env, objectContextStr); 272cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (objectContext.c_str() == NULL) { 273cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 274cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 275c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 276cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars objectClass(env, objectClassStr); 277cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (objectClass.c_str() == NULL) { 278cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 279cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 280c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 281cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars permission(env, permissionStr); 282cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (permission.c_str() == NULL) { 283cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 284cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 285c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 286cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root char *tmp1 = const_cast<char *>(subjectContext.c_str()); 287cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root char *tmp2 = const_cast<char *>(objectContext.c_str()); 288cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root int accessGranted = selinux_check_access(tmp1, tmp2, objectClass.c_str(), permission.c_str(), 289cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root NULL); 290c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 291cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("checkSELinuxAccess(%s, %s, %s, %s) => %d", subjectContext.c_str(), objectContext.c_str(), 292cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root objectClass.c_str(), permission.c_str(), accessGranted); 293c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 294cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return (accessGranted == 0) ? true : false; 295cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 296c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 297cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 298cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Function: native_restorecon 299cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Purpose: restore default SELinux security context 300cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Parameters: pathname: the pathname for the file to be relabeled 301cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Returns: boolean: (true) file label successfully restored, (false) otherwise 302cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * Exceptions: none 303cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 304d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkeystatic jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr, jint flags) { 305cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (isSELinuxDisabled) { 306cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return true; 307cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 308c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 309cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ScopedUtfChars pathname(env, pathnameStr); 310cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root if (pathname.c_str() == NULL) { 311d06969518b12afb27a487ae66f8d73a4d3116587Colin Cross ALOGV("restorecon(%p) => threw exception", pathnameStr); 312cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return false; 313cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root } 314554cb0c290406f5bba34908489db5382a69d0a9arpcraig 315d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey int ret = selinux_android_restorecon(pathname.c_str(), flags); 316cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root ALOGV("restorecon(%s) => %d", pathname.c_str(), ret); 317cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root return (ret == 0); 318cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 319c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 320cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root/* 321cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root * JNI registration. 322cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root */ 32376f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod method_table[] = { 324c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley /* name, signature, funcPtr */ 325c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess }, 326c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "getContext" , "()Ljava/lang/String;" , (void*)getCon }, 327c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "getFileContext" , "(Ljava/lang/String;)Ljava/lang/String;" , (void*)getFileCon }, 328c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "getPeerContext" , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon }, 329c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "getPidContext" , "(I)Ljava/lang/String;" , (void*)getPidCon }, 330c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "isSELinuxEnforced" , "()Z" , (void*)isSELinuxEnforced}, 331c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "isSELinuxEnabled" , "()Z" , (void*)isSELinuxEnabled }, 332d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey { "native_restorecon" , "(Ljava/lang/String;I)Z" , (void*)native_restorecon}, 333c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon }, 334c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley { "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon }, 335cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root}; 336c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 337cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootstatic int log_callback(int type, const char *fmt, ...) { 338c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley va_list ap; 339e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley int priority; 340e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley 341e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley switch (type) { 342e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley case SELINUX_WARNING: 343e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley priority = ANDROID_LOG_WARN; 344e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley break; 345e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley case SELINUX_INFO: 346e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley priority = ANDROID_LOG_INFO; 347e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley break; 348e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley default: 349e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley priority = ANDROID_LOG_ERROR; 350e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley break; 351e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley } 352c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley va_start(ap, fmt); 353e0dda3c8e2c8341e60383619e4ab780bb3b02403Stephen Smalley LOG_PRI_VA(priority, "SELinux", fmt, ap); 354c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley va_end(ap); 355c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley return 0; 356cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 357c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 358cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Rootint register_android_os_SELinux(JNIEnv *env) { 359c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley union selinux_callback cb; 360c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley cb.func_log = log_callback; 361c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley selinux_set_callback(SELINUX_CB_LOG, cb); 362c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 363c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false; 364c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley 365ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, "android/os/SELinux", method_table, NELEM(method_table)); 366cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root} 367cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root 368c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley} 369