btrfs icon indicating copy to clipboard operation
btrfs copied to clipboard

|FSCTL_DUPLICATE_EXTENTS_TO_FILE| is likely to fail for 32bit processes on 64bit kernels

Open gisburn opened this issue 6 months ago • 3 comments

[The issue was originally reported for the Windows NFSv4.2 driver, see https://github.com/kofemann/ms-nfs41-client ]

|FSCTL_DUPLICATE_EXTENTS_TO_FILE| is likely to fail for 32bit processes on 64bit kernels, because the layout of DUPLICATE_EXTENTS_DATA| differs between 32bit and 64bit, so a 64bit kernel must test for 32bit processes and use |DUPLICATE_EXTENTS_DATA32| instead to use the correct struct layout.

I assume Windows btrfs has the same issue, because it neither contains |IoIs32bitProcess()| nor |DUPLICATE_EXTENTS_DATA32| in the codepath for |FSCTL_DUPLICATE_EXTENTS_TO_FILE|

Prototype patch for ms-nfs41-client is https://nrubsig.kpaste.net/7b2b16b Standalone (dumb) test program: https://github.com/kofemann/ms-nfs41-client/tree/master/tests/winclonefile/

gisburn avatar Jun 11 '25 19:06 gisburn

Thanks for letting me know about this, I'll have a look. The VFS doesn't do the translation for us? That's surprising.

maharmstone avatar Jun 11 '25 20:06 maharmstone

I'll have to double-check, but it's possible that this isn't an issue. The 64-bit version has a 64-bit HANDLE, the 32-bit version a 32-bit HANDLE followed by a 32-bit padding gap:

#include <windows.h>

typedef struct _DUPLICATE_EXTENTS_DATA {
    HANDLE FileHandle;
    LARGE_INTEGER SourceFileOffset;
    LARGE_INTEGER TargetFileOffset;
    LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;

typedef struct _DUPLICATE_EXTENTS_DATA32 {
    UINT32 FileHandle;
    LARGE_INTEGER SourceFileOffset;
    LARGE_INTEGER TargetFileOffset;
    LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA32, *PDUPLICATE_EXTENTS_DATA32;

static_assert(sizeof(DUPLICATE_EXTENTS_DATA32) == 32);
static_assert(sizeof(DUPLICATE_EXTENTS_DATA) == 32);
static_assert(offsetof(DUPLICATE_EXTENTS_DATA32, SourceFileOffset) == 8);
static_assert(offsetof(DUPLICATE_EXTENTS_DATA, SourceFileOffset) == 8);

maharmstone avatar Jun 11 '25 20:06 maharmstone

Thanks for letting me know about this, I'll have a look. The VFS doesn't do the translation for us? That's surprising.

No, the VFS layer is not going to help. Problem is also that both 32bit and 64bit end-up with the same struct size, so you have to use |IoIs32bitProcess()| like I did in the ms-nfs41-client driver. And "yes", people use 32bit processes for that FSCTL, and that includes CERN+institute Pasteur... ;/

gisburn avatar Jul 26 '25 14:07 gisburn