Users are managed by the object manager now. Fix enum_objects_by_type.
authorcoderain <coderain@sdf.org>
Thu, 16 Feb 2017 15:46:44 +0000 (16:46 +0100)
committercoderain <coderain@sdf.org>
Thu, 16 Feb 2017 15:46:44 +0000 (16:46 +0100)
kernel/include/object.h
kernel/include/user.h
kernel/src/object.c
kernel/src/user.c

index 325f00d3676d8fe143b9956c83651825ecf23665..0bf68f8254f5890dfae8a711da949f23f3615952 100644 (file)
@@ -36,6 +36,7 @@ typedef enum
     OBJECT_THREAD,
     OBJECT_MEMORY,
     OBJECT_SEMAPHORE,
+    OBJECT_USER,
 
     OBJECT_TYPE_MAX
 } object_type_t;
index e534d3af356af49e3591a7d9076060102beae321..49aefa8ae17b782830762d9fb1214c3a44528997 100644 (file)
@@ -21,7 +21,7 @@
 #define _USER_H_
 
 #include <common.h>
-#include <list.h>
+#include <object.h>
 
 #define MAX_USERNAME_LENGTH 32
 #define LOGIN_ATTEMPT_TIMEOUT 3000
@@ -95,7 +95,7 @@
 
 typedef struct
 {
-    list_entry_t list;
+    object_t header;
     dword_t uid;
     qword_t privileges;
     char name[MAX_USERNAME_LENGTH];
index ce8c0091c0f4990d8aac18b47ef0be53626d5fee..3971595df60517b18108ffc70d4a4a814b3fd522 100644 (file)
@@ -29,7 +29,7 @@ extern void pipe_cleanup(object_t*);
 static lock_t obj_lock = 0;
 static DECLARE_LIST(anonymous_objects);
 static DECLARE_LIST_ARRAY(named_objects, 256);
-static DECLARE_LIST_ARRAY(objects_by_type, 7);
+static DECLARE_LIST_ARRAY(objects_by_type, 8);
 static object_cleanup_proc_t cleanup_procedures[OBJECT_TYPE_MAX] =
 {
     file_cleanup,
@@ -39,6 +39,7 @@ static object_cleanup_proc_t cleanup_procedures[OBJECT_TYPE_MAX] =
     NULL,
     NULL,
     NULL,
+    NULL,
 };
 
 static inline byte_t get_name_hash(const char *name)
@@ -422,23 +423,29 @@ dword_t duplicate_handle(handle_t source_process, handle_t handle, handle_t dest
 
 dword_t enum_objects_by_type(object_type_t type, object_t **object)
 {
+    dword_t ret = ERR_SUCCESS;
     list_entry_t *ptr;
+    object_t *previous = *object;
+
     acquire_lock(&obj_lock);
 
-    if (*object == NULL) ptr = objects_by_type[type].next;
-    else ptr = (*object)->by_type_list.next;
+    if (previous == NULL) ptr = objects_by_type[type].next;
+    else ptr = previous->by_type_list.next;
 
-    if (ptr == &objects_by_type[type])
+    if (ptr != &objects_by_type[type])
     {
-        dereference(*object);
-        release_lock(&obj_lock);
-        return ERR_NOMORE;
+        *object = CONTAINER_OF(ptr, object_t, by_type_list);
+        ret = ERR_SUCCESS;
+    }
+    else
+    {
+        *object = NULL;
+        ret = ERR_NOMORE;
     }
-
-    dereference(*object);
-    *object = CONTAINER_OF(ptr, object_t, by_type_list);
-    reference(*object);
 
     release_lock(&obj_lock);
-    return ERR_SUCCESS;
+
+    if (*object) reference(*object);
+    if (previous) dereference(previous);
+    return ret;
 }
index c8c9d5f0a91aba501646b1a56551002b7e727258..cc40b48e9f53096bf589724d35795dd9f833b280 100644 (file)
 #include <heap.h>
 #include <timer.h>
 
-static DECLARE_LIST(users);
-static resource_t user_list_res;
-
-extern list_entry_t process_list;
-extern resource_t proc_list_res;
-
-static user_t *get_user(dword_t uid)
+static user_t *reference_user_by_id(dword_t uid)
 {
-    acquire_resource_shared(&user_list_res);
-    user_t *ptr = (user_t*)users.next;
+    user_t *user = NULL;
 
-    while (&ptr->list != &users)
+    while (enum_objects_by_type(OBJECT_USER, (object_t**)&user) == ERR_SUCCESS)
     {
-        if (ptr->uid == uid)
-        {
-            release_resource(&user_list_res);
-            return ptr;
-        }
-
-        ptr = (user_t*)ptr->list.next;
+        if (user->uid == uid) return user;
     }
 
-    release_resource(&user_list_res);
     return NULL;
 }
 
 static dword_t add_user(dword_t uid, const char *name, dword_t *password_hash, qword_t privileges)
 {
-    user_t *user = (user_t*)malloc(sizeof(user_t));
-    if (user == NULL) return ERR_NOMEMORY;
-
-    acquire_resource_shared(&user_list_res);
-    user_t *ptr = CONTAINER_OF(users.next, user_t, list);
+    user_t *user;
 
-    while (&ptr->list != &users)
+    if ((user = reference_user_by_id(uid)) != NULL)
     {
-        if (ptr->uid == uid || strcmp(ptr->name, name) == 0)
-        {
-            release_resource(&user_list_res);
-            return ERR_EXISTS;
-        }
+        dereference(&user->header);
+        return ERR_EXISTS;
+    }
 
-        ptr = (user_t*)ptr->list.next;
+    if (reference_by_name(name, OBJECT_USER, (object_t**)&user))
+    {
+        dereference(&user->header);
+        return ERR_EXISTS;
     }
 
-    release_resource(&user_list_res);
+    user = (user_t*)malloc(sizeof(user_t));
+    if (user == NULL) return ERR_NOMEMORY;
 
+    user->header.name = strdup(name);
+    user->header.type = OBJECT_USER;
     user->uid = uid;
-    strcpy(user->name, name);
     memcpy(user->password_hash, password_hash, sizeof(user->password_hash));
     user->privileges = privileges;
 
-    acquire_resource_exclusive(&user_list_res);
-    list_append(&users, &user->list);
-    release_resource(&user_list_res);
-
-    return ERR_SUCCESS;
+    return create_object(&user->header);
 }
 
 static void sha256_compute(byte_t *buffer, size_t size, dword_t *sum)
@@ -191,15 +172,18 @@ dword_t get_user_id()
 dword_t set_user_id(dword_t uid)
 {
     process_t *proc = get_current_process();
-    user_t *user = get_user(uid);
+    user_t *user = reference_user_by_id(uid);
     if (user == NULL) return ERR_NOTFOUND;
 
     if (get_previous_mode() == USER_MODE && !check_privileges(PRIVILEGE_CHANGE_UID))
     {
+        dereference(&user->header);
         return ERR_FORBIDDEN;
     }
 
+    if (proc->current_user) dereference(&proc->current_user->header);
     proc->current_user = user;
+
     return ERR_SUCCESS;
 }
 
@@ -209,6 +193,8 @@ dword_t revert_user()
 
     if (proc->original_user != proc->current_user)
     {
+        if (proc->current_user) dereference(&proc->current_user->header);
+        reference(&proc->original_user->header);
         proc->current_user = proc->original_user;
         return ERR_SUCCESS;
     }
@@ -266,10 +252,11 @@ dword_t delete_user(dword_t uid)
 
     ASSERT(ret == ERR_NOMORE);
 
-    acquire_resource_exclusive(&user_list_res);
-    user_t *user = get_user(uid);
-    list_remove(&user->list);
-    release_resource(&user_list_res);
+    user_t *user = reference_user_by_id(uid);
+    if (user == NULL) return ERR_NOTFOUND;
+
+    dereference(&user->header);
+    dereference(&user->header);
 
     return ERR_SUCCESS;
 }
@@ -278,7 +265,7 @@ dword_t logon_user(dword_t uid, const char *password)
 {
     dword_t ret;
     process_t *proc = get_current_process();
-    user_t *user = get_user(uid);
+    user_t *user = reference_user_by_id(uid);
     user_t *current_user = get_current_process()->current_user;
     char *safe_password;
 
@@ -313,6 +300,7 @@ dword_t logon_user(dword_t uid, const char *password)
 
     if (memcmp(hash_sum, user->password_hash, sizeof(hash_sum)) == 0)
     {
+        reference(&user->header);
         proc->current_user = user;
         ret = ERR_SUCCESS;
     }
@@ -323,6 +311,7 @@ dword_t logon_user(dword_t uid, const char *password)
     }
 
 cleanup:
+    dereference(&user->header);
     if (get_previous_mode() == USER_MODE) free(safe_password);
     return ret;
 }
