2 * Copyright (c) 2016 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <sys/capability.h>
22 #include <sys/prctl.h>
24 #include <sys/types.h>
29 #include <unordered_map>
31 #include <security-manager-types.h>
32 #include <app-runtime.h>
33 #include <privilege_info.h>
34 #include <scoped_process_label.h>
36 #include <dpl/test/test_runner.h>
39 #include <sm_commons.h>
41 #include <tests_common.h>
42 #include "tzplatform.h"
43 #include <template_parser.h>
44 #include <temp_test_user.h>
46 using namespace SecurityManagerTest;
51 // Common DB/nftw checks
53 // nftw doesn't allow passing user data to functions. Work around by using global variable
54 static std::string nftw_expected_label;
55 bool nftw_expected_transmute;
56 bool nftw_expected_exec;
58 static int nftw_check_sm_labels_app_dir(const char *fpath, const struct stat *sb,
59 const char* correctLabel, bool transmute_test, bool exec_test)
63 char* label = nullptr;
66 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
67 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
68 labelPtr.reset(label);
69 RUNNER_ASSERT_MSG(label != nullptr, "ACCESS label on " << fpath << " is not set");
70 result = strcmp(correctLabel, label);
71 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect"
72 " (should be '" << correctLabel << "' and is '" << label << "')");
76 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
77 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
78 labelPtr.reset(label);
80 if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR) && exec_test) {
81 RUNNER_ASSERT_MSG(label != nullptr, "EXEC label on " << fpath << " is not set");
82 result = strcmp(correctLabel, label);
83 RUNNER_ASSERT_MSG(result == 0, "Incorrect EXEC label on executable file " << fpath);
85 RUNNER_ASSERT_MSG(label == nullptr, "EXEC label on " << fpath << " is set");
89 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
90 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
91 labelPtr.reset(label);
93 if (S_ISDIR(sb->st_mode) && transmute_test == true) {
94 RUNNER_ASSERT_MSG(label != nullptr, "TRANSMUTE label on " << fpath << " is not set at all");
95 RUNNER_ASSERT_MSG(strcmp(label,"TRUE") == 0,
96 "TRANSMUTE label on " << fpath << " is not set properly: '"<<label<<"'");
98 RUNNER_ASSERT_MSG(label == nullptr, "TRANSMUTE label on " << fpath << " is set");
104 static int nftw_check_sm_labels(const char *fpath, const struct stat *sb,
105 int /*typeflag*/, struct FTW* /*ftwbuf*/)
107 return nftw_check_sm_labels_app_dir(fpath, sb,
108 nftw_expected_label.c_str(), nftw_expected_transmute, nftw_expected_exec);
111 int nftw_check_labels_non_app_dir(const char *fpath, const struct stat* /*sb*/,
112 int /*typeflag*/, struct FTW* /*ftwbuf*/)
116 char* label = nullptr;
119 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
120 labelPtr.reset(label);
121 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
122 result = strcmp("canary_label", labelPtr.get());
123 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
126 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
127 labelPtr.reset(label);
128 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
129 result = strcmp("canary_label", labelPtr.get());
130 RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
133 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
134 labelPtr.reset(label);
135 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
136 RUNNER_ASSERT_MSG(labelPtr.get() == nullptr, "TRANSMUTE label on " << fpath << " is set");
141 int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
142 int /*typeflag*/, struct FTW* /*ftwbuf*/)
144 smack_lsetlabel(fpath, nullptr, SMACK_LABEL_ACCESS);
145 smack_lsetlabel(fpath, nullptr, SMACK_LABEL_EXEC);
146 smack_lsetlabel(fpath, nullptr, SMACK_LABEL_TRANSMUTE);
151 void check_path(const std::string &path, const std::string &label, bool transmute, bool execute) {
152 nftw_expected_label = label;
153 nftw_expected_transmute = transmute;
154 nftw_expected_exec = execute;
157 int result = nftw(path.c_str(), &nftw_check_sm_labels, FTW_MAX_FDS, FTW_PHYS);
158 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path);
161 CapsSetsUniquePtr setCaps(const char *cap_string)
163 CapsSetsUniquePtr caps(cap_init());
164 caps.reset(cap_from_text(cap_string));
165 RUNNER_ASSERT_MSG(caps, "can't convert capabilities from text");
166 int result = cap_set_proc(caps.get());
167 RUNNER_ASSERT_MSG(result == 0, "can't set capabilities. Result: " << result);
171 static int getOppositeAccessType(int accessType) {
172 return accessType ^ (R_OK | W_OK | X_OK);
175 static const std::unordered_map<int, const char* const> accessTypeToString {
176 std::make_pair(0, "F_OK"),
177 std::make_pair(1, "X_OK"),
178 std::make_pair(2, "W_OK"),
179 std::make_pair(3, "W_OK|X_OK"),
180 std::make_pair(4, "R_OK"),
181 std::make_pair(5, "R_OK|X_OK"),
182 std::make_pair(6, "R_OK|W_OK"),
183 std::make_pair(7, "R_OK|W_OK|X_OK")
186 void accessCheck(const std::string &id, const std::string &path, int accessType,
189 RUNNER_ASSERT_MSG(::access(path.c_str(), accessType) == expected,
190 "access from " << id << " to path " << path
191 << (expected == 0 ? " not granted" : " unnecessarily granted")
192 << " (" << accessTypeToString.at(accessType) << ")");
195 void accessTest(const std::string &id, const std::string &testPath, int accessType) {
196 int oppositeAccessType = getOppositeAccessType(accessType);
198 if (accessType != 0) {
199 accessCheck(id, testPath, accessType, ALLOW);
201 if (oppositeAccessType != 0) {
202 static const std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
203 for (auto singleAccessType : singleAccessTypes) {
204 if (oppositeAccessType & singleAccessType) {
205 accessCheck(id, testPath, singleAccessType, DENY);
211 void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
212 const std::string &testPath, int accessType) {
214 ScopedProcessLabel spl(label, false);
215 RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid),
216 "drop_root_privileges failed.");
218 accessTest(label, testPath, accessType);
221 runInChildParentWait(fun);
224 void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) {
226 Api::setProcessLabel(app.getAppId());
227 RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(app.getUID(), app.getGID()),
228 "drop_root_privileges failed.");
229 accessTest(app.getAppId(), testPath, accessType);
232 runInChildParentWait(fun);
235 static const std::vector<std::string> SM_SYSTEM_LABELS = {"System", "System::Privileged", "User"};
237 void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType) {
238 for (const auto &label : SM_SYSTEM_LABELS)
239 runAccessTest(label, uid, gid, testPath, accessType);
242 bool isAskuserDisabled() {
243 static bool isAskuserDisabled = false;
244 static bool isChecked = false;
247 return isAskuserDisabled;
249 std::string sysShare = TzPlatformConfig::getPath(TZ_SYS_SHARE);
250 std::string askDisableFile = sysShare + "/askuser_disable";
252 isAskuserDisabled = (access(askDisableFile.c_str(), F_OK) != -1);
254 return isAskuserDisabled;
257 bool isPrivilegePrivacy(const std::string &priv) {
258 return (1 == privilege_info_is_privacy(priv.c_str()));
261 int countPrivacyPrivileges(const PrivilegeVector &privs) {
262 return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
265 int countPrivacyPrivileges(const std::vector<std::string> &privs) {
266 return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
269 int setLauncherSecurityAttributes(uid_t uid, gid_t gid)
271 // Add launcher capabilities (cap_dac_override, cap_setgid, cap_sys_admin, cap_mac_admin),
272 // launcher is user process, we must drop root privileges (cap_setgid, cap_setuid are needed).
273 // By default, the permitted capability set is cleared when credentials change is made
274 // (if a process drops a capability from its permitted set, it can never reacquire that capability),
275 // setting the "keep capabilities" flag prevents it from being cleared.
276 // Effective capability set is always cleared when credential change is made, we need to add them again.
278 setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
279 int ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0);
283 ret = drop_root_privileges(uid, gid);
287 setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
290 int setLauncherSecurityAttributes(TemporaryTestUser &user)
292 return setLauncherSecurityAttributes(user.getUid(), user.getGid());