Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Oct 2003 07:00:37 -0600
From:      "Kenneth D. Merry" <ken@kdm.org>
To:        Thomas Quinot <thomas@FreeBSD.ORG>
Cc:        freebsd-scsi@FreeBSD.ORG
Subject:   Re: Defend against calling sysctl_ctx_free on uninitialized context
Message-ID:  <20031007130037.GA74403@panzer.kdm.org>
In-Reply-To: <20030919175032.GA2430@melusine.cuivre.fr.eu.org>
References:  <20030919175032.GA2430@melusine.cuivre.fr.eu.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Sep 19, 2003 at 19:50:32 +0200, Thomas Quinot wrote:
> If a fatal error occurs while cd(4) is attaching, before the sysctl_ctx
> has been initialized, then it must not be freed. The following patch
> resolves this problem, please review.
> 
> Thanks,
> Thomas.
> 
> Index: scsi_cd.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/cam/scsi/scsi_cd.c,v
> retrieving revision 1.83
> diff -u -r1.83 scsi_cd.c
> --- scsi_cd.c	11 Sep 2003 19:27:24 -0000	1.83
> +++ scsi_cd.c	19 Sep 2003 17:47:03 -0000
> @@ -91,17 +91,18 @@
>  } cd_quirks;
>  
>  typedef enum {
> -	CD_FLAG_INVALID		= 0x001,
> -	CD_FLAG_NEW_DISC	= 0x002,
> -	CD_FLAG_DISC_LOCKED	= 0x004,
> -	CD_FLAG_DISC_REMOVABLE	= 0x008,
> -	CD_FLAG_TAGGED_QUEUING	= 0x010,
> -	CD_FLAG_CHANGER		= 0x040,
> -	CD_FLAG_ACTIVE		= 0x080,
> -	CD_FLAG_SCHED_ON_COMP	= 0x100,
> -	CD_FLAG_RETRY_UA	= 0x200,
> -	CD_FLAG_VALID_MEDIA	= 0x400,
> -	CD_FLAG_VALID_TOC	= 0x800
> +	CD_FLAG_INVALID		= 0x0001,
> +	CD_FLAG_NEW_DISC	= 0x0002,
> +	CD_FLAG_DISC_LOCKED	= 0x0004,
> +	CD_FLAG_DISC_REMOVABLE	= 0x0008,
> +	CD_FLAG_TAGGED_QUEUING	= 0x0010,
> +	CD_FLAG_CHANGER		= 0x0040,
> +	CD_FLAG_ACTIVE		= 0x0080,
> +	CD_FLAG_SCHED_ON_COMP	= 0x0100,
> +	CD_FLAG_RETRY_UA	= 0x0200,
> +	CD_FLAG_VALID_MEDIA	= 0x0400,
> +	CD_FLAG_VALID_TOC	= 0x0800,
> +	CD_FLAG_SCTX_INIT	= 0x1000
>  } cd_flags;
>  
>  typedef enum {
> @@ -458,7 +459,8 @@
>  	xpt_print_path(periph->path);
>  	printf("removing device entry\n");
>  
> -	if (sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
> +	if ((softc->flags & CD_FLAG_SCTX_INIT) != 0
> +	    && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
>  		xpt_print_path(periph->path);
>  		printf("can't remove sysctl context\n");
>  	}
> @@ -622,6 +624,7 @@
>  	mtx_lock(&Giant);
>  
>  	sysctl_ctx_init(&softc->sysctl_ctx);
> +	softc->flags |= CD_FLAG_SCTX_INIT;
>  	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
>  		SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
>  		tmpstr2, CTLFLAG_RD, 0, tmpstr);
> 
> -- 
>     Thomas.Quinot@Cuivre.FR.EU.ORG

This looks fine, feel free to commit.

There is also a potential race condition between the device going away and
the taskqueue running.  If the device goes away before the taskqueue runs,
it'll end up shoving sysctl context into freed memory, and will likely
leave the sysctl variable for that cd(4) instance hanging around.

It doesn't look like there is a taskqueue_dequeue(), though, so we can't
check for an active taskqueue request in cdcleanup() and dequeue it.

Ken
-- 
Kenneth Merry
ken@kdm.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031007130037.GA74403>