summaryrefslogtreecommitdiff
path: root/src/kernel/vfs
diff options
context:
space:
mode:
authordzwdz2023-06-04 20:43:51 +0200
committerdzwdz2023-06-04 20:43:51 +0200
commit78cb60b644538a33e0479f25393d6c861e3605f8 (patch)
tree15d310b2bba5cce086633c025080155ca36e7c43 /src/kernel/vfs
parent8fd4943b2721696f86783d22dd2e8d593a22a766 (diff)
kernel: rework /proc/ and process IDs
I'm yet to write proper docs but the TL;DR is: Mounting /proc/ creates a new pid namespace. You're still visible in the old namespace with your old pid, but your children won't be. You see your own pid as 1. Current pids of children will be preserved, pids will be allocated starting from the highest one of your children.
Diffstat (limited to 'src/kernel/vfs')
-rw-r--r--src/kernel/vfs/procfs.c95
1 files changed, 54 insertions, 41 deletions
diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c
index 4f2bbd1..7669b78 100644
--- a/src/kernel/vfs/procfs.c
+++ b/src/kernel/vfs/procfs.c
@@ -7,6 +7,7 @@
#include <shared/mem.h>
enum phandle_type {
+ PhRoot,
PhDir,
PhIntr,
PhMem,
@@ -24,48 +25,52 @@ static void procfs_cleanup(VfsBackend *be);
static int isdigit(int c);
static struct phandle *
-openpath(const char *path, size_t len, Proc *p)
+openpath(const char *path, size_t len, Proc *root)
{
struct phandle *h;
enum phandle_type type;
+ uint32_t gid = 0;
if (len == 0) return NULL;
path++, len--;
- while (len && isdigit(*path)) {
- /* parse numerical segment / "directory" name */
- uint32_t cid = 0;
+ if (len == 0) {
+ type = PhRoot;
+ } else if (isdigit(*path)) {
+ Proc *p;
+ uint32_t lid = 0;
for (; 0 < len && *path != '/'; path++, len--) {
- char c = *path;
- if (!isdigit(c)) {
+ if (!isdigit(*path)) {
return NULL;
}
- cid = cid * 10 + *path - '0';
+ lid = lid * 10 + *path - '0';
+ }
+ if (len == 0) {
+ return NULL;
}
- if (len == 0) return NULL;
assert(*path == '/');
path++, len--;
- p = p->child;
- if (!p) return NULL;
- while (p->cid != cid) {
- p = p->sibling;
- if (!p) return NULL;
+ if (len == 0) {
+ type = PhDir;
+ } else if (len == 4 && memcmp(path, "intr", 4) == 0) {
+ type = PhIntr;
+ } else if (len == 3 && memcmp(path, "mem", 3) == 0) {
+ type = PhMem;
+ } else {
+ return NULL;
}
- }
- /* parse the per-process part */
- if (len == 0) {
- type = PhDir;
- } else if (len == 4 && memcmp(path, "intr", 4) == 0) {
- type = PhIntr;
- } else if (len == 3 && memcmp(path, "mem", 3) == 0) {
- type = PhMem;
+ p = proc_ns_byid(root, lid);
+ if (!p) {
+ return NULL;
+ }
+ gid = p->globalid;
} else {
return NULL;
}
h = kmalloc(sizeof *h);
- h->gid = p->globalid;
+ h->gid = gid;
h->type = type;
return h;
}
@@ -87,36 +92,47 @@ procfs_accept(VfsReq *req)
Proc *p;
char buf[512];
assert(root);
+ assert(root->pns == root);
+
if (req->type == VFSOP_OPEN) {
assert(req->input.kern);
h = openpath(req->input.buf_kern, req->input.len, root);
vfsreq_finish_short(req, h ? (long)h : -ENOENT);
return;
- }
- assert(h);
- p = findgid(h->gid, root);
- if (!p) {
- vfsreq_finish_short(req, -EGENERIC);
+ } else if (req->type == VFSOP_CLOSE) {
+ assert(h);
+ kfree(h);
+ vfsreq_finish_short(req, 0);
return;
+ } else {
+ assert(h);
}
- if (req->type == VFSOP_READ && h->type == PhDir) {
+ if (h->type != PhRoot) {
+ p = findgid(h->gid, root);
+ if (!p) {
+ vfsreq_finish_short(req, -ENOENT);
+ return;
+ }
+ }
+
+ if (req->type == VFSOP_READ && (h->type == PhDir || h->type == PhRoot)) {
// TODO port dirbuild to kernel
int pos = 0;
if (req->offset != 0) {
vfsreq_finish_short(req, -ENOSYS);
return;
}
- pos += snprintf(buf + pos, 512 - pos, "intr")+1;
- pos += snprintf(buf + pos, 512 - pos, "mem")+1;
- for (Proc *iter = p->child; iter; iter = iter->sibling) {
- assert(pos < 512);
- // processes could possibly be identified by unique identifiers instead
- // e.g. an encrypted gid, or just a randomly generated one
- // con: would require bringing in a crypto library
- pos += snprintf(buf + pos, 512 - pos, "%d/", iter->cid) + 1;
- if (512 <= pos) {
- vfsreq_finish_short(req, -1);
+ if (h->type == PhDir) {
+ pos += snprintf(buf + pos, 512 - pos, "intr")+1;
+ pos += snprintf(buf + pos, 512 - pos, "mem")+1;
+ } else {
+ for (Proc *it = root; it; it = proc_ns_next(root, it)) {
+ assert(pos < 512);
+ pos += snprintf(buf + pos, 512 - pos, "%d/", proc_ns_id(root, it)) + 1;
+ if (512 <= pos) {
+ vfsreq_finish_short(req, -EGENERIC);
+ }
}
}
assert(0 <= pos && (size_t)pos <= sizeof buf);
@@ -136,9 +152,6 @@ procfs_accept(VfsReq *req)
} else if (req->type == VFSOP_WRITE && h->type == PhIntr) {
proc_intr(p);
vfsreq_finish_short(req, req->input.len);
- } else if (req->type == VFSOP_CLOSE) {
- kfree(h);
- vfsreq_finish_short(req, 0);
} else {
vfsreq_finish_short(req, -ENOSYS);
}