Why no Unix error device?
Suppose you're writing some program that does file I/O. You'd like to
include a unit test to make sure it properly handles the error when
the disk fills up and the write can't complete. This is tough to
simulate. The test itself obviously can't (or at least shouldn't)
actually fill the disk.
A while back some Unix systems introduced a device called
/dev/full . Reading from /dev/full returns zero bytes, just like
/dev/zero . But all attempts to write to /dev/full fail with
ENOSPC , the system error that indices a full disk. You can set up
your tests to try to write to /dev/full and make sure they fail
gracefully.
That's fun, but why not generalize it? Suppose there was a
/dev/error device:
#include <sys/errdev.h>
error = open("/dev/error", O_RDWR);
ioctl(error, ERRDEV_SET, 23);
The device driver would remember the number 23 from this ioctl call,
and the next time the process tried to read or write the error
descriptor, the request would fail and set errno to 23, whatever
that is. Of course you wouldn't hardwire the 23, you'd actually do
#include <sys/errno.h>
ioctl(error, ERRDEV_SET, EBUSY);
and then the next I/O attempt would fail with EBUSY .
Well, that's the way I always imagined it, but now that I think about
it a little more, you don't need this to be a device driver. It
would be better if instead of an ioctl it was an fcntl that you
could do on any file descriptor at all.
Big drawback: the most common I/O errors are probably EACCESS and
ENOENT , failures in the open , not in the actual I/O. This idea
doesn't address that at all. But maybe some variation would work
there. Maybe for those we go back to the original idea, have a
/dev/openerror , and after you do ioctl(dev_openerror, ERRDEV_SET,
EACCESS) , the next call to open fails with EACCESS . That might
be useful.
There are some security concerns with the fcntl version of the idea.
Suppose I write a malicious program that opens some file descriptor,
dups it to standard input, does fcntl(1, ERRDEV_SET,
ESOMEWEIRDERROR) , then execs the target program t . Hapless t tries
to read standard input, gets ESOMEWEIRDERROR , and then does
something unexpected that it wasn't supposed to do. This particular attack is
easily foiled: exec should reset all the file descriptor saved-error
states. But there might be something more subtle that I haven't
thought of and in OS security there usually is.
Eh, probably the right solution these days is to LD_PRELOAD a
complete mock filesystem library that has any hooks you want in it. I
don't know what the security implications of LD_PRELOAD are but I
have to believe that someone figured them all out by now.
[ Addendum 20220314: Better solutions exist. ]
[Other articles in category /Unix]
permanent link
|