Thank you for your contribution! Sashiko AI review found 1 potential issue(s) 
to consider:
- [Medium] fbcon: race between fbcon_del_cursor_work() and dequeued 
fb_flashcursor()
--

commit 7fd3c01c297e05df19b561b8622916f2e7e0e858
Author: Yao Yiqi <[email protected]>

fbcon: Avoid cancel_delayed_work_sync() in atomic context

This commit switches fbcon_del_cursor_work() to use cancel_delayed_work() so
it can be called safely from atomic console printing contexts, while adding
fbcon_del_cursor_work_sync() for teardown in fbcon_release(). It also moves
the queue_delayed_work() call in fb_flashcursor() inside the console_lock
critical section.

> diff --git a/drivers/video/fbdev/core/fbcon.c 
> b/drivers/video/fbdev/core/fbcon.c
> index 7720dfc80c165..066cd974ea3bb 100644
> --- a/drivers/video/fbdev/core/fbcon.c
> +++ b/drivers/video/fbdev/core/fbcon.c
> @@ -422,10 +422,14 @@ static void fb_flashcursor(struct work_struct *work)
>       par->bitops->cursor(vc, info, enable,
>                           get_fg_color(vc, info, c),
>                           get_bg_color(vc, info, c));
> -     console_unlock();
>  
> +     /*
> +      * Re-arm under console_lock so that a concurrent
> +      * fbcon_del_cursor_work() cannot race with this requeue.
> +      */
>       queue_delayed_work(system_power_efficient_wq, &par->cursor_work,
>                          par->cur_blink_jiffies);
> +     console_unlock();
>  }
>  
>  static void fbcon_add_cursor_work(struct fb_info *info)
> @@ -437,10 +441,30 @@ static void fbcon_add_cursor_work(struct fb_info *info)
>                                  par->cur_blink_jiffies);
>  }
>  
> +/*
> + * Stop the cursor blink.
> + *
> + * Does not wait for a callback that is already running, so it is safe to
> + * call from any context.
> + *
> + * console_lock serializes this with the requeue in fb_flashcursor();
> + * otherwise a running callback could re-arm the work.
> + */
>  static void fbcon_del_cursor_work(struct fb_info *info)
>  {
>       struct fbcon_par *par = info->fbcon_par;
>  
> +     cancel_delayed_work(&par->cursor_work);
> +}

[Severity: Medium]
Can fb_flashcursor() still race with fbcon_del_cursor_work() and re-arm
par->cursor_work after blinking has been stopped?

In kernel/workqueue.c, process_one_work() clears WORK_STRUCT_PENDING_BIT via
set_work_pool_and_clear_pending() before invoking the work callback, and
fb_flashcursor() does not acquire console_lock until it calls
console_trylock():

CPU 0 (workqueue)                     CPU 1 (holding console_lock)
-----------------                     ----------------------------
process_one_work()
  set_work_pool_and_clear_pending()
  fb_flashcursor()
                                      fbcon_del_cursor_work(info)
                                        cancel_delayed_work(&par->cursor_work)
                                          /* returns false, not pending */
                                      console_unlock()
    console_trylock() /* succeeds */
    ...
    par->bitops->cursor(...)
    queue_delayed_work(..., &par->cursor_work, ...)
    console_unlock()

Once fb_flashcursor() acquires console_lock in drivers/video/fbdev/core/fbcon.c,
it only checks:

        if (!vc || !con_is_visible(vc) ||
            fbcon_info_from_console(vc->vc_num) != info ||
            vc->vc_deccm != 1) {
                console_unlock();
                return;
        }

It does not check whether cursor blinking was stopped by:

- cursor_blink_store() setting fbcon_cursor_blink = false before calling
  fbcon_del_cursor_work(info)
- fbcon_cursor() seeing (vc->vc_cursor_type & CUR_SW) and calling
  fbcon_del_cursor_work(info)
- fbcon_blank() or fbcon_switch() stopping the cursor when blanking or
  switching to KD_GRAPHICS mode

Because cancel_delayed_work() does not wait for or disable an already-dequeued
work item and fbcon_del_cursor_work() records no state under console_lock,
wouldn't fb_flashcursor() draw the cursor and re-arm par->cursor_work
indefinitely?

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=1

Reply via email to