Hello everyone,
I am trying to make subhurd run without root's permission.
AFAIK, the reason that subhurd needs the root's permission is that the
subhurd needs the master device port and privileged host port, and the
current implementation gets the real ones from mach.
It's relatively easy to handle the master device port and boot has
already done part of the work (it gives the subhurd a pseudo master
device port and acts as a device proxy itself). The device proxy can
access some real devices with the help of other translators. As long
as the user has the permission to access the device file, it should
work fine.
However, the same method cannot apply to the privileged host port.
As I understand, the privileged host port is used to communicate with
the kernel and manipulate the host. Again I can give the subhurd a
pseudo one, create a host proxy, and implement the server side of RPC.
The RPCs directly involved to the privileged host port are:
routine vm_set_default_memory_manager(
host_priv : host_priv_t;
inout default_manager : mach_port_make_send_t);
hurd/boot/boot.c <<main>>
hurd/libdiskfs/init-init.c <<diskfs_init_diskfs>>
hurd/mach-defpager/main.c <<main>>
hurd/serverboot/default_pager.c <<default_pager_initialize>>
hurd/sutils/swapon.c <<swaponoff>>
hurd/tmpfs/tmpfs.c <<main>>
hurd/trans/proxy-defpager.c <<main>>
hurd/utils/vmstat.c <<ensure_def_pager_info>>
routine host_adjust_time(
host_priv : host_priv_t;
in new_adjustment : time_value_t;
out old_adjustment : time_value_t);
routine host_get_boot_info(
host_priv : host_priv_t;
out boot_info : kernel_boot_info_t);
routine host_reboot(
host_priv : host_priv_t;
options : int);
hurd/init/init.c
hurd/serverboot/bootstrap.c
hurd/serverboot/panic.c
routine host_set_time(
host_priv : host_priv_t;
new_time : time_value_t);
routine host_processors(
host_priv : host_priv_t;
out processor_list : processor_array_t);
routine host_processor_set_priv(
host_priv : host_priv_t;
set_name : processor_set_name_t;
out set : processor_set_t);
hurd/proc/main.c,
hurd/proc/mgt.c
routine vm_wire(
host_priv : host_priv_t;
task : vm_task_t;
address : vm_address_t;
size : vm_size_t;
access : vm_prot_t);
hurd/libshouldbeinlibc/wire.c
hurd/serverboot/wiring.c
routine thread_wire(
host_priv : host_priv_t;
thread : thread_t;
wired : boolean_t);
hurd/serverboot/wiring.c
I list all routines and the place where they are called in Hurd below
them.
Note: several of them are not used by Hurd.
The problem here is host_processor_set_priv, which converts a
processor set name port to a control port.
proc gets the control port with host_processor_set_priv, but instead
of calling an RPC to this port, it calls an RPC to its thread port and
uses this port as a parameter, so the host proxy cannot get the RPC.
The host proxy cannot return a real control port, either, because it
doesn't has the root permission. The code in proc/main.c (shown below)
will fail for sure:
err = host_processor_set_priv (master_host_port, pset, &psetcntl);
assert_perror (err);
thread_max_priority (mach_thread_self (), psetcntl, 0);
assert_perror (err);
err = task_priority (mach_task_self (), 2, 1);
assert_perror (err);
A simple solution might be to modify the code of proc since it is the
only place having this problem.
For a long run, it might not be a good idea. It might limit the
ability of subhurd and I don't know if more similar code will be used
in the future Hurd.
The other solution is to give pseudo task ports and thread ports to
the subhurd, so boot can receive all RPCs from subhurd (which should
go to the kernel). Now boot can get the full control of subhurd (it
might give subhurd more features even though I don't know yet). The
problem I mentioned above can be solved easily. However, this solution
needs more work and makes the things more complicated. I wonder if it
is worth the work.
The more important question is how to give pseudo task ports and
thread ports.
mach_thread_self () and mach_task_self () are system trap.
Maybe I can modify the implementation of mach_thread_self () and
mach_task_self () in glibc and use an RPC to ask boot for the ports,
but then every task has to know the port to boot. It needs much work
and seems quite ugly.