Mirai's Watchdog in rust.

Table of Contents

Disabling the watchdog.

One of the first things that mirai does is disable the watchdog of the host to ensure that it didnt reboot if the system begins to take too long.


// Prevent watchdog from rebooting device
if ((wfd = open("/dev/watchdog", 2)) != -1 ||
    (wfd = open("/dev/misc/watchdog", 2)) != -1)
{
    int one = 1;

    ioctl(wfd, 0x80045704, &one);
    close(wfd);
    wfd = 0;
}

Lets break that down,

if ((wfd = open("/dev/watchdog", 2)) != -1 ||

It opens the watchdog device read/write (#define O_RDWR 00000002).

It issues an 'ioctl' with a magic number.

ioctl(wfd, 0x80045704, &one);

Then closes the opened file descriptor.

close(wfd);

While this does adhere to the spec, its also not the most supported method of disabling the watchdog. there is another…

The magic close feature.

The aptly named "magic close feature" (https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt))

Magic Close feature:

If a driver supports "Magic Close", the driver will not disable the
watchdog unless a specific magic character 'V' has been sent to
/dev/watchdog just before closing the file. If the userspace daemon
closes the file without sending this special character, the driver
will assume that the daemon (and userspace in general) died, and will
stop pinging the watchdog without disabling it first. This will then
cause a reboot if the watchdog is not re-opened in sufficient time.

Seems to be more widely supported than the ioctl method. There are watchdog drivers in the tree that do not support ioctl manipulation, but instead support the magic close feature.

Rust doesn't have a close() function, From the std::fs::File docs:

Files are automatically closed when they go out of scope. Errors detected on
closing are ignored by the implementation of Drop. Use the method sync_all if
these errors must be manually handled.

This would leave us with a simple function :

use std::fs;

fn disable_watchodg() -> std::io::Result<()> {
    fs::write("/dev/watchdog", "V")?
}

fn main() {
 disable_watchdog();
}

Wild right ?

Additional resources

Author: Wade Mealing

Created: 2022-07-11 Mon 12:40