| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <cil/cil.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <utils.h>
 | 
					
						
							|  |  |  | #include <logging.h>
 | 
					
						
							| 
									
										
										
										
											2019-11-20 21:48:49 -05:00
										 |  |  | #include <stream.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-09 04:14:30 -05:00
										 |  |  | #include <magiskpolicy.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "sepolicy.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int load_policydb(const char *file) { | 
					
						
							| 
									
										
										
										
											2019-12-13 06:05:12 -05:00
										 |  |  | 	LOGD("Load policy from: %s\n", file); | 
					
						
							| 
									
										
										
										
											2019-11-19 05:20:18 -05:00
										 |  |  | 	if (magisk_policydb) | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 		destroy_policydb(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct policy_file pf; | 
					
						
							|  |  |  | 	policy_file_init(&pf); | 
					
						
							|  |  |  | 	pf.fp = xfopen(file, "re"); | 
					
						
							|  |  |  | 	pf.type = PF_USE_STDIO; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 05:20:18 -05:00
										 |  |  | 	magisk_policydb = static_cast<policydb_t *>(xmalloc(sizeof(policydb_t))); | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	if (policydb_init(magisk_policydb) || policydb_read(magisk_policydb, &pf, 0)) { | 
					
						
							|  |  |  | 		LOGE("Fail to load policy from %s\n", file); | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	fclose(pf.fp); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SHALEN 64
 | 
					
						
							|  |  |  | static bool cmp_sha256(const char *a, const char *b) { | 
					
						
							|  |  |  | 	char id_a[SHALEN] = {0}; | 
					
						
							|  |  |  | 	char id_b[SHALEN] = {0}; | 
					
						
							|  |  |  | 	if (int fd = xopen(a, O_RDONLY | O_CLOEXEC); fd >= 0) { | 
					
						
							|  |  |  | 		xread(fd, id_a, SHALEN); | 
					
						
							|  |  |  | 		close(fd); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (int fd = xopen(b, O_RDONLY | O_CLOEXEC); fd >= 0) { | 
					
						
							|  |  |  | 		xread(fd, id_b, SHALEN); | 
					
						
							|  |  |  | 		close(fd); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-04 00:26:16 -04:00
										 |  |  | 	LOGD("%s=[%.*s]\n", a, SHALEN, id_a); | 
					
						
							|  |  |  | 	LOGD("%s=[%.*s]\n", b, SHALEN, id_b); | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	return memcmp(id_a, id_b, SHALEN) == 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool check_precompiled(const char *precompiled) { | 
					
						
							|  |  |  | 	bool ok = false; | 
					
						
							|  |  |  | 	const char *actual_sha; | 
					
						
							|  |  |  | 	char compiled_sha[128]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actual_sha = PLAT_POLICY_DIR "plat_and_mapping_sepolicy.cil.sha256"; | 
					
						
							|  |  |  | 	if (access(actual_sha, R_OK) == 0) { | 
					
						
							|  |  |  | 		ok = true; | 
					
						
							|  |  |  | 		sprintf(compiled_sha, "%s.plat_and_mapping.sha256", precompiled); | 
					
						
							|  |  |  | 		if (!cmp_sha256(actual_sha, compiled_sha)) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actual_sha = PLAT_POLICY_DIR "plat_sepolicy_and_mapping.sha256"; | 
					
						
							|  |  |  | 	if (access(actual_sha, R_OK) == 0) { | 
					
						
							|  |  |  | 		ok = true; | 
					
						
							|  |  |  | 		sprintf(compiled_sha, "%s.plat_sepolicy_and_mapping.sha256", precompiled); | 
					
						
							|  |  |  | 		if (!cmp_sha256(actual_sha, compiled_sha)) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actual_sha = PROD_POLICY_DIR "product_sepolicy_and_mapping.sha256"; | 
					
						
							|  |  |  | 	if (access(actual_sha, R_OK) == 0) { | 
					
						
							|  |  |  | 		ok = true; | 
					
						
							|  |  |  | 		sprintf(compiled_sha, "%s.product_sepolicy_and_mapping.sha256", precompiled); | 
					
						
							|  |  |  | 		if (!cmp_sha256(actual_sha, compiled_sha) != 0) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 00:49:33 -08:00
										 |  |  | 	actual_sha = SYSEXT_POLICY_DIR "system_ext_sepolicy_and_mapping.sha256"; | 
					
						
							|  |  |  | 	if (access(actual_sha, R_OK) == 0) { | 
					
						
							|  |  |  | 		ok = true; | 
					
						
							|  |  |  | 		sprintf(compiled_sha, "%s.system_ext_sepolicy_and_mapping.sha256", precompiled); | 
					
						
							|  |  |  | 		if (!cmp_sha256(actual_sha, compiled_sha) != 0) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int load_split_cil() { | 
					
						
							|  |  |  | 	const char *odm_pre = ODM_POLICY_DIR "precompiled_sepolicy"; | 
					
						
							|  |  |  | 	const char *vend_pre = VEND_POLICY_DIR "precompiled_sepolicy"; | 
					
						
							|  |  |  | 	if (access(odm_pre, R_OK) == 0 && check_precompiled(odm_pre)) | 
					
						
							|  |  |  | 		return load_policydb(odm_pre); | 
					
						
							|  |  |  | 	else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre)) | 
					
						
							|  |  |  | 		return load_policydb(vend_pre); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return compile_split_cil(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void load_cil(struct cil_db *db, const char *file) { | 
					
						
							|  |  |  | 	char *addr; | 
					
						
							|  |  |  | 	size_t size; | 
					
						
							|  |  |  | 	mmap_ro(file, addr, size); | 
					
						
							|  |  |  | 	cil_add_file(db, (char *) file, addr, size); | 
					
						
							| 
									
										
										
										
											2019-12-13 06:05:12 -05:00
										 |  |  | 	LOGD("cil_add [%s]\n", file); | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	munmap(addr, size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int compile_split_cil() { | 
					
						
							|  |  |  | 	char path[128], plat_ver[10]; | 
					
						
							|  |  |  | 	struct cil_db *db = nullptr; | 
					
						
							|  |  |  | 	sepol_policydb_t *pdb = nullptr; | 
					
						
							|  |  |  | 	FILE *f; | 
					
						
							|  |  |  | 	int policy_ver; | 
					
						
							|  |  |  | 	const char *cil_file; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cil_db_init(&db); | 
					
						
							|  |  |  | 	cil_set_mls(db, 1); | 
					
						
							|  |  |  | 	cil_set_multiple_decls(db, 1); | 
					
						
							|  |  |  | 	cil_set_disable_neverallow(db, 1); | 
					
						
							|  |  |  | 	cil_set_target_platform(db, SEPOL_TARGET_SELINUX); | 
					
						
							|  |  |  | 	cil_set_attrs_expand_generated(db, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f = xfopen(SELINUX_VERSION, "re"); | 
					
						
							|  |  |  | 	fscanf(f, "%d", &policy_ver); | 
					
						
							|  |  |  | 	fclose(f); | 
					
						
							|  |  |  | 	cil_set_policy_version(db, policy_ver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get mapping version
 | 
					
						
							|  |  |  | 	f = xfopen(VEND_POLICY_DIR "plat_sepolicy_vers.txt", "re"); | 
					
						
							|  |  |  | 	fscanf(f, "%s", plat_ver); | 
					
						
							|  |  |  | 	fclose(f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// plat
 | 
					
						
							|  |  |  | 	load_cil(db, SPLIT_PLAT_CIL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf(path, PLAT_POLICY_DIR "mapping/%s.cil", plat_ver); | 
					
						
							|  |  |  | 	load_cil(db, path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// product
 | 
					
						
							|  |  |  | 	sprintf(path, PROD_POLICY_DIR "mapping/%s.cil", plat_ver); | 
					
						
							|  |  |  | 	if (access(path, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cil_file = PROD_POLICY_DIR "product_sepolicy.cil"; | 
					
						
							|  |  |  | 	if (access(cil_file, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, cil_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// vendor
 | 
					
						
							|  |  |  | 	cil_file = VEND_POLICY_DIR "nonplat_sepolicy.cil"; | 
					
						
							|  |  |  | 	if (access(cil_file, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, cil_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cil_file = VEND_POLICY_DIR "plat_pub_versioned.cil"; | 
					
						
							|  |  |  | 	if (access(cil_file, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, cil_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cil_file = VEND_POLICY_DIR "vendor_sepolicy.cil"; | 
					
						
							|  |  |  | 	if (access(cil_file, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, cil_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// odm
 | 
					
						
							|  |  |  | 	cil_file = ODM_POLICY_DIR "odm_sepolicy.cil"; | 
					
						
							|  |  |  | 	if (access(cil_file, R_OK) == 0) | 
					
						
							|  |  |  | 		load_cil(db, cil_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cil_compile(db)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	if (cil_build_policydb(db, &pdb)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cil_db_destroy(&db); | 
					
						
							| 
									
										
										
										
											2019-11-19 05:20:18 -05:00
										 |  |  | 	magisk_policydb = &pdb->p; | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int dump_policydb(const char *file) { | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	uint8_t *data; | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	size_t len; | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-23 04:57:52 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-12-13 00:37:06 -05:00
										 |  |  | 		auto fp = make_stream_fp<byte_stream>(data, len); | 
					
						
							| 
									
										
										
										
											2019-11-23 04:57:52 -05:00
										 |  |  | 		struct policy_file pf; | 
					
						
							|  |  |  | 		policy_file_init(&pf); | 
					
						
							|  |  |  | 		pf.type = PF_USE_STDIO; | 
					
						
							|  |  |  | 		pf.fp = fp.get(); | 
					
						
							|  |  |  | 		if (policydb_write(magisk_policydb, &pf)) { | 
					
						
							|  |  |  | 			LOGE("Fail to create policy image\n"); | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	int fd = xopen(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	if (fd < 0) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	xwrite(fd, data, len); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	close(fd); | 
					
						
							| 
									
										
										
										
											2019-11-20 03:47:15 -05:00
										 |  |  | 	free(data); | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void destroy_policydb() { | 
					
						
							| 
									
										
										
										
											2019-11-19 05:20:18 -05:00
										 |  |  | 	if (magisk_policydb) { | 
					
						
							|  |  |  | 		policydb_destroy(magisk_policydb); | 
					
						
							|  |  |  | 		free(magisk_policydb); | 
					
						
							|  |  |  | 		magisk_policydb = nullptr; | 
					
						
							| 
									
										
										
										
											2019-03-15 06:17:37 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-19 05:20:18 -05:00
										 |  |  | } |