Indeed this looks like a bug in vfs layer. Thanks for finding it :-)

Here is a patch that fixes it (needs unit tests). 

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 7e028ffb..eca89556 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -825,7 +825,7 @@ mkdir(const char *pathname, mode_t mode)
     mode = apply_umask(mode);
 
     trace_vfs_mkdir(pathname, mode);
-    if ((error = task_conv(t, pathname, VWRITE, path)) != 0)
+    if ((error = task_conv_remove_trailing_slash(t, pathname, VWRITE, 
path)) != 0)
         goto out_errno;
 
     error = sys_mkdir(path, mode);
@@ -853,7 +853,7 @@ int rmdir(const char *pathname)
     error = ENOENT;
     if (pathname == nullptr)
         goto out_errno;
-    if ((error = task_conv(t, pathname, VWRITE, path)) != 0)
+    if ((error = task_conv_remove_trailing_slash(t, pathname, VWRITE, 
path)) != 0)
         goto out_errno;
 
     error = sys_rmdir(path);
@@ -977,7 +977,7 @@ int chdir(const char *pathname)
     if (pathname == nullptr)
         goto out_errno;
 
-    if ((error = task_conv(t, pathname, VREAD, path)) != 0)
+    if ((error = task_conv_remove_trailing_slash(t, pathname, VREAD, 
path)) != 0)
         goto out_errno;
 
     /* Check if directory exits */
diff --git a/fs/vfs/vfs.h b/fs/vfs/vfs.h
index d86ef957..38d2a2ab 100644
--- a/fs/vfs/vfs.h
+++ b/fs/vfs/vfs.h
@@ -135,7 +135,8 @@ int sys_fchmod(int fd, mode_t mode);
 
 int task_alloc(struct task **pt);
 int task_conv(struct task *t, const char *path, int mode, char *full);
-int path_conv(char *wd, const char *cpath, char *full);
+int task_conv_remove_trailing_slash(struct task *t, const char *path, int 
mode, char *full);
 
 //int sec_file_permission(task_t task, char *path, int mode);
 int sec_vnode_permission(char *path);
diff --git a/fs/vfs/vfs_lookup.cc b/fs/vfs/vfs_lookup.cc
index ad03fe25..4569061b 100644
--- a/fs/vfs/vfs_lookup.cc
+++ b/fs/vfs/vfs_lookup.cc
@@ -85,7 +85,7 @@ namei_follow_link(struct dentry *dp, char *node, char 
*name, char *fp, size_t mo
     } else {
         strlcpy(t.get(), p, PATH_MAX);
         strlcpy(node, fp, mountpoint_len + c + 1);
-        path_conv(node, lp, fp);
+        path_conv(node, lp, fp, false);
         strlcat(fp, t.get(), PATH_MAX);
     }
     node[0] = 0;
diff --git a/fs/vfs/vfs_task.cc b/fs/vfs/vfs_task.cc
index 332c460d..178740a0 100644
--- a/fs/vfs/vfs_task.cc
+++ b/fs/vfs/vfs_task.cc
@@ -65,7 +65,7 @@ task_alloc(struct task **pt)
  * @full: full path to be returned
  */
 int
-path_conv(char *wd, const char *cpath, char *full)
+path_conv(char *wd, const char *cpath, char *full, bool 
truncate_trailing_slash)
 {
  char path[PATH_MAX];
  char *src, *tgt, *p, *end;
@@ -129,6 +129,10 @@ path_conv(char *wd, const char *cpath, char *full)
  }
  src = p + 1;
  }
+ if (truncate_trailing_slash &&
+ tgt != full && *(tgt - 1) == '/' && tgt - 1 != full) {
+ tgt--;
+ }
  *tgt = '\0';
 
  return (0);
@@ -141,8 +145,8 @@ path_conv(char *wd, const char *cpath, char *full)
  * @full: full path to be returned
  * @acc: access mode
  */
-int
-task_conv(struct task *t, const char *cpath, int acc, char *full)
+static int
+_task_conv(struct task *t, const char *cpath, int acc, char *full, bool 
truncate_trailing_slash)
 {
        int rc;
 
@@ -150,7 +154,7 @@ task_conv(struct task *t, const char *cpath, int acc, 
char *full)
                return (EFAULT);
        }
 
-       rc = path_conv(t->t_cwd, cpath, full);
+       rc = path_conv(t->t_cwd, cpath, full, truncate_trailing_slash);
        if (rc != 0) {
                return (rc);
        }
@@ -159,6 +163,32 @@ task_conv(struct task *t, const char *cpath, int acc, 
char *full)
        return (0); //sec_file_permission(t->t_taskid, full, acc);
 }
 
+/*
+ * Convert to full path from the cwd of task and path.
+ * @t:    task structure
+ * @path: target path
+ * @full: full path to be returned
+ * @acc: access mode
+ */
+int
+task_conv(struct task *t, const char *cpath, int acc, char *full)
+{
+    return _task_conv(t, cpath, acc, full, false);
+}
+
+/*
+ * Convert to full path from the cwd of task and path. Remove any trailing 
slash.
+ * @t:    task structure
+ * @path: target path
+ * @full: full path to be returned
+ * @acc: access mode
+ */
+int
+task_conv_remove_trailing_slash(struct task *t, const char *cpath, int 
acc, char *full)
+{
+    return _task_conv(t, cpath, acc, full, true);
+}
+
 /*
  * Safe copying function that checks for overflow.
  */


I will send a proper patch with unit tests later. I changes VFS in critical 
places so it would be nice to review it.

Also I am not 100% it fixes all the cases. Note I have not simply made a 
fix in central path_conv() function as t would break many non-directory 
cases where trailing slash matters. 

On Friday, November 1, 2019 at 12:38:14 PM UTC-4, zhiting zhu wrote:
>
>  OSv:
>
> >>> import os
> >>> os.makedirs("/tmp/lambda_11111")
> >>> os.mkdir("/tmp/lambda_11111/out_0/")
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> FileNotFoundError: [Errno 2] No such file or directory: 
> '/tmp/lambda_11111/out_0/'
> >>> os.mkdir("/tmp/lambda_11111/out_0") 
> >>> 
>
> On the host:
> >>> import os
> >>> os.makedirs("/tmp/lambda_11111")
> >>> os.mkdir("/tmp/lambda_11111/out_0/")
> >>> 
>
> Why I can't put the / in the path? I'm using the same python 
> Python 3.6.8 (default, Oct  7 2019, 12:59:55) 
> [GCC 8.3.0] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>
> from Ubuntu 18.04 LTS. 
>
> Best,
> Zhiting
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/c4fb9005-1033-4ded-b234-880cf551deeb%40googlegroups.com.

Reply via email to