Fedora Firewall Management 101

On Fedora Core, the iptables rules are stored in /etc/sysconfig/iptables. To change the rules, the iptables(8) utility is used. When done, store the updated rules in /etc/sysconfig/iptables by running the following as root:

# /sbin/iptables-save > /etc/sysconfig/iptables

I’m sure I’ll need this again, and I’m sure I’ll have forgotten all of it by then.

D’oh! Stepping over functions in gdb

I feel really dumb at the moment.

While debugging, I frequently find myself in need of a “step over function call” functionality. It has always bothered me that the gdb command “step” steps into functions, while I wasn’t interested at all in what was happening inside the function. It turns out that gdb has the command I’ve always wanted, and it is:

(gdb) next

The GNU Debugger (gdb) and Files loaded at Runtime

I’m working on a project where one program loads an ELF file at runtime and then transfers control to that dynamically loaded file. The file will be loaded at an address obtained by malloc(3), so the address will be arbitrary (from a user perspective).

Normally, if a crash occurs while a program is being run under a debugger, the debugger automatically shows you where in the source code the crash occurred. This works only if the debugged program includes debug information. That debug information is stored in the executable file itself. It is ignored by the operating system, but the debugger can use it to resolve addresses to symbols, i.e. to variable and function names.

In my case, if a crash is caused by the dynamically loaded file, then all I see is the register contents and maybe a plain stack trace. That’s because the debugger does not know where to find the debug information. Seeing the addresses is useful as it can be used to look up the problematic instruction with objdump. However, debugging would be a lot easier if the addresses could be automatically resolved to symbols by the debugger.

The GNU Debugger (gdb), my debugger of choice, has a add-symbol-file command that instructs the debugger to load symbol information from a file on disk. This command can be issued before the program to be debugged is started, while it’s running or even after it has crashed. There are two parameters required by the command. The first one will tell it where to load the debug information from, i.e. the path to the ELF file on disk. The other one will tell it at what address the ELF .text section of the ELF file has been loaded. So the syntax is:

(gdb) add-symbol-file file.elf <address>

For my project, I’m expecting frequent crashes in the dynamically loaded program. So in order to make debugging less time consuming, I created a little .gdbinit file in my home directory that does these things:

  • Tell gdb which program is being debugged. This is the program that will load another one at runtime.
  • Set a breakpoint in that first stage program. The breakpoint needs to be somewhere where the address of the .text section of the dynamically loaded file can be determined.
  • Then start the program.
  • When the breakpoint is hit, print the address of the .text section of the dynamically loaded ELF file.

My .gdbinit file that does the above looks like this:

file primary_stage
break jump_to_second_stage
run
p/x entry_point

Now anytime the debugger is started, it will automatically load the primary stage ELF file, set a breakpoint and start the program. As soon as the breakpoint is hit, the address of the .text section will be printed. Since that’s the first print instruction in the debug session, it can now be accessed through the use of a placeholder: $1.


Unfortunately, automatically loading the second stage ELF program from the .gdbinit file does not work. So I then need to manually enter this command:

(gdb) add-symbol-file second_stage $1

Well, it turns out that you can add the above command to the .gdbinit and it will work just fine. I have no idea why that did not work the last time I tried it.

Now, a crash in the second_stage program will be reported with full symbol information available to the debugger.

DHCP, DNS and dynamic updates

Today I updated my router, a Soekris net4801 (I think), to OpenBSD 4.2. I know it’s dumb to upgrade to OpenBSD 4.2 about three weeks before OpenBSD 4.3 is officially released, but today I actually had time and the box was in desperate need of an update. Also, I have recently moved and the network changed. I used to have a designated server running FreeBSD that also handled DNS and DHCP. When I moved, I shut the server down, and so for the last few weeks I had only very basic DHCP services running and no local DNS at all. Anyways, to make the long story short, I needed a DNS server that would resolve local names as well as a DHCP server that does dynamic DNS upates.

First, I installed OpenBSD 4.2 by netbooting the Soekris box from another OpenBSD “box” running inside Parallels. The instructions for that can be found in the OpenBSD FAQ. There is one thing to remember, though: The Soekris doesn’t have a VGA console but only serial, so the PXE-booted kernel needs to be told that it should only use the serial console for output. So the boot.conf file the FAQ mentions needs to look like this:

