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
20c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "JNIHelp.h"
21c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "jni.h"
22c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "android_runtime/AndroidRuntime.h"
23c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
24c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include "selinux/selinux.h"
25554cb0c290406f5bba34908489db5382a69d0a9arpcraig#include "selinux/android.h"
26c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
27c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#include <errno.h>
28c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
29c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalleynamespace android {
30c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
31c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean isSELinuxDisabled = true;
32c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
33c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static void throw_NullPointerException(JNIEnv *env, const char* msg) {
34c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jclass clazz;
35c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    clazz = env->FindClass("java/lang/NullPointerException");
36c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ThrowNew(clazz, msg);
37c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
38c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
39c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
40c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: isSELinuxEnabled
41c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose:  checks whether SELinux is enabled/disbaled
42c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: none
43c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Return value : true (enabled) or false (disabled)
44c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: none
45c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
46c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) {
47c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
48c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return !isSELinuxDisabled;
49c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
50c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
51c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
52c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: isSELinuxEnforced
53c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: return the current SELinux enforce mode
54c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: none
55c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Return value: true (enforcing) or false (permissive)
56c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: none
57c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
58c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) {
59c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
60c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (security_getenforce() == 1) ? true : false;
61c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
62c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
63c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
64c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
65c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
66c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
67c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: setSELinuxEnforce
68c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: set the SE Linux enforcing mode
69c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: true (enforcing) or false (permissive)
70c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Return value: true (success) or false (fail)
71c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: none
72c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
73c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) {
74c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
75c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
76c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
77c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
78c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int enforce = (value) ? 1 : 0;
79c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
80c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (security_setenforce(enforce) != -1) ? true : false;
81c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
82c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
83c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
84c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
85c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
86c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
87c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getPeerCon
88c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: retrieves security context of peer socket
89c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
90c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *        fileDescriptor: peer socket file as a FileDescriptor object
91c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: jstring representing the security_context of socket or NULL if error
92c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: NullPointerException if fileDescriptor object is NULL
93c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
94c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) {
95c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
96c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
97c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
98c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
99c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (fileDescriptor == NULL) {
100c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      throw_NullPointerException(env, "Trying to check security context of a null peer socket.");
101c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
102c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
103c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
104c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    security_context_t context = NULL;
105c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jstring securityString = NULL;
106c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
107c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
108c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
109c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (env->ExceptionOccurred() != NULL) {
110365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle      ALOGE("There was an issue with retrieving the file descriptor");
111c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
112c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
113c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
114c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (getpeercon(fd, &context) == -1)
115c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
116c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
117365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context);
118c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
119c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    securityString = env->NewStringUTF(context);
120c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
121c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
122c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (context != NULL)
123c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      freecon(context);
124c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
125c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return securityString;
126c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
127c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return NULL;
128c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
129c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
130c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
131c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
132c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: setFSCreateCon
133c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: set security context used for creating a new file system object
134c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
135c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *       context: security_context_t representing the new context of a file system object,
136c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *                set to NULL to return to the default policy behavior
137c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: true on success, false on error
138c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exception: none
139c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
140c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) {
141c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
142c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
143c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
144c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
145c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    char * securityContext = NULL;
146c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *constant_securityContext = NULL;
147c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
148c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (context != NULL) {
149c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      constant_securityContext = env->GetStringUTFChars(context, NULL);
150c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
151c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      // GetStringUTFChars returns const char * yet setfscreatecon needs char *
152c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      securityContext = const_cast<char *>(constant_securityContext);
153c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
154c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
155c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int ret;
156c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if ((ret = setfscreatecon(securityContext)) == -1)
157c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
158c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
159365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context);
160c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
161c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
162c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (constant_securityContext != NULL)
163c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      env->ReleaseStringUTFChars(context, constant_securityContext);
164c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
165c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (ret == 0) ? true : false;
166c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
167c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
168c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
169c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
170c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
171c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
172c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: setFileCon
173c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose:  set the security context of a file object
174c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
175c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *       path: the location of the file system object
176c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *       con: the new security context of the file system object
177c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: true on success, false on error
178c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exception: NullPointerException is thrown if either path or context strign are NULL
179c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
180c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) {
181c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
182c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
183c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
184c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
185c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (path == NULL) {
186c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      throw_NullPointerException(env, "Trying to change the security context of a NULL file object.");
187c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
188c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
189c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
190c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (con == NULL) {
191c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      throw_NullPointerException(env, "Trying to set the security context of a file object with NULL.");
192c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
193c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
194c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
195c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *objectPath = env->GetStringUTFChars(path, NULL);
196c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *constant_con = env->GetStringUTFChars(con, NULL);
197c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
198c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    // GetStringUTFChars returns const char * yet setfilecon needs char *
199c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    char *newCon = const_cast<char *>(constant_con);
200c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
201c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int ret;
202c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if ((ret = setfilecon(objectPath, newCon)) == -1)
203c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
204c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
205365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath);
206c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
207c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
208c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(path, objectPath);
209c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(con, constant_con);
210c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (ret == 0) ? true : false;
211c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
212c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
213c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
214c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
215c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
216c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
217c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getFileCon
218c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: retrieves the context associated with the given path in the file system
219c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
220c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *        path: given path in the file system
221c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns:
222c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *        string representing the security context string of the file object
223c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *        the string may be NULL if an error occured
224c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: NullPointerException if the path object is null
225c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
226c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) {
227c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
228c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
229c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
230c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
231c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (path == NULL) {
232c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      throw_NullPointerException(env, "Trying to check security context of a null path.");
233c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
234c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
235c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
236c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *objectPath = env->GetStringUTFChars(path, NULL);
237c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
238c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    security_context_t context = NULL;
239c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jstring securityString = NULL;
240c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
241c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (getfilecon(objectPath, &context) == -1)
242c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
243c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
244365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath);
245c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
246c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    securityString = env->NewStringUTF(context);
247c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
248c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
249c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (context != NULL)
250c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      freecon(context);
251c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
252c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(path, objectPath);
253c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
254c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return securityString;
255c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
256c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return NULL;
257c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
258c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
259c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
260c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
261c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getCon
262c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Get the context of the current process.
263c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: none
264c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: a jstring representing the security context of the process,
265c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *          the jstring may be NULL if there was an error
266c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: none
267c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
268c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jstring getCon(JNIEnv *env, jobject clazz) {
269c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
270c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
271c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
272c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
273c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    security_context_t context = NULL;
274c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jstring securityString = NULL;
275c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
276c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (getcon(&context) == -1)
277c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
278c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
279365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("getCon: Successfully retrieved context '%s'", context);
280c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
281c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    securityString = env->NewStringUTF(context);
282c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
283c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
284c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (context != NULL)
285c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      freecon(context);
286c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
287c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return securityString;
288c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
289c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return NULL;
290c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
291c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
292c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
293c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
294c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getPidCon
295c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Get the context of a process identified by its pid
296c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
297c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *            pid: a jint representing the process
298c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: a jstring representing the security context of the pid,
299c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *          the jstring may be NULL if there was an error
300c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: none
301c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
302c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) {
303c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
304c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
305c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
306c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
307c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    security_context_t context = NULL;
308c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jstring securityString = NULL;
309c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
310c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    pid_t checkPid = (pid_t)pid;
311c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
312c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (getpidcon(checkPid, &context) == -1)
313c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
314c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
315365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid);
316c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
317c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    securityString = env->NewStringUTF(context);
318c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
319c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
320c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (context != NULL)
321c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      freecon(context);
322c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
323c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return securityString;
324c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
325c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return NULL;
326c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
327c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
328c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
329c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
330c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getBooleanNames
331c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Gets a list of the SELinux boolean names.
332c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: None
333c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: an array of strings  containing the SELinux boolean names.
334c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *          returns NULL string on error
335c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: None
336c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
337c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) {
338c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
339c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
340c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
341c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
342c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    char **list;
343c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int i, len, ret;
344c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jclass stringClass;
345c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    jobjectArray stringArray = NULL;
346c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
347c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (security_get_boolean_names(&list, &len) == -1)
348c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return NULL;
349c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
350c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    stringClass = env->FindClass("java/lang/String");
351c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF(""));
352c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    for (i = 0; i < len; i++) {
353c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      jstring obj;
354c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      obj = env->NewStringUTF(list[i]);
355c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      env->SetObjectArrayElement(stringArray, i, obj);
356c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      env->DeleteLocalRef(obj);
357c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      free(list[i]);
358c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    }
359c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    free(list);
360c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
361c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return stringArray;
362c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
363c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return NULL;
364c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
365c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
366c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
367c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
368c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: getBooleanValue
369c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Gets the value for the given SELinux boolean name.
370c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
371c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *            String: The name of the SELinux boolean.
372c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: a boolean: (true) boolean is set or (false) it is not.
373c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: None
374c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
375c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) {
376c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
377c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
378c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
379c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
380c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *boolean_name;
381c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int ret;
382c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
383c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (name == NULL)
384c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
385c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    boolean_name = env->GetStringUTFChars(name, NULL);
386c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    ret = security_get_boolean_active(boolean_name);
387c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(name, boolean_name);
388c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (ret == 1) ? true : false;
389c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
390c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
391c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
392c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
393c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
394c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
395c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: setBooleanNames
396c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Sets the value for the given SELinux boolean name.
397c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters:
398c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *            String: The name of the SELinux boolean.
399c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *            Boolean: The new value of the SELinux boolean.
400c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: a boolean indicating whether or not the operation succeeded.
401c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: None
402c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
403c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) {
404c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
405c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
406c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
407c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
408c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *boolean_name = NULL;
409c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int ret;
410c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
411c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (name == NULL)
412c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
413c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    boolean_name = env->GetStringUTFChars(name, NULL);
414c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    ret = security_set_boolean(boolean_name, (value) ? 1 : 0);
415c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(name, boolean_name);
416c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (ret)
417c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
418c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
419c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (security_commit_booleans() == -1)
420c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return false;
421c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
422c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return true;
423c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
424c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return false;
425c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
426c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
427c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
428c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
429c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Function: checkSELinuxAccess
430c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Purpose: Check permissions between two security contexts.
431c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Parameters: scon: subject security context as a string
432c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *             tcon: object security context as a string
433c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *             tclass: object's security class name as a string
434c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   *             perm: permission name as a string
435c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Returns: boolean: (true) if permission was granted, (false) otherwise
436c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * Exceptions: None
437c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
438c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) {
439c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
440c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (isSELinuxDisabled)
441c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      return true;
442c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
443c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    int accessGranted = -1;
444c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
445c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const char *const_scon, *const_tcon, *mytclass, *myperm;
446c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    char *myscon, *mytcon;
447c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
448c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL)
449c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley      goto bail;
450c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
451c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const_scon = env->GetStringUTFChars(scon, NULL);
452c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    const_tcon = env->GetStringUTFChars(tcon, NULL);
453c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    mytclass   = env->GetStringUTFChars(tclass, NULL);
454c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    myperm     = env->GetStringUTFChars(perm, NULL);
455c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
456c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    // selinux_check_access needs char* for some
457c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    myscon = const_cast<char *>(const_scon);
458c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    mytcon = const_cast<char *>(const_tcon);
459c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
460c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL);
461c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
462365861e3aae9cccdb19b8d4ee375c57e0a431f1eJoshua Brindle    ALOGV("selinux_check_access returned %d", accessGranted);
463c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
464c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(scon, const_scon);
465c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(tcon, const_tcon);
466c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(tclass, mytclass);
467c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    env->ReleaseStringUTFChars(perm, myperm);
468c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
469c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  bail:
470c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return (accessGranted == 0) ? true : false;
471c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
472c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#else
473c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return true;
474c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
475c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
476c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
477c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  /*
478554cb0c290406f5bba34908489db5382a69d0a9arpcraig   * Function: native_restorecon
479554cb0c290406f5bba34908489db5382a69d0a9arpcraig   * Purpose: restore default SELinux security context
480554cb0c290406f5bba34908489db5382a69d0a9arpcraig   * Parameters: pathname: the pathname for the file to be relabeled
481554cb0c290406f5bba34908489db5382a69d0a9arpcraig   * Returns: boolean: (true) file label successfully restored, (false) otherwise
482554cb0c290406f5bba34908489db5382a69d0a9arpcraig   * Exceptions: none
483554cb0c290406f5bba34908489db5382a69d0a9arpcraig   */
484554cb0c290406f5bba34908489db5382a69d0a9arpcraig  static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) {
485554cb0c290406f5bba34908489db5382a69d0a9arpcraig#ifdef HAVE_SELINUX
486554cb0c290406f5bba34908489db5382a69d0a9arpcraig    if (isSELinuxDisabled)
487554cb0c290406f5bba34908489db5382a69d0a9arpcraig      return true;
488554cb0c290406f5bba34908489db5382a69d0a9arpcraig
489554cb0c290406f5bba34908489db5382a69d0a9arpcraig    const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL));
490554cb0c290406f5bba34908489db5382a69d0a9arpcraig    int ret = selinux_android_restorecon(file);
491554cb0c290406f5bba34908489db5382a69d0a9arpcraig    env->ReleaseStringUTFChars(pathname, file);
492554cb0c290406f5bba34908489db5382a69d0a9arpcraig    return (ret == 0);
493554cb0c290406f5bba34908489db5382a69d0a9arpcraig#else
494554cb0c290406f5bba34908489db5382a69d0a9arpcraig    return true;
495554cb0c290406f5bba34908489db5382a69d0a9arpcraig#endif
496554cb0c290406f5bba34908489db5382a69d0a9arpcraig  }
497554cb0c290406f5bba34908489db5382a69d0a9arpcraig
498554cb0c290406f5bba34908489db5382a69d0a9arpcraig  /*
499c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   * JNI registration.
500c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley   */
501c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static JNINativeMethod method_table[] = {
502c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
503c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    /* name,                     signature,                    funcPtr */
504c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "checkSELinuxAccess"       , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
505c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getBooleanNames"          , "()[Ljava/lang/String;"                        , (void*)getBooleanNames  },
506c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getBooleanValue"          , "(Ljava/lang/String;)Z"                        , (void*)getBooleanValue  },
507c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getContext"               , "()Ljava/lang/String;"                         , (void*)getCon           },
508c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getFileContext"           , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)getFileCon       },
509c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getPeerContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon       },
510c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "getPidContext"            , "(I)Ljava/lang/String;"                        , (void*)getPidCon        },
511c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "isSELinuxEnforced"        , "()Z"                                          , (void*)isSELinuxEnforced},
512c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "isSELinuxEnabled"         , "()Z"                                          , (void*)isSELinuxEnabled },
513554cb0c290406f5bba34908489db5382a69d0a9arpcraig    { "native_restorecon"        , "(Ljava/lang/String;)Z"                        , (void*)native_restorecon},
514c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "setBooleanValue"          , "(Ljava/lang/String;Z)Z"                       , (void*)setBooleanValue  },
515c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "setFileContext"           , "(Ljava/lang/String;Ljava/lang/String;)Z"      , (void*)setFileCon       },
516c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "setFSCreateContext"       , "(Ljava/lang/String;)Z"                        , (void*)setFSCreateCon   },
517c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    { "setSELinuxEnforce"        , "(Z)Z"                                         , (void*)setSELinuxEnforce},
518c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  };
519c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
520c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  static int log_callback(int type, const char *fmt, ...) {
521c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    va_list ap;
522c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    va_start(ap, fmt);
523c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    LOG_PRI_VA(ANDROID_LOG_ERROR, "SELinux", fmt, ap);
524c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    va_end(ap);
525c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return 0;
526c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
527c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
528c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  int register_android_os_SELinux(JNIEnv *env) {
529c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#ifdef HAVE_SELINUX
530c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    union selinux_callback cb;
531c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    cb.func_log = log_callback;
532c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    selinux_set_callback(SELINUX_CB_LOG, cb);
533c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
534c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false;
535c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley
536c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley#endif
537c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley    return AndroidRuntime::registerNativeMethods(
538c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley         env, "android/os/SELinux",
539c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley         method_table, NELEM(method_table));
540c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley  }
541c07fca3831baf4d812dd724f506b4ed23dcc39e0Stephen Smalley}
542