summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <justus@gnupg.org>2017-03-12 17:16:40 +0100
committerJustus Winter <justus@gnupg.org>2017-03-12 17:41:04 +0100
commit4089f37cdd776e046d51604041c3fe62a2bc1435 (patch)
tree22a6f3203934672fd2d02b934023c8afd241fbf5
parentef729f8642cc96ddfd3f5b5db4d6aac057b1d397 (diff)
Pass the kernel's task port to proc.
Previously, the early server bootstrap relied upon a specific task layout to determine the kernels task port. Explicitly pass it from the kernel instead. * boot/boot.c (default_boot_script): Add '--kernel-task' parameter to ext2fs. (main): New bootscript variable 'kernel-task'. * libdiskfs/boot-start.c (diskfs_kernel_task): Declaration variable. (diskfs_start_bootstrap): If '--kernel-task' was given to us, pass it along to startup. * libdiskfs/opts-std-startup.c (diskfs_kernel_task): New variable. (startup_options): Add '--kernel-task' option. (parse_startup_opt): Handle option. * proc/main.c (kernel_task): New variable. (OPT_KERNEL_TASK): New macro. (options): New variable. (parse_opt): New function. (main): Parse options. Use 'kernel_task' if provided. * release/servers.boot: Add '--kernel-task' parameter to ext2fs. * startup/startup.c (OPT_KERNEL_TASK): New macro. (options): Add '--kernel-task' option. (kernel_task): New variable. (insert_ports_fnc_t): New declaration. (run): Add argument for a function that inserts rights into the newly created task and adds arguments to the argument vector. (argz_task_insert_right): New function. (proc_insert_ports): Likewise. (parse_opt): New function. (main): Pass the kernel's task port to proc. (frob_kernel_process): Use the kernel's task port.
-rw-r--r--boot/boot.c3
-rw-r--r--libdiskfs/boot-start.c44
-rw-r--r--libdiskfs/opts-std-startup.c5
-rw-r--r--proc/main.c42
-rw-r--r--release/servers.boot2
-rw-r--r--startup/startup.c97
6 files changed, 166 insertions, 27 deletions
diff --git a/boot/boot.c b/boot/boot.c
index 13a19d28..978f56e6 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -520,6 +520,7 @@ const char *default_boot_script =
" --multiboot-command-line=${kernel-command-line}"
" --host-priv-port=${host-port}"
" --device-master-port=${device-port}"
+ " --kernel-task=${kernel-task}"
" --exec-server-task=${exec-task}"
" -T device ${root-device} $(task-create) $(task-resume)"
"\n"
@@ -649,6 +650,8 @@ main (int argc, char **argv, char **envp)
: (int) pseudo_privileged_host_port)
|| boot_script_set_variable ("device-port", VAL_PORT,
(integer_t) pseudo_master_device_port)
+ || boot_script_set_variable ("kernel-task", VAL_PORT,
+ (integer_t) pseudo_kernel)
|| boot_script_set_variable ("kernel-command-line", VAL_STR,
(integer_t) kernel_command_line)
|| boot_script_set_variable ("root-device",
diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
index 0fb3e89d..f048badf 100644
--- a/libdiskfs/boot-start.c
+++ b/libdiskfs/boot-start.c
@@ -40,6 +40,7 @@
static mach_port_t diskfs_exec_ctl;
extern task_t diskfs_exec_server_task;
+extern task_t diskfs_kernel_task;
static task_t parent_task = MACH_PORT_NULL;
static pthread_mutex_t execstartlock;
@@ -206,9 +207,6 @@ diskfs_start_bootstrap ()
/* We have a boot command line to run instead of init. */
err = argz_create (_diskfs_boot_command, &exec_argv, &exec_argvlen);
assert_perror (err);
- initname = exec_argv;
- while (*initname == '/')
- initname++;
}
else
{
@@ -223,10 +221,42 @@ diskfs_start_bootstrap ()
err = argz_add_sep (&exec_argv, &exec_argvlen,
diskfs_boot_command_line, ' ');
assert_perror (err);
+ }
+
+ err = task_create (mach_task_self (),
+#ifdef KERN_INVALID_LEDGER
+ NULL, 0, /* OSF Mach */
+#endif
+ 0, &newt);
+ assert_perror (err);
- initname = exec_argv + 1;
+ if (MACH_PORT_VALID (diskfs_kernel_task))
+ {
+ mach_port_t kernel_task_name = MACH_PORT_NULL;
+ char buf[20];
+ int len;
+
+ do
+ {
+ kernel_task_name += 1;
+ err = mach_port_insert_right (newt, kernel_task_name,
+ diskfs_kernel_task, MACH_MSG_TYPE_MOVE_SEND);
+ }
+ while (err == KERN_NAME_EXISTS);
+ diskfs_kernel_task = MACH_PORT_NULL;
+
+ len = snprintf (buf, sizeof buf, "--kernel-task=%d", kernel_task_name);
+ assert (len < sizeof buf);
+ /* Insert as second argument. */
+ err = argz_insert (&exec_argv, &exec_argvlen,
+ argz_next (exec_argv, exec_argvlen, exec_argv), buf);
+ assert_perror (err);
}
+ initname = exec_argv;
+ while (*initname == '/')
+ initname++;
+
lookup_init:
err = dir_lookup (root_pt, (char *) initname, O_READ, 0, &retry, pathbuf,
&startup_pt);
@@ -270,12 +300,6 @@ diskfs_start_bootstrap ()
err = argz_create (environ, &exec_env, &exec_envlen);
assert_perror (err);
- err = task_create (mach_task_self (),
-#ifdef KERN_INVALID_LEDGER
- NULL, 0, /* OSF Mach */
-#endif
- 0, &newt);
- assert_perror (err);
if (_diskfs_boot_pause)
{
printf ("pausing for %s...\n", exec_argv);
diff --git a/libdiskfs/opts-std-startup.c b/libdiskfs/opts-std-startup.c
index ed25a18d..a38db99a 100644
--- a/libdiskfs/opts-std-startup.c
+++ b/libdiskfs/opts-std-startup.c
@@ -35,6 +35,7 @@ int _diskfs_boot_pause;
extern char **diskfs_argv;
mach_port_t diskfs_exec_server_task = MACH_PORT_NULL;
+mach_port_t diskfs_kernel_task = MACH_PORT_NULL;
/* ---------------------------------------------------------------- */
@@ -45,6 +46,7 @@ mach_port_t diskfs_exec_server_task = MACH_PORT_NULL;
#define OPT_BOOT_COMMAND (-5)
#define OPT_BOOT_INIT_PROGRAM (-6)
#define OPT_BOOT_PAUSE (-7)
+#define OPT_KERNEL_TASK (-8)
static const struct argp_option
startup_options[] =
@@ -68,6 +70,7 @@ startup_options[] =
{"host-priv-port", OPT_HOST_PRIV_PORT, "PORT"},
{"device-master-port", OPT_DEVICE_MASTER_PORT, "PORT"},
{"exec-server-task", OPT_EXEC_SERVER_TASK, "PORT"},
+ {"kernel-task", OPT_KERNEL_TASK, "PORT"},
{0}
};
@@ -106,6 +109,8 @@ parse_startup_opt (int opt, char *arg, struct argp_state *state)
_hurd_host_priv = atoi (arg); break;
case OPT_EXEC_SERVER_TASK:
diskfs_exec_server_task = atoi (arg); break;
+ case OPT_KERNEL_TASK:
+ diskfs_kernel_task = atoi (arg); break;
case OPT_BOOT_CMDLINE:
diskfs_boot_command_line = arg; break;
case OPT_BOOT_INIT_PROGRAM:
diff --git a/proc/main.c b/proc/main.c
index d97650fc..e615f363 100644
--- a/proc/main.c
+++ b/proc/main.c
@@ -123,6 +123,32 @@ open_console (mach_port_t device_master)
return 0;
}
+
+
+static task_t kernel_task;
+
+#define OPT_KERNEL_TASK -1
+
+static struct argp_option
+options[] =
+{
+ {"kernel-task", OPT_KERNEL_TASK, "PORT"},
+ {0}
+};
+
+static int
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case OPT_KERNEL_TASK:
+ kernel_task = atoi (arg);
+ break;
+ default: return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
int
main (int argc, char **argv, char **envp)
{
@@ -131,7 +157,8 @@ main (int argc, char **argv, char **envp)
void *genport;
process_t startup_port;
mach_port_t startup;
- struct argp argp = { 0, 0, 0, "Hurd process server" };
+ char **original_argv;
+ struct argp argp = { options, parse_opt, 0, "Hurd process server" };
argp_parse (&argp, argc, argv, 0, 0, 0);
@@ -191,10 +218,15 @@ main (int argc, char **argv, char **envp)
if (err && err != EPERM)
error (0, err, "Increasing priority failed");
- /* Get a list of all tasks to find the kernel. */
- /* XXX: I't be nice if GNU Mach would hand us the task port. */
- add_tasks (MACH_PORT_NULL);
- kernel_proc = pid_find (HURD_PID_KERNEL);
+ /* Find the kernel. */
+ if (MACH_PORT_VALID (kernel_task))
+ kernel_proc = task_find (kernel_task);
+ else
+ {
+ /* Get a list of all tasks to find the kernel. */
+ add_tasks (MACH_PORT_NULL);
+ kernel_proc = pid_find (HURD_PID_KERNEL);
+ }
/* Register for new task notifications using the kernel's process as
the port. */
diff --git a/release/servers.boot b/release/servers.boot
index 9ba7f6a4..8b66743f 100644
--- a/release/servers.boot
+++ b/release/servers.boot
@@ -3,7 +3,7 @@
# First, the bootstrap filesystem. It needs several ports as arguments,
# as well as the user flags from the boot loader.
-/hurd/ext2fs.static --multiboot-command-line=${kernel-command-line} --host-priv-port=${host-port} --device-master-port=${device-port} --exec-server-task=${exec-task} -T typed ${root} $(task-create) $(task-resume)
+/hurd/ext2fs.static --multiboot-command-line=${kernel-command-line} --host-priv-port=${host-port} --device-master-port=${device-port} --exec-server-task=${exec-task} --kernel-task=${kernel-task} -T typed ${root} $(task-create) $(task-resume)
# Now the exec server; to load the dynamically-linked exec server program,
diff --git a/startup/startup.c b/startup/startup.c
index 4a0304ea..3c3ead4c 100644
--- a/startup/startup.c
+++ b/startup/startup.c
@@ -72,6 +72,8 @@ static int verbose = 0;
const char *argp_program_version = STANDARD_HURD_VERSION (startup);
+#define OPT_KERNEL_TASK -1
+
static struct argp_option
options[] =
{
@@ -83,6 +85,7 @@ options[] =
{"fake-boot", 'f', 0, 0, "This hurd hasn't been booted on the raw machine"},
{"verbose", 'v', 0, 0, "be verbose"},
{0, 'x', 0, OPTION_HIDDEN},
+ {"kernel-task", OPT_KERNEL_TASK, "PORT"},
{0}
};
@@ -136,6 +139,7 @@ static int fakeboot;
/* The tasks of auth and proc and the bootstrap filesystem. */
static task_t authtask, proctask, fstask;
+static task_t kernel_task;
static mach_port_t default_ports[INIT_PORT_MAX];
static mach_port_t default_dtable[3];
@@ -344,10 +348,13 @@ record_essential_task (const char *name, task_t task)
/** Starting programs **/
+typedef error_t (*insert_ports_fnc_t) (char **argv, size_t *argv_len, task_t task);
+
/* Run SERVER, giving it INIT_PORT_MAX initial ports from PORTS.
Set TASK to be the task port of the new image. */
void
-run (const char *server, mach_port_t *ports, task_t *task)
+run (const char *server, mach_port_t *ports, task_t *task,
+ insert_ports_fnc_t insert_ports)
{
char buf[BUFSIZ];
const char *prog = server;
@@ -369,18 +376,31 @@ run (const char *server, mach_port_t *ports, task_t *task)
error (0, errno, "%s", prog);
else
{
- task_create (mach_task_self (),
+ char *argz = NULL;
+ size_t argz_len = 0;
+ err = argz_create_sep (prog, ' ', &argz, &argz_len);
+ assert_perror (err);
+
+ err = task_create (mach_task_self (),
#ifdef KERN_INVALID_LEDGER
- NULL, 0, /* OSF Mach */
+ NULL, 0, /* OSF Mach */
#endif
- 0, task);
+ 0, task);
+ assert_perror (err);
+
+ if (insert_ports)
+ {
+ err = insert_ports (&argz, &argz_len, *task);
+ assert_perror (err);
+ }
+
if (bootstrap_args & RB_KDB)
{
fprintf (stderr, "Pausing for %s\n", prog);
getchar ();
}
err = file_exec (file, *task, 0,
- (char *)prog, strlen (prog) + 1, /* Args. */
+ argz, argz_len, /* Args. */
startup_envz, startup_envz_len,
default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
@@ -408,6 +428,50 @@ run (const char *server, mach_port_t *ports, task_t *task)
request_dead_name (*task);
}
+/* Insert PORT of type PORT_TYPE into TASK, adding '--ARGUMENT=<name>'
+ to ARGZ (with <name> being the name valid in TASK). */
+error_t
+argz_task_insert_right (char **argz, size_t *argz_len, task_t task,
+ const char *argument,
+ mach_port_t port, mach_msg_type_name_t port_type)
+{
+ error_t err;
+ mach_port_t name;
+ char *arg;
+
+ name = MACH_PORT_NULL;
+ do
+ {
+ name += 1;
+ err = mach_port_insert_right (task, name, port, port_type);
+ }
+ while (err == KERN_NAME_EXISTS);
+
+ if (asprintf (&arg, "--%s=%d", argument, name) < 0)
+ return errno;
+
+ err = argz_add (argz, argz_len, arg);
+ free (arg);
+ return err;
+}
+
+error_t
+proc_insert_ports (char **argz, size_t *argz_len, task_t task)
+{
+ error_t err;
+
+ if (MACH_PORT_VALID (kernel_task))
+ {
+ err = argz_task_insert_right (argz, argz_len, task,
+ "kernel-task",
+ kernel_task, MACH_MSG_TYPE_COPY_SEND);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
/* Run FILENAME as root with ARGS as its argv (length ARGLEN). Return
the task that we started. If CTTY is set, then make that the
controlling terminal of the new process and put it in its own login
@@ -597,6 +661,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'H': crash_flags = RB_DEBUGGER; break;
case 'v': verbose++; break;
case 'x': /* NOP */ break;
+ case OPT_KERNEL_TASK:
+ kernel_task = atoi (arg);
+ break;
default: return ARGP_ERR_UNKNOWN;
}
return 0;
@@ -685,10 +752,10 @@ main (int argc, char **argv, char **envp)
| sigmask (SIGTTOU));
default_ports[INIT_PORT_BOOTSTRAP] = startup;
- run ("/hurd/proc", default_ports, &proctask);
+ run ("/hurd/proc", default_ports, &proctask, proc_insert_ports);
if (! verbose)
fprintf (stderr, " proc");
- run ("/hurd/auth", default_ports, &authtask);
+ run ("/hurd/auth", default_ports, &authtask, NULL);
if (! verbose)
fprintf (stderr, " auth");
default_ports[INIT_PORT_BOOTSTRAP] = MACH_PORT_NULL;
@@ -905,11 +972,19 @@ frob_kernel_process (void)
if (verbose)
fprintf (stderr, "Frobbing kernel process\n");
- err = proc_pid2task (procserver, HURD_PID_KERNEL, &task);
- if (err)
+ if (MACH_PORT_VALID (kernel_task))
{
- error (0, err, "cannot get kernel task port");
- return;
+ task = kernel_task;
+ kernel_task = MACH_PORT_NULL;
+ }
+ else
+ {
+ err = proc_pid2task (procserver, HURD_PID_KERNEL, &task);
+ if (err)
+ {
+ error (0, err, "cannot get kernel task port");
+ return;
+ }
}
/* Make the kernel our child. */