1 #include "android_common.h"
2 
3 // For 'system', 'product' (optional), 'vendor' (mandatory) and/or 'odm' (optional).
4 #define MAX_FILE_CONTEXT_SIZE 4
5 
6 #ifdef __ANDROID_VNDK__
7 #ifndef LOG_EVENT_STRING
8 #define LOG_EVENT_STRING(...)
9 #endif  // LOG_EVENT_STRING
10 #endif  // __ANDROID_VNDK__
11 
12 static const struct selinux_opt seopts_service_plat[] = {
13     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_service_contexts" },
14     { SELABEL_OPT_PATH, "/plat_service_contexts" }
15 };
16 static const struct selinux_opt seopts_service_product[] = {
17     { SELABEL_OPT_PATH, "/product/etc/selinux/product_service_contexts" },
18     { SELABEL_OPT_PATH, "/product_service_contexts" }
19 };
20 static const struct selinux_opt seopts_service_vendor[] = {
21     { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_service_contexts" },
22     { SELABEL_OPT_PATH, "/vendor_service_contexts" },
23     // TODO: remove nonplat* when no need to retain backward compatibility.
24     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_service_contexts" },
25     { SELABEL_OPT_PATH, "/nonplat_service_contexts" }
26 };
27 
28 static const struct selinux_opt seopts_hwservice_plat[] = {
29     { SELABEL_OPT_PATH, "/system/etc/selinux/plat_hwservice_contexts" },
30     { SELABEL_OPT_PATH, "/plat_hwservice_contexts" }
31 };
32 static const struct selinux_opt seopts_hwservice_product[] = {
33     { SELABEL_OPT_PATH, "/product/etc/selinux/product_hwservice_contexts" },
34     { SELABEL_OPT_PATH, "/product_hwservice_contexts" }
35 };
36 static const struct selinux_opt seopts_hwservice_vendor[] = {
37     { SELABEL_OPT_PATH, "/vendor/etc/selinux/vendor_hwservice_contexts" },
38     { SELABEL_OPT_PATH, "/vendor_hwservice_contexts" },
39     // TODO: remove nonplat* when no need to retain backward compatibility.
40     { SELABEL_OPT_PATH, "/vendor/etc/selinux/nonplat_hwservice_contexts" },
41     { SELABEL_OPT_PATH, "/nonplat_hwservice_contexts" }
42 };
43 static const struct selinux_opt seopts_hwservice_odm[] = {
44     { SELABEL_OPT_PATH, "/odm/etc/selinux/odm_hwservice_contexts" },
45     { SELABEL_OPT_PATH, "/odm_hwservice_contexts" }
46 };
47 
48 static const struct selinux_opt seopts_vndservice =
49     { SELABEL_OPT_PATH, "/vendor/etc/selinux/vndservice_contexts" };
50 
51 static const struct selinux_opt seopts_vndservice_rootfs =
52     { SELABEL_OPT_PATH, "/vndservice_contexts" };
53 
selinux_android_service_open_context_handle(const struct selinux_opt * seopts_service,unsigned nopts)54 struct selabel_handle* selinux_android_service_open_context_handle(const struct selinux_opt* seopts_service,
55                                                                    unsigned nopts)
56 {
57     struct selabel_handle* sehandle;
58 
59     sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE,
60             seopts_service, nopts);
61 
62     if (!sehandle) {
63         selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
64                 __FUNCTION__, strerror(errno));
65         return NULL;
66     }
67     selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from:\n");
68     for (unsigned i = 0; i < nopts; i++) {
69         selinux_log(SELINUX_INFO, "    %s\n", seopts_service[i].value);
70     }
71     return sehandle;
72 }
73 
selinux_android_service_context_handle(void)74 struct selabel_handle* selinux_android_service_context_handle(void)
75 {
76     struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE];
77     int size = 0;
78     unsigned int i;
79     for (i = 0; i < ARRAY_SIZE(seopts_service_plat); i++) {
80         if (access(seopts_service_plat[i].value, R_OK) != -1) {
81             seopts_service[size++] = seopts_service_plat[i];
82             break;
83         }
84     }
85     for (i = 0; i < ARRAY_SIZE(seopts_service_product); i++) {
86         if (access(seopts_service_product[i].value, R_OK) != -1) {
87             seopts_service[size++] = seopts_service_product[i];
88             break;
89         }
90     }
91     for (i = 0; i < ARRAY_SIZE(seopts_service_vendor); i++) {
92         if (access(seopts_service_vendor[i].value, R_OK) != -1) {
93             seopts_service[size++] = seopts_service_vendor[i];
94             break;
95         }
96     }
97 
98     return selinux_android_service_open_context_handle(seopts_service, size);
99 }
100 
selinux_android_hw_service_context_handle(void)101 struct selabel_handle* selinux_android_hw_service_context_handle(void)
102 {
103     struct selinux_opt seopts_service[MAX_FILE_CONTEXT_SIZE];
104     int size = 0;
105     unsigned int i;
106     for (i = 0; i < ARRAY_SIZE(seopts_hwservice_plat); i++) {
107         if (access(seopts_hwservice_plat[i].value, R_OK) != -1) {
108             seopts_service[size++] = seopts_hwservice_plat[i];
109             break;
110         }
111     }
112     for (i = 0; i < ARRAY_SIZE(seopts_hwservice_product); i++) {
113         if (access(seopts_hwservice_product[i].value, R_OK) != -1) {
114             seopts_service[size++] = seopts_hwservice_product[i];
115             break;
116         }
117     }
118     for (i = 0; i < ARRAY_SIZE(seopts_hwservice_vendor); i++) {
119         if (access(seopts_hwservice_vendor[i].value, R_OK) != -1) {
120             seopts_service[size++] = seopts_hwservice_vendor[i];
121             break;
122         }
123     }
124     for (i = 0; i < ARRAY_SIZE(seopts_hwservice_odm); i++) {
125         if (access(seopts_hwservice_odm[i].value, R_OK) != -1) {
126             seopts_service[size++] = seopts_hwservice_odm[i];
127             break;
128         }
129     }
130     return selinux_android_service_open_context_handle(seopts_service, size);
131 }
132 
selinux_android_vendor_service_context_handle(void)133 struct selabel_handle* selinux_android_vendor_service_context_handle(void)
134 {
135     const struct selinux_opt* seopts_service;
136     if (access(seopts_vndservice.value, R_OK) != -1) {
137         seopts_service = &seopts_vndservice;
138     } else {
139         seopts_service = &seopts_vndservice_rootfs;
140     }
141 
142     return selinux_android_service_open_context_handle(seopts_service, 1);
143 }
144 
selinux_log_callback(int type,const char * fmt,...)145 int selinux_log_callback(int type, const char *fmt, ...)
146 {
147     va_list ap;
148     int priority;
149     char *strp;
150 
151     switch(type) {
152     case SELINUX_WARNING:
153         priority = ANDROID_LOG_WARN;
154         break;
155     case SELINUX_INFO:
156         priority = ANDROID_LOG_INFO;
157         break;
158     default:
159         priority = ANDROID_LOG_ERROR;
160         break;
161     }
162 
163     va_start(ap, fmt);
164     if (vasprintf(&strp, fmt, ap) != -1) {
165         LOG_PRI(priority, "SELinux", "%s", strp);
166         LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
167         free(strp);
168     }
169     va_end(ap);
170     return 0;
171 }
172 
selinux_vendor_log_callback(int type,const char * fmt,...)173 int selinux_vendor_log_callback(int type, const char *fmt, ...)
174 {
175     va_list ap;
176     int priority;
177     char *strp;
178 
179     switch(type) {
180     case SELINUX_WARNING:
181         priority = ANDROID_LOG_WARN;
182         break;
183     case SELINUX_INFO:
184         priority = ANDROID_LOG_INFO;
185         break;
186     default:
187         priority = ANDROID_LOG_ERROR;
188         break;
189     }
190 
191     va_start(ap, fmt);
192     if (vasprintf(&strp, fmt, ap) != -1) {
193         LOG_PRI(priority, "SELinux", "%s", strp);
194         free(strp);
195     }
196     va_end(ap);
197     return 0;
198 }
199