2 * Copyright (c) 2012 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.
18 * @file test_cases.cpp
19 * @author Jan Olszak (j.olszak@samsung.com)
20 * @author Rafal Krypa (r.krypa@samsung.com)
22 * @brief libprivilege-control test runer
31 #include <dpl/test/test_runner.h>
32 #include <dpl/log/log.h>
33 #include <sys/types.h>
36 #include <sys/xattr.h>
37 #include <sys/smack.h>
38 #include <privilege-control.h>
41 #define SMACK_RULES_DIR "/etc/smack/accesses.d/"
42 #define TEST_APP_DIR "/etc/smack/test_privilege_control_DIR/app_dir"
43 #define TEST_NON_APP_DIR "/etc/smack/test_privilege_control_DIR/non_app_dir"
44 #define APPID_ADD "test_APP_ID_add"
45 #define APPID_REVOKE "test_APP_ID_revoke"
46 #define APPID_DIR "test_APP_ID_dir"
47 #define APPID_SHARED_DIR "test_APP_ID_shared_dir"
48 #define CANARY_LABEL "tiny_yellow_canary"
50 #define APP_SET_PRIV "test_APP"
51 #define APP_SET_PRIV_PATH "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP"
53 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
57 #define APP_USER_NAME "app"
58 #define APP_HOME_DIR "/opt/home/app"
60 // How many open file descriptors should ftw() function use?
61 #define FTW_MAX_FDS 16
63 // Rules from test_privilege_control_rules.smack
64 const std::vector< std::vector<std::string> > rulesAdd = {
65 { APPID_ADD, "test_book_1", "r" },
66 { APPID_ADD, "test_book_2", "w" },
67 { APPID_ADD, "test_book_3", "x" },
68 { APPID_ADD, "test_book_4", "rw" },
69 { APPID_ADD, "test_book_5", "rx" },
70 { APPID_ADD, "test_book_6", "wx" },
71 { APPID_ADD, "test_book_7", "rwx" },
72 { "test_subject_1", APPID_ADD, "r" },
73 { "test_subject_2", APPID_ADD, "w" },
74 { "test_subject_3", APPID_ADD, "x" },
75 { "test_subject_4", APPID_ADD, "rw" },
76 { "test_subject_5", APPID_ADD, "rx" },
77 { "test_subject_6", APPID_ADD, "wx" },
78 { "test_subject_7", APPID_ADD, "rwx" },
79 { APPID_ADD, APPID_SHARED_DIR, "rwxat"}};
82 // Rules from test_privilege_control_rules.smack
83 const std::vector< std::vector<std::string> > rulesRevoke = {
84 { APPID_REVOKE, "test_book_1", "r" },
85 { APPID_REVOKE, "test_book_2", "w" },
86 { APPID_REVOKE, "test_book_3", "x" },
87 { APPID_REVOKE, "test_book_4", "rw" },
88 { APPID_REVOKE, "test_book_5", "rx" },
89 { APPID_REVOKE, "test_book_6", "wx" },
90 { APPID_REVOKE, "test_book_7", "rwx" },
91 { "test_subject_1", APPID_REVOKE, "r" },
92 { "test_subject_2", APPID_REVOKE, "w" },
93 { "test_subject_3", APPID_REVOKE, "x" },
94 { "test_subject_4", APPID_REVOKE, "rw" },
95 { "test_subject_5", APPID_REVOKE, "rx" },
96 { "test_subject_6", APPID_REVOKE, "wx" },
97 { "test_subject_7", APPID_REVOKE, "rwx" }};
100 * Check if every rule is true.
101 * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
103 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
105 for(uint i =0; i<rules.size();++i ){
106 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
114 * Check if every rule is true.
115 * @return 1 if ANY rule in SMACK, 0 if
117 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
119 for(uint i =0; i<rules.size();++i ){
120 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
127 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
129 static int nftw_remove_labels(const char *fpath, const struct stat *sb,
130 int typeflag, struct FTW *ftwbuf)
132 smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
133 smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
134 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
139 static int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
140 int typeflag, struct FTW *ftwbuf)
142 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
143 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
144 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
149 static int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
150 int typeflag, struct FTW *ftwbuf)
156 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
157 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
158 result = strcmp(CANARY_LABEL, label);
159 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
162 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
163 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
164 result = strcmp(CANARY_LABEL, label);
165 RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
168 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
169 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
170 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
175 static int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
176 int typeflag, struct FTW *ftwbuf)
182 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
183 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
184 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
185 result = strcmp(APPID_DIR, label);
186 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
189 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
190 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
191 if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
192 RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
193 result = strcmp(APPID_DIR, label);
194 RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
196 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
199 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
200 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
201 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
206 static int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
207 int typeflag, struct FTW *ftwbuf)
213 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
214 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
215 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
216 result = strcmp(APPID_SHARED_DIR, label);
217 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
220 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
221 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
222 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
225 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
226 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
227 if (S_ISDIR(sb->st_mode)) {
228 RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
229 result = strcmp("TRUE", label);
230 RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
232 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
238 * Test setting labels for all files and folders in given path.
240 RUNNER_TEST(privilege_control01_app_label_dir)
244 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
245 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
247 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
248 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
250 result = app_label_dir(APPID_DIR, TEST_APP_DIR);
251 RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
253 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
254 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
256 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
257 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
260 RUNNER_TEST(privilege_control02_app_label_shared_dir)
264 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
265 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
267 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
268 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
270 result = app_label_shared_dir(APPID_ADD, APPID_SHARED_DIR, TEST_APP_DIR);
271 RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
273 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
274 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
276 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
277 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
282 * Add permisions from test_privilege_control_rules template
284 RUNNER_TEST(privilege_control03_add_permissions)
288 int result = app_add_permissions(APPID_ADD, PRIVS);
289 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
290 " Error adding app permissions. Errno: " << result);
292 // Check if the accesses are realy applied..
293 result = test_have_all_accesses(rulesAdd);
294 RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
296 ///Investigate created SMACK rules files..
297 RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_ADD) != -1,
298 "Error in asprintf");
301 FILE *pFile = fopen(path, "rb");
302 RUNNER_ASSERT_MSG(pFile != NULL,
303 "SMACK file NOT created!. Errno: " << errno);
306 fseek(pFile, 0L, SEEK_END);
307 int smack_file_length = ftell(pFile);
308 RUNNER_ASSERT_MSG(smack_file_length>0,
309 "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
312 result = app_revoke_permissions(APPID_ADD);
313 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
314 "Error revoking app permissions. Errno: " << result);
323 * Revoke permissions from the list. Should be executed as privileged user.
325 RUNNER_TEST(privilege_control04_revoke_permissions)
329 // Prepare permissions that we want to revoke
330 result = app_add_permissions(APPID_REVOKE, PRIVS);
331 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
332 " Error adding app permissions. Errno: " << result);
334 // Revoke permissions
335 result = app_revoke_permissions(APPID_REVOKE);
336 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
337 "Error revoking app permissions. Errno: " << result);
339 // Are all the permissions revoked?
340 result = test_have_all_accesses(rulesRevoke);
341 RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
343 // Investigate SMACK rules file
345 RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_REVOKE) != -1,
346 "Error in asprintf");
348 //// Is the smack file deleted?
349 FILE *pFile = fopen(path, "rb");
350 RUNNER_ASSERT_MSG(pFile == NULL,
351 "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
353 RUNNER_ASSERT_MSG(errno == ENOENT,
354 "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
361 * Set APP privileges.
363 RUNNER_TEST(privilege_control05_set_app_privilege)
366 char* labelApp = "test_pc_label";
369 smack_setlabel(APP_SET_PRIV_PATH,labelApp, SMACK_LABEL_EXEC);
371 // Set APP privileges
372 result = set_app_privilege(APP_SET_PRIV, NULL, APP_SET_PRIV_PATH);
373 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
375 // Check if SMACK label really set
377 result = smack_new_label_from_self(&label);
378 RUNNER_ASSERT_MSG(result == 0, "Error setting label for exec" << result);
379 result = strcmp(labelApp, label);
380 RUNNER_ASSERT_MSG(result == 0, "Label NOT set");
382 // Check if DAC privileges really set
383 RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
384 RUNNER_ASSERT_MSG(getgid() == APP_GID, "Wrong GID");
386 result = strcmp(getenv("HOME"), APP_HOME_DIR);
387 RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
389 result = strcmp(getenv("USER"), APP_USER_NAME);
390 RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");