Variables and packages

The ELF Virus Writing HOWTO: sparc-sunos5.9
Prev |  | Next

# 1. Variables and packages

| Once it hits the fan, the only rational choice is to sweep it up, package it, and sell it as fertilizer.
| anonymous

This document tries to cover multiple platforms through conditional compilation. There is a `configure.pl` that determines the host type and sets up a `config.sh` containing environment variable definitions. There also are equivalent `config.csh`, `config.h`, `config.mak`, `config.sed`, and `config.xml`. The `Makefile` then uses individual sub-directories for each platform. The name of these directories (and some other platform specific values) is retrieved through environment variables. The directory structure is not without meaning.

- `src/` is for source code, i.e. text files written and maintained by humans.

- `pre/sparc-sunos5.9/` is directory `src/` pre-processed with `config.sed`. In `pre/` all program names are absolute. Magic numbers and platform specific constants are verbatim.

- `tmp/sparc-sunos5.9/` is the only place to hold binaries, i.e. executables and `.o` files.

- `out/sparc-sunos5.9/` is for the output of executables, hex dumps, disassembly listings, text processing.

## 1.1. Variables prefixed with `TEVWH_`

The files in `src/` are obfuscated with obscene amounts of variable references like `${TEVWH_ELF_BASE}` or even `${TEVWH_PATH_LS}`. I admit that using variables instead of plain program names makes shell scripts harder to read. But this is necessary to maintain a minimum level of reproducibility on SunOS. Anyway, directory `pre/` makes that `10000` and `/usr/xpg4/bin/ls`. You will encounter this syntax nightmare only in a few places. An almost complete list of used variables is given below.

Table 1. Variables prefixed with `TEVWH_`

Variable name | Value on this platform
--- | ---
`CFLAGS` | `-Wall -O1 -I . -I out/sparc-sunos5.9 -D NDEBUG`

Variable name | Value on this platform | Variable name | Value on this platform
--- | --- | --- | ---
`AFLAGS` | `-I . -D _ASM` | `ARCH` | `sparc`
`ASM` | `sparc_SunOS_att` | `ASM_COMMENT` | `!`
`ASM_FLAVOR` | `` | `ASM_OBJDUMP` | ``
`ASM_RETURN` | `(restore|unimp)` | `ASM_STYLE` | `att`
`BYTE_ORDER` | `M` | `ELF_ADDR` | `Elf32_Addr`
`ELF_ADDR_SIZE` | `32` | `ELF_ALIGN` | `10000`
`ELF_BASE` | `10000` | `ELF_EHDR` | `Elf32_Ehdr`
`ELF_MAGIC` | `10001` | `ELF_OFF` | `Elf32_Off`
`ELF_PAGE_SIZE` | `1000` | `ELF_PHDR` | `Elf32_Phdr`
`ELF_SHDR` | `Elf32_Shdr` | `HOSTTYPE` | `SunOS/sparc`
`OS_CODE` | `sparc-sunos5.9` | `OS_NAME` | `SunOS 5.9`
`OS_PKG_SYS` | `SunOS` | `OS_VERSION` | `5.9`
`OUT` | `out/sparc-sunos5.9` | `OUT_XML` | `out/sparc-sunos5.9/xml`
`PRE` | `pre/sparc-sunos5.9` | `PROC_EXE` | `/proc/self/object/a.out`
`TMP` | `tmp/sparc-sunos5.9` | `UNAME` | `SunOS`

Note that hexadecimal shell variables actually miss the leading `0x` to simplify calculations with `bc`. These values are also available to C code through corresponding `#define` statements after `#include <config.h>`. Values are not quoted, but hexadecimal values are correctly prefixed by `0x`.

## 1.2. Variables prefixed with `TEVWH_PATH_`

Table 2. Variables prefixed with `TEVWH_PATH_`

