> Date: Mon, 9 Apr 2018 13:51:34 +0200
> From: Martin Pieuchot <m...@openbsd.org>
> 
> Diff below avoids a lock ordering issue between the SCHED_LOCK() and
> printf(9)'s mutex.  This problem has been reported multiple times in
> drm(4) code where debug printfs are placed between sleep_setup() and
> sleep_finish().
> 
> The problem is easily fixed. logwakeup() must not be called while
> holding the mutex.  This function can end up in wakeup_n() which will
> grab the SCHED_LOCK().
> 
> While here ensure that the mutex is always when TOCONS is specified.
> This was not the case in the error path of log(9) and addlog(9).
> 
> Ok?

That makes a lot of sense; thanks.

ok kettenis@

> Index: kern/subr_prf.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/subr_prf.c,v
> retrieving revision 1.94
> diff -u -p -r1.94 subr_prf.c
> --- kern/subr_prf.c   20 Mar 2018 15:45:32 -0000      1.94
> +++ kern/subr_prf.c   9 Apr 2018 11:35:11 -0000
> @@ -89,8 +89,7 @@
>  int   kprintf(const char *, int, void *, char *, va_list);
>  void  kputchar(int, int, struct tty *);
>  
> -struct mutex kprintf_mutex =
> -    MUTEX_INITIALIZER_FLAGS(IPL_HIGH, "kprintf", MTX_NOWITNESS);
> +struct mutex kprintf_mutex = MUTEX_INITIALIZER(IPL_HIGH);
>  
>  /*
>   * globals
> @@ -264,7 +263,9 @@ log(int level, const char *fmt, ...)
>       splx(s);
>       if (!log_open) {
>               va_start(ap, fmt);
> +             mtx_enter(&kprintf_mutex);
>               kprintf(fmt, TOCONS, NULL, NULL, ap);
> +             mtx_leave(&kprintf_mutex);
>               va_end(ap);
>       }
>       logwakeup();            /* wake up anyone waiting for log msgs */
> @@ -304,7 +305,9 @@ addlog(const char *fmt, ...)
>       splx(s);
>       if (!log_open) {
>               va_start(ap, fmt);
> +             mtx_enter(&kprintf_mutex);
>               kprintf(fmt, TOCONS, NULL, NULL, ap);
> +             mtx_leave(&kprintf_mutex);
>               va_end(ap);
>       }
>       logwakeup();
> @@ -502,15 +505,15 @@ printf(const char *fmt, ...)
>       va_list ap;
>       int retval;
>  
> -     mtx_enter(&kprintf_mutex);
>  
>       va_start(ap, fmt);
> +     mtx_enter(&kprintf_mutex);
>       retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
> +     mtx_leave(&kprintf_mutex);
>       va_end(ap);
>       if (!panicstr)
>               logwakeup();
>  
> -     mtx_leave(&kprintf_mutex);
>  
>       return(retval);
>  }
> @@ -526,12 +529,11 @@ vprintf(const char *fmt, va_list ap)
>       int retval;
>  
>       mtx_enter(&kprintf_mutex);
> -
>       retval = kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap);
> +     mtx_leave(&kprintf_mutex);
>       if (!panicstr)
>               logwakeup();
>  
> -     mtx_leave(&kprintf_mutex);
>  
>       return (retval);
>  }
> @@ -686,6 +688,9 @@ kprintf(const char *fmt0, int oflags, vo
>       char *xdigs = NULL;     /* digits for [xX] conversion */
>       char buf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
>       char *tailp = NULL;     /* tail pointer for snprintf */
> +
> +     if (oflags & TOCONS)
> +             MUTEX_ASSERT_LOCKED(&kprintf_mutex);
>  
>       if ((oflags & TOBUFONLY) && (vp != NULL))
>               tailp = *(char **)vp;
> 
> 

Reply via email to