set tty com0
set stty 9600
boot bsd.rd

Now on to the DHCP and DNS installation. The DHCP server included with OpenBSD will not do dynamic DNS updates, so the ISC DHCP Server is needed. It can be installed by running (as root):

# ftp ftp://ftp.de.openbsd.org/pub/OpenBSD/4.2/packages/i386/isc-dhcp-server-3.0.4p0.tgz
# pkg_add -v isc-dhcp-server-3.0.4p0.tgz

The dhcpd binary will be installed in /usr/local/sbin. Be aware that the base dhcpd included in OpenBSD lives in /usr/sbin, so simply typing “dhcpd” at the command line will most certainly start the OpenBSD DHCP Server! In order to automatically start the DHCP server on boot, these lines need to be added to /etc/rc.local:

if [ -x /usr/local/sbin/dhcpd ] ; then
        echo -n ' dhcpd' ; /usr/local/sbin/dhcpd
fi

Next, before the Server can be fully configured, a key that will be shared between DHCP and DNS server needs to be created:

$ dnssec-keygen -a HMAC-MD5 -b 128 -n USER <name>

This command generates to files in the current working directory. The file with the extension *.private will include the key required later. Wherever the configuration files include a “secret” statement, that value needs to be inserted. The parameter <name> determines the name of the key. This will be used later, but I don’t know if the name actually has to be reused. For the rest of this posting, we’ll use key_name to represent the generated key’s name.

So now on to the DHCP Server configuration. My /etc/dhcpd.conf now looks like this:

option  domain-name "local.deadc0.de";

ddns-update-style ad-hoc;

key key_name {
        algorithm       hmac-md5;
        secret          "...";
}

zone local.deadc0.de. {
        primary 127.0.0.1;
        key key_name;
}

zone 1.168.192.in-addr.arpa. {
        primary 127.0.0.1;
        key key_name;
}

zone 2.168.192.in-addr.arpa. {
        primary 127.0.0.1;
        key key_name;
}

subnet 192.168.1.0 netmask 255.255.255.0 {
        range 192.168.1.1 192.168.1.127;
        
        option domain-name-servers 192.168.1.254;
        option routers 192.168.1.254;
}
        
subnet 192.168.2.0 netmask 255.255.255.0 {
        range 192.168.2.1 192.168.2.127;

        option domain-name-servers 192.168.2.254;
        option routers 192.168.2.254;
}

Now that the DHCP server is configured, the DNS server needs configuration. In OpenBSD, the DNS Server is BIND, but it’s started in a chroot environment, so its configuration files live under /var/named. The server configuration file is /var/named/etc/named.conf and looks like this on my system:

include "etc/rndc.key";

controls {
        inet 127.0.0.1 allow {
                localhost;
        } keys {
                key_name;
        };
};

acl clients {
        localnets;
        ::1;
};

options {
        listen-on    { any; };
        listen-on-v6 { any; };

        allow-recursion { clients; };
};

// Standard zones ommited.

zone "local.deadc0.de" {
        type master;
        file "master/local.deadc0.de";
        
        allow-update {
                key     "key_name";
        };
};

zone "1.168.192.in-addr.arpa" {
        type master;
        file "master/1.168.192.in-addr.arpa";

        allow-update {
                key     "key_name";
        };
};

zone "2.168.192.in-addr.arpa" {
        type master;
        file "master/2.168.192.in-addr.arpa";

        allow-update {
                key     "key_name";
        };
};

The actual zone files will not be posted, they are just standard zone declarations, nothing special. However, notice the include statement at top of the file. It includes the key declaration file /var/named/etc/rndc.key that looks like this:

key key_name {
        algorithm hmac-md5;
        secret "...";
};

In order to supress some warning when the DNS server starts, the file /var/named/etc/rndc.conf needs to be created. It should look like this:

options {
        default-server  localhost;
        default-key     "key_name";
};

server localhost {
        key     "key_name";
};

include "rndc.key";

