Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:Update
xen
xsa443-10.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa443-10.patch of Package xen
From a5be7e8b054f586ad934e786232af29fdc6e3ead Mon Sep 17 00:00:00 2001 From: Roger Pau Monne <roger.pau@citrix.com> Date: Mon, 25 Sep 2023 14:30:20 +0200 Subject: [PATCH 10/11] libxl: add support for running bootloader in restricted mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Much like the device model depriv mode, add the same kind of support for the bootloader. Such feature allows passing a UID as a parameter for the bootloader to run as, together with the bootloader itself taking the necessary actions to isolate. Note that the user to run the bootloader as must have the right permissions to access the guest disk image (in read mode only), and that the bootloader will be run in non-interactive mode when restricted. If enabled bootloader restrict mode will attempt to re-use the user(s) from the QEMU depriv implementation if no user is provided on the configuration file or the environment. See docs/features/qemu-deprivilege.pandoc for more information about how to setup those users. Bootloader restrict mode is not enabled by default as it requires certain setup to be done first (setup of the user(s) to use in restrict mode). 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> --- docs/man/xl.1.pod.in | 33 +++++++++++ tools/libxl/libxl_bootloader.c | 89 ++++++++++++++++++++++++++++- tools/libxl/libxl_dm.c | 8 +-- tools/libxl/libxl_internal.h | 8 +++ 4 files changed, 131 insertions(+), 7 deletions(-) --- a/docs/man/xl.1.pod.in +++ b/docs/man/xl.1.pod.in @@ -1988,6 +1988,39 @@ Transcendent Memory. =back +=head1 ENVIRONMENT VARIABLES + +The following environment variables shall affect the execution of xl: + +=over 4 + +=item LIBXL_BOOTLOADER_RESTRICT + +Attempt to restrict the bootloader after startup, to limit the +consequences of security vulnerabilities due to parsing guest +owned image files. + +See docs/features/qemu-deprivilege.pandoc for more information +on how to setup the unprivileged users. + +Note that running the bootloader in restricted mode also implies using +non-interactive mode, and the disk image must be readable by the +restricted user. + +Having this variable set is equivalent to enabling the option, even if the +value is 0. + +=item LIBXL_BOOTLOADER_USER + +When using bootloader_restrict, run the bootloader as this user. If +not set the default QEMU restrict users will be used. + +NOTE: Each domain MUST have a SEPARATE username. + +See docs/features/qemu-deprivilege.pandoc for more information. + +=back + =head1 SEE ALSO The following man pages: --- a/tools/libxl/libxl_bootloader.c +++ b/tools/libxl/libxl_bootloader.c @@ -14,6 +14,7 @@ #include "libxl_osdeps.h" /* must come before any other headers */ +#include <pwd.h> #include <termios.h> #ifdef HAVE_UTMP_H #include <utmp.h> @@ -46,8 +47,71 @@ static void bootloader_arg(libxl__bootlo bl->args[bl->nargs++] = arg; } -static void make_bootloader_args(libxl__gc *gc, libxl__bootloader_state *bl, - const char *bootloader_path) +static int bootloader_uid(libxl__gc *gc, domid_t guest_domid, + const char *user, uid_t *intended_uid) +{ + struct passwd *user_base, user_pwbuf; + int rc; + + if (user) { + rc = userlookup_helper_getpwnam(gc, user, &user_pwbuf, &user_base); + if (rc) return rc; + + if (!user_base) { + LOGD(ERROR, guest_domid, "Couldn't find user %s", user); + return ERROR_INVAL; + } + + *intended_uid = user_base->pw_uid; + return 0; + } + + /* Re-use QEMU user range for the bootloader. */ + rc = userlookup_helper_getpwnam(gc, LIBXL_QEMU_USER_RANGE_BASE, + &user_pwbuf, &user_base); + if (rc) return rc; + + if (user_base) { + struct passwd *user_clash, user_clash_pwbuf; + uid_t temp_uid = user_base->pw_uid + guest_domid; + + rc = userlookup_helper_getpwuid(gc, temp_uid, &user_clash_pwbuf, + &user_clash); + if (rc) return rc; + + if (user_clash) { + LOGD(ERROR, guest_domid, + "wanted to use uid %ld (%s + %d) but that is user %s !", + (long)temp_uid, LIBXL_QEMU_USER_RANGE_BASE, + guest_domid, user_clash->pw_name); + return ERROR_INVAL; + } + + *intended_uid = temp_uid; + return 0; + } + + rc = userlookup_helper_getpwnam(gc, LIBXL_QEMU_USER_SHARED, &user_pwbuf, + &user_base); + if (rc) return rc; + + if (user_base) { + LOGD(WARN, guest_domid, "Could not find user %s, falling back to %s", + LIBXL_QEMU_USER_RANGE_BASE, LIBXL_QEMU_USER_SHARED); + *intended_uid = user_base->pw_uid; + + return 0; + } + + LOGD(ERROR, guest_domid, + "Could not find user %s or range base pseudo-user %s, cannot restrict", + LIBXL_QEMU_USER_SHARED, LIBXL_QEMU_USER_RANGE_BASE); + + return ERROR_INVAL; +} + +static int make_bootloader_args(libxl__gc *gc, libxl__bootloader_state *bl, + const char *bootloader_path) { const libxl_domain_build_info *info = bl->info; @@ -65,6 +129,23 @@ static void make_bootloader_args(libxl__ ARG(GCSPRINTF("--ramdisk=%s", info->ramdisk)); if (info->cmdline && *info->cmdline != '\0') ARG(GCSPRINTF("--args=%s", info->cmdline)); + if (getenv("LIBXL_BOOTLOADER_RESTRICT") || + getenv("LIBXL_BOOTLOADER_USER")) { + uid_t uid = -1; + int rc = bootloader_uid(gc, bl->domid, getenv("LIBXL_BOOTLOADER_USER"), + &uid); + + if (rc) return rc; + + assert(uid != -1); + if (!uid) { + LOGD(ERROR, bl->domid, "bootloader restrict UID is 0 (root)!"); + return ERROR_INVAL; + } + LOGD(DEBUG, bl->domid, "using uid %ld", (long)uid); + ARG(GCSPRINTF("--runas=%ld", (long)uid)); + ARG("--quiet"); + } ARG(GCSPRINTF("--output=%s", bl->outputpath)); ARG("--output-format=simple0"); @@ -83,6 +164,7 @@ static void make_bootloader_args(libxl__ /* Sentinel for execv */ ARG(NULL); + return 0; #undef ARG } @@ -447,7 +529,8 @@ static void bootloader_disk_attached_cb( bootloader = bltmp; } - make_bootloader_args(gc, bl, bootloader); + rc = make_bootloader_args(gc, bl, bootloader); + if (rc) goto out; bl->openpty.ao = ao; bl->openpty.callback = bootloader_gotptys; --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -81,10 +81,10 @@ static int libxl__create_qemu_logfile(li * On error, return a libxl-style error code. */ #define DEFINE_USERLOOKUP_HELPER(NAME,SPEC_TYPE,STRUCTNAME,SYSCONF) \ - static int userlookup_helper_##NAME(libxl__gc *gc, \ - SPEC_TYPE spec, \ - struct STRUCTNAME *resultbuf, \ - struct STRUCTNAME **out) \ + int userlookup_helper_##NAME(libxl__gc *gc, \ + SPEC_TYPE spec, \ + struct STRUCTNAME *resultbuf, \ + struct STRUCTNAME **out) \ { \ struct STRUCTNAME *resultp = NULL; \ char *buf = NULL; \ --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -4625,6 +4625,15 @@ static inline const char *libxl__qemu_qm { return GCSPRINTF("%s/qmp-libxl-%d", libxl__run_dir_path(), domid); } + +struct passwd; +_hidden int userlookup_helper_getpwnam(libxl__gc*, const char *user, + struct passwd *res, + struct passwd **out); +_hidden int userlookup_helper_getpwuid(libxl__gc*, uid_t uid, + struct passwd *res, + struct passwd **out); + #endif /*
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor