driverdev-devel.linuxdriverproject.org archive mirror
 help / color / mirror / Atom feed
From: yakui.zhao@intel.com (Zhao, Yakui)
Subject: [RFC PATCH 08/15] drivers/acrn: add VM memory management for ACRN char device
Date: Mon, 19 Aug 2019 13:32:54 +0800	[thread overview]
Message-ID: <8b909c22-3873-2b5d-4845-1fee1a5d81ce@intel.com> (raw)
In-Reply-To: <20190816124757.GW1974@kadam>



On 2019?08?16? 20:58, Dan Carpenter wrote:
> On Fri, Aug 16, 2019@10:25:49AM +0800, Zhao Yakui wrote:
>> +int hugepage_map_guest(struct acrn_vm *vm, struct vm_memmap *memmap)
>> +{
>> +	struct page *page = NULL, *regions_buf_pg = NULL;
>> +	unsigned long len, guest_gpa, vma;
>> +	struct vm_memory_region *region_array;
>> +	struct set_regions *regions;
>> +	int max_size = PAGE_SIZE / sizeof(struct vm_memory_region);
>> +	int ret;
>> +
>> +	if (!vm || !memmap)
>> +		return -EINVAL;
>> +
>> +	len = memmap->len;
>> +	vma = memmap->vma_base;
>> +	guest_gpa = memmap->gpa;
>> +
>> +	/* prepare set_memory_regions info */
>> +	regions_buf_pg = alloc_page(GFP_KERNEL);
>> +	if (!regions_buf_pg)
>> +		return -ENOMEM;
>> +
>> +	regions = kzalloc(sizeof(*regions), GFP_KERNEL);
>> +	if (!regions) {
>> +		__free_page(regions_buf_pg);
>> +		return -ENOMEM;
> 
> It's better to do a goto err_free_regions_buf here.  More comments
> below.
> 
>> +	}
>> +	regions->mr_num = 0;
>> +	regions->vmid = vm->vmid;
>> +	regions->regions_gpa = page_to_phys(regions_buf_pg);
>> +	region_array = page_to_virt(regions_buf_pg);
>> +
>> +	while (len > 0) {
>> +		unsigned long vm0_gpa, pagesize;
>> +
>> +		ret = get_user_pages_fast(vma, 1, 1, &page);
>> +		if (unlikely(ret != 1) || (!page)) {
>> +			pr_err("failed to pin huge page!\n");
>> +			ret = -ENOMEM;
>> +			goto err;
> 
> goto err is a red flag.  It's better if error labels do one specific
> named thing like:
> 
> err_regions:
> 	kfree(regions);
> err_free_regions_buf:
> 	__free_page(regions_buf_pg);
> 
> We should unwind in the opposite/mirror order from how things were
> allocated.  Then we can remove the if statements in the error handling.

Thanks for the review.

Will follow your suggestion to unwind the error handling.

> 
> In this situation, say the user triggers an -EFAULT in
> get_user_pages_fast() in the second iteration through the loop.  That
> means that "page" is the non-NULL page from the previous iteration.  We
> have already added it to add_guest_map().  But now we're freeing it
> without removing it from the map so probably it leads to a use after
> free.
> 
> The best way to write the error handling in a loop like this is to
> clean up the partial iteration that has succeed (nothing here), and then
> unwind all the successful iterations at the bottom of the function.
> "goto unwind_loop;"
> 

In theory we should cleanup the previous success iteration if it 
encounters one error in the current iteration.
But it will be quite complex to cleanup up the previous iteration.
call the set_memory_regions for MR_DEL op.
call the remove_guest_map for the added hash item
call the put_page for returned page in get_user_pages_fast.

In fact as this driver is mainly used for embedded IOT usage, it doesn't 
handle the complex cleanup when such error is encountered. Instead the 
clean up is handled in free_guest_vm.

>> +		}
>> +
>> +		vm0_gpa = page_to_phys(page);
>> +		pagesize = PAGE_SIZE << compound_order(page);
>> +
>> +		ret = add_guest_map(vm, vm0_gpa, guest_gpa, pagesize);
>> +		if (ret < 0) {
>> +			pr_err("failed to add memseg for huge page!\n");
>> +			goto err;
> 
> So then here, it would be:
> 
> 			pr_err("failed to add memseg for huge page!\n");
> 			put_page(page);
> 			goto unwind_loop;
> 
> regards,
> dan carpenter
> 
>> +		}
>> +
>> +		/* fill each memory region into region_array */
>> +		region_array[regions->mr_num].type = MR_ADD;
>> +		region_array[regions->mr_num].gpa = guest_gpa;
>> +		region_array[regions->mr_num].vm0_gpa = vm0_gpa;
>> +		region_array[regions->mr_num].size = pagesize;
>> +		region_array[regions->mr_num].prot =
>> +				(MEM_TYPE_WB & MEM_TYPE_MASK) |
>> +				(memmap->prot & MEM_ACCESS_RIGHT_MASK);
>> +		regions->mr_num++;
>> +		if (regions->mr_num == max_size) {
>> +			pr_debug("region buffer full, set & renew regions!\n");
>> +			ret = set_memory_regions(regions);
>> +			if (ret < 0) {
>> +				pr_err("failed to set regions,ret=%d!\n", ret);
>> +				goto err;
>> +			}
>> +			regions->mr_num = 0;
>> +		}
>> +
>> +		len -= pagesize;
>> +		vma += pagesize;
>> +		guest_gpa += pagesize;
>> +	}
>> +
>> +	ret = set_memory_regions(regions);
>> +	if (ret < 0) {
>> +		pr_err("failed to set regions, ret=%d!\n", ret);
>> +		goto err;
>> +	}
>> +
>> +	__free_page(regions_buf_pg);
>> +	kfree(regions);
>> +
>> +	return 0;
>> +err:
>> +	if (regions_buf_pg)
>> +		__free_page(regions_buf_pg);
>> +	if (page)
>> +		put_page(page);
>> +	kfree(regions);
>> +	return ret;
>> +}
>> +
> 

  reply	other threads:[~2019-08-19  5:32 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-16  2:25 [RFC PATCH 00/15] acrn: add the ACRN driver module Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 01/15] x86/acrn: Report X2APIC for ACRN guest Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 02/15] x86/acrn: Add two APIs to add/remove driver-specific upcall ISR handler Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 03/15] x86/acrn: Add hypercall for ACRN guest Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 04/15] drivers/acrn: add the basic framework of acrn char device driver Zhao Yakui
