kernel: chroot, #! scripts, rename and mmap as apk needs them

Found by running Alpine's apk on SchOS, one failure at a time:

- chroot(2) was a stub returning EPERM. Each process now has a root:
  where an absolute path starts and where .. stops. Mounts remember
  whose root they were made under, and a walk leaves a mount by the way
  it came in, so one filesystem can be mounted twice.
- devtmpfs and proc mounted only on /dev and /proc, whatever the target;
  a chroot got "already mounted".
- mmap never reused freed address space, so musl's malloc used up the
  256 mapping records while 780 MB were free. A mergeable mapping now
  goes straight after an anonymous one whose end has room.
- unlinkat returned -1 (EPERM) where apk expects ENOENT, and renameat
  was an old copy of rename: no replacing the target, and v1 dirents
  written into SchFS. Both now share rename's implementation.
- execve runs #! scripts, and says ENOEXEC for what it cannot run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-24 15:28:32 +02:00
commit 2cfa3f0bf2
9 changed files with 361 additions and 129 deletions

View file

@ -615,16 +615,16 @@ const struct fs_ops procfs_ops = {
// so they are unreachable and harmless. Removing them from init is a separate,
// later cleanup -- doing both at once would make a boot failure ambiguous
// between "the mount is wrong" and "the nodes are missing".
void
procfs_mount(void)
int
procfs_mount(const char *target)
{
struct inode *dp = namei("/proc");
struct inode *dp = namei((char *)target);
int r;
if (dp == 0) {
cprintf("procfs: /proc does not exist; not mounted\n");
return;
}
if (mount_add(dp->dev, dp->inum, PROCFS_DEV, PROCFS_ROOT, "/proc", "proc", "proc") < 0)
cprintf("procfs: /proc already has something mounted on it\n");
if (dp == 0)
return -ENOENT;
r = mount_add(dp->dev, dp->inum, PROCFS_DEV, PROCFS_ROOT, (char *)target,
"proc", "proc");
iput(dp);
return r < 0 ? -EBUSY : 0;
}