Skip to content

Instantly share code, notes, and snippets.

@muzlightbeer
Last active March 17, 2021 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muzlightbeer/2ec6927786233c70377d636f50b25176 to your computer and use it in GitHub Desktop.
Save muzlightbeer/2ec6927786233c70377d636f50b25176 to your computer and use it in GitHub Desktop.
Findings Bugs with SystemTap

Findings Bugs with SystemTap

SystemTap lets you view and modify a running Linux kernel. For in-depth information, refer to Don Domingo's Red Hat Enterprise Linux SystemTap Beginners Guide.

Installation

On Fedora 33:

sudo dnf install systemtap systemtap-runtime kernel-devel

sudo debuginfo-install kernel

Testing SystemTap

To test that SystemTap is working correctly for a Linux VMware guest that has 3D acceleration enabled, enter the following into a test.stp file:

probe module("vmwgfx").function("vmw_execbuf_ioctl") {
	printf("Successfully entered vmw_execbuf_ioctl\n");
}

This lets us hook the entry of the vmw_execbuf_ioctl() function, which is located in linux-5.10.22-200.fc33.x86_64/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c.

Run the script and wait. The output should be as follows. If you get no output, resize the terminal window:

$ sudo stap test.stp
Successfully entered vmw_execbuf_ioctl
Successfully entered vmw_execbuf_ioctl
Successfully entered vmw_execbuf_ioctl
...

Viewing Parameters

Consider the vmci_send_datagram() function from linux-5.10.22-200.fc33.x86_64/drivers/misc/vmw_vmci/vmci_guest.c:

92 /*
93  * VM to hypervisor call mechanism. We use the standard VMware naming
94  * convention since shared code is calling this function as well.
95  */
96 int vmci_send_datagram(struct vmci_datagram *dg)
97 {

This function accepts a *dg parameter, which is a pointer to a vmci_datagram structure. The following shows this structure's definition:

456 struct vmci_datagram {
457     struct vmci_handle dst;
458     struct vmci_handle src;
459     u64 payload_size;
460 };

Parameters can be accessed using $ in SystemTap scripts. If we wanted to view the payload_size parameter, we would probe the vmw_vmci module, looking at the entry point of vmci_send_datagram(), and then using $dg->payload_size to view the value of payload_size:

probe module("vmw_vmci").function("vmci_send_datagram") {
	printf("vmci_send_datagram() was called\n");
	printf("%u\n", $dg->payload_size);
}

If you run this script shortly after the operating system has loaded, the output should be similar to the following:

$ sudo stap test.stp 
vmci_send_datagram() was called
32
vmci_send_datagram() was called
32
vmci_send_datagram() was called
32

kernel_string can be used in a SystemTap script to view the contents of strings, for example the following prints the kernel_commands variable, which is a void *kernel_commands string:

printf("%s \n", kernel_string($kernel_commands));

Hooking on Line Numbers

You can hook on line numbers (but not in all places) using a function_name@path_to_file_containing_it:linenumber statement:

probe module("vmw_vmci").statement("vmci_send_datagram@drivers/misc/vmw_vmci/vmci_guest.c:102") {
	printf("Line number break\n");
}

This would hook line 102 here:

96 int vmci_send_datagram(struct vmci_datagram *dg)
97 {
98     unsigned long flags;
99     int result;
100 
101     /* Check args. */
102     if (dg == NULL)

Changing Parameters

Parameters can also be changed. Using the *dg parameter for vmci_send_datagram() again:

456 struct vmci_datagram {
457     struct vmci_handle dst;
458     struct vmci_handle src;
459     u64 payload_size;
460 };

The vmci_handle structure is defined as follows:

123 /*
124  * struct vmci_handle - Ownership information structure
125  * @context:    The VMX context ID.
126  * @resource:   The resource ID (used for locating in resource hash).
127  *
128  * The vmci_handle structure is used to track resources used within
129  * vmw_vmci.
130  */
131 struct vmci_handle {
132     u32 context;
133     u32 resource;
134 };

The following script will change the destination resource to an invalid value:

probe module("vmw_vmci").function("vmci_send_datagram") {
    printf("Changing res\n");
    $dg->dst->resource = 4444;
}

Since this will change a value, it must be run in guru mode, stap -g.

The consequences of changing this can be viewed in the guest's vmware.log file on the host, for example on macOS:

% tail -f Virtual\ Machines.localized/Fedora\ 64-bit.vmwarevm/vmware.log
2021-03-17T15:45:00.017+11:00| vcpu-1| I005: VMCIDatagram: Destination resource 4444 invalid.

Viewing Kernel Source

On Fedora, the following steps download a kernel source RPM, extract it, and then apply all patches:

  1. $ yumdownloader --source kernel

  2. $ rpm -ivh kernel-5.10.22-200.fc33.src.rpm

  3. cd ~/rpmbuild/SPECS/

  4. rpmbuild -bp --nodeps kernel.spec

  5. $ cd ~/rpmbuild/BUILD/kernel-5.10.fc33/linux-5.10.22-200.fc33.x86_64/

cscope is useful for viewing C code. From step 5, run cscope -R -u to get started (do not use -u except for the first time). This lets you find function definitions, where functions are called from, and so on. You can set an editor (that is used when viewing functions) in ~/.bashrc, for example, export CSCOPE_EDITOR=vim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment