Browse Source

[LibOS] Miscellaneous bugfixes, mostly found by the previous commit

The previous commit added some asserts on locks state, which unveiled
a bunch of bugs. This fixes all of them and a bit more found in the
process.
borysp 4 years ago
parent
commit
5c37c4d21a

+ 1 - 1
LibOS/shim/include/shim_fs.h

@@ -324,7 +324,7 @@ extern struct shim_lock dcache_lock;
 /* Checks permission (specified by mask) of a dentry. If force is not set, permission is considered
  * granted on invalid dentries.
  * Assumes that caller has acquired dcache_lock. */
-int permission(struct shim_dentry* dent, mode_t mask);
+int __permission(struct shim_dentry* dent, mode_t mask);
 
 /* This function looks up a single dentry based on its parent dentry pointer and the name. `namelen`
  * is the length of char* name. The dentry is returned in pointer *new.

+ 6 - 3
LibOS/shim/include/shim_internal.h

@@ -608,14 +608,17 @@ extern struct shim_lock __master_lock;
 # define MASTER_UNLOCK() do { unlock(&__master_lock); } while (0)
 #endif
 
-static inline void create_lock_runtime(struct shim_lock* l)
-{
+static inline bool create_lock_runtime(struct shim_lock* l) {
+    bool ret = true;
+
     if (!lock_created(l)) {
         MASTER_LOCK();
         if (!lock_created(l))
-            create_lock(l);
+            ret = create_lock(l);
         MASTER_UNLOCK();
     }
+
+    return ret;
 }
 
 static inline void create_event (AEVENTTYPE * e)

+ 22 - 7
LibOS/shim/src/bookkeep/shim_handle.c

@@ -130,10 +130,13 @@ static int __set_new_fd_handle(struct shim_fd_handle** fdhdl, FDTYPE fd, struct
 static struct shim_handle_map* __enlarge_handle_map(struct shim_handle_map* map, FDTYPE size);
 
 int init_handle(void) {
-    create_lock(&handle_mgr_lock);
+    if (!create_lock(&handle_mgr_lock)) {
+        return -ENOMEM;
+    }
     handle_mgr = create_mem_mgr(init_align_up(HANDLE_MGR_ALLOC));
-    if (!handle_mgr)
+    if (!handle_mgr) {
         return -ENOMEM;
+    }
     return 0;
 }
 
@@ -278,7 +281,10 @@ struct shim_handle* get_new_handle(void) {
 
     memset(new_handle, 0, sizeof(struct shim_handle));
     REF_SET(new_handle->ref_count, 1);
-    create_lock(&new_handle->lock);
+    if (!create_lock(&new_handle->lock)) {
+        free_mem_obj_to_mgr(handle_mgr, new_handle);
+        return NULL;
+    }
     new_handle->owner = cur_process.vmid;
     INIT_LISTP(&new_handle->epolls);
     return new_handle;
@@ -555,7 +561,10 @@ static struct shim_handle_map* get_new_handle_map(FDTYPE size) {
 
     handle_map->fd_top  = FD_NULL;
     handle_map->fd_size = size;
-    create_lock(&handle_map->lock);
+    if (!create_lock(&handle_map->lock)) {
+        free(handle_map);
+        return NULL;
+    }
 
     return handle_map;
 }
@@ -781,13 +790,17 @@ BEGIN_RS_FUNC(handle) {
     CP_REBASE(hdl->dentry);
     CP_REBASE(hdl->epolls);
 
-    create_lock(&hdl->lock);
+    if (!create_lock(&hdl->lock)) {
+        return -ENOMEM;
+    }
 
     if (!hdl->fs) {
         assert(hdl->fs_type);
         search_builtin_fs(hdl->fs_type, &hdl->fs);
-        if (!hdl->fs)
+        if (!hdl->fs) {
+            destroy_lock(&hdl->lock);
             return -EINVAL;
+        }
     }
 
     if (hdl->fs && hdl->fs->fs_ops && hdl->fs->fs_ops->checkin)
@@ -874,7 +887,9 @@ BEGIN_RS_FUNC(handle_map) {
 
     DEBUG_RS("size=%d,top=%d", handle_map->fd_size, handle_map->fd_top);
 
-    create_lock(&handle_map->lock);
+    if (!create_lock(&handle_map->lock)) {
+        return -ENOMEM;
+    }
     lock(&handle_map->lock);
 
     if (handle_map->fd_top != FD_NULL)

+ 52 - 10
LibOS/shim/src/bookkeep/shim_thread.c

@@ -49,7 +49,9 @@ PAL_HANDLE thread_start_event = NULL;
 
 int init_thread (void)
 {
-    create_lock(&thread_list_lock);
+    if (!create_lock(&thread_list_lock)) {
+        return -ENOMEM;
+    }
 
     struct shim_thread * cur_thread = get_cur_thread();
     if (cur_thread)
@@ -226,14 +228,39 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
         }
     }
 
+    thread->vmid = cur_process.vmid;
     thread->signal_logs = malloc(sizeof(struct shim_signal_log) *
                                  NUM_SIGS);
-    thread->vmid = cur_process.vmid;
-    create_lock(&thread->lock);
+    if (!thread->signal_logs) {
+        goto out_error;
+    }
+    if (!create_lock(&thread->lock)) {
+        goto out_error;
+    }
     thread->scheduler_event = DkNotificationEventCreate(PAL_TRUE);
     thread->exit_event = DkNotificationEventCreate(PAL_FALSE);
     thread->child_exit_event = DkNotificationEventCreate(PAL_FALSE);
     return thread;
+
+out_error:
+    free(thread->signal_logs);
+    if (thread->handle_map) {
+        put_handle_map(thread->handle_map);
+    }
+    if (thread->root) {
+        put_dentry(thread->root);
+    }
+    if (thread->cwd) {
+        put_dentry(thread->cwd);
+    }
+    for (int i = 0; i < NUM_SIGS; i++) {
+        free(thread->signal_handles[i].action);
+    }
+    if (thread->exec) {
+        put_handle(thread->exec);
+    }
+    free(thread);
+    return NULL;
 }
 
 struct shim_thread * get_new_internal_thread (void)
@@ -248,7 +275,10 @@ struct shim_thread * get_new_internal_thread (void)
     thread->vmid  = cur_process.vmid;
     thread->tid   = new_tid;
     thread->in_vm = thread->is_alive = true;
-    create_lock(&thread->lock);
+    if (!create_lock(&thread->lock)) {
+        free(thread);
+        return NULL;
+    }
     thread->exit_event = DkNotificationEventCreate(PAL_FALSE);
     return thread;
 }
@@ -289,7 +319,10 @@ struct shim_simple_thread * get_new_simple_thread (void)
 
     INIT_LIST_HEAD(thread, list);
 
-    create_lock(&thread->lock);
+    if (!create_lock(&thread->lock)) {
+        free(thread);
+        return NULL;
+    }
     thread->exit_event = DkNotificationEventCreate(PAL_FALSE);
 
     return thread;
@@ -333,7 +366,9 @@ void put_thread (struct shim_thread * thread)
             DkObjectClose(thread->exit_event);
         if (thread->child_exit_event)
             DkObjectClose(thread->child_exit_event);
-        destroy_lock(&thread->lock);
+        if (lock_created(&thread->lock)) {
+            destroy_lock(&thread->lock);
+        }
 
         free(thread->signal_logs);
         free(thread);
@@ -345,8 +380,7 @@ void get_simple_thread (struct shim_simple_thread * thread)
     REF_INC(thread->ref_count);
 }
 
-void put_simple_thread (struct shim_simple_thread * thread)
-{
+static void __put_simple_thread(struct shim_simple_thread* thread) {
     assert(locked(&thread_list_lock));
 
     int ref_count = REF_DEC(thread->ref_count);
@@ -361,6 +395,12 @@ void put_simple_thread (struct shim_simple_thread * thread)
     }
 }
 
+void put_simple_thread(struct shim_simple_thread* thread) {
+    lock(&thread_list_lock);
+    __put_simple_thread(thread);
+    unlock(&thread_list_lock);
+}
+
 void set_as_child (struct shim_thread * parent,
                    struct shim_thread * child)
 {
@@ -455,8 +495,8 @@ void del_simple_thread (struct shim_simple_thread * thread)
 
     lock(&thread_list_lock);
     LISTP_DEL_INIT(thread, &simple_thread_list, list);
+    __put_simple_thread(thread);
     unlock(&thread_list_lock);
-    put_simple_thread(thread);
 }
 
 static int _check_last_thread(struct shim_thread* self) {
@@ -704,7 +744,9 @@ BEGIN_RS_FUNC(thread)
     CP_REBASE(thread->cwd);
     CP_REBASE(thread->signal_handles);
 
-    create_lock(&thread->lock);
+    if (!create_lock(&thread->lock)) {
+        return -ENOMEM;
+    }
     thread->scheduler_event = DkNotificationEventCreate(PAL_TRUE);
     thread->exit_event = DkNotificationEventCreate(PAL_FALSE);
     thread->child_exit_event = DkNotificationEventCreate(PAL_FALSE);

+ 21 - 13
LibOS/shim/src/bookkeep/shim_vma.c

@@ -292,9 +292,14 @@ __bkeep_preloaded (void * start, void * end, int prot, int flags,
     return __bkeep_mmap(prev, start, end, prot, flags, NULL, 0, comment);
 }
 
-int init_vma (void)
-{
-    int ret;
+int init_vma(void) {
+    int ret = 0;
+
+    if (!create_lock(&vma_list_lock)) {
+        return -ENOMEM;
+    }
+
+    lock(&vma_list_lock);
 
     for (int i = 0 ; i < RESERVED_VMAS ; i++)
         reserved_vmas[i] = &early_vmas[i];
@@ -307,7 +312,7 @@ int init_vma (void)
                                 PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|VMA_UNMAPPED,
                                 "reserved");
         if (ret < 0)
-            return ret;
+            goto out;
     }
 
     ret = __bkeep_preloaded(PAL_CB(executable_range.start),
@@ -315,14 +320,14 @@ int init_vma (void)
                             PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|VMA_UNMAPPED,
                             "exec");
     if (ret < 0)
-        return ret;
+        goto out;
 
     ret = __bkeep_preloaded(PAL_CB(manifest_preload.start),
                             PAL_CB(manifest_preload.end),
                             PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
                             "manifest");
     if (ret < 0)
-        return ret;
+        goto out;
 
     /* Keep track of LibOS code itself so nothing overwrites it */
     ret = __bkeep_preloaded(&__load_address,
@@ -330,13 +335,14 @@ int init_vma (void)
                             PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
                             "LibOS");
     if (ret < 0)