Finally, everything under /var/named/etc and /var/named/master needs to be owned by the user “named”, so as root run this:

# chown -R named:named /var/named/etc
# chown -R named:named /var/named/master

Now make sure that the DNS server is enabled by including this line in /etc/rc.conf.local:

named_flags=""

Then reboot the box and that should be it.

Embedding binary BLOBs into an ELF file

I needed this yesterday, found a link describing it – and forgot it by today 🙁

For a project I’m working on, I need to embed a file into an ELF executable. The executable then needs to do things with the embedded file, i.e. it has to know where in memory the file resides and how large it is.

So here it goes, largely copied from the link mentioned above.

  • Create an object file from the binary blob:
    $ ld -r -b binary -o example.o example.bin
  • In the sources, declare the symbols:
    extern char _binary_example_bin_start[];
    extern char _binary_example_bin_end[];
    
  • Make sure the object file is linked with the other sources:
    $ gcc -o example example.c example.o
    

TianoCore on QEMU

There is a bios.bin binary file for use with QEMU available at http://fabrice.bellard.free.fr/qemu/efi-bios.tar.bz2. It is meant to be used as a BIOS replacement for QEMU and provides an EFI interface. It is compiled from the TianoCore sources, at least that’s what the QEMU homepage suggests.

The problem with this file is that it can only be used with very few versions of QEMU, that’s why I’m writing this.

I’ve had success with version 0.9.0 when the patches linked from the coreboot wiki were applied. I’ve also had success with a CVS snapshot from July 3rd, 2007. Version 0.9.1 or the stock 0.9.0 do not work.

QEMU and kqemu on IBM’s OpenClient

Today I wanted to try QEMU on IBM’s OpenClient Linux distribution. Unfortunately, I was unable to install a binary package through yum because the default package repositories don’t provide one. So I ended up installing QEMU from the sources.

Getting the sources is easy. To fetch the latest sources (i.e. CVS HEAD), just run:

$ cvs -z3 -d:pserver:anonymous@cvs.savannah.nongnu.org:/sources/qemu 
 co qemu

In my case, I wanted version QEMU version 0.9.1, so I did this:

$ cvs -z3 -d:pserver:anonymous@cvs.savannah.nongnu.org:/sources/qemu 
 co -rrelease_0_9_1 qemu

Building the sources is trivial as well. The usual three step process (configure, make, make install) works like a charm. If PREFIX isn’t set, QEMU installs in /usr/local, but I want it in /opt. So here’s what I did:

$ ./configure --prefix=/opt
$ make
$ sudo make install

Now I had a bunch of QEMU executables in /opt/bin, each one for a different architecture. But I wanted kqemu, the kernel accellerator for QEMU, as well. Through the QEMU home page, I found this site which provides kqemu RPMs for RHEL and Fedora.

For the IBM OpenClient distribution, I had to do this:

$ wget http://dl.atrpms.net/all/kqemu-1.3.0-2.el5.i386.rpm
$ wget http://dl.atrpms.net/all/kqemu-kmdl-2.6.18-53.1.13.el5-1.3.0-2.el5.i686.rpm
$ sudo rpm -iv kqemu-1.3.0-2.el5.i386.rpm kqemu-kmdl-2.6.18-53.1.13.el5-1.3.0-2.el5.i686.rpm

In case the links to the RPMs are truncated, there is a kqemu RPM and a kqemu-kmdl RPM.

Finally, in order to actually load the kernel module, I did this:

$ sudo modprobe kqemu

Everything described here is pretty straight forward, but I wanted to make sure I document the installation of the kqemu module somwhere, hence this post.

Cell SDK 3.0 on IBM’s OpenClient Distribution

Today I was finally able to build a simple HelloWorld-Application with and within the TianoCore build environment. This is good news, as it leads me to the next task: Building the same HelloWorld-Application, but this time for Linux on 64-Bit PowerPC.

Since I do not yet have access to a 64-Bit PowerPC machine running Linux, I’m going to use the Cell SDK 3.0 for now. It can be used from an i386 machine and includes a toolchain as well as the full system simulator. The toolchain includes a cross-compiler that is cabable of producing binaries for the Cell BE’s PPU, which is essentially a 64-Bit PowerPC processor. The system simulator simulates a Linux-installation running on Cell.

