title: Why dynamically allocated buffer in user program makes kernel driver crash?
body: <p>I have a program that allocates a buffer whose pointer is passed to a kernel driver through a custom IOCTL. In the driver I get an Mdl and lock the pages of the user-program buffer with "MmGetSystemAddressForMdlSafe" and then use the Mdl to fill the user program buffer.</p>
  
  <p>If in the user program the buffer was a normal array, the driver always works as it should.
  (WORD buffer[256], where word is an unsigned short)</p>
  
  <p>If the user program buffer was instead allocated with the new keyword <code>(WORD *buffer = new WORD[256])</code> or the malloc keyword <code>(WORD *buffer=(WORD*) malloc(sizeof(*buffer)*256)))</code> from time to time I get a BSOD and the error is "page fault in non paged area".</p>
  
  <p>WHY?</p>
  
  <p>Thanks!</p>
  
  <p>EDIT(additional details):</p>
  
  <p>In the driver I use <code>MmGetSystemAddressForMdlSafe</code> this way:</p>
  
  <p><code>PVOID p_buffer = MmGetSystemAddressForMdlSafe(Irp-&gt;MdlAddress, HighPagePriority);</code></p>
  
  <p>Irp is a PIRP that I receive as the second parameter when I handle the <code>IRP_MJ_DEVICE_CONTROL</code> MajorFunction.</p>
  
  <p>After I've checked that <code>p_buffer</code> is not null, I use that pointer to write user buffer:</p>
  
  <p><code>READ_PORT_BUFFER_USHORT((PUSHORT)(USHORT)current_port.address, (PUSHORT)p_buffer, 256)</code></p>
  
  <p>IOCTL definition:</p>
  
  <pre><code>#define IOCTL_TEST_READPORT      CTL_CODE(FILE_DEVICE_TEST,  \
      TEST_IOCTL_INDEX + 0,   \
      METHOD_OUT_DIRECT,         \
      FILE_ANY_ACCESS)
  </code></pre>
  
  <p>Driver function that handles <code>IRP_MJ_DEVICE_CONTROL</code>:</p>
  
  <pre><code>    NTSTATUS TESTDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
  PIO_STACK_LOCATION IrpStack;
  ULONG              input_buffer_size;
  ULONG              output_buffer_size;
  ULONG              control_code;
  PVOID              p_buffer;
  NTSTATUS           nt_status;
  struct             port current_port;
  
  UNREFERENCED_PARAMETER(DeviceObject);
  PAGED_CODE();
  
  Irp-&gt;IoStatus.Status      = STATUS_SUCCESS;
  Irp-&gt;IoStatus.Information = 0;
  
  IrpStack = IoGetCurrentIrpStackLocation(Irp);
  
  switch (IrpStack-&gt;MajorFunction)
  {
  
  case IRP_MJ_DEVICE_CONTROL:
  
      control_code = IrpStack-&gt;Parameters.DeviceIoControl.IoControlCode;
  
      switch (control_code)
      {
          case IOCTL_TEST_READPORT:
              p_buffer = MmGetSystemAddressForMdlSafe(Irp-&gt;MdlAddress, HighPagePriority);
              input_buffer_size  = IrpStack-&gt;Parameters.DeviceIoControl.InputBufferLength;
  
              if (!p_buffer) 
              {
                  nt_status = STATUS_INSUFFICIENT_RESOURCES;
                  break;
              }
              if (input_buffer_size)
              {
                  memcpy (&amp;current_port, Irp-&gt;AssociatedIrp.SystemBuffer, input_buffer_size);
                  switch (current_port.size)
                  {
                  case 1:
                      current_port.value = (ULONG)READ_PORT_UCHAR((PUCHAR)(USHORT)current_port.address);
                      memcpy (p_buffer, &amp;current_port.value, sizeof(current_port.value));
                      Irp-&gt;IoStatus.Information = sizeof(current_port.value);
                      break;
                  case 0xF0:
                      READ_PORT_BUFFER_USHORT((PUSHORT)(USHORT)current_port.address, (PUSHORT)p_buffer, 256);
                      Irp-&gt;IoStatus.Information = sizeof(current_port.value);
                      break;
                  case 2:
                      current_port.value = (ULONG)READ_PORT_USHORT((PUSHORT)(USHORT)current_port.address);
                      memcpy (p_buffer, &amp;current_port.value, sizeof(current_port.value));
                      Irp-&gt;IoStatus.Information = sizeof(current_port.value);
                      break;
                  }
              }
              else
                  Irp-&gt;IoStatus.Status = STATUS_INVALID_PARAMETER;
                  break;
          case IRP_MJ_CREATE:
              KdPrint(("IRP_MJ_CREATE"));
              break;
  
          case IRP_MJ_CLOSE:
              KdPrint(("IRP_MJ_CLOSE"));
              break;
  
          default:
              Irp-&gt;IoStatus.Status = STATUS_INVALID_PARAMETER;
              break;
      }
      break;
  }
  nt_status = Irp-&gt;IoStatus.Status;
  IoCompleteRequest (Irp, IO_NO_INCREMENT);
  return nt_status;
  }
  </code></pre>
  
  <p>The relevant case is <code>case 0xF0:</code> inside <code>case IOCTL_TEST_READPORT:</code></p>