Tuesday, February 19, 2008

Running Leopard

The runtime architecture of Mac OS X is Mach-O. Although Mac OS X understands only the Mach-O binary executable format, many specialized applications can run on Mac OS X. Mac OS X kernel uses execve() system call (implemented in the BSD portion of the OS X kernel) to load the Mach-O program to run. The following are the main applications that can run on OS X:
  • UNIX command-line tools and X Windows applications written in portable interfaces such as POSIX
  • Carbon GUI and command-line applications written in C
  • Cocoa GUI and command-line applications written in Objective-C, Java, or AppleScript
  • AWT and Swing applications written in Java
  • Generic command-line applications or tools written in C++ or C that may link with one or more frameworks such as Core Foundation (of Carbon), Core Services, Foundation (of Cocoa), and I/O Kit.
Mach-O files used on Mac OS X for implementing different types of system components:
  • Bundles (programmatically loadable code)
  • Dynamics shared libraries
  • Frameworks
  • Umbrella frameworks
  • Kernel extensions
  • Linkable object files
  • Static archives
  • Executables

Frameworks
Frameworks differ from shared libraries in that they can contain resources, such as headers, in addition to codes. They are usually found in /System/Library/Frameworks. The standard frameworks on Mac OS X are:
  • Application Environment - Carbon, Cocoa, System
  • Application Functionality - e.g. Screen Saver, WebKit, etc
  • Core Functionality - e.g. CoreFoundation, CoreServices, etc
  • Graphics and Multimedia - e.g. CoreAudio, OpenGL, QuickTime, Quartz, etc
  • Security and System Management - e.g. DirectoryService, Kerberos, LDAP, etc
  • Languages, Scripting, and Automation - e.g. Automator, JavaVM, Python, etc
  • Peripheral Access - e.g. FWAUserLib, ForceFeedback, etc
Static and dynamic shared libraries
Previous operating systems used statically linked libraries (also called archived libraries with file extension .a). Modern operating systems used shared libraries. The names of these files have filename extension of .dylib (dynamic libraries). Applications can have their own shared libraries. For example, the gcc compiler might keep its libraries in /usr/lib/gcc/i686-apple-darwin9/.

The Carbon API, used with C and C++, provides compatibility with Mac OS 9 and earlier. The Cocoa API, which is based on the OpenStep API, is used for native OS X development. The Cocoa API is used with Objetive-C. Cocoa classes have names starting with NS is stands for NeXT and SUN.

Mac OS X's UNIX API follows the conventions associated with BSD UNIX more often than System V UNIX. It is called the BSD API because it also offers some BSD extensions. The standard libraries and headers for the BSD environment reside in the directories /usr/lib and /usr/include respectively. Many header files in /usr/include are part of the System framework. However, the System framework directory neither contains or links to these headers since the C compiler searches in /usr/include by default. A typical OS X installation has more than 150 shard libraries in /usr/lib and more than 30 in /usr/X11R6/lib. For X11, OS X includes an optimized X Winder server (/usr/X11R6/bin/xquartz) along with a modern X Window environment. The Xquartz sits atop the native Core Graphics APIs, links to the native OS X event system.

The libc, the user-level standard C library, is also found in libSystem on Mac OS X. libSystem consists of several BSD libraries, some of which are independent libraries on a typical UNIX system. Normalcy is maintained by symbolically linking such libraries to libSystem, as is the case with libpoll. Some of externally visible libraries contained in libSystem:
  • libc - the standard C library (/usr/lib/libc.dylib on OS X 10.5)
  • libdbm - a database library (/usr/lib/libdbm.dylib on OS X 10.5)
  • libdl - a programming interface to the dynamically linking loader (/usr/lib/libdl.dylib on OS X 10.5. On OS X 10.3 and earlier, libdl is a wrapper library that emulates the POSIX dynamic linking loader API functions - - dlopen(), dlclose(), dlsym(), and dlerror() - on top of Darwin's native dyld API.)
  • libinfo - a library that provides various "info" APIs, such as DNS and NIS, and NetInfo (/usr/lib/libinfo.dylib on OS X 10.5)
  • libkvm - a library that provides a uniform interface for accessing kernel virtual memory images; used by programs such as ps (no libkvm is found in /usr/lib on OS X 10.5)
  • libm - the standard math library (/usr/lib/libm.dylib on OS X 10.5)
  • libpoll - a wrapper library that emulates the System V poll () system call on top of BSD's select () system call
  • libpthread - the POSIX thread library. On Mac, POSIX threads are implemented using Mach kernel threads, with one Mach thread per pthread.
  • librpcsvc - a miscellaneous "Sun" RPC services library

Some of internally available functionality in libSystem includes the following:
  • libdyldapis - provides a low level API to the dynamic link editor
  • libkeymgr - used for maintaining process-wide global data known to all threads across all dynamic libraries
  • liblaunch - provides an interface to launchd, the manager of system-wide and per-user daemons and agents
  • libmacho - provides an API for accessing segments and sections in Mach-O files
  • libnotify - allows applications to exchange events through namespace-based stateless notifications
  • libstreams - implements an I/O streams mechanism
  • libunc - allows creation, dispatch, and manipulation of user notifications
libSysetm also includes an object file containing the commpage symbols. The commpage area is a region of memory that is mapped (shared and read-only) into every process's address space. It contains frequently used system-wide code and data. The commpage symbols in libSystem are placed in a special segment (the _DATA segment within the _commpage section), which allows a debugger to access them.

The otool (object tool) utility with the -L option lists which shared libraries a program needs.
e.g.# otool -L /bin/cp

Dynamic libraries are searched for in DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH. Frameworks are search for in DYLD_FRAMEWORK_PATH and DYLD_FALLBACK_FRAMEWORK_PATH.

DYLD_LIBRARY_PATH is used in the script called wrappers to fix broken binaries.
Rename bb to bb.broken and create a /bin/sh wrapper named bb:

$cat bb
#! /bin/sh
DYLD_LIBRARY_PATH=/opt/bb/lib
export DYLD_LIBRARY_PATH
exec bb.broken "$@"

Trojan horse security issue
In this case, a malicious user can create a Trojan horse named libc.dylib and place it in a directory that is searched before /usr/lib by using DYLD_LIBRARY_PATH.