diff options
-rw-r--r-- | debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch | 631 | ||||
-rw-r--r-- | debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch | 457 | ||||
-rw-r--r-- | debian/patches/series | 2 |
3 files changed, 1090 insertions, 0 deletions
diff --git a/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch b/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch new file mode 100644 index 00000000..128c212e --- /dev/null +++ b/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch @@ -0,0 +1,631 @@ +From 74fb5209f06edcf0b52bdf44ba805cb5f6cd41c8 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Sun, 31 May 2015 00:26:40 +0200 +Subject: [PATCH hurd 1/2] utils: split-off the message id parsing + +* utils/rpctrace.c: Move all the code handling the message id files... +* utils/msgids.c: ... to a new file. +* utils/msgids.h: And add the relevand declarations. +* utils/Makefile (SRCS): Add the new file. +--- + utils/Makefile | 8 +- + utils/msgids.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + utils/msgids.h | 33 ++++++++ + utils/rpctrace.c | 202 ++------------------------------------------ + 4 files changed, 298 insertions(+), 197 deletions(-) + create mode 100644 utils/msgids.c + create mode 100644 utils/msgids.h + +diff --git a/utils/Makefile b/utils/Makefile +index 1117be1..9ad2a40 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -31,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ + parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ + unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ + rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ +- nullauth.c match-options.c ++ nullauth.c match-options.c msgids.c + + OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) + HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc +@@ -67,8 +67,10 @@ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ + + $(filter-out $(special-targets), $(targets)): %: %.o + +-rpctrace: ../libports/libports.a ../libihash/libihash.a +-rpctrace-CPPFLAGS = -DDATADIR=\"${datadir}\" ++rpctrace: ../libports/libports.a ++rpctrace: msgids.o \ ++ ../libihash/libihash.a ++msgids-CPPFLAGS = -DDATADIR=\"${datadir}\" + + fakeauth: authServer.o auth_requestUser.o interruptServer.o \ + ../libports/libports.a ../libihash/libihash.a \ +diff --git a/utils/msgids.c b/utils/msgids.c +new file mode 100644 +index 0000000..4bc08de +--- /dev/null ++++ b/utils/msgids.c +@@ -0,0 +1,252 @@ ++/* Translate message ids to symbolic names. ++ ++ Copyright (C) 1998-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. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#include <argp.h> ++#include <argz.h> ++#include <dirent.h> ++#include <errno.h> ++#include <error.h> ++#include <fnmatch.h> ++#include <hurd/ihash.h> ++#include <mach.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#include "msgids.h" ++ ++static void ++msgid_ihash_cleanup (void *element, void *arg) ++{ ++ struct msgid_info *info = element; ++ free (info->name); ++ free (info->subsystem); ++ free (info); ++} ++ ++static struct hurd_ihash msgid_ihash ++ = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); ++ ++/* Parse a file of RPC names and message IDs as output by mig's -list ++ option: "subsystem base-id routine n request-id reply-id". Put each ++ request-id value into `msgid_ihash' with the routine name as its value. */ ++static error_t ++parse_msgid_list (const char *filename) ++{ ++ FILE *fp; ++ char *buffer = NULL; ++ size_t bufsize = 0; ++ unsigned int lineno = 0; ++ char *name, *subsystem; ++ unsigned int msgid; ++ error_t err; ++ ++ fp = fopen (filename, "r"); ++ if (fp == NULL) ++ return errno; ++ ++ while (getline (&buffer, &bufsize, fp) > 0) ++ { ++ ++lineno; ++ if (buffer[0] == '#' || buffer[0] == '\0') ++ continue; ++ if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n", ++ &subsystem, &name, &msgid) != 3) ++ error (0, 0, "%s:%u: invalid format in RPC list file", ++ filename, lineno); ++ else ++ { ++ struct msgid_info *info = malloc (sizeof *info); ++ if (info == 0) ++ error (1, errno, "malloc"); ++ info->name = name; ++ info->subsystem = subsystem; ++ err = hurd_ihash_add (&msgid_ihash, msgid, info); ++ if (err) ++ return err; ++ } ++ } ++ ++ free (buffer); ++ fclose (fp); ++ return 0; ++} ++ ++/* Look for a name describing MSGID. We check the table directly, and ++ also check if this looks like the ID of a reply message whose request ++ ID is already in the table. */ ++const struct msgid_info * ++msgid_info (mach_msg_id_t msgid) ++{ ++ const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid); ++ if (info == 0 && (msgid / 100) % 2 == 1) ++ { ++ /* This message ID is not in the table, and its number makes it ++ what should be an RPC reply message ID. So look up the message ++ ID of the corresponding RPC request and synthesize a name from ++ that. Then stash that name in the table so the next time the ++ lookup will match directly. */ ++ info = hurd_ihash_find (&msgid_ihash, msgid - 100); ++ if (info != 0) ++ { ++ struct msgid_info *reply_info = malloc (sizeof *info); ++ if (reply_info != 0) ++ { ++ reply_info->subsystem = strdup (info->subsystem); ++ reply_info->name = 0; ++ asprintf (&reply_info->name, "%s-reply", info->name); ++ hurd_ihash_add (&msgid_ihash, msgid, reply_info); ++ info = reply_info; ++ } ++ else ++ info = 0; ++ } ++ } ++ return info; ++} ++ ++static int ++msgids_file_p (const struct dirent *eps) ++{ ++ return fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH; ++} ++ ++static void ++scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append) ++{ ++ struct dirent **eps; ++ int n; ++ ++ n = scandir (dir, &eps, msgids_file_p, NULL); ++ if (n >= 0) ++ { ++ for (int cnt = 0; cnt < n; ++cnt) ++ { ++ char *msgids_file; ++ ++ if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0) ++ error (1, errno, "asprintf"); ++ ++ if (append == TRUE) ++ { ++ if (argz_add (argz, argz_len, msgids_file) != 0) ++ error (1, errno, "argz_add"); ++ } ++ else ++ { ++ if (argz_insert (argz, argz_len, *argz, msgids_file) != 0) ++ error (1, errno, "argz_insert"); ++ } ++ free (msgids_file); ++ } ++ } ++ ++ /* If the directory couldn't be scanned for whatever reason, just ignore ++ it. */ ++} ++ ++/* Argument parsing. */ ++ ++static char *msgids_files_argz = NULL; ++static size_t msgids_files_argz_len = 0; ++static bool nostdinc = FALSE; ++ ++#define STD_MSGIDS_DIR DATADIR "/msgids/" ++#define OPT_NOSTDINC -1 ++ ++static const struct argp_option options[] = ++{ ++ {"nostdinc", OPT_NOSTDINC, 0, 0, ++ "Do not search inside the standard system directory, `" STD_MSGIDS_DIR ++ "', for `.msgids' files.", 0}, ++ {"rpc-list", 'i', "FILE", 0, ++ "Read FILE for assocations of message ID numbers to names.", 0}, ++ {0, 'I', "DIR", 0, ++ "Add the directory DIR to the list of directories to be searched for files " ++ "containing message ID numbers.", 0}, ++ {0} ++}; ++ ++/* Parse our options... */ ++static error_t parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ switch (key) ++ { ++ case ARGP_KEY_INIT: ++ hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0); ++ break; ++ ++ case OPT_NOSTDINC: ++ nostdinc = TRUE; ++ break; ++ ++ case 'i': ++ if (argz_add (&msgids_files_argz, &msgids_files_argz_len, ++ arg) != 0) ++ error (1, errno, "argz_add"); ++ break; ++ ++ case 'I': ++ scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, ++ arg, TRUE); ++ break; ++ ++ case ARGP_KEY_NO_ARGS: ++ return 0; ++ ++ case ARGP_KEY_ARG: ++ return EINVAL; ++ ++ case ARGP_KEY_END: ++ /* Insert the files from STD_MSGIDS_DIR at the beginning of the ++ list, so that their content can be overridden by subsequently ++ parsed files. */ ++ if (nostdinc == FALSE) ++ scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, ++ STD_MSGIDS_DIR, FALSE); ++ ++ if (msgids_files_argz != NULL) ++ { ++ error_t err = 0; ++ char *msgids_file = NULL; ++ ++ while (! err ++ && (msgids_file = argz_next (msgids_files_argz, ++ msgids_files_argz_len, ++ msgids_file))) ++ err = parse_msgid_list (msgids_file); ++ ++ free (msgids_files_argz); ++ if (err) ++ argp_failure (state, 1, err, "%s", msgids_file); ++ } ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ return 0; ++} ++ ++const struct argp msgid_argp = { ++ .options = options, ++ .parser = parse_opt, ++ .doc = "msgid doc", ++}; +diff --git a/utils/msgids.h b/utils/msgids.h +new file mode 100644 +index 0000000..6bd2372 +--- /dev/null ++++ b/utils/msgids.h +@@ -0,0 +1,33 @@ ++/* Translate message ids to symbolic names. ++ ++ Copyright (C) 1998-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. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#ifndef _HURD_MSGIDS_H_ ++#define _HURD_MSGIDS_H_ ++ ++/* We map message ids to procedure and subsystem names. */ ++struct msgid_info ++{ ++ char *name; ++ char *subsystem; ++}; ++ ++const struct msgid_info *msgid_info (mach_msg_id_t msgid); ++const struct argp msgid_argp; ++ ++#endif /* _HURD_MSGIDS_H_ */ +diff --git a/utils/rpctrace.c b/utils/rpctrace.c +index 48daa07..d53b510 100644 +--- a/utils/rpctrace.c ++++ b/utils/rpctrace.c +@@ -26,9 +26,7 @@ + #include <mach/message.h> + #include <assert.h> + #include <fcntl.h> +-#include <fnmatch.h> + #include <sys/stat.h> +-#include <dirent.h> + #include <unistd.h> + #include <argp.h> + #include <error.h> +@@ -41,24 +39,15 @@ + #include <argz.h> + #include <envz.h> + +-const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); ++#include "msgids.h" + +-#define STD_MSGIDS_DIR DATADIR "/msgids/" ++const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); + + static unsigned strsize = 80; + +-#define OPT_NOSTDINC -1 + static const struct argp_option options[] = + { + {"output", 'o', "FILE", 0, "Send trace output to FILE instead of stderr."}, +- {"nostdinc", OPT_NOSTDINC, 0, 0, +- "Do not search inside the standard system directory, `" STD_MSGIDS_DIR +- "', for `.msgids' files."}, +- {"rpc-list", 'i', "FILE", 0, +- "Read FILE for assocations of message ID numbers to names."}, +- {0, 'I', "DIR", 0, +- "Add the directory DIR to the list of directories to be searched for files " +- "containing message ID numbers."}, + {0, 's', "SIZE", 0, "Specify the maximum string size to print (the default is 80)."}, + {0, 'E', "var[=value]", 0, + "Set/change (var=value) or remove (var) an environment variable among the " +@@ -71,23 +60,6 @@ static const struct argp_option options[] = + static const char args_doc[] = "COMMAND [ARG...]"; + static const char doc[] = "Trace Mach Remote Procedure Calls."; + +-/* The msgid_ihash table maps msgh_id values to names. */ +- +-struct msgid_info +-{ +- char *name; +- char *subsystem; +-}; +- +-static void +-msgid_ihash_cleanup (void *element, void *arg) +-{ +- struct msgid_info *info = element; +- free (info->name); +- free (info->subsystem); +- free (info); +-} +- + /* This structure stores the information of the traced task. */ + struct task_info + { +@@ -95,9 +67,6 @@ struct task_info + boolean_t threads_wrapped; /* All threads of the task has been wrapped? */ + }; + +-static struct hurd_ihash msgid_ihash +- = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); +- + static struct hurd_ihash task_ihash + = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); + +@@ -126,86 +95,6 @@ remove_task (task_t task) + hurd_ihash_remove (&task_ihash, task); + } + +-/* Parse a file of RPC names and message IDs as output by mig's -list +- option: "subsystem base-id routine n request-id reply-id". Put each +- request-id value into `msgid_ihash' with the routine name as its value. */ +-static void +-parse_msgid_list (const char *filename) +-{ +- FILE *fp; +- char *buffer = NULL; +- size_t bufsize = 0; +- unsigned int lineno = 0; +- char *name, *subsystem; +- unsigned int msgid; +- error_t err; +- +- fp = fopen (filename, "r"); +- if (fp == 0) +- { +- error (2, errno, "%s", filename); +- return; +- } +- +- while (getline (&buffer, &bufsize, fp) > 0) +- { +- ++lineno; +- if (buffer[0] == '#' || buffer[0] == '\0') +- continue; +- if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n", +- &subsystem, &name, &msgid) != 3) +- error (0, 0, "%s:%u: invalid format in RPC list file", +- filename, lineno); +- else +- { +- struct msgid_info *info = malloc (sizeof *info); +- if (info == 0) +- error (1, errno, "malloc"); +- info->name = name; +- info->subsystem = subsystem; +- err = hurd_ihash_add (&msgid_ihash, msgid, info); +- if (err) +- error (1, err, "hurd_ihash_add"); +- } +- } +- +- free (buffer); +- fclose (fp); +-} +- +-/* Look for a name describing MSGID. We check the table directly, and +- also check if this looks like the ID of a reply message whose request +- ID is already in the table. */ +-static const struct msgid_info * +-msgid_info (mach_msg_id_t msgid) +-{ +- const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid); +- if (info == 0 && (msgid / 100) % 2 == 1) +- { +- /* This message ID is not in the table, and its number makes it +- what should be an RPC reply message ID. So look up the message +- ID of the corresponding RPC request and synthesize a name from +- that. Then stash that name in the table so the next time the +- lookup will match directly. */ +- info = hurd_ihash_find (&msgid_ihash, msgid - 100); +- if (info != 0) +- { +- struct msgid_info *reply_info = malloc (sizeof *info); +- if (reply_info != 0) +- { +- reply_info->subsystem = strdup (info->subsystem); +- reply_info->name = 0; +- asprintf (&reply_info->name, "%s-reply", info->name); +- hurd_ihash_add (&msgid_ihash, msgid, reply_info); +- info = reply_info; +- } +- else +- info = 0; +- } +- } +- return info; +-} +- + static const char * + msgid_name (mach_msg_id_t msgid) + { +@@ -1781,55 +1670,9 @@ traced_spawn (char **argv, char **envp) + return pid; + } + +- +-static void +-scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append) +-{ +- struct dirent **eps; +- int n; +- +- int +- msgids_file_p (const struct dirent *eps) +- { +- if (fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH) +- return 1; +- return 0; +- } +- +- n = scandir (dir, &eps, msgids_file_p, NULL); +- if (n >= 0) +- { +- for (int cnt = 0; cnt < n; ++cnt) +- { +- char *msgids_file; +- +- if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0) +- error (1, errno, "asprintf"); +- +- if (append == TRUE) +- { +- if (argz_add (argz, argz_len, msgids_file) != 0) +- error (1, errno, "argz_add"); +- } +- else +- { +- if (argz_insert (argz, argz_len, *argz, msgids_file) != 0) +- error (1, errno, "argz_insert"); +- } +- free (msgids_file); +- } +- } +- +- /* If the directory couldn't be scanned for whatever reason, just ignore +- it. */ +-} +- + int + main (int argc, char **argv, char **envp) + { +- char *msgids_files_argz = NULL; +- size_t msgids_files_argz_len = 0; +- bool nostdinc = FALSE; + const char *outfile = 0; + char **cmd_argv = 0; + pthread_t thread; +@@ -1847,21 +1690,6 @@ main (int argc, char **argv, char **envp) + outfile = arg; + break; + +- case OPT_NOSTDINC: +- nostdinc = TRUE; +- break; +- +- case 'i': +- if (argz_add (&msgids_files_argz, &msgids_files_argz_len, +- arg) != 0) +- error (1, errno, "argz_add"); +- break; +- +- case 'I': +- scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, +- arg, TRUE); +- break; +- + case 's': + strsize = atoi (arg); + break; +@@ -1908,7 +1736,12 @@ main (int argc, char **argv, char **envp) + } + return 0; + } +- const struct argp argp = { options, parse_opt, args_doc, doc }; ++ const struct argp_child children[] = ++ { ++ { .argp=&msgid_argp, }, ++ { 0 } ++ }; ++ const struct argp argp = { options, parse_opt, args_doc, doc, &children }; + + /* Parse our arguments. */ + argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); +@@ -1917,23 +1750,6 @@ main (int argc, char **argv, char **envp) + &unknown_task); + assert_perror (err); + +- /* Insert the files from STD_MSGIDS_DIR at the beginning of the list, so that +- their content can be overridden by subsequently parsed files. */ +- if (nostdinc == FALSE) +- scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len, +- STD_MSGIDS_DIR, FALSE); +- +- if (msgids_files_argz != NULL) +- { +- char *msgids_file = NULL; +- +- while ((msgids_file = argz_next (msgids_files_argz, +- msgids_files_argz_len, msgids_file))) +- parse_msgid_list (msgids_file); +- +- free (msgids_files_argz); +- } +- + if (outfile) + { + ostream = fopen (outfile, "w"); +@@ -1951,8 +1767,6 @@ main (int argc, char **argv, char **envp) + sizeof (*notify_pi), ¬ify_pi); + assert_perror (err); + +- hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0); +- + /* Spawn a single thread that will receive intercepted messages, print + them, and interpose on the ports they carry. The access to the + `traced_info' and ihash data structures is all single-threaded, +-- +2.1.4 + diff --git a/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch b/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch new file mode 100644 index 00000000..5ea67a3d --- /dev/null +++ b/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch @@ -0,0 +1,457 @@ +From 566a246f2c2881f1598d376032f9f73427790feb Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Fri, 29 May 2015 16:37:00 +0200 +Subject: [PATCH hurd 2/2] utils/rpcscan: new utility + +* utils/rpcscan.c: New file. +* utils/Makefile: Add `rpcscan'. +--- + utils/Makefile | 6 +- + utils/rpcscan.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 407 insertions(+), 3 deletions(-) + create mode 100644 utils/rpcscan.c + +diff --git a/utils/Makefile b/utils/Makefile +index 9ad2a40..955789b 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -22,7 +22,7 @@ targets = shd ps settrans showtrans syncfs fsysopts \ + storeinfo login w uptime ids loginpr sush vmstat portinfo \ + devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \ + storeread msgport rpctrace mount gcore fakeauth fakeroot remap \ +- umount nullauth ++ umount nullauth rpcscan + + special-targets = loginpr sush uptime fakeroot remap + SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ +@@ -31,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ + parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ + unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ + rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ +- nullauth.c match-options.c msgids.c ++ nullauth.c match-options.c msgids.c rpcscan.c + + OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) + HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc +@@ -68,7 +68,7 @@ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ + $(filter-out $(special-targets), $(targets)): %: %.o + + rpctrace: ../libports/libports.a +-rpctrace: msgids.o \ ++rpctrace rpcscan: msgids.o \ + ../libihash/libihash.a + msgids-CPPFLAGS = -DDATADIR=\"${datadir}\" + +diff --git a/utils/rpcscan.c b/utils/rpcscan.c +new file mode 100644 +index 0000000..e32c016 +--- /dev/null ++++ b/utils/rpcscan.c +@@ -0,0 +1,404 @@ ++/* An RPC scanner for the Hurd. ++ ++ Copyright (C) 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. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#include <mach.h> ++#include <hurd.h> ++#include <hurd/ihash.h> ++#include <mach/message.h> ++#include <unistd.h> ++#include <argp.h> ++#include <error.h> ++#include <string.h> ++#include <version.h> ++#include <sys/wait.h> ++#include <inttypes.h> ++#include <stdbool.h> ++#include <stddef.h> ++#include <argz.h> ++ ++#include "msgids.h" ++ ++/* Send messages with arbitrary message ids. */ ++struct Request { ++ mach_msg_header_t Head; ++} RequestTemplate; ++ ++struct Reply { ++ mach_msg_header_t Head; ++ mach_msg_type_t RetCodeType; ++ kern_return_t RetCode; ++ char Body[4096]; ++}; ++ ++union { ++ struct Request Request; ++ struct Reply Reply; ++} Message; ++ ++error_t ++setup (mach_port_t request, mach_msg_type_name_t requestType) ++{ ++ RequestTemplate.Head.msgh_remote_port = request; ++ if (! MACH_PORT_VALID (RequestTemplate.Head.msgh_local_port)) ++ RequestTemplate.Head.msgh_local_port = mach_reply_port (); ++ RequestTemplate.Head.msgh_bits = ++ MACH_MSGH_BITS (requestType, MACH_MSG_TYPE_MAKE_SEND_ONCE); ++ return 0; ++} ++ ++error_t ++send (mach_msg_id_t msgid) ++{ ++ error_t err; ++ Message.Request = RequestTemplate; ++ Message.Request.Head.msgh_id = msgid; ++ err = mach_msg (&Message.Request.Head, ++ MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, ++ sizeof Message.Request, ++ sizeof Message.Reply, ++ Message.Request.Head.msgh_local_port, ++ MACH_MSG_TIMEOUT_NONE, ++ MACH_PORT_NULL); ++ if (err) ++ return err; ++ ++ // xxx typecheck ++ return Message.Reply.RetCode; ++} ++ ++typedef error_t (*setup_function_t) (); ++setup_function_t setup_target; ++void *setup_argument; ++ ++error_t ++setup_task_target (void) ++{ ++ error_t err; ++ static task_t task; ++ static mach_msg_type_name_t taskType = MACH_MSG_TYPE_COPY_SEND; ++ ++ if (MACH_PORT_VALID (task)) ++ { ++ task_terminate (task); ++ mach_port_deallocate (mach_task_self (), task); ++ } ++ ++ err = task_create (mach_task_self (), 0, &task); ++ if (err) ++ return err; ++ ++ return setup (task, taskType); ++} ++ ++error_t ++setup_thread_target (void) ++{ ++ error_t err; ++ static task_t task; ++ static thread_t thread; ++ ++ if (MACH_PORT_VALID (thread)) ++ { ++ thread_terminate (thread); ++ mach_port_deallocate (mach_task_self (), thread); ++ } ++ ++ if (MACH_PORT_VALID (task)) ++ { ++ task_terminate (task); ++ mach_port_deallocate (mach_task_self (), task); ++ } ++ ++ err = task_create (mach_task_self (), 0, &task); ++ if (err) ++ return err; ++ ++ err = thread_create (task, &thread); ++ if (err) ++ return err; ++ ++ return setup (thread, MACH_MSG_TYPE_COPY_SEND); ++} ++ ++error_t ++setup_proc_target (void) ++{ ++ error_t err; ++ static task_t task; ++ static process_t proc, target; ++ static mach_msg_type_name_t targetType = MACH_MSG_TYPE_COPY_SEND; ++ ++ if (! MACH_PORT_VALID (proc)) ++ proc = getproc (); ++ if (MACH_PORT_VALID (task)) ++ mach_port_deallocate (mach_task_self (), task); ++ if (MACH_PORT_VALID (target)) ++ mach_port_deallocate (mach_task_self (), target); ++ ++ err = task_create (mach_task_self (), 0, &task); ++ if (err) ++ return err; ++ ++ err = proc_task2proc (proc, task, &target); ++ if (err) ++ return err; ++ ++ return setup (target, targetType); ++} ++ ++error_t ++setup_auth_target (void) ++{ ++ static auth_t auth; ++ static mach_msg_type_name_t authType = MACH_MSG_TYPE_COPY_SEND; ++ ++ if (MACH_PORT_VALID (auth)) ++ mach_port_deallocate (mach_task_self (), auth); ++ ++ auth = getauth (); ++ if (! MACH_PORT_VALID (auth)) ++ return errno; ++ ++ return setup (auth, authType); ++} ++ ++error_t ++setup_hurd_target (void) ++{ ++ char *name = (char *) setup_argument; ++ mach_port_t request; ++ mach_msg_type_name_t requestType; ++ ++ request = file_name_lookup (name, 0, 0); ++ if (! MACH_PORT_VALID (request)) ++ return errno; ++ requestType = MACH_MSG_TYPE_COPY_SEND; ++ ++ return setup (request, requestType); ++} ++ ++task_t extract_target_task; ++mach_port_t extract_target_port; ++mach_msg_type_name_t extract_target_type; ++ ++error_t ++setup_extract_target (void) ++{ ++ error_t err; ++ char *name = (char *) setup_argument; ++ mach_port_t request; ++ mach_msg_type_name_t requestType; ++ ++ err = mach_port_extract_right (extract_target_task, ++ extract_target_port, ++ extract_target_type, ++ &request, ++ &requestType); ++ if (err) ++ error (1, err, "mach_port_extract_right"); ++ if (err) ++ return err; ++ requestType = MACH_MSG_TYPE_COPY_SEND; ++ return setup (request, requestType); ++} ++ ++const char *argp_program_version = STANDARD_HURD_VERSION (rpcscan); ++ ++char **cmd_argv; ++int verbose; ++int numeric; ++int subsystem; ++ ++#define OPT_TARGET_TASK -1 ++#define OPT_TARGET_THREAD -2 ++#define OPT_TARGET_PROC -3 ++#define OPT_TARGET_AUTH -4 ++#define OPT_TARGET_EXTRACT -5 ++ ++static const struct argp_option options[] = ++{ ++ {NULL, 0, NULL, OPTION_DOC, "Target selection", 1}, ++ {"task", OPT_TARGET_TASK, NULL, 0, "target a task port", 1}, ++ {"thread", OPT_TARGET_THREAD, NULL, 0, "target a thread port", 1}, ++ {"proc", OPT_TARGET_PROC, NULL, 0, "target a proc port", 1}, ++ {"auth", OPT_TARGET_AUTH, NULL, 0, "target an auth port", 1}, ++ {"extract", OPT_TARGET_EXTRACT, "PID.PORT", 0, "target port PORT of PID", 1}, ++ ++ {NULL, 0, NULL, OPTION_DOC, "Options", 2}, ++ {"verbose", 'v', NULL, 0, "be verbose", 2}, ++ {"numeric", 'n', NULL, 0, "show numeric message ids", 2}, ++ {"subsystem", 's', NULL, 0, "show subsystem names", 2}, ++ {0} ++}; ++ ++static const char args_doc[] = "[FILE]"; ++static const char doc[] = "Scan a given Mach port."; ++ ++/* Parse our options... */ ++error_t ++parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ error_t err; ++ switch (key) ++ { ++ case 'v': ++ verbose = 1; ++ break; ++ ++ case 'n': ++ numeric = 1; ++ break; ++ ++ case 's': ++ subsystem = 1; ++ break; ++ ++#define SELECT_TARGET(target) \ ++ if (setup_target) \ ++ argp_error (state, "Multiple targets specified."); \ ++ setup_target = target; ++ ++ case OPT_TARGET_TASK: ++ SELECT_TARGET (setup_task_target); ++ break; ++ ++ case OPT_TARGET_THREAD: ++ SELECT_TARGET (setup_thread_target); ++ break; ++ ++ case OPT_TARGET_PROC: ++ SELECT_TARGET (setup_proc_target); ++ break; ++ ++ case OPT_TARGET_AUTH: ++ SELECT_TARGET (setup_auth_target); ++ break; ++ ++ case OPT_TARGET_EXTRACT:; ++ process_t proc; ++ pid_t pid; ++ char *end; ++ ++ pid = strtol (arg, &end, 10); ++ if (arg == end || *end != '.') ++ argp_error (state, "Expected format PID.PORT, got `%s'.", arg); ++ ++ arg = end + 1; ++ extract_target_port = strtol (arg, &end, 10); ++ if (arg == end || *end != '\0') ++ argp_error (state, "Expected format PORT, got `%s'.", arg); ++ ++ proc = getproc (); ++ err = proc_pid2task (proc, pid, &extract_target_task); ++ if (err) ++ argp_failure (state, 1, err, ++ "Could not get task of process %d", pid); ++ ++ extract_target_type = MACH_MSG_TYPE_COPY_SEND; /* XXX */ ++ SELECT_TARGET (setup_extract_target); ++ break; ++ ++ case ARGP_KEY_ARG: ++ SELECT_TARGET (setup_hurd_target); ++ setup_argument = arg; ++ break; ++#undef SELECT_TARGET ++ ++ case ARGP_KEY_NO_ARGS: ++ if (setup_target == NULL) ++ argp_usage (state); ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ return 0; ++} ++ ++const struct argp_child children[] = ++ { ++ { .argp=&msgid_argp, }, ++ { 0 } ++ }; ++ ++const struct argp argp = { options, parse_opt, args_doc, doc, &children }; ++ ++void ++format_msgid (char *buf, size_t len, mach_msg_id_t id) ++{ ++ if (numeric) ++ numeric: ++ snprintf (buf, len, "%d", id); ++ else ++ { ++ const struct msgid_info *info; ++ info = msgid_info (id); ++ if (info == NULL) ++ goto numeric; ++ ++ if (subsystem) ++ snprintf (buf, len, "%s/%s", info->subsystem, info->name); ++ else ++ snprintf (buf, len, "%s", info->name); ++ } ++} ++ ++int ++main (int argc, char **argv, char **envp) ++{ ++ error_t err; ++ mach_msg_id_t msgid; ++ ++ /* Parse our arguments. */ ++ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); ++ ++ err = setup_target (); ++ if (err) ++ /* Initial setup failed. Bail out. */ ++ error (1, err, "%s", ++ setup_target == setup_hurd_target? (char *) setup_argument: "setup"); ++ ++ for (msgid = 0; msgid < 500000; msgid++) ++ { ++ err = send (msgid); ++ switch (err) ++ { ++ case MACH_SEND_INVALID_DEST: ++ err = setup_target (); ++ if (err) ++ error (1, err, "setup"); ++ msgid--; /* redo */ ++ continue; ++ ++ case MIG_BAD_ID: ++ /* do nothing */ ++ break; ++ ++ default:; ++ char buf[80]; ++ format_msgid (buf, sizeof buf, msgid); ++ if (verbose) ++ error (0, err, "%s", buf); ++ else ++ fprintf (stdout, "%s\n", buf); ++ } ++ } ++ ++ return EXIT_SUCCESS; ++} +-- +2.1.4 + diff --git a/debian/patches/series b/debian/patches/series index 14754761..bc3855a7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -69,3 +69,5 @@ exec_filename_use.patch exec_filename_fix.patch huge-nodecache0001-xxx-huge-nodecache.patch dde-enable-device.patch +rpcscan0001-utils-split-off-the-message-id-parsing.patch +rpcscan0002-utils-rpcscan-new-utility.patch |