-        return ret;
+        goto out;
 
     /* Initialize the allocator */
 
     if (!(vma_mgr = create_mem_mgr(init_align_up(VMA_MGR_ALLOC)))) {
         debug("failed creating the VMA allocator\n");
-        return -ENOMEM;
+        ret = -ENOMEM;
+        goto out;
     }
 
     for (int i = 0 ; i < RESERVED_VMAS ; i++) {
@@ -357,8 +363,6 @@ int init_vma (void)
         assert(reserved_vmas[i]);
     }
 
-    create_lock(&vma_list_lock);
-
     current_heap_top = PAL_CB(user_address.end);
 
 #if ENABLE_ASLR == 1
@@ -371,14 +375,18 @@ int init_vma (void)
         (PAL_CB(user_address.end) - PAL_CB(user_address.start)) * 5 / 6;
     size_t rand;
     ret = DkRandomBitsRead(&rand, sizeof(rand));
-    if (ret < 0)
-        return -convert_pal_errno(-ret);
+    if (ret < 0) {
+        ret = -convert_pal_errno(-ret);
+        goto out;
+    }
     current_heap_top -= ALLOC_ALIGN_DOWN(rand % addr_rand_size);
 #endif
 
     debug("heap top adjusted to %p\n", current_heap_top);
 
