)
SET(libprivilege-control_LDFLAGS " -module -avoid-version ")
SET(libprivilege-control_CFLAGS " ${CFLAGS} -fPIC -I${include_dir}")
-SET(libprivilege-control_LIBADD "${pkgs_LDFLAGS} -lcap")
+SET(libprivilege-control_LIBADD "${pkgs_LDFLAGS} -lcap -lcrypt")
ADD_LIBRARY(privilege-control SHARED ${libprivilege-control_SOURCES})
TARGET_LINK_LIBRARIES(privilege-control ${libprivilege-control_LIBADD} ${pkgs_LIBRARIES})
INSTALL(FILES .privilege_control_all_apps_id.db DESTINATION /opt/dbspace)
INSTALL(FILES .privilege_control_all_avs_id.db DESTINATION /opt/dbspace)
INSTALL(FILES .privilege_control_app_gids.db DESTINATION /opt/dbspace)
+INSTALL(FILES .privilege_control_public_dirs.db DESTINATION /opt/dbspace)
#INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/udev/ DESTINATION lib/udev)
INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/slp-su DESTINATION bin)
*/
int get_app_gids(const char *app_id, unsigned **gids, int *len);
+/**
+ * This functions add public RO path to the database.
+ */
+int db_add_public_dir(const char *dir_label);
+
+/**
+ * This function returns (in params) list of public RO paths
+ * dir_labels should be freed by caller.
+ */
+int db_get_public_dirs(char ***dir_labels, int *len);
#endif // _ACCESS_DB_H_
#define API __attribute__((visibility("default")))
#endif // API
+#define DEPRECATED __attribute__((deprecated));
+
/* error codes */
#define PC_OPERATION_SUCCESS ((int)0)
#define PC_ERR_FILE_OPERATION -1
APP_TYPE_OTHER,
} app_type_t;
+typedef enum {
+ APP_PATH_PRIVATE,
+ APP_PATH_GROUP_RW,
+ APP_PATH_PUBLIC_RO,
+ APP_PATH_SETTINGS_RW
+} app_path_type_t;
+
/* APIs - used by applications */
-int control_privilege(void) __attribute__((deprecated));
+int control_privilege(void) DEPRECATED;
-int set_privilege(const char* pkg_name) __attribute__((deprecated));
+int set_privilege(const char* pkg_name) DEPRECATED;
/**
* Function get process smack label base on pid.
* @param app_id application identifier
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error.
*/
-int app_register_av(const char* app_av_id) __attribute__((deprecated));
+int app_register_av(const char* app_av_id) DEPRECATED;
/**
* Grant SMACK permissions based on permissions list.
* @param perm_list array of permission names, last element must be NULL
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
*/
-int app_add_permissions(const char* app_id, const char** perm_list) __attribute__((deprecated));
+int app_add_permissions(const char* app_id, const char** perm_list) DEPRECATED;
/**
* Grant temporary SMACK permissions based on permissions list.
* @param perm_list array of permission names, last element must be NULL
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
*/
-int app_add_volatile_permissions(const char* app_id, const char** perm_list) __attribute__((deprecated));
+int app_add_volatile_permissions(const char* app_id, const char** perm_list) DEPRECATED;
/**
* Grant SMACK permissions based on permissions list.
* This function should be called once during app installation.
* Results will be persistent on the file system.
* It must be called by privileged user.
+ * THIS FUNCTION IS NOW DEPRECATED. app_setup_path() SHOULD BE USED INSTEAD.
*
* @param app_label label name
* @param path directory path
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
*/
-int app_label_dir(const char* app_label, const char* path);
+int app_label_dir(const char* app_label, const char* path) DEPRECATED;
/**
* Recursively set SMACK access and transmute labels for an application
* Results will be persistent on the file system.
* It must be called by privileged user.
* Labels app_label and shared_label should not be equal.
+ * THIS FUNCTION IS NOW DEPRECATED. app_setup_path() SHOULD BE USED INSTEAD.
*
* @param app_label label name, used as subject for SMACK rule
* @param shared_label, used as object for SMACK rule
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
*/
int app_label_shared_dir(const char* app_label, const char* shared_label,
- const char* path);
-
-
+ const char* path) DEPRECATED;
/**
* Add SMACK rx rules for application identifiers to shared_label.
* This function should be called during app installation.
* It must be called by privileged user.
+ * THIS FUNCTION IS NOW DEPRECATED. NO REPLACEMENT IS NEEDED.
*
* @param shared_label label of the shared resource
* @param app_list list of application SMACK identifiers
* @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
*/
-int add_shared_dir_readers(const char* shared_label, const char** app_list);
+int add_shared_dir_readers(const char* shared_label, const char** app_list) DEPRECATED;
+
+/**
+ * Recursively set SMACK labels for an application directory. The exact behavior
+ * depends on app_path_type argument:
+ * - APP_PATH_PRIVATE: label with app's label, set access label on everything
+ * and execute label on executable files and symlinks to executable files
+ *
+ * - APP_PATH_GROUP_RW: label with given shared_label, set access label on
+ * everything and enable transmute on directories. Also give app_id full access
+ * to the shared label.
+ *
+ * - APP_PATH_PUBLIC_RO: label with autogenerated label, set access label on
+ * everything and enable transmute on directories. Give full access to the label to
+ * app_id and RX access to all other apps.
+ *
+ * - APP_PATH_SETTINGS_RW: label with autogenerated label, set access label on
+ * everything and enable transmute on directories. Give full access to the label to
+ * app_id and RWX access to all appsetting apps.
+ *
+ * This function should be called during app installation.
+ * Results will be persistent on the file system.
+ * It must be called by privileged user.
+ *
+ * @param app_id
+ * @param path
+ * @param app_path_type
+ * @param shared_label (optional argument for APP_PATH_GROUP_RW path type)
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int app_setup_path(const char* app_id, const char* path, app_path_type_t app_path_type, ...);
/**
* Make two applications "friends", by giving them both full permissions on
<filesystem path="/opt/dbspace/.privilege_control_all_apps_id.db" label="system::privilege_control::db"/>
<filesystem path="/opt/dbspace/.privilege_control_all_avs_id.db" label="system::privilege_control::db"/>
<filesystem path="/opt/dbspace/.privilege_control_app_gids.db" label="system::privilege_control::db"/>
+ <filesystem path="/opt/dbspace/.privilege_control_public_dirs.db" label="system::privilege_control::db"/>
</assign>
</manifest>
DB_APP_TYPE_APPLICATION,
DB_APP_TYPE_ANTIVIRUS,
DB_APP_TYPE_GROUPS,
+ DB_APP_TYPE_PUBLIC_DIRS,
DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */
} db_app_type_t;
"/opt/dbspace/.privilege_control_all_apps_id.db",
"/opt/dbspace/.privilege_control_all_avs_id.db",
"/opt/dbspace/.privilege_control_app_gids.db",
+ "/opt/dbspace/.privilege_control_public_dirs.db",
};
typedef struct element_s {
return ret;
}
+
+int db_add_public_dir(const char *dir_label)
+{
+ C_LOGD("Enter function: %s", __func__);
+
+ if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
+ return PC_ERR_DB_OPERATION;
+
+ return PC_OPERATION_SUCCESS;
+}
+
+int db_get_public_dirs(char ***dir_labels, int *len)
+{
+ C_LOGD("Enter function: %s", __func__);
+
+ if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
+ return PC_ERR_DB_OPERATION;
+
+ return PC_OPERATION_SUCCESS;
+}
return ret;
}
+/**
+ * This function will grant app_id RX access to all public directories and
+ * files, previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
+ * This should be call in app_install function.
+ */
+static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
+{
+ C_LOGD("Enter function: %s", __func__);
+ int ret, i;
+ char **public_dirs AUTO_FREE;
+ int public_dirs_cnt = 0;
+
+ ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("Error while geting data from database");
+ return ret;
+ }
+
+ for (i = 0; i < public_dirs_cnt; ++i) {
+ C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
+ if (smack_accesses_add(smack, app_id, public_dirs[i], "rx")) {
+ C_LOGE("app_add_rule failed");
+ while (i < public_dirs_cnt)
+ free(public_dirs[i++]);
+ return PC_ERR_INVALID_OPERATION;
+ }
+ free(public_dirs[i]);
+ }
+
+ return PC_OPERATION_SUCCESS;
+}
+
static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
{
C_LOGD("Enter function: %s", __func__);
return PC_OPERATION_SUCCESS;
}
+static char* smack_label_for_path(const char *app_id, const char *path)
+{
+ C_LOGD("Enter function: %s", __func__);
+ char *salt AUTO_FREE;
+ char *label;
+ char *x;
+
+ /* Prefix $1$ causes crypt() to use MD5 function */
+ if (-1 == asprintf(&salt, "$1$%s", app_id)) {
+ C_LOGE("asprintf failed");
+ return NULL;
+ }
+
+ label = crypt(path, salt);
+ if (label == NULL) {
+ C_LOGE("crypt failed");
+ return NULL;
+ }
+
+ /* crypt() output may contain slash character,
+ * which is not legal in Smack labels */
+ for (x = label; *x; ++x) {
+ if (*x == '/')
+ *x = '%';
+ }
+
+ return label;
+}
+
+/* FIXME: remove this pragma once deprecated API is deleted */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+API int app_setup_path(const char* app_id, const char* path, app_path_type_t app_path_type, ...)
+{
+ C_LOGD("Enter function: %s", __func__);
+ va_list ap;
+
+ if (!smack_label_is_valid(app_id)) {
+ C_LOGE("Invalid app_id %s", app_id);
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ switch (app_path_type) {
+ case APP_PATH_PRIVATE:
+ va_start(ap, app_path_type);
+ va_end(ap);
+ return app_label_dir(app_id, path);
+
+ case APP_PATH_GROUP_RW: {
+ const char *shared_label;
+
+ va_start(ap, app_path_type);
+ shared_label = va_arg(ap, const char *);
+ va_end(ap);
+
+ if (!smack_label_is_valid(shared_label)) {
+ C_LOGE("Invalid shared_label %s", shared_label);
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ if (strcmp(app_id, shared_label) == 0) {
+ C_LOGE("app_id equals shared_label");
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ return app_label_shared_dir(app_id, shared_label, path);
+ }
+
+ case APP_PATH_PUBLIC_RO: {
+ char **app_ids AUTO_FREE;
+ int app_ids_cnt = 0;
+ const char *label;
+ int i, ret;
+
+ va_start(ap, app_path_type);
+ va_end(ap);
+
+ C_LOGD("New public RO path %s", path);
+ label = smack_label_for_path(app_id, path);
+ if (label == NULL)
+ return PC_ERR_INVALID_OPERATION;
+
+ C_LOGD("Generated label '%s' for public RO path %s", label, path);
+ ret = app_label_shared_dir(app_id, label, path);
+ if (ret != PC_OPERATION_SUCCESS)
+ return ret;
+
+ /* FIXME: This should be in some kind of transaction/lock */
+ ret = db_add_public_dir(label);
+ if (ret != PC_OPERATION_SUCCESS)
+ return ret;
+
+ ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
+ if (ret != PC_OPERATION_SUCCESS)
+ return ret;
+
+ for (i = 0; i < app_ids_cnt; ++i) {
+ C_LOGD("Allowing app %s to access public path %s", app_id, label[i]);
+ ret = app_add_rule(app_ids[i], label, "rx");
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("smack_accesses_new failed");
+ while (i < app_ids_cnt)
+ free(app_ids[i++]);
+ return ret;
+ }
+ free(app_ids[i]);
+ }
+
+ return PC_OPERATION_SUCCESS;
+ }
+
+ case APP_PATH_SETTINGS_RW:
+ va_start(ap, app_path_type);
+ va_end(ap);
+ /* TODO */
+ break;
+
+ default:
+ va_start(ap, app_path_type);
+ va_end(ap);
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ return PC_OPERATION_SUCCESS;
+}
+/* FIXME: remove this pragma once deprecated API is deleted */
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+
API int app_add_friend(const char* app_id1, const char* app_id2)
{
C_LOGD("Enter function: %s", __func__);
int ret;
int fd AUTO_CLOSE;
char* smack_path AUTO_FREE;
+ struct smack_accesses *smack AUTO_SMACK_FREE;
if (!smack_label_is_valid(app_id))
return PC_ERR_INVALID_PARAM;
return PC_ERR_FILE_OPERATION;
}
+ if (smack_accesses_new(&smack)) {
+ C_LOGE("smack_accesses_new failed");
+ return PC_ERR_MEM_OPERATION;
+ }
+
ret = add_app_id_to_databse(app_id);
if (ret != PC_OPERATION_SUCCESS ) {
C_LOGE("Error while adding app %s to database: %s ", app_id, strerror(errno));
return ret;
}
+ ret = register_app_for_public_dirs(app_id, smack);
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", app_id, strerror(errno));
+ return ret;
+ }
+
+ if (have_smack() && smack_accesses_apply(smack)) {
+ C_LOGE("smack_accesses_apply failed");
+ return PC_ERR_INVALID_OPERATION;
+ }
+
+ if (smack_accesses_save(smack, fd)) {
+ C_LOGE("smack_accesses_save failed");
+ return PC_ERR_INVALID_OPERATION;
+ }
+
return PC_OPERATION_SUCCESS;
}