All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
@ 2009-09-29 12:23 Suresh Jayaraman
  2009-09-30  6:57 ` Jens Axboe
  2009-10-01 10:07 ` Hugh Dickins
  0 siblings, 2 replies; 9+ messages in thread
From: Suresh Jayaraman @ 2009-09-29 12:23 UTC (permalink / raw)
  To: Jens Axboe; +Cc: LKML, Hugh Dickins, Andrew Morton

While testing Swap over NFS patchset, I noticed an oops that was triggered
during swapon. Investigating further, the NULL pointer deference is due to the
SSD device check/optimization in the swapon code that assumes s_bdev could never
be NULL.

inode->i_sb->s_bdev could be NULL in a few cases. For e.g. one such case is
loopback NFS mount, there could be others as well. Fix this by ensuring s_bdev
is not NULL before we try to deference s_bdev.

Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 mm/swapfile.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 4de7f02..a1bc6b9 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1974,12 +1974,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 		goto bad_swap;
 	}
 
-	if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
-		p->flags |= SWP_SOLIDSTATE;
-		p->cluster_next = 1 + (random32() % p->highest_bit);
+	if (p->bdev) {
+		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
+			p->flags |= SWP_SOLIDSTATE;
+			p->cluster_next = 1 + (random32() % p->highest_bit);
+		}
+		if (discard_swap(p) == 0)
+			p->flags |= SWP_DISCARDABLE;
 	}
-	if (discard_swap(p) == 0)
-		p->flags |= SWP_DISCARDABLE;
 
 	mutex_lock(&swapon_mutex);
 	spin_lock(&swap_lock);

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev  is NULL
  2009-09-29 12:23 [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL Suresh Jayaraman
@ 2009-09-30  6:57 ` Jens Axboe
  2009-10-01 10:07 ` Hugh Dickins
  1 sibling, 0 replies; 9+ messages in thread
From: Jens Axboe @ 2009-09-30  6:57 UTC (permalink / raw)
  To: Suresh Jayaraman; +Cc: LKML, Hugh Dickins, Andrew Morton

On Tue, Sep 29 2009, Suresh Jayaraman wrote:
> While testing Swap over NFS patchset, I noticed an oops that was triggered
> during swapon. Investigating further, the NULL pointer deference is due to the
> SSD device check/optimization in the swapon code that assumes s_bdev could never
> be NULL.
> 
> inode->i_sb->s_bdev could be NULL in a few cases. For e.g. one such case is
> loopback NFS mount, there could be others as well. Fix this by ensuring s_bdev
> is not NULL before we try to deference s_bdev.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
> ---
>  mm/swapfile.c |   12 +++++++-----
>  1 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 4de7f02..a1bc6b9 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -1974,12 +1974,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
>  		goto bad_swap;
>  	}
>  
> -	if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
> -		p->flags |= SWP_SOLIDSTATE;
> -		p->cluster_next = 1 + (random32() % p->highest_bit);
> +	if (p->bdev) {
> +		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
> +			p->flags |= SWP_SOLIDSTATE;
> +			p->cluster_next = 1 + (random32() % p->highest_bit);
> +		}
> +		if (discard_swap(p) == 0)
> +			p->flags |= SWP_DISCARDABLE;
>  	}
> -	if (discard_swap(p) == 0)
> -		p->flags |= SWP_DISCARDABLE;
>  
>  	mutex_lock(&swapon_mutex);
>  	spin_lock(&swap_lock);

Thanks for the patch, looks correct.

