]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_preopen: only try to preopen if we can construct an absolute path
authorStefan Metzmacher <metze@samba.org>
Fri, 11 Jun 2021 20:05:14 +0000 (20:05 +0000)
committerStefan Metzmacher <metze@samba.org>
Thu, 1 Jul 2021 13:02:31 +0000 (13:02 +0000)
So we make sure the dirfsp contains an absolute path to begin with
and smb_fname is a relative name within the directory.

Note: dirfsp->fsp_name->base_name[0] is only '/' because currently all callers pass
conn->cwd_fsp as dirfsp ... though there's already one caller that calls
fd_openat() with a real dirfsp, that is in vfs_fruit though on the
resource fork stream so doesn't really effect us currently.

If more callers are changed in future the situation may change,
but I guess then this is not the only place with potential problems.
We most likely need a generic helper function that returns the absolute
path of a dirfsp and use it here.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/modules/vfs_preopen.c

index c54daaf44c86c33b0e34dcdecd05fea89be794ac..db8fe5b491051786952e55348dde76ff5a51bf9a 100644 (file)
@@ -396,6 +396,7 @@ static int preopen_openat(struct vfs_handle_struct *handle,
                          int flags,
                          mode_t mode)
 {
+       const char *dirname = dirfsp->fsp_name->base_name;
        struct preopen_state *state;
        int res;
        unsigned long num;
@@ -421,6 +422,27 @@ static int preopen_openat(struct vfs_handle_struct *handle,
                return res;
        }
 
+       /*
+        * Make sure we can later contruct an absolute pathname
+        */
+       if (dirname[0] != '/') {
+               return res;
+       }
+       /*
+        * There's no point in preopen the directory itself.
+        */
+       if (ISDOT(smb_fname->base_name)) {
+               return res;
+       }
+       /*
+        * If we got an absolute path in
+        * smb_fname it's most likely the
+        * reopen via /proc/self/fd/$fd
+        */
+       if (smb_fname->base_name[0] == '/') {
+               return res;
+       }
+
        if (!is_in_path(smb_fname->base_name, state->preopen_names, true)) {
                DEBUG(10, ("%s does not match the preopen:names list\n",
                           smb_fname_str_dbg(smb_fname)));
@@ -430,8 +452,7 @@ static int preopen_openat(struct vfs_handle_struct *handle,
        TALLOC_FREE(state->template_fname);
        state->template_fname = talloc_asprintf(
                state, "%s/%s",
-               dirfsp->fsp_name->base_name, smb_fname->base_name);
-
+               dirname, smb_fname->base_name);
        if (state->template_fname == NULL) {
                return res;
        }