mirror of
https://gitee.com/openharmony/security_selinux
synced 2024-11-26 23:00:22 +00:00
policy map
Signed-off-by: steven_q <qichanggui@huawei.com> Change-Id: I3d10cdc1ab9a46b43247ff91972fa4a4721592ea
This commit is contained in:
parent
7dc63495b9
commit
779fc23eea
4
.gitignore
vendored
4
.gitignore
vendored
@ -37,3 +37,7 @@
|
||||
|
||||
# Dirs
|
||||
sepolicy/hx*
|
||||
|
||||
# py
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
43
BUILD.gn
43
BUILD.gn
@ -369,6 +369,13 @@ action("build_policy") {
|
||||
components,
|
||||
]
|
||||
|
||||
if (components != "default") {
|
||||
args += [
|
||||
"--vendor-policy-version",
|
||||
"$vendor_policy_version",
|
||||
]
|
||||
}
|
||||
|
||||
if (extra_args != "default") {
|
||||
foreach(arg, string_split(extra_args, " ")) {
|
||||
args += [ arg ]
|
||||
@ -385,6 +392,9 @@ action("build_policy") {
|
||||
target_out_dir + "/prebuild_sepolicy.system.cil.sha256",
|
||||
target_out_dir + "/system.cil",
|
||||
target_out_dir + "/system.cil.sha256",
|
||||
target_out_dir + "/$vendor_policy_version.cil",
|
||||
target_out_dir + "/version",
|
||||
target_out_dir + "/public.cil",
|
||||
]
|
||||
}
|
||||
|
||||
@ -528,6 +538,16 @@ ohos_prebuilt_etc("build_updater_sepolicy") {
|
||||
install_images = [ "updater" ]
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("selinux_version") {
|
||||
deps = [ ":build_policy" ]
|
||||
source = target_out_dir + "/version"
|
||||
license_file = "LICENSE"
|
||||
part_name = "selinux"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "selinux/"
|
||||
install_images = [ "vendor" ]
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("config") {
|
||||
deps = [ ":selinux_config" ]
|
||||
source = target_out_dir + "/config"
|
||||
@ -615,6 +635,26 @@ ohos_prebuilt_etc("vendor_cil") {
|
||||
install_images = [ "vendor" ]
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("public_cil") {
|
||||
deps = [ ":build_policy" ]
|
||||
source = target_out_dir + "/public.cil"
|
||||
license_file = "LICENSE"
|
||||
part_name = "selinux"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "selinux/"
|
||||
install_images = [ "vendor" ]
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("version_cil") {
|
||||
deps = [ ":build_policy" ]
|
||||
source = target_out_dir + "/$vendor_policy_version.cil"
|
||||
license_file = "LICENSE"
|
||||
part_name = "selinux"
|
||||
subsystem_name = "security"
|
||||
relative_install_dir = "selinux/compatible/"
|
||||
install_images = [ "system" ]
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("prebuild_sepolicy_system_cil_sha256") {
|
||||
deps = [ ":build_policy" ]
|
||||
source = target_out_dir + "/prebuild_sepolicy.system.cil.sha256"
|
||||
@ -678,11 +718,14 @@ group("selinux_group") {
|
||||
deps += [
|
||||
":system_cil",
|
||||
":system_cil_sha256",
|
||||
":version_cil",
|
||||
]
|
||||
} else if (components == "vendor") {
|
||||
deps += [
|
||||
":build_sepolicy",
|
||||
":prebuild_sepolicy_system_cil_sha256",
|
||||
":public_cil",
|
||||
":selinux_version",
|
||||
":vendor_cil",
|
||||
]
|
||||
} else {
|
||||
|
@ -32,11 +32,14 @@ constexpr int32_t PIPE_NUM = 2;
|
||||
constexpr int32_t BUFF_SIZE = 1024;
|
||||
constexpr const char SYSTEM_CIL[] = "/system/etc/selinux/system.cil";
|
||||
constexpr const char VENDOR_CIL[] = "/vendor/etc/selinux/vendor.cil";
|
||||
constexpr const char PUBLIC_CIL[] = "/vendor/etc/selinux/public.cil";
|
||||
constexpr const char SYSTEM_CIL_HASH[] = "/system/etc/selinux/system.cil.sha256";
|
||||
constexpr const char PRECOMPILED_POLICY_SYSTEM_CIL_HASH[] = "/vendor/etc/selinux/prebuild_sepolicy.system.cil.sha256";
|
||||
constexpr const char COMPILE_OUTPUT_POLICY[] = "/dev/policy.31";
|
||||
constexpr const char DEFAULT_POLICY[] = "/system/etc/selinux/targeted/policy/policy.31";
|
||||
constexpr const char PRECOMPILED_POLICY[] = "/vendor/etc/selinux/prebuild_sepolicy/policy.31";
|
||||
constexpr const char VERSION_POLICY_PATH[] = "/vendor/etc/selinux/version";
|
||||
constexpr const char COMPATIBLE_CIL_PATH[] = "/system/etc/selinux/compatible/";
|
||||
} // namespace
|
||||
|
||||
static void InitSelinuxLog(void)
|
||||
@ -82,6 +85,14 @@ static void DeleteTmpPolicyFile(const std::string &policyFile)
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetVendorPolicyVersion(std::string & version)
|
||||
{
|
||||
if (!ReadFileFirstLine(VERSION_POLICY_PATH, version)) {
|
||||
return false;
|
||||
}
|
||||
return !version.empty();
|
||||
}
|
||||
|
||||
static bool ReadPolicyFile(const std::string &policyFile, void **data, size_t &size)
|
||||
{
|
||||
int fd = open(policyFile.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
@ -188,6 +199,32 @@ static bool LoadPolicy(void *data, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetVersionPolicy(std::string &versionPolicy)
|
||||
{
|
||||
std::string version;
|
||||
if (!GetVendorPolicyVersion(version)) {
|
||||
selinux_log(SELINUX_ERROR, "Get vendor policy version failed\n");
|
||||
return false;
|
||||
}
|
||||
std::string path(COMPATIBLE_CIL_PATH + version + ".cil");
|
||||
if (access(path.c_str(), F_OK) == 0) {
|
||||
versionPolicy = path;
|
||||
return true;
|
||||
}
|
||||
selinux_log(SELINUX_ERROR, "Get vendor version policy failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool GetPublicPolicy(std::string &publicPolicy)
|
||||
{
|
||||
if (access(PUBLIC_CIL, F_OK) == 0) {
|
||||
publicPolicy = PUBLIC_CIL;
|
||||
return true;
|
||||
}
|
||||
selinux_log(SELINUX_ERROR, "Get vendor public policy failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::vector<const char *> CombineCompileCmd(void)
|
||||
{
|
||||
std::vector<const char *> compileCmd = {
|
||||
@ -206,6 +243,16 @@ static std::vector<const char *> CombineCompileCmd(void)
|
||||
COMPILE_OUTPUT_POLICY,
|
||||
};
|
||||
compileCmd.emplace_back(SYSTEM_CIL);
|
||||
std::string versionPolicy;
|
||||
if (GetVersionPolicy(versionPolicy)) {
|
||||
selinux_log(SELINUX_WARNING, "Add policy %s\n", versionPolicy.c_str());
|
||||
compileCmd.emplace_back(versionPolicy.c_str());
|
||||
}
|
||||
std::string publicPolicy;
|
||||
if (GetPublicPolicy(publicPolicy)) {
|
||||
selinux_log(SELINUX_WARNING, "Add policy %s\n", publicPolicy.c_str());
|
||||
compileCmd.emplace_back(publicPolicy.c_str());
|
||||
}
|
||||
compileCmd.emplace_back(nullptr);
|
||||
return compileCmd;
|
||||
}
|
||||
@ -265,10 +312,25 @@ static bool CompilePolicy(void)
|
||||
return false;
|
||||
}
|
||||
(void)close(pipeFd[1]);
|
||||
char buf[BUFF_SIZE] = {0};
|
||||
while (read(pipeFd[0], buf, BUFF_SIZE - 1) > 0) {
|
||||
selinux_log(SELINUX_ERROR, "Selinux compile result: %s\n", buf);
|
||||
|
||||
FILE *fp = fdopen(pipeFd[0], "r");
|
||||
if (fp != nullptr) {
|
||||
char buf[BUFF_SIZE] = {0};
|
||||
while (fgets(buf, sizeof(buf) - 1, fp) != nullptr) {
|
||||
size_t n = strlen(buf);
|
||||
if (n == 0) {
|
||||
continue;
|
||||
}
|
||||
if (buf[n - 1] == '\n') {
|
||||
buf[n - 1] = '\0';
|
||||
}
|
||||
if (strstr(buf, "Failed") != nullptr) {
|
||||
selinux_log(SELINUX_ERROR, "SELinux compile result: %s\n", buf);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
(void)close(pipeFd[0]);
|
||||
|
||||
return WaitForChild(pid);
|
||||
|
@ -2,7 +2,7 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
Copyright (c) 2021-2023 Huawei Device Co., Ltd.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
@ -19,27 +19,11 @@ limitations under the License.
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
# list of all macros and te for sepolicy build
|
||||
SEPOLICY_TYPE_LIST = ["security_classes",
|
||||
"initial_sids",
|
||||
"access_vectors",
|
||||
"glb_perm_def.spt",
|
||||
"glb_never_def.spt",
|
||||
"mls",
|
||||
"policy_cap",
|
||||
"glb_te_def.spt",
|
||||
"attributes",
|
||||
".te",
|
||||
"glb_roles.spt",
|
||||
"users",
|
||||
"initial_sid_contexts",
|
||||
"fs_use",
|
||||
"virtfs_contexts",
|
||||
]
|
||||
import build_policy_api
|
||||
|
||||
|
||||
def parse_args():
|
||||
@ -58,218 +42,11 @@ def parse_args():
|
||||
help='build for updater target', required=True)
|
||||
parser.add_argument('--components',
|
||||
help='system or vendor or default', required=True)
|
||||
parser.add_argument('--vendor-policy-version',
|
||||
help='plat version of vendor policy', required=False)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def traverse_folder_in_dir_name(search_dir, folder_suffix):
|
||||
folder_list = []
|
||||
for root, dirs, _ in os.walk(search_dir):
|
||||
for dir_i in dirs:
|
||||
if dir_i == folder_suffix:
|
||||
folder_list.append(os.path.join(root, dir_i))
|
||||
return folder_list
|
||||
|
||||
|
||||
def traverse_folder_in_type(search_dir, file_suffix, build_root):
|
||||
policy_file_list = []
|
||||
flag = 0
|
||||
for root, _, files in os.walk(search_dir):
|
||||
for each_file in files:
|
||||
if each_file.endswith(file_suffix):
|
||||
path = os.path.join(root, each_file)
|
||||
rel_path = os.path.relpath(path, build_root)
|
||||
flag |= check_empty_row(rel_path)
|
||||
policy_file_list.append(rel_path)
|
||||
policy_file_list.sort()
|
||||
return " ".join(str(x) for x in policy_file_list), flag
|
||||
|
||||
|
||||
def traverse_file_in_each_type(folder_list, sepolicy_type_list, build_root):
|
||||
policy_files = ""
|
||||
err = 0
|
||||
for policy_type in sepolicy_type_list:
|
||||
for folder in folder_list:
|
||||
str_tra, flag = traverse_folder_in_type(folder, policy_type, build_root)
|
||||
err |= flag
|
||||
str_seq = (policy_files, str_tra)
|
||||
policy_files = " ".join(str_seq)
|
||||
if err:
|
||||
raise Exception(err)
|
||||
return policy_files
|
||||
|
||||
|
||||
def check_empty_row(policy_file_list):
|
||||
"""
|
||||
Check whether the last line of te is empty.
|
||||
:param policy_file_list: list of te file
|
||||
:return:
|
||||
"""
|
||||
err = 0
|
||||
with open(policy_file_list, 'r') as fp:
|
||||
lines = fp.readlines()
|
||||
if len(lines) != 0:
|
||||
last_line = lines[-1]
|
||||
if '\n' not in last_line:
|
||||
print(policy_file_list + " :" + " need an empty line at end \n")
|
||||
err = 1
|
||||
return err
|
||||
|
||||
|
||||
def run_command(in_cmd):
|
||||
|
||||
cmdstr = " ".join(in_cmd)
|
||||
ret = subprocess.run(cmdstr, shell=True).returncode
|
||||
if ret != 0:
|
||||
raise Exception(ret)
|
||||
|
||||
|
||||
def build_conf(args, output_conf, input_policy_file_list):
|
||||
m4_args = "-D build_with_debug=" + args.debug_version + " "
|
||||
m4_args += "-D build_with_updater=" + args.updater_version + " "
|
||||
|
||||
build_conf_cmd = ["m4",
|
||||
"--fatal-warnings", m4_args,
|
||||
"-s", input_policy_file_list, ">", output_conf]
|
||||
|
||||
run_command(build_conf_cmd)
|
||||
|
||||
|
||||
def build_cil(args, output_cil, input_conf):
|
||||
check_policy_cmd = [os.path.join(args.tool_path, "checkpolicy"),
|
||||
input_conf,
|
||||
"-M -C -c 31",
|
||||
"-o " + output_cil]
|
||||
run_command(check_policy_cmd)
|
||||
|
||||
|
||||
def build_policy(args, output_policy, vendor_cil, system_cil):
|
||||
build_policy_cmd = [os.path.join(args.tool_path, "secilc"),
|
||||
vendor_cil,
|
||||
system_cil,
|
||||
"-m -M true -G -c 31",
|
||||
"-f /dev/null",
|
||||
"-o " + output_policy]
|
||||
run_command(build_policy_cmd)
|
||||
|
||||
|
||||
|
||||
def prepare_build_path(dir_list, root_dir, build_dir_list, sepolicy_path):
|
||||
build_policy_list = [os.path.join(sepolicy_path, "base"), os.path.join(sepolicy_path, "ohos_policy")]
|
||||
build_policy_list += dir_list.split(":")
|
||||
|
||||
for i in build_policy_list:
|
||||
if i == "" or i == "default":
|
||||
continue
|
||||
path = os.path.join(root_dir, i)
|
||||
if (os.path.exists(path)):
|
||||
build_dir_list.append(path)
|
||||
else:
|
||||
print("following path not exists!! {}".format(path))
|
||||
exit(-1)
|
||||
|
||||
|
||||
def filter_out(pattern_file, input_file):
|
||||
patterns = []
|
||||
with open(pattern_file, 'r') as pat_file:
|
||||
patterns.extend(pat_file.readlines())
|
||||
|
||||
tmp_output = tempfile.NamedTemporaryFile()
|
||||
with open(input_file, 'r') as in_file:
|
||||
tmp_output.writelines(line.encode(encoding='utf-8') for line in in_file.readlines()
|
||||
if line not in patterns)
|
||||
tmp_output.write("\n".encode(encoding='utf-8'))
|
||||
tmp_output.flush()
|
||||
shutil.copyfile(tmp_output.name, input_file)
|
||||
|
||||
|
||||
def generate_hash_file(input_file, output_file):
|
||||
build_policy_cmd = ["sha256sum",
|
||||
input_file,
|
||||
"| cut -d' ' -f1",
|
||||
">",
|
||||
output_file]
|
||||
run_command(build_policy_cmd)
|
||||
|
||||
|
||||
def compile_sepolicy(args):
|
||||
output_path = os.path.abspath(os.path.dirname(args.dst_file))
|
||||
build_root = os.path.abspath(os.path.join(args.tool_path, "../../.."))
|
||||
sepolicy_path = os.path.join(args.source_root_dir, "base/security/selinux/sepolicy/")
|
||||
dir_list = []
|
||||
prepare_build_path(args.policy_dir_list, args.source_root_dir, dir_list, sepolicy_path)
|
||||
min_policy = [os.path.join(sepolicy_path, "min")]
|
||||
system_policy = []
|
||||
public_policy = []
|
||||
vendor_policy = []
|
||||
|
||||
for item in dir_list:
|
||||
public_policy += traverse_folder_in_dir_name(item, "public")
|
||||
system_policy += traverse_folder_in_dir_name(item, "system")
|
||||
vendor_policy += traverse_folder_in_dir_name(item, "vendor")
|
||||
|
||||
# list of all policy folders
|
||||
system_folder_list = public_policy + system_policy
|
||||
vendor_folder_list = public_policy + vendor_policy + min_policy
|
||||
|
||||
# add temp dirs base/te folders
|
||||
system_folder_list.append(os.path.join(sepolicy_path, "base/te"))
|
||||
vendor_folder_list.append(os.path.join(sepolicy_path, "base/te"))
|
||||
|
||||
# list of all policy files
|
||||
system_policy_file_list = traverse_file_in_each_type(system_folder_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
vendor_policy_file_list = traverse_file_in_each_type(vendor_folder_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
min_policy_file_list = traverse_file_in_each_type(min_policy, SEPOLICY_TYPE_LIST, build_root)
|
||||
|
||||
system_output_conf = os.path.join(output_path, "system.conf")
|
||||
vendor_output_conf = os.path.join(output_path, "vendor.conf")
|
||||
min_output_conf = os.path.join(output_path, "min.conf")
|
||||
|
||||
system_cil_path = os.path.join(output_path, "system.cil")
|
||||
vendor_cil_path = os.path.join(output_path, "vendor.cil")
|
||||
min_cil_path = os.path.join(output_path, "min.cil")
|
||||
|
||||
# build system.conf
|
||||
build_conf(args, system_output_conf, system_policy_file_list)
|
||||
# build system.cil
|
||||
build_cil(args, system_cil_path, system_output_conf)
|
||||
|
||||
if args.components == "system":
|
||||
system_cil_sha256 = os.path.join(output_path, "system.cil.sha256")
|
||||
generate_hash_file(system_cil_path, system_cil_sha256)
|
||||
|
||||
elif args.components == "vendor":
|
||||
prebuild_sepolicy_system_cil_sha256 = os.path.join(output_path, "prebuild_sepolicy.system.cil.sha256")
|
||||
generate_hash_file(system_cil_path, prebuild_sepolicy_system_cil_sha256)
|
||||
|
||||
# build vendor.conf
|
||||
build_conf(args, vendor_output_conf, vendor_policy_file_list)
|
||||
# build vendor.cil
|
||||
build_cil(args, vendor_cil_path, vendor_output_conf)
|
||||
|
||||
# build min.conf
|
||||
build_conf(args, min_output_conf, min_policy_file_list)
|
||||
# build min.cil
|
||||
build_cil(args, min_cil_path, min_output_conf)
|
||||
|
||||
filter_out(min_cil_path, vendor_cil_path)
|
||||
build_policy(args, args.dst_file, vendor_cil_path, system_cil_path)
|
||||
|
||||
|
||||
def main(args):
|
||||
# check both debug and release sepolicy
|
||||
origin_debug_version = args.debug_version
|
||||
if args.debug_version == "true":
|
||||
args.debug_version = "false"
|
||||
compile_sepolicy(args)
|
||||
else:
|
||||
args.debug_version = "true"
|
||||
compile_sepolicy(args)
|
||||
|
||||
# build target policy according to desire debug_version
|
||||
args.debug_version = origin_debug_version
|
||||
compile_sepolicy(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
input_args = parse_args()
|
||||
main(input_args)
|
||||
build_policy_api.main(input_args)
|
||||
|
489
scripts/build_policy_api.py
Normal file
489
scripts/build_policy_api.py
Normal file
@ -0,0 +1,489 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
SYSTEM_CIL_HASH = "system.cil.sha256"
|
||||
PREBUILD_SEPOLICY_SYSTEM_CIL_HASH = "prebuild_sepolicy.system.cil.sha256"
|
||||
|
||||
# list of all macros and te for sepolicy build
|
||||
SEPOLICY_TYPE_LIST = ["security_classes",
|
||||
"initial_sids",
|
||||
"access_vectors",
|
||||
"glb_perm_def.spt",
|
||||
"glb_never_def.spt",
|
||||
"mls",
|
||||
"policy_cap",
|
||||
"glb_te_def.spt",
|
||||
"attributes",
|
||||
".te",
|
||||
"glb_roles.spt",
|
||||
"users",
|
||||
"initial_sid_contexts",
|
||||
"fs_use",
|
||||
"virtfs_contexts",
|
||||
]
|
||||
|
||||
POLICY_TYPE_LIST = ["allow", "auditallow", "dontaudit",
|
||||
"allowx", "auditallowx", "dontauditx",
|
||||
"neverallow", "neverallowx", ]
|
||||
|
||||
|
||||
class PolicyDirList(object):
|
||||
def __init__(self, min_policy_dir_list, system_policy_dir_list, vendor_policy_dir_list, public_policy_dir_list):
|
||||
self.min_policy_dir_list = min_policy_dir_list
|
||||
self.system_policy_dir_list = system_policy_dir_list
|
||||
self.vendor_policy_dir_list = vendor_policy_dir_list
|
||||
self.public_policy_dir_list = public_policy_dir_list
|
||||
|
||||
|
||||
class PolicyFileList(object):
|
||||
def __init__(self, min_policy_file_list, system_policy_file_list, vendor_policy_file_list, public_policy_file_list):
|
||||
self.min_policy_file_list = min_policy_file_list
|
||||
self.system_policy_file_list = system_policy_file_list
|
||||
self.vendor_policy_file_list = vendor_policy_file_list
|
||||
self.public_policy_file_list = public_policy_file_list
|
||||
|
||||
|
||||
def traverse_folder_in_dir_name(search_dir, folder_suffix):
|
||||
folder_list = []
|
||||
for root, dirs, _ in os.walk(search_dir):
|
||||
for dir_i in dirs:
|
||||
if dir_i == folder_suffix:
|
||||
folder_list.append(os.path.join(root, dir_i))
|
||||
return folder_list
|
||||
|
||||
|
||||
def traverse_folder_in_type(search_dir, file_suffix, build_root):
|
||||
policy_file_list = []
|
||||
flag = 0
|
||||
for root, _, files in os.walk(search_dir):
|
||||
for each_file in files:
|
||||
if each_file.endswith(file_suffix):
|
||||
path = os.path.join(root, each_file)
|
||||
rel_path = os.path.relpath(path, build_root)
|
||||
flag |= check_empty_row(rel_path)
|
||||
policy_file_list.append(rel_path)
|
||||
policy_file_list.sort()
|
||||
return policy_file_list, flag
|
||||
|
||||
|
||||
def traverse_file_in_each_type(folder_list, sepolicy_type_list, build_root):
|
||||
policy_files_list = []
|
||||
err = 0
|
||||
for policy_type in sepolicy_type_list:
|
||||
for folder in folder_list:
|
||||
type_file_list, flag = traverse_folder_in_type(
|
||||
folder, policy_type, build_root)
|
||||
err |= flag
|
||||
policy_files_list.extend(type_file_list)
|
||||
if err:
|
||||
raise Exception(err)
|
||||
return policy_files_list
|
||||
|
||||
|
||||
def check_empty_row(policy_file):
|
||||
"""
|
||||
Check whether the last line of te file is empty.
|
||||
:param policy_file: te file
|
||||
:return:
|
||||
"""
|
||||
err = 0
|
||||
with open(policy_file, 'r') as fp:
|
||||
lines = fp.readlines()
|
||||
if len(lines) == 0:
|
||||
return 0
|
||||
last_line = lines[-1]
|
||||
if '\n' not in last_line:
|
||||
print("".join([policy_file, " : need an empty line at end\n"]))
|
||||
err = 1
|
||||
return err
|
||||
|
||||
|
||||
def run_command(in_cmd):
|
||||
cmdstr = " ".join(in_cmd)
|
||||
ret = subprocess.run(cmdstr, shell=True).returncode
|
||||
if ret != 0:
|
||||
raise Exception(ret)
|
||||
|
||||
|
||||
def build_conf(args, output_conf, file_list):
|
||||
m4_args = ["-D", "build_with_debug=" + args.debug_version]
|
||||
m4_args += ["-D", "build_with_updater=" + args.updater_version]
|
||||
build_conf_cmd = ["m4", "-s", "--fatal-warnings"] + m4_args + file_list
|
||||
with open(output_conf, 'w') as fd:
|
||||
ret = subprocess.run(build_conf_cmd, shell=False, stdout=fd).returncode
|
||||
if ret != 0:
|
||||
raise Exception(ret)
|
||||
|
||||
|
||||
def build_cil(args, output_cil, input_conf):
|
||||
check_policy_cmd = [os.path.join(args.tool_path, "checkpolicy"),
|
||||
input_conf,
|
||||
"-M -C -c 31",
|
||||
"-o " + output_cil]
|
||||
run_command(check_policy_cmd)
|
||||
|
||||
|
||||
def add_version(version, string):
|
||||
return "".join([string, "_", version])
|
||||
|
||||
|
||||
def simplify_string(string):
|
||||
return string.replace('(', '').replace(')', '').replace('\n', '')
|
||||
|
||||
|
||||
def deal_with_roletype(version, cil_write, elem_list, type_set, file, line):
|
||||
if len(elem_list) < 3:
|
||||
print('Error: invalid roletype in %s:%d' % (file, line))
|
||||
raise Exception(1)
|
||||
|
||||
sub_string = simplify_string(elem_list[2])
|
||||
if sub_string in type_set:
|
||||
cil_write.write('(typeattribute ' + add_version(version, sub_string) + ')\n')
|
||||
elem_list[2] = elem_list[2].replace(
|
||||
sub_string, add_version(version, sub_string))
|
||||
cil_write.write(" ".join(elem_list))
|
||||
|
||||
|
||||
def deal_with_typeattribute(version, cil_write, elem_list, type_set, file, line):
|
||||
if len(elem_list) < 2:
|
||||
print('Error: invalid typeattribute in %s:%d' % (file, line))
|
||||
raise Exception(1)
|
||||
|
||||
sub_string = simplify_string(elem_list[1])
|
||||
if sub_string.startswith("base_typeattr_"):
|
||||
elem_list[1] = elem_list[1].replace(
|
||||
sub_string, add_version(version, sub_string))
|
||||
cil_write.write(" ".join(elem_list))
|
||||
|
||||
|
||||
def deal_with_typeattributeset(version, cil_write, elem_list, type_set, file, line):
|
||||
if len(elem_list) < 2:
|
||||
print('Error: invalid typeattributeset in %s:%d' % (file, line))
|
||||
raise Exception(1)
|
||||
|
||||
for index, elem in enumerate(elem_list[1:]):
|
||||
sub_string = simplify_string(elem)
|
||||
if sub_string.startswith("base_typeattr_") or sub_string in type_set:
|
||||
elem_list[index + 1] = elem.replace(sub_string, add_version(version, sub_string))
|
||||
cil_write.write(" ".join(elem_list))
|
||||
|
||||
|
||||
def deal_with_policy(version, cil_write, elem_list, type_set, file, line):
|
||||
if len(elem_list) < 4:
|
||||
print('Error: invalid policy in %s:%d' % (file, line))
|
||||
raise Exception(1)
|
||||
|
||||
for index, elem in enumerate(elem_list[1:3]):
|
||||
sub_string = simplify_string(elem)
|
||||
if sub_string.startswith("base_typeattr_") or sub_string in type_set:
|
||||
elem_list[index + 1] = elem.replace(sub_string, add_version(version, sub_string))
|
||||
cil_write.write(" ".join(elem_list))
|
||||
|
||||
|
||||
def deal_with_type(version, cil_write, elem_list, file, line):
|
||||
if len(elem_list) < 2:
|
||||
print('Error: invalid type in %s:%d' % (file, line))
|
||||
raise Exception(1)
|
||||
|
||||
sub_string = simplify_string(elem_list[1])
|
||||
cil_write.write(" ".join(['(typeattributeset', add_version(version, sub_string), '(', sub_string, '))\n']))
|
||||
cil_write.write(" ".join(['(expandtypeattribute', '(', add_version(version, sub_string), ') true)\n']))
|
||||
cil_write.write(" ".join(['(typeattribute', add_version(version, sub_string), ')\n']))
|
||||
|
||||
|
||||
def build_version_cil(version, cil_file_input, cil_file_output, type_set):
|
||||
index = 0
|
||||
with open(cil_file_input, 'r') as cil_read, open(cil_file_output, 'w') as cil_write:
|
||||
for line in cil_read:
|
||||
index += 1
|
||||
if not line.startswith('('):
|
||||
continue
|
||||
|
||||
elem_list = line.split(' ')
|
||||
if not elem_list:
|
||||
continue
|
||||
|
||||
if elem_list[0] == '(type':
|
||||
cil_write.write(line)
|
||||
elif elem_list[0] == '(roletype':
|
||||
deal_with_roletype(version, cil_write, elem_list, type_set, cil_file_input, line)
|
||||
elif elem_list[0] == '(typeattribute':
|
||||
deal_with_typeattribute(version, cil_write, elem_list, type_set, cil_file_input, line)
|
||||
elif elem_list[0] == '(typeattributeset':
|
||||
deal_with_typeattributeset(version, cil_write, elem_list, type_set, cil_file_input, line)
|
||||
elif simplify_string(elem_list[0]) in POLICY_TYPE_LIST:
|
||||
deal_with_policy(version, cil_write, elem_list, type_set, cil_file_input, line)
|
||||
else:
|
||||
cil_write.write(line)
|
||||
|
||||
|
||||
def build_type_version_cil(version, cil_file_input, cil_file_output):
|
||||
index = 0
|
||||
with open(cil_file_input, 'r') as cil_read, open(cil_file_output, 'w') as cil_write:
|
||||
for line in cil_read:
|
||||
index += 1
|
||||
if not line.startswith('('):
|
||||
continue
|
||||
|
||||
elem_list = line.split(' ')
|
||||
if not elem_list:
|
||||
continue
|
||||
|
||||
if elem_list[0] == '(type':
|
||||
deal_with_type(version, cil_write, elem_list, line, index)
|
||||
|
||||
|
||||
def get_type_set(cil_file_input):
|
||||
pattern_type = re.compile(r'^\(type (.*)\)$')
|
||||
pattern_typeattribute = re.compile(r'^\(type_attribute (base_typeattr_[0-9]+)\)$')
|
||||
type_set = set()
|
||||
with open(cil_file_input, 'r') as cil_read:
|
||||
for line in cil_read:
|
||||
match_type = pattern_type.match(line)
|
||||
match_typeattribute = pattern_typeattribute.match(line)
|
||||
if match_type:
|
||||
type_set.add(match_type.group(1))
|
||||
elif match_typeattribute:
|
||||
type_set.add(match_typeattribute.group(1))
|
||||
return type_set
|
||||
|
||||
|
||||
def build_binary_policy(tool_path, output_policy, check_neverallow, cil_list):
|
||||
build_policy_cmd = [os.path.join(tool_path, "secilc"),
|
||||
" ".join(cil_list),
|
||||
"-m -M true -G -c 31",
|
||||
"-f /dev/null",
|
||||
"-o " + output_policy]
|
||||
if not check_neverallow:
|
||||
build_policy_cmd.append("-N")
|
||||
run_command(build_policy_cmd)
|
||||
|
||||
|
||||
def prepare_build_path(dir_list, root_dir, build_dir_list, sepolicy_path):
|
||||
build_policy_list = [os.path.join(sepolicy_path, "base"), os.path.join(sepolicy_path, "ohos_policy")]
|
||||
build_policy_list += dir_list.split(":")
|
||||
|
||||
for i in build_policy_list:
|
||||
if i == "" or i == "default":
|
||||
continue
|
||||
path = os.path.join(root_dir, i)
|
||||
if (os.path.exists(path)):
|
||||
build_dir_list.append(path)
|
||||
else:
|
||||
print("following path not exists!! {}".format(path))
|
||||
exit(-1)
|
||||
|
||||
|
||||
def get_policy_dir_list(args):
|
||||
sepolicy_path = os.path.join(args.source_root_dir, "base/security/selinux/sepolicy/")
|
||||
dir_list = []
|
||||
prepare_build_path(args.policy_dir_list, args.source_root_dir, dir_list, sepolicy_path)
|
||||
min_policy_dir_list = [os.path.join(sepolicy_path, "min")]
|
||||
system_policy = []
|
||||
public_policy = []
|
||||
vendor_policy = []
|
||||
|
||||
for item in dir_list:
|
||||
public_policy += traverse_folder_in_dir_name(item, "public")
|
||||
system_policy += traverse_folder_in_dir_name(item, "system")
|
||||
vendor_policy += traverse_folder_in_dir_name(item, "vendor")
|
||||
|
||||
# list of all policy folders
|
||||
system_policy_dir_list = public_policy + system_policy
|
||||
vendor_policy_dir_list = public_policy + vendor_policy + min_policy_dir_list
|
||||
public_policy_dir_list = public_policy + min_policy_dir_list
|
||||
|
||||
# add temp dirs base/te folders
|
||||
system_policy_dir_list.append(os.path.join(sepolicy_path, "base/te"))
|
||||
vendor_policy_dir_list.append(os.path.join(sepolicy_path, "base/te"))
|
||||
public_policy_dir_list.append(os.path.join(sepolicy_path, "base/te"))
|
||||
|
||||
return PolicyDirList(min_policy_dir_list, system_policy_dir_list, vendor_policy_dir_list, public_policy_dir_list)
|
||||
|
||||
|
||||
def get_policy_file_list(args, dir_list_object):
|
||||
build_root = os.path.abspath(os.path.join(args.tool_path, "../../.."))
|
||||
# list of all policy files
|
||||
system_policy_file_list = traverse_file_in_each_type(
|
||||
dir_list_object.system_policy_dir_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
vendor_policy_file_list = traverse_file_in_each_type(
|
||||
dir_list_object.vendor_policy_dir_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
public_policy_file_list = traverse_file_in_each_type(
|
||||
dir_list_object.public_policy_dir_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
min_policy_file_list = traverse_file_in_each_type(
|
||||
dir_list_object.min_policy_dir_list, SEPOLICY_TYPE_LIST, build_root)
|
||||
|
||||
return PolicyFileList(min_policy_file_list, system_policy_file_list, vendor_policy_file_list,
|
||||
public_policy_file_list)
|
||||
|
||||
|
||||
def filter_out(pattern_file, input_file):
|
||||
patterns = []
|
||||
with open(pattern_file, 'r') as pat_file:
|
||||
patterns.extend(pat_file.readlines())
|
||||
|
||||
tmp_output = tempfile.NamedTemporaryFile()
|
||||
with open(input_file, 'r') as in_file:
|
||||
tmp_output.writelines(line.encode(encoding='utf-8') for line in in_file.readlines()
|
||||
if line not in patterns)
|
||||
tmp_output.write("\n".encode(encoding='utf-8'))
|
||||
tmp_output.flush()
|
||||
shutil.copyfile(tmp_output.name, input_file)
|
||||
|
||||
|
||||
def generate_hash_file(input_file_list, output_file):
|
||||
build_policy_cmd = ["cat",
|
||||
" ".join(input_file_list),
|
||||
"| sha256sum",
|
||||
"| cut -d' ' -f1",
|
||||
">",
|
||||
output_file]
|
||||
run_command(build_policy_cmd)
|
||||
|
||||
|
||||
def generate_version_file(args, output_file):
|
||||
cmd = ["echo", args.vendor_policy_version,
|
||||
">", output_file]
|
||||
run_command(cmd)
|
||||
|
||||
|
||||
def generate_default_policy(args, system_policy_file_list, vendor_policy_file_list, min_policy_file_list):
|
||||
output_path = os.path.abspath(os.path.dirname(args.dst_file))
|
||||
system_output_conf = os.path.join(output_path, "system.conf")
|
||||
vendor_output_conf = os.path.join(output_path, "vendor.conf")
|
||||
min_output_conf = os.path.join(output_path, "min.conf")
|
||||
|
||||
system_cil_path = os.path.join(output_path, "system.cil")
|
||||
vendor_cil_path = os.path.join(output_path, "vendor.cil")
|
||||
min_cil_path = os.path.join(output_path, "min.cil")
|
||||
|
||||
# build system.conf
|
||||
build_conf(args, system_output_conf, system_policy_file_list)
|
||||
# build system.cil
|
||||
build_cil(args, system_cil_path, system_output_conf)
|
||||
|
||||
# build vendor.conf
|
||||
build_conf(args, vendor_output_conf, vendor_policy_file_list)
|
||||
# build vendor.cil
|
||||
build_cil(args, vendor_cil_path, vendor_output_conf)
|
||||
|
||||
# build min.conf
|
||||
build_conf(args, min_output_conf, min_policy_file_list)
|
||||
# build min.cil
|
||||
build_cil(args, min_cil_path, min_output_conf)
|
||||
|
||||
filter_out(min_cil_path, vendor_cil_path)
|
||||
|
||||
return [vendor_cil_path, system_cil_path]
|
||||
|
||||
|
||||
def generate_special_policy(args, system_policy_file_list, vendor_policy_file_list, public_policy_file_list,
|
||||
min_policy_file_list):
|
||||
output_path = os.path.abspath(os.path.dirname(args.dst_file))
|
||||
system_output_conf = os.path.join(output_path, "system.conf")
|
||||
vendor_output_conf = os.path.join(output_path, "vendor.conf")
|
||||
public_output_conf = os.path.join(output_path, "public.conf")
|
||||
min_output_conf = os.path.join(output_path, "min.conf")
|
||||
|
||||
vendor_origin_cil_path = os.path.join(output_path, "vendor_origin.cil")
|
||||
public_origin_cil_path = os.path.join(output_path, "public_origin.cil")
|
||||
min_cil_path = os.path.join(output_path, "min.cil")
|
||||
|
||||
# output file
|
||||
system_cil_path = os.path.join(output_path, "system.cil")
|
||||
vendor_cil_path = os.path.join(output_path, "vendor.cil")
|
||||
public_version_cil_path = os.path.join(output_path, "public.cil")
|
||||
type_version_cil_path = os.path.join(output_path, "".join([args.vendor_policy_version, ".cil"]))
|
||||
|
||||
# build system.conf
|
||||
build_conf(args, system_output_conf, system_policy_file_list)
|
||||
# build system.cil
|
||||
build_cil(args, system_cil_path, system_output_conf)
|
||||
|
||||
# build min.cil
|
||||
build_conf(args, min_output_conf, min_policy_file_list)
|
||||
build_cil(args, min_cil_path, min_output_conf)
|
||||
|
||||
# build public.cil
|
||||
build_conf(args, public_output_conf, public_policy_file_list)
|
||||
build_cil(args, public_origin_cil_path, public_output_conf)
|
||||
type_set = get_type_set(public_origin_cil_path)
|
||||
filter_out(min_cil_path, public_origin_cil_path)
|
||||
build_version_cil(args.vendor_policy_version, public_origin_cil_path, public_version_cil_path, type_set)
|
||||
|
||||
# build vendor.cil
|
||||
build_conf(args, vendor_output_conf, vendor_policy_file_list)
|
||||
build_cil(args, vendor_origin_cil_path, vendor_output_conf)
|
||||
filter_out(min_cil_path, vendor_origin_cil_path)
|
||||
build_version_cil(args.vendor_policy_version, vendor_origin_cil_path, vendor_cil_path, type_set)
|
||||
filter_out(public_version_cil_path, vendor_cil_path)
|
||||
|
||||
build_type_version_cil(args.vendor_policy_version, public_origin_cil_path, type_version_cil_path)
|
||||
|
||||
if args.components == "system":
|
||||
generate_hash_file([system_cil_path, type_version_cil_path],
|
||||
os.path.join(output_path, SYSTEM_CIL_HASH))
|
||||
|
||||
elif args.components == "vendor":
|
||||
generate_hash_file([system_cil_path, type_version_cil_path], os.path.join(
|
||||
output_path, PREBUILD_SEPOLICY_SYSTEM_CIL_HASH))
|
||||
|
||||
version_file = os.path.join(output_path, "version")
|
||||
generate_version_file(args, version_file)
|
||||
|
||||
return [vendor_cil_path, system_cil_path, type_version_cil_path, public_version_cil_path]
|
||||
|
||||
|
||||
def compile_sepolicy(args):
|
||||
dir_list_object = get_policy_dir_list(args)
|
||||
file_list_object = get_policy_file_list(args, dir_list_object)
|
||||
|
||||
cil_list = []
|
||||
if args.components == "default" or args.updater_version == "enable":
|
||||
cil_list += generate_default_policy(args, file_list_object.system_policy_file_list,
|
||||
file_list_object.vendor_policy_file_list,
|
||||
file_list_object.min_policy_file_list)
|
||||
else:
|
||||
cil_list += generate_special_policy(args, file_list_object.system_policy_file_list,
|
||||
file_list_object.vendor_policy_file_list,
|
||||
file_list_object.public_policy_file_list,
|
||||
file_list_object.min_policy_file_list)
|
||||
|
||||
build_binary_policy(args.tool_path, args.dst_file, True, cil_list)
|
||||
|
||||
|
||||
def main(args):
|
||||
# check both debug and release sepolicy
|
||||
origin_debug_version = args.debug_version
|
||||
if args.debug_version == "true":
|
||||
args.debug_version = "false"
|
||||
compile_sepolicy(args)
|
||||
else:
|
||||
args.debug_version = "true"
|
||||
compile_sepolicy(args)
|
||||
|
||||
# build target policy according to desire debug_version
|
||||
args.debug_version = origin_debug_version
|
||||
compile_sepolicy(args)
|
@ -17,6 +17,7 @@ THIRD_PARTY_DIR = "//third_party"
|
||||
declare_args() {
|
||||
selinux_build_path = "default"
|
||||
components = "default"
|
||||
vendor_policy_version = "40"
|
||||
special_build_policy_script = "default"
|
||||
extra_args = "default"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user