Re: [PATCH RFC] libceph: replace WARN_ON() with error handling for network input

Aleksandr Nogikh <[email protected]>
Newsgroups dev.linux.lists.syzbot
Message-ID <CANp29Y67g9oxPXTVPfCowAT2sLq0SCrNMm_BvJGotUHgiN8nxA@mail.gmail.com>
On Sat, Aug 8, 2026 at 11:53 AM 'syzbot' via
syzkaller-upstream-moderation
<[email protected]> wrote:
>
> The Ceph messenger v1 and v2 protocol implementations currently use
> WARN_ON() to assert that the server's response adheres to the protocol.
> However, network input from a server can be invalid due to a buggy or
> malicious server. WARN_ON() must not be used for conditions that can
> legitimately happen, such as receiving invalid network data. While WARNINGs
> are not fatal by default, they pollute the kernel log with stack traces and
> can lead to kernel panics on systems configured with panic_on_warn.
>
> When the kernel Ceph client connects to a Ceph server, it initiates a
> handshake and reads the server's reply directly from the network socket.
> The reply is then processed in process_connect() (for v1) or other
> processing functions (for v2). If the server sends an unexpected value,
> such as an incorrect connect_seq, the client triggers a WARN_ON(),
> resulting in the following warning:
>
> ------------[ cut here ]------------
> con->v1.connect_seq != le32_to_cpu(con->v1.in_reply.connect_seq)
> WARNING: net/ceph/messenger_v1.c:902 at process_connect
> net/ceph/messenger_v1.c:901 [inline], CPU#1: kworker/1:3/5645
> WARNING: net/ceph/messenger_v1.c:902 at ceph_con_v1_try_read+0x3335/0x6eb0
> net/ceph/messenger_v1.c:1366, CPU#1: kworker/1:3/5645
> RIP: 0010:process_connect net/ceph/messenger_v1.c:901 [inline]
> RIP: 0010:ceph_con_v1_try_read+0x3335/0x6eb0 net/ceph/messenger_v1.c:1366
> Call Trace:
>  <TASK>
>  ceph_con_workfn+0x208/0x14a0 net/ceph/messenger.c:1577
>  process_one_work kernel/workqueue.c:3322 [inline]
>  process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
>  worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
>  kthread+0x388/0x470 kernel/kthread.c:436
>  ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>  </TASK>
>
> Fix this by replacing WARN_ON() assertions on network input with graceful
> error handling. If the server sends unexpected data, log a descriptive
> error message using pr_err() instead, set the connection error message, and
> return an error code to abort the connection. This ensures that invalid
> network input is treated as a protocol violation rather than a kernel bug.
> The fix is applied to both messenger v1 (process_connect) and v2
> (process_hello, process_server_ident, process_session_retry, and
> process_session_retry_global).
>
> Fixes: 31b8006e1d79 ("ceph: messenger library")
> Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=21f8628595b2061c438d
> Link: https://syzkaller.appspot.com/ai_job?id=56e865ad-bcea-4dc1-9df8-618a118f27c9
> To: "Alex Markuze" <[email protected]>
> To: <[email protected]>
> To: "Ilya Dryomov" <[email protected]>
> To: "Viacheslav Dubeyko" <[email protected]>
> To: "Sage Weil" <[email protected]>
> Cc: <[email protected]>
>
> ---
> diff --git a/net/ceph/messenger_v1.c b/net/ceph/messenger_v1.c
> index c9e002d96..df2248b7b 100644
> --- a/net/ceph/messenger_v1.c
> +++ b/net/ceph/messenger_v1.c
> @@ -898,8 +898,15 @@ static int process_connect(struct ceph_connection *con)
>                      con->v1.peer_global_seq,
>                      le32_to_cpu(con->v1.in_reply.connect_seq),
>                      con->v1.connect_seq);
> -               WARN_ON(con->v1.connect_seq !=
> -                       le32_to_cpu(con->v1.in_reply.connect_seq));
> +               if (con->v1.connect_seq != le32_to_cpu(con->v1.in_reply.connect_seq)) {
> +                       pr_err("%s%lld %s connect_seq mismatch, expected %u, got %u\n",
> +                              ENTITY_NAME(con->peer_name),
> +                              ceph_pr_addr(&con->peer_addr),
> +                              con->v1.connect_seq,
> +                              le32_to_cpu(con->v1.in_reply.connect_seq));
> +                       con->error_msg = "connect_seq mismatch";
> +                       return -1;
> +               }
>
>                 if (con->v1.in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
>                         ceph_con_flag_set(con, CEPH_CON_F_LOSSYTX);
> diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
> index 05f6eea29..966a5f800 100644
> --- a/net/ceph/messenger_v2.c
> +++ b/net/ceph/messenger_v2.c
> @@ -2237,9 +2237,16 @@ static int process_hello(struct ceph_connection *con, void *p, void *end)
>                      __func__, con, ceph_pr_addr(my_addr));
>         }
>
> -       WARN_ON(ceph_addr_is_blank(my_addr) || ceph_addr_port(my_addr));
> -       WARN_ON(my_addr->type != CEPH_ENTITY_ADDR_TYPE_ANY);
> -       WARN_ON(!my_addr->nonce);
> +       if (ceph_addr_is_blank(my_addr) || ceph_addr_port(my_addr) ||
> +           my_addr->type != CEPH_ENTITY_ADDR_TYPE_ANY ||
> +           !my_addr->nonce) {

Don't we actually want to leave my_addr validation as it was - it's
not coming from the remote device?

> +               pr_err("%s%lld %s bad my_addr %s\n",
> +                      ENTITY_NAME(con->peer_name),
> +                      ceph_pr_addr(&con->peer_addr),
> +                      ceph_pr_addr(my_addr));
> +               con->error_msg = "bad my_addr";
> +               return -EINVAL;
> +       }
>
>         /* no reset_out_kvecs() as our hello may still be pending */
>         ret = prepare_auth_request(con);
> @@ -2529,14 +2536,33 @@ static int process_server_ident(struct ceph_connection *con,
>         con->peer_name.num = cpu_to_le64(global_id);
>         con->v2.peer_global_seq = global_seq;
>         con->peer_features = features;
> -       WARN_ON(required_features & ~client->supported_features);
> +       if (required_features & ~client->supported_features) {
> +               pr_err("%s%lld %s missing required protocol features, my supported 0x%llx, server's required 0x%llx\n",
> +                      ENTITY_NAME(con->peer_name),
> +                      ceph_pr_addr(&con->peer_addr),
> +                      client->supported_features, required_features);
> +               con->error_msg = "missing required protocol features";
> +               return -EINVAL;
> +       }
>         con->v2.server_cookie = cookie;
>
>         if (flags & CEPH_MSG_CONNECT_LOSSY) {
>                 ceph_con_flag_set(con, CEPH_CON_F_LOSSYTX);
> -               WARN_ON(con->v2.server_cookie);
> +               if (con->v2.server_cookie) {
> +                       pr_err("%s%lld %s server_cookie is set for lossy connection\n",
> +                              ENTITY_NAME(con->peer_name),
> +                              ceph_pr_addr(&con->peer_addr));
> +                       con->error_msg = "server_cookie is set for lossy connection";
> +                       return -EINVAL;
> +               }
>         } else {
> -               WARN_ON(!con->v2.server_cookie);
> +               if (!con->v2.server_cookie) {
> +                       pr_err("%s%lld %s server_cookie is not set for lossless connection\n",
> +                              ENTITY_NAME(con->peer_name),
> +                              ceph_pr_addr(&con->peer_addr));
> +                       con->error_msg = "server_cookie is not set for lossless connection";
> +                       return -EINVAL;
> +               }
>         }
>
>         clear_in_sign_kvecs(con);
> @@ -2618,7 +2644,14 @@ static int process_session_retry(struct ceph_connection *con,
>         ceph_decode_64_safe(&p, end, connect_seq, bad);
>
>         dout("%s con %p connect_seq %llu\n", __func__, con, connect_seq);
> -       WARN_ON(connect_seq <= con->v2.connect_seq);
> +       if (connect_seq <= con->v2.connect_seq) {
> +               pr_err("%s%lld %s connect_seq mismatch, expected > %llu, got %llu\n",
> +                      ENTITY_NAME(con->peer_name),
> +                      ceph_pr_addr(&con->peer_addr),
> +                      con->v2.connect_seq, connect_seq);
> +               con->error_msg = "connect_seq mismatch";
> +               return -EINVAL;
> +       }
>         con->v2.connect_seq = connect_seq + 1;
>
>         free_conn_bufs(con);
> @@ -2651,7 +2684,14 @@ static int process_session_retry_global(struct ceph_connection *con,
>         ceph_decode_64_safe(&p, end, global_seq, bad);
>
>         dout("%s con %p global_seq %llu\n", __func__, con, global_seq);
> -       WARN_ON(global_seq <= con->v2.global_seq);
> +       if (global_seq <= con->v2.global_seq) {
> +               pr_err("%s%lld %s global_seq mismatch, expected > %llu, got %llu\n",
> +                      ENTITY_NAME(con->peer_name),
> +                      ceph_pr_addr(&con->peer_addr),
> +                      con->v2.global_seq, global_seq);
> +               con->error_msg = "global_seq mismatch";
> +               return -EINVAL;
> +       }
>         con->v2.global_seq = ceph_get_global_seq(con->msgr, global_seq);
>
>         free_conn_bufs(con);
>
>
> base-commit: 075b74841bd0065a3bda3440873c747938e69b68
> --
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.