lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <693e0aa4-34cd-4cb8-88a2-2cbacbe99a42@kzalloc.com>
Date: Sun, 1 Jun 2025 19:10:32 +0900
From: Yunseong Kim <ysk@...lloc.com>
To: Aaron Ballman <aaron@...selapp.com>, Reid Kleckner <reid@...m.org>,
 David Greene <david.greene@...el.com>,
 Christian König <christian.koenig@....com>
Cc: Boris Brezillon <boris.brezillon@...labora.com>,
 Danilo Krummrich <dakr@...hat.com>, Alex Deucher
 <alexander.deucher@....com>, llvm-dev <llvm-dev@...ts.llvm.org>,
 Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
 Byungchul Park <byungchul@...com>,
 "max.byungchul.park@...il.com" <max.byungchul.park@...il.com>,
 Yeo Reum Yun <YeoReum.Yun@....com>, Yunseong Kim
 <yunseong.kim@...csson.com>,
 "kernel_team@...ynix.com" <kernel_team@...ynix.com>
Subject: Clang compilation error in Linux kernel with DEPT patch: cannot jump
 from this indirect goto statement to one of its possible targets

Dear LLVM/Clang Developers,

I'm encountering a compilation error when building the Linux kernel with Clang
(clang version 20.1.3 (Fedora 20.1.3-1.fc42)) after applying a DEPT
(Dynamic Execution Path Tracing) patch.
Link: https://lore.kernel.org/all/20250519091826.19752-1-byungchul@sk.com/

The error occurs in “drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c” and is related to
an indirect ‘goto’ jumping into a statement expression. This issue does not
occur when compiling with GCC(gcc version 15.1.1 20250425
(Red Hat 15.1.1-1)).


Problem Description:

The core error message is:
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c:1372:3: error: cannot jump from this indirect goto statement to one of its possible targets
 1372 |                 drm_exec_retry_on_contention(&exec);
      |                 ^

Followed by notes showing the expansion:

./include/drm/drm_exec.h:123:4: note: expanded from macro 'drm_exec_retry_on_contention'
  123 |                         goto *__drm_exec_retry_ptr;             \
      |                         ^
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c:1399:2: note: possible target of indirect goto statement
 1399 |         dma_fence_wait(fence, false);
      |         ^
./include/linux/dma-fence.h:679:2: note: expanded from macro 'dma_fence_wait'
  679 |         sdt_might_sleep_start_timeout(NULL, MAX_SCHEDULE_TIMEOUT);      \
      |         ^
./include/linux/dept_sdt.h:45:45: note: expanded from macro 'sdt_might_sleep_start_timeout'
   45 |                 dept_stage_wait(__m, __m ? NULL : &__key, _THIS_IP_, __func__, t);\
      |                                                           ^
./include/linux/instruction_pointer.h:10:41: note: expanded from macro '_THIS_IP_'
   10 | #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
      |                                         ^
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c:1399:2: note: jump enters a statement expression
./include/linux/dma-fence.h:679:2: note: expanded from macro 'dma_fence_wait'
  679 |         sdt_might_sleep_start_timeout(NULL, MAX_SCHEDULE_TIMEOUT);      \
      |         ^
./include/linux/dept_sdt.h:45:45: note: expanded from macro 'sdt_might_sleep_start_timeout'
   45 |                 dept_stage_wait(__m, __m ? NULL : &__key, _THIS_IP_, __func__, t);\
      |                                                           ^
./include/linux/instruction_pointer.h:10:20: note: expanded from macro '_THIS_IP_'
   10 | #define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
      |                    ^
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c:1399:2: note: jump enters a statement expression
./include/linux/dma-fence.h:675:38: note: expanded from macro 'dma_fence_wait'
  675 | #define dma_fence_wait(f, intr)                                         \
      |                                                                         ^
1 error generated.


Context and Analysis:

1. “ _THIS_IP_” Macro: This macro, defined in
   “include/linux/instruction_pointer.h”, uses a GNU C statement expression with
   an address-of-label (&&__here) to obtain the current instruction pointer.

2. Code Flow:
    The “drm_exec_retry_on_contention” macro (from include/drm/drm_exec.h)
    expands to an indirect ‘goto’ statement (goto *_drm_exec_retry_ptr;). This
    pointer is set within the “drm_exec_until_all_locked” macro. One of the
    possible targets of this indirect ‘goto’ (as identified by Clang) is a line
    within the “dma_fence_wait()” function call.
    “dma_fence_wait()” (from include/linux/dma-fence.h) calls
    “sdt_might_sleep_start_timeout” (from include/linux/dept_sdt.h).
    “sdt_might_sleep_start_timeout” then utilizes the “_THIS_IP_” macro.

3.  The Problem:
    Clang reports an error because the indirect ‘goto’  from
    “drm_exec_retry_on_contention” attempts to jump into the statement
    expression generated by “_THIS_IP_”. The diagnostic “note: jump enters
    a statement expression” is the key.


Comparison with GCC:

GCC compiles this code without errors. This highlights a difference in how GCC
and Clang handle GNU extensions like statement expressions and
address-of-labels, especially when combined with indirect ‘goto’ for control
flow. GCC appears more lenient or implements these features differently.


Relevant LLVM Issues/Patches:

1. LLVM Issue 138272 (Add builtin/intrinsic to get current instruction pointer):
   Link: https://github.com/llvm/llvm-project/issues/138272
   This issue discusses the problematic nature of _THIS_IP_'s usage in LLVM.
   It indicates that ‘blockaddress’ (LLVM's representation for ‘&&label’) has
   defined behavior only when used as an operand to “indirectbr” or for null
   comparisons. Using it merely to obtain the instruction pointer violates
   LLVM's requirements.


2. LLVM Patch D154696 ([Clang] Diagnose jumps into statement expressions):
   Link: https://reviews.llvm.org/D154696
   This patch directly addresses the issue of jumps into statement expressions.
   It was initially reverted due to breaking the Linux kernel build but was
   later relanded. This shows Clang's active effort to enforce stricter
   diagnostics for such constructs, which GCC's documentation also implicitly
   states as undefined behavior.


3. LLVM Issue 28019 (Wrong 'error: cannot jump from this indirect goto statement
   to one of its possible targets'):
   Link: https://github.com/llvm/llvm-project/issues/28019
   While not directly about statement expressions, this issue describes a
   similar error where Clang flags an indirect ‘goto’ bypassing VLA
   initialization. This reinforces Clang's conservative static analysis and its
   tendency to diagnose potential undefined behavior.


Conclusion and Request:

The compilation error seems to stem from Clang's stricter adherence to LLVM's
‘blockaddress’ usage rules and its diagnostics for jumps into statement
expressions, which Clang considers undefined behavior. The DEPT patch integrates
“sdt_might_sleep_start_timeout” into the “dma_fence_wait” call path, exposing
this problematic pattern when combined with “drm_exec_retry_on_contention”.


I haven't found any specific Clang compiler options that would allow us to
disable this diagnostic or work around the issue.

Could you please provide guidance on how to address this compilation error? Is
this a known limitation or an intended diagnostic behavior that kernel
developers need to adapt to? Are there any recommended patterns or compiler
flags that could mitigate this issue without fundamentally altering the kernel's
use of these GNU extensions?


Thank you for your time and assistance.

Sincerely,
Yunseong Kim

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