Skip to content

LinuxIoctlCommandExecuter drops reply data #3

@nichenke

Description

@nichenke

LinuxIoctlCommandExecuter _os_send() is dropping the return from fcntl.ioctl(). It appears the code is expecting the "mutable" nature (https://docs.python.org/2/library/fcntl.html) of the buffer to allow ioctl to update the original buffer. However, it seems that is not the case when using source_buffer.to_raw(). The net result of this is the lack of CheckCondition exceptions raised on failing commands, as _os_receive() is returning the original buffer but it does not have status or the other data filled in by the host.

Link to code in question:

class LinuxIoctlCommandExecuter(LinuxCommandExecuter):

Two possible fixes are here in the test code as well. I prefer the capturing of the ioctl return & keeping the input and output SGIO separate, as that makes some logging and debugging easier. It does come at the cost of more memory & processing.

In the test here, status should be 2, along with the other data indicating the error. In this particular case, the command should be generating a SCSI Check Condition with 'MEDIUM NOT PRESENT'.

Test code:

import fcntl
import os

from infi.asi import SCSIReadCommand
from infi.asi.linux import SGIO

SG_IO = 0x2285

TUR = b"\x00" * 6

command = SCSIReadCommand(TUR, 0)
sgio = SGIO.create(1, command, 30)

print "ORIG COMMAND:", sgio

drive_fd = os.open('/dev/nst1', os.O_RDWR|os.O_NONBLOCK)

print "="*8, "ALL NOPES", "="*8
foo = fcntl.ioctl(drive_fd, SG_IO, sgio.to_raw())
print "retdata type, len:", type(foo), len(foo)
resp_sgio = sgio.from_string(foo)
print resp_sgio

# this works, buffer is seen as mutable by fcntl.ioctl()
print "="*8, "RAINBOWS", "="*8
foo = fcntl.ioctl(drive_fd, SG_IO, ctypes.addressof(sgio.source_buffer))
print "retdata type, value:", type(foo), foo
print sgio

Code output, using a TUR command to a tape drive that doesn't have media (it was handy).

ORIG COMMAND: SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=35466208, sbp=33181424, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=0, masked_status=0, msg_status=0, sb_len_wr=0, host_status=0, driver_status=0, resid=0, duration=0, info=0)
======== ALL NOPES ========
retdata type, len: <type 'str'> 88
BUG!! original status == 0 (should be 2): 0
Processed return SGIO: SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=18422752, sbp=16949824, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=2, masked_status=1, msg_status=0, sb_len_wr=96, host_status=0, driver_status=8, resid=0, duration=0, info=1)
======== RAINBOWS ========
retdata type, value: <type 'int'> 0
SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=18422752, sbp=16949824, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=2, masked_status=1, msg_status=0, sb_len_wr=96, host_status=0, driver_status=8, resid=0, duration=1, info=1)```

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions