pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patch to fix file cloning for 32bit processes on 64bit kernels, 2025-06-11
Posted by Anonymous on Wed 11th Jun 2025 20:30
raw | new post

  1. From e688215b3952be252574eaaf2aacbaefe34abad6 Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Wed, 11 Jun 2025 21:04:36 +0200
  4. Subject: [PATCH] sys,tests: |FSCTL_DUPLICATE_EXTENTS_TO_FILE| fails with 32bit
  5.  processes on 64bit kernel
  6.  
  7. |FSCTL_DUPLICATE_EXTENTS_TO_FILE| fails with 32bit processes on a
  8. 64bit kernel, typically failing with |STATUS_INVALID_HANDLE|.
  9.  
  10. This happens because the layout of |DUPLICATE_EXTENTS_DATA| differs between
  11. 32bit and 64bit, so a 64bit kernel must test for 32bit processes
  12. and use |DUPLICATE_EXTENTS_DATA32| instead to use the correct struct
  13. layout.
  14.  
  15. Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
  16. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  17. ---
  18. sys/nfs41sys_fsctl.c                      | 94 ++++++++++++++++-------
  19.  tests/sparsefiles/multisparsefiletest.ksh | 44 ++++++++---
  20.  2 files changed, 101 insertions(+), 37 deletions(-)
  21.  
  22. diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
  23. index e80321b..9df5528 100644
  24. --- a/sys/nfs41sys_fsctl.c
  25. +++ b/sys/nfs41sys_fsctl.c
  26. @@ -614,14 +614,27 @@ NTSTATUS nfs41_DuplicateData(
  27.          NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
  28.      __notnull XXCTL_LOWIO_COMPONENT *FsCtl =
  29.          &RxContext->LowIoContext.ParamsFor.FsCtl;
  30. -    __notnull PDUPLICATE_EXTENTS_DATA duplicatedatabuffer =
  31. -        (PDUPLICATE_EXTENTS_DATA)FsCtl->pInputBuffer;
  32.      __notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
  33. -    PFILE_OBJECT srcfo = NULL;
  34. -    LONGLONG io_delay;
  35. +
  36. +    /*
  37. +     * Temporary store |FSCTL_DUPLICATE_EXTENTS_TO_FILE| data here, which
  38. +     * can be either |DUPLICATE_EXTENTS_DATA32| for 32bit processes on a
  39. +     * 64bit kernel, |DUPLICATE_EXTENTS_DATA| for 64bit processes on a
  40. +     * 64bit kernel, or |DUPLICATE_EXTENTS_DATA| for 32bit processes on
  41. +     * a 32bit kernel
  42. +     */
  43. +    struct {
  44. +        HANDLE      handle;
  45. +        LONGLONG    srcfileoffset;
  46. +        LONGLONG    destfileoffset;
  47. +        LONGLONG    bytecount;
  48. +    } dd;
  49.  
  50.      DbgEn();
  51.  
  52. +    PFILE_OBJECT srcfo = NULL;
  53. +    LONGLONG io_delay;
  54. +
  55.      RxContext->IoStatusBlock.Information = 0;
  56.  
  57.      status = check_nfs41_duplicatedata_args(RxContext);
  58. @@ -633,30 +646,60 @@ NTSTATUS nfs41_DuplicateData(
  59.          goto out;
  60.      }
  61.  
  62. -    if (FsCtl->InputBufferLength <
  63. -        sizeof(DUPLICATE_EXTENTS_DATA)) {
  64. -        DbgP("nfs41_DuplicateData: "
  65. -            "buffer to small\n");
  66. -        status = STATUS_BUFFER_TOO_SMALL;
  67. -        goto out;
  68. +#if defined(_WIN64)
  69. +    if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  70. +        if (FsCtl->InputBufferLength <
  71. +            sizeof(DUPLICATE_EXTENTS_DATA32)) {
  72. +            DbgP("nfs41_DuplicateData: "
  73. +                "buffer too small for DUPLICATE_EXTENTS_DATA32\n");
  74. +            status = STATUS_BUFFER_TOO_SMALL;
  75. +            goto out;
  76. +        }
  77. +
  78. +        PDUPLICATE_EXTENTS_DATA32 ded32bit =
  79. +            (PDUPLICATE_EXTENTS_DATA32)FsCtl->pInputBuffer;
  80. +
  81. +        dd.handle           = (HANDLE)ded32bit->FileHandle;
  82. +        dd.srcfileoffset    = ded32bit->SourceFileOffset.QuadPart;
  83. +        dd.destfileoffset   = ded32bit->TargetFileOffset.QuadPart;
  84. +        dd.bytecount        = ded32bit->ByteCount.QuadPart;
  85. +    }
  86. +    else
  87. +#endif /* defined(_WIN64) */
  88. +    {
  89. +        if (FsCtl->InputBufferLength <
  90. +            sizeof(DUPLICATE_EXTENTS_DATA)) {
  91. +            DbgP("nfs41_DuplicateData: "
  92. +                "buffer too small for DUPLICATE_EXTENTS_DATA\n");
  93. +            status = STATUS_BUFFER_TOO_SMALL;
  94. +            goto out;
  95. +        }
  96. +
  97. +        PDUPLICATE_EXTENTS_DATA ded =
  98. +            (PDUPLICATE_EXTENTS_DATA)FsCtl->pInputBuffer;
  99. +
  100. +        dd.handle           = ded->FileHandle;
  101. +        dd.srcfileoffset    = ded->SourceFileOffset.QuadPart;
  102. +        dd.destfileoffset   = ded->TargetFileOffset.QuadPart;
  103. +        dd.bytecount        = ded->ByteCount.QuadPart;
  104.      }
  105.  
  106.      DbgP("nfs41_DuplicateData: "
  107. -        "duplicatedatabuffer=(FileHandle=0x%p,"
  108. -        "SourceFileOffset=%lld,"
  109. -        "TargetFileOffset=%lld,"
  110. -        "ByteCount=%lld)\n",
  111. -        (void *)duplicatedatabuffer->FileHandle,
  112. -        (long long)duplicatedatabuffer->SourceFileOffset.QuadPart,
  113. -        (long long)duplicatedatabuffer->TargetFileOffset.QuadPart,
  114. -        (long long)duplicatedatabuffer->ByteCount.QuadPart);
  115. -
  116. -    if (duplicatedatabuffer->ByteCount.QuadPart == 0LL) {
  117. +        "dd=(handle=0x%p,"
  118. +        "srcfileoffset=%lld,"
  119. +        "destfileoffset=%lld,"
  120. +        "bytecount=%lld)\n",
  121. +        (void *)dd.handle,
  122. +        (long long)dd.srcfileoffset,
  123. +        (long long)dd.destfileoffset,
  124. +        (long long)dd.bytecount);
  125. +
  126. +    if (dd.bytecount == 0LL) {
  127.          status = STATUS_SUCCESS;
  128.          goto out;
  129.      }
  130.  
  131. -    status = ObReferenceObjectByHandle(duplicatedatabuffer->FileHandle,
  132. +    status = ObReferenceObjectByHandle(dd.handle,
  133.          0,
  134.          *IoFileObjectType,
  135.          RxContext->CurrentIrp->RequestorMode,
  136. @@ -724,12 +767,9 @@ NTSTATUS nfs41_DuplicateData(
  137.          goto out;
  138.  
  139.      entry->u.DuplicateData.src_state = nfs41_src_fobx->nfs41_open_state;
  140. -    entry->u.DuplicateData.srcfileoffset =
  141. -        duplicatedatabuffer->SourceFileOffset.QuadPart;
  142. -    entry->u.DuplicateData.destfileoffset =
  143. -        duplicatedatabuffer->TargetFileOffset.QuadPart;
  144. -    entry->u.DuplicateData.bytecount =
  145. -        duplicatedatabuffer->ByteCount.QuadPart;
  146. +    entry->u.DuplicateData.srcfileoffset = dd.srcfileoffset;
  147. +    entry->u.DuplicateData.destfileoffset = dd.destfileoffset;
  148. +    entry->u.DuplicateData.bytecount = dd.bytecount;
  149.  
  150.      /* Add extra timeout depending on file size */
  151.      io_delay = pVNetRootContext->timeout +
  152. diff --git a/tests/sparsefiles/multisparsefiletest.ksh b/tests/sparsefiles/multisparsefiletest.ksh
  153. index 3994c1f..b62f577 100644
  154. --- a/tests/sparsefiles/multisparsefiletest.ksh
  155. +++ b/tests/sparsefiles/multisparsefiletest.ksh
  156. @@ -221,16 +221,40 @@ function multisparsefiletest1
  157.  
  158.          typeset tstmod
  159.  
  160. -        typeset -a tstmodlist=(
  161. -            'plainfile'
  162. -            'cp_sparseauto'
  163. -            'cloned_full'
  164. -            'cloned_1mbchunks'
  165. -        )
  166. +        case "$(getconf LONG_BIT)" in
  167. +            '64')
  168. +                typeset -a tstmodlist=(
  169. +                    'plainfile'
  170. +                    'cp_sparseauto'
  171. +                    'cloned_full_64bit'
  172. +                    'cloned_1mbchunks_64bit'
  173. +                    'cloned_full_32bit'
  174. +                    'cloned_1mbchunks_32bit'
  175. +                )
  176. +                ;;
  177. +            '32')
  178. +                typeset -a tstmodlist=(
  179. +                    'plainfile'
  180. +                    'cp_sparseauto'
  181. +                    'cloned_full'
  182. +                    'cloned_1mbchunks'
  183. +                )
  184. +                ;;
  185. +            *)
  186. +                print -u2 -f 'ERROR: unknown getconf LONG_BIT result\n'
  187. +                return 8
  188. +                ;;
  189. +        esac
  190.  
  191.          for tstmod in "${tstmodlist[@]}" ; do
  192.              printf '# Test %d '%s' generated\n' c.i "${c.testlabel}/$tstmod"
  193.  
  194. +            if [[ "${tstmod}" == *32bit ]] ; then
  195. +                winclonefilecmd='winclonefile.i686.exe'
  196. +            else
  197. +                winclonefilecmd='winclonefile.exe'
  198. +            fi
  199. +
  200.              case "${tstmod}" in
  201.                  'plainfile')
  202.                      c.stdout="$(lssparse -H 'sparsefile2.bin')"
  203. @@ -239,9 +263,9 @@ function multisparsefiletest1
  204.                      /usr/bin/cp --sparse='auto' 'sparsefile2.bin' 'sparsefile2_cpsparse.bin'
  205.                      c.stdout="$(lssparse -H 'sparsefile2_cpsparse.bin')"
  206.                      ;;
  207. -                'cloned_full')
  208. +                'cloned_full' | 'cloned_full_64bit' | 'cloned_full_32bit')
  209.                      if $test_cloning ; then
  210. -                        winclonefile.exe 'sparsefile2.bin' 'sparsefile2_cloned_full.bin' 1>'/dev/null'
  211. +                        ${winclonefilecmd} 'sparsefile2.bin' 'sparsefile2_cloned_full.bin' 1>'/dev/null'
  212.                          c.stdout="$(lssparse -H 'sparsefile2_cloned_full.bin')"
  213.                      else
  214.                          printf "# Test '%s' SKIPPED\n" "${c.testlabel}/${tstmod}"
  215. @@ -249,9 +273,9 @@ function multisparsefiletest1
  216.                          continue
  217.                      fi
  218.                      ;;
  219. -                'cloned_1mbchunks')
  220. +                'cloned_1mbchunks' | 'cloned_1mbchunks_64bit' | 'cloned_1mbchunks_32bit')
  221.                      if $test_cloning ; then
  222. -                        winclonefile.exe \
  223. +                        ${winclonefilecmd} \
  224.                              --clonechunksize $((1024*1024)) \
  225.                              'sparsefile2.bin' \
  226.                              'sparsefile2_cloned_1mbchunks.bin' 1>'/dev/null'
  227. --
  228. 2.45.1

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at