public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch] exofs: confusion between kmap() and kmap_atomic() api
@ 2010-05-07  9:05 Dan Carpenter
  2010-05-09 10:16 ` Boaz Harrosh
  0 siblings, 1 reply; 5+ messages in thread
From: Dan Carpenter @ 2010-05-07  9:05 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: Benny Halevy, Avishay Traeger, osd-dev, linux-kernel

For kmap_atomic() we call kunmap_atomic() on the returned pointer.
That's different from kmap() and kunmap() and so it's easy to get them
backwards.

Signed-off-by: Dan Carpenter <error27@gmail.com>

diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c
index 4cfab1c..d91e9d8 100644
--- a/fs/exofs/dir.c
+++ b/fs/exofs/dir.c
@@ -608,7 +608,7 @@ int exofs_make_empty(struct inode *inode, struct inode *parent)
 	de->inode_no = cpu_to_le64(parent->i_ino);
 	memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR));
 	exofs_set_de_type(de, inode);
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(kaddr, KM_USER0);
 	err = exofs_commit_chunk(page, 0, chunk_size);
 fail:
 	page_cache_release(page);

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [patch] exofs: confusion between kmap() and kmap_atomic() api
  2010-05-07  9:05 [patch] exofs: confusion between kmap() and kmap_atomic() api Dan Carpenter
@ 2010-05-09 10:16 ` Boaz Harrosh
  2010-05-10 16:15   ` Dan Carpenter
  2010-05-10 23:03   ` Andrew Morton
  0 siblings, 2 replies; 5+ messages in thread
From: Boaz Harrosh @ 2010-05-09 10:16 UTC (permalink / raw)
  To: Dan Carpenter, Benny Halevy, Avishay Traeger, osd-dev,
	linux-kernel

On 05/07/2010 12:05 PM, Dan Carpenter wrote:
> For kmap_atomic() we call kunmap_atomic() on the returned pointer.
> That's different from kmap() and kunmap() and so it's easy to get them
> backwards.
> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>
> 

Thank you Dan, I'll push it ASAP. 

Looks like a bad bug. So this is actually a leak, right? kunmap_atomic
would detect the bad pointer and do nothing?

Thanks again
Boaz

> diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c
> index 4cfab1c..d91e9d8 100644
> --- a/fs/exofs/dir.c
> +++ b/fs/exofs/dir.c
> @@ -608,7 +608,7 @@ int exofs_make_empty(struct inode *inode, struct inode *parent)
>  	de->inode_no = cpu_to_le64(parent->i_ino);
>  	memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR));
>  	exofs_set_de_type(de, inode);
> -	kunmap_atomic(page, KM_USER0);
> +	kunmap_atomic(kaddr, KM_USER0);
>  	err = exofs_commit_chunk(page, 0, chunk_size);
>  fail:
>  	page_cache_release(page);


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] exofs: confusion between kmap() and kmap_atomic() api
  2010-05-09 10:16 ` Boaz Harrosh
@ 2010-05-10 16:15   ` Dan Carpenter
  2010-05-10 23:03   ` Andrew Morton
  1 sibling, 0 replies; 5+ messages in thread
From: Dan Carpenter @ 2010-05-10 16:15 UTC (permalink / raw)
  To: Boaz Harrosh; +Cc: Benny Halevy, Avishay Traeger, osd-dev, linux-kernel

On Sun, May 09, 2010 at 01:16:38PM +0300, Boaz Harrosh wrote:
> On 05/07/2010 12:05 PM, Dan Carpenter wrote:
> > For kmap_atomic() we call kunmap_atomic() on the returned pointer.
> > That's different from kmap() and kunmap() and so it's easy to get them
> > backwards.
> > 
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> > 
> 
> Thank you Dan, I'll push it ASAP. 
> 
> Looks like a bad bug. So this is actually a leak, right? kunmap_atomic
> would detect the bad pointer and do nothing?
> 

I've looked at it, and I think you're right but I'm not the guy to ask...

I saw somenoe else fixing these and wrote a smatch check is all.  I'm at
the "Monkey see, monkey do" level of kernel hacking.

regards,
dan carpenter

 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] exofs: confusion between kmap() and kmap_atomic() api
  2010-05-09 10:16 ` Boaz Harrosh
  2010-05-10 16:15   ` Dan Carpenter
@ 2010-05-10 23:03   ` Andrew Morton
  2010-05-11  8:05     ` Boaz Harrosh
  1 sibling, 1 reply; 5+ messages in thread
From: Andrew Morton @ 2010-05-10 23:03 UTC (permalink / raw)
  To: Boaz Harrosh
  Cc: Dan Carpenter, Benny Halevy, Avishay Traeger, osd-dev,
	linux-kernel

On Sun, 09 May 2010 13:16:38 +0300
Boaz Harrosh <bharrosh@panasas.com> wrote:

> On 05/07/2010 12:05 PM, Dan Carpenter wrote:
> > For kmap_atomic() we call kunmap_atomic() on the returned pointer.
> > That's different from kmap() and kunmap() and so it's easy to get them
> > backwards.
> > 
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> > 
> 
> Thank you Dan, I'll push it ASAP. 

> Looks like a bad bug. So this is actually a leak, right? kunmap_atomic
> would detect the bad pointer and do nothing?

void kunmap_atomic(void *kvaddr, enum km_type type)
{
	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();

	/*
	 * Force other mappings to Oops if they'll try to access this pte
	 * without first remap it.  Keeping stale mappings around is a bad idea
	 * also, in case the page changes cacheability attributes or becomes
	 * a protected page in a hypervisor.
	 */
	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
		kpte_clear_flush(kmap_pte-idx, vaddr);
	else {
#ifdef CONFIG_DEBUG_HIGHMEM
		BUG_ON(vaddr < PAGE_OFFSET);
		BUG_ON(vaddr >= (unsigned long)high_memory);
#endif
	}

	pagefault_enable();
}

if CONFIG_DEBUG_HIGHMEM=y, kunmap_atomic() will go BUG.

if CONFIG_DEBUG_HIGHMEM=n, kunmap_atomic() will do nothing, leaving the
pte pointing at the old page.  Next time someone tries to use that
kmap_atomic() slot,

void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
{
	enum fixed_addresses idx;
	unsigned long vaddr;

	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
	pagefault_disable();

	if (!PageHighMem(page))
		return page_address(page);

	debug_kmap_atomic(type);

	idx = type + KM_TYPE_NR*smp_processor_id();
	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
	BUG_ON(!pte_none(*(kmap_pte-idx)));
	set_pte(kmap_pte-idx, mk_pte(page, prot));

	return (void *)vaddr;
}

kmap_atomic_prot() will go BUG because the pte wasn't cleared.


I can only assume that this code has never been run on i386. I'd suggest
adding a "Cc: <stable@kernel.org>" to the changelog if you have
expectations that anyone will try to run it on i386.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] exofs: confusion between kmap() and kmap_atomic() api
  2010-05-10 23:03   ` Andrew Morton
