From: Andrew Cooper Subject: grant_table: Default to v1, and disallow transitive grants The reference counting and locking discipline for transitive grants is broken. Their use is therefore declared out of security support. This is XSA-226. Transitive grants are expected to be unconditionally available with grant table v2. Hiding transitive grants alone is an ABI breakage for the guest. Modern versions of Linux and the Windows PV drivers use grant table v1, but older versions did use v2. In principle, disabling gnttab v2 entirely is the safer way to cause guests to avoid using transitive grants. However, some older guests which defaulted to using gnttab v2 don't tolerate falling back from v2 to v1 over migrate. This patch introduces a new command line option to control grant table behaviour. One suboption allows a choice of the maximum grant table version Xen will allow the guest to use, and defaults to v2. A different suboption independently controls whether transitive grants can be used. The default case is: gnttab=max_ver:2 To disable gnttab v2 entirely, use: gnttab=max_ver:1 To allow gnttab v2 and transitive grants, use: gnttab=max_ver:2,transitive Reported-by: Jan Beulich Signed-off-by: Andrew Cooper diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index 73f5265..b792abf 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -758,6 +758,22 @@ Controls EPT related features. Specify which console gdbstub should use. See **console**. +### gnttab +> `= List of [ max_ver:, transitive ]` + +> Default: `gnttab=max_ver:2,no-transitive` + +Control various aspects of the grant table behaviour available to guests. + +* `max_ver` Select the maximum grant table version to offer to guests. Valid +version are 1 and 2. +* `transitive` Permit or disallow the use of transitive grants. Note that the +use of grant table v2 without transitive grants is an ABI breakage from the +guests point of view. + +*Warning:* +Due to XSA-226, the use of transitive grants is outside of security support. + ### gnttab\_max\_frames > `= ` diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index f06b664..109c552 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -50,6 +50,42 @@ integer_param("gnttab_max_nr_frames", max_nr_grant_frames); unsigned int __read_mostly max_grant_frames; integer_param("gnttab_max_frames", max_grant_frames); +static unsigned int __read_mostly opt_gnttab_max_version = 2; +static bool_t __read_mostly opt_transitive_grants; + +static void __init parse_gnttab(char *s) +{ + char *ss; + + do { + ss = strchr(s, ','); + if ( ss ) + *ss = '\0'; + + if ( !strncmp(s, "max_ver:", 8) ) + { + long ver = simple_strtol(s + 8, NULL, 10); + + if ( ver >= 1 && ver <= 2 ) + opt_gnttab_max_version = ver; + } + else + { + bool_t val = !!strncmp(s, "no-", 3); + + if ( !val ) + s += 3; + + if ( !strcmp(s, "transitive") ) + opt_transitive_grants = val; + } + + s = ss + 1; + } while ( ss ); +} + +custom_param("gnttab", parse_gnttab); + /* The maximum number of grant mappings is defined as a multiplier of the * maximum number of grant table entries. This defines the multiplier used. * Pretty arbitrary. [POLICY] @@ -2188,6 +2224,10 @@ __acquire_grant_for_copy( } else if ( (shah->flags & GTF_type_mask) == GTF_transitive ) { + if ( !opt_transitive_grants ) + PIN_FAIL(unlock_out_clear, GNTST_general_error, + "transitive grant disallowed by policy\n"); + if ( !allow_transitive ) PIN_FAIL(unlock_out_clear, GNTST_general_error, "transitive grant when transitivity not allowed\n"); @@ -3156,7 +3196,10 @@ do_grant_table_op( } case GNTTABOP_set_version: { - rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t)); + if ( opt_gnttab_max_version == 1 ) + rc = -ENOSYS; /* Behave as before set_version was introduced. */ + else + rc = gnttab_set_version(guest_handle_cast(uop, gnttab_set_version_t)); break; } case GNTTABOP_get_status_frames: