• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 
6 #include <log/log.h>
7 #include <selinux/android.h>
8 #include <selinux/label.h>
9 
10 #include "android_internal.h"
11 #include "callbacks.h"
12 
13 #ifdef __ANDROID_VNDK__
14 #ifndef LOG_EVENT_STRING
15 #define LOG_EVENT_STRING(...)
16 #endif  // LOG_EVENT_STRING
17 #endif  // __ANDROID_VNDK__
18 
19 static const path_alts_t service_context_paths = { .paths = {
20 	{
21 		"/system/etc/selinux/plat_service_contexts",
22 		"/plat_service_contexts"
23 	},
24 	{
25 		"/dev/selinux/apex_service_contexts"
26 	},
27 	{
28 		"/system_ext/etc/selinux/system_ext_service_contexts",
29 		"/system_ext_service_contexts"
30 	},
31 	{
32 		"/product/etc/selinux/product_service_contexts",
33 		"/product_service_contexts"
34 	},
35 	{
36 		"/vendor/etc/selinux/vendor_service_contexts",
37 		"/vendor_service_contexts"
38 	},
39 	{
40 		"/odm/etc/selinux/odm_service_contexts",
41 	}
42 }};
43 
44 static const path_alts_t hwservice_context_paths = { .paths = {
45 	{
46 		"/system/etc/selinux/plat_hwservice_contexts",
47 		"/plat_hwservice_contexts"
48 	},
49 	{
50 		"/system_ext/etc/selinux/system_ext_hwservice_contexts",
51 		"/system_ext_hwservice_contexts"
52 	},
53 	{
54 		"/product/etc/selinux/product_hwservice_contexts",
55 		"/product_hwservice_contexts"
56 	},
57 	{
58 		"/vendor/etc/selinux/vendor_hwservice_contexts",
59 		"/vendor_hwservice_contexts"
60 	},
61 	{
62 		"/odm/etc/selinux/odm_hwservice_contexts",
63 		"/odm_hwservice_contexts"
64 	},
65 }};
66 
67 static const path_alts_t vndservice_context_paths = { .paths = {
68 	{
69 		"/vendor/etc/selinux/vndservice_contexts",
70 		"/vndservice_contexts"
71 	}
72 }};
73 
74 static const path_alts_t keystore2_context_paths = { .paths = {
75 	{
76 		"/system/etc/selinux/plat_keystore2_key_contexts",
77 		"/plat_keystore2_key_contexts"
78 	},
79 	{
80 		"/system_ext/etc/selinux/system_ext_keystore2_key_contexts",
81 		"/system_ext_keystore2_key_contexts"
82 	},
83 	{
84 		"/product/etc/selinux/product_keystore2_key_contexts",
85 		"/product_keystore2_key_contexts"
86 	},
87 	{
88 		"/vendor/etc/selinux/vendor_keystore2_key_contexts",
89 		"/vendor_keystore2_key_contexts"
90 	}
91 }};
92 
find_existing_files(const path_alts_t * path_sets,const char * paths[MAX_CONTEXT_PATHS])93 size_t find_existing_files(
94 		const path_alts_t *path_sets,
95 		const char* paths[MAX_CONTEXT_PATHS])
96 {
97 	size_t i, j, len = 0;
98 	for (i = 0; i < MAX_CONTEXT_PATHS; i++) {
99 		for (j = 0; j < MAX_ALT_CONTEXT_PATHS; j++) {
100 			const char* file = path_sets->paths[i][j];
101 			if (file && access(file, R_OK) != -1) {
102 				paths[len++] = file;
103 				/* Within each set, only the first valid entry is used */
104 				break;
105 			}
106 		}
107 	}
108 	return len;
109 }
110 
paths_to_opts(const char * paths[MAX_CONTEXT_PATHS],size_t npaths,struct selinux_opt * const opts)111 void paths_to_opts(const char* paths[MAX_CONTEXT_PATHS],
112 		size_t npaths,
113 		struct selinux_opt* const opts)
114 {
115 	for (size_t i = 0; i < npaths; i++) {
116 		opts[i].type = SELABEL_OPT_PATH;
117 		opts[i].value = paths[i];
118 	}
119 }
120 
initialize_backend(unsigned int backend,const char * name,const struct selinux_opt * opts,size_t nopts)121 struct selabel_handle* initialize_backend(
122 		unsigned int backend,
123 		const char* name,
124 		const struct selinux_opt* opts,
125 		size_t nopts)
126 {
127 		struct selabel_handle* sehandle;
128 
129 		sehandle = selabel_open(backend, opts, nopts);
130 
131 		if (!sehandle) {
132 				selinux_log(SELINUX_ERROR, "%s: Error getting %s handle (%s)\n",
133 								__FUNCTION__, name, strerror(errno));
134 				return NULL;
135 		}
136 		selinux_log(SELINUX_INFO, "SELinux: Loaded %s context from:\n", name);
137 		for (unsigned i = 0; i < nopts; i++) {
138 			if (opts[i].type == SELABEL_OPT_PATH)
139 				selinux_log(SELINUX_INFO, "		%s\n", opts[i].value);
140 		}
141 		return sehandle;
142 }
143 
context_handle(unsigned int backend,const path_alts_t * context_paths,const char * name)144 struct selabel_handle* context_handle(
145 		unsigned int backend,
146 		const path_alts_t *context_paths,
147 		const char *name)
148 {
149 	const char* existing_paths[MAX_CONTEXT_PATHS];
150 	struct selinux_opt opts[MAX_CONTEXT_PATHS];
151 	int size = 0;
152 
153 	size = find_existing_files(context_paths, existing_paths);
154 	paths_to_opts(existing_paths, size, opts);
155 
156 	return initialize_backend(backend, name, opts, size);
157 }
158 
selinux_android_service_context_handle(void)159 struct selabel_handle* selinux_android_service_context_handle(void)
160 {
161 	return context_handle(SELABEL_CTX_ANDROID_SERVICE, &service_context_paths, "service");
162 }
163 
selinux_android_hw_service_context_handle(void)164 struct selabel_handle* selinux_android_hw_service_context_handle(void)
165 {
166 	return context_handle(SELABEL_CTX_ANDROID_SERVICE, &hwservice_context_paths, "hwservice");
167 }
168 
selinux_android_vendor_service_context_handle(void)169 struct selabel_handle* selinux_android_vendor_service_context_handle(void)
170 {
171 	return context_handle(SELABEL_CTX_ANDROID_SERVICE, &vndservice_context_paths, "vndservice");
172 }
173 
selinux_android_keystore2_key_context_handle(void)174 struct selabel_handle* selinux_android_keystore2_key_context_handle(void)
175 {
176 	return context_handle(SELABEL_CTX_ANDROID_KEYSTORE2_KEY, &keystore2_context_paths, "keystore2");
177 }
178 
__selinux_log_callback(bool add_to_event_log,int type,const char * fmt,va_list ap)179 static void __selinux_log_callback(bool add_to_event_log, int type, const char *fmt, va_list ap) {
180 	int priority;
181 	char *strp;
182 
183 	switch(type) {
184 	case SELINUX_WARNING:
185 		priority = ANDROID_LOG_WARN;
186 		break;
187 	case SELINUX_INFO:
188 		priority = ANDROID_LOG_INFO;
189 		break;
190 	default:
191 		priority = ANDROID_LOG_ERROR;
192 		break;
193 	}
194 
195 	int len = vasprintf(&strp, fmt, ap);
196 	if (len < 0) {
197 		return;
198 	}
199 
200 	/* libselinux log messages usually contain a new line character, while
201 	 * Android LOG() does not expect it. Remove it to avoid empty lines in
202 	 * the log buffers.
203 	 */
204 	if (len > 0 && strp[len - 1] == '\n') {
205 		strp[len - 1] = '\0';
206 	}
207 	LOG_PRI(priority, "SELinux", "%s", strp);
208 	if (add_to_event_log) {
209 		LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
210 	}
211 	free(strp);
212 }
213 
selinux_log_callback(int type,const char * fmt,...)214 int selinux_log_callback(int type, const char *fmt, ...)
215 {
216 	va_list ap;
217 	va_start(ap, fmt);
218 	__selinux_log_callback(true, type, fmt, ap);
219 	va_end(ap);
220 	return 0;
221 }
222 
selinux_vendor_log_callback(int type,const char * fmt,...)223 int selinux_vendor_log_callback(int type, const char *fmt, ...)
224 {
225 	va_list ap;
226 	va_start(ap, fmt);
227 	__selinux_log_callback(false, type, fmt, ap);
228 	va_end(ap);
229 	return 0;
230 }
231