Implement the basics of a security system for objects.
authorcoderain <coderain@sdf.org>
Wed, 28 Jun 2017 17:50:14 +0000 (19:50 +0200)
committercoderain <coderain@sdf.org>
Wed, 28 Jun 2017 17:50:14 +0000 (19:50 +0200)
kernel/include/object.h
kernel/include/process.h
kernel/include/user.h
kernel/src/filesystem.c
kernel/src/memory.c
kernel/src/object.c
kernel/src/pipe.c
kernel/src/process.c
kernel/src/sync.c
kernel/src/thread.c

index 0bf68f8254f5890dfae8a711da949f23f3615952..fb2cf1128843869c5ba882676c0392682b5bab41 100644 (file)
@@ -26,6 +26,7 @@
 #define INVALID_HANDLE (handle_t)-1
 
 typedef dword_t handle_t;
+typedef dword_t access_flags_t;
 
 typedef enum
 {
@@ -47,6 +48,19 @@ typedef enum
     HANDLE_INFO_TYPE,
 } handle_info_type_t;
 
+typedef enum
+{
+    ACCESS_DEFAULT_ALLOW = 0,
+    ACCESS_DEFAULT_DENY,
+} access_control_policy_t;
+
+typedef struct
+{
+    list_entry_t list;
+    dword_t uid;
+    access_flags_t access_mask;
+} access_control_entry_t;
+
 typedef struct
 {
     list_entry_t by_name_list;
@@ -54,6 +68,8 @@ typedef struct
     char *name;
     qword_t ref_count, open_count;
     object_type_t type;
+    access_control_policy_t acp;
+    list_entry_t acl;
 } object_t;
 
 typedef void (*object_cleanup_proc_t)(object_t *obj);
@@ -63,8 +79,8 @@ void reference(object_t *object);
 void dereference(object_t *object);
 bool_t reference_by_name(const char *name, object_type_t type, object_t **object);
 bool_t reference_by_handle(handle_t handle, object_type_t type, object_t **object);
-dword_t open_object(object_t *obj, handle_t *handle);
-dword_t open_object_by_name(const char *name, object_type_t type, handle_t *handle);
+dword_t open_object(object_t *obj, access_flags_t access_flags, handle_t *handle);
+dword_t open_object_by_name(const char *name, object_type_t type, access_flags_t access_flags, handle_t *handle);
 void close_object_internal(object_t *obj);
 dword_t close_object(handle_t handle);
 dword_t query_handle(handle_t handle, handle_info_type_t type, void *buffer, size_t size);
index ce26214855f5c601576995a5dd6353a8565bdeb3..29e3ea63593f60acab82c808999634255204efb0 100644 (file)
@@ -32,7 +32,7 @@
 #define MAX_PROCESSES 2097152
 #define PROCESS_POOL_ADDRESS NULL
 #define PROCESS_POOL_SIZE 524288
-#define STARTUP_HANDLE_TABLE_SIZE (256 * sizeof(void*))
+#define STARTUP_HANDLE_TABLE_SIZE (256 * sizeof(handle_info_t))
 
 #define CLONE_MAGIC 0x79706F43
 
@@ -57,6 +57,12 @@ typedef enum
 typedef struct thread thread_t;
 #endif
 