@@ -332,15 +321,25 @@ dword_t query_user(dword_t uid, user_info_t info_type, void *buffer, dword_t siz
     dword_t ret = ERR_SUCCESS;
     void *safe_buffer;
 
-    user_t *user = get_user(uid);
+    user_t *user = reference_user_by_id(uid);
     if (user == NULL) return ERR_NOTFOUND;
 
     if (get_previous_mode() == USER_MODE)
     {
-        if (!check_usermode(buffer, size)) return ERR_BADPTR;
+        if (!check_usermode(buffer, size))
+        {
+            ret = ERR_BADPTR;
+            goto cleanup;
+        }
 
         safe_buffer = malloc(size);
-        if (safe_buffer == NULL) return ERR_NOMEMORY;
+
+        if (safe_buffer == NULL)
+        {
+            ret = ERR_NOMEMORY;
+            goto cleanup;
+        }
+
         memset(safe_buffer, 0, size);
     }
     else
@@ -373,6 +372,8 @@ dword_t query_user(dword_t uid, user_info_t info_type, void *buffer, dword_t siz
         EH_DONE;
     }
 
+cleanup:
+    dereference(&user->header);
     return ret;
 }
 
@@ -385,5 +386,8 @@ void user_init()
         KERNEL_CRASH("Failed to create root user!");
     }
 
-    kernel_process->original_user = kernel_process->current_user = get_user(0);
+    user_t *root = reference_user_by_id(0);
+    reference(&root->header);
+
+    kernel_process->original_user = kernel_process->current_user = root;
 }