-- 
Jens Axboe


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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-09-29 12:23 [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL Suresh Jayaraman
  2009-09-30  6:57 ` Jens Axboe
@ 2009-10-01 10:07 ` Hugh Dickins
  2009-10-01 11:30   ` Suresh Jayaraman
  1 sibling, 1 reply; 9+ messages in thread
From: Hugh Dickins @ 2009-10-01 10:07 UTC (permalink / raw)
  To: Suresh Jayaraman; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

On Tue, 29 Sep 2009, Suresh Jayaraman wrote:

> While testing Swap over NFS patchset, I noticed an oops that was triggered
> during swapon. Investigating further, the NULL pointer deference is due to the
> SSD device check/optimization in the swapon code that assumes s_bdev could never
> be NULL.
> 
> inode->i_sb->s_bdev could be NULL in a few cases. For e.g. one such case is
> loopback NFS mount, there could be others as well. Fix this by ensuring s_bdev
> is not NULL before we try to deference s_bdev.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>

Acked-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>

Thanks a lot for that: sorry to say I was ignorant of the possibility.

This is only an issue with an out-of-tree patch, is that correct?
I'd like it to be fixed anyway, but if there's a way in which it can
happen in unpatched 2.6.31, then we ought to send the fix to -stable.

I've added Rafael to the Cc, because CONFIG_HIBERNATION's swap_type_of()
looks also dangerous in this respect - and especially where it does that
"if (bdev == sis->bdev) {" match, I think it's assuming NULL bdev cannot
match against anything.

Hugh

> ---
>  mm/swapfile.c |   12 +++++++-----
>  1 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 4de7f02..a1bc6b9 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -1974,12 +1974,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
>  		goto bad_swap;
>  	}
>  
> -	if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
> -		p->flags |= SWP_SOLIDSTATE;
> -		p->cluster_next = 1 + (random32() % p->highest_bit);
> +	if (p->bdev) {
> +		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
> +			p->flags |= SWP_SOLIDSTATE;
> +			p->cluster_next = 1 + (random32() % p->highest_bit);
> +		}
> +		if (discard_swap(p) == 0)
> +			p->flags |= SWP_DISCARDABLE;
>  	}
> -	if (discard_swap(p) == 0)
> -		p->flags |= SWP_DISCARDABLE;
>  
>  	mutex_lock(&swapon_mutex);
>  	spin_lock(&swap_lock);

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-01 10:07 ` Hugh Dickins
@ 2009-10-01 11:30   ` Suresh Jayaraman
  2009-10-01 11:53     ` Hugh Dickins
  0 siblings, 1 reply; 9+ messages in thread
From: Suresh Jayaraman @ 2009-10-01 11:30 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

Hugh Dickins wrote:
> On Tue, 29 Sep 2009, Suresh Jayaraman wrote:
> 
>> While testing Swap over NFS patchset, I noticed an oops that was triggered
>> during swapon. Investigating further, the NULL pointer deference is due to the
>> SSD device check/optimization in the swapon code that assumes s_bdev could never
>> be NULL.
>>
>> inode->i_sb->s_bdev could be NULL in a few cases. For e.g. one such case is
>> loopback NFS mount, there could be others as well. Fix this by ensuring s_bdev
>> is not NULL before we try to deference s_bdev.
>>
>> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
> 
> Acked-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
> 
> Thanks a lot for that: sorry to say I was ignorant of the possibility.
> 
> This is only an issue with an out-of-tree patch, is that correct?

Yes, it was reproducible only with an out-of-tree patch.

> I'd like it to be fixed anyway, but if there's a way in which it can
> happen in unpatched 2.6.31, then we ought to send the fix to -stable.
> 
> I've added Rafael to the Cc, because CONFIG_HIBERNATION's swap_type_of()
> looks also dangerous in this respect - and especially where it does that
> "if (bdev == sis->bdev) {" match, I think it's assuming NULL bdev cannot
> match against anything.

Yeah, perhaps. I stumbled upon one more of such error - a NULL pointer
dereference in blkdev_issue_discard() called from get_swap_page() when I ran
memhog, a simple program to generate a memory hog with Swap over NFS patches.

The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
-> discard_swap_cluster() -> blkdev_issue_discard().

Wrapping the code around a NULL check fixes the Oops for me.


Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
 mm/swapfile.c |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 4de7f02..51f39cf 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -160,11 +160,13 @@ static int discard_swap(struct swap_info_struct *si)
 				continue;
 		}
 
-		err = blkdev_issue_discard(si->bdev, start_block,
-						nr_blocks, GFP_KERNEL,
-						DISCARD_FL_BARRIER);
-		if (err)
-			break;
+		if (si->bdev) {
+			err = blkdev_issue_discard(si->bdev, start_block,
+					nr_blocks, GFP_KERNEL,
+					DISCARD_FL_BARRIER);
+			if (err)
+				break;
+		}
 
 		cond_resched();
 	}
