1/* 2* Copyright (c) 2024 Huawei Device Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16/* Skipping relabel path if define in ignore_cfg. */ 17#include <errno.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <string.h> 21#include <stdbool.h> 22 23#include "ignore_path.h" 24#include "callbacks.h" 25 26static g_system_config_loaded = false; 27static g_vendor_config_loaded = false; 28ignore_paths_t g_ignore_paths = {NULL, NULL}; 29 30ignore_path_node_t *insert_ignore_path(ignore_path_node_t **paths_ptr, const char *line) 31{ 32 ignore_path_node_t *new_node = malloc(sizeof(ignore_path_node_t)); 33 if (new_node == NULL) { 34 return NULL; 35 } 36 new_node->path = strdup(line); 37 if (new_node->path == NULL) { 38 free(new_node); 39 return NULL; 40 } 41 new_node->next = *paths_ptr; 42 *paths_ptr = new_node; 43 return new_node; 44} 45 46size_t trim_newline(char *str) 47{ 48 size_t length = strlen(str); 49 if (length == 0) { 50 return 0; 51 } 52 if (str[length - 1] == '\n') { 53 str[--length] = '\0'; 54 } 55 if (length > 0 && str[length - 1] == '\r') { 56 str[--length] = '\0'; 57 } 58 return length; 59} 60 61path_info_t trim_suffix_and_get_path_info(char *line, size_t real_length) 62{ 63 path_info_t info; 64 if (line[real_length - SLASH_SUFFIX_LEN] == '/') { 65 info.paths_ptr = &g_ignore_paths.slash_suffix_paths; 66 info.suffix_len = SLASH_SUFFIX_LEN; 67 } else if (real_length > 1 68 && line[real_length - SLASH_SUFFIX_LEN] == '*' 69 && line[real_length - STAR_SUFFIX_LEN] == '/') { 70 info.paths_ptr = &g_ignore_paths.star_suffix_paths; 71 info.suffix_len = STAR_SUFFIX_LEN; 72 } else { 73 info.paths_ptr = NULL; 74 info.suffix_len = 0; 75 } 76 if (info.paths_ptr != NULL) { 77 line[real_length - info.suffix_len] = '\0'; 78 } 79 return info; 80} 81 82bool load_ignore_cfg_from_file(const char *cfg_path) 83{ 84 FILE *file = fopen(cfg_path, "r"); 85 if (file == NULL) { 86 selinux_log(SELINUX_INFO, "Failed to open file: %s\n", cfg_path); 87 return false; 88 } 89 90 char *line = NULL; 91 size_t len = 0; 92 bool result = true; 93 while (getline(&line, &len, file) != -1) { 94 size_t real_length = trim_newline(line); 95 if (real_length > 0) { 96 path_info_t info = trim_suffix_and_get_path_info(line, real_length); 97 if (info.paths_ptr == NULL) { 98 continue; 99 } 100 line[real_length - info.suffix_len] = '\0'; 101 ignore_path_node_t *new_node = insert_ignore_path(info.paths_ptr, line); 102 if (new_node == NULL) { 103 selinux_log(SELINUX_ERROR, "Failed to allocate memory or duplicate string: %s\n", line); 104 continue; 105 } 106 } 107 } 108 109 if (fclose(file)) { 110 selinux_log(SELINUX_ERROR, "Failed to close file: %s\n", strerror(errno)); 111 } 112 free(line); 113 return result; 114} 115 116bool load_ignore_cfg() 117{ 118 if (g_system_config_loaded && g_vendor_config_loaded) { 119 return true; 120 } 121 bool result = true; 122 if (!g_system_config_loaded) { 123 g_system_config_loaded = load_ignore_cfg_from_file(SYSTEM_IGNORE_CFG_PATH); 124 } 125 if (!g_vendor_config_loaded) { 126 g_vendor_config_loaded = load_ignore_cfg_from_file(VENDOR_IGNORE_CFG_PATH); 127 } 128 if (!g_system_config_loaded || !g_vendor_config_loaded) { 129 result = false; 130 } 131 return result; 132} 133 134static bool find_ignore_path(ignore_path_node_t *current, const char *path) 135{ 136 while (current != NULL) { 137 if (strcmp(path, current->path) == 0) { 138 return true; 139 } 140 current = current->next; 141 } 142 return false; 143} 144 145enum skip_type skip_ignore_relabel(const char *path) 146{ 147 if (find_ignore_path(g_ignore_paths.slash_suffix_paths, path)) { 148 return SKIP_SELF_SUB_DIR; 149 } 150 if (find_ignore_path(g_ignore_paths.star_suffix_paths, path)) { 151 return SKIP_SUB_DIR; 152 } 153 return SKIP_NONE; 154} 155 156void free_ignore_list(ignore_path_node_t **list_ptr) 157{ 158 while (*list_ptr != NULL) { 159 ignore_path_node_t *temp = *list_ptr; 160 *list_ptr = (*list_ptr)->next; 161 free(temp->path); 162 free(temp); 163 } 164 *list_ptr = NULL; 165} 166 167void free_ignore_cfg() 168{ 169 free_ignore_list(&g_ignore_paths.slash_suffix_paths); 170 free_ignore_list(&g_ignore_paths.star_suffix_paths); 171 g_system_config_loaded = false; 172 g_vendor_config_loaded = false; 173} 174