1 /*
2 * auth_base_impl.c
3 *
4 * function for base hash operation
5 *
6 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17 #include "auth_base_impl.h"
18 #include <linux/string.h>
19 #include <linux/mutex.h>
20 #include <linux/types.h>
21 #include <linux/rwsem.h>
22 #include <linux/path.h>
23 #include <linux/file.h>
24 #include <linux/fs.h>
25
26 #include <linux/mm.h>
27 #include <linux/dcache.h>
28 #include <linux/mm_types.h>
29 #include <linux/highmem.h>
30 #include <linux/cred.h>
31 #include <linux/slab.h>
32 #if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
33 #include <linux/sched/mm.h>
34 #endif
35 #if defined (CONFIG_SELINUX_AUTH_ENABLE) && defined (CONFIG_SECURITY_SELINUX)
36 #include <linux/security.h>
37 #endif
38 #include <securec.h>
39 #include "tc_ns_log.h"
40 #include "tc_ns_client.h"
41 #include "agent.h" /* for get_proc_dpath */
42 #include "ko_adapt.h"
43
44 /* for crypto */
45 struct crypto_shash *g_shash_handle;
46 bool g_shash_handle_state = false;
47 struct mutex g_shash_handle_lock;
48
init_crypto_hash_lock(void)49 void init_crypto_hash_lock(void)
50 {
51 mutex_init(&g_shash_handle_lock);
52 }
53
mutex_crypto_hash_lock(void)54 void mutex_crypto_hash_lock(void)
55 {
56 mutex_lock(&g_shash_handle_lock);
57 }
58
mutex_crypto_hash_unlock(void)59 void mutex_crypto_hash_unlock(void)
60 {
61 mutex_unlock(&g_shash_handle_lock);
62 }
63
64 /* begin: prepare crypto context */
get_shash_handle(void)65 struct crypto_shash *get_shash_handle(void)
66 {
67 return g_shash_handle;
68 }
69
free_shash_handle(void)70 void free_shash_handle(void)
71 {
72 if (g_shash_handle) {
73 crypto_free_shash(g_shash_handle);
74 g_shash_handle_state = false;
75 g_shash_handle = NULL;
76 }
77 }
78
tee_init_shash_handle(char * hash_type)79 int tee_init_shash_handle(char *hash_type)
80 {
81 long rc;
82
83 if (!hash_type) {
84 tloge("tee init crypto: error input parameter\n");
85 return -EFAULT;
86 }
87
88 mutex_crypto_hash_lock();
89 if (g_shash_handle_state) {
90 mutex_crypto_hash_unlock();
91 return 0;
92 }
93
94 g_shash_handle = crypto_alloc_shash(hash_type, 0, 0);
95 if (IS_ERR_OR_NULL(g_shash_handle)) {
96 rc = PTR_ERR(g_shash_handle);
97 tloge("Can not allocate %s reason: %ld\n", hash_type, rc);
98 mutex_crypto_hash_unlock();
99 return rc;
100 }
101 g_shash_handle_state = true;
102
103 mutex_crypto_hash_unlock();
104 return 0;
105 }
106 /* end: prepare crypto context */
107
108 /* begin: Calculate the SHA256 file digest */
prepare_desc(struct sdesc ** desc)109 static int prepare_desc(struct sdesc **desc)
110 {
111 size_t size;
112 size_t shash_size;
113
114 shash_size = crypto_shash_descsize(g_shash_handle);
115 size = sizeof((*desc)->shash) + shash_size;
116 if (size < sizeof((*desc)->shash) || size < shash_size) {
117 tloge("size flow\n");
118 return -ENOMEM;
119 }
120
121 *desc = kzalloc(size, GFP_KERNEL);
122 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*desc))) {
123 tloge("alloc desc failed\n");
124 return -ENOMEM;
125 }
126
127 return EOK;
128 }
129
130 #define PINED_PAGE_NUMBER 1
get_proc_user_pages(struct mm_struct * mm,unsigned long start_code,struct page ** ptr_page,struct task_struct * cur_struct)131 static int get_proc_user_pages(struct mm_struct *mm, unsigned long start_code,
132 struct page **ptr_page, struct task_struct *cur_struct)
133 {
134 #if (KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE)
135 (void)cur_struct;
136 return get_user_pages_remote(mm, start_code,
137 (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL, NULL);
138 #elif (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
139 return get_user_pages_remote(cur_struct, mm, start_code,
140 (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL, NULL);
141 #elif (KERNEL_VERSION(4, 4, 197) == LINUX_VERSION_CODE)
142 return get_user_pages_locked(cur_struct, mm, start_code,
143 (unsigned long)PINED_PAGE_NUMBER, FOLL_FORCE, ptr_page, NULL);
144 #else
145 return get_user_pages_locked(cur_struct, mm, start_code,
146 (unsigned long)PINED_PAGE_NUMBER, 0, 1, ptr_page, NULL);
147 #endif
148 }
149
update_task_hash(struct mm_struct * mm,struct task_struct * cur_struct,struct shash_desc * shash)150 static int update_task_hash(struct mm_struct *mm,
151 struct task_struct *cur_struct, struct shash_desc *shash)
152 {
153 int rc = -1;
154 unsigned long in_size;
155 struct page *ptr_page = NULL;
156 void *ptr_base = NULL;
157
158 unsigned long start_code = mm->start_code;
159 unsigned long end_code = mm->end_code;
160 unsigned long code_size = end_code - start_code;
161 if (code_size == 0) {
162 tloge("bad code size\n");
163 return -EINVAL;
164 }
165
166 while (start_code < end_code) {
167 /* Get a handle of the page we want to read */
168 rc = get_proc_user_pages(mm, start_code, &ptr_page, cur_struct);
169 if (rc != PINED_PAGE_NUMBER) {
170 tloge("get user pages error[0x%x]\n", rc);
171 rc = -EFAULT;
172 break;
173 }
174
175 ptr_base = kmap_atomic(ptr_page);
176 if (!ptr_base) {
177 rc = -EFAULT;
178 put_page(ptr_page);
179 break;
180 }
181
182 in_size = (code_size > PAGE_SIZE) ? PAGE_SIZE : code_size;
183 rc = crypto_shash_update(shash, ptr_base, in_size);
184 if (rc) {
185 kunmap_atomic(ptr_base);
186 put_page(ptr_page);
187 break;
188 }
189
190 kunmap_atomic(ptr_base);
191 put_page(ptr_page);
192 start_code += in_size;
193 code_size = end_code - start_code;
194 }
195 return rc;
196 }
197
calc_task_hash(unsigned char * digest,uint32_t dig_len,struct task_struct * cur_struct,uint32_t pub_key_len)198 int calc_task_hash(unsigned char *digest, uint32_t dig_len,
199 struct task_struct *cur_struct, uint32_t pub_key_len)
200 {
201 struct mm_struct *mm = NULL;
202 struct sdesc *desc = NULL;
203 bool check_value = false;
204 int rc;
205
206 check_value = (!cur_struct || !digest ||
207 dig_len != SHA256_DIGEST_LENTH);
208 if (check_value) {
209 tloge("tee hash: input param is error\n");
210 return -EFAULT;
211 }
212
213 mm = get_task_mm(cur_struct);
214 if (!mm) {
215 if (memset_s(digest, dig_len, 0, MAX_SHA_256_SZ))
216 return -EFAULT;
217 tloge("kernel proc need not check\n");
218 return EOK;
219 }
220
221 if (pub_key_len != sizeof(uint32_t)) {
222 tloge("apk need not check\n");
223 mmput(mm);
224 return EOK;
225 }
226
227 if (prepare_desc(&desc) != EOK) {
228 mmput(mm);
229 tloge("prepare desc failed\n");
230 return -ENOMEM;
231 }
232
233 desc->shash.tfm = g_shash_handle;
234 if (crypto_shash_init(&desc->shash)) {
235 tloge("shash init failed\n");
236 rc = -ENOMEM;
237 goto free_res;
238 }
239
240 down_read(&mm_sem_lock(mm));
241 if (update_task_hash(mm, cur_struct, &desc->shash)) {
242 up_read(&mm_sem_lock(mm));
243 rc = -ENOMEM;
244 goto free_res;
245 }
246 up_read(&mm_sem_lock(mm));
247
248 rc = crypto_shash_final(&desc->shash, digest);
249 free_res:
250 mmput(mm);
251 kfree(desc);
252 return rc;
253 }
254 /* end: Calculate the SHA256 file digest */
255
256 #if defined(CONFIG_SELINUX_AUTH_ENABLE) && defined (CONFIG_SECURITY_SELINUX)
check_proc_selinux_access(const char * s_ctx)257 static int check_proc_selinux_access(const char * s_ctx)
258 {
259 if (s_ctx == NULL) {
260 tloge("bad params\n");
261 return CHECK_ACCESS_FAIL;
262 }
263
264 int rc;
265 u32 sid;
266 u32 tid;
267 u32 s_ctx_len = strnlen(s_ctx, MAX_SCTX_LEN);
268 if (s_ctx_len == 0 || s_ctx_len >= MAX_SCTX_LEN) {
269 tloge("invalid selinux ctx\n");
270 return CHECK_ACCESS_FAIL;
271 }
272
273 security_task_getsecid(current, &sid);
274 rc = security_secctx_to_secid(s_ctx, s_ctx_len, &tid);
275 if (rc != 0) {
276 tloge("secctx to sid failed, rc %d", rc);
277 return CHECK_ACCESS_FAIL;
278 }
279 if (sid != tid) {
280 tloge("check selinux label failed\n");
281 return CHECK_ACCESS_FAIL;
282 }
283
284 return EOK;
285 }
286 #else
check_proc_selinux_access(const char * s_ctx)287 static int check_proc_selinux_access(const char * s_ctx)
288 {
289 (void)s_ctx;
290 return 0;
291 }
292 #endif
293
get_proc_uid(uid_t * proc_uid)294 static int get_proc_uid(uid_t *proc_uid)
295 {
296 #ifdef CONFIG_LIBLINUX
297 if (current->cred == NULL) {
298 tloge("cred is NULL\n");
299 return CHECK_ACCESS_FAIL;
300 }
301 *proc_uid = current->cred->uid.val;
302 #else
303 const struct cred *cred = NULL;
304 get_task_struct(current);
305 cred = koadpt_get_task_cred(current);
306 if (cred == NULL) {
307 tloge("cred is NULL\n");
308 put_task_struct(current);
309 return CHECK_ACCESS_FAIL;
310 }
311
312 *proc_uid = cred->uid.val;
313 put_cred(cred);
314 put_task_struct(current);
315 #endif
316 return CHECK_ACCESS_SUCC;
317 }
318
check_proc_uid_path(const char * auth_ctx)319 static int check_proc_uid_path(const char *auth_ctx)
320 {
321 int ret = 0;
322 char str_path_uid[MAX_PATH_SIZE] = { 0 };
323 char *pro_dpath = NULL;
324 char *k_path = NULL;
325 u32 auth_ctx_len;
326 uid_t proc_uid;
327
328 if (auth_ctx == NULL) {
329 tloge("bad params\n");
330 return CHECK_ACCESS_FAIL;
331 }
332
333 auth_ctx_len = (u32)strnlen(auth_ctx, MAX_PATH_SIZE);
334 if (auth_ctx_len == 0 || auth_ctx_len >= MAX_PATH_SIZE) {
335 tloge("invalid uid path\n");
336 return CHECK_ACCESS_FAIL;
337 }
338
339 k_path = kmalloc(MAX_PATH_SIZE, GFP_KERNEL);
340 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)k_path)) {
341 tloge("path kmalloc fail\n");
342 return CHECK_ACCESS_FAIL;
343 }
344
345 pro_dpath = get_proc_dpath(k_path, MAX_PATH_SIZE);
346 if (IS_ERR_OR_NULL(pro_dpath)) {
347 kfree(k_path);
348 return CHECK_ACCESS_FAIL;
349 }
350
351 ret = get_proc_uid(&proc_uid);
352 if (ret != CHECK_ACCESS_SUCC) {
353 tloge("get proc uid failed\n");
354 goto clean;
355 }
356
357 if (snprintf_s(str_path_uid, MAX_PATH_SIZE, MAX_PATH_SIZE - 1, "%s:%u",
358 pro_dpath, (unsigned int)proc_uid) < 0) {
359 tloge("snprintf_s path uid failed, ret %d\n", ret);
360 ret = CHECK_ACCESS_FAIL;
361 goto clean;
362 }
363
364 if (strnlen(str_path_uid, MAX_PATH_SIZE) != auth_ctx_len || strncmp(str_path_uid, auth_ctx, auth_ctx_len) != 0)
365 ret = ENTER_BYPASS_CHANNEL;
366 else
367 ret = CHECK_ACCESS_SUCC;
368
369 clean:
370 kfree(k_path);
371 return ret;
372 }
373
374 #ifdef CONFIG_CADAEMON_AUTH
check_cadaemon_auth(void)375 int check_cadaemon_auth(void)
376 {
377 int ret = check_proc_uid_path(CADAEMON_PATH_UID_AUTH_CTX);
378 if (ret != 0) {
379 tloge("check cadaemon path failed, ret %d\n", ret);
380 return ret;
381 }
382 ret = check_proc_selinux_access(SELINUX_CADAEMON_LABEL);
383 if (ret != 0) {
384 tloge("check cadaemon selinux label failed!, ret %d\n", ret);
385 return -EACCES;
386 }
387 return 0;
388 }
389 #endif
390
check_hidl_auth(void)391 int check_hidl_auth(void)
392 {
393 int ret = check_proc_uid_path(CA_HIDL_PATH_UID_AUTH_CTX);
394 if (ret != CHECK_ACCESS_SUCC)
395 return ret;
396
397 #if defined(CONFIG_SELINUX_AUTH_ENABLE) && defined (CONFIG_SECURITY_SELINUX)
398 ret = check_proc_selinux_access(SELINUX_CA_HIDL_LABEL);
399 if (ret != EOK) {
400 tloge("check hidl selinux label failed, ret %d\n", ret);
401 return CHECK_SECLABEL_FAIL;
402 }
403 #endif
404
405 return CHECK_ACCESS_SUCC;
406 }
407
408 #ifdef CONFIG_TEECD_AUTH
check_teecd_auth(void)409 int check_teecd_auth(void)
410 {
411 int ret = check_proc_uid_path(TEECD_PATH_UID_AUTH_CTX);
412 if (ret != 0) {
413 tloge("check teecd path failed, ret %d\n", ret);
414 return ret;
415 }
416
417 #if defined(CONFIG_SELINUX_AUTH_ENABLE) && defined (CONFIG_SECURITY_SELINUX)
418 ret = check_proc_selinux_access(SELINUX_TEECD_LABEL);
419 if (ret != 0) {
420 tloge("check teecd selinux label failed!, ret %d\n", ret);
421 return -EACCES;
422 }
423 #endif
424 return CHECK_ACCESS_SUCC;
425 }
426 #endif