Skip to content

Commit 86232e2

Browse files
0.15.1: an image built for a processor this machine lacks is not a program (EBADARCH, EBADMACHO), as ENOEXEC is
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent f4dc428 commit 86232e2

2 files changed

Lines changed: 84 additions & 1 deletion

File tree

‎src/sys.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ enum : int {
270270
e_inval = 22, e_nfile = 23, e_mfile = 24, e_notty = 25, e_fbig = 27,
271271
e_nospc = 28, e_spipe = 29, e_rofs = 30, e_pipe = 32, e_range = 34,
272272
e_nametoolong = 63, e_nosys = 78, e_notempty = 66, e_loop = 62,
273+
// A file this machine cannot start: built for another processor, or not
274+
// an image this loader reads.
275+
e_badarch = 86, e_badmacho = 88,
273276
// This system has two values for an operation the object does not support,
274277
// and they are different numbers: 45 is the one a call upon a resource of
275278
// the wrong kind returns, and 102 is the one a socket returns.
@@ -341,7 +344,7 @@ inline int translate(okm_long r) {
341344
case e_notempty: return 11; // not empty
342345
case e_isdir: return 12; // is directory
343346
case e_notdir: return 13; // not directory
344-
case e_noexec: return 14; // not program
347+
case e_noexec: case e_badarch: case e_badmacho: return 14; // not program
345348
default: return 3; // io
346349
}
347350
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// A file this machine cannot start is "not a program" (kal_err_not_program),
2+
// whichever of this kernel's values says so (0.15.1): ENOEXEC for a file that
3+
// is no image, EBADARCH for an image built for a processor this machine does
4+
// not have. Before, only ENOEXEC was translated, and an image of another
5+
// processor --- the case a runner asks about --- arrived as an input/output
6+
// error.
7+
//
8+
// The foreign image is a Mach-O header naming a processor that does not exist;
9+
// the kernel refuses it by its header before reading anything else.
10+
#include <cstdio>
11+
#include <cstring>
12+
#include <fcntl.h>
13+
#include <unistd.h>
14+
import openkal.types;
15+
import openkal.fs;
16+
import openkal.process;
17+
18+
namespace {
19+
int failures = 0;
20+
void check(bool held, const char* what) {
21+
if (!held) { std::printf("FAIL: %s\n", what); ++failures; }
22+
}
23+
24+
kal_dir root() {
25+
for (kal_uintptr i = 0; i < kal_fs_preopen_count(); ++i) {
26+
kal_dir d{}; char n[8]; kal_uintptr l = 0;
27+
if (kal_fs_preopen(i, &d, n, sizeof n, &l) == kal_ok && l == 1 && n[0] == '/') return d;
28+
}
29+
return kal_dir{};
30+
}
31+
32+
// The refusal a start of `path' (absolute) meets.
33+
int start(const char* path) {
34+
const kal_dir r = root();
35+
const char* argv[] = { path };
36+
const kal_uintptr lens[] = { std::strlen(path) };
37+
const kal_spawn how{ r, r, nullptr, nullptr, 0, 0 };
38+
kal_process p{};
39+
const int e = kal_process_spawn(&how, path + 1, std::strlen(path + 1), argv, lens, 1,
40+
nullptr, nullptr, 0, nullptr, &p);
41+
if (e == kal_ok) {
42+
int status = 0, terminated = 0;
43+
kal_process_wait(p, &status, &terminated);
44+
}
45+
return e;
46+
}
47+
48+
// A file of `bytes', executable, at a fresh name under /tmp.
49+
bool place(char* path, const unsigned char* bytes, std::size_t n) {
50+
const int fd = ::mkstemp(path);
51+
if (fd < 0) return false;
52+
const bool written = ::write(fd, bytes, n) == static_cast<ssize_t>(n);
53+
::fchmod(fd, 0755);
54+
::close(fd);
55+
return written;
56+
}
57+
} // namespace
58+
59+
int main() {
60+
// mach_header_64: magic, a processor type no machine has, a subtype, MH_EXECUTE.
61+
const unsigned char foreign[32] = {
62+
0xcf, 0xfa, 0xed, 0xfe, 0x45, 0x23, 0x01, 0x00,
63+
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
64+
};
65+
char image[] = "/tmp/okm-foreign-XXXXXX";
66+
check(place(image, foreign, sizeof foreign), "a foreign image is written");
67+
check(start(image) == kal_err_not_program, "an image of a processor this machine lacks is not a program");
68+
::unlink(image);
69+
70+
const unsigned char text[] = { 'n', 'o', 't', ' ', 'a', 'n', ' ', 'i', 'm', 'a', 'g', 'e', '\n' };
71+
char plain[] = "/tmp/okm-plain-XXXXXX";
72+
check(place(plain, text, sizeof text), "a file of text is written");
73+
const int e = start(plain);
74+
// A file with no `#!' and no image header: the kernel's ENOEXEC.
75+
check(e == kal_err_not_program, "a file that is no image is not a program");
76+
::unlink(plain);
77+
78+
if (failures == 0) std::printf("openkal-macos: a file this machine cannot start is not a program\n");
79+
return failures == 0 ? 0 : 1;
80+
}

0 commit comments

Comments
 (0)