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"
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>
27cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root#include <ScopedLocalRef.h>
28cd19e3f2db333afcf84e2d66d9811e6ccae733a2Kenny Root#include <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