Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mshv: Add ioctl for self targeted passthrough hvcalls

Allow MSHV_ROOT_HVCALL IOCTL on the /dev/mshv fd. This IOCTL would
execute a passthrough hypercall targeting the root/parent partition
i.e. HV_PARTITION_ID_SELF.

This will be useful for the VMM to query things like supported
synthetic processor features, supported VMM capabiliites etc.

Since hypercalls targeting the host partition could potentially perform
privileged operations, allow only a limited set of hypercalls. To begin
with, allow only:

HVCALL_GET_PARTITION_PROPERTY
HVCALL_GET_PARTITION_PROPERTY_EX

Signed-off-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
Reviewed-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>

authored by

Anirudh Rayabharam (Microsoft) and committed by
Wei Liu
c720e6a8 7bfe3b8e

+38 -9
+38 -9
drivers/hv/mshv_root_main.c
··· 122 122 */ 123 123 static u16 mshv_passthru_hvcalls[] = { 124 124 HVCALL_GET_PARTITION_PROPERTY, 125 + HVCALL_GET_PARTITION_PROPERTY_EX, 125 126 HVCALL_SET_PARTITION_PROPERTY, 126 127 HVCALL_INSTALL_INTERCEPT, 127 128 HVCALL_GET_VP_REGISTERS, ··· 137 136 HVCALL_GET_VP_CPUID_VALUES, 138 137 }; 139 138 139 + /* 140 + * Only allow hypercalls that are safe to be called by the VMM with the host 141 + * partition as target (i.e. HV_PARTITION_ID_SELF). Carefully audit that a 142 + * hypercall cannot be misused by the VMM before adding it to this list. 143 + */ 144 + static u16 mshv_self_passthru_hvcalls[] = { 145 + HVCALL_GET_PARTITION_PROPERTY, 146 + HVCALL_GET_PARTITION_PROPERTY_EX, 147 + }; 148 + 140 149 static bool mshv_hvcall_is_async(u16 code) 141 150 { 142 151 switch (code) { ··· 158 147 return false; 159 148 } 160 149 150 + static bool mshv_passthru_hvcall_allowed(u16 code, u64 pt_id) 151 + { 152 + int i; 153 + int n = ARRAY_SIZE(mshv_passthru_hvcalls); 154 + u16 *allowed_hvcalls = mshv_passthru_hvcalls; 155 + 156 + if (pt_id == HV_PARTITION_ID_SELF) { 157 + n = ARRAY_SIZE(mshv_self_passthru_hvcalls); 158 + allowed_hvcalls = mshv_self_passthru_hvcalls; 159 + } 160 + 161 + for (i = 0; i < n; ++i) 162 + if (allowed_hvcalls[i] == code) 163 + return true; 164 + 165 + return false; 166 + } 167 + 161 168 static int mshv_ioctl_passthru_hvcall(struct mshv_partition *partition, 162 169 bool partition_locked, 163 170 void __user *user_args) 164 171 { 165 172 u64 status; 166 - int ret = 0, i; 173 + int ret = 0; 167 174 bool is_async; 168 175 struct mshv_root_hvcall args; 169 176 struct page *page; ··· 189 160 void *input_pg = NULL; 190 161 void *output_pg = NULL; 191 162 u16 reps_completed; 163 + u64 pt_id = partition ? partition->pt_id : HV_PARTITION_ID_SELF; 192 164 193 165 if (copy_from_user(&args, user_args, sizeof(args))) 194 166 return -EFAULT; ··· 201 171 if (args.out_ptr && (!args.out_sz || args.out_sz > HV_HYP_PAGE_SIZE)) 202 172 return -EINVAL; 203 173 204 - for (i = 0; i < ARRAY_SIZE(mshv_passthru_hvcalls); ++i) 205 - if (args.code == mshv_passthru_hvcalls[i]) 206 - break; 207 - 208 - if (i >= ARRAY_SIZE(mshv_passthru_hvcalls)) 174 + if (!mshv_passthru_hvcall_allowed(args.code, pt_id)) 209 175 return -EINVAL; 210 176 211 177 is_async = mshv_hvcall_is_async(args.code); 212 178 if (is_async) { 213 179 /* async hypercalls can only be called from partition fd */ 214 - if (!partition_locked) 180 + if (!partition || !partition_locked) 215 181 return -EINVAL; 216 182 ret = mshv_init_async_handler(partition); 217 183 if (ret) ··· 235 209 * NOTE: This only works because all the allowed hypercalls' input 236 210 * structs begin with a u64 partition_id field. 237 211 */ 238 - *(u64 *)input_pg = partition->pt_id; 212 + *(u64 *)input_pg = pt_id; 239 213 240 214 reps_completed = 0; 241 215 do { ··· 264 238 ret = hv_result_to_errno(status); 265 239 else 266 240 ret = hv_call_deposit_pages(NUMA_NO_NODE, 267 - partition->pt_id, 1); 241 + pt_id, 1); 268 242 } while (!ret); 269 243 270 244 args.status = hv_result(status); ··· 2076 2050 case MSHV_CREATE_PARTITION: 2077 2051 return mshv_ioctl_create_partition((void __user *)arg, 2078 2052 misc->this_device); 2053 + case MSHV_ROOT_HVCALL: 2054 + return mshv_ioctl_passthru_hvcall(NULL, false, 2055 + (void __user *)arg); 2079 2056 } 2080 2057 2081 2058 return -ENOTTY;