From 8212e7002976ac716f7429e985ed276a08717076 Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Fri, 14 Aug 2009 17:31:11 +0100 Subject: [PATCH] devfsctl - Disable ruletab support; use proper working dirs * Disable (temporarily) all ruletab support in devfsctl. * If a configuration file cannot be found, it is searched after in the default directory (/etc/devfs) before erroring out. * When including a file in some other directory, the working directory is temporarily changed to that dir, so that further includes work as intended. After each include, the working directory is restored to the previous one. * Make sure that all configuration files are owned by root so the system is protected from malicious rule files. --- usr.sbin/devfsctl/devfsctl.c | 57 +++++++++++++++++++++++++++++++++----------- usr.sbin/devfsctl/devfsctl.h | 6 ++++- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/usr.sbin/devfsctl/devfsctl.c b/usr.sbin/devfsctl/devfsctl.c index a8b1e070ab..099f974905 100644 --- a/usr.sbin/devfsctl/devfsctl.c +++ b/usr.sbin/devfsctl/devfsctl.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -86,7 +87,9 @@ static int rule_send(struct rule *, struct groupdevid *); static int rule_check_num_args(char **, int); static int process_line(FILE*, int); static int rule_parser(char **tokens); +#if 0 static int ruletab_parser(char **tokens); +#endif static void usage(void); static int dev_fd; @@ -96,6 +99,7 @@ static int dflag = 0; static int aflag = 0, cflag = 0, rflag = 0, tflag = 0; static int line_stack[RULE_MAX_STACK]; static char *file_stack[RULE_MAX_STACK]; +static char *cwd_stack[RULE_MAX_STACK]; static int line_stack_depth = 0; static int jail = 0; @@ -151,7 +155,8 @@ parser_include(char **tokens) syntax_error("could not stat %s on include, error: %s", tokens[1], strerror(errno)); - read_config(tokens[1], RULES_FILE); + chdir(dirname(tokens[1])); + read_config(basename(tokens[1]), RULES_FILE); return 0; } @@ -466,6 +471,7 @@ static void rule_fill(struct devfs_rule_ioctl *dr, struct rule *r, struct groupdevid *id) { dr->rule_type = 0; + dr->rule_cmd = 0; switch (id->type) { default: @@ -555,6 +561,7 @@ int read_config(const char *name, int ftype) { FILE *fd; + struct stat sb; if ((fd = fopen(name, "r")) == NULL) { printf("Error opening config file %s\n", name); @@ -562,6 +569,13 @@ read_config(const char *name, int ftype) return 1; } + if (fstat(fileno(fd), &sb) != 0) { + errx(1, "file %s could not be fstat'ed, aborting", name); + } + + if (sb.st_uid != 0) + errx(1, "file %s does not belong to root, aborting!", name); + if (++line_stack_depth >= RULE_MAX_STACK) { --line_stack_depth; syntax_error("Maximum include depth (%d) exceeded, " @@ -570,6 +584,7 @@ read_config(const char *name, int ftype) line_stack[line_stack_depth] = 1; file_stack[line_stack_depth] = strdup(name); + cwd_stack[line_stack_depth] = getwd(NULL); while (process_line(fd, ftype) == 0) line_stack[line_stack_depth]++; @@ -577,7 +592,9 @@ read_config(const char *name, int ftype) fclose(fd); free(file_stack[line_stack_depth]); + free(cwd_stack[line_stack_depth]); --line_stack_depth; + chdir(cwd_stack[line_stack_depth]); return 0; } @@ -652,9 +669,11 @@ process_line(FILE* fd, int ftype) case RULES_FILE: ret = rule_parser(tokens); break; +#if 0 case RULETAB_FILE: ret = ruletab_parser(tokens); break; +#endif default: ret = 1; } @@ -690,6 +709,7 @@ rule_parser(char **tokens) return 0; } +#if 0 static int ruletab_parser(char **tokens) { @@ -727,7 +747,6 @@ rule_tab(void) { struct rule_tab *rt; int error; int mode; - char buf[PATH_MAX]; chdir("/etc/devfs"); error = read_config("ruletab", RULETAB_FILE); @@ -787,6 +806,7 @@ delete_rules(void) TAILQ_REMOVE(&group_list, gdp, link); } } +#endif static void usage(void) @@ -816,9 +836,10 @@ usage(void) int main(int argc, char *argv[]) { struct devfs_rule_ioctl dummy_rule; - int ch; + struct stat sb; + int ch, error; - while ((ch = getopt(argc, argv, "acdf:hm:rt")) != -1) { + while ((ch = getopt(argc, argv, "acdf:hm:r")) != -1) { switch (ch) { case 'f': config_name = optarg; @@ -838,9 +859,7 @@ int main(int argc, char *argv[]) case 'd': dflag = 1; break; - case 't': - tflag = 1; - break; + case 'h': case '?': default: @@ -858,16 +877,12 @@ int main(int argc, char *argv[]) * - can not use -d with any other mode * - can not use -t with any other mode or -f */ - if (!(aflag || tflag || rflag || cflag || dflag) || - (dflag && (aflag || rflag || cflag || tflag)) || - (tflag && (aflag || dflag || rflag || cflag || config_name))) { + if (!(aflag || rflag || cflag || dflag) || + (dflag && (aflag || rflag || cflag || tflag))) { usage(); /* NOT REACHED */ } - if (tflag) - rule_tab(); - if (mountp == NULL) mountp = "*"; else if (mountp[0] != '/') { @@ -876,8 +891,22 @@ int main(int argc, char *argv[]) strncpy(dummy_rule.mntpoint, mountp, PATH_MAX-1); - if (config_name != NULL) + if (config_name != NULL) { + error = stat(config_name, &sb); + + if (error) { + chdir("/etc/devfs"); + error = stat(config_name, &sb); + } + + if (error) + err(1, "could not stat specified configuration file %s", config_name); + + if (config_name[0] == '/') + chdir(dirname(config_name)); + read_config(config_name, RULES_FILE); + } if (dflag) { dump_config(); diff --git a/usr.sbin/devfsctl/devfsctl.h b/usr.sbin/devfsctl/devfsctl.h index 5a2e53cd36..6c339770f6 100644 --- a/usr.sbin/devfsctl/devfsctl.h +++ b/usr.sbin/devfsctl/devfsctl.h @@ -6,11 +6,13 @@ #define iswhitespace(X) ((((X) == ' ') || ((X) == '\t'))?1:0) #define RULE_MAX_STACK 32 #define RULES_FILE 0x01 -#define RULETAB_FILE 0x02 +#if 0 +#define RULETAB_FILE 0x02 #define RULETAB_ALL 0x01 #define RULETAB_ONLY_BOOT 0x02 #define RULETAB_SPECIFIC 0x03 +#endif struct groupdevid { enum { @@ -51,11 +53,13 @@ struct rule { TAILQ_ENTRY(rule) link; }; +#if 0 struct rule_tab { const char *mntpoint; const char *rule_file; TAILQ_ENTRY(rule_tab) link; }; +#endif typedef int (rule_iterate_callback_t)(struct rule *rule, struct groupdevid *id); -- 2.11.4.GIT