From a85d762796e36a664734574599d8854c54db7479 Mon Sep 17 00:00:00 2001 From: jamie Date: Wed, 8 Feb 2012 23:51:46 +0000 Subject: Improvements in error messages: Some errors printed the jail name for unnamed (command line) jails. Attempting to create an already-existing jail from the command line returned with no error (even for non-root) due to bad logic in start_state. Ignore kvm_proc errors, which are typically caused by permission problems. Instead, stop ignoring permission errors when removing a jail (but continue to silently ignore other errors, i.e. the jail no longer existing). This makes non-root attempts at removing a jail give a clearer error message. --- usr.sbin/jail/command.c | 12 ++++++++---- usr.sbin/jail/jail.c | 32 +++++++++++++++++++++++++------- usr.sbin/jail/jailp.h | 3 ++- usr.sbin/jail/state.c | 15 +++++++++------ 4 files changed, 44 insertions(+), 18 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c index 774cac3..10ff3e2 100644 --- a/usr.sbin/jail/command.c +++ b/usr.sbin/jail/command.c @@ -274,7 +274,11 @@ run_command(struct cfjail *j) case IP__OP: if (down) { - (void)jail_remove(j->jid); + if (jail_remove(j->jid) < 0 && errno == EPERM) { + jail_warnx(j, "jail_remove: %s", + strerror(errno)); + return -1; + } if (verbose > 0 || (verbose == 0 && (j->flags & JF_STOP ? note_remove : j->name != NULL))) jail_note(j, "removed\n"); @@ -711,14 +715,14 @@ term_procs(struct cfjail *j) return 0; if (kd == NULL) { - kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "jail"); + kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); if (kd == NULL) - exit(1); + return 0; } ki = kvm_getprocs(kd, KERN_PROC_PROC, 0, &pcnt); if (ki == NULL) - exit(1); + return 0; noted = 0; for (i = 0; i < pcnt; i++) if (ki[i].ki_jid == j->jid && diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c index 513a3b8..227280f 100644 --- a/usr.sbin/jail/jail.c +++ b/usr.sbin/jail/jail.c @@ -62,6 +62,8 @@ static void clear_persist(struct cfjail *j); static int update_jail(struct cfjail *j); static int rdtun_params(struct cfjail *j, int dofail); static void running_jid(struct cfjail *j, int dflag); +static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg, + const char *noname_msg); static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp, int flags); static void print_jail(FILE *fp, struct cfjail *j, int oldcl); @@ -317,10 +319,10 @@ main(int argc, char **argv) error = 0; if (op == JF_STOP) { for (i = 0; i < argc; i++) - if (start_state(argv[i], op, Rflag) < 0) + if (start_state(argv[i], docf, op, Rflag) < 0) error = 1; } else { - if (start_state(docf ? argv[0] : NULL, op, 0) < 0) + if (start_state(argv[0], docf, op, 0) < 0) exit(1); } @@ -376,7 +378,8 @@ main(int argc, char **argv) break; case JF_SET_RESTART: if (j->jid < 0) { - warnx("\"%s\" not found", j->name); + jail_quoted_warnx(j, "not found", + "no jail specified"); failed(j); continue; } @@ -396,7 +399,8 @@ main(int argc, char **argv) if (j->comparam == NULL) { if (j->jid > 0 && !(j->flags & (JF_DEPEND | JF_WILD))) { - warnx("\"%s\" already exists", j->name); + jail_quoted_warnx(j, "already exists", + NULL); failed(j); continue; } @@ -420,7 +424,8 @@ main(int argc, char **argv) case JF_SET: if (j->jid < 0 && !(j->flags & JF_DEPEND)) { - warnx("\"%s\" not found", j->name); + jail_quoted_warnx(j, "not found", + "no jail specified"); failed(j); continue; } @@ -444,8 +449,8 @@ main(int argc, char **argv) if (j->jid < 0) { if (!(j->flags & (JF_DEPEND | JF_WILD)) && verbose >= 0) - warnx("\"%s\" not found", - j->name); + jail_quoted_warnx(j, + "not found", NULL); goto jail_remove_done; } j->comparam = stopcommands; @@ -834,6 +839,19 @@ running_jid(struct cfjail *j, int dflag) j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0); } +static void +jail_quoted_warnx(const struct cfjail *j, const char *name_msg, + const char *noname_msg) +{ + const char *pval; + + if ((pval = j->name) || (pval = string_param(j->intparams[KP_JID])) || + (pval = string_param(j->intparams[KP_NAME]))) + warnx("\"%s\" %s", pval, name_msg); + else + warnx("%s", noname_msg); +} + /* * Set jail parameters and possible print them out. */ diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h index 68ad7a3..65cd88c 100644 --- a/usr.sbin/jail/jailp.h +++ b/usr.sbin/jail/jailp.h @@ -215,7 +215,8 @@ extern int dep_check(struct cfjail *j); extern void dep_done(struct cfjail *j, unsigned flags); extern void dep_reset(struct cfjail *j); extern struct cfjail *next_jail(void); -extern int start_state(const char *target, unsigned state, int running); +extern int start_state(const char *target, int docf, unsigned state, + int running); extern void requeue(struct cfjail *j, struct cfjails *queue); extern void yyerror(const char *); diff --git a/usr.sbin/jail/state.c b/usr.sbin/jail/state.c index 680a2ff..17b2a0c 100644 --- a/usr.sbin/jail/state.c +++ b/usr.sbin/jail/state.c @@ -128,7 +128,7 @@ dep_setup(int docf) /* Look for dependency loops. */ if (deps && (deps > 1 || ldeps)) { - (void)start_state(NULL, 0, 0); + (void)start_state(NULL, 0, 0, 0); while ((j = TAILQ_FIRST(&ready))) { requeue(j, &cfjails); dep_done(j, DF_NOFAIL); @@ -300,20 +300,23 @@ next_jail(void) * Set jails to the proper start state. */ int -start_state(const char *target, unsigned state, int running) +start_state(const char *target, int docf, unsigned state, int running) { struct iovec jiov[6]; struct cfjail *j, *tj; int jid; char namebuf[MAXHOSTNAMELEN]; - if (!target || (!running && !strcmp(target, "*"))) { + if (!target || (!docf && state != JF_STOP) || + (!running && !strcmp(target, "*"))) { /* - * If there's no target specified, set the state on all jails, - * and start with those that have no dependencies. + * For a global wildcard (including no target specified), + * set the state on all jails and start with those that + * have no dependencies. */ TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) { - j->flags = (j->flags & JF_FAILED) | state | JF_WILD; + j->flags = (j->flags & JF_FAILED) | state | + (docf ? JF_WILD : 0); dep_reset(j); requeue(j, j->ndeps ? &depend : &ready); } -- cgit v1.1