Browse Source

[LibOS] Update TYPE_DEV handles with correct function pointers in dev_ops

For device handles, `info.dev.dev_ops` contains function pointers into
LibOS. They may become invalid due to relocation of LibOS text section
in the child process on fork. This commit forces an update of these
function pointers.
Dmitrii Kuvaiskii 4 years ago
parent
commit
c685e56e67

+ 2 - 0
LibOS/shim/include/shim_handle.h

@@ -125,6 +125,8 @@ struct shim_dev_ops {
     int (*hstat)(struct shim_handle* hdl, struct stat* buf);
 };
 
+int dev_update_dev_ops(struct shim_handle* hdl);
+
 struct shim_dev_handle {
     struct shim_dev_ops dev_ops;
 };

+ 8 - 0
LibOS/shim/src/bookkeep/shim_handle.c

@@ -803,6 +803,14 @@ BEGIN_RS_FUNC(handle) {
         }
     }
 
+    if (hdl->type == TYPE_DEV) {
+        /* for device handles, info.dev.dev_ops contains function pointers into LibOS; they may
+           have become invalid due to relocation of LibOS text section in the child, update them */
+        if (dev_update_dev_ops(hdl) < 0) {
+            return -EINVAL;
+        }
+    }
+
     if (hdl->fs && hdl->fs->fs_ops && hdl->fs->fs_ops->checkin)
         hdl->fs->fs_ops->checkin(hdl);
 

+ 20 - 0
LibOS/shim/src/fs/dev/fs.c

@@ -438,6 +438,26 @@ static int dev_follow_link(struct shim_dentry* dent, struct shim_qstr* link) {
     return -ENOENT;
 }
 
+int dev_update_dev_ops(struct shim_handle* hdl) {
+    int ret;
+    char buf[STR_SIZE];
+    size_t bufsize = sizeof(buf);
+    struct shim_dev_ops ops_buf = EMPTY_DEV_OPS;
+
+    assert(hdl && hdl->type == TYPE_DEV);
+
+    ret = get_base_name(qstrgetstr(&hdl->path), buf, &bufsize);
+    if (ret < 0)
+        return -ENOENT;
+
+    ret = search_dev_driver(buf, &ops_buf);
+    if (ret < 0)
+        return ret;
+
+    memcpy(&hdl->info.dev.dev_ops, &ops_buf, sizeof(ops_buf));
+    return 0;
+}
+
 struct shim_fs_ops dev_fs_ops = {
     .mount    = &dev_mount,
     .unmount  = &dev_unmount,