VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46098

CVE-2026-46098

Description

In the Linux kernel, the following vulnerability has been resolved:

net: caif: clear client service pointer on teardown

caif_connect() can tear down an existing client after remote shutdown by calling caif_disconnect_client() followed by caif_free_client(). caif_free_client() releases the service layer referenced by adap_layer->dn, but leaves that pointer stale.

When the socket is later destroyed, caif_sock_destructor() calls caif_free_client() again and dereferences the freed service pointer.

Clear the client/service links before releasing the service object so repeated teardown becomes harmless.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel, the CAIF protocol's client teardown leaves a stale service pointer, causing a use-after-free when the socket is later destroyed.

Vulnerability

In the Linux kernel's CAIF (CAI F) protocol implementation, a use-after-free vulnerability exists in the client teardown path. When caif_connect() handles a remote shutdown, it calls caif_disconnect_client() followed by caif_free_client(). The caif_free_client() function releases the service layer object referenced by adap_layer->dn but does not clear the pointer. Later, when the socket is destroyed, caif_sock_destructor() calls caif_free_client() again, dereferencing the freed service pointer. This affects all Linux kernel versions prior to the inclusion of commit 914c6456fcfc21a3d553945dff62fd1621d6155d. [1]

Exploitation

An attacker who can trigger a remote shutdown of a CAIF connection and subsequently cause the local socket to be closed can exploit this vulnerability. The remote shutdown causes the initial teardown, and the subsequent socket destruction triggers the use-after-free. No special privileges are required beyond the ability to establish and manipulate a CAIF connection.

Impact

Successful exploitation results in a use-after-free condition in kernel memory. This can lead to a system crash (denial of service) or, under the right memory conditions, arbitrary code execution with kernel privileges. The exact impact depends on the memory allocator state and the attacker's ability to control the freed memory.

Mitigation

The vulnerability is fixed in Linux kernel versions that include commit 914c6456fcfc21a3d553945dff62fd1621d6155d. This commit clears the client/service links before releasing the service object, preventing the double-free. Users should update their kernel to a version containing this fix. No workaround is known. [1]

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

10
f7cf8ece8cee

net: caif: clear client service pointer on teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengchuan LiangApr 11, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
914c6456fcfc

net: caif: clear client service pointer on teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengchuan LiangApr 11, 2026Fixed in 6.6.140via kernel-cna
1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 9cef9496a70705..9a474d99bae8b7 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -197,10 +197,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
3ac6db584d9d

net: caif: clear client service pointer on teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengchuan LiangApr 11, 2026Fixed in 6.12.86via kernel-cna
1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 9cef9496a70705..9a474d99bae8b7 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -197,10 +197,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
63d21a3aa010

net: caif: clear client service pointer on teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengchuan LiangApr 11, 2026Fixed in 6.18.27via kernel-cna
1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
a4b191ddc12c

net: caif: clear client service pointer on teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitZhengchuan LiangApr 11, 2026Fixed in 7.0.4via kernel-cna
1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
3ac6db584d9d

net: caif: clear client service pointer on teardown

1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 9cef9496a70705..9a474d99bae8b7 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -197,10 +197,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
63d21a3aa010

net: caif: clear client service pointer on teardown

1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
914c6456fcfc

net: caif: clear client service pointer on teardown

1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 9cef9496a70705..9a474d99bae8b7 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -197,10 +197,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
a4b191ddc12c

net: caif: clear client service pointer on teardown

1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    
f7cf8ece8cee

net: caif: clear client service pointer on teardown

1 file changed · +12 3
  • net/caif/cfsrvl.c+12 3 modified
    diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
    index 171fa32ada85c0..d687fd0b4ed3a8 100644
    --- a/net/caif/cfsrvl.c
    +++ b/net/caif/cfsrvl.c
    @@ -191,10 +191,20 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
     
     void caif_free_client(struct cflayer *adap_layer)
     {
    +	struct cflayer *serv_layer;
     	struct cfsrvl *servl;
    -	if (adap_layer == NULL || adap_layer->dn == NULL)
    +
    +	if (!adap_layer)
    +		return;
    +
    +	serv_layer = adap_layer->dn;
    +	if (!serv_layer)
     		return;
    -	servl = container_obj(adap_layer->dn);
    +
    +	layer_set_dn(adap_layer, NULL);
    +	layer_set_up(serv_layer, NULL);
    +
    +	servl = container_obj(serv_layer);
     	servl->release(&servl->layer);
     }
     EXPORT_SYMBOL(caif_free_client);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Use-after-free due to stale pointer: caif_free_client() frees the service layer object but does not clear adap_layer->dn, so a second call dereferences freed memory."

Attack vector

An attacker can trigger a use-after-free by causing a CAIF socket to be torn down twice. `caif_connect()` tears down an existing client after remote shutdown by calling `caif_disconnect_client()` followed by `caif_free_client()`. The first call to `caif_free_client()` frees the service layer object but leaves `adap_layer->dn` pointing to freed memory. When the socket is later destroyed, `caif_sock_destructor()` calls `caif_free_client()` again, which dereferences the stale `adap_layer->dn` pointer, leading to a use-after-free [patch_id=2659729].

Affected code

The vulnerability is in the `caif_free_client()` function in `net/caif/cfsrvl.c` [patch_id=2659729]. The function releases the service layer referenced by `adap_layer->dn` but does not clear that pointer, leaving it stale for any subsequent call.

What the fix does

The patch modifies `caif_free_client()` in `net/caif/cfsrvl.c` to clear the cross-layer pointers before releasing the service object [patch_id=2659729]. It saves `adap_layer->dn` into a local variable `serv_layer`, then calls `layer_set_dn(adap_layer, NULL)` and `layer_set_up(serv_layer, NULL)` to null out both the adaptation layer's down pointer and the service layer's up pointer. Only after clearing these links does it call `servl->release()`. This ensures that if `caif_free_client()` is called again on the same adaptation layer, the null check on `adap_layer->dn` will cause an early return, making repeated teardown harmless.

Preconditions

  • inputA CAIF socket must have been connected and then remotely shut down, causing caif_connect() to tear down the client.
  • inputThe socket must later be destroyed (e.g., via close()), triggering caif_sock_destructor() which calls caif_free_client() again.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.