2019-08-16  7:05   ` Greg KH
2019-08-19  4:02     ` Zhao, Yakui
2019-08-19  5:26       ` Greg KH
2019-08-16 11:28   ` Dan Carpenter
2019-08-16  2:25 ` [RFC PATCH 05/15] drivers/acrn: add driver-specific hypercall for ACRN_HSM Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 06/15] drivers/acrn: add the support of querying ACRN api version Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 07/15] drivers/acrn: add acrn vm/vcpu management for ACRN_HSM char device Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 08/15] drivers/acrn: add VM memory management for ACRN " Zhao Yakui
2019-08-16 12:58   ` Dan Carpenter
2019-08-19  5:32     ` Zhao, Yakui [this message]
2019-08-19  7:39       ` Dan Carpenter
2019-08-19  7:46         ` Borislav Petkov
2019-08-20  2:25         ` Zhao, Yakui
2019-08-16  2:25 ` [RFC PATCH 09/15] drivers/acrn: add passthrough device support Zhao Yakui
2019-08-16 13:05   ` Dan Carpenter
2019-09-02  0:18     ` Zhao, Yakui
2019-08-16  2:25 ` [RFC PATCH 10/15] drivers/acrn: add interrupt injection support Zhao Yakui
2019-08-16 13:12   ` Dan Carpenter
2019-08-19  4:59     ` Zhao, Yakui
2019-08-16  2:25 ` [RFC PATCH 11/15] drivers/acrn: add the support of handling emulated ioreq Zhao Yakui
2019-08-16 13:39   ` Dan Carpenter
2019-08-19  4:54     ` Zhao, Yakui
2019-08-16  2:25 ` [RFC PATCH 12/15] drivers/acrn: add driver-specific IRQ handle to dispatch IO_REQ request Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 13/15] drivers/acrn: add service to obtain Power data transition Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 14/15] drivers/acrn: add the support of irqfd and eventfd Zhao Yakui
2019-08-16  2:25 ` [RFC PATCH 15/15] drivers/acrn: add the support of offline SOS cpu Zhao Yakui
2019-08-19 10:34   ` Dan Carpenter
2019-08-20  2:23     ` Zhao, Yakui
2019-08-16  6:39 ` [RFC PATCH 00/15] acrn: add the ACRN driver module Borislav Petkov
2019-08-16  7:03   ` Greg KH
2019-08-19  2:39     ` Zhao, Yakui
2019-08-19  5:25       ` Greg KH
2019-08-19  1:44   ` Zhao, Yakui
2019-08-19  5:25     ` Greg KH
2019-08-19  5:39       ` Zhao, Yakui
2019-08-19  6:18     ` Borislav Petkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8b909c22-3873-2b5d-4845-1fee1a5d81ce@intel.com \
    --to=yakui.zhao@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).