+static int nftw_remove_labels(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
+ smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
+ smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
+
+ return 0;
+}
+
+static int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
+ smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
+ smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
+
+ return 0;
+}
+
+static int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ int result;
+ char* label;
+
+ /* ACCESS */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ result = strcmp(CANARY_LABEL, label);
+ RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
+
+ /* EXEC */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ result = strcmp(CANARY_LABEL, label);
+ RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
+
+ /* TRANSMUTE */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+ return 0;
+}
+
+static int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ int result;
+ char* label;
+
+ /* ACCESS */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
+ result = strcmp(APPID_DIR, label);
+ RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
+
+ /* EXEC */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
+ RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
+ result = strcmp(APPID_DIR, label);
+ RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
+ } else
+ RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
+
+ /* TRANSMUTE */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+ return 0;
+}
+
+static int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ int result;
+ char* label;
+
+ /* ACCESS */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
+ result = strcmp(APPID_SHARED_DIR, label);
+ RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
+
+ /* EXEC */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
+
+ /* TRANSMUTE */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ if (S_ISDIR(sb->st_mode)) {
+ RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
+ result = strcmp("TRUE", label);
+ RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
+ } else
+ RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+ return 0;
+}
+
+/**
+ * Test setting labels for all files and folders in given path.
+ */
+RUNNER_TEST(privilege_control01_app_label_dir)
+{
+ int result;
+
+ result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
+
+ result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
+
+ result = app_label_dir(APPID_DIR, TEST_APP_DIR);
+ RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
+
+ result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
+
+ result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
+}
+
+RUNNER_TEST(privilege_control02_app_label_shared_dir)
+{
+ int result;
+
+ result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
+
+ result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
+
+ result = app_label_shared_dir(APPID_ADD, APPID_SHARED_DIR, TEST_APP_DIR);
+ RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
+
+ result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
+
+ result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
+}
+
+