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
32 #include <dpl/test/test_runner.h>
33 #include <dpl/test/test_runner_child.h>
34 #include <dpl/log/log.h>
35 #include <sys/types.h>
38 #include <sys/xattr.h>
39 #include <sys/smack.h>
40 #include <privilege-control.h>
43 #define SMACK_RULES_DIR "/etc/smack/accesses.d/"
44 #define TEST_APP_DIR "/etc/smack/test_privilege_control_DIR/app_dir"
45 #define TEST_NON_APP_DIR "/etc/smack/test_privilege_control_DIR/non_app_dir"
46 #define APPID_ADD "test_APP_ID_add"
47 #define APPID_REVOKE "test_APP_ID_revoke"
48 #define APPID_DIR "test_APP_ID_dir"
49 #define APPID_SHARED_DIR "test_APP_ID_shared_dir"
50 #define CANARY_LABEL "tiny_yellow_canary"
52 #define APP_SET_PRIV "test_APP"
53 #define APP_SET_PRIV_PATH "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP"
54 #define APP_SET_PRIV_PATH_REAL "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP_REAL"
56 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
60 #define APP_USER_NAME "app"
61 #define APP_HOME_DIR "/opt/home/app"
63 // How many open file descriptors should ftw() function use?
64 #define FTW_MAX_FDS 16
66 // Rules from test_privilege_control_rules.smack
67 const std::vector< std::vector<std::string> > rulesAdd = {
68 { APPID_ADD, "test_book_1", "r" },
69 { APPID_ADD, "test_book_2", "w" },
70 { APPID_ADD, "test_book_3", "x" },
71 { APPID_ADD, "test_book_4", "rw" },
72 { APPID_ADD, "test_book_5", "rx" },
73 { APPID_ADD, "test_book_6", "wx" },
74 { APPID_ADD, "test_book_7", "rwx" },
75 { "test_subject_1", APPID_ADD, "r" },
76 { "test_subject_2", APPID_ADD, "w" },
77 { "test_subject_3", APPID_ADD, "x" },
78 { "test_subject_4", APPID_ADD, "rw" },
79 { "test_subject_5", APPID_ADD, "rx" },
80 { "test_subject_6", APPID_ADD, "wx" },
81 { "test_subject_7", APPID_ADD, "rwx" },
82 { APPID_ADD, APPID_SHARED_DIR, "rwxat"}};
85 // Rules from test_privilege_control_rules.smack
86 const std::vector< std::vector<std::string> > rulesRevoke = {
87 { APPID_REVOKE, "test_book_1", "r" },
88 { APPID_REVOKE, "test_book_2", "w" },
89 { APPID_REVOKE, "test_book_3", "x" },
90 { APPID_REVOKE, "test_book_4", "rw" },
91 { APPID_REVOKE, "test_book_5", "rx" },
92 { APPID_REVOKE, "test_book_6", "wx" },
93 { APPID_REVOKE, "test_book_7", "rwx" },
94 { "test_subject_1", APPID_REVOKE, "r" },
95 { "test_subject_2", APPID_REVOKE, "w" },
96 { "test_subject_3", APPID_REVOKE, "x" },
97 { "test_subject_4", APPID_REVOKE, "rw" },
98 { "test_subject_5", APPID_REVOKE, "rx" },
99 { "test_subject_6", APPID_REVOKE, "wx" },
100 { "test_subject_7", APPID_REVOKE, "rwx" }};
103 * Check if every rule is true.
104 * @return 1 if ALL rules in SMACK, 0 if ANY rule isn't
106 int test_have_all_accesses(const std::vector< std::vector<std::string> >& rules){
108 for(uint i =0; i<rules.size();++i ){
109 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
117 * Check if every rule is true.
118 * @return 1 if ANY rule in SMACK, 0 if
120 int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules){
122 for(uint i =0; i<rules.size();++i ){
123 result = smack_have_access(rules[i][0].c_str(),rules[i][1].c_str(),rules[i][2].c_str());
130 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
132 static int nftw_remove_labels(const char *fpath, const struct stat *sb,
133 int typeflag, struct FTW *ftwbuf)
135 smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
136 smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
137 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
142 static int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
143 int typeflag, struct FTW *ftwbuf)
145 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
146 smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
147 smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
152 static int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
153 int typeflag, struct FTW *ftwbuf)
159 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
160 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
161 result = strcmp(CANARY_LABEL, label);
162 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
165 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
166 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
167 result = strcmp(CANARY_LABEL, label);
168 RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
171 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
172 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
173 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
178 static int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
179 int typeflag, struct FTW *ftwbuf)
185 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
186 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
187 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
188 result = strcmp(APPID_DIR, label);
189 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
192 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
193 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
194 if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
195 RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
196 result = strcmp(APPID_DIR, label);
197 RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
199 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
202 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
203 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
204 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
209 static int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
210 int typeflag, struct FTW *ftwbuf)
216 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
217 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
218 RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
219 result = strcmp(APPID_SHARED_DIR, label);
220 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
223 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
224 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
225 RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
228 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
229 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
230 if (S_ISDIR(sb->st_mode)) {
231 RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
232 result = strcmp("TRUE", label);
233 RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
235 RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
241 * Test setting labels for all files and folders in given path.
243 RUNNER_TEST(privilege_control01_app_label_dir)
247 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
248 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
250 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
251 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
253 result = app_label_dir(APPID_DIR, TEST_APP_DIR);
254 RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
256 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
257 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
259 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
260 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
263 RUNNER_TEST(privilege_control02_app_label_shared_dir)
267 result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
268 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
270 result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
271 RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
273 result = app_label_shared_dir(APPID_ADD, APPID_SHARED_DIR, TEST_APP_DIR);
274 RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
276 result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
277 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
279 result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
280 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
285 * Add permisions from test_privilege_control_rules template
287 RUNNER_TEST(privilege_control03_add_permissions)
291 int result = app_add_permissions(APPID_ADD, PRIVS);
292 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
293 " Error adding app permissions. Errno: " << result);
295 // Check if the accesses are realy applied..
296 result = test_have_all_accesses(rulesAdd);
297 RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
299 ///Investigate created SMACK rules files..
300 RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_ADD) != -1,
301 "Error in asprintf");
304 FILE *pFile = fopen(path, "rb");
305 RUNNER_ASSERT_MSG(pFile != NULL,
306 "SMACK file NOT created!. Errno: " << errno);
309 fseek(pFile, 0L, SEEK_END);
310 int smack_file_length = ftell(pFile);
311 RUNNER_ASSERT_MSG(smack_file_length>0,
312 "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
315 result = app_revoke_permissions(APPID_ADD);
316 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
317 "Error revoking app permissions. Errno: " << result);
325 * Revoke permissions from the list. Should be executed as privileged user.
327 RUNNER_TEST(privilege_control04_revoke_permissions)
331 // Prepare permissions that we want to revoke
332 result = app_add_permissions(APPID_REVOKE, PRIVS);
333 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
334 " Error adding app permissions. Errno: " << result);
336 // Revoke permissions
337 result = app_revoke_permissions(APPID_REVOKE);
338 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
339 "Error revoking app permissions. Errno: " << result);
341 // Are all the permissions revoked?
342 result = test_have_all_accesses(rulesRevoke);
343 RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
345 // Investigate SMACK rules file
347 RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_REVOKE) != -1,
348 "Error in asprintf");
350 //// Is the smack file deleted?
351 FILE *pFile = fopen(path, "rb");
352 RUNNER_ASSERT_MSG(pFile == NULL,
353 "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
355 RUNNER_ASSERT_MSG(errno == ENOENT,
356 "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
363 * Set APP privileges.
365 RUNNER_CHILD_TEST(privilege_control05_set_app_privilege)
368 char* labelApp = "test_pc_label";
369 char* labelAppSymlink = "test_pc_label_symlink";
372 smack_lsetlabel(APP_SET_PRIV_PATH_REAL, labelApp, SMACK_LABEL_EXEC);
373 smack_lsetlabel(APP_SET_PRIV_PATH, labelAppSymlink, SMACK_LABEL_EXEC);
375 // Set APP privileges
376 result = set_app_privilege(APP_SET_PRIV, NULL, APP_SET_PRIV_PATH);
377 RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
379 // Check if SMACK label really set
381 result = smack_new_label_from_self(&label);
382 RUNNER_ASSERT_MSG(result == 0, "Error getting current process label");
383 RUNNER_ASSERT_MSG(label != NULL, "Process label is not set");
384 result = strcmp(labelApp, label);
385 RUNNER_ASSERT_MSG(result == 0, "Process label " << label << " is incorrect");
387 // Check if DAC privileges really set
388 RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
389 RUNNER_ASSERT_MSG(getgid() == APP_GID, "Wrong GID");
391 result = strcmp(getenv("HOME"), APP_HOME_DIR);
392 RUNNER_ASSERT_MSG(result == 0, "Wrong HOME DIR");
394 result = strcmp(getenv("USER"), APP_USER_NAME);
395 RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
398 RUNNER_TEST(privilege_control06_app_give_access)
400 const char *subject = "lkjq345v34sfa";
401 const char *object = "lk9290f92lkjz";
402 smack_accesses *tmp = NULL;
404 RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
406 std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
407 smack(tmp, smack_accesses_free);
409 RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "r--a-"));
410 RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
412 app_give_access(subject, object, "wt");
414 RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwat"));
415 RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
417 app_revoke_access(subject, object);
419 RUNNER_ASSERT(1 == smack_have_access(subject, object, "ra"));
420 RUNNER_ASSERT(0 == smack_have_access(subject, object, "w"));
421 RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
422 RUNNER_ASSERT(0 == smack_have_access(subject, object, "t"));
424 RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-"));
425 RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));