224 |
could provide the index in the table for fast O(1) lookup instead |
could provide the index in the table for fast O(1) lookup instead |
225 |
linear search. Threads with access could be allowed to add other |
linear search. Threads with access could be allowed to add other |
226 |
threads or change existing table entries. The same scheme can be |
threads or change existing table entries. The same scheme can be |
227 |
used int the device driver framework. |
used in the device driver framework. |
228 |
|
|
229 |
The rootserver should have one thread per CPU, and run at a high |
The rootserver should have one thread per CPU, and run at a high |
230 |
priority. |
priority. |
1899 |
\subsubsection{The \texttt{exec()} function} |
\subsubsection{The \texttt{exec()} function} |
1900 |
\label{exec} |
\label{exec} |
1901 |
|
|
1902 |
The exec() operation will be done locally in a task. Traditionally, |
The \texttt{exec()} operation will be done locally in a task. |
1903 |
exec() overlays the same task with a new process image, because |
Traditionally, \texttt{exec()} overlays the same task with a new |
1904 |
creating a new task and transferring the associated state is |
process image, because creating a new task and transferring the |
1905 |
expensive. In L4, only the threads and virtual memory mappings are |
associated state is expensive. In L4, only the threads and virtual |
1906 |
actually kernel state associated with a task, and exactly those have |
memory mappings are actually kernel state associated with a task, and |
1907 |
to be destroyed by exec() anyway. There is a lot of Hurd specific |
exactly those have to be destroyed by \texttt{exec()} anyway. There |
1908 |
state associated with a task (capabilities, for example), but it is |
is a lot of Hurd specific state associated with a task (capabilities, |
1909 |
difficult to preserve that. There are security concerns, because |
for example), but it is difficult to preserve that. There are |
1910 |
POSIX programs do not know about Hurd features like capabilities, so |
security concerns, because POSIX programs do not know about Hurd |
1911 |
inheriting all capabilities across exec() seems dangerous. There are |
features like capabilities, so inheriting all capabilities across |
1912 |
also implementation obstacles, because only local threads can |
\texttt{exec()} unconditionally seems dangerous. |
1913 |
manipulate the virtual memory mappings, and there is a lot of local |
|
1914 |
state that has to be kept somewhere between the time the old program |
\begin{comment} |
1915 |
becomes defunct and the new binary image is installed and used (not to |
One could think that if a program is not Hurd-aware, then it will |
1916 |
speak of the actual program snippet that runs during the transition). |
not make any use of capabilities except through the normal POSIX |
1917 |
|
API, and thus there are no capabilities except those that the GNU C |
1918 |
So a decision was made to always create a new task with exec(), and |
library uses itself, which \texttt{exec()} can take care of. |
1919 |
move the desired state over from the current task to the new task. |
However, this is only true if code that is not Hurd-aware is never |
1920 |
This is a clean solution, because a new task will always start out |
mixed with Hurd specific code, even libraries (unless the library |
1921 |
without any capabilities in servers, etc, and thus there is no need |
intimately cooperates with the GNU C library). This would be a high |
1922 |
for the old task to try to destroy all unneeded capabilities and other |
barrier to enable Hurd features in otherwise portable programs and |
1923 |
local state before exec(). Also, in case the exec fails, the old |
libraries. |
1924 |
program can continue to run, even if the exec fails at a very late |
|
1925 |
point (there is no ``point of no return'' until the new task is |
It is better to make all POSIX functions safe by default and allow |
1926 |
actually up and running). |
for extensions to let the user specify which capabilities besides |
1927 |
|
those used for file descriptors etc to be inherited by the new |
1928 |
For suid/sgid applications, the actual exec has to be done by the |
executable. |
1929 |
filesystem. However, the filesystem can not be bothered to also |
|
1930 |
transfer all the user state into the new task. It can not even do |
For \texttt{posix_spawn}, this is straight-forward. For |
1931 |
that, because it can not accept capabilities implemented by untrusted |
\texttt{exec()}, it is not. either specific capabilities could be |
1932 |
servers from the user. Also, the filesystem does not want to rely on |
markes as ``do not close on \texttt{exec()}'', or variants of the |
1933 |
the new task to be cooperative, because it does not necessarily trust |
\texttt{exec()} function could be provided which take further |
1934 |
the code. (This actually depends on if users are allowed to set the |
arguments. |
1935 |
suid/sgid flag on their own programs. If not, then it might be ok for |
\end{comment} |
1936 |
the filesystem to trust the program, but it is assumed that the Hurd |
|
1937 |
will not be so restrictive). Here is how it can be done. Only the |
There are also implementation obstacles hindering the reuse of the |
1938 |
suid/sgid case is provided, the other one is naturally easier but |
existing task. Only local threads can manipulate the virtual memory |
1939 |
comparable. |
mappings, and there is a lot of local state that has to be kept |
1940 |
|
somewhere between the time the old program becomes defunct and the new |
1941 |
|
binary image is installed and used (not to speak of the actual program |
1942 |
|
snippet that runs during the transition). |
1943 |
|
|
1944 |
|
So the decision was made to always create a new task with |
1945 |
|
\texttt{exec()}, and copy the desired state from the current task to |
1946 |
|
the new task. This is a clean solution, because a new task will |
1947 |
|
always start out without any capabilities in servers, etc, and thus |
1948 |
|
there is no need for the old task to try to destroy all unneeded |
1949 |
|
capabilities and other local state before \texttt{exec()}. Also, in |
1950 |
|
case the exec fails, the old program can continue to run, even if the |
1951 |
|
exec fails at a very late point (there is no ``point of no return'' |
1952 |
|
until the new task is actually up and running). |
1953 |
|
|
1954 |
|
For suid and sgid applications, the actual \texttt{exec()} has to be |
1955 |
|
done by the filesystem. However, the filesystem can not be bothered |
1956 |
|
to also transfer all the user state into the new task. It can not |
1957 |
|
even do that, because it can not accept capabilities implemented by |
1958 |
|
untrusted servers from the user. Also, the filesystem does not want |
1959 |
|
to rely on the new task to be cooperative, because it does not |
1960 |
|
necessarily trust the code, if is is owned by an untrusted user. |
1961 |
|
|
1962 |
\begin{enumerate} |
\begin{enumerate} |
1963 |
\item The user creates a new task and a container with a single |
\item The user creates a new task and a container with a single |
1964 |
physical page, and makes the exec() call to the file capability, |
physical page, and makes the \texttt{exec()} call to the file |
1965 |
providing the task control capability. Before that, it creates a |
capability, providing the task control capability. Before that, it |
1966 |
task info capability from it for its own use. |
creates a task info capability from it for its own use. |
1967 |
\item The filesystem checks permission and then revokes all other |
\item The filesystem checks permission and then revokes all other |
1968 |
users on the task control capability. This will revoke the users |
users on the task control capability. This will revoke the users |
1969 |
access to the task, and will fail if the user did not provide a |
access to the task, and will fail if the user did not provide a |