8adb4d9d12
The property service uses an SELinux userspace check to determine if a process is allowed to set a property. If the security check fails, a userspace SELinux denial is generated. Currently, these denials are only sent to dmesg. Instead of sending these denials to dmesg, send it to the kernel audit system. This will cause these userspace denials to be treated similarly to kernel generated denials (eg, logd will pick them up and process them). This will ensure that denials generated by the property service will show up in logcat / dmesg / event log. After this patch, running "setprop asdf asdf" from the unprivileged adb shell user will result in the following audit message: type=1107 audit(39582851.013:48): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=u:r:init:s0 msg='avc: denied { set } for property=asdf pid=5537 uid=2000 gid=2000 scontext=u:r:shell:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service' Test: manual Bug: 27878170 Change-Id: I0b8994888653501f2f315eaa63d9e2ba32d851ef
82 lines
2.3 KiB
C++
82 lines
2.3 KiB
C++
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "log.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
|
|
#include <linux/audit.h>
|
|
#include <netlink/netlink.h>
|
|
#include <selinux/selinux.h>
|
|
|
|
void InitKernelLogging(char* argv[]) {
|
|
// Make stdin/stdout/stderr all point to /dev/null.
|
|
int fd = open("/sys/fs/selinux/null", O_RDWR);
|
|
if (fd == -1) {
|
|
int saved_errno = errno;
|
|
android::base::InitLogging(argv, &android::base::KernelLogger);
|
|
errno = saved_errno;
|
|
PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
|
|
}
|
|
dup2(fd, 0);
|
|
dup2(fd, 1);
|
|
dup2(fd, 2);
|
|
if (fd > 2) close(fd);
|
|
|
|
android::base::InitLogging(argv, &android::base::KernelLogger);
|
|
}
|
|
|
|
static void selinux_avc_log(char* buf, size_t buf_len) {
|
|
size_t str_len = strnlen(buf, buf_len);
|
|
|
|
// trim newline at end of string
|
|
buf[str_len - 1] = '\0';
|
|
|
|
struct nl_sock* sk = nl_socket_alloc();
|
|
if (sk == NULL) {
|
|
return;
|
|
}
|
|
nl_connect(sk, NETLINK_AUDIT);
|
|
int result;
|
|
do {
|
|
result = nl_send_simple(sk, AUDIT_USER_AVC, 0, buf, str_len);
|
|
} while (result == -NLE_INTR);
|
|
nl_socket_free(sk);
|
|
}
|
|
|
|
int selinux_klog_callback(int type, const char *fmt, ...) {
|
|
android::base::LogSeverity severity = android::base::ERROR;
|
|
if (type == SELINUX_WARNING) {
|
|
severity = android::base::WARNING;
|
|
} else if (type == SELINUX_INFO) {
|
|
severity = android::base::INFO;
|
|
}
|
|
char buf[1024];
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
int res = vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
va_end(ap);
|
|
if (res <= 0) {
|
|
return 0;
|
|
}
|
|
if (type == SELINUX_AVC) {
|
|
selinux_avc_log(buf, sizeof(buf));
|
|
} else {
|
|
android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
|
|
}
|
|
return 0;
|
|
}
|