netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: syzbot <syzbot+628f93722c08dc5aabe0@syzkaller.appspotmail.com>
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	pabeni@redhat.com, syzkaller-bugs@googlegroups.com
Subject: Re: [syzbot] [net?] UBSAN: array-index-out-of-bounds in llc_conn_state_process (2)
Date: Fri, 9 May 2025 12:46:22 -0700	[thread overview]
Message-ID: <202505091223.3C51585567@keescook> (raw)
In-Reply-To: <0000000000009767ec0619fe6a1d@google.com>

On Mon, Jun 03, 2024 at 08:59:20AM -0700, syzbot wrote:
> HEAD commit:    6d7ddd805123 Merge tag 'soc-fixes-6.9-3' of git://git.kern..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=12596604980000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=7144b4fe7fbf5900
> dashboard link: https://syzkaller.appspot.com/bug?extid=628f93722c08dc5aabe0
> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> 
> Unfortunately, I don't have any reproducer for this issue yet.
> 
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/4d60cb47fbb1/disk-6d7ddd80.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/f3ff90de7db5/vmlinux-6d7ddd80.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/d452970444cd/bzImage-6d7ddd80.xz
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+628f93722c08dc5aabe0@syzkaller.appspotmail.com
> 
> ------------[ cut here ]------------
> UBSAN: array-index-out-of-bounds in net/llc/llc_conn.c:694:24
> index -1 is out of range for type 'int [12][5]'
> CPU: 0 PID: 15346 Comm: syz-executor.4 Not tainted 6.9.0-rc7-syzkaller-00023-g6d7ddd805123 #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024
> Call Trace:
>  <IRQ>
>  __dump_stack lib/dump_stack.c:88 [inline]
>  dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:114
>  ubsan_epilogue lib/ubsan.c:231 [inline]
>  __ubsan_handle_out_of_bounds+0x110/0x150 lib/ubsan.c:429
>  llc_find_offset net/llc/llc_conn.c:694 [inline]

static int llc_find_offset(int state, int ev_type)
...
                rc = llc_offset_table[state][3]; break;

But this seems to be racing against:

>  llc_qualify_conn_ev net/llc/llc_conn.c:401 [inline]

static const struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
                                                              struct sk_buff *skb)
...
        struct llc_conn_state *curr_state =
                                        &llc_conn_state_table[llc->state - 1]; // <<<<<<
...
        for (next_trans = curr_state->transitions +
                llc_find_offset(llc->state - 1, ev->type);

Otherwise the first one would have crashed too (a -1 array index). Is
something racing:

void llc_sk_free(struct sock *sk)
...
        llc->state = LLC_CONN_OUT_OF_SVC;	// = 0
        /* Stop all (possibly) running timers */
        llc_sk_stop_all_timers(sk, true);


>  llc_conn_service net/llc/llc_conn.c:366 [inline]
>  llc_conn_state_process+0x1381/0x14e0 net/llc/llc_conn.c:72
>  llc_process_tmr_ev net/llc/llc_c_ac.c:1445 [inline]
>  llc_conn_tmr_common_cb+0x450/0x8e0 net/llc/llc_c_ac.c:1331
>  call_timer_fn+0x1a0/0x610 kernel/time/timer.c:1793
>  expire_timers kernel/time/timer.c:1844 [inline]

Given this is in a timer, it seems likely, especially given the above
"llc_sk_stop_all_timer()" call. And llc_conn_tmr_common_cb() is reachable
from several timers:

void llc_conn_pf_cycle_tmr_cb(struct timer_list *t)
{
        struct llc_sock *llc = from_timer(llc, t, pf_cycle_timer.timer);

        llc_conn_tmr_common_cb(&llc->sk, LLC_CONN_EV_TYPE_P_TMR);
}

void llc_conn_busy_tmr_cb(struct timer_list *t)
{
        struct llc_sock *llc = from_timer(llc, t, busy_state_timer.timer);

        llc_conn_tmr_common_cb(&llc->sk, LLC_CONN_EV_TYPE_BUSY_TMR);
}

void llc_conn_ack_tmr_cb(struct timer_list *t)
{
        struct llc_sock *llc = from_timer(llc, t, ack_timer.timer);

        llc_conn_tmr_common_cb(&llc->sk, LLC_CONN_EV_TYPE_ACK_TMR);
}

void llc_conn_rej_tmr_cb(struct timer_list *t)
{
        struct llc_sock *llc = from_timer(llc, t, rej_sent_timer.timer);

        llc_conn_tmr_common_cb(&llc->sk, LLC_CONN_EV_TYPE_REJ_TMR);
}

llc_ui_release() does:

        sock_put(sk);
        sock_orphan(sk);
        sock->sk = NULL;
        llc_sk_free(sk);

And I see llc_sk_free() also does:

	sock_put(sk);

What holds locking on llc? The timer callback is locking itself, but I
don't see any locks in llc_sk_free(), but in theory there should be no
locks left?

What's supposed to be happening here? Moving the state assignment later
doesn't look right, given the explicit check here:

static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
{
        if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
                printk(KERN_WARNING "%s: timer called on closed connection\n",
                       __func__);
                kfree_skb(skb);

Is it just that a lock is missing in llc_sk_free?

diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 5c0ac243b248..99c4f06477eb 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -974,7 +974,9 @@ void llc_sk_free(struct sock *sk)
 {
 	struct llc_sock *llc = llc_sk(sk);
 
+	bh_lock_sock(sk);
 	llc->state = LLC_CONN_OUT_OF_SVC;
+	bh_unlock_sock(sk);
 	/* Stop all (possibly) running timers */
 	llc_sk_stop_all_timers(sk, true);
 #ifdef DEBUG_LLC_CONN_ALLOC

-- 
Kees Cook

      reply	other threads:[~2025-05-09 19:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-03 15:59 [syzbot] [net?] UBSAN: array-index-out-of-bounds in llc_conn_state_process (2) syzbot
2025-05-09 19:46 ` Kees Cook [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202505091223.3C51585567@keescook \
    --to=kees@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=syzbot+628f93722c08dc5aabe0@syzkaller.appspotmail.com \
    --cc=syzkaller-bugs@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).