Skip to content

Commit 0d86a8d

Browse files
YaSuenagliuw
authored andcommitted
tools/hv: fcopy: Fix incorrect file path conversion
The hv_fcopy_uio_daemon fails to correctly handle file copy requests from Windows hosts (e.g. via Copy-VMFile) due to wchar_t size differences between Windows and Linux. On Linux, wchar_t is 32 bit, whereas Windows uses 16 bit wide characters. Fix this by ensuring that file transfers from host to Linux guest succeed with correctly decoded file names and paths. - Treats file name and path as __u16 arrays, not wchar_t*. - Allocates fixed-size buffers (W_MAX_PATH) for converted strings instead of using malloc. - Adds a check for target path length to prevent snprintf() buffer overflow. Fixes: 82b0945 ("tools: hv: Add new fcopy application based on uio driver") Signed-off-by: Yasumasa Suenaga <[email protected]> Reviewed-by: Naman Jain <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Message-ID: <[email protected]>
1 parent 7b89a44 commit 0d86a8d

File tree

1 file changed

+14
-23
lines changed

1 file changed

+14
-23
lines changed

tools/hv/hv_fcopy_uio_daemon.c

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ static int hv_fcopy_create_file(char *file_name, char *path_name, __u32 flags)
6262

6363
filesize = 0;
6464
p = path_name;
65-
snprintf(target_fname, sizeof(target_fname), "%s/%s",
66-
path_name, file_name);
65+
if (snprintf(target_fname, sizeof(target_fname), "%s/%s",
66+
path_name, file_name) >= sizeof(target_fname)) {
67+
syslog(LOG_ERR, "target file name is too long: %s/%s", path_name, file_name);
68+
goto done;
69+
}
6770

6871
/*
6972
* Check to see if the path is already in place; if not,
@@ -270,7 +273,7 @@ static void wcstoutf8(char *dest, const __u16 *src, size_t dest_size)
270273
{
271274
size_t len = 0;
272275

273-
while (len < dest_size) {
276+
while (len < dest_size && *src) {
274277
if (src[len] < 0x80)
275278
dest[len++] = (char)(*src++);
276279
else
@@ -282,27 +285,15 @@ static void wcstoutf8(char *dest, const __u16 *src, size_t dest_size)
282285

283286
static int hv_fcopy_start(struct hv_start_fcopy *smsg_in)
284287
{
285-
setlocale(LC_ALL, "en_US.utf8");
286-
size_t file_size, path_size;
287-
char *file_name, *path_name;
288-
char *in_file_name = (char *)smsg_in->file_name;
289-
char *in_path_name = (char *)smsg_in->path_name;
290-
291-
file_size = wcstombs(NULL, (const wchar_t *restrict)in_file_name, 0) + 1;
292-
path_size = wcstombs(NULL, (const wchar_t *restrict)in_path_name, 0) + 1;
293-
294-
file_name = (char *)malloc(file_size * sizeof(char));
295-
path_name = (char *)malloc(path_size * sizeof(char));
296-
297-
if (!file_name || !path_name) {
298-
free(file_name);
299-
free(path_name);
300-
syslog(LOG_ERR, "Can't allocate memory for file name and/or path name");
301-
return HV_E_FAIL;
302-
}
288+
/*
289+
* file_name and path_name should have same length with appropriate
290+
* member of hv_start_fcopy.
291+
*/
292+
char file_name[W_MAX_PATH], path_name[W_MAX_PATH];
303293

304-
wcstoutf8(file_name, (__u16 *)in_file_name, file_size);
305-
wcstoutf8(path_name, (__u16 *)in_path_name, path_size);
294+
setlocale(LC_ALL, "en_US.utf8");
295+
wcstoutf8(file_name, smsg_in->file_name, W_MAX_PATH - 1);
296+
wcstoutf8(path_name, smsg_in->path_name, W_MAX_PATH - 1);
306297

307298
return hv_fcopy_create_file(file_name, path_name, smsg_in->copy_flags);
308299
}

0 commit comments

Comments
 (0)