bug-hurd
[Top][All Lists]
Advanced

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

Re: [RFC] Implementing RLIMIT_AS


From: Sergey Bugaev
Subject: Re: [RFC] Implementing RLIMIT_AS
Date: Mon, 23 Dec 2024 09:35:43 +0300

On Sun, Dec 22, 2024 at 1:45 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > FWIW, this means that the caller would be potentially sending the host
> > priv port to someone who's not necessarily the kernel. That's fine if
> > we're acting on mach_task_self (since if someone is interposing our
> > task port, we can trust them), but not fine if we're a privileged
> > server who's willing to raise the given task's memory allowance
> > according to some policy.
>
> Task ports are created only by task_create, so only managed by gnumach.
> Privileges servers do trust that their task ports are indeed from that.

What I meant is imagine you have

routine foo_server_raise_memory_size_limit (reqport: foo_server_t;
task: task_t; desired_limit: vm_size_t);

error_t
S_foo_server_raise_memory_size_limit (... reqport, task_t task,
vm_size_t desired_limit)
{
  error_t err;

  if (/* some permission or policy checks */)
    return EACCESS;

  err = vm_set_size_limit (task, host_priv, desired_limit);
  if (!err)
    mach_port_deallocate (mach_task_self (), task);
  return err;
}

then if 'task' was not a real task port, we've sent the host priv port
to someone.

You can of course be careful to never write servers that do that, but
a good practice is to design APIs so that they're harder to misuse in
the first place. This means only using the host priv port as a message
destination, unless we explicitly mean to send it in a message (like
proc_getprivports). I don't remember seeing an RPC so far that
would've done it differently. So we should either have two RPCs:

routine vm_limit_size (task: vm_task_t; limit: vm_size_t);
routine vm_increase_size_limit (host_priv: host_priv_t; task:
vm_task_t; limit: vm_size_t);

or we could have a single routine that accepts either the host or host
priv port, but it would require some more ceremony to check which one,
perhaps like this:

routine vm_set_size_limit (host: mach_port_t; target_task: task_t;
limit: vm_size_t);

kern_return_t vm_set_size_limit(
        const ipc_port_t        host_port,
        vm_map_t                map,
        vm_size_t               limit)
{
        ipc_kobject_type_t ikot_host = IKOT_NONE;

        if (!IP_VALID(host_port))
                return(KERN_INVALID_HOST);
        ip_lock(host_port);
        if (ip_active(port))
                ikot_host = ip_kotype(host_port);
        ip_unlock(host_port);
        if (ikot_host != IKOT_HOST && ikot_host != IKOT_HOST_PRIV)
                return(KERN_INVALID_HOST);

        if (map == VM_MAP_NULL)
                return(KERN_INVALID_ARGUMENT);

        vm_map_lock(map);

        /*
         *      Must pass the host priv port to increase the limit.
         */
        if (limit > map->size_limit && ikot_host != IKOT_HOST_PRIV) {
                vm_map_unlock(map);
                return(KERN_INVALID_HOST);
        }

        ...
}

Sergey



reply via email to

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