-    return 0;
+out:
+    unlock(&vma_list_lock);
+    return ret;
 }
 
 static inline struct shim_vma * __get_new_vma (void)

+ 6 - 4
LibOS/shim/src/fs/chroot/fs.c

@@ -141,13 +141,15 @@ static inline ssize_t concat_uri (char * buffer, size_t size, int type,
 
 /* simply just create data, sometimes it is individually called when the
    handle is not linked to a dentry */
-static struct shim_file_data * __create_data (void)
-{
-    struct shim_file_data * data = calloc(1, sizeof(struct shim_file_data));
+static struct shim_file_data* __create_data(void) {
+    struct shim_file_data* data = calloc(1, sizeof(struct shim_file_data));
     if (!data)
         return NULL;
 
-    create_lock(&data->lock);
+    if (!create_lock(&data->lock)) {
+        free(data);
+        return NULL;
+    }
     return data;
 }
 

+ 12 - 4
LibOS/shim/src/fs/proc/ipc-thread.c

@@ -192,7 +192,9 @@ static int proc_match_ipc_thread(const char* name) {
     if (parse_ipc_thread_name(name, &pid, NULL, NULL, NULL) < 0)
         return 0;
 
-    create_lock_runtime(&status_lock);
+    if (!create_lock_runtime(&status_lock)) {
+        return -ENOMEM;
+    }
     lock(&status_lock);
 
     if (pid_status_cache)
@@ -214,7 +216,9 @@ static int proc_ipc_thread_dir_mode(const char* name, mode_t* mode) {
     if (ret < 0)
         return ret;
 
-    create_lock_runtime(&status_lock);
+    if (!create_lock_runtime(&status_lock)) {
+        return -ENOMEM;
+    }
     lock(&status_lock);
 
     if (pid_status_cache)
@@ -237,7 +241,9 @@ static int proc_ipc_thread_dir_stat(const char* name, struct stat* buf) {
     if (ret < 0)
         return ret;
 
-    create_lock_runtime(&status_lock);
+    if (!create_lock_runtime(&status_lock)) {
+        return -ENOMEM;
+    }
     lock(&status_lock);
 
     if (pid_status_cache)
@@ -265,7 +271,9 @@ static int proc_list_ipc_thread(const char* name, struct shim_dirent** buf, int
     struct pid_status_cache* status = NULL;
     int ret                         = 0;
 
-    create_lock_runtime(&status_lock);
+    if (!create_lock_runtime(&status_lock)) {
+        return -ENOMEM;
+    }
 
     lock(&status_lock);
     if (pid_status_cache && !pid_status_cache->dirty) {

+ 20 - 4
LibOS/shim/src/fs/shim_dcache.c

@@ -28,13 +28,19 @@
 #include <shim_internal.h>
 #include <shim_types.h>
 
-struct shim_lock dcache_lock;
+static struct shim_lock dcache_mgr_lock;
+
+#define SYSTEM_LOCK()   lock(&dcache_mgr_lock)
+#define SYSTEM_UNLOCK() unlock(&dcache_mgr_lock)
+#define SYSTEM_LOCKED() locked(&dcache_mgr_lock)
 
 #define DCACHE_MGR_ALLOC 64
 
 #define OBJ_TYPE struct shim_dentry
 #include <memmgr.h>
 
+struct shim_lock dcache_lock;
+
 static MEM_MGR dentry_mgr = NULL;
 
 struct shim_dentry* dentry_root = NULL;
@@ -59,13 +65,20 @@ static struct shim_dentry* alloc_dentry(void) {
     INIT_LISTP(&dent->children);
     INIT_LIST_HEAD(dent, siblings);
 
+    if (!create_lock(&dent->lock)) {
+        free_mem_obj_to_mgr(dentry_mgr, dent);
+        return NULL;
+    }
+
     return dent;
 }
 
 int init_dcache(void) {
-    dentry_mgr = create_mem_mgr(init_align_up(DCACHE_MGR_ALLOC));
+    if (!create_lock(&dcache_mgr_lock) || !create_lock(&dcache_lock)) {
+        return -ENOMEM;
+    }
 
-    create_lock(&dcache_lock);
+    dentry_mgr = create_mem_mgr(init_align_up(DCACHE_MGR_ALLOC));
 
     dentry_root = alloc_dentry();
 
@@ -100,6 +113,7 @@ void get_dentry(struct shim_dentry* dent) {
 }
 
 static void free_dentry(struct shim_dentry* dent) {
+    destroy_lock(&dent->lock);
     free_mem_obj_to_mgr(dentry_mgr, dent);
 }
 
@@ -378,7 +392,9 @@ BEGIN_RS_FUNC(dentry) {
     CP_REBASE(dent->parent);
     CP_REBASE(dent->mounted);
 
-    create_lock(&dent->lock);
+    if (!create_lock(&dent->lock)) {
+        return -ENOMEM;
+    }
 
     /* DEP 6/16/17: I believe the point of this line is to
      * fix up the children linked list.  Presumably the ref count and

+ 8 - 6
LibOS/shim/src/fs/shim_fs.c

@@ -89,8 +89,10 @@ int init_fs(void) {
     if (!mount_mgr)
         return -ENOMEM;
 
-    create_lock(&mount_mgr_lock);
-    create_lock(&mount_list_lock);
+    if (!create_lock(&mount_mgr_lock) || !create_lock(&mount_list_lock)) {
+        destroy_mem_mgr(mount_mgr);
+        return -ENOMEM;
+    }
     return 0;
 }
 
@@ -401,6 +403,8 @@ int mount_fs(const char* type, const char* uri, const char* mount_point, struct
     size_t last_len;
     find_last_component(mount_point, &last, &last_len);
 
+    lock(&dcache_lock);
+
     if (!parent) {
         // See if we are not at the root mount
         if (last_len > 0) {
@@ -412,7 +416,7 @@ int mount_fs(const char* type, const char* uri, const char* mount_point, struct
             if ((ret = __path_lookupat(dentry_root, parent_path, 0, &parent, 0, dentry_root->fs,
                                        make_ancestor)) < 0) {
                 debug("Path lookup failed %d\n", ret);
-                goto out;
+                goto out_with_unlock;
             }
         }
     }
@@ -423,12 +427,10 @@ int mount_fs(const char* type, const char* uri, const char* mount_point, struct
         if (parent->rel_path.len + 1 + last_len >= STR_SIZE) {  /* +1 for '/' */
             debug("Relative path exceeds the limit %d\n", STR_SIZE);
             ret = -ENAMETOOLONG;
-            goto out;
+            goto out_with_unlock;
         }
     }
 
-    lock(&dcache_lock);
-
     struct shim_mount* mount = alloc_mount();
     void* mount_data         = NULL;
 

+ 3 - 3
LibOS/shim/src/fs/shim_namei.c

@@ -72,7 +72,7 @@ static inline int __lookup_flags (int flags)
  * Returns 0 on success, negative on failure.
  */
 /* Assume caller has acquired dcache_lock */
-int permission (struct shim_dentry * dent, mode_t mask) {
+int __permission(struct shim_dentry* dent, mode_t mask) {
     assert(locked(&dcache_lock));
 
     mode_t mode = 0;
@@ -548,7 +548,7 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
         }
 
         // Check the parent permission first
-        err = permission(dir, MAY_WRITE | MAY_EXEC);
+        err = __permission(dir, MAY_WRITE | MAY_EXEC);
         if (err)  goto out;
 
         // Try EINVAL when creat isn't an option
@@ -593,7 +593,7 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
     // creat/O_CREAT have idiosyncratic semantics about opening a
     // newly-created, read-only file for writing, but only the first time.
     if (!newly_created) {
-        if ((err = permission(mydent, acc_mode)) < 0)
+        if ((err = __permission(mydent, acc_mode)) < 0)
             goto out;
     }
 

+ 13 - 2
LibOS/shim/src/ipc/shim_ipc.c

@@ -34,6 +34,12 @@
 #include <shim_unistd.h>
 #include <shim_utils.h>
 
+static struct shim_lock ipc_info_mgr_lock;
+
+#define SYSTEM_LOCK()   lock(&ipc_info_mgr_lock)
+#define SYSTEM_UNLOCK() unlock(&ipc_info_mgr_lock)
+#define SYSTEM_LOCKED() locked(&ipc_info_mgr_lock)
+
 #define IPC_INFO_MGR_ALLOC 32
 #define OBJ_TYPE           struct shim_ipc_info
 #include "memmgr.h"
@@ -60,7 +66,11 @@ int init_ns_sysv(void);
 int init_ipc(void) {
     int ret = 0;
 
-    create_lock(&ipc_info_lock);
+    if (!create_lock(&ipc_info_lock)
+        || !create_lock(&cur_process.lock)
+        || !create_lock(&ipc_info_mgr_lock)) {
+        return -ENOMEM;
+    }
 
     if (!(ipc_info_mgr = create_mem_mgr(init_align_up(IPC_INFO_MGR_ALLOC))))
         return -ENOMEM;
@@ -596,7 +606,8 @@ BEGIN_RS_FUNC(process) {
             get_ipc_info(process->ns[i]);
 
     memcpy(&cur_process, process, sizeof(struct shim_process));
-    create_lock(&cur_process.lock);
+    // this lock will be created in init_ipc
+    clear_lock(&cur_process.lock);
 
     DEBUG_RS("vmid=%u,uri=%s,parent=%u(%s)", process->vmid,
              process->self ? qstrgetstr(&process->self->uri) : "",

+ 18 - 3
LibOS/shim/src/ipc/shim_ipc_helper.c

@@ -34,6 +34,12 @@
 
 #define IPC_HELPER_STACK_SIZE (g_pal_alloc_align * 4)
 
+static struct shim_lock ipc_port_mgr_lock;
+
+#define SYSTEM_LOCK()   lock(&ipc_port_mgr_lock)
+#define SYSTEM_UNLOCK() unlock(&ipc_port_mgr_lock)
+#define SYSTEM_LOCKED() locked(&ipc_port_mgr_lock)
+
 #define PORT_MGR_ALLOC 32
 #define OBJ_TYPE       struct shim_ipc_port
 #include "memmgr.h"
@@ -168,6 +174,10 @@ static int init_ns_ipc_port(int ns_idx) {
 }
 
 int init_ipc_ports(void) {
+    if (!create_lock(&ipc_port_mgr_lock)) {
+        return -ENOMEM;
+    }
+
     if (!(port_mgr = create_mem_mgr(init_align_up(PORT_MGR_ALLOC))))
         return -ENOMEM;
 
@@ -187,7 +197,9 @@ int init_ipc_ports(void) {
 int init_ipc_helper(void) {
     /* early enough in init, can write global vars without the lock */
     ipc_helper_state = HELPER_NOTALIVE;
-    create_lock(&ipc_helper_lock);
+    if (!create_lock(&ipc_helper_lock)) {
+        return -ENOMEM;
+    }
     create_event(&install_new_event);
 
     /* some IPC ports were already added before this point, so spawn IPC helper thread (and enable
@@ -211,7 +223,10 @@ static struct shim_ipc_port* __create_ipc_port(PAL_HANDLE hdl) {
     INIT_LIST_HEAD(port, list);
     INIT_LISTP(&port->msgs);
     REF_SET(port->ref_count, 0);
-    create_lock(&port->msgs_lock);
+    if (!create_lock(&port->msgs_lock)) {
+        free_mem_obj_to_mgr(port_mgr, port);
+        return NULL;
+    }
     return port;
 }
 
@@ -388,7 +403,7 @@ void del_ipc_port_fini(struct shim_ipc_port* port, unsigned int exitcode) {
             port->fini[i] = NULL;
         }
 
-    __put_ipc_port(port);
+    put_ipc_port(port);
 }
 
 void del_all_ipc_ports(void) {

+ 5 - 2
LibOS/shim/src/ipc/shim_ipc_nsimpl.h

@@ -700,8 +700,11 @@ out:
     unlock(&range_map_lock);
 }
 
-static inline void init_namespace(void) {
-    create_lock(&range_map_lock);
+static inline int init_namespace(void) {
+    if (!create_lock(&range_map_lock)) {
+        return -ENOMEM;
+    }
+    return 0;
 }
 
 #define _NS_ID(ns)     __NS_ID(ns)

+ 15 - 6
LibOS/shim/src/ipc/shim_ipc_pid.c

@@ -54,7 +54,9 @@ int init_ns_pid(void) {
     struct shim_ipc_info* info;
     int ret = 0;
 
-    init_namespace();
+    if ((ret = init_namespace()) < 0) {
+        return ret;
+    }
 
     if ((ret = get_ipc_info_cur_process(&info)) < 0)
         return ret;
@@ -690,7 +692,9 @@ static LISTP_TYPE(rpcreq) rpc_reqs;
 static struct shim_lock rpc_queue_lock;
 
 int get_rpc_msg(IDTYPE* sender, void* buf, int len) {
-    create_lock_runtime(&rpc_queue_lock);
+    if (!create_lock_runtime(&rpc_queue_lock)) {
+        return -ENOMEM;
+    }
     lock(&rpc_queue_lock);
 
     if (!LISTP_EMPTY(&rpc_msgs)) {
@@ -738,7 +742,10 @@ int ipc_pid_sendrpc_callback(IPC_CALLBACK_ARGS) {
 
     debug("ipc callback from %u: IPC_PID_SENDPRC(%u, %d)\n", msg->src, msgin->sender, msgin->len);
 
-    create_lock_runtime(&rpc_queue_lock);
+    if (!create_lock_runtime(&rpc_queue_lock)) {
+        ret = -ENOMEM;
+        goto out;
+    }
     lock(&rpc_queue_lock);
 
     if (!LISTP_EMPTY(&rpc_reqs)) {
@@ -749,13 +756,13 @@ int ipc_pid_sendrpc_callback(IPC_CALLBACK_ARGS) {
         r->sender = msgin->sender;
         memcpy(r->buffer, msgin->payload, r->len);
         thread_wakeup(r->thread);
-        goto out;
+        goto out_unlock;
     }
 
     struct rpcmsg* m = malloc(sizeof(struct rpcmsg) + msgin->len);
     if (!m) {
         ret = -ENOMEM;
-        goto out;
+        goto out_unlock;
     }
 
     INIT_LIST_HEAD(m, list);
@@ -763,8 +770,10 @@ int ipc_pid_sendrpc_callback(IPC_CALLBACK_ARGS) {
     m->len    = msgin->len;
     memcpy(m->payload, msgin->payload, msgin->len);
     LISTP_ADD_TAIL(m, &rpc_msgs, list);
-out:
+
+out_unlock:
     unlock(&rpc_queue_lock);
+out:
     SAVE_PROFILE_INTERVAL(ipc_pid_sendrpc_callback);
     return ret;
 }

+ 1 - 2
LibOS/shim/src/ipc/shim_ipc_sysv.c

@@ -48,8 +48,7 @@
 #include "shim_ipc_nsimpl.h"
 
 int init_ns_sysv(void) {
-    init_namespace();
-    return 0;
+    return init_namespace();
 }
 
 DEFINE_PROFILE_INTERVAL(ipc_sysv_delres_send, ipc);

+ 4 - 2
LibOS/shim/src/shim_async.c

@@ -41,7 +41,7 @@ struct async_event {
 DEFINE_LISTP(async_event);
 static LISTP_TYPE(async_event) async_list;
 
-/* can be read without async_helper_lock but always written with lock held */
+/* Should be accessed with async_helper_lock held. */
 static enum { HELPER_NOTALIVE, HELPER_ALIVE } async_helper_state;
 
 static struct shim_thread* async_helper_thread;
@@ -137,7 +137,9 @@ int64_t install_async_event(PAL_HANDLE object, uint64_t time,
 int init_async(void) {
     /* early enough in init, can write global vars without the lock */
     async_helper_state = HELPER_NOTALIVE;
-    create_lock(&async_helper_lock);
+    if (!create_lock(&async_helper_lock)) {
+        return -ENOMEM;
+    }
     create_event(&install_new_event);
 
     /* enable locking mechanisms since we are going in multi-threaded mode */

+ 4 - 1
LibOS/shim/src/shim_init.c

@@ -663,7 +663,10 @@ noreturn void* shim_init (int argc, void * args)
         shim_clean_and_exit(-EINVAL);
     }
 
-    create_lock(&__master_lock);
+    if (!create_lock(&__master_lock)) {
+        SYS_PRINTF("shim_init(): error: failed to allocate __master_lock\n");
+        shim_clean_and_exit(-ENOMEM);
+    }
 
     int * argcp = &argc;
     const char ** argv, ** envp, ** argp = NULL;

+ 6 - 1
LibOS/shim/src/shim_malloc.c

@@ -99,8 +99,13 @@ void __system_free(void* addr, size_t size) {
 }
 
 int init_slab(void) {
-    create_lock(&slab_mgr_lock);
+    if (!create_lock(&slab_mgr_lock)) {
+        return -ENOMEM;
+    }
     slab_mgr = create_slab_mgr();
+    if (!slab_mgr) {
+        return -ENOMEM;
+    }
     return 0;
 }
 

+ 12 - 4
LibOS/shim/src/sys/shim_access.c

@@ -41,9 +41,13 @@ int shim_do_access(const char* file, mode_t mode) {
     struct shim_dentry* dent = NULL;
     int ret = 0;
 
-    ret = path_lookupat(NULL, file, LOOKUP_ACCESS | LOOKUP_FOLLOW, &dent, NULL);
+    lock(&dcache_lock);
+
+    ret = __path_lookupat(NULL, file, LOOKUP_ACCESS | LOOKUP_FOLLOW, &dent, 0, NULL, false);
     if (!ret)
-        ret = permission(dent, mode);
+        ret = __permission(dent, mode);
+
+    unlock(&dcache_lock);
 
     return ret;
 }
@@ -62,13 +66,17 @@ int shim_do_faccessat(int dfd, const char* filename, mode_t mode) {
     if ((ret = get_dirfd_dentry(dfd, &dir)) < 0)
         return ret;
 
-    ret = path_lookupat(dir, filename, LOOKUP_ACCESS | LOOKUP_FOLLOW, &dent, NULL);
+    lock(&dcache_lock);
+
+    ret = __path_lookupat(dir, filename, LOOKUP_ACCESS | LOOKUP_FOLLOW, &dent, 0, NULL, false);
     if (ret < 0)
         goto out;
 
-    ret = permission(dent, mode);
+    ret = __permission(dent, mode);
 
 out:
+    unlock(&dcache_lock);
+
     put_dentry(dir);
     return ret;
 }

+ 27 - 11
LibOS/shim/src/sys/shim_getrlimit.c

@@ -63,7 +63,9 @@ static struct __kernel_rlimit64 __rlim[RLIM_NLIMITS] __attribute_migratable = {
 static struct shim_lock rlimit_lock;
 
 int init_rlimit(void) {
-    create_lock(&rlimit_lock);
+    if (!create_lock(&rlimit_lock)) {
+        return -ENOMEM;
+    }
     return 0;
 }
 
@@ -106,10 +108,12 @@ int shim_do_setrlimit(int resource, struct __kernel_rlimit* rlim) {
     if (rlim->rlim_cur > rlim->rlim_max)
         return -EINVAL;
 
-    if (rlim->rlim_max > __rlim[resource].rlim_max && cur_thread->euid)
+    lock(&rlimit_lock);
+    if (rlim->rlim_max > __rlim[resource].rlim_max && cur_thread->euid) {
+        unlock(&rlimit_lock);
         return -EPERM;
+    }
 
-    lock(&rlimit_lock);
     __rlim[resource].rlim_cur = rlim->rlim_cur;
     __rlim[resource].rlim_max = rlim->rlim_max;
     unlock(&rlimit_lock);
@@ -120,6 +124,7 @@ int shim_do_prlimit64(pid_t pid, int resource, const struct __kernel_rlimit64* n
                       struct __kernel_rlimit64* old_rlim) {
     struct shim_thread* cur_thread = get_cur_thread();
     assert(cur_thread);
+    int ret = 0;
 
     // XXX: Do not support setting/getting the rlimit of other processes yet.
     if (pid && pid != (pid_t)cur_thread->tgid)
@@ -134,20 +139,31 @@ int shim_do_prlimit64(pid_t pid, int resource, const struct __kernel_rlimit64* n
     }
 
     if (new_rlim) {
-        if (test_user_memory((void*)new_rlim, sizeof(*new_rlim), false))
-            return -EFAULT;
-        if (new_rlim->rlim_cur > new_rlim->rlim_max)
-            return -EINVAL;
-        if (new_rlim->rlim_max > __rlim[resource].rlim_max && cur_thread->euid)
-            return -EPERM;
+        if (test_user_memory((void*)new_rlim, sizeof(*new_rlim), false)) {
+            ret = -EFAULT;
+            goto out;
+        }
+        if (new_rlim->rlim_cur > new_rlim->rlim_max) {
+            ret = -EINVAL;
+            goto out;
+        }
     }
 
     lock(&rlimit_lock);
+
+    if (new_rlim) {
+        if (new_rlim->rlim_max > __rlim[resource].rlim_max && cur_thread->euid) {
+            ret = -EPERM;
+            goto out;
+        }
+    }
+
     if (old_rlim)
         *old_rlim = __rlim[resource];
     if (new_rlim)
         __rlim[resource] = *new_rlim;
-    unlock(&rlimit_lock);
 
-    return 0;
+out:
+    unlock(&rlimit_lock);
+    return ret;
 }

+ 31 - 11
LibOS/shim/src/sys/shim_msgget.c

@@ -18,6 +18,10 @@
  * shim_msgget.c
  *
  * Implementation of system call "msgget", "msgsnd", "msgrcv" and "msgctl".
+ *
+ * XXX(borysp): I'm pretty sure there are possible deadlocks in this code. Sometimes it first takes
+ * `msgq_list_lock` and then `hdl->lock`, sometimes other way round. Someone will have to rewrite
+ * it someday.
  */
 
 #include <errno.h>
@@ -260,15 +264,14 @@ int del_msg_handle(struct shim_msg_handle* msgq) {
     return ret;
 }
 
-static void __try_create_lock(void) {
-    create_lock_runtime(&msgq_list_lock);
-}
-
 int shim_do_msgget(key_t key, int msgflg) {
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
     IDTYPE msgid = 0;
     int ret;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
 
     if (key != IPC_PRIVATE) {
         struct shim_msg_handle* msgq = get_msg_handle_by_key(key);
@@ -376,7 +379,10 @@ int shim_do_msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg) {
         return -EINVAL;
 
     struct shim_msg_handle* msgq;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
 
     if ((ret = connect_msg_handle(msqid, &msgq)) < 0)
         return ret;
@@ -401,7 +407,10 @@ int shim_do_msgrcv(int msqid, void* msgp, size_t msgsz, long msgtype, int msgflg
 
     struct __kernel_msgbuf* msgbuf = (struct __kernel_msgbuf*)msgp;
     struct shim_msg_handle* msgq;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
 
     if ((ret = connect_msg_handle(msqid, &msgq)) < 0)
         return ret;
@@ -419,7 +428,10 @@ int shim_do_msgctl(int msqid, int cmd, struct msqid_ds* buf) {
 
     struct shim_msg_handle* msgq;
     int ret;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
 
     if ((ret = connect_msg_handle(msqid, &msgq)) < 0)
         return ret;
@@ -432,7 +444,7 @@ int shim_do_msgctl(int msqid, int cmd, struct msqid_ds* buf) {
                     break;
             }
 
-            __del_msg_handle(msgq);
+            del_msg_handle(msgq);
             break;
 
         default:
@@ -890,11 +902,15 @@ int store_all_msg_persist(void) {
     struct shim_msg_handle* msgq;
     struct shim_msg_handle* n;
 
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
+
     lock(&msgq_list_lock);
 
     LISTP_FOR_EACH_ENTRY_SAFE(msgq, n, &msgq_list, list) {
         if (msgq->owned) {
-            struct shim_handle* hdl = container_of(msgq, struct shim_handle, info.msg);
+            struct shim_handle* hdl = MSG_TO_HANDLE(msgq);
             lock(&hdl->lock);
             __store_msg_persist(msgq);
             unlock(&hdl->lock);
@@ -910,13 +926,17 @@ int shim_do_msgpersist(int msqid, int cmd) {
     struct shim_handle* hdl;
     int ret = -EINVAL;
 
+    if (!create_lock_runtime(&msgq_list_lock)) {
+        return -ENOMEM;
+    }
+
     switch (cmd) {
         case MSGPERSIST_STORE:
             msgq = get_msg_handle_by_id(msqid);
             if (!msgq)
                 return -EINVAL;
 
-            hdl = container_of(msgq, struct shim_handle, info.msg);
+            hdl = MSG_TO_HANDLE(msgq);
             lock(&hdl->lock);
             ret = __store_msg_persist(msgq);
             unlock(&hdl->lock);

+ 12 - 8
LibOS/shim/src/sys/shim_semget.c

@@ -220,20 +220,19 @@ static int __del_sem_handle(struct shim_sem_handle* sem) {
 int del_sem_handle(struct shim_sem_handle* sem) {
     struct shim_handle* hdl = SEM_TO_HANDLE(sem);
     lock(&hdl->lock);
-    int ret = del_sem_handle(sem);
+    int ret = __del_sem_handle(sem);
     unlock(&hdl->lock);
     return ret;
 }
 
-static void __try_create_lock(void) {
-    create_lock_runtime(&sem_list_lock);
-}
-
 int shim_do_semget(key_t key, int nsems, int semflg) {
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
     IDTYPE semid = 0;
     int ret;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&sem_list_lock)) {
+        return -ENOMEM;
+    }
 
     if (key != IPC_PRIVATE) {
         struct shim_sem_handle* sem = get_sem_handle_by_key(key);
@@ -350,7 +349,9 @@ static int __do_semop(int semid, struct sembuf* sops, unsigned int nsops, unsign
         if (sops[i].sem_num >= nsems)
             nsems = sops[i].sem_num + 1;
 
-    __try_create_lock();
+    if (!create_lock_runtime(&sem_list_lock)) {
+        return -ENOMEM;
+    }
 
     if ((ret = connect_sem_handle(semid, nsems, &sem)) < 0)
         return ret;
@@ -375,7 +376,10 @@ int shim_do_semctl(int semid, int semnum, int cmd, unsigned long arg) {
     INC_PROFILE_OCCURENCE(syscall_use_ipc);
     struct shim_sem_handle* sem;
     int ret;
-    __try_create_lock();
+
+    if (!create_lock_runtime(&sem_list_lock)) {
+        return -ENOMEM;
+    }
 
     if ((ret = connect_sem_handle(semid, 0, &sem)) < 0)
         return ret;

+ 7 - 1
LibOS/shim/src/utils/strobjs.c

@@ -37,8 +37,14 @@ static struct shim_lock str_mgr_lock;
 static MEM_MGR str_mgr = NULL;
 
 int init_str_mgr(void) {
-    create_lock(&str_mgr_lock);
+    if (!create_lock(&str_mgr_lock)) {
+        return -ENOMEM;
+    }
     str_mgr = create_mem_mgr(init_align_up(STR_MGR_ALLOC));
+    if (!str_mgr) {
+        destroy_lock(&str_mgr_lock);
+        return -ENOMEM;
+    }
     return 0;
 }
 

+ 0 - 1
Pal/src/host/Skeleton/db_misc.c

@@ -37,7 +37,6 @@ void _DkInternalUnlock(PAL_LOCK* lock) {
 
 bool _DkInternalIsLocked(PAL_LOCK* lock) {
     __abort();
-    return false;
 }
 
 unsigned long _DkSystemTimeQuery(void) {