16cd6a6acSopenharmony_ci/*
26cd6a6acSopenharmony_ci * Copyright 2011 Tresys Technology, LLC. All rights reserved.
36cd6a6acSopenharmony_ci *
46cd6a6acSopenharmony_ci * Redistribution and use in source and binary forms, with or without
56cd6a6acSopenharmony_ci * modification, are permitted provided that the following conditions are met:
66cd6a6acSopenharmony_ci *
76cd6a6acSopenharmony_ci *    1. Redistributions of source code must retain the above copyright notice,
86cd6a6acSopenharmony_ci *       this list of conditions and the following disclaimer.
96cd6a6acSopenharmony_ci *
106cd6a6acSopenharmony_ci *    2. Redistributions in binary form must reproduce the above copyright notice,
116cd6a6acSopenharmony_ci *       this list of conditions and the following disclaimer in the documentation
126cd6a6acSopenharmony_ci *       and/or other materials provided with the distribution.
136cd6a6acSopenharmony_ci *
146cd6a6acSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
156cd6a6acSopenharmony_ci * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
166cd6a6acSopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
176cd6a6acSopenharmony_ci * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
186cd6a6acSopenharmony_ci * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
196cd6a6acSopenharmony_ci * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
206cd6a6acSopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
216cd6a6acSopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
226cd6a6acSopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
236cd6a6acSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
246cd6a6acSopenharmony_ci *
256cd6a6acSopenharmony_ci * The views and conclusions contained in the software and documentation are those
266cd6a6acSopenharmony_ci * of the authors and should not be interpreted as representing official policies,
276cd6a6acSopenharmony_ci * either expressed or implied, of Tresys Technology, LLC.
286cd6a6acSopenharmony_ci */
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci#include <stdlib.h>
316cd6a6acSopenharmony_ci#include <stdio.h>
326cd6a6acSopenharmony_ci#include <string.h>
336cd6a6acSopenharmony_ci#include <stdint.h>
346cd6a6acSopenharmony_ci#include <sepol/errcodes.h>
356cd6a6acSopenharmony_ci
366cd6a6acSopenharmony_ci#include "cil_internal.h"
376cd6a6acSopenharmony_ci#include "cil_log.h"
386cd6a6acSopenharmony_ci#include "cil_mem.h"
396cd6a6acSopenharmony_ci#include "cil_tree.h"
406cd6a6acSopenharmony_ci#include "cil_lexer.h"
416cd6a6acSopenharmony_ci#include "cil_parser.h"
426cd6a6acSopenharmony_ci#include "cil_strpool.h"
436cd6a6acSopenharmony_ci#include "cil_stack.h"
446cd6a6acSopenharmony_ci
456cd6a6acSopenharmony_ci#define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12)
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_cistruct hll_info {
486cd6a6acSopenharmony_ci	uint32_t hll_offset;
496cd6a6acSopenharmony_ci	uint32_t hll_expand;
506cd6a6acSopenharmony_ci};
516cd6a6acSopenharmony_ci
526cd6a6acSopenharmony_cistatic void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand)
536cd6a6acSopenharmony_ci{
546cd6a6acSopenharmony_ci	struct hll_info *new = cil_malloc(sizeof(*new));
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_ci	new->hll_offset = hll_offset;
576cd6a6acSopenharmony_ci	new->hll_expand = hll_expand;
586cd6a6acSopenharmony_ci
596cd6a6acSopenharmony_ci	cil_stack_push(stack, CIL_NONE, new);
606cd6a6acSopenharmony_ci}
616cd6a6acSopenharmony_ci
626cd6a6acSopenharmony_cistatic void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand)
636cd6a6acSopenharmony_ci{
646cd6a6acSopenharmony_ci	struct cil_stack_item *curr = cil_stack_pop(stack);
656cd6a6acSopenharmony_ci	struct hll_info *info;
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_ci	if (!curr) {
686cd6a6acSopenharmony_ci		return;
696cd6a6acSopenharmony_ci	}
706cd6a6acSopenharmony_ci	info = curr->data;
716cd6a6acSopenharmony_ci	*hll_expand = info->hll_expand;
726cd6a6acSopenharmony_ci	*hll_offset = info->hll_offset;
736cd6a6acSopenharmony_ci	free(curr->data);
746cd6a6acSopenharmony_ci}
756cd6a6acSopenharmony_ci
766cd6a6acSopenharmony_cistatic void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value)
776cd6a6acSopenharmony_ci{
786cd6a6acSopenharmony_ci	cil_tree_node_init(node);
796cd6a6acSopenharmony_ci	(*node)->parent = current;
806cd6a6acSopenharmony_ci	(*node)->flavor = CIL_NODE;
816cd6a6acSopenharmony_ci	(*node)->line = line;
826cd6a6acSopenharmony_ci	(*node)->hll_offset = hll_offset;
836cd6a6acSopenharmony_ci	(*node)->data = value;
846cd6a6acSopenharmony_ci}
856cd6a6acSopenharmony_ci
866cd6a6acSopenharmony_cistatic void insert_node(struct cil_tree_node *node, struct cil_tree_node *current)
876cd6a6acSopenharmony_ci{
886cd6a6acSopenharmony_ci	if (current->cl_head == NULL) {
896cd6a6acSopenharmony_ci		current->cl_head = node;
906cd6a6acSopenharmony_ci	} else {
916cd6a6acSopenharmony_ci		current->cl_tail->next = node;
926cd6a6acSopenharmony_ci	}
936cd6a6acSopenharmony_ci	current->cl_tail = node;
946cd6a6acSopenharmony_ci}
956cd6a6acSopenharmony_ci
966cd6a6acSopenharmony_cistatic int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path)
976cd6a6acSopenharmony_ci{
986cd6a6acSopenharmony_ci	char *hll_type;
996cd6a6acSopenharmony_ci	struct cil_tree_node *node;
1006cd6a6acSopenharmony_ci	struct token tok;
1016cd6a6acSopenharmony_ci	uint32_t prev_hll_expand, prev_hll_offset;
1026cd6a6acSopenharmony_ci
1036cd6a6acSopenharmony_ci	cil_lexer_next(&tok);
1046cd6a6acSopenharmony_ci	if (tok.type != SYMBOL) {
1056cd6a6acSopenharmony_ci		cil_log(CIL_ERR, "Invalid line mark syntax\n");
1066cd6a6acSopenharmony_ci		goto exit;
1076cd6a6acSopenharmony_ci	}
1086cd6a6acSopenharmony_ci	hll_type = cil_strpool_add(tok.value);
1096cd6a6acSopenharmony_ci	if (hll_type != CIL_KEY_SRC_HLL_LME && hll_type != CIL_KEY_SRC_HLL_LMS && hll_type != CIL_KEY_SRC_HLL_LMX) {
1106cd6a6acSopenharmony_ci		cil_log(CIL_ERR, "Invalid line mark syntax\n");
1116cd6a6acSopenharmony_ci		goto exit;
1126cd6a6acSopenharmony_ci	}
1136cd6a6acSopenharmony_ci	if (hll_type == CIL_KEY_SRC_HLL_LME) {
1146cd6a6acSopenharmony_ci		if (cil_stack_is_empty(stack)) {
1156cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Line mark end without start\n");
1166cd6a6acSopenharmony_ci			goto exit;
1176cd6a6acSopenharmony_ci		}
1186cd6a6acSopenharmony_ci		prev_hll_expand = *hll_expand;
1196cd6a6acSopenharmony_ci		prev_hll_offset = *hll_offset;
1206cd6a6acSopenharmony_ci		pop_hll_info(stack, hll_offset, hll_expand);
1216cd6a6acSopenharmony_ci		if (!*hll_expand) {
1226cd6a6acSopenharmony_ci			/* This is needed if not going back to an lmx section. */
1236cd6a6acSopenharmony_ci			*hll_offset = prev_hll_offset;
1246cd6a6acSopenharmony_ci		}
1256cd6a6acSopenharmony_ci		if (prev_hll_expand && !*hll_expand) {
1266cd6a6acSopenharmony_ci			/* This is needed to count the lme at the end of an lmx section
1276cd6a6acSopenharmony_ci			 * within an lms section (or within no hll section).
1286cd6a6acSopenharmony_ci			 */
1296cd6a6acSopenharmony_ci			(*hll_offset)++;
1306cd6a6acSopenharmony_ci		}
1316cd6a6acSopenharmony_ci		*current = (*current)->parent;
1326cd6a6acSopenharmony_ci	} else {
1336cd6a6acSopenharmony_ci		push_hll_info(stack, *hll_offset, *hll_expand);
1346cd6a6acSopenharmony_ci		if (cil_stack_number_of_items(stack) > CIL_PARSER_MAX_EXPR_DEPTH) {
1356cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Number of active line marks exceeds limit of %d\n", CIL_PARSER_MAX_EXPR_DEPTH);
1366cd6a6acSopenharmony_ci			goto exit;
1376cd6a6acSopenharmony_ci		}
1386cd6a6acSopenharmony_ci
1396cd6a6acSopenharmony_ci		create_node(&node, *current, tok.line, *hll_offset, NULL);
1406cd6a6acSopenharmony_ci		insert_node(node, *current);
1416cd6a6acSopenharmony_ci		*current = node;
1426cd6a6acSopenharmony_ci
1436cd6a6acSopenharmony_ci		create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO);
1446cd6a6acSopenharmony_ci		insert_node(node, *current);
1456cd6a6acSopenharmony_ci
1466cd6a6acSopenharmony_ci		create_node(&node, *current, tok.line, *hll_offset, hll_type);
1476cd6a6acSopenharmony_ci		insert_node(node, *current);
1486cd6a6acSopenharmony_ci
1496cd6a6acSopenharmony_ci		cil_lexer_next(&tok);
1506cd6a6acSopenharmony_ci		if (tok.type != SYMBOL) {
1516cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Invalid line mark syntax\n");
1526cd6a6acSopenharmony_ci			goto exit;
1536cd6a6acSopenharmony_ci		}
1546cd6a6acSopenharmony_ci
1556cd6a6acSopenharmony_ci		create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
1566cd6a6acSopenharmony_ci		insert_node(node, *current);
1576cd6a6acSopenharmony_ci
1586cd6a6acSopenharmony_ci		cil_lexer_next(&tok);
1596cd6a6acSopenharmony_ci		if (tok.type != SYMBOL && tok.type != QSTRING) {
1606cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Invalid line mark syntax\n");
1616cd6a6acSopenharmony_ci			goto exit;
1626cd6a6acSopenharmony_ci		}
1636cd6a6acSopenharmony_ci
1646cd6a6acSopenharmony_ci		if (tok.type == QSTRING) {
1656cd6a6acSopenharmony_ci			tok.value[strlen(tok.value) - 1] = '\0';
1666cd6a6acSopenharmony_ci			tok.value = tok.value+1;
1676cd6a6acSopenharmony_ci		}
1686cd6a6acSopenharmony_ci
1696cd6a6acSopenharmony_ci		create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value));
1706cd6a6acSopenharmony_ci		insert_node(node, *current);
1716cd6a6acSopenharmony_ci
1726cd6a6acSopenharmony_ci		*hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0;
1736cd6a6acSopenharmony_ci	}
1746cd6a6acSopenharmony_ci
1756cd6a6acSopenharmony_ci	cil_lexer_next(&tok);
1766cd6a6acSopenharmony_ci	if (tok.type != NEWLINE) {
1776cd6a6acSopenharmony_ci		cil_log(CIL_ERR, "Invalid line mark syntax\n");
1786cd6a6acSopenharmony_ci		goto exit;
1796cd6a6acSopenharmony_ci	}
1806cd6a6acSopenharmony_ci
1816cd6a6acSopenharmony_ci	if (!*hll_expand) {
1826cd6a6acSopenharmony_ci		/* Need to increment because of the NEWLINE */
1836cd6a6acSopenharmony_ci		(*hll_offset)++;
1846cd6a6acSopenharmony_ci	}
1856cd6a6acSopenharmony_ci
1866cd6a6acSopenharmony_ci	return SEPOL_OK;
1876cd6a6acSopenharmony_ci
1886cd6a6acSopenharmony_ciexit:
1896cd6a6acSopenharmony_ci	cil_log(CIL_ERR, "Problem with high-level line mark at line %u of %s\n", tok.line, path);
1906cd6a6acSopenharmony_ci	return SEPOL_ERR;
1916cd6a6acSopenharmony_ci}
1926cd6a6acSopenharmony_ci
1936cd6a6acSopenharmony_cistatic void add_cil_path(struct cil_tree_node **current, char *path)
1946cd6a6acSopenharmony_ci{
1956cd6a6acSopenharmony_ci	struct cil_tree_node *node;
1966cd6a6acSopenharmony_ci
1976cd6a6acSopenharmony_ci	create_node(&node, *current, 0, 0, NULL);
1986cd6a6acSopenharmony_ci	insert_node(node, *current);
1996cd6a6acSopenharmony_ci	*current = node;
2006cd6a6acSopenharmony_ci
2016cd6a6acSopenharmony_ci	create_node(&node, *current, 0, 0, CIL_KEY_SRC_INFO);
2026cd6a6acSopenharmony_ci	insert_node(node, *current);
2036cd6a6acSopenharmony_ci
2046cd6a6acSopenharmony_ci	create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL);
2056cd6a6acSopenharmony_ci	insert_node(node, *current);
2066cd6a6acSopenharmony_ci
2076cd6a6acSopenharmony_ci	create_node(&node, *current, 0, 0, cil_strpool_add("1"));
2086cd6a6acSopenharmony_ci	insert_node(node, *current);
2096cd6a6acSopenharmony_ci
2106cd6a6acSopenharmony_ci	create_node(&node, *current, 0, 0, path);
2116cd6a6acSopenharmony_ci	insert_node(node, *current);
2126cd6a6acSopenharmony_ci}
2136cd6a6acSopenharmony_ci
2146cd6a6acSopenharmony_ciint cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree)
2156cd6a6acSopenharmony_ci{
2166cd6a6acSopenharmony_ci
2176cd6a6acSopenharmony_ci	int paren_count = 0;
2186cd6a6acSopenharmony_ci
2196cd6a6acSopenharmony_ci	struct cil_tree *tree = NULL;
2206cd6a6acSopenharmony_ci	struct cil_tree_node *node = NULL;
2216cd6a6acSopenharmony_ci	struct cil_tree_node *current = NULL;
2226cd6a6acSopenharmony_ci	char *path = cil_strpool_add(_path);
2236cd6a6acSopenharmony_ci	struct cil_stack *stack;
2246cd6a6acSopenharmony_ci	uint32_t hll_offset = 1;
2256cd6a6acSopenharmony_ci	uint32_t hll_expand = 0;
2266cd6a6acSopenharmony_ci	struct token tok;
2276cd6a6acSopenharmony_ci	int rc = SEPOL_OK;
2286cd6a6acSopenharmony_ci
2296cd6a6acSopenharmony_ci	cil_stack_init(&stack);
2306cd6a6acSopenharmony_ci
2316cd6a6acSopenharmony_ci	cil_lexer_setup(buffer, size);
2326cd6a6acSopenharmony_ci
2336cd6a6acSopenharmony_ci	tree = *parse_tree;
2346cd6a6acSopenharmony_ci	current = tree->root;
2356cd6a6acSopenharmony_ci
2366cd6a6acSopenharmony_ci	add_cil_path(&current, path);
2376cd6a6acSopenharmony_ci
2386cd6a6acSopenharmony_ci	do {
2396cd6a6acSopenharmony_ci		cil_lexer_next(&tok);
2406cd6a6acSopenharmony_ci		switch (tok.type) {
2416cd6a6acSopenharmony_ci		case HLL_LINEMARK:
2426cd6a6acSopenharmony_ci			rc = add_hll_linemark(&current, &hll_offset, &hll_expand, stack, path);
2436cd6a6acSopenharmony_ci			if (rc != SEPOL_OK) {
2446cd6a6acSopenharmony_ci				goto exit;
2456cd6a6acSopenharmony_ci			}
2466cd6a6acSopenharmony_ci			break;
2476cd6a6acSopenharmony_ci		case OPAREN:
2486cd6a6acSopenharmony_ci			paren_count++;
2496cd6a6acSopenharmony_ci			if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) {
2506cd6a6acSopenharmony_ci				cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path);
2516cd6a6acSopenharmony_ci				goto exit;
2526cd6a6acSopenharmony_ci			}
2536cd6a6acSopenharmony_ci			create_node(&node, current, tok.line, hll_offset, NULL);
2546cd6a6acSopenharmony_ci			insert_node(node, current);
2556cd6a6acSopenharmony_ci			current = node;
2566cd6a6acSopenharmony_ci			break;
2576cd6a6acSopenharmony_ci		case CPAREN:
2586cd6a6acSopenharmony_ci			paren_count--;
2596cd6a6acSopenharmony_ci			if (paren_count < 0) {
2606cd6a6acSopenharmony_ci				cil_log(CIL_ERR, "Close parenthesis without matching open at line %d of %s\n", tok.line, path);
2616cd6a6acSopenharmony_ci				goto exit;
2626cd6a6acSopenharmony_ci			}
2636cd6a6acSopenharmony_ci			current = current->parent;
2646cd6a6acSopenharmony_ci			break;
2656cd6a6acSopenharmony_ci		case QSTRING:
2666cd6a6acSopenharmony_ci			tok.value[strlen(tok.value) - 1] = '\0';
2676cd6a6acSopenharmony_ci			tok.value = tok.value+1;
2686cd6a6acSopenharmony_ci			/* FALLTHRU */
2696cd6a6acSopenharmony_ci		case SYMBOL:
2706cd6a6acSopenharmony_ci			if (paren_count == 0) {
2716cd6a6acSopenharmony_ci				cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path);
2726cd6a6acSopenharmony_ci				goto exit;
2736cd6a6acSopenharmony_ci			}
2746cd6a6acSopenharmony_ci
2756cd6a6acSopenharmony_ci			create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value));
2766cd6a6acSopenharmony_ci			insert_node(node, current);
2776cd6a6acSopenharmony_ci			break;
2786cd6a6acSopenharmony_ci		case NEWLINE :
2796cd6a6acSopenharmony_ci			if (!hll_expand) {
2806cd6a6acSopenharmony_ci				hll_offset++;
2816cd6a6acSopenharmony_ci			}
2826cd6a6acSopenharmony_ci			break;
2836cd6a6acSopenharmony_ci		case COMMENT:
2846cd6a6acSopenharmony_ci			while (tok.type != NEWLINE && tok.type != END_OF_FILE) {
2856cd6a6acSopenharmony_ci				cil_lexer_next(&tok);
2866cd6a6acSopenharmony_ci			}
2876cd6a6acSopenharmony_ci			if (!hll_expand) {
2886cd6a6acSopenharmony_ci				hll_offset++;
2896cd6a6acSopenharmony_ci			}
2906cd6a6acSopenharmony_ci			if (tok.type != END_OF_FILE) {
2916cd6a6acSopenharmony_ci				break;
2926cd6a6acSopenharmony_ci			}
2936cd6a6acSopenharmony_ci			/* FALLTHRU */
2946cd6a6acSopenharmony_ci			// Fall through if EOF
2956cd6a6acSopenharmony_ci		case END_OF_FILE:
2966cd6a6acSopenharmony_ci			if (paren_count > 0) {
2976cd6a6acSopenharmony_ci				cil_log(CIL_ERR, "Open parenthesis without matching close at line %d of %s\n", tok.line, path);
2986cd6a6acSopenharmony_ci				goto exit;
2996cd6a6acSopenharmony_ci			}
3006cd6a6acSopenharmony_ci			if (!cil_stack_is_empty(stack)) {
3016cd6a6acSopenharmony_ci				cil_log(CIL_ERR, "High-level language line marker start without close at line %d of %s\n", tok.line, path);
3026cd6a6acSopenharmony_ci				goto exit;
3036cd6a6acSopenharmony_ci			}
3046cd6a6acSopenharmony_ci			break;
3056cd6a6acSopenharmony_ci		case UNKNOWN:
3066cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path);
3076cd6a6acSopenharmony_ci			goto exit;
3086cd6a6acSopenharmony_ci		default:
3096cd6a6acSopenharmony_ci			cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path);
3106cd6a6acSopenharmony_ci			goto exit;
3116cd6a6acSopenharmony_ci		}
3126cd6a6acSopenharmony_ci	}
3136cd6a6acSopenharmony_ci	while (tok.type != END_OF_FILE);
3146cd6a6acSopenharmony_ci
3156cd6a6acSopenharmony_ci	cil_lexer_destroy();
3166cd6a6acSopenharmony_ci
3176cd6a6acSopenharmony_ci	cil_stack_destroy(&stack);
3186cd6a6acSopenharmony_ci
3196cd6a6acSopenharmony_ci	*parse_tree = tree;
3206cd6a6acSopenharmony_ci
3216cd6a6acSopenharmony_ci	return SEPOL_OK;
3226cd6a6acSopenharmony_ci
3236cd6a6acSopenharmony_ciexit:
3246cd6a6acSopenharmony_ci	while (!cil_stack_is_empty(stack)) {
3256cd6a6acSopenharmony_ci		pop_hll_info(stack, &hll_offset, &hll_expand);
3266cd6a6acSopenharmony_ci	}
3276cd6a6acSopenharmony_ci	cil_lexer_destroy();
3286cd6a6acSopenharmony_ci	cil_stack_destroy(&stack);
3296cd6a6acSopenharmony_ci
3306cd6a6acSopenharmony_ci	return SEPOL_ERR;
3316cd6a6acSopenharmony_ci}
332