Re: Yet another hot unplug NULL pointer dereference (was Re: status of oops in sd_revalidate_disk?)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/26/11 05:58, Stefan Richter wrote:
> First I tested a FireWire drive and got the first log which is included
> below, instantly in two attempts.  Then I made two attempts with a USB
> CD-ROM which did not oops immediately at device removal but when I then
> hit the eject button in the still open grip.  This consistently produced
> the second log at the end of this post.
> 
> First test with 1394 CD-ROM:
> -----------------------------------------------------------------
>   - attach CD-ROM drive
> -----------------------------------------------------------------
> scsi4 : SBP-2 IEEE-1394
> firewire_sbp2 fw1.0: logged in to LUN 0000 (0 retries)
> scsi 4:0:0:0: CD-ROM		TEAC	 CD-W28E	  1.1A PQ: 0 ANSI: 0 CCS
> sr1: scsi3-mmc drive: 24x/24x writer cd/rw xa/form2 cdda tray
> sr 4:0:0:0: Attached scsi CD-ROM sr1
> -----------------------------------------------------------------
>   - start grip
>   - detach CD-ROM drive
> -----------------------------------------------------------------
> sr 4:0:0:0: Attached scsi generic sg2 type 5
> scsi 4:0:0:0: killing request
> BUG: unable to handle kernel NULL pointer dereference at 000003f0
> IP: [<c11bc19f>] scsi_prep_state_check+0x6/0x68
> *pde = 00000000 
> Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
> Modules linked in: firewire_sbp2 firewire_ohci firewire_core netconsole snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss nfs lockd sunrpc i2c_i801 applesmc sr_mod rtc sg input_polldev cdrom snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_pcm snd_timer snd sky2 snd_page_alloc
> 
> Pid: 2832, comm: grip Not tainted 3.2.0-rc7 #1 Apple Computer, Inc. Macmini1,1/Mac-F4208EC8
> EIP: 0060:[<c11bc19f>] EFLAGS: 00010046 CPU: 0
> EIP is at scsi_prep_state_check+0x6/0x68
> EAX: 00000000 EBX: f33f3f18 ECX: 00000000 EDX: f33f3f18
> ESI: f4815a68 EDI: 00000000 EBP: f160bc14 ESP: f160bc10
>  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> Process grip (pid: 2832, ti=f160a000 task=f5d48760 task.ti=f160a000)
> Stack:
>  f33f3f18 f160bc2c c11bc8b1 f160bc3c f33f3f18 f4815a68 f33f3f18 f160bc3c
>  c11bc9a5 f33f3f18 f4815a68 f160bc50 c10efad5 00000000 f33f3f18 f4815a68
>  f160bc78 c11bd09f f4815db0 f33f3f18 00000001 f33f3f18 f4815a68 f4815a68
> 
> Call Trace:
>  [<c11bc8b1>] scsi_setup_blk_pc_cmnd+0x12/0xe7
>  [<c11bc9a5>] scsi_prep_fn+0x1f/0x2e
>  [<c10efad5>] blk_peek_request+0x98/0x168
>  [<c11bd09f>] scsi_request_fn+0x23/0x3b5
>  [<c10ed9d6>] __blk_run_queue+0x14/0x16
>  [<c10f25d5>] blk_execute_rq_nowait+0x7d/0x98
>  [<c10f2697>] blk_execute_rq+0xa7/0xe8
>  [<c10f2530>] ? blk_rq_map_user+0x1b7/0x1b7
>  [<c10f8c81>] ? changed_ioprio+0x70/0x70
>  [<c10ed700>] ? elv_set_request+0x12/0x20
>  [<c10eeebd>] ? get_request+0x21e/0x2bb
>  [<c11bcad2>] scsi_execute+0xc4/0x10a
>  [<c11bcb6c>] scsi_execute_req+0x54/0x81
>  [<c11bcbea>] scsi_test_unit_ready+0x51/0xb2
>  [<f828248b>] sr_drive_status+0x33/0xd5 [sr_mod]
>  [<f81f7860>] cdrom_ioctl+0x6a9/0xb31 [cdrom]
>  [<c1279f36>] ? mutex_lock_nested+0x26c/0x2b0
>  [<c10231e5>] ? get_parent_ip+0xb/0x31
>  [<c1023287>] ? sub_preempt_count+0x7c/0x89
>  [<c1279f5f>] ? mutex_lock_nested+0x295/0x2b0
>  [<f82815f1>] ? sr_block_ioctl+0x2e/0x9a [sr_mod]
>  [<f8281612>] sr_block_ioctl+0x4f/0x9a [sr_mod]
>  [<f82815c3>] ? sr_block_check_events+0x13/0x13 [sr_mod]
>  [<c10f39ee>] __blkdev_driver_ioctl+0x22/0x2e
>  [<c10f42f5>] blkdev_ioctl+0x66d/0x68c
>  [<c104bf7e>] ? __lock_acquire+0x62e/0x14bb
>  [<c10b1861>] block_ioctl+0x32/0x3a
>  [<c10b1861>] ? block_ioctl+0x32/0x3a
>  [<c10b182f>] ? bd_set_size+0x67/0x67
>  [<c109bfd5>] do_vfs_ioctl+0x481/0x4b7
>  [<c1090993>] ? fget_light+0x4c/0xd0
>  [<c109c039>] sys_ioctl+0x2e/0x49
>  [<c127bb50>] sysenter_do_call+0x12/0x36