Variable name | Value on this platform | Variable name | Value on this platform
--- | --- | --- | ---
`BASH` | `/usr/bin/bash` | `BC` | `/usr/bin/bc`
`CAT` | `/usr/bin/cat` | `CC` | `/opt/sfw/bin/gcc`
`CHMOD` | `/usr/bin/chmod` | `CSH` | `/usr/bin/tcsh`
`CUT` | `/usr/bin/cut` | `DD` | `/usr/bin/dd`
`DISTID` | `/etc/release` | `DU` | `/usr/xpg4/bin/du`
`DUMP` | `/usr/ccs/bin/dump` | `ECHO` | `/usr/bin/echo`
`ELFDUMP` | `/usr/ccs/bin/elfdump` | `EXPAND` | `/usr/bin/expand`
`FILE` | `/usr/bin/file` | `FIND` | `/usr/xpg4/bin/find`
`FMT` | `/usr/bin/fmt` | `GDB` | `/opt/sfw/bin/gdb`
`GREP` | `/usr/xpg4/bin/grep` | `ISAINFO` | `/usr/bin/isainfo`
`ISALIST` | `/usr/bin/isalist` | `KILL` | `/usr/xpg4/bin/kill`
`LD` | `/usr/ucb/ld` | `LDD` | `/usr/bin/ldd`
`LS` | `/usr/xpg4/bin/ls` | `MAKE` | `/usr/xpg4/bin/make`
`MAN` | `/usr/bin/man` | `NICE` | `/usr/xpg4/bin/nice`
`NM` | `/usr/xpg4/bin/nm` | `OBJDUMP` | `/opt/sfw/bin/gobjdump`
`OD` | `/usr/xpg4/bin/od` | `PERL` | `/usr/perl5/5.6.1/bin/perl`
`PKGCHK` | `/usr/sbin/pkgchk` | `PKGINFO` | `/usr/bin/pkginfo`
`READELF` | `/opt/sfw/bin/greadelf` | `SED` | `/usr/xpg4/bin/sed`
`SH` | `/usr/xpg4/bin/sh` | `SORT` | `/usr/xpg4/bin/sort`
`STRACE` | `/usr/sbin/strace` | `STRINGS` | `/usr/bin/strings`
`STRIP` | `/usr/ccs/bin/strip` | `TAIL` | `/usr/xpg4/bin/tail`
`TEE` | `/usr/bin/tee` | `TR` | `/usr/xpg4/bin/tr`
`TRUSS` | `/usr/bin/truss` | `UNIQ` | `/usr/bin/uniq`
`WC` | `/usr/bin/wc` | `XARGS` | `/usr/bin/xargs`
`XXD` | `/opt/sfw/bin/xxd` |  |

## 1.3. The name of the X

Command: src/packages/uname.sh

    #!/bin/sh
    uname -mprs
    echo "[${HOSTTYPE}]"
    echo "[${VENDOR}]"
    echo "[${OSTYPE}]"
    echo "[${MACHTYPE}]"
    echo "[${LANG}]"

The value of `LANG` is not directly related. But some tools create strange output for `en_US.UTF-8`.

Output: out/sparc-sunos5.9/packages/uname

    SunOS 5.9 sun4m sparc
    [sun4]
    [sun]
    [solaris]
    [sparc]
    []

While most Linux distributions ship with slightly modified kernels, no vendor has ever dared to mess with the values returned by uname(2). Instead the tradition of distribution dependent text files in directory `/etc` was established.

Command: pre/sparc-sunos5.9/packages/distid.sh

    #!/usr/xpg4/bin/sh
    # We need this script to copy the id-file into directory out/.
    # I use many machines to test examples, but only one to render the document.

    /usr/bin/cat /etc/release

Output: out/sparc-sunos5.9/packages/distid

                            Solaris 9 12/02 s9s_u2wos_10 SPARC
               Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
                            Use is subject to license terms.
                               Assembled 05 November 2002

Solaris features another interesting tool.

Command: pre/sparc-sunos5.9/packages/SunOS/isalist.sh

    #!/usr/xpg4/bin/sh
    isalist

Output: out/sparc-sunos5.9/packages/SunOS/isalist

    sparcv8 sparcv8-fsmuld sparcv7 sparc

Command: pre/sparc-sunos5.9/packages/SunOS/isainfo.sh

    #!/usr/xpg4/bin/sh
    isainfo -v

Output: out/sparc-sunos5.9/packages/SunOS/isainfo

    32-bit sparc applications

## 1.4. The owner of files

One of the lesser known features of package management is self-reflection. How do we determine the package owning a file if we have the canonical path name?

The package format used by SunOS 5.9 is called "pkg Datastream (SVR4)" by a recent file(1). Relevant information is stored as a set of text files in directory `/var/sadm`. For each installed package there is a sub directory in `/var/sadm/pkg` that includes a description.

