Why smartctl could not be run without root

George Shuklin
OpsOps
Published in
2 min readAug 7, 2018

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 group disk. Usually all devices have rw access for group disk. 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.

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.