I’m still on IBM’s OpenClient Linux distribution, which is apparently based on RHEL 5.1, at least according to /etc/redhat-release

Red Hat Enterprise Linux Client release 5.1 (Tikanga)

This is good on one hand, but made things slightly more complicated on the other hand. But first things first. Here’s what I did to prepare the Cell SDK installation:

  • I went to the developerWorks download page for the Cell SDK 3.0 and downloaded the RHEL 5.1 packages.
  • I had to download the "basic libraries and headers for cross-compiling to Cell Broadband Engine’s PPU", both the 32-Bit version and the 64-Bit version, from the Barcelona Supercomputer Center (BSC). Note that I could have built those RPMs myself, but only if I had a few other required RPMs like e.g. a glibc for PowerPC. Apparently those required RPMs are provided on the RHEL installation CDs, however, I’m on IBM’s OpenClient and thus do not have access to the installation CDs. The good thing is, the Fedora RPMs provided by the BSC turned out to work just fine.
  • For the full system simulator, I had to download the sysroot image from the BSC website.

So that’s it for the preparation part, now to actually installing the SDK.

  • I installed the installer RPM like this:
    # rpm -ivh cell-install-3.0.0-1.0.noarch.rpm

    This installs the installer to /opt/cell.

  • Now I needed to install the cross-compilation libraries and headers:
    # rpm -ivh ppu-sysroot-f7-2.noarch.rpm
    # rpm -ivh ppu-sysroot64-f7-2.noarch.rpm
  • Next I ran the installer as instructed by the installation manual:
    # cd /opt/cell
    # ./cellskd –iso /home/phs/Downloads install

After successfully running the installer, I found a functioning cross-compiler in /opt/cell/toolchain/bin.

For the system simulator, I had to install the sysroot imae RPM like this:

# rpm -ivh sysroot_image-3.0-7.noarch.rpm

Unfortunately, I wasn’t able to make the system simulator work because of a missing dependency on a simulation library.

By the way, there’s also official documentation available here.

Setting up a Subversion Server

Ok, there’s probably a million Blog posts, tutorials and HowTos on how to do this already. Yet I still find it hard to find short instructions on how to set up a subversion server quickly. I just had to do it again, and it took me longer than expected, so here it goes.

My requirements are pretty basic:

  • WebDAV so I can access the repository over HTTP.
  • I don’t need too much security, so SSL won’t be needed.
  • I want SVN:Web, a web front end to the repositories.

Here’s what I did for the Subversion+WebDAV part. Note that I’m currently on IBM’s OpenClient Linux Distribution which is based on RedHat.

  • I made sure that the httpd package is installed. I didn’t have to install it, so I guess it’s installed by default.
  • I had to install the mod_dav_svn package with yum:
    $ sudo yum install mod_dav_svn
  • The package installs a config file at /etc/httpd/conf.d/subversion.conf. By default, the <Location> tag is commented out. I just copied it, removed the comment signs and adjusted the values to my needs. This is what it now looks like:
    LoadModule dav_svn_module     modules/mod_dav_svn.so
    LoadModule authz_svn_module   modules/mod_authz_svn.so
    
    <Location /repos>
       DAV svn
       SVNParentPath /var/www/svn
    
       <LimitExcept GET PROPFIND OPTIONS REPORT>
          AuthType Basic
          AuthName "Authorization Realm"
          AuthUserFile /var/www/passwd
          Require valid-user
       </LimitExcept>
    </Location>
    
  • Now the Apache HTTP Server will serve the contents of /var/www/svn via WebDAV (I think), but it will query for a valid user entry. The entry must be created as follows:
    # cd /var/www
    # htpasswd -c passwd <username>
    
  • Next, I created the direcories for the repositories. As root, I ran these commands:
    # cd /var/www
    # mkdir svn
    # cd svn
    # svnadmin create <name of repository>
    # chown -R apache:apache <name of repository>
    
  • I then activated the HTTP service so the Apache Web Server would be started at boot time. I did this using a GUI tool called system-config-services. I had to check the box next to the httpd entry. I didn’t want to reboot right aways, so I clicked Start in the toolbar. The tool told me that the service would now be running and I could verify this by going to http://localhost/. Testing the Subversion part was easy, too. Navigating to http://localhost/repos/example did the trick. Note that the actual repository name must be used instead of "example".
  • Oh, and I want at least minimal security. That is, I want the HTTP Server to serve pages only to the local machine. Therefore, I changed the Listen directive in the server config uration file to this:
    Listen 127.0.0.1:80
    

