2 * libprivilege control, rules database
4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Jan Olszak <j.olszak@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 * @file rules-db-internals.c
24 * @author Jan Olszak (j.olszak@samsung.com)
26 * @brief Definition of internal functions of the rules-db API.
29 #include <errno.h> // For error logging
30 #include <stdarg.h> // For handling multiple arguments
31 #include <stdlib.h> // For free
32 #include <stdio.h> // For file manipulation
33 #include "common.h" // For smack_label_is_valid
34 #include <unistd.h> // For sleep
36 #include "rules-db-internals.h"
39 #define RDB_MAX_QUERY_ATTEMPTS 50
40 #define RDB_TIME_BETWEEN_ATTEMPTS 1 // sec
43 * Reset and unbind statement. Used in functions that use bindings.
44 * @param p_stmt SQLite3 statement
45 * @return PC_OPERATION_SUCCESS on success, error code otherwise
47 static int reset_and_unbind_stmt(sqlite3_stmt *p_stmt)
49 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
50 C_LOGE("RDB: Error unbinding statement: %s",
51 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
52 return PC_ERR_DB_QUERY_STEP;
55 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
56 C_LOGE("RDB: Error reseting statement: %s",
57 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
58 return PC_ERR_DB_QUERY_STEP;
60 return PC_OPERATION_SUCCESS;
66 * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
68 * @ingroup RDB: internal functions
70 * @param p_stmt SQLite3 statement
71 * @return PC_OPERATION_SUCCESS on success, error code otherwise
73 static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
75 if(sqlite3_step(p_stmt) == SQLITE_DONE) {
76 return PC_OPERATION_SUCCESS;
78 C_LOGE("RDB: Error during stepping: %s",
79 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
80 return PC_ERR_DB_QUERY_STEP;
84 int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
86 int ret = PC_OPERATION_SUCCESS;
87 sqlite3_stmt *p_stmt = NULL;
88 ret = prepare_stmt(p_db, &p_stmt,
89 "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
91 if(ret != PC_OPERATION_SUCCESS) goto finish;
93 ret = step_and_convert_returned_value(p_stmt);
95 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
96 C_LOGE("RDB: Error during finalizing statement: %s",
97 sqlite3_errmsg(p_db));
102 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
104 int ret = PC_OPERATION_SUCCESS;
105 sqlite3_stmt *p_stmt = NULL;
106 ret = prepare_stmt(p_db, &p_stmt,
107 "INSERT OR IGNORE INTO modified_label(name) \
108 SELECT app_permission_view.app_name \
109 FROM app_permission_view \
110 WHERE app_permission_view.permission_id = %d",
112 if(ret != PC_OPERATION_SUCCESS) goto finish;
114 ret = step_and_convert_returned_value(p_stmt);
116 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
117 C_LOGE("RDB: Error during finalizing statement: %s",
118 sqlite3_errmsg(p_db));
123 int add_modified_apps_path_internal(sqlite3 *p_db,
124 const char *const s_app_label_name)
126 int ret = PC_OPERATION_SUCCESS;
127 sqlite3_stmt *p_stmt = NULL;
128 ret = prepare_stmt(p_db, &p_stmt,
129 "INSERT OR IGNORE INTO modified_label(name) \
130 SELECT path_view.path_label_name \
132 WHERE path_view.owner_app_label_name = %Q",
134 if(ret != PC_OPERATION_SUCCESS) goto finish;
136 ret = step_and_convert_returned_value(p_stmt);
138 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
139 C_LOGE("RDB: Error during finalizing statement: %s",
140 sqlite3_errmsg(p_db));
146 * Function called when the target database is busy.
147 * We attempt to access the database every
148 * RDB_TIME_BETWEEN_ATTEMPTS seconds
150 * @param not_used not used
151 * @param i_attempt number of the attempt
152 * @return 0 when stops waiting
155 static int database_busy_handler(void *not_used UNUSED,
158 if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
159 // I ain't gonna wait for you forever!
160 C_LOGE("RDB: Database busy for too long.");
163 C_LOGW("RDB: Database busy, waiting");
164 sleep(RDB_TIME_BETWEEN_ATTEMPTS);
169 int open_rdb_connection(sqlite3 **p_db, bool b_create_temporary_tables)
176 int ret = sqlite3_open_v2(RDB_PATH,
181 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
182 return PC_ERR_DB_CONNECTION;
184 if(ret != SQLITE_OK) {
185 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
186 return PC_ERR_DB_CONNECTION;
189 //Register busy handler:
190 if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
191 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
192 return PC_ERR_DB_CONNECTION;
196 if(sqlite3_enable_load_extension(*p_db, 1) != SQLITE_OK) {
197 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
198 return PC_ERR_DB_CONNECTION;
201 if(sqlite3_load_extension(*p_db,
202 "/usr/lib/librules-db-sql-udf.so", 0,
203 &p_err_msg) != SQLITE_OK) {
205 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
207 sqlite3_free(p_err_msg);
208 return PC_ERR_DB_CONNECTION;
210 sqlite3_free(p_err_msg);
213 if (b_create_temporary_tables) {
214 // Create the temporary tables:
215 if(sqlite3_exec(*p_db,
216 "PRAGMA foreign_keys = ON; \
218 PRAGMA temp_store = MEMORY; \
220 CREATE TEMPORARY TABLE modified_label( \
221 name VARCHAR NOT NULL PRIMARY KEY); \
223 CREATE TEMPORARY TABLE all_smack_binary_rules_modified( \
224 subject TEXT NOT NULL, \
225 object TEXT NOT NULL, \
226 access INTEGER NOT NULL, \
227 is_volatile INTEGER NOT NULL); \
229 CREATE TEMPORARY TABLE current_smack_rule_modified( \
230 subject VARCHAR NOT NULL, \
231 object VARCHAR NOT NULL, \
232 access INTEGER NOT NULL); \
234 CREATE TEMPORARY TABLE history_smack_rule_modified( \
235 subject VARCHAR NOT NULL, \
236 object VARCHAR NOT NULL, \
237 access INTEGER NOT NULL); \
239 CREATE TEMPORARY VIEW modified_smack_rules AS \
240 SELECT subject, object, \
241 access_to_str(access_add) AS access_add, \
242 access_to_str(access_del) AS access_del \
244 SELECT subject, object, \
245 s1.access & ~s2.access AS access_add, \
246 s2.access & ~s1.access AS access_del \
247 FROM current_smack_rule_modified AS s1 \
248 INNER JOIN history_smack_rule_modified AS s2 \
249 USING (subject, object) \
250 WHERE s1.access != s2.access \
252 SELECT subject, object, \
253 s1.access AS access_add, \
255 FROM current_smack_rule_modified s1 \
256 LEFT JOIN history_smack_rule_modified s2 \
257 USING (subject, object) \
258 WHERE s2.subject IS NULL AND \
261 SELECT subject, object, \
263 s1.access AS access_del \
264 FROM history_smack_rule_modified s1 \
265 LEFT JOIN current_smack_rule_modified s2 \
266 USING (subject, object) \
267 WHERE s2.subject IS NULL AND \
270 ORDER BY subject, object ASC;",
271 0, 0, 0) != SQLITE_OK) {
272 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
273 return PC_ERR_DB_CONNECTION;
276 // Just enable foreign keys:
277 if(sqlite3_exec(*p_db, "PRAGMA foreign_keys = ON", 0, 0, 0) != SQLITE_OK) {
278 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
279 return PC_ERR_DB_CONNECTION;
283 return PC_OPERATION_SUCCESS;
287 int prepare_stmt(sqlite3 *p_db,
288 sqlite3_stmt **pp_stmt,
289 const char *const s_sql,
292 int ret = PC_ERR_DB_QUERY_PREP;
293 char *s_query = NULL;
295 va_start(args, s_sql);
297 s_query = sqlite3_vmprintf(s_sql, args);
299 if(s_query == NULL) {
300 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
301 ret = PC_ERR_DB_QUERY_PREP;
305 if(sqlite3_prepare_v2(p_db,
309 NULL) != SQLITE_OK) {
310 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
311 ret = PC_ERR_DB_QUERY_PREP;
315 if(*pp_stmt == NULL) {
316 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
317 ret = PC_ERR_DB_QUERY_PREP;
321 ret = PC_OPERATION_SUCCESS;
325 sqlite3_free(s_query);
330 int check_app_label_internal(sqlite3 *p_db,
331 const char *const s_label_name)
333 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
335 int ret = PC_ERR_DB_OPERATION;
336 sqlite3_stmt *p_stmt = NULL;
338 ret = prepare_stmt(p_db, &p_stmt,
340 FROM application_view \
341 WHERE application_view.name=%Q \
344 if(ret != PC_OPERATION_SUCCESS) goto finish;
346 ret = sqlite3_step(p_stmt);
347 if(ret == SQLITE_ROW) {
348 // There is such application label
349 ret = PC_ERR_DB_LABEL_TAKEN;
350 } else if(ret == SQLITE_DONE) {
351 // No such application label
352 ret = PC_OPERATION_SUCCESS;
354 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
355 ret = PC_ERR_DB_QUERY_STEP;
358 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
359 C_LOGE("RDB: Error during finalizing statement: %s",
360 sqlite3_errmsg(p_db));
365 int add_app_internal(sqlite3 *p_db,
366 const char *const s_label_name)
368 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
370 int ret = PC_ERR_DB_OPERATION;
371 sqlite3_stmt *p_stmt = NULL;
373 ret = prepare_stmt(p_db, &p_stmt,
374 "INSERT into application_view(name) VALUES(%Q)",
376 if(ret != PC_OPERATION_SUCCESS) goto finish;
378 ret = step_and_convert_returned_value(p_stmt);
380 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
381 C_LOGE("RDB: Error during finalizing statement: %s",
382 sqlite3_errmsg(p_db));
387 int remove_app_internal(sqlite3 *p_db,
388 const char *const s_label_name)
390 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
392 int ret = PC_ERR_DB_OPERATION;
393 sqlite3_stmt *p_stmt = NULL;
395 ret = prepare_stmt(p_db, &p_stmt,
396 "DELETE FROM application_view \
397 WHERE application_view.name=%Q",
400 if(ret != PC_OPERATION_SUCCESS) goto finish;
402 ret = step_and_convert_returned_value(p_stmt);
404 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
405 C_LOGE("RDB: Error during finalizing statement: %s",
406 sqlite3_errmsg(p_db));
411 int add_path_internal(sqlite3 *p_db,
412 const char *const s_owner_label_name,
413 const char *const s_path_label_name,
414 const char *const s_path,
415 const char *const s_access,
416 const char *const s_access_reverse,
417 const char *const s_type)
419 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
420 s_owner_label_name, s_path_label_name,
421 s_path, s_access, s_access_reverse, s_type);
423 int ret = PC_ERR_DB_OPERATION;
424 sqlite3_stmt *p_stmt = NULL;
426 ret = prepare_stmt(p_db, &p_stmt,
427 "INSERT INTO path_view(owner_app_label_name, \
433 VALUES(%Q, %Q, %Q, %Q, %Q, %Q);",
434 s_owner_label_name, s_path, s_path_label_name,
435 s_access, s_access_reverse, s_type);
436 if(ret != PC_OPERATION_SUCCESS) goto finish;
438 ret = step_and_convert_returned_value(p_stmt);
440 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
441 C_LOGE("RDB: Error during finalizing statement: %s",
442 sqlite3_errmsg(p_db));
447 int add_permission_internal(sqlite3 *p_db,
448 const char *const s_permission_name,
449 const char *const s_permission_type_name)
451 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
453 int ret = PC_ERR_DB_OPERATION;
454 sqlite3_stmt *p_stmt = NULL;
456 ret = prepare_stmt(p_db, &p_stmt,
457 "INSERT INTO permission_view(name, type_name) \
459 s_permission_name, s_permission_type_name);
461 if(ret != PC_OPERATION_SUCCESS) goto finish;
463 ret = step_and_convert_returned_value(p_stmt);
465 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
466 C_LOGE("RDB: Error during finalizing statement: %s",
467 sqlite3_errmsg(p_db));
472 int get_permission_id_internal(sqlite3 *p_db,
473 const char *const s_permission_name,
474 const char *const s_permission_type_name,
475 sqlite3_int64 *p_permission_id)
477 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
479 int ret = PC_ERR_DB_OPERATION;
480 sqlite3_stmt *p_stmt = NULL;
482 ret = prepare_stmt(p_db, &p_stmt,
483 "SELECT permission_view.permission_id \
484 FROM permission_view \
485 WHERE permission_view.name = %Q AND \
486 permission_view.type_name = %Q \
488 s_permission_name, s_permission_type_name);
489 if(ret != PC_OPERATION_SUCCESS) goto finish;
491 ret = sqlite3_step(p_stmt);
492 if(ret == SQLITE_ROW) {
493 ret = PC_OPERATION_SUCCESS;
494 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
495 } else if(ret == SQLITE_DONE) {
496 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
497 ret = PC_ERR_DB_OPERATION;
500 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
501 ret = PC_ERR_DB_QUERY_STEP;
505 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
506 C_LOGE("RDB: Error during finalizing statement: %s",
507 sqlite3_errmsg(p_db));
513 int prepare_stmts_for_bind(sqlite3 *p_db,
514 sqlite3_stmt **pp_stmt,
515 const char *const s_query)
517 if(sqlite3_prepare_v2(p_db,
521 NULL) != SQLITE_OK) {
522 C_LOGE("RDB: Error during preparing statement: %s",
523 sqlite3_errmsg(p_db));
524 return PC_ERR_DB_QUERY_PREP;
526 return PC_OPERATION_SUCCESS;
530 static int add_permission_label_rule(sqlite3_stmt *p_stmt,
531 const sqlite3_int64 i_permission_id,
532 const char *const s_label_name,
533 const char *const s_access,
534 const int i_is_reverse)
536 int ret = PC_OPERATION_SUCCESS;
538 // Bind values to the statement and run it:
539 // Bind returns SQLITE_OK == 0 on success
540 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
541 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
542 sqlite3_bind_text(p_stmt, 3, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
543 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
544 C_LOGE("RDB: Error during binding to statement: %s",
545 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
546 ret = PC_ERR_DB_QUERY_BIND;
550 // Perform the insert
551 ret = step_and_convert_returned_value(p_stmt);
554 reset_and_unbind_stmt(p_stmt);
559 static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
560 const sqlite3_int64 i_permission_id,
561 const sqlite3_int64 i_target_permission_id,
562 const char *const s_access,
563 const int i_is_reverse)
565 int ret = PC_OPERATION_SUCCESS;
567 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
568 sqlite3_bind_int(p_stmt, 2, i_target_permission_id) ||
569 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
570 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
571 C_LOGE("RDB: Error during binding to statement: %s",
572 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
573 ret = PC_ERR_DB_QUERY_BIND;
577 ret = step_and_convert_returned_value(p_stmt);
580 reset_and_unbind_stmt(p_stmt);
585 static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
586 const sqlite3_int64 i_permission_id,
587 const char *const s_path_type_name,
588 const char *const s_access,
589 const int i_is_reverse)
591 int ret = PC_OPERATION_SUCCESS;
593 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
594 sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0) ||
595 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
596 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
597 C_LOGE("RDB: Error during binding to statement: %s",
598 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
599 ret = PC_ERR_DB_QUERY_BIND;
603 ret = step_and_convert_returned_value(p_stmt);
606 reset_and_unbind_stmt(p_stmt);
610 int add_permission_rules_internal(sqlite3 *p_db,
611 const sqlite3_int64 i_permission_id,
612 const char *const *const pp_smack_rules)
616 int ret = PC_OPERATION_SUCCESS;
617 char s_label[SMACK_LABEL_LEN + 1];
618 char s_access[ACC_LEN + 1];
619 sqlite3_int64 i_all_apps_permission_id = 1;
620 int i_is_reverse = 0;
622 sqlite3_stmt *p_perm_to_label_stmt = NULL;
623 sqlite3_stmt *p_perm_to_perm_stmt = NULL;
624 sqlite3_stmt *p_perm_to_app_path_type_stmt = NULL;
626 // Prepare stmts. They are static, so we parse SQL only once per process and reuse it.
627 ret = prepare_stmts_for_bind(p_db, &p_perm_to_label_stmt,
628 "INSERT INTO permission_label_rule_view( \
629 permission_id, access, label_name, is_reverse) \
631 if(ret != PC_OPERATION_SUCCESS) goto finish;
633 ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
634 "INSERT OR REPLACE INTO permission_permission_rule( \
635 permission_id, target_permission_id, \
636 access, is_reverse) \
637 VALUES(?,?,str_to_access(?),?)");
638 if(ret != PC_OPERATION_SUCCESS) goto finish;
641 ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
642 "INSERT INTO permission_app_path_type_rule_view( \
643 permission_id, app_path_type_name, access, is_reverse) \
645 if(ret != PC_OPERATION_SUCCESS) goto finish;
648 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
649 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
651 // Ignore empty lines
652 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
655 ret = parse_rule(pp_smack_rules[i], s_label, s_access, &i_is_reverse);
656 if(ret != PC_OPERATION_SUCCESS) goto finish;
658 // Interpret wildcards
659 if(s_label[0] != '~' &&
660 s_label[strlen(s_label) - 1] != '~') {
661 // It's not a wildcard!
662 ret = add_permission_label_rule(p_perm_to_label_stmt,
667 if(ret != PC_OPERATION_SUCCESS) goto finish;
669 } else if(!strcmp(s_label, "~ALL_APPS~")) {
670 ret = get_permission_id_internal(p_db,
673 &i_all_apps_permission_id);
674 if(ret != PC_OPERATION_SUCCESS) goto finish;
676 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
678 i_all_apps_permission_id,
681 if(ret != PC_OPERATION_SUCCESS) goto finish;
683 } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
684 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
689 if(ret != PC_OPERATION_SUCCESS) goto finish;
691 } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
692 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
697 if(ret != PC_OPERATION_SUCCESS) goto finish;
699 } else if(!strcmp(s_label, "~GROUP_PATH~")) {
700 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
705 if(ret != PC_OPERATION_SUCCESS) goto finish;
707 } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
708 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
713 if(ret != PC_OPERATION_SUCCESS) goto finish;
717 ret = PC_OPERATION_SUCCESS;
720 if(p_perm_to_label_stmt &&
721 sqlite3_finalize(p_perm_to_label_stmt) != SQLITE_OK) {
722 C_LOGE("RDB: Error during finalizing statement: %s",
723 sqlite3_errmsg(p_db));
726 if(p_perm_to_perm_stmt &&
727 sqlite3_finalize(p_perm_to_perm_stmt) != SQLITE_OK) {
728 C_LOGE("RDB: Error during finalizing statement: %s",
729 sqlite3_errmsg(p_db));
732 if(p_perm_to_app_path_type_stmt &&
733 sqlite3_finalize(p_perm_to_app_path_type_stmt) != SQLITE_OK) {
734 C_LOGE("RDB: Error during finalizing statement: %s",
735 sqlite3_errmsg(p_db));
741 int get_app_id_internal(sqlite3 *p_db,
743 const char *const s_app_label_name)
745 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
747 int ret = PC_ERR_DB_OPERATION;
748 sqlite3_stmt *p_stmt = NULL;
750 ret = prepare_stmt(p_db, &p_stmt,
751 "SELECT application_view.app_id \
752 FROM application_view \
753 WHERE application_view.name = %Q LIMIT 1",
756 if(ret != PC_OPERATION_SUCCESS) goto finish;
758 ret = sqlite3_step(p_stmt);
759 if(ret == SQLITE_ROW) {
760 ret = PC_OPERATION_SUCCESS;
761 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
763 } else if(ret == SQLITE_DONE) {
764 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
765 ret = PC_ERR_DB_OPERATION;
768 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
769 ret = PC_ERR_DB_QUERY_STEP;
773 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
774 C_LOGE("RDB: Error during finalizing statement: %s",
775 sqlite3_errmsg(p_db));
780 int add_app_permission_internal(sqlite3 *p_db,
782 const char *const s_permission_name,
783 const char *const s_permission_type_name,
784 const bool b_is_volatile_new,
785 const bool b_is_enabled_new)
787 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
788 s_permission_name, s_permission_type_name,
789 b_is_volatile_new, b_is_enabled_new);
792 int ret = PC_ERR_DB_OPERATION;
793 sqlite3_stmt *p_stmt = NULL;
795 ret = prepare_stmt(p_db, &p_stmt,
797 app_permission_view(app_id, name, type_name, \
798 is_volatile, is_enabled) \
799 VALUES(%d,%Q,%Q,%d,%d)",
800 i_app_id, s_permission_name, s_permission_type_name,
801 (int)b_is_volatile_new, (int)b_is_enabled_new);
803 if(ret != PC_OPERATION_SUCCESS) goto finish;
805 ret = step_and_convert_returned_value(p_stmt);
807 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
808 C_LOGE("RDB: Error during finalizing statement: %s",
809 sqlite3_errmsg(p_db));
814 int switch_app_permission_internal(sqlite3 *p_db,
816 const char *const s_permission_name,
817 const char *const s_permission_type_name,
818 const bool b_is_enabled_new)
820 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
821 s_permission_name, s_permission_type_name,
824 int ret = PC_ERR_DB_OPERATION;
825 sqlite3_stmt *p_stmt = NULL;
827 ret = prepare_stmt(p_db, &p_stmt,
828 "UPDATE app_permission_view \
830 WHERE app_id = %d AND \
833 b_is_enabled_new, i_app_id,
834 s_permission_name, s_permission_type_name);
836 if(ret != PC_OPERATION_SUCCESS) goto finish;
837 ret = step_and_convert_returned_value(p_stmt);
839 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
840 C_LOGE("RDB: Error during finalizing statement: %s",
841 sqlite3_errmsg(p_db));
846 int update_app_permission_internal(sqlite3 *p_db,
848 const int i_permission_id,
849 const bool b_is_volatile_new,
850 const bool b_is_enabled_new)
852 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
853 i_app_id, i_permission_id,
854 b_is_volatile_new, b_is_enabled_new);
856 int ret = PC_ERR_DB_OPERATION;
857 sqlite3_stmt *p_stmt = NULL;
859 ret = prepare_stmt(p_db, &p_stmt,
860 "UPDATE app_permission \
861 SET is_volatile = %d, is_enabled=%d \
862 WHERE app_id = %d AND permission_id = %d",
863 b_is_volatile_new, b_is_enabled_new,
864 i_app_id, i_permission_id);
866 if(ret != PC_OPERATION_SUCCESS) goto finish;
867 ret = step_and_convert_returned_value(p_stmt);
869 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
870 C_LOGE("RDB: Error during finalizing statement: %s",
871 sqlite3_errmsg(p_db));
876 int change_app_permission_internal(sqlite3 *p_db,
878 const char *const s_permission_name,
879 const char *const s_permission_type_name,
880 int i_is_volatile_new,
881 int i_is_enabled_new)
883 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
884 s_permission_name, s_permission_type_name,
885 i_is_volatile_new, i_is_enabled_new);
887 int ret = PC_ERR_DB_OPERATION;
888 sqlite3_stmt *p_stmt = NULL;
889 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
891 ret = prepare_stmt(p_db, &p_stmt,
892 "SELECT is_volatile, is_enabled, permission_id \
893 FROM app_permission_list_view \
894 WHERE app_id = %d AND \
895 permission_name=%Q AND \
896 permission_type_name=%Q LIMIT 1",
897 i_app_id, s_permission_name, s_permission_type_name);
898 if(ret != PC_OPERATION_SUCCESS) goto finish;
900 ret = sqlite3_step(p_stmt);
901 if(ret == SQLITE_ROW) {
902 // Phi, I already have this permission...
903 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
904 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
906 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
907 // Confucius say, No man can down-cast volatility.
908 C_LOGE("RDB: Down-casting volatility is forbidden.");
909 ret = PC_ERR_DB_PERM_FORBIDDEN;
913 if(i_is_volatile_old == i_is_volatile_new &&
914 i_is_enabled_old == i_is_enabled_new) {
915 // There is no change. Nice.
916 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
917 ret = PC_OPERATION_SUCCESS;
921 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
923 // Finalize statement
924 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
925 C_LOGE("RDB: Error during finalizing statement: %s",
926 sqlite3_errmsg(p_db));
929 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
930 ret = update_app_permission_internal(p_db,
936 } else if(ret == SQLITE_DONE) {
937 // Wow! A brand new permission! Omnomnom...
939 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
940 C_LOGE("RDB: Error during finalizing statement: %s",
941 sqlite3_errmsg(p_db));
944 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
945 ret = add_app_permission_internal(p_db,
948 s_permission_type_name,
952 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
953 ret = PC_ERR_DB_QUERY_STEP;
957 if(p_stmt && sqlite3_finalize(p_stmt) != SQLITE_OK)
958 C_LOGE("RDB: Error during finalizing statement: %s",
959 sqlite3_errmsg(p_db));
964 int revoke_app_permissions_internal(sqlite3 *p_db,
965 const char *const s_app_label_name)
967 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
969 int ret = PC_ERR_DB_OPERATION;
970 sqlite3_stmt *p_stmt = NULL;
972 ret = prepare_stmt(p_db, &p_stmt,
973 "DELETE FROM app_permission_view \
974 WHERE app_permission_view.app_name=%Q;",
977 if(ret != PC_OPERATION_SUCCESS) goto finish;
979 ret = step_and_convert_returned_value(p_stmt);
981 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
982 C_LOGE("RDB: Error during finalizing statement: %s",
983 sqlite3_errmsg(p_db));
988 int reset_app_permissions_internal(sqlite3 *p_db,
989 const char *const s_app_label_name)
991 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
993 int ret = PC_ERR_DB_OPERATION;
994 sqlite3_stmt *p_stmt = NULL;
996 ret = prepare_stmt(p_db, &p_stmt,
997 "DELETE FROM app_permission_volatile_view \
998 WHERE app_permission_volatile_view.app_name=%Q;",
1001 if(ret != PC_OPERATION_SUCCESS) goto finish;
1003 ret = step_and_convert_returned_value(p_stmt);
1005 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
1006 C_LOGE("RDB: Error during finalizing statement: %s",
1007 sqlite3_errmsg(p_db));
1011 int update_rules_in_db(sqlite3 *p_db)
1015 if(sqlite3_exec(p_db,
1017 -- clean temporary tables\n \
1018 DELETE FROM all_smack_binary_rules_modified; \
1019 DELETE FROM current_smack_rule_modified; \
1020 DELETE FROM history_smack_rule_modified; \
1022 -- gather possibly modified rules\n \
1023 INSERT INTO all_smack_binary_rules_modified \
1024 SELECT subject, object, access, is_volatile \
1025 FROM all_smack_binary_rules_view \
1026 WHERE subject IN modified_label; \
1028 INSERT INTO all_smack_binary_rules_modified \
1029 SELECT subject, object, access, is_volatile \
1030 FROM all_smack_binary_rules_view \
1031 WHERE object IN modified_label AND subject NOT IN modified_label; \
1033 -- prepare aggregated rules for diff algorithm\n \
1034 INSERT INTO current_smack_rule_modified \
1035 SELECT subject, object, bitwise_or(access) \
1036 FROM all_smack_binary_rules_modified \
1037 GROUP BY subject, object \
1038 ORDER BY subject, object ASC; \
1040 INSERT INTO history_smack_rule_modified \
1041 SELECT subject, object, bitwise_or(access) \
1042 FROM all_smack_binary_rules \
1043 WHERE subject IN modified_label OR object IN modified_label \
1044 GROUP BY subject, object \
1045 ORDER BY subject, object ASC; \
1047 -- apply changes to all_smack_binary_rules\n \
1048 DELETE FROM all_smack_binary_rules \
1049 WHERE subject IN modified_label OR \
1050 object IN modified_label; \
1052 INSERT INTO all_smack_binary_rules \
1053 SELECT subject, object, access, is_volatile \
1054 FROM all_smack_binary_rules_modified; \
1057 DELETE FROM modified_label; \
1059 0, 0, 0) != SQLITE_OK) {
1060 C_LOGE("RDB: Error during updating rules: %s",
1061 sqlite3_errmsg(p_db));
1062 return PC_ERR_DB_OPERATION;
1064 return PC_OPERATION_SUCCESS;
1067 int update_smack_rules(sqlite3 *p_db)
1071 int ret = PC_OPERATION_SUCCESS;
1072 sqlite3_stmt *p_stmt = NULL;
1073 const unsigned char *s_subject = NULL;
1074 const unsigned char *s_object = NULL;
1075 const unsigned char *s_access_add = NULL;
1076 const unsigned char *s_access_del = NULL;
1077 struct smack_accesses *smack = NULL;
1079 if(smack_accesses_new(&smack)) {
1080 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1081 ret = PC_ERR_MEM_OPERATION;
1085 ret = prepare_stmt(p_db, &p_stmt,
1086 "SELECT * from modified_smack_rules;");
1087 if(ret != PC_OPERATION_SUCCESS) goto finish;
1089 while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1090 s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1091 s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1092 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1093 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1095 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1096 s_subject, s_object, s_access_add, s_access_del);
1098 if(smack_accesses_add_modify(smack,
1099 (const char *) s_subject,
1100 (const char *) s_object,
1101 (const char *) s_access_add,
1102 (const char *) s_access_del)) {
1103 C_LOGE("RDB: Error during updating smack rules: %s",
1104 sqlite3_errmsg(p_db));
1105 ret = PC_ERR_INVALID_OPERATION;
1109 if(ret == SQLITE_DONE) {
1110 ret = PC_OPERATION_SUCCESS;
1112 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1113 ret, sqlite3_errmsg(p_db));
1114 ret = PC_ERR_DB_OPERATION;
1117 if(smack_accesses_apply(smack)) {
1118 C_LOGE("RDB: Error in smack_accesses_apply");
1119 ret = PC_ERR_INVALID_OPERATION;
1123 if(sqlite3_finalize(p_stmt) != SQLITE_OK)
1124 C_LOGE("RDB: Error during finalizing statement: %s",
1125 sqlite3_errmsg(p_db));
1127 smack_accesses_free(smack);