Skip to content

Commit 280623b

Browse files
0.24.0 --- openkal 0.23: a region at an address, MAP_FIXED_NOREPLACE; a name with every link followed, O_PATH and /proc/self/fd
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent e146e78 commit 280623b

4 files changed

Lines changed: 82 additions & 6 deletions

File tree

‎README.md‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ for Linux, written on the kernel's own system-call interface.
55

66
```toml
77
[dependencies]
8-
openkal = "0.22.0"
8+
openkal = "0.23.0"
99

1010
[target.'cfg(os = "linux")'.dependencies]
11-
openkal-linux = "0.23.0"
11+
openkal-linux = "0.24.0"
1212
```
1313

1414
## Why it does not use a C library
@@ -102,6 +102,13 @@ A program that carries a runtime of its own answers from that runtime instead
102102
(`pthread_getattr_np`), because in that arrangement the runtime is what owns the
103103
stacks and is what a program above openkal would ask for itself.
104104

105+
## What 0.24 adds (openkal 0.23)
106+
107+
**A region at an address.** `kal_exec_alloc_at` maps the region with
108+
`MAP_FIXED_NOREPLACE`, which refuses rather than replaces what is there; a kernel
109+
before 4.17 reads the flag as a hint, so a mapping placed elsewhere is released
110+
and the request refused. `KAL_EXEC_PROP_PLACE` is claimed.
111+
105112
## What 0.23 adds (openkal 0.22)
106113

107114
**The null device at a position.** `KAL_SPAWN_NULL_IN`, `KAL_SPAWN_NULL_OUT` and

‎mcpp.toml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
namespace = "mcpplibs"
33
name = "openkal-linux"
4-
version = "0.23.0"
4+
version = "0.24.0"
55
description = "The reference implementation of openkal for Linux, written on the kernel's own system-call interface so that it can be placed beneath a C library as well as above one."
66
license = "Apache-2.0"
77

@@ -65,7 +65,7 @@ provides-interfaces = [
6565
]
6666

6767
[dependencies]
68-
openkal = "0.22.0"
68+
openkal = "0.23.0"
6969

7070
# The package contributes definitions and no modules. The interface it
7171
# implements is declared by the specification package, which this package

‎src/exec.cpp‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,26 @@ void* kal_exec_alloc(kal_uintptr size) {
5151
return reinterpret_cast<void*>(r);
5252
}
5353

