]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Hgfs Server: fix error result for new dir creation in the virtual folder
authorOliver Kurth <okurth@vmware.com>
Fri, 26 Jan 2018 23:04:35 +0000 (15:04 -0800)
committerOliver Kurth <okurth@vmware.com>
Fri, 26 Jan 2018 23:04:35 +0000 (15:04 -0800)
The Hgfs server code detects when a client tries to create a new folder in the
virtual folder containing the VMware Shares. This is not allowed as only the
host can add new Shares which appears in this folder. The current error code
returned to the client in these cases is access denied. This is only correct
when the new folder does not collide with an existing share. This stops clients
treating the virtual folder as a regular read/write physical folder. However,
for the case where the name collides, the access denied error is not correct,
as it does not tell the client the folder already exists. This causes some
applications to fail as they expect to see this error if the path component
exists as that is okay and expected. At this point the application will continue
to traverse the path and ensure the next component exists or if not create that.

To ensure that applications don't prematurely fail and can test that the share
still exists in the path the Hgfs server should return HGFS_ERROR_FILE_EXIST
and leave HGFS_ERROR_ACCESS_DENIED for all other cases.

open-vm-tools/lib/hgfsServer/hgfsServer.c

index b942653e393fbfa3886f251117570a3ec08ca1e3..ea9d48180027078604b9f85671e1e625b167e9bf 100644 (file)
@@ -7466,63 +7466,78 @@ HgfsServerCreateDir(HgfsInputParam *input)  // IN: Input params
 
    HGFS_ASSERT_INPUT(input);
 
-   if (HgfsUnpackCreateDirRequest(input->payload, input->payloadSize,
-                                  input->op, &info)) {
-      nameStatus = HgfsServerGetLocalNameInfo(info.cpName, info.cpNameSize, info.caseFlags,
-                                              &shareInfo, &utf8Name, &utf8NameLen);
-      if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
-         ASSERT(utf8Name);
+   if (!HgfsUnpackCreateDirRequest(input->payload, input->payloadSize,
+                                   input->op, &info)) {
+      status = HGFS_ERROR_PROTOCOL;
+      goto exit;
+   }
 
-         LOG(4, ("%s: making dir \"%s\"", __FUNCTION__, utf8Name));
-         /*
-          * For read-only shares we must never attempt to create a directory.
-          * However the error code must be different depending on the existence
-          * of the file with the same name.
-          */
-         if (shareInfo.writePermissions) {
-            status = HgfsPlatformCreateDir(&info, utf8Name);
-            if (HGFS_ERROR_SUCCESS == status) {
-               if (!HgfsPackCreateDirReply(input->packet, input->request, info.requestType,
-                                           &replyPayloadSize, input->session)) {
-                  status = HGFS_ERROR_PROTOCOL;
-               }
-            }
-         } else {
-            status = HgfsPlatformFileExists(utf8Name);
-            if (HGFS_ERROR_SUCCESS == status) {
-               status = HGFS_ERROR_FILE_EXIST;
-            } else if (HGFS_ERROR_FILE_NOT_FOUND == status) {
-               status = HGFS_ERROR_ACCESS_DENIED;
+   nameStatus = HgfsServerGetLocalNameInfo(info.cpName, info.cpNameSize, info.caseFlags,
+                                           &shareInfo, &utf8Name, &utf8NameLen);
+   if (HGFS_NAME_STATUS_COMPLETE == nameStatus) {
+      ASSERT(utf8Name);
+
+      /*
+       * Check if the guest is attempting to create a directory as a new
+       * share in our virtual root folder. If so, then it exists as we have found
+       * the share. This should error as a file exists whereas access denied is for
+       * new folders that do not collide.
+       * The virtual root folder is read-only for guests and new shares can only be
+       * created from the host.
+       */
+      if (HgfsServerIsSharedFolderOnly(info.cpName, info.cpNameSize)) {
+         /* Disallow creating a subfolder matching the share in the virtual folder. */
+         LOG(4, ("%s: Collision: cannot create a folder which is a share\n", __FUNCTION__));
+         status = HGFS_ERROR_FILE_EXIST;
+         goto exit;
+      }
+      /*
+       * For read-only shares we must never attempt to create a directory.
+       * However the error code must be different depending on the existence
+       * of the file with the same name.
+       */
+      if (shareInfo.writePermissions) {
+         status = HgfsPlatformCreateDir(&info, utf8Name);
+         if (HGFS_ERROR_SUCCESS == status) {
+            if (!HgfsPackCreateDirReply(input->packet, input->request, info.requestType,
+                                        &replyPayloadSize, input->session)) {
+               status = HGFS_ERROR_PROTOCOL;
             }
          }
       } else {
-         /*
-          * Check if the name does not exist - the share was not found.
-          * Then it could one of two things: the share was removed/disabled;
-          * or we could be in the root share itself and have a new name.
-          * To return the correct error, if we are in the root share,
-          * we must check the open mode too - creation of new files/folders
-          * should fail access denied, for anything else "not found" is acceptable.
-          */
-         if (nameStatus == HGFS_NAME_STATUS_DOES_NOT_EXIST) {
-             if (HgfsServerIsSharedFolderOnly(info.cpName,
-                                              info.cpNameSize)) {
-               nameStatus = HGFS_NAME_STATUS_ACCESS_DENIED;
-               LOG(4, ("%s: New file creation in share root not allowed\n", __FUNCTION__));
-            } else {
-               LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
-            }
+         status = HgfsPlatformFileExists(utf8Name);
+         if (HGFS_ERROR_SUCCESS == status) {
+            status = HGFS_ERROR_FILE_EXIST;
+         } else if (HGFS_ERROR_FILE_NOT_FOUND == status) {
+            status = HGFS_ERROR_ACCESS_DENIED;
+         }
+      }
+   } else {
+      /*
+       * Check if the name does not exist - the share was not found.
+       * Then it could one of two things: the share was removed/disabled;
+       * or we could be in the root share itself and have a new name.
+       * To return the correct error, if we are in the root share,
+       * we must check the open mode too - creation of new files/folders
+       * should fail access denied, for anything else "not found" is acceptable.
+       */
+      if (nameStatus == HGFS_NAME_STATUS_DOES_NOT_EXIST) {
+         if (HgfsServerIsSharedFolderOnly(info.cpName,
+                                          info.cpNameSize)) {
+            nameStatus = HGFS_NAME_STATUS_ACCESS_DENIED;
+            LOG(4, ("%s: disallow new folder creation in virtual share root.\n",
+                    __FUNCTION__));
          } else {
-            LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
+            LOG(4, ("%s: Shared folder not found\n", __FUNCTION__));
          }
-
-         status = HgfsPlatformConvertFromNameStatus(nameStatus);
+      } else {
+         LOG(4, ("%s: Shared folder access error %u\n", __FUNCTION__, nameStatus));
       }
 
-   } else {
-      status = HGFS_ERROR_PROTOCOL;
+      status = HgfsPlatformConvertFromNameStatus(nameStatus);
    }
 
+exit:
    HgfsServerCompleteRequest(status, replyPayloadSize, input);
    free(utf8Name);
 }