The second part was installing the SVN::Web CGI Script. Here’s what I did to do it.

  • First, I had to install the subversion-perl package with yum. As root, I ran
    # yum install subversion-perl
  • Second, I installed the actuall SVN::Web script through CPAN. Again as root, I did
    # cpan install SVN::Web
  • I then created a directory that would hold all the SVN::Web files:
    #cd /var/www
    #mkdir svnweb
    
  • In that directory, I let the Perl script set itself up using default values:
    # cd /var/www/svnweb
    # svnweb-install
    
  • The last step created a file called config.yaml. It must be edited so the CGI script finds the repositories. Near the end, I edited the reposparent value:
    reposparent: '/var/www/svn'
  • Now, as the final step, the script needs to be introduced to the Apache Server. I created a file svnweb.conf in /etc/httpd/conf.d with the following contents:
    Alias /svnweb /var/www/svnweb
    
    AddHandler cgi-script .cgi
    
    <Directory /var/www/svnweb>
            Options All ExecCGI
            DirectoryIndex index.cgi
    </Directory>
    

After restarting the Apache HTTP Server, I could access http://localhost/svnweb and see the repositories.

TianoCore on IBM’s OpenClient

I’ve started work at IBM yesterday. Today I found a room and got all my user accounts and passwords set up so I can actually start to work.

I’m trying to build the TianoCore EDKII (SVN Revision 4792) on IBM’s own Linux distribution, called OpenClient. The distribution sucks but it’s the only kind of Linux we’re allowed to use around here. It’s based on Red Hat (I think), but it feels "different".

To bootstrap the TianoCore Build Environment, I sort of followed my FreeBSD and Fedora Core notes. Here’s what I did:

  • Installed Java JDK 6 Update 4 (JDK 1.6.0_04) for Linux through the self-extracting binary file (not the RPM) that Sun provides. I placed the JDK in /opt.
  • Installed the binary distribution of Apache Ant 1.7.0, Saxon 8.1.1, XMLBeans 2.1.0 as well as ant-contrib 1.0b3 and placed all of them in /opt.
  • Created the symlinks:
    $ cd /opt/apache-ant-1.7.0/lib
    $ sudo ln -s /opt/ant-contrib/ant-contrib-1.0b3.jar ant-contrib.jar
    $ sudo ln -sf /opt/saxonb8.1.1/saxon8.jar /opt/xmlbeans-2.1.0/lib/saxon8.jar
    

I then created a small script that automates the build tool bootstrapping process:

export JAVA_HOME=/opt/jdk1.6.0_04
export XMLBEANS_HOME=/opt/xmlbeans-2.1.0
export ANT_HOME=/opt/apache-ant-1.7.0
export WORKSPACE=/home/phs/Sources/edk2
export PATH=$PATH:$XMLBEANS_HOME/bin:$ANT_HOME/bin
. edksetup.sh ForceRebuild

Sourcing the script successfully builds the build tools. Then, in the file $WORKSPACE/Tools/Conf/target.txt, two settings need to be adjusted:

ACTIVE_PLATFORM=EdkUnixPkg/Unix.fpd
TOOL_CHAIN_TAG=ELFGCC

Of course, the previously mentioned patch needs to be applied. After that, the EDKII Unix Emulation Package can be built and run as described in the tutorial:

$ cd $WORKSPACE/
$ build
$ cd Build/Unix
$ . run.cmd

I found that the IBM OpenClient distribution already includes the e2fsprogs-devel package as well as the relevant X11 development packages. Please also note that it is not neccessary to build an PE32+ cross compiler on Linux.