summaryrefslogtreecommitdiff
path: root/docs/vfs.org
blob: 7312851185b7dae6de7fc907b602e3d68a2374e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#+title: The VFS
* intro
  In Camellia, all resources will be accessed through the VFS. This doesn't only include "normal" files, but also networking, hardware, the kernel state - pretty much everything. This probably sounds like plan9, but there's one important difference - there's no way to elevate your privileges. If a program doesn't have access to e.g. your ~, it will never have it. Thus, it can be used for access control / privilege separation. Also, this means that every part of the VFS can be emulated - so you won't ever need Camellia VMs on a Camellia host.
** goals
*** simple "broad" access control
    For example: if you want a program to only access the internet over port 80, you can just only expose ~/net/80~ in its namespace. If you want to prevent a program from accessing your ssh keys, you can mount a null fs over ~~/.ssh~.
*** simple fine-grained access control
    Since filesystems are handled in userspace, you can overlay any part of the filesystem with something which restricts access to resources based on some advanced criteria. For example, you could mount a program over ~/net/80~ which scans packets and disallows using HTTP proxies.
*** be the only abstraction for accessing resources / access control
    I don't really know how to explain this well (TODO). In short: the less shit there is to manage, the easier it is to manage.
* operations
** mounting
   ~void mount(path_t path, fd_t fd);~
   
   Mounts ~fd~ over ~path~ (~path~ doesn't have to be a real directory/file!). The files previously accessible under ~path~ won't ever be accessible anymore to the process or any of its children. If the ~fd~ refers to a file/directory, a bind mount is created. The bind mount is a copy of the original mount, so it will persist even if the latter is gone. This means that you can e.g. mount a directory over ~/~ and it will work like a chroot.
** creating filesystems
   ~fd_t fs_create(fs_handle_t *);~
   ~void fs_destroy(fs_handle_t *);~
   
   ~void fs_wait(fs_handle_t, fs_call_t *info);~
   Waits for a filesystem request, the details of which will be put in ~info~.
   
   ~void fs_respond(fs_call_t *info);~
   Responds to a filesystem request.
*** TODO more details
*** example
    #+begin_src C
struct fs_call call;
fs_handle_t myfs_back;
fd_t myfs_front;

myfs_front = fs_create(&myfs_back);
mount("/some/where", myfs_front);

for (;;) {
	fs_wait(myfs_back, &call);
	switch (call.type) {
		case FS_CLEANUP:
			break;
		default:
			call.error = ENOTIMPLEMENTED;
	}
	fs_respond(&call);
}
    #+end_src
** file IO
   ~fd_t open(path_t path);~
   
   Find the last filesystem mounted which is a prefix of ~path~, and passes the ~open()~ call to it, stripping its prefix in the process. If the call succeeds, you get a file descriptor which you can ~read()~, ~write()~, ~close()~, you get the idea.
* considerations
** ~path_t~ preprocessing
   The path format will need to be restricted to prevent programs from bypassing mounts. The current idea is to disallow empty directory names (e.g. ~//~), and to resolve ~.~ and ~..~ before resolving mounts.