mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libxl: limit bootloader execution in restricted mode
Introduce a timeout for bootloader execution when running in restricted mode. Allow overwriting the default time out with an environment provided value. This is part of XSA-443 / CVE-2023-34325 Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
This commit is contained in:
1 parent
1f762642d2
commit
9c114178ff
3 files changed
+50
No files matched your search
@@ -1985,6 +1985,14 @@ compatibility reasons.
|
||||
|
||||
If set takes precedence over L<xl.cfg(5)> B<bootloader_user> option.
|
||||
|
||||
=item LIBXL_BOOTLOADER_TIMEOUT
|
||||
|
||||
Timeout in seconds for bootloader execution when running in restricted mode.
|
||||
Otherwise the build time default in LIBXL_BOOTLOADER_TIMEOUT will be used.
|
||||
|
||||
If defined the value must be an unsigned integer between 0 and INT_MAX,
|
||||
otherwise behavior is undefined. Setting to 0 disables the timeout.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
@@ -30,6 +30,8 @@ static void bootloader_keystrokes_copyfail(libxl__egc *egc,
|
||||
libxl__datacopier_state *dc, int rc, int onwrite, int errnoval);
|
||||
static void bootloader_display_copyfail(libxl__egc *egc,
|
||||
libxl__datacopier_state *dc, int rc, int onwrite, int errnoval);
|
||||
static void bootloader_timeout(libxl__egc *egc, libxl__ev_time *ev,
|
||||
const struct timeval *requested_abs, int rc);
|
||||
static void bootloader_domaindeath(libxl__egc*, libxl__domaindeathcheck *dc,
|
||||
int rc);
|
||||
static void bootloader_finished(libxl__egc *egc, libxl__ev_child *child,
|
||||
@@ -296,6 +298,7 @@ void libxl__bootloader_init(libxl__bootloader_state *bl)
|
||||
bl->ptys[0].master = bl->ptys[0].slave = 0;
|
||||
bl->ptys[1].master = bl->ptys[1].slave = 0;
|
||||
libxl__ev_child_init(&bl->child);
|
||||
libxl__ev_time_init(&bl->time);
|
||||
libxl__domaindeathcheck_init(&bl->deathcheck);
|
||||
bl->keystrokes.ao = bl->ao; libxl__datacopier_init(&bl->keystrokes);
|
||||
bl->display.ao = bl->ao; libxl__datacopier_init(&bl->display);
|
||||
@@ -313,6 +316,7 @@ static void bootloader_cleanup(libxl__egc *egc, libxl__bootloader_state *bl)
|
||||
libxl__domaindeathcheck_stop(gc,&bl->deathcheck);
|
||||
libxl__datacopier_kill(&bl->keystrokes);
|
||||
libxl__datacopier_kill(&bl->display);
|
||||
libxl__ev_time_deregister(gc, &bl->time);
|
||||
for (i=0; i<2; i++) {
|
||||
libxl__carefd_close(bl->ptys[i].master);
|
||||
libxl__carefd_close(bl->ptys[i].slave);
|
||||
@@ -374,6 +378,7 @@ static void bootloader_stop(libxl__egc *egc,
|
||||
|
||||
libxl__datacopier_kill(&bl->keystrokes);
|
||||
libxl__datacopier_kill(&bl->display);
|
||||
libxl__ev_time_deregister(gc, &bl->time);
|
||||
if (libxl__ev_child_inuse(&bl->child)) {
|
||||
r = kill(bl->child.pid, SIGTERM);
|
||||
if (r) LOGED(WARN, bl->domid, "%sfailed to kill bootloader [%lu]",
|
||||
@@ -635,6 +640,25 @@ static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
|
||||
LOGD(DEBUG, bl->domid, " bootloader arg: %s", *blarg);
|
||||
|
||||
struct termios termattr;
|
||||
const libxl_domain_build_info *info = bl->info;
|
||||
|
||||
if (libxl_defbool_val(info->bootloader_restrict)) {
|
||||
const char *timeout_env = getenv("LIBXL_BOOTLOADER_TIMEOUT");
|
||||
int timeout = timeout_env ? atoi(timeout_env)
|
||||
: LIBXL_BOOTLOADER_TIMEOUT;
|
||||
|
||||
if (timeout) {
|
||||
/* Set execution timeout */
|
||||
rc = libxl__ev_time_register_rel(ao, &bl->time,
|
||||
bootloader_timeout,
|
||||
timeout * 1000);
|
||||
if (rc) {
|
||||
LOGED(ERROR, bl->domid,
|
||||
"unable to register timeout for bootloader execution");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pid_t pid = libxl__ev_child_fork(gc, &bl->child, bootloader_finished);
|
||||
if (pid == -1) {
|
||||
@@ -701,6 +725,21 @@ static void bootloader_display_copyfail(libxl__egc *egc,
|
||||
libxl__bootloader_state *bl = CONTAINER_OF(dc, *bl, display);
|
||||
bootloader_copyfail(egc, "bootloader output", bl, 1, rc,onwrite,errnoval);
|
||||
}
|
||||
static void bootloader_timeout(libxl__egc *egc, libxl__ev_time *ev,
|
||||
const struct timeval *requested_abs, int rc)
|
||||
{
|
||||
libxl__bootloader_state *bl = CONTAINER_OF(ev, *bl, time);
|
||||
STATE_AO_GC(bl->ao);
|
||||
|
||||
libxl__ev_time_deregister(gc, &bl->time);
|
||||
|
||||
assert(libxl__ev_child_inuse(&bl->child));
|
||||
LOGD(ERROR, bl->domid, "killing bootloader because of timeout");
|
||||
|
||||
libxl__ev_child_kill_deregister(ao, &bl->child, SIGKILL);
|
||||
|
||||
bootloader_callback(egc, bl, rc);
|
||||
}
|
||||
|
||||
static void bootloader_domaindeath(libxl__egc *egc,
|
||||
libxl__domaindeathcheck *dc,
|
||||
@@ -717,6 +756,7 @@ static void bootloader_finished(libxl__egc *egc, libxl__ev_child *child,
|
||||
STATE_AO_GC(bl->ao);
|
||||
int rc;
|
||||
|
||||
libxl__ev_time_deregister(gc, &bl->time);
|
||||
libxl__datacopier_kill(&bl->keystrokes);
|
||||
libxl__datacopier_kill(&bl->display);
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
#define LIBXL_QMP_CMD_TIMEOUT 10
|
||||
#define LIBXL_STUBDOM_START_TIMEOUT 30
|
||||
#define LIBXL_QEMU_BODGE_TIMEOUT 2
|
||||
#define LIBXL_BOOTLOADER_TIMEOUT 120
|
||||
#define LIBXL_XENCONSOLE_LIMIT 1048576
|
||||
#define LIBXL_XENCONSOLE_PROTOCOL "vt100"
|
||||
#define LIBXL_MAXMEM_CONSTANT 1024
|
||||
@@ -3744,6 +3745,7 @@ struct libxl__bootloader_state {
|
||||
libxl__openpty_state openpty;
|
||||
libxl__openpty_result ptys[2]; /* [0] is for bootloader */
|
||||
libxl__ev_child child;
|
||||
libxl__ev_time time;
|
||||
libxl__domaindeathcheck deathcheck;
|
||||
int nargs, argsspace;
|
||||
const char **args;
|
||||
|
||||