@ 2010-05-11  8:05     ` Boaz Harrosh
  0 siblings, 0 replies; 5+ messages in thread
From: Boaz Harrosh @ 2010-05-11  8:05 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Dan Carpenter, Benny Halevy, Avishay Traeger, osd-dev,
	linux-kernel

On 05/11/2010 02:03 AM, Andrew Morton wrote:
> On Sun, 09 May 2010 13:16:38 +0300
> Boaz Harrosh <bharrosh@panasas.com> wrote:
> 
>> On 05/07/2010 12:05 PM, Dan Carpenter wrote:
>>> For kmap_atomic() we call kunmap_atomic() on the returned pointer.
>>> That's different from kmap() and kunmap() and so it's easy to get them
>>> backwards.
>>>
>>> Signed-off-by: Dan Carpenter <error27@gmail.com>
>>>
>>
>> Thank you Dan, I'll push it ASAP. 
> 
>> Looks like a bad bug. So this is actually a leak, right? kunmap_atomic
>> would detect the bad pointer and do nothing?
> 
> void kunmap_atomic(void *kvaddr, enum km_type type)
> {
> 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
> 	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
> 
> 	/*
> 	 * Force other mappings to Oops if they'll try to access this pte
> 	 * without first remap it.  Keeping stale mappings around is a bad idea
> 	 * also, in case the page changes cacheability attributes or becomes
> 	 * a protected page in a hypervisor.
> 	 */
> 	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
> 		kpte_clear_flush(kmap_pte-idx, vaddr);
> 	else {
> #ifdef CONFIG_DEBUG_HIGHMEM
> 		BUG_ON(vaddr < PAGE_OFFSET);
> 		BUG_ON(vaddr >= (unsigned long)high_memory);
> #endif
> 	}
> 
> 	pagefault_enable();
> }
> 
> if CONFIG_DEBUG_HIGHMEM=y, kunmap_atomic() will go BUG.
> 
> if CONFIG_DEBUG_HIGHMEM=n, kunmap_atomic() will do nothing, leaving the
> pte pointing at the old page.  Next time someone tries to use that
> kmap_atomic() slot,
> 
> void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
> {
> 	enum fixed_addresses idx;
> 	unsigned long vaddr;
> 
> 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
> 	pagefault_disable();
> 
> 	if (!PageHighMem(page))
> 		return page_address(page);
> 
> 	debug_kmap_atomic(type);
> 
> 	idx = type + KM_TYPE_NR*smp_processor_id();
> 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
> 	BUG_ON(!pte_none(*(kmap_pte-idx)));
> 	set_pte(kmap_pte-idx, mk_pte(page, prot));
> 
> 	return (void *)vaddr;
> }
> 
> kmap_atomic_prot() will go BUG because the pte wasn't cleared.
> 
> 
> I can only assume that this code has never been run on i386. I'd suggest
> adding a "Cc: <stable@kernel.org>" to the changelog if you have
> expectations that anyone will try to run it on i386.
> 

Right! Everyone I know runs 64bit. I will add the Cc: <stable@kernel.org>
to the patch. Thanks.

Boaz

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-05-11  8:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-07  9:05 [patch] exofs: confusion between kmap() and kmap_atomic() api Dan Carpenter
2010-05-09 10:16 ` Boaz Harrosh
2010-05-10 16:15   ` Dan Carpenter
2010-05-10 23:03   ` Andrew Morton
2010-05-11  8:05     ` Boaz Harrosh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox