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