Teaching Valgrind ioctl

by sprkv5

ioctl or input/output control is a system call by which we can talk to devices rather than having unique functions for controlling the various devices that work in conjunction to help a computer run. The numerous operations for various devices are assigned certain code numbers and are multiplexed through the ioctl function.

Valgrind is a dynamic binary instrumentation framework that can be used to build dynamic analysis tools or it can be used to detect many memory management and threading bugs, and profile programs in detail using its inbuilt tools.

On a Debian 7.4 system running in a VM with the Valgrind source and these,

First I compiled Valgrind using the instructions in the source:
$ ./autogen.sh
$ ./configure
$ make
# make install

Note – it needed automake which was notified when autogen.sh was run

Then I set up an ioctl module – ioctl_basic.c, ioctl_basic.h and Makefile by:
make
# insmod ./ioctl_basic.ko
# dmesg | grep ‘major number’
[ 9354.761844] The major number for your device is 250
# mknod /dev/mytemp c 250 0

and make and execute the user program user_basic_ioctl.c by:
$ make ./user_basic_ioctl
$ ./user_basic_ioctl

I ran dmesg to check that the module works and logs proper messages.

Now back to Valgrind. I ran the user program under valgrind and it returned warning messages:

# valgrind ./user_basic_ioctl
==8650== Memcheck, a memory error detector
==8650== Copyright (C) 2002-2013, and GNU GPL’d, by Julian Seward et al.
==8650== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==8650== Command: ./user_basic_ioctl
==8650==
==8650== Warning: noted but unhandled ioctl 0x6b00 with no size/direction hints
==8650== This could cause spurious value errors to appear.
==8650== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==8650==
==8650== HEAP SUMMARY:
==8650== in use at exit: 0 bytes in 0 blocks
==8650== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==8650==
==8650== All heap blocks were freed — no leaks are possible
==8650==
==8650== For counts of detected and suppressed errors, rerun with: -v
==8650== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

A read through README_MISSING_SYSCALL_OR_IOCTL tells me I need to implement PRE() and POST() functions to wrap the system call and use PRE_MEM_READ(), POST_MEM_WRITE() and functions alike.

Now looking at the wrappers for ioctl at Valgrind/coregrind/m_syswrap/syswrap-linux.c and the manual for ioctl where I could see that since ioctl takes two arguments and may pass an extra argument with some information it made sense to add case 0x6b00 to the part where the wrapper handled two arguments but I waited for a reply at the valgrind-devel mailing list having asked about this. Turns out I was right.

So having added “case 0x6b00:” to lines 5500 I built Valgrind again and executed the user_basic_ioctl to find valgrind working on it in the normal way as it should:

# valgrind ./user_basic_ioctl
==11329== Memcheck, a memory error detector
==11329== Copyright (C) 2002-2013, and GNU GPL’d, by Julian Seward et al.
==11329== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==11329== Command: ./user_basic_ioctl
==11329==
==11329==
==11329== HEAP SUMMARY:
==11329== in use at exit: 0 bytes in 0 blocks
==11329== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==11329==
==11329== All heap blocks were freed — no leaks are possible
==11329==
==11329== For counts of detected and suppressed errors, rerun with: -v
==11329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

Notes:
Todo.