Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:GA
xen.31758
6526347a-libxl-allow-bootloader-restricted-mode...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 6526347a-libxl-allow-bootloader-restricted-mode.patch of Package xen.31758
# Commit 1f762642d2cad1a40634e3280361928109d902f1 # Date 2023-10-11 06:36:50 +0100 # Author Roger Pau Monne <roger.pau@citrix.com> # Committer Andrew Cooper <andrew.cooper3@citrix.com> libxl: add support for running bootloader in restricted mode 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> --- a/docs/man/xl.1.pod.in +++ b/docs/man/xl.1.pod.in @@ -1976,6 +1976,39 @@ ignored: =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/libs/light/libxl_bootloader.c +++ b/tools/libs/light/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> @@ -42,8 +43,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; @@ -61,6 +125,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"); @@ -79,6 +160,7 @@ static void make_bootloader_args(libxl__ /* Sentinel for execv */ ARG(NULL); + return 0; #undef ARG } @@ -443,7 +525,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/libs/light/libxl_dm.c +++ b/tools/libs/light/libxl_dm.c @@ -80,10 +80,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/libs/light/libxl_internal.h +++ b/tools/libs/light/libxl_internal.h @@ -4864,6 +4864,14 @@ struct libxl__cpu_policy { struct xc_msr *msr; }; +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