> > +/* > + * The guest context contains all the information, keys and metadata > + * associated with the guest that the firmware tracks to implement SEV > + * and SNP features. The firmware stores the guest context in hypervisor > + * provide page via the SNP_GCTX_CREATE command. > + */ > +static void *snp_context_create(struct kvm *kvm, struct kvm_sev_cmd *argp) > +{ > + struct sev_data_snp_addr data = {}; > + void *context; > + int rc; > + > + /* Allocate memory for context page */ > + context = snp_alloc_firmware_page(GFP_KERNEL_ACCOUNT); > + if (!context) > + return NULL; > + > + data.gctx_paddr = __psp_pa(context); > + rc = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_GCTX_CREATE, &data, &argp->error); > + if (rc) { > + snp_free_firmware_page(context); > + return NULL; > + } > + > + return context; > +} > + > +static int snp_bind_asid(struct kvm *kvm, int *error) > +{ > + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; > + struct sev_data_snp_activate data = {0}; > + > + data.gctx_paddr = __psp_pa(sev->snp_context); > + data.asid = sev_get_asid(kvm); > + return sev_issue_cmd(kvm, SEV_CMD_SNP_ACTIVATE, &data, error); > +} > + > +static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) > +{ > + struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; > + struct sev_data_snp_launch_start start = {0}; > + struct kvm_sev_snp_launch_start params; > + int rc; > + > + if (!sev_snp_guest(kvm)) > + return -ENOTTY; > + > + if (copy_from_user(¶ms, (void __user *)(uintptr_t)argp->data, sizeof(params))) > + return -EFAULT; > + > + sev->snp_context = snp_context_create(kvm, argp); > + if (!sev->snp_context) > + return -ENOTTY; This was reported-by josheads@. Its possible that userspace can repeatedly call snp_launch_start() causing the leak of memory from repeated snp_context_create() calls, leaking SNP contexts in the ASP, and leaking ASIDs. A possible solution could be to just error out if snp_context already exists? + if (sev->snp_context) + return -EINVAL; + > + > + start.gctx_paddr = __psp_pa(sev->snp_context); > + start.policy = params.policy; > + memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw)); > + rc = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_START, &start, &argp->error); > + if (rc) > + goto e_free_context; > + > + sev->fd = argp->sev_fd; > + rc = snp_bind_asid(kvm, &argp->error); > + if (rc) > + goto e_free_context; > + > + return 0; > + > +e_free_context: > + snp_decommission_context(kvm); > + > + return rc; > +} > +