While scsi_device is propery refcounted object,
q->queuedata is set to NULL by scsi_remove_device() asynchronously.
So every reader of scsi_device's q->queuedata should always check it.

Though I don't have a machine to actually test it,
the following patch should remove such places.

Index: linux-3.3/drivers/scsi/scsi_lib.c
===================================================================
--- linux-3.3.orig/drivers/scsi/scsi_lib.c	2012-02-01 06:31:54.000000000 +0900
+++ linux-3.3/drivers/scsi/scsi_lib.c	2012-02-14 19:12:57.641216402 +0900
@@ -1214,10 +1214,8 @@ int scsi_prep_state_check(struct scsi_de
 }
 EXPORT_SYMBOL(scsi_prep_state_check);
 
-int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
+int scsi_prep_return(struct request_queue *q, struct scsi_device *sdev, struct request *req, int ret)
 {
-	struct scsi_device *sdev = q->queuedata;
-
 	switch (ret) {
 	case BLKPREP_KILL:
 		req->errors = DID_NO_CONNECT << 16;
@@ -1251,9 +1249,11 @@ int scsi_prep_fn(struct request_queue *q
 	struct scsi_device *sdev = q->queuedata;
 	int ret = BLKPREP_KILL;
 
+	if (!sdev)
+		return ret;
 	if (req->cmd_type == REQ_TYPE_BLOCK_PC)
 		ret = scsi_setup_blk_pc_cmnd(sdev, req);
-	return scsi_prep_return(q, req, ret);
+	return scsi_prep_return(q, sdev, req, ret);
 }
 EXPORT_SYMBOL(scsi_prep_fn);
 
Index: linux-3.3/drivers/scsi/sd.c
===================================================================
--- linux-3.3.orig/drivers/scsi/sd.c	2012-02-13 13:02:14.000000000 +0900
+++ linux-3.3/drivers/scsi/sd.c	2012-02-14 19:15:18.224212107 +0900
@@ -653,6 +653,9 @@ static int sd_prep_fn(struct request_que
 	int ret, host_dif;
 	unsigned char protect;
 
+	if (!sdp)
+		return BLKPREP_KILL;
+
 	/*
 	 * Discard request come in as REQ_TYPE_FS but we turn them into
 	 * block PC requests to make life easier.
@@ -905,7 +908,7 @@ static int sd_prep_fn(struct request_que
 	 */
 	ret = BLKPREP_OK;
  out:
-	return scsi_prep_return(q, rq, ret);
+	return scsi_prep_return(q, sdp, rq, ret);
 }
 
 /**
Index: linux-3.3/drivers/scsi/sr.c
===================================================================
--- linux-3.3.orig/drivers/scsi/sr.c	2012-02-01 06:31:54.000000000 +0900
+++ linux-3.3/drivers/scsi/sr.c	2012-02-14 19:15:59.001211143 +0900
@@ -372,6 +372,9 @@ static int sr_prep_fn(struct request_que
 	struct scsi_device *sdp = q->queuedata;
 	int ret;
 
+	if (!sdp)
+		return BLKPREP_KILL;
+
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		ret = scsi_setup_blk_pc_cmnd(sdp, rq);
 		goto out;
@@ -503,7 +506,7 @@ static int sr_prep_fn(struct request_que
 	 */
 	ret = BLKPREP_OK;
  out:
-	return scsi_prep_return(q, rq, ret);
+	return scsi_prep_return(q, sdp, rq, ret);
 }
 
 static int sr_block_open(struct block_device *bdev, fmode_t mode)
Index: linux-3.3/include/scsi/scsi_driver.h
===================================================================
--- linux-3.3.orig/include/scsi/scsi_driver.h	2012-02-01 06:31:54.000000000 +0900
+++ linux-3.3/include/scsi/scsi_driver.h	2012-02-14 19:16:47.478209843 +0900
@@ -31,7 +31,7 @@ extern int scsi_register_interface(struc
 int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req);
 int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req);
 int scsi_prep_state_check(struct scsi_device *sdev, struct request *req);
-int scsi_prep_return(struct request_queue *q, struct request *req, int ret);
+int scsi_prep_return(struct request_queue *q, struct scsi_device *sdev, struct request *req, int ret);
 int scsi_prep_fn(struct request_queue *, struct request *);
 
 #endif /* _SCSI_SCSI_DRIVER_H */
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux