diff options
author | Justus Winter <justus@gnupg.org> | 2016-04-22 02:54:04 +0200 |
---|---|---|
committer | Justus Winter <justus@gnupg.org> | 2016-04-22 02:54:04 +0200 |
commit | 4a22f9c18291e21b28671f089b5763643fccb49c (patch) | |
tree | b53781bf81e583be2d356fefa5663334b4a260a3 /debian | |
parent | 4c35603b6c1d584bdf8c749801f079d95a6b2764 (diff) |
add patch series
Diffstat (limited to 'debian')
-rw-r--r-- | debian/patches/series | 2 | ||||
-rw-r--r-- | debian/patches/shutdown0001-trans-add-shutdown-translator.patch | 581 | ||||
-rw-r--r-- | debian/patches/shutdown0002-xxx-halt-hack.patch | 45 |
3 files changed, 628 insertions, 0 deletions
diff --git a/debian/patches/series b/debian/patches/series index cad5f5c7..cdd19f04 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -45,3 +45,5 @@ fs_unification0002-libnetfs-rename-diruser-to-dircred.patch fs_unification0003-libdiskfs-cosmetic-changes.patch fs_unification0004-YYY-Unify-the-short-circuit-translator-logic.patch fs_unification0005-libnetfs-treat-disconnected-shadow-roots-as-virtual-.patch +shutdown0001-trans-add-shutdown-translator.patch +shutdown0002-xxx-halt-hack.patch diff --git a/debian/patches/shutdown0001-trans-add-shutdown-translator.patch b/debian/patches/shutdown0001-trans-add-shutdown-translator.patch new file mode 100644 index 00000000..b29f7463 --- /dev/null +++ b/debian/patches/shutdown0001-trans-add-shutdown-translator.patch @@ -0,0 +1,581 @@ +From bd0301366daa289993ba16a4a65bb8768ef8ccf8 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Tue, 13 Jan 2015 19:01:50 +0100 +Subject: [PATCH hurd 1/2] trans: add shutdown translator + +Provide a stripped-down version of the startup translator that +supervises core servers and handles server shutdown. + +* trans/shutdown.c: New file. +* trans/Makefile: Add shutdown translator. +--- + trans/Makefile | 18 +- + trans/shutdown.c | 514 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 528 insertions(+), 4 deletions(-) + create mode 100644 trans/shutdown.c + +diff --git a/trans/Makefile b/trans/Makefile +index 65b51d1..39dfa9b 100644 +--- a/trans/Makefile ++++ b/trans/Makefile +@@ -21,14 +21,14 @@ makemode := servers + + targets = symlink firmlink ifsock magic null fifo new-fifo fwd crash \ + password hello hello-mt streamio fakeroot proxy-defpager remap \ +- mtab ++ mtab shutdown + SRCS = ifsock.c symlink.c magic.c null.c fifo.c new-fifo.c fwd.c \ + crash.c firmlink.c password.c hello.c hello-mt.c streamio.c \ +- fakeroot.c proxy-defpager.c remap.c mtab.c ++ fakeroot.c proxy-defpager.c remap.c mtab.c shutdown.c + OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o \ + crashServer.o crash_replyUser.o msgServer.o \ + default_pagerServer.o default_pagerUser.o \ +- device_replyServer.o elfcore.o ++ device_replyServer.o elfcore.o startup_notifyServer.o startupServer.o + HURDLIBS = ports netfs trivfs iohelp fshelp pipe ihash shouldbeinlibc + LDLIBS += -lpthread + password-LDLIBS = -lcrypt +@@ -66,8 +66,18 @@ streamio: device_replyServer.o + symlink: fsysServer.o + + fakeroot: ../libnetfs/libnetfs.a ++shutdown: startupServer.o startup_notifyUser.o ++ ++# startupServer is used by the shutdown translator. ++startup-MIGSFLAGS=\ ++ "-DSTARTUP_INTRAN=trivfs_protid_t trivfs_begin_using_protid (startup_t)" \ ++ "-DSTARTUP_INTRAN_PAYLOAD=trivfs_protid_t trivfs_begin_using_protid_payload" \ ++ "-DSTARTUP_DESTRUCTOR=trivfs_end_using_protid (trivfs_protid_t)" \ ++ "-DSTARTUP_IMPORTS=import \"../libtrivfs/mig-decls.h\";" ++ ++ + fifo new-fifo: ../libpipe/libpipe.a +-crash fifo firmlink hello hello-mt ifsock magic mtab new-fifo null password proxy-defpager remap streamio: ../libtrivfs/libtrivfs.a ++crash fifo firmlink hello hello-mt ifsock magic mtab new-fifo null password proxy-defpager remap streamio shutdown: ../libtrivfs/libtrivfs.a + $(targets): ../libfshelp/libfshelp.a \ + ../libihash/libihash.a \ + ../libiohelp/libiohelp.a \ +diff --git a/trans/shutdown.c b/trans/shutdown.c +new file mode 100644 +index 0000000..6824cf6 +--- /dev/null ++++ b/trans/shutdown.c +@@ -0,0 +1,514 @@ ++/* Start and maintain hurd core servers and system run state ++ ++ Copyright (C) 1993-2015 Free Software Foundation, Inc. ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2, or (at your option) ++ any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd; see the file COPYING. If not, write to ++ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ ++/* Written by Michael I. Bushnell and Roland McGrath. */ ++ ++/* This is probably more include files than I've ever seen before for ++ one file. */ ++ ++#include <argp.h> ++#include <argz.h> ++#include <error.h> ++#include <fcntl.h> ++#include <hurd/ports.h> ++#include <hurd/trivfs.h> ++#include <hurd/startup.h> ++#include <stdlib.h> ++#include <stdio.h> ++#include <string.h> ++#include <sys/mman.h> ++#include <sys/reboot.h> ++#include <unistd.h> ++#include <version.h> ++ ++#include "startup_notify_U.h" ++#include "startup_reply_U.h" ++#include "startup_S.h" ++#include "notify_S.h" ++ ++/* The privileged host control port. Used for communication with the ++ kernel, and for authentication with our parent shutdown server. */ ++mach_port_t host_priv; ++ ++int system_mode; ++int supervise; ++ ++/* Time to wait for translators to shut down. */ ++mach_msg_timeout_t timeout = 5000; ++ ++/* Time to wait for privileged translators to shut down. */ ++mach_msg_timeout_t privileged_timeout = 60000; ++ ++/* We receive dead-name notifications here. */ ++struct port_info *notification; ++ ++/* host_reboot flags for when we crash. */ ++static int crash_flags = RB_AUTOBOOT; ++ ++ ++ ++#define BOOT(flags) ((flags & RB_HALT) ? "halt" : "reboot") ++ ++ ++ ++/* This structure keeps track of each notified task. */ ++struct ntfy_task ++ { ++ struct ntfy_task *next; ++ mach_port_t notify_port; ++ int privileged; ++ char *name; ++ }; ++ ++/* This structure keeps track of each registered essential task. */ ++struct ess_task ++ { ++ struct ess_task *next; ++ task_t task_port; ++ char *name; ++ }; ++ ++/* These are linked lists of all of the registered items. */ ++static struct ess_task *ess_tasks; ++static struct ntfy_task *ntfy_tasks; ++ ++/* Our trivfs control structure. */ ++struct trivfs_control *control; ++ ++ ++ ++const char *argp_program_version = STANDARD_HURD_VERSION (shutdown); ++ ++/* Trivfs hooks. */ ++int trivfs_fstype = FSTYPE_MISC; ++int trivfs_fsid = 0; ++ ++int trivfs_allow_open = 0; ++int trivfs_support_read = 0; ++int trivfs_support_write = 0; ++int trivfs_support_exec = 0; ++ ++void ++trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) ++{ ++ /* Mark the node as a read-only plain file. */ ++ st->st_mode &= ~(S_IFMT | ALLPERMS); ++ st->st_mode |= (S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH); ++ st->st_size = 0; ++} ++ ++error_t ++trivfs_goaway (struct trivfs_control *cntl, int flags) ++{ ++ if (ntfy_tasks && (flags & FSYS_GOAWAY_FORCE) == 0) ++ return EBUSY; ++ ++ exit (0); ++} ++ ++/* Options processing. We accept the same options on the command line ++ and from fsys_set_options. */ ++ ++#define OPT_SUPERVISE -1 ++#define OPT_SYSTEM -2 ++static const struct argp_option options[] = ++{ ++ {"supervise", OPT_SUPERVISE, NULL, 0, ++ "Enable supervision of essential servers", 0}, ++ {"system", OPT_SYSTEM, NULL, 0, ++ "Actually shut down the system (requires privileges)", 0}, ++ {"crash-debug", 'H', NULL, 0, ++ "On system crash, go to the kernel debugger", 0}, ++ {0} ++}; ++ ++static error_t ++parse_opt (int opt, char *arg, struct argp_state *state) ++{ ++ switch (opt) ++ { ++ case 'H': ++ crash_flags = RB_DEBUGGER; ++ break; ++ ++ case OPT_SUPERVISE: ++ supervise = 1; ++ break; ++ ++ case OPT_SYSTEM: ++ system_mode = 1; ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ case ARGP_KEY_INIT: ++ case ARGP_KEY_SUCCESS: ++ case ARGP_KEY_ERROR: ++ break; ++ } ++ return 0; ++} ++ ++/* This will be called from libtrivfs to help construct the answer ++ to an fsys_get_options RPC. */ ++error_t ++trivfs_append_args (struct trivfs_control *fsys, ++ char **argz, size_t *argz_len) ++{ ++ error_t err = 0; ++ ++ if (! err && supervise) ++ err = argz_add (argz, argz_len, "--supervise"); ++ ++ if (! err && system_mode) ++ err = argz_add (argz, argz_len, "--system"); ++ ++ if (! err && crash_flags == RB_DEBUGGER) ++ err = argz_add (argz, argz_len, "--crash-debug"); ++ ++ return err; ++} ++ ++static const char doc[] = ++ "Supervise and shut down Hurd servers."; ++ ++static struct argp argp = ++ { ++ .options = options, ++ .parser = parse_opt, ++ .args_doc = NULL, ++ .doc = doc, ++ }; ++ ++/* Setting this variable makes libtrivfs use our argp to ++ parse options passed in an fsys_set_options RPC. */ ++struct argp *trivfs_runtime_argp = &argp; ++ ++static int ++demuxer (mach_msg_header_t *inp, ++ mach_msg_header_t *outp) ++{ ++ mig_routine_t routine; ++ if ((routine = startup_server_routine (inp)) || ++ (routine = NULL, trivfs_demuxer (inp, outp))) ++ { ++ if (routine) ++ (*routine) (inp, outp); ++ return TRUE; ++ } ++ else ++ return FALSE; ++} ++ ++static int ++isowner (trivfs_protid_t cred) ++{ ++ return idvec_contains (cred->user->uids, getuid ()); ++} ++ ++int ++main (int argc, char **argv) ++{ ++ error_t err; ++ mach_port_t bootstrap; ++ struct port_class *notification_class; ++ ++ /* We use the same argp for options available at startup ++ as for options we'll accept in an fsys_set_options RPC. */ ++ argp_parse (&argp, argc, argv, 0, 0, 0); ++ ++ err = get_privileged_ports (&host_priv, NULL); ++ if (err && system_mode) ++ error (1, err, "Must be started as root in system mode"); ++ ++ task_get_bootstrap_port (mach_task_self (), &bootstrap); ++ if (bootstrap == MACH_PORT_NULL) ++ error (1, 0, "Must be started as a translator"); ++ ++ /* Reply to our parent */ ++ err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &control); ++ if (err) ++ error (3, err, "trivfs_startup"); ++ ++ err = mach_port_deallocate (mach_task_self (), bootstrap); ++ assert_perror (err); ++ ++ notification_class = ports_create_class (NULL, NULL); ++ if (! notification_class) ++ error (1, errno, "ports_create_class"); ++ ++ err = ports_create_port (notification_class, control->pi.bucket, 0, ++ ¬ification); ++ if (err) ++ error (1, err, "ports_create_port"); ++ ++ /* Launch. */ ++ ports_manage_port_operations_one_thread (control->pi.bucket, demuxer, 0); ++ ++ return 0; ++} ++ ++ ++ ++/** System shutdown **/ ++ ++/* Reboot the microkernel. */ ++void ++reboot_mach (int flags) ++{ ++ error_t err; ++ ++ if (system_mode) ++ { ++ fprintf (stderr, "%s: %sing Mach (flags %#x)...\n", ++ program_invocation_short_name, BOOT (flags), flags); ++ sleep (5); ++ while ((err = host_reboot (host_priv, flags))) ++ error (0, err, "reboot"); ++ for (;;); ++ } ++ ++ err = startup_reboot (control->underlying, host_priv, flags); ++ if (err) ++ error (1, err, "Failed to contact next shutdown server"); ++ exit (EXIT_FAILURE); ++} ++ ++/* Reboot the microkernel, specifying that this is a crash. */ ++void ++crash_mach (void) ++{ ++ reboot_mach (crash_flags); ++} ++ ++/* Notify all tasks that have requested shutdown notifications. */ ++void ++notify_shutdown (const char *msg) ++{ ++ struct ntfy_task *n; ++ ++ for (n = ntfy_tasks; n != NULL; n = n->next) ++ { ++ error_t err; ++ fprintf (stderr, "%s: notifying %s of %s...", ++ program_invocation_short_name, n->name, msg); ++ err = startup_dosync (n->notify_port, ++ n->privileged ? privileged_timeout : timeout); ++ if (err == MACH_SEND_INVALID_DEST) ++ fprintf (stderr, "(no longer present)\n"); ++ else if (err) ++ fprintf (stderr, "%s\n", strerror (err)); ++ else ++ fprintf (stderr, "done\n"); ++ } ++} ++ ++/* Reboot the Hurd. */ ++void ++reboot_system (int flags) ++{ ++ notify_shutdown (BOOT (flags)); ++ reboot_mach (flags); ++} ++ ++/* Request a dead-name notification sent to our port. */ ++static error_t ++request_dead_name (mach_port_t name) ++{ ++ error_t err; ++ mach_port_t prev; ++ err = mach_port_request_notification (mach_task_self (), name, ++ MACH_NOTIFY_DEAD_NAME, 1, ++ notification->port_right, ++ MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev); ++ if (! err && MACH_PORT_VALID (prev)) ++ mach_port_deallocate (mach_task_self (), prev); ++ return err; ++} ++ ++/* Record an essential task in the list. */ ++static error_t ++record_essential_task (const char *name, task_t task) ++{ ++ error_t err; ++ struct ess_task *et; ++ /* Record this task as essential. */ ++ et = malloc (sizeof (struct ess_task)); ++ if (et == NULL) ++ return ENOMEM; ++ et->task_port = task; ++ et->name = strdup (name); ++ if (et->name == NULL) ++ { ++ free (et); ++ return ENOMEM; ++ } ++ et->next = ess_tasks; ++ ess_tasks = et; ++ ++ /* Dead-name notification on the task port will tell us when it dies. */ ++ err = request_dead_name (task); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++kern_return_t ++S_startup_essential_task (trivfs_protid_t cred, ++ mach_port_t reply, ++ mach_msg_type_name_t replytype, ++ task_t task, ++ mach_port_t excpt, ++ char *name, ++ mach_port_t credential) ++{ ++ error_t err; ++ mach_port_deallocate (mach_task_self (), credential); ++ ++ if (! cred->isroot && ! isowner (cred)) ++ return EPERM; ++ ++ if (system_mode && credential != host_priv) ++ return EPERM; ++ ++ if (! supervise) ++ return EOPNOTSUPP; ++ ++ err = record_essential_task (name, task); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++kern_return_t ++S_startup_request_notification (trivfs_protid_t cred, ++ mach_port_t notify, ++ char *name) ++{ ++ error_t err; ++ struct ntfy_task *nt; ++ ++ err = request_dead_name (notify); ++ if (err) ++ return err; ++ ++ /* Note that the ntfy_tasks list is kept in inverse order of the ++ calls; this is important. We need later notification requests ++ to get executed first. */ ++ nt = malloc (sizeof (struct ntfy_task)); ++ if (nt == NULL) ++ return ENOMEM; ++ nt->next = ntfy_tasks; ++ nt->notify_port = notify; ++ nt->privileged = cred->isroot; ++ nt->name = strdup (name); ++ ntfy_tasks = nt; ++ return 0; ++} ++ ++kern_return_t ++S_startup_procinit (trivfs_protid_t cred, ++ mach_port_t reply, ++ mach_msg_type_name_t replyPoly, ++ process_t procserver, ++ mach_port_t *startuptask, ++ auth_t *auth, ++ mach_port_t *hostpriv, ++ mach_msg_type_name_t *hostprivPoly, ++ mach_port_t *devmaster, ++ mach_msg_type_name_t *devmasterPoly) ++{ ++ return EOPNOTSUPP; ++} ++ ++kern_return_t ++S_startup_authinit (trivfs_protid_t cred, ++ mach_port_t reply, ++ mach_msg_type_name_t replyPoly, ++ mach_port_t auth, ++ mach_port_t *proc, ++ mach_msg_type_name_t *procPoly) ++{ ++ return EOPNOTSUPP; ++} ++ ++error_t ++ports_do_mach_notify_dead_name (struct port_info *pi, ++ mach_port_t dead_name) ++{ ++ error_t err; ++ struct ntfy_task *nt, *pnt; ++ struct ess_task *et; ++ ++ if (!pi) ++ return EOPNOTSUPP; ++ ++ ports_dead_name (pi, dead_name); ++ ++ /* Drop gratuitous extra reference that the notification creates. */ ++ err = mach_port_deallocate (mach_task_self (), dead_name); ++ assert_perror (err); ++ ++ if (pi != notification) ++ return 0; ++ ++ for (et = ess_tasks; et != NULL; et = et->next) ++ if (et->task_port == dead_name) ++ /* An essential task has died. */ ++ { ++ error (0, 0, "Crashing system; essential task %s died", et->name); ++ reboot_system (crash_flags); ++ } ++ ++ for (nt = ntfy_tasks, pnt = NULL; nt != NULL; pnt = nt, nt = nt->next) ++ if (nt->notify_port == dead_name) ++ { ++ /* Someone who wanted to be notified is gone. */ ++ err = mach_port_deallocate (mach_task_self (), dead_name); ++ assert_perror (err); ++ if (pnt != NULL) ++ pnt->next = nt->next; ++ else ++ ntfy_tasks = nt->next; ++ free (nt); ++ ++ return 0; ++ } ++ ++ return 0; ++} ++ ++kern_return_t ++S_startup_reboot (trivfs_protid_t cred, ++ mach_port_t refpt, ++ int code) ++{ ++ mach_port_deallocate (mach_task_self (), refpt); ++ ++ if (! cred->isroot && ! isowner (cred)) ++ return EPERM; ++ ++ if (system_mode && refpt != host_priv) ++ return EPERM; ++ ++ reboot_system (code); ++ for (;;); ++} +-- +2.1.4 + diff --git a/debian/patches/shutdown0002-xxx-halt-hack.patch b/debian/patches/shutdown0002-xxx-halt-hack.patch new file mode 100644 index 00000000..83792752 --- /dev/null +++ b/debian/patches/shutdown0002-xxx-halt-hack.patch @@ -0,0 +1,45 @@ +From 8ff13a86d9a26a479164ea251eb0d3c00b95c726 Mon Sep 17 00:00:00 2001 +From: Justus Winter <justus@gnupg.org> +Date: Fri, 22 Apr 2016 02:53:44 +0200 +Subject: [PATCH hurd 2/2] xxx halt hack + +--- + sutils/halt.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/sutils/halt.c b/sutils/halt.c +index 08f754c..4d36ca2 100644 +--- a/sutils/halt.c ++++ b/sutils/halt.c +@@ -25,6 +25,8 @@ + #include <argp.h> + #include <error.h> + #include <hurd.h> ++#include <hurd/paths.h> ++#include <hurd/startup.h> + #include <version.h> + + const char *argp_program_version = STANDARD_HURD_VERSION (halt); +@@ -32,9 +34,17 @@ const char *argp_program_version = STANDARD_HURD_VERSION (halt); + int + main (int argc, char *argv[]) + { ++ error_t err; ++ file_t server; + struct argp argp = {0, 0, 0, "Halt the system"}; + argp_parse (&argp, argc, argv, 0, 0, 0); +- reboot (RB_HALT); +- error (1, errno, "reboot"); ++ ++ server = file_name_lookup (_SERVERS_STARTUP, 0, 0); ++ if (! MACH_PORT_VALID (server)) ++ error (1, errno, _HURD_STARTUP); ++ ++ err = startup_reboot (server, MACH_PORT_NULL, RB_HALT); ++ if (err) ++ error (1, err, "reboot"); + return 1; + } +-- +2.1.4 + |