Hi, On Sat, Dec 13, 2008 at 03:55:26PM +0000, Da Zheng wrote: > olafbuddenha...@gmx.net wrote: >> On Tue, Dec 09, 2008 at 12:30:08AM +0000, Da Zheng wrote:
>>> 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. >>> >> >> I don't understand. >> > Actually, I wanted you to read the code in add_tasks() yourself > because I didn't think I could explain it well:-). Well, saying so explicitely tends to work better :-) It seems to me that the code is actually easy to explain... But you are right: It's even easier to read up myself :-) It's the RPC names that confused me -- they are not really self-explaning... > The point here is that the process server needs to get all tasks in > the host, Yes, obviously it needs to. I understand your concern now, but I still don't see an actual problem... Note that the implementation of the pseudo master host port does not need to forward the RPCs directly to Mach. (In fact, it can't even do that, as it lacks the necessary privileges...) It can simply ask the main Hurd's proc server instead. I would hope that the proc server also has the necessary information to find out which tasks belong to the subhurd -- though I don't know for sure... > I believe it can cause a serious security problem if the subhurd can > see all tasks in the host and every user can create his own subhurd. > If a subhurd can see a task, it means it can also destroy the task. > As a result, any user (suppose the user have the root permission in a > subhurd) can destroy any tasks in the host. Not at all. The subhurd's processes, from the main Hurd's point of view, all run with the rights of the user who started the subhurd. They do not have permission to manipulate other users' processes. Depending on some details of the implementation which I don't know, it could be possible to manipulate processes belonging to the user who started the subhurd, from within the subhurd. Depending on the individual use case, that might or might not be desirable... I'm more and more convinced that filtering tasks visible in the subhurd should be made an option. > I guess the reason mach_task_self() is designed as a system trap > instead of RPC is that the kernel can recognize tasks with their > address spaces, so there is no point to use a RPC to the kernel and a > system trap is very enough. I don't think it has anything to do with being "enough" -- if that was so, many more kernel RPCs could be implemented as direct system traps instead. I think it's the other way around: There are certain advantages of using RPCs (like easy virtualization), and only where this is problematic, traps are used instead. > However, even if mach_task_self() was implemented with RPC, it would > still be very difficult to virtualize it. Let's suppose the RPC > version of mach_task_self() is mach_task_self(mach_port_t host_port). > Now we want to virtualize it in subhurd. Suppose that the server side > of this RPC is implemented in boot. When boot gets the request, it > has no idea who sends the request, whether the request is from the > same task or not. I see it now: It really boils down to a simple bootstrap problem. To invoke any RPCs, we first need to obtain *some* port to send RPCs to... So we need an entry point, to get the first RPC port. This is what mach_*_self() do. I guess there would be other ways to solve the bootstrap problem, but it seems the Mach creators considered this the best approach... > One way I think of is to use a different RPC. Suppose it is called > mach_task_to_subhurd_task(mach_port_t subhurd_port, task_t task). > Therefore, the task in subhurd gets its task port with > mach_task_self() and translate it to subhurd task port with this RPC. Well, if we really need to modify the client-side code for obtaining the task port, I guess a simpler and more efficient approch would be to inject a send right for the pseudo task port into the process address space at process creation time, and simply read that when mach_task_self() is attempted. (Pseudo thread port is more tricky, though.) However, I browsed the Mach documentation a bit, and found task_set_emulation(). It is not documented properly, so I don't know what it can do exactly -- whether it's for UNIX system call emulation, or Mach trap emulation, or both... It *might* be a way to provide pseudo task/thread ports without client-side changes. I agree though that proxying thread/task ports -- with client-side modifications or without -- is a very heavyweight solution, and we should try to avoid it if at all possible. As I don't see a need to do this kind of proxying when obtaining the process list (see above), the thread_max_priority() in proc still seems the only really problematic place. -antrik-