Why smartctl could not be run without root
As you can guess, this title gives answer to the question: ‘How to run smartctl from a normal user?’. The answer is ‘no way. Root only’.
Here are detailed explanation.
If we run smartctl from non-priveleged user it will complain:
Smartctl open device: /dev/sda failed: Permission denied
. This is a simple thing to fix: just add current user to the groupdisk
. Usually all devices have rw access for groupdisk.
This fix ‘permission’ problem.- Then you get more cryptic message:
Probable ATA device behind a SAT layer
Try an additional '-d ata' or '-d sat' argument.
And fixing this… is impossible. All you have a fall back to sudo
or suid
.
Why it’s impossible?
Well, let’s read the strace output for smartctl
:
openat(AT_FDCWD, "/dev/sda", O_RDONLY|O_NONBLOCK) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_FROM_DEV, cmd_len=6, cmdp="\x12\x00\x00\x00\x24\x00", mx_sb_len=32, iovec_count=0, dxfer_len=36, timeout=20000, flags=0, dxferp="\x00\x00\x05\x02\x5b\x00\x00\x02\x41\x54\x41\x20\x20\x20\x20\x20\x48\x69\x74\x61\x63\x68\x69\x20\x48\x44\x53\x37\x32\x32\x30\x32"..., status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=0, info=0}) = 0
ioctl(3, SG_IO, {interface_id='S', dxfer_direction=SG_DXFER_FROM_DEV, cmd_len=16, cmdp="\x85\x08\x0e\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xec\x00", mx_sb_len=32, iovec_count=0, dxfer_len=512, timeout=20000, flags=0, dxferp="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., status=0, masked_status=0, msg_status=0, sb_len_wr=0, sbp="", host_status=0, driver_status=0, resid=0, duration=0, info=0}) = -1 EPERM (Operation not permitted)
As you can see, there is an SG_IO ioctl calls to the device, and we are getting EPERM error at one of them.
You can try to add cap_sys_rawio+ie
to your smartctl binary or play with other capabilities and permissions, but let’s look to the docs:
- https://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/sg_io.html: All commands to SCSI device type SCANNER are accepted. Other cases yield an EPERM error. Note that the write() read() interface must have the sg file descriptor open()-ed with O_RDWR as write permission is required by Linux to execute a write() system call
- And you can see
openat(AT_FDCWD, “/dev/sda”, O_RDONLY|O_NONBLOCK)
in the strace.
Why? Here are few pieces of the smartctl source code:
linux_scsi_device::linux_scsi_device(smart_interface * intf,
const char * dev_name, const char * req_type, bool scanning /*= false*/)
: smart_device(intf, dev_name, "scsi", req_type),
// If opened with O_RDWR, a SATA disk in standby mode
// may spin-up after device close().
linux_smart_device(O_RDONLY | O_NONBLOCK),
m_scanning(scanning)
{
}
and ata device:
linux_ata_device::linux_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
: smart_device(intf, dev_name, "ata", req_type),
linux_smart_device(O_RDONLY | O_NONBLOCK)
{
}
Yep, O_RDONLY
. With a small justification — no spin-up, please.
Unfortunately, we need sat or ata or scsi here, and all them are O_RDONLY
.
This is very unfortunate and I think it worth reporting a problem to smartmontools upstream. [reported, and was wrong].
Meanwhile, the answer to the problem is ‘you need to have root/sudo to do smartctl for sata or scsi devices’. There is no other way.
Update
Unfortunately, my conclusion was wrong. I patched smartctl to use O_RDWR mode and it still have problems with EPERM. I even tried to use all+ie capability on the binary — no luck at all.