Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/jail/jail.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
int iflag; | int iflag; | ||||
int note_remove; | int note_remove; | ||||
int verbose; | int verbose; | ||||
const char *separator = "\t"; | const char *separator = "\t"; | ||||
static void clear_persist(struct cfjail *j); | static void clear_persist(struct cfjail *j); | ||||
static int update_jail(struct cfjail *j); | static int update_jail(struct cfjail *j); | ||||
static int rdtun_params(struct cfjail *j, int dofail); | static int rdtun_params(struct cfjail *j, int dofail); | ||||
static void running_jid(struct cfjail *j, int dflag); | static void running_jid(struct cfjail *j); | ||||
static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg, | static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg, | ||||
const char *noname_msg); | const char *noname_msg); | ||||
static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp, | static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp, | ||||
unsigned njp, int flags); | unsigned njp, int flags); | ||||
static void print_jail(FILE *fp, struct cfjail *j, int oldcl, int running); | static void print_jail(FILE *fp, struct cfjail *j, int oldcl, int running); | ||||
static void print_param(FILE *fp, const struct cfparam *p, int sep, int doname); | static void print_param(FILE *fp, const struct cfparam *p, int sep, int doname); | ||||
static void show_jails(void); | static void show_jails(void); | ||||
static void quoted_print(FILE *fp, char *str); | static void quoted_print(FILE *fp, char *str); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
struct stat st; | struct stat st; | ||||
FILE *jfp; | FILE *jfp; | ||||
struct cfjail *j; | struct cfjail *j; | ||||
char *JidFile; | char *JidFile; | ||||
size_t sysvallen; | size_t sysvallen; | ||||
unsigned op, pi; | unsigned op, pi; | ||||
int ch, docf, error, i, oldcl, sysval; | int ch, docf, error, i, oldcl, sysval, dying_warned; | ||||
int dflag, Rflag; | int dflag, Rflag; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
char *cs, *ncs; | char *cs, *ncs; | ||||
#endif | #endif | ||||
#if defined(INET) && defined(INET6) | #if defined(INET) && defined(INET6) | ||||
struct in6_addr addr6; | struct in6_addr addr6; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 220 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
setlinebuf(stdout); | setlinebuf(stdout); | ||||
/* | /* | ||||
* The main loop: Get an available jail and perform the required | * The main loop: Get an available jail and perform the required | ||||
* operation on it. When that is done, the jail may be finished, | * operation on it. When that is done, the jail may be finished, | ||||
* or it may go back for the next step. | * or it may go back for the next step. | ||||
*/ | */ | ||||
dying_warned = 0; | |||||
while ((j = next_jail())) | while ((j = next_jail())) | ||||
{ | { | ||||
if (j->flags & JF_FAILED) { | if (j->flags & JF_FAILED) { | ||||
error = 1; | error = 1; | ||||
if (j->comparam == NULL) { | if (j->comparam == NULL) { | ||||
dep_done(j, 0); | dep_done(j, 0); | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
if (!(j->flags & JF_PARAMS)) | if (!(j->flags & JF_PARAMS)) | ||||
{ | { | ||||
j->flags |= JF_PARAMS; | j->flags |= JF_PARAMS; | ||||
if (dflag) | if (dflag) | ||||
add_param(j, NULL, IP_ALLOW_DYING, NULL); | add_param(j, NULL, IP_ALLOW_DYING, NULL); | ||||
if (check_intparams(j) < 0) | if (check_intparams(j) < 0) | ||||
continue; | continue; | ||||
if ((j->flags & (JF_START | JF_SET)) && | if ((j->flags & (JF_START | JF_SET)) && | ||||
import_params(j) < 0) | import_params(j) < 0) | ||||
continue; | continue; | ||||
} | } | ||||
if (j->intparams[IP_ALLOW_DYING] && !dying_warned) { | |||||
warnx("%s", "the 'allow.dying' parameter and '-d' flag" | |||||
"are deprecated and have no effect."); | |||||
dying_warned = 1; | |||||
} | |||||
if (!j->jid) | if (!j->jid) | ||||
running_jid(j, | running_jid(j); | ||||
(j->flags & (JF_SET | JF_DEPEND)) == JF_SET | |||||
? dflag || bool_param(j->intparams[IP_ALLOW_DYING]) | |||||
: 0); | |||||
if (finish_command(j)) | if (finish_command(j)) | ||||
continue; | continue; | ||||
switch (j->flags & JF_OP_MASK) { | switch (j->flags & JF_OP_MASK) { | ||||
/* | /* | ||||
* These operations just turn into a different op | * These operations just turn into a different op | ||||
* depending on the jail's current status. | * depending on the jail's current status. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Create a new jail. | * Create a new jail. | ||||
*/ | */ | ||||
int | int | ||||
create_jail(struct cfjail *j) | create_jail(struct cfjail *j) | ||||
{ | { | ||||
struct iovec jiov[4]; | |||||
struct stat st; | struct stat st; | ||||
struct jailparam *jp, *setparams, *setparams2, *sjp; | struct jailparam *jp, *setparams, *sjp; | ||||
const char *path; | const char *path; | ||||
int dopersist, ns, jid, dying, didfail; | int dopersist, ns; | ||||
/* | /* | ||||
* Check the jail's path, with a better error message than jail_set | * Check the jail's path, with a better error message than jail_set | ||||
* gives. | * gives. | ||||
*/ | */ | ||||
if ((path = string_param(j->intparams[KP_PATH]))) { | if ((path = string_param(j->intparams[KP_PATH]))) { | ||||
if (j->name != NULL && path[0] != '/') { | if (j->name != NULL && path[0] != '/') { | ||||
jail_warnx(j, "path %s: not an absolute pathname", | jail_warnx(j, "path %s: not an absolute pathname", | ||||
Show All 23 Lines | if (dopersist && jailparam_init(sjp++, "persist") < 0) { | ||||
jail_warnx(j, "%s", jail_errmsg); | jail_warnx(j, "%s", jail_errmsg); | ||||
return -1; | return -1; | ||||
} | } | ||||
for (jp = j->jp; jp < j->jp + j->njp; jp++) | for (jp = j->jp; jp < j->jp + j->njp; jp++) | ||||
if (!dopersist || !equalopts(jp->jp_name, "persist")) | if (!dopersist || !equalopts(jp->jp_name, "persist")) | ||||
*sjp++ = *jp; | *sjp++ = *jp; | ||||
ns = sjp - setparams; | ns = sjp - setparams; | ||||
didfail = 0; | |||||
j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE); | j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE); | ||||
if (j->jid < 0 && errno == EEXIST && | if (j->jid < 0) { | ||||
bool_param(j->intparams[IP_ALLOW_DYING]) && | |||||
int_param(j->intparams[KP_JID], &jid) && jid != 0) { | |||||
/* | |||||
* The jail already exists, but may be dying. | |||||
* Make sure it is, in which case an update is appropriate. | |||||
*/ | |||||
jiov[0].iov_base = __DECONST(char *, "jid"); | |||||
jiov[0].iov_len = sizeof("jid"); | |||||
jiov[1].iov_base = &jid; | |||||
jiov[1].iov_len = sizeof(jid); | |||||
jiov[2].iov_base = __DECONST(char *, "dying"); | |||||
jiov[2].iov_len = sizeof("dying"); | |||||
jiov[3].iov_base = &dying; | |||||
jiov[3].iov_len = sizeof(dying); | |||||
if (jail_get(jiov, 4, JAIL_DYING) < 0) { | |||||
/* | |||||
* It could be that the jail just barely finished | |||||
* dying, or it could be that the jid never existed | |||||
* but the name does. In either case, another try | |||||
* at creating the jail should do the right thing. | |||||
*/ | |||||
if (errno == ENOENT) | |||||
j->jid = jailparam_set_note(j, setparams, ns, | |||||
JAIL_CREATE); | |||||
} else if (dying) { | |||||
j->jid = jid; | |||||
if (rdtun_params(j, 1) < 0) { | |||||
j->jid = -1; | |||||
didfail = 1; | |||||
} else { | |||||
sjp = setparams2 = alloca((j->njp + dopersist) * | |||||
sizeof(struct jailparam)); | |||||
for (jp = setparams; jp < setparams + ns; jp++) | |||||
if (!JP_RDTUN(jp) || | |||||
!strcmp(jp->jp_name, "jid")) | |||||
*sjp++ = *jp; | |||||
j->jid = jailparam_set_note(j, setparams2, | |||||
sjp - setparams2, JAIL_UPDATE | JAIL_DYING); | |||||
/* | |||||
* Again, perhaps the jail just finished dying. | |||||
*/ | |||||
if (j->jid < 0 && errno == ENOENT) | |||||
j->jid = jailparam_set_note(j, | |||||
setparams, ns, JAIL_CREATE); | |||||
} | |||||
} | |||||
} | |||||
if (j->jid < 0 && !didfail) { | |||||
jail_warnx(j, "%s", jail_errmsg); | jail_warnx(j, "%s", jail_errmsg); | ||||
failed(j); | failed(j); | ||||
} | } | ||||
if (dopersist) { | if (dopersist) { | ||||
jailparam_free(setparams, 1); | jailparam_free(setparams, 1); | ||||
if (j->jid > 0) | if (j->jid > 0) | ||||
j->flags |= JF_PERSIST; | j->flags |= JF_PERSIST; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | if (jailparam_init(sjp, "jid") < 0 || | ||||
jail_warnx(j, "%s", jail_errmsg); | jail_warnx(j, "%s", jail_errmsg); | ||||
failed(j); | failed(j); | ||||
return -1; | return -1; | ||||
} | } | ||||
for (jp = j->jp; jp < j->jp + j->njp; jp++) | for (jp = j->jp; jp < j->jp + j->njp; jp++) | ||||
if (!JP_RDTUN(jp)) | if (!JP_RDTUN(jp)) | ||||
*++sjp = *jp; | *++sjp = *jp; | ||||
jid = jailparam_set_note(j, setparams, ns, | jid = jailparam_set_note(j, setparams, ns, JAIL_UPDATE); | ||||
bool_param(j->intparams[IP_ALLOW_DYING]) | |||||
? JAIL_UPDATE | JAIL_DYING : JAIL_UPDATE); | |||||
if (jid < 0) { | if (jid < 0) { | ||||
jail_warnx(j, "%s", jail_errmsg); | jail_warnx(j, "%s", jail_errmsg); | ||||
failed(j); | failed(j); | ||||
} | } | ||||
jailparam_free(setparams, 1); | jailparam_free(setparams, 1); | ||||
return jid; | return jid; | ||||
} | } | ||||
Show All 22 Lines | if (jailparam_init(rtjp, "jid") < 0 || | ||||
exit(1); | exit(1); | ||||
} | } | ||||
for (jp = j->jp; jp < j->jp + j->njp; jp++) | for (jp = j->jp; jp < j->jp + j->njp; jp++) | ||||
if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) { | if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) { | ||||
*++rtjp = *jp; | *++rtjp = *jp; | ||||
rtjp->jp_value = NULL; | rtjp->jp_value = NULL; | ||||
} | } | ||||
rval = 0; | rval = 0; | ||||
if (jailparam_get(rtparams, nrt, | if (jailparam_get(rtparams, nrt, 0) > 0) { | ||||
bool_param(j->intparams[IP_ALLOW_DYING]) ? JAIL_DYING : 0) > 0) { | |||||
rtjp = rtparams + 1; | rtjp = rtparams + 1; | ||||
for (jp = j->jp; rtjp < rtparams + nrt; jp++) { | for (jp = j->jp; rtjp < rtparams + nrt; jp++) { | ||||
if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) { | if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) { | ||||
if (!((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) && | if (!((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) && | ||||
jp->jp_valuelen == 0 && | jp->jp_valuelen == 0 && | ||||
*(int *)jp->jp_value) && | *(int *)jp->jp_value) && | ||||
!(rtjp->jp_valuelen == jp->jp_valuelen && | !(rtjp->jp_valuelen == jp->jp_valuelen && | ||||
!((jp->jp_ctltype & CTLTYPE) == | !((jp->jp_ctltype & CTLTYPE) == | ||||
Show All 20 Lines | rdtun_params(struct cfjail *j, int dofail) | ||||
jailparam_free(rtparams, nrt); | jailparam_free(rtparams, nrt); | ||||
return rval; | return rval; | ||||
} | } | ||||
/* | /* | ||||
* Get the jail's jid if it is running. | * Get the jail's jid if it is running. | ||||
*/ | */ | ||||
static void | static void | ||||
running_jid(struct cfjail *j, int dflag) | running_jid(struct cfjail *j) | ||||
{ | { | ||||
struct iovec jiov[2]; | struct iovec jiov[2]; | ||||
const char *pval; | const char *pval; | ||||
char *ep; | char *ep; | ||||
int jid; | int jid; | ||||
if ((pval = string_param(j->intparams[KP_JID]))) { | if ((pval = string_param(j->intparams[KP_JID]))) { | ||||
if (!(jid = strtol(pval, &ep, 10)) || *ep) { | if (!(jid = strtol(pval, &ep, 10)) || *ep) { | ||||
Show All 9 Lines | if ((pval = string_param(j->intparams[KP_JID]))) { | ||||
jiov[0].iov_len = sizeof("name"); | jiov[0].iov_len = sizeof("name"); | ||||
jiov[1].iov_len = strlen(pval) + 1; | jiov[1].iov_len = strlen(pval) + 1; | ||||
jiov[1].iov_base = alloca(jiov[1].iov_len); | jiov[1].iov_base = alloca(jiov[1].iov_len); | ||||
strcpy(jiov[1].iov_base, pval); | strcpy(jiov[1].iov_base, pval); | ||||
} else { | } else { | ||||
j->jid = -1; | j->jid = -1; | ||||
return; | return; | ||||
} | } | ||||
j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0); | j->jid = jail_get(jiov, 2, 0); | ||||
} | } | ||||
static void | static void | ||||
jail_quoted_warnx(const struct cfjail *j, const char *name_msg, | jail_quoted_warnx(const struct cfjail *j, const char *name_msg, | ||||
const char *noname_msg) | const char *noname_msg) | ||||
{ | { | ||||
const char *pval; | const char *pval; | ||||
Show All 12 Lines | jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp, | ||||
int flags) | int flags) | ||||
{ | { | ||||
char *value; | char *value; | ||||
int jid; | int jid; | ||||
unsigned i; | unsigned i; | ||||
jid = jailparam_set(jp, njp, flags); | jid = jailparam_set(jp, njp, flags); | ||||
if (verbose > 0) { | if (verbose > 0) { | ||||
jail_note(j, "jail_set(%s%s)", | jail_note(j, "jail_set(%s)", | ||||
(flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE | (flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE | ||||
? "JAIL_CREATE" : "JAIL_UPDATE", | ? "JAIL_CREATE" : "JAIL_UPDATE"); | ||||
(flags & JAIL_DYING) ? " | JAIL_DYING" : ""); | |||||
for (i = 0; i < njp; i++) { | for (i = 0; i < njp; i++) { | ||||
printf(" %s", jp[i].jp_name); | printf(" %s", jp[i].jp_name); | ||||
if (jp[i].jp_value == NULL) | if (jp[i].jp_value == NULL) | ||||
continue; | continue; | ||||
putchar('='); | putchar('='); | ||||
value = jailparam_export(jp + i); | value = jailparam_export(jp + i); | ||||
if (value == NULL) | if (value == NULL) | ||||
err(1, "jailparam_export"); | err(1, "jailparam_export"); | ||||
▲ Show 20 Lines • Show All 132 Lines • Show Last 20 Lines |