54+
// AT AN ADDRESS (0.23): MAP_FIXED_NOREPLACE, which refuses rather than replaces
55+
// what is there. A kernel before 4.17 does not know the flag and reads the
56+
// address as a hint, so the answer is compared and a mapping placed elsewhere
57+
// released: the address is either given or refused, never approximated.
58+
void* kal_exec_alloc_at(void* at, kal_uintptr size) {
59+
const okl_uptr where = reinterpret_cast<okl_uptr>(at);
60+
if (size == 0 || where == 0 || (where & (page() - 1)) != 0) return nullptr;
61+
const okl_uptr bytes = round_up(static_cast<okl_uptr>(size), page());
62+
const okl_long r = okl::sys(okl::nr_mmap, static_cast<okl_long>(where), static_cast<okl_long>(bytes),
63+
okl::prot_read | okl::prot_write,
64+
okl::map_private | okl::map_anonymous | 0x100000 /* MAP_FIXED_NOREPLACE */,
65+
-1, 0);
66+
if (okl::failed(r)) return nullptr;
67+
if (static_cast<okl_uptr>(r) != where) {
68+
okl::sys(okl::nr_munmap, r, static_cast<okl_long>(bytes));
69+
return nullptr;
70+
}
71+
return at;
72+
}
73+
5474
int kal_exec_publish(void* p, kal_uintptr size) {
5575
if (p == nullptr || size == 0) return kal_err_invalid;
5676
const okl_uptr bytes = round_up(static_cast<okl_uptr>(size), page());
@@ -163,7 +183,7 @@ void kal_exec_free(void* p, kal_uintptr size) {
163183
kal_uintptr kal_exec_props(void) {
164184
// Executable memory is available to every artifact on this kernel: nothing
165185
// here is granted only to a program produced in a particular way.
166-
return KAL_EXEC_PROP_REPUBLISH | KAL_EXEC_PROP_AVAILABLE | KAL_EXEC_PROP_FILE;
186+
return KAL_EXEC_PROP_REPUBLISH | KAL_EXEC_PROP_AVAILABLE | KAL_EXEC_PROP_FILE | KAL_EXEC_PROP_PLACE;
167187
}
168188

169189
} // extern "C"

‎src/fs.cpp‎

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,8 +825,24 @@ int kal_fs_list_next(kal_dir d, kal_uintptr* iter,
825825
// filesystem it mounts, and `renameat' within one directory is atomic by POSIX.
826826
// Case sensitivity and links are claimed only where the format is known to have
827827
// them.
828+
// WHETHER THE KERNEL NAMES A DESCRIPTOR (/proc/self/fd), which a name with
829+
// every link followed is read from (0.23). Asked once: /proc is mounted for the
830+
// process or it is not, whatever the volume.
831+
static bool descriptor_names() {
832+
static int known = -1;
833+
if (known < 0) {
834+
char b[8];
835+
known = okl::failed(okl::sys(okl::nr_readlinkat, okl::at_fdcwd,
836+
reinterpret_cast<okl_long>("/proc/self/cwd"),
837+
reinterpret_cast<okl_long>(b), static_cast<okl_long>(sizeof b))) ? 0 : 1;
838+
}
839+
return known == 1;
840+
}
841+
828842
kal_uintptr kal_fs_props(kal_dir d) {
829-
return volume_props(okl::unpack(d.h));
843+
const int fd = okl::unpack(d.h);
844+
if (fd < 0) return 0;
845+
return volume_props(fd) | (descriptor_names() ? KAL_FS_PROP_RESOLVED_NAME : 0u);
830846
}
831847

832848
// --- exclusion upon a range of a file --------------------------------------
@@ -938,6 +954,39 @@ int kal_fs_link_create(kal_dir base, const char* name, kal_uintptr len,
938954
return okl::failed(r) ? okl::translate(r) : kal_ok;
939955
}
940956

957+
// THE NAME WITH EVERY LINK FOLLOWED (0.23): the node opened for its path alone
958+
// (O_PATH, which needs no permission upon it and follows every link), and the
959+
// kernel's record of that descriptor's name read, as this system's own C
960+
// library answers `realpath' of an open file. Two calls and a close, where a
961+
// walk asks about every component of the name.
962+
kal_intptr kal_fs_resolved_name(kal_dir base, const char* name, kal_uintptr len,
963+
char* out, kal_uintptr cap) {
964+
const int b = okl::unpack(base.h);
965+
if (b < 0 || !okl::acceptable(name, len)) return -kal_err_invalid;
966+
if (!descriptor_names()) return -kal_err_not_supported;
967+
okl::terminated t(name, len); if (!t.ok) return -kal_err_invalid;
968+
const okl_long fd = okl::sys(okl::nr_openat, b, reinterpret_cast<okl_long>(t.buf),
969+
okl::o_path | okl::o_cloexec, 0);
970+
if (okl::failed(fd)) return -okl::translate(fd);
971+
char link[32] = "/proc/self/fd/";
972+
{
973+
okl_uptr at = 14;
974+
char digits[20]; int n = 0;
975+
okl_ulong v = static_cast<okl_ulong>(fd);
976+
do { digits[n++] = static_cast<char>('0' + v % 10); v /= 10; } while (v);
977+
while (n) link[at++] = digits[--n];
978+
link[at] = '\0';
979+
}
980+
char own[2 * okl::max_name + 2];
981+
const okl_long r = okl::sys(okl::nr_readlinkat, okl::at_fdcwd, reinterpret_cast<okl_long>(link),
982+
reinterpret_cast<okl_long>(own), static_cast<okl_long>(sizeof own));
983+
okl::sys(okl::nr_close, fd);
984+
if (okl::failed(r)) return -okl::translate(r);
985+
if (out != nullptr)
986+
for (okl_long i = 0; i < r && static_cast<okl_uptr>(i) < cap; ++i) out[i] = own[i];
987+
return static_cast<kal_intptr>(r);
988+
}
989+
941990
kal_intptr kal_fs_link_read(kal_dir base, const char* name, kal_uintptr len,
942991
char* out, kal_uintptr cap) {
943992
const int b = okl::unpack(base.h);

0 commit comments

Comments
 (0)