+typedef struct
+{
+    object_t *obj;
+    access_flags_t access_flags;
+} handle_info_t;
+
 struct process
 {
     object_t header;
@@ -70,7 +76,7 @@ struct process
     clock_time_t end_time;
     list_entry_t threads;
     resource_t thread_list_res;
-    object_t **handle_table;
+    handle_info_t *handle_table;
     dword_t handle_count, handle_table_size;
     resource_t handle_table_res;
     user_t *original_user, *current_user;
index 49aefa8ae17b782830762d9fb1214c3a44528997..bc7451190e6940d47c176db2d7fd876b71d95358 100644 (file)
@@ -58,9 +58,9 @@
 #define PRIVILEGE_UNNAMED29        (1ULL << 29)
 #define PRIVILEGE_UNNAMED30        (1ULL << 30)
 #define PRIVILEGE_SET_TIME         (1ULL << 31)
-#define PRIVILEGE_CHARACTER_DEVICE (1ULL << 32)
-#define PRIVILEGE_BLOCK_DEVICE     (1ULL << 33)
-#define PRIVILEGE_UNNAMED34        (1ULL << 34)
+#define PRIVILEGE_ACCESS_ALL       (1ULL << 32)
+#define PRIVILEGE_CHARACTER_DEVICE (1ULL << 33)
+#define PRIVILEGE_BLOCK_DEVICE     (1ULL << 34)
 #define PRIVILEGE_UNNAMED35        (1ULL << 35)
 #define PRIVILEGE_UNNAMED36        (1ULL << 36)
 #define PRIVILEGE_UNNAMED37        (1ULL << 37)
index 706d7952f5754f6344d7c089bc896bbc4e8f8c6d..1925b0bcb1d1e7830c368e97cc0162fd8ed46925 100644 (file)
@@ -368,7 +368,7 @@ dword_t open_file(const char *path, handle_t *handle, dword_t mode, dword_t attr
     ret = open_file_internal(safe_path, &file, mode, attributes);
     if (ret != ERR_SUCCESS) goto cleanup;
 
-    ret = open_object(&file->header, &safe_handle);
+    ret = open_object(&file->header, 0, &safe_handle);
     if (ret != ERR_SUCCESS)
     {
         dereference(&file->header);
index 10f7331fb4d478dd5affdd130073a34c0ba259b1..e40ec7bc8e21463c05e7de353b009be2ccb1af95 100644 (file)
@@ -1752,7 +1752,7 @@ dword_t create_memory_section(const char *name, handle_t file, size_t max_size,
         goto cleanup;
     }
 
-    ret = open_object(&section->header, &safe_handle);
+    ret = open_object(&section->header, 0, &safe_handle);
     if (ret == ERR_SUCCESS)
     {
         EH_TRY
@@ -1795,7 +1795,7 @@ dword_t open_memory_section(const char *name, handle_t *handle)
     }
     else safe_name = (char*)name;
 
-    dword_t ret = open_object_by_name(safe_name, OBJECT_MEMORY, &safe_handle);
+    dword_t ret = open_object_by_name(safe_name, OBJECT_MEMORY, 0, &safe_handle);
 
     EH_TRY
     {
index 3971595df60517b18108ffc70d4a4a814b3fd522..01bd20961b18889ebbe56dd1b35ad9ae95318a06 100644 (file)
@@ -49,29 +49,30 @@ static inline byte_t get_name_hash(const char *name)
     return sum;
 }
 
-static handle_t insert_object(object_t *obj)
+static handle_t insert_object(object_t *obj, access_flags_t access_flags)
 {
     handle_t i;
     process_t *proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
 
     acquire_resource_exclusive(&proc->handle_table_res);
 
-    for (i = 0; i < proc->handle_table_size; i++) if (!proc->handle_table[i])
+    for (i = 0; i < proc->handle_table_size; i++) if (!proc->handle_table[i].obj)
     {
-        proc->handle_table[i] = obj;
+        proc->handle_table[i].obj = obj;
+        proc->handle_table[i].access_flags = access_flags;
         proc->handle_count++;
         goto cleanup;
     }
 
-    object_t **expanded_table = (object_t**)heap_realloc(&evictable_heap, proc->handle_table, proc->handle_table_size * 2);
+    handle_info_t *expanded_table = (handle_info_t*)heap_realloc(&evictable_heap, proc->handle_table, proc->handle_table_size * 2);
     if (expanded_table == NULL)
     {
         i = INVALID_HANDLE;
         goto cleanup;
     }
 
-    expanded_table[proc->handle_table_size] = obj;
-    for (i = proc->handle_table_size + 1; i < proc->handle_table_size * 2; i++) expanded_table[i] = NULL;
+    expanded_table[proc->handle_table_size].obj = obj;
+    for (i = proc->handle_table_size + 1; i < proc->handle_table_size * 2; i++) expanded_table[i].obj = NULL;
 
     proc->handle_table = expanded_table;
     i = proc->handle_table_size;
@@ -82,6 +83,22 @@ cleanup:
     return i;
 }
 
+static bool_t access_check(object_t *obj, access_flags_t access_flags)
+{
+    if (check_privileges(PRIVILEGE_ACCESS_ALL)) return TRUE;
+
+    list_entry_t *ptr;
+    dword_t uid = get_user_id();
+
+    for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
+    {
+        access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, list);
+        if (ace->uid == uid) return (access_flags == (access_flags & ace->access_mask));
+    }
+
+    return (obj->acp == ACCESS_DEFAULT_ALLOW) ? TRUE : FALSE;
+}
+
 void reference(object_t *object)
 {
     acquire_lock(&obj_lock);
@@ -118,7 +135,7 @@ bool_t reference_by_handle(handle_t handle, object_type_t type, object_t **objec
     acquire_lock(&obj_lock);
     acquire_resource_shared(&proc->handle_table_res);
 
-    *object = proc->handle_table[handle];
+    *object = proc->handle_table[handle].obj;
     if (*object != NULL && (*object)->type == type)
     {
         (*object)->ref_count++;
@@ -180,12 +197,18 @@ dword_t create_object(object_t *obj)
     return ERR_SUCCESS;
 }
 
-dword_t open_object(object_t *obj, handle_t *handle)
+dword_t open_object(object_t *obj, access_flags_t access_flags, handle_t *handle)
 {
     dword_t ret = ERR_SUCCESS;
     acquire_lock(&obj_lock);
 
-    handle_t new_handle = insert_object(obj);
+    if (!access_check(obj, access_flags))
+    {
+        ret = ERR_FORBIDDEN;
+        goto done;
+    }
+
+    handle_t new_handle = insert_object(obj, access_flags);
     if (new_handle == INVALID_HANDLE)
     {
         ret = ERR_NOMEMORY;
@@ -201,7 +224,7 @@ done:
     return ret;
 }
 
-dword_t open_object_by_name(const char *name, object_type_t type, handle_t *handle)
+dword_t open_object_by_name(const char *name, object_type_t type, access_flags_t access_flags, handle_t *handle)
 {
     dword_t ret = ERR_SUCCESS;
     object_t *obj;
@@ -209,7 +232,13 @@ dword_t open_object_by_name(const char *name, object_type_t type, handle_t *hand
     if (!reference_by_name(name, type, &obj)) return ERR_NOTFOUND;
     acquire_lock(&obj_lock);
 
-    handle_t new_handle = insert_object(obj);
+    if (!access_check(obj, access_flags))
+    {
+        ret = ERR_FORBIDDEN;
+        goto done;
+    }
+
+    handle_t new_handle = insert_object(obj, access_flags);
     if (new_handle == INVALID_HANDLE)
     {
         ret = ERR_NOMEMORY;
@@ -263,13 +292,13 @@ dword_t close_object(handle_t handle)
         return ERR_NOTFOUND;
     }
 
-    object_t *obj = proc->handle_table[handle];
+    object_t *obj = proc->handle_table[handle].obj;
 
     if (obj != NULL)
     {
         close_object_internal(obj);
 
-        proc->handle_table[handle] = NULL;
+        proc->handle_table[handle].obj = NULL;
         proc->handle_count--;
     }
     else
@@ -306,7 +335,7 @@ dword_t query_handle(handle_t handle, handle_info_type_t type, void *buffer, siz
     reference(&proc->header);
     acquire_resource_exclusive(&proc->handle_table_res);
 
-    object_t *obj = proc->handle_table[handle];
+    object_t *obj = proc->handle_table[handle].obj;
     if (obj == NULL)
     {
         ret = ERR_NOTFOUND;
@@ -374,7 +403,8 @@ dword_t duplicate_handle(handle_t source_process, handle_t handle, handle_t dest
         return ERR_INVALID;
     }
 
-    object_t *obj = proc->handle_table[handle];
+    object_t *obj = proc->handle_table[handle].obj;
+    access_flags_t access_flags = proc->handle_table[handle].access_flags;
     if (obj == NULL)
     {
         release_resource(&proc->handle_table_res);
@@ -402,7 +432,7 @@ dword_t duplicate_handle(handle_t source_process, handle_t handle, handle_t dest
     }
 
     process_t *old_process = switch_process(proc);
-    dword_t ret = open_object(obj, &safe_handle);
+    dword_t ret = open_object(obj, access_flags, &safe_handle);
     switch_process(old_process);
 
     dereference(&proc->header);
index e4c33db7eadaac8571b7426ff4d171cc036f0f7f..879b012a472c529366feeff2f96e6a053a232903 100644 (file)
@@ -69,7 +69,7 @@ dword_t create_pipe(const char *name, handle_t *handle)
         goto cleanup;
     }
 
-    ret = open_object(&pipe->header, &safe_handle);
+    ret = open_object(&pipe->header, 0, &safe_handle);
     if (ret != ERR_SUCCESS)
     {
         dereference(&pipe->header);
@@ -115,7 +115,7 @@ dword_t open_pipe(const char *name, handle_t *handle)
         safe_name = (char*)name;
     }
 
-    dword_t ret = open_object_by_name(safe_name, OBJECT_PIPE, &safe_handle);
+    dword_t ret = open_object_by_name(safe_name, OBJECT_PIPE, 0, &safe_handle);
     if (ret != ERR_SUCCESS) goto cleanup;
 
     EH_TRY
index 1af7330904e04d7cc20fbac673fc80930bc4eeff..5c0933d3f02793634a9084ed61054504bd209718 100644 (file)
@@ -70,11 +70,11 @@ void destroy_process(process_t *proc)
 
     for (i = 0; i < proc->handle_table_size / sizeof(object_t*); i++)
     {
-        if (proc->handle_table[i])
+        if (proc->handle_table[i].obj)
         {
-            close_object_internal(proc->handle_table[i]);
+            close_object_internal(proc->handle_table[i].obj);
 
-            proc->handle_table[i] = NULL;
+            proc->handle_table[i].obj = NULL;
             proc->handle_count--;
         }
     }
@@ -124,7 +124,7 @@ dword_t open_process(dword_t pid, handle_t *handle)
     {
         if (proc->current_user->uid == get_user_id() || check_privileges(PRIVILEGE_PROCESS_CONTROL))
         {
-            ret = open_object(&proc->header, handle);
+            ret = open_object(&proc->header, 0, handle);
         }
         else
         {
@@ -266,7 +266,7 @@ dword_t create_process(const char *path, dword_t flags, process_params_t *parame
         dword_t i;
         acquire_resource_shared(&current->handle_table_res);
 
-        proc->handle_table = (object_t**)malloc(current->handle_table_size);
+        proc->handle_table = (handle_info_t*)malloc(current->handle_table_size);
         memset(proc->handle_table, 0, current->handle_table_size);
         proc->handle_table_size = current->handle_table_size;
         proc->handle_count = current->handle_count;
@@ -274,10 +274,10 @@ dword_t create_process(const char *path, dword_t flags, process_params_t *parame
 
         for (i = 0; i < current->handle_table_size; i++)
         {
-            if (current->handle_table[i])
+            if (current->handle_table[i].obj)
             {
-                reference(current->handle_table[i]);
-                current->handle_table[i]->open_count++;
+                reference(current->handle_table[i].obj);
+                current->handle_table[i].obj->open_count++;
                 proc->handle_table[i] = current->handle_table[i];
             }
         }
@@ -286,7 +286,7 @@ dword_t create_process(const char *path, dword_t flags, process_params_t *parame
     }
     else
     {
-        proc->handle_table = (object_t**)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
+        proc->handle_table = (handle_info_t*)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
         memset(proc->handle_table, 0, STARTUP_HANDLE_TABLE_SIZE);
         proc->handle_table_size = STARTUP_HANDLE_TABLE_SIZE;
         proc->handle_count = 0;
@@ -314,7 +314,7 @@ dword_t create_process(const char *path, dword_t flags, process_params_t *parame
     thread_state_t initial_state;
     memset(&initial_state, 0, sizeof(initial_state));
 
-    ret = open_object(&proc->header, &safe_process_handle);
+    ret = open_object(&proc->header, 0, &safe_process_handle);
     if (ret != ERR_SUCCESS) goto cleanup;
 
     if (file != INVALID_HANDLE)
@@ -357,7 +357,7 @@ dword_t create_process(const char *path, dword_t flags, process_params_t *parame
             goto cleanup;
         }
 
-        ret = open_object(&thread->header, &safe_thread_handle);
+        ret = open_object(&thread->header, 0, &safe_thread_handle);
         if (ret != ERR_SUCCESS)
         {
             dereference(&thread->header);
@@ -595,7 +595,7 @@ dword_t query_process(handle_t handle, process_info_t info_type, void *buffer, d
 
                 for (i = 0; i < proc->handle_table_size && j < (size / sizeof(dword_t)); i++)
                 {
-                    if (proc->handle_table[i]) ((dword_t*)safe_buffer)[j++] = i;
+                    if (proc->handle_table[i].obj) ((dword_t*)safe_buffer)[j++] = i;
                 }
 
                 if (i != proc->handle_table_size) ret = ERR_SMALLBUF;
@@ -760,7 +760,7 @@ void process_init(char *root_directory)
     list_init(&kernel_process->threads);
     kernel_process->thread_list_res = 0;
 
-    kernel_process->handle_table = (object_t**)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
+    kernel_process->handle_table = (handle_info_t*)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
     kernel_process->handle_table_size = STARTUP_HANDLE_TABLE_SIZE;
     kernel_process->handle_count = 0;
     kernel_process->handle_table_res = 0;
index aab85a5e7a542f11bc02a3d9664c400eae0b8743..d151cdbe295598d4637393b45ecf6e8ec3c96d5c 100644 (file)
@@ -88,6 +88,7 @@ void init_semaphore(semaphore_t *semaphore, dword_t init_count, dword_t max_coun
 
 dword_t create_semaphore(const char *name, dword_t init_count, dword_t max_count, handle_t *handle)
 {
+    handle_t safe_handle;
     char *safe_name = NULL;
     if ((max_count == 0) || (init_count > max_count)) return ERR_INVALID;
 
@@ -108,7 +109,7 @@ dword_t create_semaphore(const char *name, dword_t init_count, dword_t max_count
     dword_t ret = create_object(&semaphore->header);
     if (ret == ERR_SUCCESS)
     {
-        ret = open_object(&semaphore->header, handle);
+        ret = open_object(&semaphore->header, 0, &safe_handle);
         dereference(&semaphore->header);
     }
 
@@ -118,7 +119,11 @@ dword_t create_semaphore(const char *name, dword_t init_count, dword_t max_count
         free(semaphore);
     }
 
-    free(safe_name);
+    EH_TRY *handle = safe_handle;
+    EH_CATCH ret = ERR_BADPTR;
+    EH_DONE;
+
+    if (get_previous_mode() == USER_MODE) free(safe_name);
     return ret;
 }
 
@@ -143,7 +148,7 @@ dword_t open_semaphore(const char *name, handle_t *handle)
     }
     else safe_name = (char*)name;
 
-    dword_t ret = open_object_by_name(safe_name, OBJECT_SEMAPHORE, &safe_handle);
+    dword_t ret = open_object_by_name(safe_name, OBJECT_SEMAPHORE, 0, &safe_handle);
 
     EH_TRY *handle = safe_handle;
     EH_CATCH
index 47c77dbc2d3d4418c8936116c7d83640fbe7e6f6..7f17d3b317ab3f00ad103c2a0c540042ef83309e 100644 (file)
@@ -461,7 +461,7 @@ dword_t create_thread(handle_t process, thread_state_t *initial_state, dword_t f
     }
 
     handle_t thread_handle;
-    ret = open_object(&thread->header, &thread_handle);
+    ret = open_object(&thread->header, 0, &thread_handle);
 
     EH_TRY *new_thread = thread_handle;
     EH_CATCH close_object(thread_handle);
@@ -504,7 +504,7 @@ dword_t open_thread(dword_t tid, handle_t *handle)
     }
 
 found:
-    if (thread != NULL) ret = open_object(&thread->header, handle);
+    if (thread != NULL) ret = open_object(&thread->header, 0, handle);
     else ret = ERR_NOTFOUND;
 
     leave_critical(&critical);