|
From: Stefan S. <dev...@gm...> - 2012-09-25 07:29:46
|
Hi !
If a userspace program communicates with a driver through ioctls, there
are various ways to exchange information.
For restricted mode ioctls, all necessary information is encoded in the
ioctl number.
This can be seen from the _IOC() macro defined in <asm-generic/ioctl.h>:
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
Thus, if a buffer should be read from the the driver, the ioctl
direction will be _IOC_READ and the size of the buffer is encoded in the
ioctl number as well.
Vice versa, for a write operation the direction would be _IOC_WRITE.
Both of these operations are handled by CUSE:
void (*ioctl) (fuse_req_t req, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags,
const void *in_buf, size_t in_bufsz, size_t out_bufsz);
For read operations, the data can be returned to the kernel (and thus to
the program doing the ioctl operation on the CUSE device) through one of
the fuse_reply_*() functions where up to out_bufsz bytes can be replied.
For write operations, the data that should be written is availble in
*in_buf with size in_bufsz.
However, there are also ioctls with the direction set to _IOC_NONE.
In this case the argument (void *arg) may have multiple purposes:
1. it is ignored
2. it is a constant
3. it is a pointer to a variable that is read from
4. it is a pointer to a variable that should be written to
Which of the above cases applies is subject to the driver implementation.
Now the burning question is how these kinds of ioctls can be handled
with CUSE.
Case 1 and 2 are not an issue of course, but what about case 3 and 4 ?
Is this supported in CUSE ?
Since no information is encoded in the ioctl number, neither the kernel
nor the CUSE code would know which of the above cases applies.
A possible solution might be best effort based.
That is, the CUSE code in the kernel would always try to interpret the
content of *arg as a pointer.
To avoid invalid memory accesses, it would have to look up the mapped
memory regions of the calling process and if the potential address is
both in a mapped region and aligned properly, the kernel would fetch
the content from the given address and pass it on to the callback function.
Regards,
Stefan
|