#define TIZEN_PRIVILEGE_ANTIVIRUS "http://tizen.org/privilege/antivirus"
#define TIZEN_PRIVILEGE_APPSETTING "http://tizen.org/privilege/appsetting"
-
typedef struct {
char user_name[10];
int uid;
return PC_OPERATION_SUCCESS;
}
-static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix)
+static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
{
const char* app_type_prefix = NULL;
char* perm_basename = NULL;
return ret;
}
- ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
- app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
- perm_basename, suffix);
+ if (is_early) {
+ ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
+ app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
+ perm_basename, "_early", suffix);
+ }
+ else {
+ ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
+ app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
+ perm_basename, suffix);
+ }
if (ret == -1) {
C_LOGE("asprintf failed");
return PC_ERR_MEM_OPERATION;
return PC_OPERATION_SUCCESS;
}
-static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
+static int perm_to_smack_generic(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm, bool is_early)
{
C_LOGD("Enter function: %s", __func__);
+
int ret;
char* path AUTO_FREE;
char* format_string AUTO_FREE;
char smack_accesses[10];
// get file name for permission (devcap)
- ret = perm_file_path(&path, app_type, perm, ".smack");
+ ret = perm_file_path(&path, app_type, perm, ".smack", is_early);
if (ret != PC_OPERATION_SUCCESS) {
C_LOGD("No smack config file for permission %s", perm);
return ret;
return PC_OPERATION_SUCCESS;
}
+static int perm_to_smack_early(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
+{
+ C_LOGD("Enter function: %s", __func__);
+
+ return perm_to_smack_generic(smack, app_label, app_type, perm, 1);
+}
+
+static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
+{
+ C_LOGD("Enter function: %s", __func__);
+
+ return perm_to_smack_generic(smack, app_label, app_type, perm, 0);
+}
+
static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
{
C_LOGD("Enter function: %s", __func__);
FILE* file AUTO_FCLOSE;
int gid;
- ret = perm_file_path(&path, app_type, perm, ".dac");
+ ret = perm_file_path(&path, app_type, perm, ".dac", 0);
if (ret != PC_OPERATION_SUCCESS) {
C_LOGD("No dac config file for permission %s", perm);
return ret;
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__);
- char* smack_path AUTO_FREE;
int i, ret;
+ char* smack_path AUTO_FREE;
+ char* smack_path_early AUTO_FREE;
int fd AUTO_CLOSE;
+ int fd_early AUTO_CLOSE;
struct smack_accesses *smack AUTO_SMACK_FREE;
+ struct smack_accesses *smack_early AUTO_SMACK_FREE;
const char* base_perm = NULL;
if (!smack_label_is_valid(app_id))
return ret;
}
+ ret = load_smack_from_file_early(app_id, &smack_early, &fd_early, &smack_path_early);
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("load_smack_from_file failed");
+ return ret;
+ }
+
/* Implicitly enable base permission for an app_type */
base_perm = app_type_name(app_type);
if (base_perm) {
C_LOGE("perm_to_smack failed");
return ret;
}
+
+ // Add early permission - such permissions should be enabled right after system boot
+ SECURE_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
+ ret = perm_to_smack_early(smack_early, app_id, APP_TYPE_OTHER, base_perm);
+ if (ret != PC_OPERATION_SUCCESS){
+ C_LOGE("perm_to_smack failed");
+ return ret;
+ }
+
}
for (i = 0; perm_list[i] != NULL; ++i) {
SECURE_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
return ret;
}
+ ret = perm_to_smack_early(smack_early, app_id, app_type, perm_list[i]);
+ if (ret != PC_OPERATION_SUCCESS){
+ C_LOGE("perm_to_smack_early failed");
+ return ret;
+ }
+
ret = perm_to_dac(app_id, app_type, perm_list[i]);
if (ret != PC_OPERATION_SUCCESS){
C_LOGE("perm_to_dac failed");
return PC_ERR_INVALID_OPERATION;
}
+ if (have_smack() && smack_accesses_apply(smack_early)) {
+ C_LOGE("smack_accesses_apply (early) failed");
+ return PC_ERR_INVALID_OPERATION;
+ }
+
if (permanent && smack_accesses_save(smack, fd)) {
C_LOGE("smack_accesses_save failed");
return PC_ERR_INVALID_OPERATION;
}
+ if (permanent && smack_accesses_save(smack_early, fd_early)) {
+ C_LOGE("smack_accesses_save (early) failed");
+ return PC_ERR_INVALID_OPERATION;
+ }
+
return PC_OPERATION_SUCCESS;
}
return PC_OPERATION_SUCCESS;
}
+static int app_uninstall_remove_early_rules(const char *app_id)
+{
+ C_LOGD("Enter function: %s", __func__);
+
+ int ret = PC_OPERATION_SUCCESS;
+ FILE *file AUTO_FCLOSE;
+ FILE *file_new AUTO_FCLOSE;
+ char *tmp_filename AUTO_FREE;
+ char *single_line_format AUTO_FREE;
+ char subject[SMACK_LABEL_LEN + 1];
+ char object[SMACK_LABEL_LEN + 1];
+ char rule_add[6]; // "rwxat" + '\0'
+ char rule_remove[6]; // "rwxat" + '\0'
+ sem_t *sem = NULL;
+
+ subject[SMACK_LABEL_LEN] = '\0';
+ object[SMACK_LABEL_LEN] = '\0';
+ rule_add[5] = '\0';
+ rule_remove[5] = '\0';
+
+ // Creating (opening) and waiting for semaphore
+ sem = sem_open(PRIVILEGE_CONTROL_UNINSTALL_SEM, O_CREAT, S_IRWXU | S_IRWXU | S_IRWXO, 1);
+ if (sem == SEM_FAILED) {
+ C_LOGE("sem_open failed, error: %s", strerror(errno));
+ ret = PC_ERR_INVALID_OPERATION;
+ goto out;
+ }
+ C_LOGD("Waiting for semaphore");
+ ret = sem_wait(sem);
+ if (ret < 0) {
+ C_LOGE("sem_wait failed, error: %s", strerror(errno));
+ ret = PC_ERR_INVALID_OPERATION;
+ goto out;
+ }
+
+ ret = asprintf(&single_line_format, "%%%ds %%%ds %%5s %%5s\\n", SMACK_LABEL_LEN, SMACK_LABEL_LEN);
+ if (ret < 0) {
+ C_LOGE("asprintf failed");
+ ret = PC_ERR_MEM_OPERATION;
+ goto out;
+ }
+
+ ret = asprintf(&tmp_filename, "%s.tmp", SMACK_STARTUP_RULES_FILE);
+ if (ret < 0) {
+ C_LOGE("asprintf failed");
+ ret = PC_ERR_MEM_OPERATION;
+ goto out;
+ }
+
+ file = fopen(SMACK_STARTUP_RULES_FILE, "r");
+ if (NULL == file) {
+ C_LOGE("fopen failed on %s", SMACK_STARTUP_RULES_FILE);
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+
+ file_new = fopen(tmp_filename, "w");
+ if (NULL == file) {
+ C_LOGE("fopen failed on %s", tmp_filename);
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+
+ while (fscanf(file, single_line_format, subject, object, rule_add, rule_remove) == 4) {
+ C_LOGD("Checking line \"%s %s %s %s\"", subject, object, rule_add, rule_remove);
+
+ if ((strncmp(subject, app_id, SMACK_LABEL_LEN) == 0) || (strncmp(object, app_id, SMACK_LABEL_LEN) == 0)) {
+ C_LOGD("app_id found - rule will be ignored");
+ continue; // do not re-write this rule for new file
+ }
+
+ if (0 > fprintf(file_new, "%s %s %s %s\n", subject, object, rule_add, rule_remove)) { // re-writing rule to new file
+ C_LOGE("Write rule \"%s %s %s %s\" to file failed. %s", subject, object, rule_add, rule_remove, strerror(errno));
+ // Should we return with error here?
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+ }
+
+ fclose(file);
+ file = NULL;
+ fclose(file_new);
+ file_new = NULL;
+
+ if (unlink(SMACK_STARTUP_RULES_FILE)) {
+ C_LOGE("unlink failed %s", strerror(errno));
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+
+ if (rename(tmp_filename, SMACK_STARTUP_RULES_FILE)) {
+ C_LOGE("rename failed. %s", strerror(errno));
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+
+ if (chmod(SMACK_STARTUP_RULES_FILE, 644)) {
+ C_LOGE("chmod failed on %s file. Error: %s", tmp_filename, strerror(errno));
+ ret = PC_ERR_FILE_OPERATION;
+ goto out;
+ }
+
+ ret = PC_OPERATION_SUCCESS;
+
+out:
+
+ sem_post(sem);
+ sem_unlink(PRIVILEGE_CONTROL_UNINSTALL_SEM);
+ return ret;
+}
+
/*
* This function will be used to allow direct communication between 2 OSP application.
* This function requires to store "state" with list of added label.
*
- * Full implementation requires some kind of database. This implemetation works without
+ * Full implementation requires some kind of database. This implementation works without
* database so you wont be able to revoke permissions added by different process.
*/
API int app_give_access(const char* subject, const char* object, const char* permissions)
return PC_OPERATION_SUCCESS;
}
+ ret = app_uninstall_remove_early_rules(pkg_id);
+ if (ret != PC_OPERATION_SUCCESS)
+ return ret;
+
+
return PC_OPERATION_SUCCESS;
}
// TODO check process capabilities
// get feature SMACK file name
- ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack");
+ ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack", 0);
if (ret != PC_OPERATION_SUCCESS || !smack_file ) {
return ret;
}
// check .dac existence only if gids are supported
if (list_of_db_gids && list_size > 0) {
// get feature DAC file name
- ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac");
+ ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
return ret;
}