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 */
45struct crypto_shash *g_shash_handle;
46bool g_shash_handle_state = false;
47struct mutex g_shash_handle_lock;
48
49void init_crypto_hash_lock(void)
50{
51	mutex_init(&g_shash_handle_lock);
52}
53
54void mutex_crypto_hash_lock(void)
55{
56	mutex_lock(&g_shash_handle_lock);
57}
58
59void mutex_crypto_hash_unlock(void)
60{
61	mutex_unlock(&g_shash_handle_lock);
62}
63
64/* begin: prepare crypto context */
65struct crypto_shash *get_shash_handle(void)
66{
67	return g_shash_handle;
68}
69
70void 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
79int 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 */
109static 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
131static 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
150static 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
198int 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);
249free_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)
257static 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
287static int check_proc_selinux_access(const char * s_ctx)
288{
289	(void)s_ctx;
290	return 0;
291}
292#endif
293
294static 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
319static 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
369clean:
370	kfree(k_path);
371	return ret;
372}
373
374#ifdef CONFIG_CADAEMON_AUTH
375int 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
391int 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
409int 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