| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Using a new client side <net/route.h>
I was able to clean up the existing options.c in pfinet
and add two new ioctls for adding/deleting network routes.
/* move to bits/ioctl.h */
struct ifrtreq {
char ifname[IFNAMSIZ];
in_addr_t rt_dest;
in_addr_t rt_mask;
in_addr_t rt_gateway;
int rt_flags;
int rt_metric;
int rt_mtu;
int rt_window;
int rt_irtt;
int rt_tos;
int rt_class;
};
Message-Id: <20220829102952.369798-1-damien@zamaudio.com>
|
|
|
|
| |
Message-Id: <20220829193617.13481-1-etienne.brateau@gmail.com>
|
| |
|
|
|
|
|
| |
Build was broken since 6d3b4cea78b22a6562eef4256cfcc40a8d372194
Message-Id: <20220827224239.54097-1-etienne.brateau@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The scenario is:
- process running inside fakeroot exec()s
- fakeroot forwards the exec call
- exec starts thrashing the previous process, and notably close its
ports
- the send port that pointed to fakeroot is thus closed
- fakeroot thus receives a no-senders notification
- its libports thus interrupts the current RPC on it, i.e. the exec(),
because it thinks that the caller is no more, but that was exactly the
point of the exec()...
- exec tries to interrupt its own RPCs, at best the execution will fail,
at worse the process is already thrashed and there's nothing better
than burying it for good.
The symptom is processes running inside fakeroot seeming randomly
crashing with SIGKILL.
Making fakeroot keep a send right avoids the no-senders notification,
thus the whole interruption (which was meaningless).
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Basically it is an automation of this:
http://walfield.org/pub/people/neal/papers/hurd-misc/manual-bootstrap.txt
To launch a storeio translator on FILE:
$ storeio -d FILE -T TYPE ARG
Message-Id: <20170126213616.26846-1-luca.dariz@gmail.com>
|
|
|
|
|
|
| |
The previous master may have gone before all previous slaves have gone. If a
slave gets stuck, TTY_OPEN will kept set, and there would be no reset performed
in open_hook, thus leaking tty state and data.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* pci-arbiter/device_map.h:
* pci-arbiter/device_map.c:
* New function: device_map_rom
* Copies the whole rom in the arbiter space.
* pci-arbiter/pcifs.h:
* struct pcifs_dirent:
* New field to store the mapping address for each device rom.
o pci-arbiter/func_files.h:
* pci-arbiter/func_files.c:
* read_rom_file:
* Retrieves the rom contents from the local space instead of
libpciaccess.
* pci-arbiter/netfs_impl.c:
* netfs_attempt_read:get_filemap_region
* Update call to read_rom_file.
* get_filemap_region:
* Uses the old code at netfs_get_filemap to get a proxy to
the device memory region.
* get_filemap_rom:
* Returns a proxy to the locally mapped device rom.
* netfs_get_filemap:
* Checks the requested file to map and calls get_filemap_rom,
get_filemap_region or returns en error.
Message-Id: <20220815161520.6059-2-jlledom@mailfence.com>
|
|
|
|
| |
This is to be defined in the glibc header.
|
| |
|
|
|
|
| |
For coherency with the existing RPCs
|
|
|
|
| |
So that existing callers can still compile, and just get MIG_BAD_ID.
|
| |
|
|
|
|
| |
And add proc_complete_reauthentication ()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Here's the sequence of events that leads to a bug:
* A task calls file_exec_paths () on itself, holding the only send right to the
protid, passing EXEC_NEWTASK (or EXEC_SECURE, which implies it).
* S_file_exec_paths () calls exec_exec_paths ()
* The exec server sets up a new task and calls proc_reassign () or
proc_reauthenticate_reassign ().
* The proc server destroys the old task, and the only send right to the protid
with it.
* The translator gets a no-senders notification, which results in a
ports_interrupt_rpcs () call on the S_file_exec_paths ().
* This propagates to the exec server (and potentially proc and auth servers).
* The exec gets canceled, and the new task gets killed.
In my opinion, the party that seems most guilty is the translator canceling exec
upon receiving a no-senders notification for the protid. Normally, a no-senders
notification means that the caller is no longer interested in the RPC, but this
is not true in case of exec.
To work around this, create an additional send right to the protid.
|
|
|
|
|
|
|
|
|
|
| |
Now that it's completely unused.
procinfo.owner is now simply set to the first UID that a process has.
proc_setowner () is kept for compatibility, but now does nothing.
The clients still try to call it, though, for compatibility with older
proc server versions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
exec_reauth () is supposed to reauthenticate the given ports and file
descriptors with a new authentication. If the secure flag is set, this
reauthentication is happening for a future exec with the EXEC_SECURE
flag.
Now that the exec server uses proc_reauthenticate_reassign (), the process
reauthentication is done atomically with task reassignment by the exec
server. So stop doing it inside exec_reauth ().
This fixes a vulnerability where a process was able to use its
reauthenticated proc port before it got exec'ed over.
|
|
|
|
|
| |
This lets the exec server atomically replace the old task with the new task
while raising its privileges.
|
|
|
|
|
| |
This is a new RPC to atomically change the UIDs of a process, recreate its
process port, and reassign a different task to it.
|
|
|
|
|
| |
If the allocation failed, we want to leave the p_ids pointer as it was, and
properly propagate the error code.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The previous scheme was to check that PROC1 has the UID that is designated
as PROC2's "owner". This is extremely problematic for several reasons,
including:
* The UIDs and the owner of a process are set separately and can easily get out
of sync. While S_proc_setowner () checks that the new owner is among the UIDs
that the process has, this invariant is violated after the process is given a
new set of UIDs with S_proc_reauthenticate (). In particular, this happens
during execution of a SUID binary: the process is reauthenticated to a
different set of UIDs first, and its owner is udpated later, if at all.
* In the Hurd, a process can have multiple UIDs. Having to designate just one
of them as the owner means the other UIDs get ignored for the purpose of
permission checking. One particularly problematic case is a SUID process that
temporarily lowers its effective UID: glibc sets the first effective UID as
the process owner, giving just about anyone access to the task.
Resolve this by ignoring the owner for the purpose of permission checking, and
relying solely on the authenticated UIDs. Roughly speaking, PROC1 can get
complete access to PROC2 if the UIDs PROC1 has form a superset of the UIDs that
PROC2 has; in other words, the access is only allowed when it would not result
in PROC1 getting access to UIDs it doesn't have already. Of course, root is
still allowed to access any process.
In particular, this means that:
* a process can access another process if they have the same auth;
* a process that has "more auth" can access one that has "less auth", but not
the other way around;
* a SUID-root process that has lowered its effective UIDs can only be accessed
by root.
Another important point here is that the UIDs in question are both effective
and available UIDs that a process has. Normally, available UIDs are ignored for
the purpose of permission checking (and that is their whole point). However,
POSIX description of kill(2) has the following clause:
> For a process to have permission to send a signal to a process designated by
> pid, unless the sending process has appropriate privileges, the real or
> effective user ID of the sending process shall match the real or saved
> set-user-ID of the receiving process.
Which I read as saying that the real (i.e. available) UID(s) of PROC1 should be
used for evaluating whether kill(2) can succeed, not only its effective UID(s).
|
|
|
|
|
| |
This is in preparation for using the UID's to evaluate permissions
in a different way.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
While fshelp_start_translator_long () has been calling proc_setowner () on the
task it creates, it has never reauthenticated its process. This meant that the
translator, once started, could access processes authenticated same as the
process that called fshelp_start_translator_long (). In particular, this means
that any unprivileged translator started by a privileged parent translator had
in fact had a privileged proc port, and could access other processes through
it.
With this change, fshelp_start_translator_long () will now reauthenticate the
process it creates. Moreover, it will now respect a custom proc server port
passed in the given ports.
|
| |
|
|
|
|
|
|
|
| |
It only really supports ports_len > INIT_PORT_BOOTSTRAP,
ports_type == MACH_MSG_TYPE_COPY_SEND, fds_type == MACH_MSG_TYPE_COPY_SEND.
Make that explicit, and remove the branches that tried to handle the other
cases.
|
|
|
|
|
| |
Since this port is never given out to anyone but the kernel,
our clients can't spoof a dead-name notification this way.
|
|
|
|
|
|
| |
libports will start requesting dead-name notifications on its own.
As we handle all notifications, both ones we have requested and ones
libports has, distinguish between the two handlers by the port.
|
|
|
|
|
|
|
|
|
|
| |
We do not impement most of the mach_notify_* () routines. Explicitly return
an error code so that our caller knows to properly deallocate all resources
the messages may carry.
Even though we don't expect to receive some of the notifications from the kernel
as we never sign up for them, we can always receive spoofed notifications from
our clients, so don't abort in that case.
|
|
|
|
|
|
| |
We can't use it to *request* notifications here, since we need to use
a custom per-display port (and not libports' notify_port), but we can
still use it to *cancel* notifications with a lot less boilerplate.
|
|
|
|
|
| |
Since this port is never given out to anyone but the kernel,
our clients can't spoof a dead-name notification this way.
|
|
|
|
|
|
| |
We do not impement most of the mach_notify_* () routines. Explicitly return
an error code so that our caller knows to properly deallocate all resources
the messages may carry.
|
|
|
|
|
|
| |
Since the implementation in libmachdev was just forwarding calls
to the corresponding libports functions, we might as well just use
ports_notify_server_routine () directly.
|
|
|
|
| |
This logic is obviously broken, let's disable it for now.
|
| |
|
|
|
|
|
| |
Namely, ports_request_dead_name_notification () where we can,
and the libports notify port when we have to pass it to libfshelp.
|
| |
|
|
|
|
| |
We can simply override proc_dead_name () to handle dead-name notifications.
|
| |
|
|
|
|
| |
We can simply override proc_dead_name () to handle dead-name notifications.
|
| |
|
|
|
|
|
| |
This significantly cuts down the boilerplate of
requesting dead-name notifications.
|
| |
|
|
|
|
|
|
|
| |
This notify port will be used to request & receive Mach notifications.
While it is present in the bucket much like any other port, it is not
counted in ports_count_bucket () and is not exposed to the user
callback in ports_bucket_iterate ().
|
|
|
|
|
|
|
| |
No-senders notifications are directed to the port that no longer has any
senders left. Since any client can easily spoof such a notification, we have to
treat the notification as just a hint and verify whether there are, in fact,
any senders, and only call ports_no_senders () if there actually are none left.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
mach_port_destroy () is a dangerous API that has to be used with extreme care.
Namely, it destroys not one user reference, but *all* user references that a
task has for a port name. Different parts of a program may all keep separate
references on a port without coordinating it with each other (which is the
whole idea behind reference counting). If one part of a program decides to
destroy a port with mach_port_destroy () without informing others, others may
still believe they hold a reference and will continue to use the name as if it
still refered to the now-destroyed port right. This consitutes a port
use-after-free, even if their use is also deallocating their reference.
In the particular case of the proc server, this manifested itself as
S_proc_reassign () destroying all user references to the task port right before
the task port right is deallocated again in the dead-name notification handler.
|
|
|
|
|
|
|
|
|
|
|
|
| |
ports_get_right () expects the caller to make a send, not a send-once,
right from the returned receive right, and increments the expected make-send
count accordingly. The kernel, however, does not increment the make-send
count when a send-once right is being made.
The result can be described as a "no-senders leak": libports' idea of the
current make-send count always stays one step ahead of it actual value (or
several steps ahead, if the process is repeated), which makes libports
ignore *all* the subsequent no-senders notifications for the port as outdated.
|