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