@@ -200,10 +202,12 @@ static void discard_swap_cluster(struct swap_info_struct *si,
 
 			start_block <<= PAGE_SHIFT - 9;
 			nr_blocks <<= PAGE_SHIFT - 9;
-			if (blkdev_issue_discard(si->bdev, start_block,
+			if (si->bdev) {
+				if (blkdev_issue_discard(si->bdev, start_block,
 							nr_blocks, GFP_NOIO,
 							DISCARD_FL_BARRIER))
-				break;
+					break;
+			}
 		}
 
 		lh = se->list.next;

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-01 11:30   ` Suresh Jayaraman
@ 2009-10-01 11:53     ` Hugh Dickins
  2009-10-01 12:07       ` Suresh Jayaraman
  0 siblings, 1 reply; 9+ messages in thread
From: Hugh Dickins @ 2009-10-01 11:53 UTC (permalink / raw)
  To: Suresh Jayaraman; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
> 
> Yeah, perhaps. I stumbled upon one more of such error - a NULL pointer
> dereference in blkdev_issue_discard() called from get_swap_page() when I ran
> memhog, a simple program to generate a memory hog with Swap over NFS patches.
> 
> The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
> -> discard_swap_cluster() -> blkdev_issue_discard().
> 
> Wrapping the code around a NULL check fixes the Oops for me.

That's odd: scan_swap_map() should only discard_swap_cluster() if
SWP_DISCARDABLE got set, and your first patch made sure that it wasn't.

So I don't think this second patch should be necessary: you did have
your first applied when you found this?

I wonder if there's a funny little issue like si->lowest_alloc not
being reset to 0 where it should be.  Were you switching between
NFS swap and SSD swap in your testing?

Hugh

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-01 11:53     ` Hugh Dickins
@ 2009-10-01 12:07       ` Suresh Jayaraman
  2009-10-06 21:03         ` Hugh Dickins
  0 siblings, 1 reply; 9+ messages in thread
From: Suresh Jayaraman @ 2009-10-01 12:07 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

Hugh Dickins wrote:
> On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
>> Yeah, perhaps. I stumbled upon one more of such error - a NULL pointer
>> dereference in blkdev_issue_discard() called from get_swap_page() when I ran
>> memhog, a simple program to generate a memory hog with Swap over NFS patches.
>>
>> The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
>> -> discard_swap_cluster() -> blkdev_issue_discard().
>>
>> Wrapping the code around a NULL check fixes the Oops for me.
> 
> That's odd: scan_swap_map() should only discard_swap_cluster() if
> SWP_DISCARDABLE got set, and your first patch made sure that it wasn't.

I forgot to mention, this is not on loopback NFS mount but an remote NFS
mount (so possibly s_bdev is not NULL) when doing swapon. The oops was
triggered when memhog program tries to use the swap space on the newly
created swapfile on NFS. I have not completely investigated the issue,
perhaps s_bdev is not being set when it ought to be..

> So I don't think this second patch should be necessary: you did have
> your first applied when you found this?

yes, I had the first patch applied when it oopsed and I don't use SSD at
all.

> I wonder if there's a funny little issue like si->lowest_alloc not
> being reset to 0 where it should be.  Were you switching between
> NFS swap and SSD swap in your testing?

No.

Thanks,

-- 
Suresh Jayaraman

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-01 12:07       ` Suresh Jayaraman
@ 2009-10-06 21:03         ` Hugh Dickins
  2009-10-07  3:55           ` Suresh Jayaraman
  0 siblings, 1 reply; 9+ messages in thread
From: Hugh Dickins @ 2009-10-06 21:03 UTC (permalink / raw)
  To: Suresh Jayaraman; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
> Hugh Dickins wrote:
> > On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
> >>
> >> The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
> >> -> discard_swap_cluster() -> blkdev_issue_discard().
> >>
> >> Wrapping the code around a NULL check fixes the Oops for me.
> > 
> > That's odd: scan_swap_map() should only discard_swap_cluster() if
> > SWP_DISCARDABLE got set, and your first patch made sure that it wasn't.
> 
> I forgot to mention, this is not on loopback NFS mount but an remote NFS
> mount (so possibly s_bdev is not NULL) when doing swapon. The oops was
> triggered when memhog program tries to use the swap space on the newly
> created swapfile on NFS. I have not completely investigated the issue,
> perhaps s_bdev is not being set when it ought to be..

I'm happy to see your first patch already in 2.6.32-rc3, but still
suspicious of this second patch you sent afterwards.  A quick skim
through your patchset suggests 23/31 is probably responsible:

--- mmotm.orig/include/linux/swap.h
+++ mmotm/include/linux/swap.h
@@ -120,6 +120,7 @@ struct swap_extent {
 enum {
 	SWP_USED	= (1 << 0),	/* is slot in swap_info[] used? */
 	SWP_WRITEOK	= (1 << 1),	/* ok to write to this swap?	*/
+	SWP_FILE	= (1 << 2),	/* file swap area */
 	SWP_DISCARDABLE = (1 << 2),	/* blkdev supports discard */
 	SWP_DISCARDING	= (1 << 3),	/* now discarding a free cluster */
 	SWP_SOLIDSTATE	= (1 << 4),	/* blkdev seeks are cheap */

Hugh

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-06 21:03         ` Hugh Dickins
@ 2009-10-07  3:55           ` Suresh Jayaraman
  2009-10-21 12:43             ` Suresh Jayaraman
  0 siblings, 1 reply; 9+ messages in thread
From: Suresh Jayaraman @ 2009-10-07  3:55 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

Hugh Dickins wrote:
> On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
>> Hugh Dickins wrote:
>>> On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
>>>> The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
>>>> -> discard_swap_cluster() -> blkdev_issue_discard().
>>>>
>>>> Wrapping the code around a NULL check fixes the Oops for me.
>>> That's odd: scan_swap_map() should only discard_swap_cluster() if
>>> SWP_DISCARDABLE got set, and your first patch made sure that it wasn't.
>> I forgot to mention, this is not on loopback NFS mount but an remote NFS
>> mount (so possibly s_bdev is not NULL) when doing swapon. The oops was
>> triggered when memhog program tries to use the swap space on the newly
>> created swapfile on NFS. I have not completely investigated the issue,
>> perhaps s_bdev is not being set when it ought to be..
> 
> I'm happy to see your first patch already in 2.6.32-rc3, but still
> suspicious of this second patch you sent afterwards.  A quick skim
> through your patchset suggests 23/31 is probably responsible:

Thanks for skimming through those patches. I noticed this already during
my review and thought I had already fixed this, but apparently I missed
out. I'll test after fixing this and report.

> --- mmotm.orig/include/linux/swap.h
> +++ mmotm/include/linux/swap.h
> @@ -120,6 +120,7 @@ struct swap_extent {
>  enum {
>  	SWP_USED	= (1 << 0),	/* is slot in swap_info[] used? */
>  	SWP_WRITEOK	= (1 << 1),	/* ok to write to this swap?	*/
> +	SWP_FILE	= (1 << 2),	/* file swap area */
>  	SWP_DISCARDABLE = (1 << 2),	/* blkdev supports discard */
>  	SWP_DISCARDING	= (1 << 3),	/* now discarding a free cluster */
>  	SWP_SOLIDSTATE	= (1 << 4),	/* blkdev seeks are cheap */
> 
> Hugh

Thanks,

-- 
Suresh Jayaraman

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

* Re: [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL
  2009-10-07  3:55           ` Suresh Jayaraman
@ 2009-10-21 12:43             ` Suresh Jayaraman
  0 siblings, 0 replies; 9+ messages in thread
From: Suresh Jayaraman @ 2009-10-21 12:43 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Rafael Wysocki, Jens Axboe, LKML, Andrew Morton

Suresh Jayaraman wrote:
> Hugh Dickins wrote:
>> On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
>>> Hugh Dickins wrote:
>>>> On Thu, 1 Oct 2009, Suresh Jayaraman wrote:
>>>>> The call sequence is add_to_swap() -> get_swap_page() ->  scan_swap_map()
>>>>> -> discard_swap_cluster() -> blkdev_issue_discard().
>>>>>
>>>>> Wrapping the code around a NULL check fixes the Oops for me.
>>>> That's odd: scan_swap_map() should only discard_swap_cluster() if
>>>> SWP_DISCARDABLE got set, and your first patch made sure that it wasn't.
>>> I forgot to mention, this is not on loopback NFS mount but an remote NFS
>>> mount (so possibly s_bdev is not NULL) when doing swapon. The oops was
>>> triggered when memhog program tries to use the swap space on the newly
>>> created swapfile on NFS. I have not completely investigated the issue,
>>> perhaps s_bdev is not being set when it ought to be..
>> I'm happy to see your first patch already in 2.6.32-rc3, but still
>> suspicious of this second patch you sent afterwards.  A quick skim
>> through your patchset suggests 23/31 is probably responsible:
> 
> Thanks for skimming through those patches. I noticed this already during
> my review and thought I had already fixed this, but apparently I missed
> out. I'll test after fixing this and report.

Sorry about the delay. I tested by fixing SWP_FILE macro only now after
returning from vacation. I was not able to reproduce this. Please ignore
the second patch and it's no longer necessary as noted by Hugh already.

Thanks,


>> --- mmotm.orig/include/linux/swap.h
>> +++ mmotm/include/linux/swap.h
>> @@ -120,6 +120,7 @@ struct swap_extent {
>>  enum {
>>  	SWP_USED	= (1 << 0),	/* is slot in swap_info[] used? */
>>  	SWP_WRITEOK	= (1 << 1),	/* ok to write to this swap?	*/
>> +	SWP_FILE	= (1 << 2),	/* file swap area */
>>  	SWP_DISCARDABLE = (1 << 2),	/* blkdev supports discard */
>>  	SWP_DISCARDING	= (1 << 3),	/* now discarding a free cluster */
>>  	SWP_SOLIDSTATE	= (1 << 4),	/* blkdev seeks are cheap */
>>
>> Hugh
> 
> Thanks,
> 


-- 
Suresh Jayaraman

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

end of thread, other threads:[~2009-10-21 12:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-29 12:23 [PATCH] swapfile: avoid NULL pointer dereference in swapon when s_bdev is NULL Suresh Jayaraman
2009-09-30  6:57 ` Jens Axboe
2009-10-01 10:07 ` Hugh Dickins
2009-10-01 11:30   ` Suresh Jayaraman
2009-10-01 11:53     ` Hugh Dickins
2009-10-01 12:07       ` Suresh Jayaraman
2009-10-06 21:03         ` Hugh Dickins
2009-10-07  3:55           ` Suresh Jayaraman
2009-10-21 12:43             ` Suresh Jayaraman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.