bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: looking for the solution of rootless subhurd


From: Da Zheng
Subject: Re: looking for the solution of rootless subhurd
Date: Tue, 09 Dec 2008 00:30:08 +0000
User-agent: Thunderbird 2.0.0.18 (Macintosh/20081105)

Hello everyone,

Da Zheng wrote:
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.
I created a proxy for all RPCs on the master host port, modified the code of proc so that proc can ignore the error of task_priority (the problem in proc as I mention in my previous letter).
However, there is still a problem in proc:
The function add_tasks (proc/mgt.c) gets all tasks in the host by calling host_processor_sets(), host_processor_set_priv() and processor_set_tasks() because the process server needs to check if the port is a task port or not. Obviously, the process server in the subhurd cannot get all tasks in the host. Instead, it should only get the tasks that belong to the subhurd.
I am thinking of a way to trace tasks in subhurd.

One way I can think of is that boot creates a proxy for the RPC task_create. As a result, boot needs to create pseudo task ports for all tasks in subhurd and run as a proxy for all RPCs on the task port. Extra RPCs are needed for the tasks to get the pseudo task ports, and mach_task_self() in glibc need to be modified.

This solution should be powerful enough (it can solve all problems I have got so far) as long as all programs in subhurd uses the modified mach_task_self() in glibc.
But it has two drawback:
1. There isn't an effective way to prevent the programs in subhurd calling the system trap mach_task_self(). If the program does use the system trap, it might not have the right behavior, but at least it doesn't harm the tasks in main Hurd and other subhurds. 2. It seems a bit heavy. Almost all of RPCs to the kernel are redirected to the boot.

Anyone has comments for the solution I suggested above?
I hope there is an easier way in Mach/Hurd to trace tasks.

Best regards,
Zheng Da




reply via email to

[Prev in Thread] Current Thread [Next in Thread]