13b31921jamie/*- 27551d83pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 37551d83pfg * 48d425bfjamie * Copyright (c) 2011 James Gritton 53b31921jamie * All rights reserved. 63b31921jamie * 73b31921jamie * Redistribution and use in source and binary forms, with or without 83b31921jamie * modification, are permitted provided that the following conditions 93b31921jamie * are met: 103b31921jamie * 1. Redistributions of source code must retain the above copyright 113b31921jamie * notice, this list of conditions and the following disclaimer. 123b31921jamie * 2. Redistributions in binary form must reproduce the above copyright 133b31921jamie * notice, this list of conditions and the following disclaimer in the 143b31921jamie * documentation and/or other materials provided with the distribution. 153b31921jamie * 163b31921jamie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 173b31921jamie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 183b31921jamie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 193b31921jamie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 203b31921jamie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 213b31921jamie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 223b31921jamie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 233b31921jamie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 243b31921jamie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253b31921jamie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263b31921jamie * SUCH DAMAGE. 273b31921jamie */ 283b31921jamie 293b31921jamie#include <sys/cdefs.h> 303b31921jamie__FBSDID("$FreeBSD$"); 313b31921jamie 323b31921jamie#include <sys/uio.h> 333b31921jamie 343b31921jamie#include <err.h> 353b31921jamie#include <stdlib.h> 363b31921jamie#include <string.h> 373b31921jamie 383b31921jamie#include "jailp.h" 393b31921jamie 403b31921jamiestruct cfjails ready = TAILQ_HEAD_INITIALIZER(ready); 413a156b8jamiestruct cfjails depend = TAILQ_HEAD_INITIALIZER(depend); 423b31921jamie 433b31921jamiestatic void dep_add(struct cfjail *from, struct cfjail *to, unsigned flags); 443b31921jamiestatic int cmp_jailptr(const void *a, const void *b); 453b31921jamiestatic int cmp_jailptr_name(const void *a, const void *b); 463b31921jamiestatic struct cfjail *find_jail(const char *name); 47fd4e870mizhkastatic struct cfjail *running_jail(const char *name, int flags); 483b31921jamie 493b31921jamiestatic struct cfjail **jails_byname; 503b31921jamiestatic size_t njails; 513b31921jamie 523b31921jamie/* 533b31921jamie * Set up jail dependency lists. 543b31921jamie */ 553b31921jamievoid 563b31921jamiedep_setup(int docf) 573b31921jamie{ 583b31921jamie struct cfjail *j, *dj; 593b31921jamie struct cfparam *p; 603b31921jamie struct cfstring *s; 613b31921jamie struct cfdepend *d; 623b31921jamie const char *cs; 633b31921jamie char *pname; 643b31921jamie size_t plen; 658665489jamie int deps, ldeps; 663b31921jamie 673b31921jamie if (!docf) { 683b31921jamie /* 693b31921jamie * With no config file, let "depend" for a single jail 703b31921jamie * look at currently running jails. 713b31921jamie */ 723b31921jamie if ((j = TAILQ_FIRST(&cfjails)) && 733b31921jamie (p = j->intparams[IP_DEPEND])) { 740e5ec9djamie TAILQ_FOREACH(s, &p->val, tq) { 75fd4e870mizhka if (running_jail(s->s, 0) == NULL) { 763b31921jamie warnx("depends on nonexistent jail " 773b31921jamie "\"%s\"", s->s); 783b31921jamie j->flags |= JF_FAILED; 793b31921jamie } 803b31921jamie } 813b31921jamie } 823b31921jamie return; 833b31921jamie } 843b31921jamie 853b31921jamie njails = 0; 863b31921jamie TAILQ_FOREACH(j, &cfjails, tq) 873b31921jamie njails++; 883b31921jamie jails_byname = emalloc(njails * sizeof(struct cfjail *)); 893b31921jamie njails = 0; 903b31921jamie TAILQ_FOREACH(j, &cfjails, tq) 913b31921jamie jails_byname[njails++] = j; 923b31921jamie qsort(jails_byname, njails, sizeof(struct cfjail *), cmp_jailptr); 933b31921jamie deps = 0; 943b31921jamie ldeps = 0; 953b31921jamie plen = 0; 963b31921jamie pname = NULL; 973b31921jamie TAILQ_FOREACH(j, &cfjails, tq) { 983b31921jamie if (j->flags & JF_FAILED) 993b31921jamie continue; 1003b31921jamie if ((p = j->intparams[IP_DEPEND])) { 1010e5ec9djamie TAILQ_FOREACH(s, &p->val, tq) { 1023b31921jamie dj = find_jail(s->s); 1033b31921jamie if (dj != NULL) { 1043b31921jamie deps++; 1053b31921jamie dep_add(j, dj, 0); 1063b31921jamie } else { 1073b31921jamie jail_warnx(j, 1083b31921jamie "depends on undefined jail \"%s\"", 1093b31921jamie s->s); 1103b31921jamie j->flags |= JF_FAILED; 1113b31921jamie } 1123b31921jamie } 1133b31921jamie } 1143b31921jamie /* A jail has an implied dependency on its parent. */ 1153b31921jamie if ((cs = strrchr(j->name, '.'))) 1163b31921jamie { 1173b31921jamie if (plen < (size_t)(cs - j->name + 1)) { 1183b31921jamie plen = (cs - j->name) + 1; 1193b31921jamie pname = erealloc(pname, plen); 1203b31921jamie } 1213b31921jamie strlcpy(pname, j->name, plen); 1223b31921jamie dj = find_jail(pname); 1233b31921jamie if (dj != NULL) { 1243b31921jamie ldeps++; 1253b31921jamie dep_add(j, dj, DF_LIGHT); 1263b31921jamie } 1273b31921jamie } 1283b31921jamie } 1293b31921jamie 1303b31921jamie /* Look for dependency loops. */ 1313b31921jamie if (deps && (deps > 1 || ldeps)) { 132a85d762jamie (void)start_state(NULL, 0, 0, 0); 1333b31921jamie while ((j = TAILQ_FIRST(&ready))) { 1343b31921jamie requeue(j, &cfjails); 1353b31921jamie dep_done(j, DF_NOFAIL); 1363b31921jamie } 1373a156b8jamie while ((j = TAILQ_FIRST(&depend)) != NULL) { 1383b31921jamie jail_warnx(j, "dependency loop"); 1393b31921jamie j->flags |= JF_FAILED; 1403b31921jamie do { 1413b31921jamie requeue(j, &cfjails); 1423b31921jamie dep_done(j, DF_NOFAIL); 1433b31921jamie } while ((j = TAILQ_FIRST(&ready))); 1443b31921jamie } 1453b31921jamie TAILQ_FOREACH(j, &cfjails, tq) 1463b31921jamie STAILQ_FOREACH(d, &j->dep[DEP_FROM], tq[DEP_FROM]) 1473b31921jamie d->flags &= ~DF_SEEN; 1483b31921jamie } 1493b31921jamie if (pname != NULL) 1503b31921jamie free(pname); 1513b31921jamie} 1523b31921jamie 1533b31921jamie/* 1543b31921jamie * Return if a jail has dependencies. 1553b31921jamie */ 1563b31921jamieint 1573b31921jamiedep_check(struct cfjail *j) 1583b31921jamie{ 1593b31921jamie int reset, depfrom, depto, ndeps, rev; 1603b31921jamie struct cfjail *dj; 1613b31921jamie struct cfdepend *d; 1623b31921jamie 1633b31921jamie static int bits[] = { 0, 1, 1, 2, 1, 2, 2, 3 }; 1643b31921jamie 1653b31921jamie if (j->ndeps == 0) 1663b31921jamie return 0; 1673b31921jamie ndeps = 0; 1683b31921jamie if ((rev = JF_DO_STOP(j->flags))) { 1693b31921jamie depfrom = DEP_TO; 1703b31921jamie depto = DEP_FROM; 1713b31921jamie } else { 1723b31921jamie depfrom = DEP_FROM; 1733b31921jamie depto = DEP_TO; 1743b31921jamie } 1753b31921jamie STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom]) { 1763b31921jamie if (d->flags & DF_SEEN) 1773b31921jamie continue; 1783b31921jamie dj = d->j[depto]; 1793b31921jamie if (dj->flags & JF_FAILED) { 1803b31921jamie if (!(j->flags & (JF_DEPEND | JF_FAILED)) && 1813b31921jamie verbose >= 0) 1823b31921jamie jail_warnx(j, "skipped"); 1833b31921jamie j->flags |= JF_FAILED; 1843b31921jamie continue; 1853b31921jamie } 1863b31921jamie /* 1873b31921jamie * The dependee's state may be set (or changed) as a result of 1883b31921jamie * being in a dependency it wasn't in earlier. 1893b31921jamie */ 1903b31921jamie reset = 0; 1913b31921jamie if (bits[dj->flags & JF_OP_MASK] <= 1) { 1923b31921jamie if (!(dj->flags & JF_OP_MASK)) { 1933b31921jamie reset = 1; 1943b31921jamie dj->flags |= JF_DEPEND; 1953b31921jamie requeue(dj, &ready); 1963b31921jamie } 1973b31921jamie /* Set or change the dependee's state. */ 1983b31921jamie switch (j->flags & JF_OP_MASK) { 1993b31921jamie case JF_START: 2003b31921jamie dj->flags |= JF_START; 2013b31921jamie break; 2023b31921jamie case JF_SET: 2033b31921jamie if (!(dj->flags & JF_OP_MASK)) 2043b31921jamie dj->flags |= JF_SET; 2053b31921jamie else if (dj->flags & JF_STOP) 2063b31921jamie dj->flags |= JF_START; 2073b31921jamie break; 2083b31921jamie case JF_STOP: 2093b31921jamie case JF_RESTART: 2103b31921jamie if (!(dj->flags & JF_STOP)) 2113b31921jamie reset = 1; 2123b31921jamie dj->flags |= JF_STOP; 2133b31921jamie if (dj->flags & JF_SET) 2143b31921jamie dj->flags ^= (JF_START | JF_SET); 2153b31921jamie break; 2163b31921jamie } 2173b31921jamie } 2183b31921jamie if (reset) 2193b31921jamie dep_reset(dj); 2203b31921jamie if (!((d->flags & DF_LIGHT) && 2213b31921jamie (rev ? dj->jid < 0 : dj->jid > 0))) 2223b31921jamie ndeps++; 2233b31921jamie } 2243b31921jamie if (ndeps == 0) 2253b31921jamie return 0; 2263a156b8jamie requeue(j, &depend); 2273b31921jamie return 1; 2283b31921jamie} 2293b31921jamie 2303b31921jamie/* 2313b31921jamie * Resolve any dependencies from a finished jail. 2323b31921jamie */ 2333b31921jamievoid 2343b31921jamiedep_done(struct cfjail *j, unsigned flags) 2353b31921jamie{ 2363b31921jamie struct cfjail *dj; 2373b31921jamie struct cfdepend *d; 2383b31921jamie int depfrom, depto; 2393b31921jamie 2403b31921jamie if (JF_DO_STOP(j->flags)) { 2413b31921jamie depfrom = DEP_TO; 2423b31921jamie depto = DEP_FROM; 2433b31921jamie } else { 2443b31921jamie depfrom = DEP_FROM; 2453b31921jamie depto = DEP_TO; 2463b31921jamie } 2473b31921jamie STAILQ_FOREACH(d, &j->dep[depto], tq[depto]) { 2483b31921jamie if ((d->flags & DF_SEEN) | (flags & ~d->flags & DF_LIGHT)) 2493b31921jamie continue; 2503b31921jamie d->flags |= DF_SEEN; 2513b31921jamie dj = d->j[depfrom]; 2523b31921jamie if (!(flags & DF_NOFAIL) && (j->flags & JF_FAILED) && 2533b31921jamie (j->flags & (JF_OP_MASK | JF_DEPEND)) != 2543b31921jamie (JF_SET | JF_DEPEND)) { 2553b31921jamie if (!(dj->flags & (JF_DEPEND | JF_FAILED)) && 2563b31921jamie verbose >= 0) 2573b31921jamie jail_warnx(dj, "skipped"); 2583b31921jamie dj->flags |= JF_FAILED; 2593b31921jamie } 2603a156b8jamie if (!--dj->ndeps && dj->queue == &depend) 2613b31921jamie requeue(dj, &ready); 2623b31921jamie } 2633b31921jamie} 2643b31921jamie 2653b31921jamie/* 2663b31921jamie * Count a jail's dependencies and mark them as unseen. 2673b31921jamie */ 2683b31921jamievoid 2693b31921jamiedep_reset(struct cfjail *j) 2703b31921jamie{ 2713b31921jamie int depfrom; 2723b31921jamie struct cfdepend *d; 2733b31921jamie 2743b31921jamie depfrom = JF_DO_STOP(j->flags) ? DEP_TO : DEP_FROM; 2753b31921jamie j->ndeps = 0; 2763b31921jamie STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom]) 2773b31921jamie j->ndeps++; 2783b31921jamie} 2793b31921jamie 2803b31921jamie/* 2813b31921jamie * Find the next jail ready to do something. 2823b31921jamie */ 2833b31921jamiestruct cfjail * 2843b31921jamienext_jail(void) 2853b31921jamie{ 2863b31921jamie struct cfjail *j; 2873b31921jamie 2883b31921jamie if (!(j = next_proc(!TAILQ_EMPTY(&ready))) && 2893b31921jamie (j = TAILQ_FIRST(&ready)) && JF_DO_STOP(j->flags) && 2903b31921jamie (j = TAILQ_LAST(&ready, cfjails)) && !JF_DO_STOP(j->flags)) { 2913b31921jamie TAILQ_FOREACH_REVERSE(j, &ready, cfjails, tq) 2923b31921jamie if (JF_DO_STOP(j->flags)) 2933b31921jamie break; 2943b31921jamie } 2953b31921jamie if (j != NULL) 2963b31921jamie requeue(j, &cfjails); 2973b31921jamie return j; 2983b31921jamie} 2993b31921jamie 3003b31921jamie/* 3013b31921jamie * Set jails to the proper start state. 3023b31921jamie */ 3033b31921jamieint 304a85d762jamiestart_state(const char *target, int docf, unsigned state, int running) 3053b31921jamie{ 3063b31921jamie struct iovec jiov[6]; 3073b31921jamie struct cfjail *j, *tj; 3083b31921jamie int jid; 3093b31921jamie char namebuf[MAXHOSTNAMELEN]; 3103b31921jamie 311a85d762jamie if (!target || (!docf && state != JF_STOP) || 312a85d762jamie (!running && !strcmp(target, "*"))) { 3133b31921jamie /* 314a85d762jamie * For a global wildcard (including no target specified), 315a85d762jamie * set the state on all jails and start with those that 316a85d762jamie * have no dependencies. 3173b31921jamie */ 3183b31921jamie TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) { 319a85d762jamie j->flags = (j->flags & JF_FAILED) | state | 320a85d762jamie (docf ? JF_WILD : 0); 3213b31921jamie dep_reset(j); 3223a156b8jamie requeue(j, j->ndeps ? &depend : &ready); 3233b31921jamie } 3243b31921jamie } else if (wild_jail_name(target)) { 3253b31921jamie /* 3263b31921jamie * For targets specified singly, or with a non-global wildcard, 3273b31921jamie * set their state and call them ready (even if there are 3283b31921jamie * dependencies). Leave everything else unqueued for now. 3293b31921jamie */ 3303b31921jamie if (running) { 3313b31921jamie /* 3323b31921jamie * -R matches its wildcards against currently running 3333b31921jamie * jails, not against the config file. 3343b31921jamie */ 3358665489jamie jiov[0].iov_base = __DECONST(char *, "lastjid"); 3363b31921jamie jiov[0].iov_len = sizeof("lastjid"); 3373b31921jamie jiov[1].iov_base = &jid; 3383b31921jamie jiov[1].iov_len = sizeof(jid); 3398665489jamie jiov[2].iov_base = __DECONST(char *, "jid"); 3403b31921jamie jiov[2].iov_len = sizeof("jid"); 3413b31921jamie jiov[3].iov_base = &jid; 3423b31921jamie jiov[3].iov_len = sizeof(jid); 3438665489jamie jiov[4].iov_base = __DECONST(char *, "name"); 3443b31921jamie jiov[4].iov_len = sizeof("name"); 3453b31921jamie jiov[5].iov_base = &namebuf; 3463b31921jamie jiov[5].iov_len = sizeof(namebuf); 3473b31921jamie for (jid = 0; jail_get(jiov, 6, 0) > 0; ) { 3483b31921jamie if (wild_jail_match(namebuf, target)) { 3493b31921jamie j = add_jail(); 3503b31921jamie j->name = estrdup(namebuf); 3513b31921jamie j->jid = jid; 3523b31921jamie j->flags = (j->flags & JF_FAILED) | 3533b31921jamie state | JF_WILD; 3543b31921jamie dep_reset(j); 3553b31921jamie requeue(j, &ready); 3563b31921jamie } 3573b31921jamie } 3583b31921jamie } else { 3593b31921jamie TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) { 3603b31921jamie if (wild_jail_match(j->name, target)) { 3613b31921jamie j->flags = (j->flags & JF_FAILED) | 3623b31921jamie state | JF_WILD; 3633b31921jamie dep_reset(j); 3643b31921jamie requeue(j, &ready); 3653b31921jamie } 3663b31921jamie } 3673b31921jamie } 3683b31921jamie } else { 3693b31921jamie j = find_jail(target); 3703b31921jamie if (j == NULL && state == JF_STOP) { 3713b31921jamie /* Allow -[rR] to specify a currently running jail. */ 372fd4e870mizhka j = running_jail(target, JAIL_DYING); 3733b31921jamie } 3743b31921jamie if (j == NULL) { 3753b31921jamie warnx("\"%s\" not found", target); 3763b31921jamie return -1; 3773b31921jamie } 3783b31921jamie j->flags = (j->flags & JF_FAILED) | state; 3793b31921jamie dep_reset(j); 3803b31921jamie requeue(j, &ready); 3813b31921jamie } 3823b31921jamie return 0; 3833b31921jamie} 3843b31921jamie 3853b31921jamie/* 3863b31921jamie * Move a jail to a new list. 3873b31921jamie */ 3883b31921jamievoid 3893b31921jamierequeue(struct cfjail *j, struct cfjails *queue) 3903b31921jamie{ 3913b31921jamie if (j->queue != queue) { 3923b31921jamie TAILQ_REMOVE(j->queue, j, tq); 3933b31921jamie TAILQ_INSERT_TAIL(queue, j, tq); 3943b31921jamie j->queue = queue; 3953b31921jamie } 3963b31921jamie} 3973b31921jamie 3980e8a4f4jamievoid 3990e8a4f4jamierequeue_head(struct cfjail *j, struct cfjails *queue) 4000e8a4f4jamie{ 4010e8a4f4jamie TAILQ_REMOVE(j->queue, j, tq); 4020e8a4f4jamie TAILQ_INSERT_HEAD(queue, j, tq); 4030e8a4f4jamie j->queue = queue; 4040e8a4f4jamie} 4050e8a4f4jamie 4063b31921jamie/* 4073b31921jamie * Add a dependency edge between two jails. 4083b31921jamie */ 4093b31921jamiestatic void 4103b31921jamiedep_add(struct cfjail *from, struct cfjail *to, unsigned flags) 4113b31921jamie{ 4123b31921jamie struct cfdepend *d; 4133b31921jamie 4143b31921jamie d = emalloc(sizeof(struct cfdepend)); 4153b31921jamie d->flags = flags; 4163b31921jamie d->j[DEP_FROM] = from; 4173b31921jamie d->j[DEP_TO] = to; 4183b31921jamie STAILQ_INSERT_TAIL(&from->dep[DEP_FROM], d, tq[DEP_FROM]); 4193b31921jamie STAILQ_INSERT_TAIL(&to->dep[DEP_TO], d, tq[DEP_TO]); 4203b31921jamie} 4213b31921jamie 4223b31921jamie/* 4233b31921jamie * Compare jail pointers for qsort/bsearch. 4243b31921jamie */ 4253b31921jamiestatic int 4263b31921jamiecmp_jailptr(const void *a, const void *b) 4273b31921jamie{ 4283b31921jamie return strcmp((*((struct cfjail * const *)a))->name, 4293b31921jamie ((*(struct cfjail * const *)b))->name); 4303b31921jamie} 4313b31921jamie 4323b31921jamiestatic int 4333b31921jamiecmp_jailptr_name(const void *a, const void *b) 4343b31921jamie{ 4353b31921jamie return strcmp((const char *)a, ((*(struct cfjail * const *)b))->name); 4363b31921jamie} 4373b31921jamie 4383b31921jamie/* 4393b31921jamie * Find a jail object by name. 4403b31921jamie */ 4413b31921jamiestatic struct cfjail * 4423b31921jamiefind_jail(const char *name) 4433b31921jamie{ 4443b31921jamie struct cfjail **jp; 445fd4e870mizhka 446fd4e870mizhka if (jails_byname == NULL) 447fd4e870mizhka return NULL; 4483b31921jamie 4493b31921jamie jp = bsearch(name, jails_byname, njails, sizeof(struct cfjail *), 4503b31921jamie cmp_jailptr_name); 4513b31921jamie return jp ? *jp : NULL; 4523b31921jamie} 4533b31921jamie 4543b31921jamie/* 455fd4e870mizhka * Return jail if it is running, and NULL if it isn't. 4563b31921jamie */ 457fd4e870mizhkastatic struct cfjail * 458fd4e870mizhkarunning_jail(const char *name, int flags) 4593b31921jamie{ 460fd4e870mizhka struct iovec jiov[4]; 461fd4e870mizhka struct cfjail *jail; 4623b31921jamie char *ep; 463fd4e870mizhka char jailname[MAXHOSTNAMELEN]; 464fd4e870mizhka int jid, ret, len; 465fd4e870mizhka 4663b31921jamie if ((jid = strtol(name, &ep, 10)) && !*ep) { 467fd4e870mizhka memset(jailname,0,sizeof(jailname)); 468fd4e870mizhka len = sizeof(jailname); 4693b31921jamie } else { 470fd4e870mizhka strncpy(jailname, name,sizeof(jailname)); 471fd4e870mizhka len = strlen(name) + 1; 472fd4e870mizhka jid = 0; 473fd4e870mizhka } 474fd4e870mizhka 475fd4e870mizhka jiov[0].iov_base = __DECONST(char *, "jid"); 476fd4e870mizhka jiov[0].iov_len = sizeof("jid"); 477fd4e870mizhka jiov[1].iov_base = &jid; 478fd4e870mizhka jiov[1].iov_len = sizeof(jid); 479fd4e870mizhka jiov[2].iov_base = __DECONST(char *, "name"); 480fd4e870mizhka jiov[2].iov_len = sizeof("name"); 481fd4e870mizhka jiov[3].iov_base = &jailname; 482fd4e870mizhka jiov[3].iov_len = len; 483fd4e870mizhka 484fd4e870mizhka if ((ret = jail_get(jiov, 4, flags)) < 0) 485fd4e870mizhka return (NULL); 486fd4e870mizhka 487fd4e870mizhka if ((jail = find_jail(jailname)) == NULL) { 488fd4e870mizhka jail = add_jail(); 489fd4e870mizhka jail->name = estrdup(jailname); 490fd4e870mizhka jail->jid = ret; 4913b31921jamie } 492fd4e870mizhka 493fd4e870mizhka return (jail); 4943b31921jamie} 495