Source: pre/sparc-sunos5.9/packages/SunOS/du.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/file /var/sadm/* | /usr/bin/expand -t 32
    /usr/xpg4/bin/ls -l /var/sadm/install/contents
    /usr/xpg4/bin/du -s /var/sadm/pkg /var/sadm/install

Output: out/sparc-sunos5.9/packages/du

    /var/sadm/README:               English text
    /var/sadm/install:              directory
    /var/sadm/install_data:         directory
    /var/sadm/pkg:                  directory
    /var/sadm/prod:                 directory
    /var/sadm/softinfo:             directory
    /var/sadm/svm:                  directory
    /var/sadm/system:               directory
    /var/sadm/wbem:                 directory
    -rw-r--r--   1 root     other    3992657 Feb 15 01:00 /var/sadm/install/contents
    5134 /var/sadm/pkg
    8176 /var/sadm/install

The first half of a query does a linear search trough text file `/var/sadm/install/contents`. The tricky part is to find the canonical name of a file. A lot of tools are provided in two different variations. The POSIX confirming ones are located in directory `/usr/xpg4/bin/`, as described by xpg4(5). The classic tools are installed in `/usr/bin`. But since `/bin` is a symbolic link to `/usr/bin`, a naive which(1) can give unexpected results.

Source: pre/sparc-sunos5.9/packages/SunOS/simple.sh

    #!/usr/xpg4/bin/sh
    query='/bin/sed /usr/bin/sed /usr/xpg4/bin/sed'
    /usr/xpg4/bin/ls -li ${query}
    /usr/sbin/pkgchk -l -p "${query}"

Output: out/sparc-sunos5.9/packages/simple

           328 -r-xr-xr-x   1 root     bin        29032 Apr  7  2002 /bin/sed
           328 -r-xr-xr-x   1 root     bin        29032 Apr  7  2002 /usr/bin/sed
          7025 -r-xr-xr-x   1 root     bin        27460 Apr  7  2002 /usr/xpg4/bin/sed
    Pathname: /usr/bin/sed
    Type: regular file
    Expected mode: 0555
    Expected owner: root
    Expected group: bin
    Expected file size (bytes): 29032
    Expected sum(1) of contents: 43067
    Expected last modification: Apr 07 01:04:46 2002
    Referenced by the following packages:
    	SUNWcsu
    Current status: installed

    Pathname: /usr/xpg4/bin/sed
    Type: regular file
    Expected mode: 0555
    Expected owner: root
    Expected group: bin
    Expected file size (bytes): 27460
    Expected sum(1) of contents: 21260
    Expected last modification: Apr 07 01:04:54 2002
    Referenced by the following packages:
    	SUNWxcu4
    Current status: installed

The second part of the query works on a single file, `/var/sadm/pkg/*/pkginfo`:

Source: pre/sparc-sunos5.9/packages/SunOS/version.sh

    #!/usr/xpg4/bin/sh
    pkg=$( /usr/sbin/pkgchk -l -p /usr/xpg4/bin/sed \
    | /usr/xpg4/bin/grep -v '^[A-Z]' )
    /usr/bin/pkginfo -x ${pkg}

Output: out/sparc-sunos5.9/packages/SunOS/version

    SUNWxcu4        XCU4 Utilities
                    (sparc) 11.9.0,REV=2002.04.06.15.27

## 1.5. The source of man-pages

Option `-a` of `man` returns all matching entries, not just the lowest section. This behavior is identical between platforms.

Command: pre/sparc-sunos5.9/packages/man-all/SunOS.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/man -a -d kill \
    | /usr/xpg4/bin/sed -ne 's/.*\<formatted = //p'

Output: out/sparc-sunos5.9/packages/man-all

    /usr/share/man/cat1/kill.1
    /usr/share/man/cat2/kill.2

Requesting a specific section requires option `-s `section`` on SunOS, while Linux and FreeBSD prefer a plain ``section``.

Command: pre/sparc-sunos5.9/packages/man-section/SunOS.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/man -d -s 2 kill \
    | /usr/xpg4/bin/sed -ne 's/.*\<formatted = //p'

Output: out/sparc-sunos5.9/packages/man-section

    /usr/share/man/cat2/kill.2

## 1.6. Verifying installed packages

This chapter is not about checking the integrity of package files. See Intrusion detection systems (i) for a general introduction.

SunOS uses checksums based on sum(1). pkgchk(1) lets you verify everything, complete packages or a list of files specified with option `-i `listfile``. Diagnostics are written to stderr and no news is good news.

Command: pre/sparc-sunos5.9/packages/SunOS/verify.sh

    #!/usr/xpg4/bin/sh
    pkg=$( /usr/sbin/pkgchk -l -p /etc/profile \
    | /usr/xpg4/bin/grep -v '^[A-Z]' )
    /usr/bin/echo pkg=[${pkg}]
    /usr/sbin/pkgchk ${pkg} 2>&1 | /usr/xpg4/bin/sed 11q
    /usr/bin/echo status=$?

Output: out/sparc-sunos5.9/packages/verify

    pkg=[ SUNWcsr ]
    ERROR: /etc/.login
        modtime <04/07/02 01:00:15 AM> expected <01/27/03 08:32:35 PM> actual
    ERROR: /etc/cron.d/at.deny
        modtime <04/07/02 12:44:24 AM> expected <01/27/03 08:32:35 PM> actual
    ERROR: /etc/cron.d/cron.deny
        modtime <04/07/02 12:44:24 AM> expected <01/27/03 08:32:36 PM> actual
    ERROR: /etc/default/cron
        modtime <04/07/02 12:48:55 AM> expected <01/27/03 08:32:36 PM> actual
    ERROR: /etc/default/devfsadm
        modtime <04/07/02 12:51:00 AM> expected <01/27/03 08:32:36 PM> actual
    ERROR: /etc/default/dhcpagent
    status=0

Option `-n` is advertised as "Do not check volatile or editable files". With option `-d `package_file`` you can verify against the checksums included in a package file, e.g. on the installation CD.

Prev | Home | Next
The ELF Virus Writing HOWTO |  | The magic of the Elf