ref: c2297ce5c180e98f2217a691a25d19a300956d9f
parent: d168b89ab110a2d1fcaf72ad085a789092b82b00
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat May 29 10:18:35 EDT 2021
kernel: use 64-bit virtual entry point for expanded header, document behaviour in a.out(6) For 64-bit architectures, the a.out header has the HDR_MAGIC flag set in the magic and is expanded by 8 bytes containing the 64-bit virtual address of the programs entry point. While Exec.entry contains physical address for kernel images. Our sysexec() would always use Exec.entry, even for 64-bit a.out binaries, which worked because PADDR(entry) == entry for userspace pointers. This change fixes it, having the kernel use the 64-bit entry point and document the behaviour in the manpage.
--- a/sys/man/6/a.out
+++ b/sys/man/6/a.out
@@ -25,7 +25,7 @@
long pcsz; /* size of pc/line number table */
} Exec;
-#define HDR_MAGIC 0x00008000
+#define HDR_MAGIC 0x00008000 /* header expansion */
#define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7))
#define A_MAGIC _MAGIC(0, 8) /* 68020 */
@@ -62,7 +62,18 @@
bytes of the binary file.
The
.B entry
-field gives the virtual address of the entry point of the program.
+field gives the virtual address of the entry point of the program
+unless
+.B HDR_MAGIC
+flag is present in the
+.B magic
+field.
+In that case, the header is expanded
+by 8 bytes containing the 64-bit virtual address of the
+program entry point and the 32-bit
+.B entry
+field is reserved for physical kernel entry point.
+.PP
The data segment starts at the first page-rounded virtual address
after the text segment.
It consists of the next
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -10,6 +10,8 @@
int anyhigher(void);
int anyready(void);
Image* attachimage(int, Chan*, uintptr, ulong);
+ulong beswal(ulong);
+uvlong beswav(uvlong);
int blocklen(Block*);
void bootlinks(void);
void cachedel(Image*, uintptr);
--- a/sys/src/9/port/rebootcmd.c
+++ b/sys/src/9/port/rebootcmd.c
@@ -6,16 +6,6 @@
#include "../port/error.h"
#include "a.out.h"
-static ulong
-l2be(long l)
-{
- uchar *cp;
-
- cp = (uchar*)&l;
- return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
-}
-
-
static void
readn(Chan *c, void *vp, long n)
{
@@ -35,8 +25,11 @@
void
rebootcmd(int argc, char *argv[])
{
+ struct {
+ Exec;
+ uvlong hdr[1];
+ } ehdr;
Chan *c;
- Exec exec;
ulong magic, text, rtext, entry, data, size, align;
uchar *p;
@@ -49,11 +42,11 @@
nexterror();
}
- readn(c, &exec, sizeof(Exec));
- magic = l2be(exec.magic);
- entry = l2be(exec.entry);
- text = l2be(exec.text);
- data = l2be(exec.data);
+ readn(c, &ehdr, sizeof(Exec));
+ magic = beswal(ehdr.magic);
+ entry = beswal(ehdr.entry);
+ text = beswal(ehdr.text);
+ data = beswal(ehdr.data);
if(!(magic == AOUT_MAGIC)){
switch(magic){
@@ -66,7 +59,7 @@
}
}
if(magic & HDR_MAGIC)
- readn(c, &exec, 8);
+ readn(c, ehdr.hdr, sizeof(ehdr.hdr));
switch(magic){
case R_MAGIC:
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -234,6 +234,8 @@
{
int i;
+ if(n <= 2 || s[0] != '#' || s[1] != '!')
+ return -1;
s += 2;
n -= 2; /* skip #! */
for(i=0;; i++){
@@ -261,20 +263,35 @@
return i;
}
-static ulong
-l2be(long l)
+ulong
+beswal(ulong l)
{
- uchar *cp;
+ uchar *p;
- cp = (uchar*)&l;
- return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
+ p = (uchar*)&l;
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
+uvlong
+beswav(uvlong v)
+{
+ uchar *p;
+
+ p = (uchar*)&v;
+ return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
+ | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
+ | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
+ | (uvlong)p[7];
+}
+
uintptr
sysexec(va_list list)
{
- Exec exec;
- char line[sizeof(Exec)];
+ struct {
+ Exec;
+ uvlong hdr[1];
+ } ehdr;
+ char line[sizeof(ehdr)];
char *progarg[sizeof(line)/2+1];
volatile char *args, *elem, *file0;
char **argv, **argp, **argp0;
@@ -281,7 +298,7 @@
char *a, *e, *charp, *file;
int i, n, indir;
ulong magic, ssize, nargs, nbytes;
- uintptr t, d, b, entry, bssend, text, data, bss, tstk, align;
+ uintptr t, d, b, entry, text, data, bss, bssend, tstk, align;
Segment *s, *ts;
Image *img;
Tos *tos;
@@ -311,7 +328,7 @@
}
nexterror();
}
- align = BY2PG;
+ align = BY2PG-1;
indir = 0;
file = file0;
for(;;){
@@ -323,39 +340,47 @@
if(!indir)
kstrdup(&elem, up->genbuf);
- n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
- if(n <= 2)
- error(Ebadexec);
- magic = l2be(exec.magic);
- if(n == sizeof(Exec) && (magic == AOUT_MAGIC)){
- entry = l2be(exec.entry);
- text = l2be(exec.text);
- if(magic & HDR_MAGIC)
- text += 8;
- switch(magic){
- case S_MAGIC: /* 2MB segment alignment for amd64 */
- align = 0x200000;
- break;
- case V_MAGIC: /* 16K segment alignment for mips */
- align = 0x4000;
- break;
- case R_MAGIC: /* 64K segment alignment for arm64 */
- align = 0x10000;
- break;
+ n = devtab[tc->type]->read(tc, &ehdr, sizeof(ehdr), 0);
+ if(n >= sizeof(Exec)) {
+ magic = beswal(ehdr.magic);
+ if(magic == AOUT_MAGIC) {
+ if(magic & HDR_MAGIC) {
+ if(n < sizeof(ehdr))
+ error(Ebadexec);
+ entry = beswav(ehdr.hdr[0]);
+ text = UTZERO+sizeof(ehdr);
+ } else {
+ entry = beswal(ehdr.entry);
+ text = UTZERO+sizeof(Exec);
+ }
+ if(entry < text)
+ error(Ebadexec);
+ text += beswal(ehdr.text);
+ if(text <= entry || text >= (USTKTOP-USTKSIZE))
+ error(Ebadexec);
+
+ switch(magic){
+ case S_MAGIC: /* 2MB segment alignment for amd64 */
+ align = 0x1fffff;
+ break;
+ case V_MAGIC: /* 16K segment alignment for mips */
+ align = 0x3fff;
+ break;
+ case R_MAGIC: /* 64K segment alignment for arm64 */
+ align = 0xffff;
+ break;
+ }
+ break; /* for binary */
}
- if(text >= (USTKTOP-USTKSIZE)-(UTZERO+sizeof(Exec))
- || entry < UTZERO+sizeof(Exec)
- || entry >= UTZERO+sizeof(Exec)+text)
- error(Ebadexec);
- break; /* for binary */
}
+ if(indir++)
+ error(Ebadexec);
+
/*
* Process #! /bin/sh args ...
*/
- memmove(line, &exec, n);
- if(line[0]!='#' || line[1]!='!' || indir++)
- error(Ebadexec);
+ memmove(line, &ehdr, n);
n = shargs(line, n, progarg);
if(n < 1)
error(Ebadexec);
@@ -371,10 +396,10 @@
cclose(tc);
}
- data = l2be(exec.data);
- bss = l2be(exec.bss);
- align--;
- t = (UTZERO+sizeof(Exec)+text+align) & ~align;
+ t = (text+align) & ~align;
+ text -= UTZERO;
+ data = beswal(ehdr.data);
+ bss = beswal(ehdr.bss);
align = BY2PG-1;
d = (t + data + align) & ~align;
bssend = t + data + bss;
@@ -518,7 +543,7 @@
up->seg[TSEG] = ts;
ts->flushme = 1;
ts->fstart = 0;
- ts->flen = sizeof(Exec)+text;
+ ts->flen = text;
unlock(img);
/* Data. Shared. */