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.