Bug 224250 - Sending SCSI command to ATA device makes kernel triple fault.
Summary: Sending SCSI command to ATA device makes kernel triple fault.
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 10.3-RELEASE
Hardware: amd64 Any
: --- Affects Only Me
Assignee: freebsd-scsi (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-12-11 17:59 UTC by Natalia Portillo
Modified: 2017-12-14 16:35 UTC (History)
3 users (show)

See Also:


Attachments
C snippet (1011 bytes, text/x-csrc)
2017-12-13 18:19 UTC, Natalia Portillo
no flags Details
C# snippet (12.71 KB, text/x-csharp)
2017-12-13 18:20 UTC, Natalia Portillo
no flags Details
Truss on real hardware (ICH7) (49.37 KB, text/plain)
2017-12-14 16:30 UTC, Natalia Portillo
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Natalia Portillo 2017-12-11 17:59:07 UTC
When sending a SCSI command thru CAM to an ATA device, kernel triple faults and machine hangs completely.

No crash dump is generated.

Code can be found in:
https://github.com/claunia/DiscImageChef/blob/7e4ba43063006fe9ef0ab157a75157f573b64db8/DiscImageChef.Devices/FreeBSD/Command.cs#L83

It only happens when csio.data_ptr is set.
Setting it using .NET pinned pointers (aka GCHandle), .NET memory allocation (aka AllocHGlobal), or libc memory allocation (aka malloc), makes no difference.

Same code with SATA, SCSI or SAS devices work as expected.
Comment 1 Alan Somers freebsd_committer freebsd_triage 2017-12-11 19:56:40 UTC
It would be very helpful if you could distill that .NET code down into a minimal C testcase.  Also, could you tell us what kind of ATA controller you have?  The output of "pciconf -lv" would be sufficient.
Comment 2 Natalia Portillo 2017-12-12 01:04:28 UTC
Stay tuned I'll attach a C snippet, and a C# snippet (just in case it only fails when under Mono) asap.

ATA controllers tested have been VirtualBox and Intel Q45.
Comment 3 Natalia Portillo 2017-12-13 17:14:03 UTC
The snippet (both in C and C#) does not crash. So maybe the problem is in a combination of commands. As it directly triple faults I'll have to go step by step, sorry, will take time.
Comment 4 Alan Somers freebsd_committer freebsd_triage 2017-12-13 17:18:44 UTC
Thanks for working on this.  Just let us know whenever you have a reliable reproduction method.
Comment 5 Natalia Portillo 2017-12-13 18:19:39 UTC
Created attachment 188806 [details]
C snippet

Works with ATA, SATA, SCSI and SAS devices.
Comment 6 Natalia Portillo 2017-12-13 18:20:15 UTC
Created attachment 188807 [details]
C# snippet

Works with SATA, SCSI and SAS devices. Triple faults kernel with ATA devices.
Comment 7 Alan Somers freebsd_committer freebsd_triage 2017-12-13 18:22:09 UTC
How does one compile the C# snippet?
Comment 8 Natalia Portillo 2017-12-13 18:22:51 UTC
I have tried to make the C# snippet as small as possible, however as structs and enums can be imported from C headers, I had to duplicate them all.

Using GCHandle, or calling libc's malloc does not make a different. Setting data_ptr to IntPtr.Zero (aka NULL) makes it not fault (and useless).

Tested with ATAPI devices for ATA/SATA buses.(In reply to Alan Somers from comment #1)
Comment 9 Natalia Portillo 2017-12-13 18:23:16 UTC
(In reply to Alan Somers from comment #7)

pkg install mono
mcs snippet.cs
sudo mono snippet.cs /dev/cd0
Comment 10 Natalia Portillo 2017-12-13 18:23:54 UTC
Sorry made a typo:

(In reply to Alan Somers from comment #7)

pkg install mono
mcs snippet.cs
sudo mono snippet.exe /dev/cd0
Comment 11 Alan Somers freebsd_committer freebsd_triage 2017-12-13 18:25:40 UTC
So in order to repro the fault, I need an ATA (not SATA) CDROM?
Comment 12 Natalia Portillo 2017-12-13 18:27:06 UTC
(In reply to Alan Somers from comment #11)

Yes. With SATA (ahcich) it works correctly, only fails with Parallel ATA (ata).
Comment 13 Scott Long freebsd_committer freebsd_triage 2017-12-13 18:29:37 UTC
I might have lost it in the comment chain, did you say it was reproducible via an emulation environment?  I'd have a hard time getting an ATA CDROM drive working with real hardware these days.
Comment 14 Natalia Portillo 2017-12-13 18:32:16 UTC
(In reply to Scott Long from comment #13)

Yes Scott, at least on VBox it makes the VM abort. Have not tested other VMs.
Comment 15 Alan Somers freebsd_committer freebsd_triage 2017-12-13 20:24:08 UTC
I can't reproduce the failure using a fresh install of 10.3-RELEASE in QEMU/KVM with the emulated IDE cdrom.  I'll try to setup Virtualbox next.
Comment 16 Alan Somers freebsd_committer freebsd_triage 2017-12-13 21:28:31 UTC
Using VirtualBox, I can reproduce the failure every time.  However, it looks less like a triple fault than like a bug in VirtualBox itself.  For a triple fault, I would expect the VM to reboot.  Instead, what I see is that the entire VM crashes with signal 5 (SIGTRAP, normally used by debuggers).  

And if I start it with "virtualbox --startvm alans-fbsd103" rather than through the gui, then it leaves this message on the console:

!!Assertion Failed!!
Expression: bm->u8Cmd & BM_CMD_WRITE
Location  : /wrkdirs/usr/ports/emulators/virtualbox-ose/work/VirtualBox-4.3.22/src/VBox/Devices/Storage/DevATA.cpp(5294) int ataAsyncIOLoop(RTTHREAD, void *)
Trace/BPT trap

Is this what you see, Natalia?
Comment 17 Natalia Portillo 2017-12-13 21:37:50 UTC
(In reply to Alan Somers from comment #16)

Strange. Let me try on real hardware. I'll comment in a few hours.
Comment 18 Scott Long freebsd_committer freebsd_triage 2017-12-13 21:59:41 UTC
Comment on attachment 188806 [details]
C snippet

The assertion is here:

VirtualBox-4.3.22/src/VBox/Devices/Storage/DevATA.cpp:5293
                if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
                    AssertRelease(bm->u8Cmd & BM_CMD_WRITE);

I'm a bit confused, I believe that the ATA driver sets this bit here:

src/sys/dev/ata/ata_all.c
                if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
                        request->flags |= ATA_R_READ;
and
src/sys/dev/ata/ata_pci.c
    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
                 (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
                 ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)|
                 ATA_BMCMD_START_STOP);

Maybe this isn't going through ata_pci_dmastart(), or maybe the flags are getting cleared/not copied correctly prior?  I don't have time to look into it further today.
Comment 19 Natalia Portillo 2017-12-14 16:30:36 UTC
Created attachment 188831 [details]
Truss on real hardware (ICH7)
Comment 20 Natalia Portillo 2017-12-14 16:35:49 UTC
(In reply to Alan Somers from comment #16)

Yes that is what happens with VirtualBox.

However on a real ICH7 machine, it hangs the computer, just it's not instant takes about 3 seconds. truss attached.