
An Introduction to FreeBSD 6 Kernel Hacking Lawrence Stewart, James Healy Centre for Advanced Internet Architectures, Technical Report 070622A Swinburne University of Technology Melbourne, Australia [email protected], [email protected] Abstract—The widely used FreeBSD UNIX-like oper- useful avenues for finding further information about the ating system provides a mature, stable and customisable topics discussed in the report. We will be making specific platform, suitable for many tasks including telecommu- reference to code snippets taken from the SIFTR code, nications research. FreeBSD is being used as part of which is available for download from [2] and should be CAIA’s NewTCP project [1] to evaluate up and coming referred to whilst reading this report. TCP congestion control algorithms. Part of this work has involved the customisation of the FreeBSD kernel, FreeBSD is a well known and widely used open source in the form of a loadable kernel module named SIFTR UNIX-like operating system. It is known as an extremely (Statistical Information For TCP Research). This report stable and mature platform that has been developed and aims to capture the knowledge learnt during this process. fine tuned over the past 15 years. Whilst FreeBSD 6.2-RELEASE was used as the basis for Modifications of kernel level functions, such as the this development, most of the technical information in instrumentation we required for SIFTR, are often done this report will be applicable to all FreeBSD 6.x releases, by creating a “patch” containing the required changes and possibly to earlier (5.x and 4.x to a lesser extent) against the kernel’s source code. Whilst relatively easy to or up and coming (7.x and beyond) releases. Topics covered include FreeBSD kernel module programming, the apply, such patches are irritating to develop and deploy sysctl interface, packet filtering, data structures, character because of the need to modify kernel sources directly devices, threading, file writing and debugging. The report and recompile the kernel each time the patch changes. draws together our personal experiences and sources of Thankfully, there are nicer ways of changing kernel further information to create a useful reference for those behaviour. that are new to FreeBSD kernel programming. FreeBSD’s dynamic kernel linker (KLD) facility [3] Index Terms—FreeBSD, Kernel, Hacking, Program- allows code modules to be dynamically loaded into and ming, Module, NewTCP unloaded from a running FreeBSD kernel. This allows system users with appropriate privileges to modify the I. INTRODUCTION kernel’s runtime behaviour very quickly and easily by This technical report discusses many tips, tricks and issuing a single line command to load the new module. lessons learnt during the development of a FreeBSD Kernel modules also make life easier for the developer, kernel module named SIFTR (Statistical Information For as only the kernel module itself needs to be recompiled TCP Research) [2] for the NewTCP [1] project at CAIA. each time a change is made. Whilst FreeBSD 6.2-RELEASE was used as the basis for this development, most of the technical information in II. ANATOMY OF A KERNEL MODULE this report will be applicable to all FreeBSD 6.x releases, and possibly to earlier (5.x and 4.x to a lesser extent) or Every kernel module starts with a call to up and coming (7.x and beyond) releases. the DECLARE MODULE() macro (defined in Over the course of developing the SIFTR kernel /usr/src/sys/sys/module.h), which defines, in order, module, a great deal of useful and in some cases hard the name, code execution entry point, category and to find information was learnt about programming in the load order for the module. Listing1 shows the call to FreeBSD kernel environment. This report should act as a DECLARE MODULE() from the SIFTR code. The primer to understanding the FreeBSD kernel architecture, siftr mod argument is a moduledata t struct, which environment and mechanisms useful in the development contains the pointer to the code execution entry point of FreeBSD kernel code. We also try to provide many (in our case a function named “load handler”). CAIA Technical Report 070622A June 2007 page 1 of 11 Listing 1 read-only or write-only). These variables reside under DECLARE MODULE(siftr, siftr mod, SI SUB KLD, the net.inet.siftr sysctl branch. SI ORDER ANY); Listing3 is used to declare the net.inet.siftr sysctl container struct. The code execution entry point is called each time the Listing 3 module is loaded and unloaded. This allows the module SYSCTL DECL( net inet siftr); to perform any necessary initialisation on start up and cleanup on shutdown as required. Listing4 declares a sysctl node “siftr” which will hang Listing2 is a sample Makefile that simplifies the off the net.inet branch of the sysctl tree. Node’s act as building of a KLD. The bsd.kmod.mk file is provided branches within the sysctl tree, and cannot be used as as part of the FreeBSD distribution and a significant variables in their own right. amount of work is saved by including it. Its behaviour is controlled by a range of environment variables, three of Listing 4 which are shown. A simple usage example is available SYSCTL NODE( net inet, OID AUTO, siftr, at [4]. CTLFLAG RW, NULL, “siftr related settings”); Listing 2 SRCS=vnode if.h subr kernio.c siftr.c Listing5 declares a read/write sysctl variable named KMOD=siftr “enabled” of type unsigned int, which will hang off the CFLAGS=-g -O3 net.inet.siftr branch of the sysctl tree. This variable is .include <bsd.kmod.mk> used to control whether the module’s functionality is switched on or off when loaded. The initial value of the variable is set to 0, and when the variable is changed, Having created your Makefile and source code, you the function siftr sysctl enabled handler() will be called can simply run “make” from the command line and then to handle the change. The variable’s data storage is “kldload ./siftr.ko” to load your module into the running provided by the variable named “siftr enabled”. kernel. The “./” infront of your module name is important as by default, kldload will look for kernel modules in Listing 5 /boot/kernel and /boot/modules, and will not find your SYSCTL OID( net inet siftr, OID AUTO, enabled, kernel module in the local directory. CTLTYPE UINTjCTLFLAG RW, &siftr enabled, 0, &siftr sysctl enabled handler, “IU”, “switch siftr mod- III. SYSCTL VARIABLES ule operations on/off”); The sysctl system interface [5] provides a means for user-space processes to query and manipulate kernel- Listing6 declares a read/write sysctl variable named space state information. It therefore provides an ideal “ppl” of type unsigned int, which will hang off the way to communicate with our kernel module to change net.inet.siftr branch of the sysctl tree. This variable its configuration parameters. is used to control how many observed packets for a Sysctl variables are arranged in a tree like hierarchy, particular TCP connection will trigger a log message with variables hanging off branches of the tree e.g. to be written. The initial value of the variable is set net.inet.ip.ttl, where net.inet.ip represents the branch of to 1 i.e. write a log message for every packet per the sysctl tree and ttl is the actual variable. Sysctl vari- connection. When the variable is changed, the function ables are always found as leaves on the tree, and a branch siftr sysctl pkts per log handler() will be called to han- cannot also be used as a variable e.g. in the previous dle the change. The variable’s data storage is provided example, net.inet.ip could not refer to a variable, but by the variable named “siftr pkts per log”. can have other branches and variables hanging off it. Finally, listing7 declares a read/write sysctl variable This structure provides a very simple way to organise named “logfile” of type string, which will hang off the and group system variables. net.inet.siftr branch of the sysctl tree. This variable is The SIFTR module exports 3 configuration paramaters used to specify the path to the file that SIFTR log mes- as read/write sysctl variables (you can make variables sages will be written to. When the variable is changed, CAIA Technical Report 070622A June 2007 page 2 of 11 Listing 6 The siftr hook pfil() function performs all the neces- SYSCTL OID( net inet siftr, OID AUTO, ppl, CTL- sary actions to install and remove PFIL hooks. Listing8 TYPE UINTjCTLFLAG RW, &siftr pkts per log, 1, gets the head of the linked list of PFIL hooks currently &siftr sysctl pkts per log handler, “IU”, “number of installed for AF INET (IPv4) packets. packets between generating a log message”); Listing 8 pfh inet = pfil head get(PFIL TYPE AF, AF INET); the function siftr sysctl logfile name handler() will be called to handle the change. The variable’s data storage Then, depending on whether we are hooking in or un- is provided by the variable named “siftr logfile”. hooking, a call to pfil add hook() or pfil remove hook() respectively is made. These functions allow us to install Listing 7 or remove our custom hook function siftr chkpkt() for SYSCTL PROC( net inet siftr, OID AUTO, logfile, both inbound and outbound IPv4 packets. Listing9 CTLTYPE STRINGjCTLFLAG RW, &siftr logfile, shows how to install the siftr chkpkt() hook function sizeof(siftr logfile), &siftr sysctl logfile name handler, for both inbound and outbound packets. The second “A”, “file to save siftr log messages to”); parameter to these functions can be used to pass an arbitrary pointer to the hook function each time it is The end result of including the above code snippets in invoked, but we did not require it and so left it as NULL.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages11 Page
-
File Size-