From 33307d3242d517d3978e75d97e2294a6d715fd95 Mon Sep 17 00:00:00 2001 From: zhongning5 Date: Mon, 11 Mar 2024 20:17:21 +0800 Subject: [PATCH] =?UTF-8?q?DAC=E7=94=A8=E6=88=B7=E7=BE=A4=E7=BB=84?= =?UTF-8?q?=E5=90=88=E6=B3=95=E6=80=A7=E7=9C=8B=E6=8A=A4=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhongning5 --- .../config_parser_mgr/config_parser_mgr.py | 4 +- .../user_group/user_group_parser.py | 140 ++++++++++++++++++ .../rules/NO-User-Group_In-Init/README.md | 25 ++++ .../NO-User-Group_In-Init/whitelist.json | 0 .../startup_guard/startup_checker/__init__.py | 2 + .../startup_checker/cmds_rule.py | 2 +- .../startup_checker/system_parameter_rules.py | 2 +- .../startup_checker/user_group_rule.py | 68 +++++++++ 8 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 tools/startup_guard/config_parser_mgr/user_group/user_group_parser.py create mode 100644 tools/startup_guard/rules/NO-User-Group_In-Init/README.md create mode 100644 tools/startup_guard/rules/NO-User-Group_In-Init/whitelist.json create mode 100644 tools/startup_guard/startup_checker/user_group_rule.py diff --git a/tools/startup_guard/config_parser_mgr/config_parser_mgr.py b/tools/startup_guard/config_parser_mgr/config_parser_mgr.py index e6e8154..7e82bce 100644 --- a/tools/startup_guard/config_parser_mgr/config_parser_mgr.py +++ b/tools/startup_guard/config_parser_mgr/config_parser_mgr.py @@ -21,6 +21,7 @@ sys.path.append('.') from .param.system_parameter_parser import parameters_collect from .cfg.config_parser import startup_config_collect +from .user_group.user_group_parser import create_user_group_parser def __create_arg_parser(): import argparse @@ -37,7 +38,8 @@ class ConfigParserMgr(object): def load_all_parser(self, options): cfg_parser = startup_config_collect(options) param_parser = parameters_collect(options) - self._parser_list = {'cmd_whitelist':cfg_parser, 'system_parameter_whitelist':param_parser} + user_group = create_user_group_parser(options) + self._parser_list = {'config_parser':cfg_parser, 'system_parameter_parser':param_parser, "user_group":user_group} def get_parser_by_name(self, key): if key: diff --git a/tools/startup_guard/config_parser_mgr/user_group/user_group_parser.py b/tools/startup_guard/config_parser_mgr/user_group/user_group_parser.py new file mode 100644 index 0000000..66f368f --- /dev/null +++ b/tools/startup_guard/config_parser_mgr/user_group/user_group_parser.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2024 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 string +import sys +import os + +class GroupFileParser(): + def __init__(self): + self._group = {} + + def _handleGroupInfo(self, groupInfo): + name = groupInfo[0].strip() + userNames = name + if len(groupInfo) > 3 and len(groupInfo[3]) > 0: + userNames = groupInfo[3] + oldGroup = self._group.get(name) + if oldGroup: + return + group = { + "name" : name, + "groupId" : int(groupInfo[2], 10), + "userNames" : userNames + } + self._group[name] = group + + def loadFile(self, fileName): + #print(" loadFile %s" % fileName) + if not os.path.exists(fileName): + return + try: + with open(fileName, encoding='utf-8') as fp: + line = fp.readline() + while line : + if line.startswith("#") or len(line) < 3: + line = fp.readline() + continue + groupInfo = line.strip("\n").split(":") + if len (groupInfo) < 3: + line = fp.readline() + continue + self._handleGroupInfo(groupInfo) + line = fp.readline() + except: + pass + + def dump(self): + for group in self._group.values() : + print(str(group)) + +class PasswdFileParser(): + def __init__(self): + self._passwd = {} + self._passwd_yellow = {} + self._name_list = [] + self._uid_list = [] + + def _handlePasswdInfo(self, passwdInfo): + name = passwdInfo[0].strip() + self._uid_list.append(int(passwdInfo[2], 10)) + self._name_list.append(name) + oldPasswd = self._passwd.get(name) + if oldPasswd: + return + + gid = int(passwdInfo[3], 10) + uid = int(passwdInfo[2], 10) + + passwd = { + "name" : name, + "groupId" : gid, + "passwdId" : uid + } + self._passwd[name] = passwd + + def loadFile(self, fileName): + # print(" loadFile %s" % fileName) + if not os.path.exists(fileName): + return + try: + with open(fileName, encoding='utf-8') as fp: + line = fp.readline() + while line : + if line.startswith("#") or len(line) < 3: + line = fp.readline() + continue + passwdInfo = line.strip("\n").split(":") + if len (passwdInfo) < 4: + line = fp.readline() + continue + self._handlePasswdInfo(passwdInfo) + line = fp.readline() + except: + pass + + def dump(self): + for group in self._passwd.values() : + print(str(group)) + +def _create_arg_parser(): + import argparse + parser = argparse.ArgumentParser(description='Collect group information from system/etc/group dir.') + parser.add_argument('-i', '--input', + help='input group files base directory example "out/rk3568/packages/phone/" ', required=True) + + parser.add_argument('-o', '--output', + help='output group information database directory', required=False) + return parser + +def create_user_group_parser(base_path): + path = os.path.join(base_path, "packages/phone") + parser = GroupFileParser() + parser.loadFile(os.path.join(path, "system/etc/group")) + #parser.dump() + + passwd = PasswdFileParser() + passwd.loadFile(os.path.join(path, "system/etc/passwd")) + # passwd.dump() + return parser, passwd + +if __name__ == '__main__': + args_parser = _create_arg_parser() + options = args_parser.parse_args() + create_user_group_parser(options.input) + diff --git a/tools/startup_guard/rules/NO-User-Group_In-Init/README.md b/tools/startup_guard/rules/NO-User-Group_In-Init/README.md new file mode 100644 index 0000000..3415338 --- /dev/null +++ b/tools/startup_guard/rules/NO-User-Group_In-Init/README.md @@ -0,0 +1,25 @@ +# DAC用户群组合法性规则说明 + +## 规则解释 + + - 规则要求 + 1. 检查用户名、uid的唯一性。 + 2. 检查passwd 文件中,同一用户定义的uid和所属的组是否一致。 + + - 解决方法 + 1. 按照uid 设置规则,重新设置用户名、uid。 + 2. 同一用户的uid和gid值一致。 + + - uid设置规则: + 1. uid具有唯一性,不同用户/组的 uid,gid不可以相同。 + 2. 用户名/组名具有唯一性,不同用户的用户名/组名不可以相同。 + +编译时会提示如下类型的告警: + ``` + [NOT ALLOWED]: repeat uid name list: ['nwebspawn', 'nwebspawn'] + [NOT ALLOWED]: repeat uid value list: [3081, 3081] + [NOT ALLOWED]: xxx has different passwd and group values +``` + +## 违规场景及处理方案建议 + 1. 根据 **[规则解释](README.md#规则解释)** 排查修改。 diff --git a/tools/startup_guard/rules/NO-User-Group_In-Init/whitelist.json b/tools/startup_guard/rules/NO-User-Group_In-Init/whitelist.json new file mode 100644 index 0000000..e69de29 diff --git a/tools/startup_guard/startup_checker/__init__.py b/tools/startup_guard/startup_checker/__init__.py index 5231516..18f77ed 100755 --- a/tools/startup_guard/startup_checker/__init__.py +++ b/tools/startup_guard/startup_checker/__init__.py @@ -18,11 +18,13 @@ from .cmds_rule import cmdRule from .system_parameter_rules import SystemParameterRule +from .user_group_rule import UserGroupModuleRule def check_all_rules(mgr, args): rules = [ cmdRule, SystemParameterRule, + UserGroupModuleRule, ] passed = True diff --git a/tools/startup_guard/startup_checker/cmds_rule.py b/tools/startup_guard/startup_checker/cmds_rule.py index 15d1ed2..59c7ef1 100644 --- a/tools/startup_guard/startup_checker/cmds_rule.py +++ b/tools/startup_guard/startup_checker/cmds_rule.py @@ -135,7 +135,7 @@ class cmdRule(BaseRule): def check_config_cmd(self): passed = True self._parse_while_list() - cfg_parser = self.get_mgr().get_parser_by_name('cmd_whitelist') + cfg_parser = self.get_mgr().get_parser_by_name('config_parser') self._get_json_service() start_passed = self._check_start_cmd(cfg_parser) diff --git a/tools/startup_guard/startup_checker/system_parameter_rules.py b/tools/startup_guard/startup_checker/system_parameter_rules.py index 3f11a4d..cbf1da1 100644 --- a/tools/startup_guard/startup_checker/system_parameter_rules.py +++ b/tools/startup_guard/startup_checker/system_parameter_rules.py @@ -49,7 +49,7 @@ class SystemParameterRule(BaseRule): passed = True value_empty_flag = True white_list =self.get_white_lists() - parser = self.get_mgr().get_parser_by_name('system_parameter_whitelist') + parser = self.get_mgr().get_parser_by_name('system_parameter_parser') counts = 0 for key, item in parser._parameters.items(): if (item.get("dacMode") != 0): diff --git a/tools/startup_guard/startup_checker/user_group_rule.py b/tools/startup_guard/startup_checker/user_group_rule.py new file mode 100644 index 0000000..25c24e0 --- /dev/null +++ b/tools/startup_guard/startup_checker/user_group_rule.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2024 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 + +from .base_rule import BaseRule + +class UserGroupModuleRule(BaseRule): + RULE_NAME = "NO-User-Group_In-Init" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + + def _check_gid_in_passwd(self, passwd): + isPassed = True + for key, value in passwd.items(): + if value["passwdId"] == value["groupId"]: + pass + else: + isPassed = False + self.error("%s has different passwd and group values" % value["name"]) + return isPassed + + def check_user_group(self): + passed = True + passwd_parser = self.get_mgr().get_parser_by_name('user_group') + group_id = passwd_parser[0] + passwd_id = passwd_parser[1] + + cfg_parser = self.get_mgr().get_parser_by_name('config_parser') + repeat_name = [] + repeat_uid = [] + for uid in passwd_id._uid_list: + if passwd_id._uid_list.count(uid) > 1: + repeat_uid.append(uid) + + for name in passwd_id._name_list: + if passwd_id._name_list.count(name) > 1: + repeat_name.append(name) + if len(repeat_name): + passed = False + self.error("repeat uid name list: %s" % repeat_name) + + if len(repeat_uid): + passed = False + self.error("repeat uid value list: %s" % repeat_uid) + + if (self._check_gid_in_passwd(passwd_id._passwd) == -1): + passed = False + self.error("%s has different passwd and group values" % value["uid"]) + + def __check__(self): + return self.check_user_group() -- Gitee