]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:smbd: let openat_pathref_dirfsp_nosymlink() do a verification loop against . and...
authorStefan Metzmacher <metze@samba.org>
Wed, 10 Aug 2022 20:01:10 +0000 (22:01 +0200)
committerVolker Lendecke <vl@samba.org>
Mon, 15 Aug 2022 15:03:37 +0000 (15:03 +0000)
I guess we should catch NT_STATUS_OBJECT_NAME_INVALID first,
currently the check is already done in check_path_syntax*,
but we may remove it in future.

But the most important reason for this is the
openat2(RESOLVE_NO_SYMLINK) optimization, which will
be introduced in the following commits.

Review with: git show -w

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/smbd/files.c

index 72d1bc7d5551bfdbf4ac67291a305f4100f52b1f..f23e9e96e52ef80ac726c7ca4b269d446c6d4747 100644 (file)
@@ -793,22 +793,45 @@ NTSTATUS openat_pathref_dirfsp_nosymlink(
                goto nomem;
        }
 
+       /*
+        * First split the path into individual components.
+        */
        path = path_to_strv(talloc_tos(), path_in);
        if (path == NULL) {
                DBG_DEBUG("path_to_strv() failed\n");
                goto nomem;
        }
+
+       /*
+        * First we loop over all components
+        * in order to verify, there's no '.' or '..'
+        */
        rel_fname.base_name = path;
+       while (rel_fname.base_name != NULL) {
 
-next:
-       next = strv_next(path, rel_fname.base_name);
+               next = strv_next(path, rel_fname.base_name);
 
-       if (ISDOT(rel_fname.base_name) || ISDOTDOT(rel_fname.base_name)) {
-               DBG_DEBUG("%s contains a dot\n", path_in);
-               status = NT_STATUS_OBJECT_NAME_INVALID;
-               goto fail;
+               if (ISDOT(rel_fname.base_name) || ISDOTDOT(rel_fname.base_name)) {
+                       DBG_DEBUG("%s contains a dot\n", path_in);
+                       status = NT_STATUS_OBJECT_NAME_INVALID;
+                       goto fail;
+               }
+
+               rel_fname.base_name = next;
        }
 
+       /*
+        * Now we loop over all components
+        * opening each one and using it
+        * as dirfd for the next one.
+        *
+        * It means we can detect symlinks
+        * within the path.
+        */
+       rel_fname.base_name = path;
+next:
+       next = strv_next(path, rel_fname.base_name);
+
        fd = SMB_VFS_OPENAT(
                conn,
                dirfsp,