Our recent contributions to the Linux kernel

Para acessar esta postagem em português, clique aqui.

During our research projects, we need to delve deep into the target operating system’s subsystems. In the process, we often find issues that are not interesting for our research purposes. In the past, we ignored them, but recently we have decided to contribute back to the upstream community by reporting these issues. In the cases covered by this blog post, we not only reported the issues but also submitted the corresponding patches. Even though we have reported vulnerabilities and helped to fix them in the past, these issues are the first for which we were the sole patch authors. In this blog post, we will detail the recent issues we have reported and fixed in the Linux kernel.

We reported three issues. Two of them are NULL pointer dereferences, and the third is a potential out-of-bounds write in the Btrfs file system. The NULL pointer dereference issues could allow unprivileged users to disrupt the system. We did not invest much time trying to trigger the potential out-of-bounds write in Btrfs, as it falls outside our research scope.

Although the vulnerability exists, it requires a condition that does not appear trivial to meet. The most interesting thing about it is that it is an “ancient” bug. The buggy code has been there for more than 17 years. While it was noticed in the past and an attempt was made to fix it, that effort was overlooked. Despite the vulnerable code having been touched several times since then, the vulnerability remained present. All of the patches are already applied upstream, and now we will detail the issues.

NULL POINTER DEREFERENCE IN FANOTIFY SUBSYSTEM

The fanotify subsystem is a feature in the Linux kernel that allows users to receive notifications and to intercept events on objects from the file systems. These objects can be files, directories, mounts, and others. In the Linux kernel version v6.16, the subsystem was updated to be able to monitor objects from different namespaces [1]. In this feature, the user of the system call is supposed to pass in a file descriptor referring to a namespace object, and the code properly validates this. However, when the user passed in a different object in path.dentry but still included the flags for a namespace, the function mnt_ns_from_dentry() returns NULL and the code uses the return value without validating it, assuming it was a valid object. The vulnerable code is shown below.

C
1802 static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1803                             int dfd, const char  __user *pathname)
1804 {
...
1992         if (obj_type == FSNOTIFY_OBJ_TYPE_INODE) {
...
1995         } else if (obj_type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
...
1998         } else if (obj_type == FSNOTIFY_OBJ_TYPE_SB) {
...
2001         } else if (obj_type == FSNOTIFY_OBJ_TYPE_MNTNS) {
2002                 mntns = mnt_ns_from_dentry(path.dentry);
2003                 user_ns = mntns->user_ns;

2005         }

C
2224 struct mnt_namespace *mnt_ns_from_dentry(struct dentry *dentry)
2225 {
2226         if (!is_mnt_ns_file(dentry))
2227                 return NULL;
2228 
2229         return to_mnt_ns(get_proc_ns(dentry->d_inode));
2230 }

The code was properly checking if the object is of the desired type and returning a NULL pointer otherwise, but the return value wasn’t being checked before being used. This issue could easily be triggered by unprivileged users with the code below from an unprivileged user namespace:

C
int main(void){
    int ffd;
    ffd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_MNT, 0);
    if(ffd < 0){
        perror("fanotify_init");
        exit(EXIT_FAILURE);
    }

    printf("Fanotify fd: %d\n",ffd);

    if(fanotify_mark(ffd, FAN_MARK_ADD | FAN_MARK_MNTNS, FAN_MNT_ATTACH, AT_FDCWD, "A") < 0){
        perror("fanotify_mark");
        exit(EXIT_FAILURE);
    }

return 0;
}

The fanotify subsystem is used mostly by EDR, anti-virus, and other security software. Although the new feature is a positive addition that grants these applications more capabilities, it introduced an issue. This problem could be inadvertently triggered by coding mistakes within that same security software, causing a negative effect. Fixing it before the feature is widely integrated into these tools brought stability and consequently, security.

This is the patch that was applied upstream [2]:

fanotify: Validate the return value of mnt_ns_from_dentry() before dereferencing
https://github.com/torvalds/linux/commit/62e59ffe8787b5550ccff70c30b6f6be6a3ac3dd

This issue also has a CVE registered:

CVE-2025-40072: fanotify: Validate the return value of mnt_ns_from_dentry() before dereferencing
https://lore.kernel.org/linux-cve-announce/2025102818-CVE-2025-40072-b9e8@gregkh

NULL POINTER DEREFERENCE IN TCP SUBSYSTEM

The second issue we reported and fixed is an issue in the core of the TCP subsystem. This is the second issue we have reported in the core of the Linux kernel’s TCP subsystem [3]. The component affected is the combination of two different features of the TCP subsystem: TCP-AO and TCP_REPAIR.

TCP-AO (TCP Authentication Option) [4] is a recent extension to the Linux kernel’s TCP subsystem that aims to authenticate the TCP segments. Its main purpose is to protect BGP sessions from spoofed TCP segments.

TCP_REPAIR [5] is a feature that allows TCP connections to be restored, for example, when VMs or containers are moved from a system to another. It gives software the flexibility to replace the state of already established connections. It’s known as transparent relocation of network connections. When TCP-AO was implemented in the Linux kernel, TCP_REPAIR wasn’t taken into account. This oversight causes a NULL pointer dereference to be triggered when enabling both features and issuing a connect() system call. When tcp_finish_connect() is called from tcp_connect(), the skb parameter is NULL and the function tcp_ao_finish_connect() doesn’t validate it before using it in tcp_hdr(). This is also triggered by an unprivileged user.

C
4073 int tcp_connect(struct sock *sk)
4074 {
...
4133         if (unlikely(tp->repair)) {
4134                 tcp_finish_connect(sk, NULL);
4135                 return 0;
4136         }
...
4174 }

C
6370 void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
6371 {
..
6375         tcp_ao_finish_connect(sk, skb);
...
6399 }

C
1171 void tcp_ao_finish_connect(struct sock *sk, struct sk_buff *skb)
1172 {
1173         struct tcp_ao_info *ao;
1174         struct tcp_ao_key *key;
1175 
1176         ao = rcu_dereference_protected(tcp_sk(sk)->ao_info,
1177                                        lockdep_sock_is_held(sk));
1178         if (!ao)
1179                 return;
1180 
1181         WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq);
...
1186 }

Below is the code to trigger the issue:

C
int main(void){
	struct sockaddr_in sockaddr;
	struct tcp_ao_add tcp_ao;
	int sk;
	int one = 1;

	memset(&sockaddr,'\0',sizeof(sockaddr));
	memset(&tcp_ao,'\0',sizeof(tcp_ao));

	sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	sockaddr.sin_family = AF_INET;

	memcpy(tcp_ao.alg_name,"cmac(aes128)",12);
	memcpy(tcp_ao.key,"ABCDEFGHABCDEFGH",16);
	tcp_ao.keylen = 16;

	memcpy(&tcp_ao.addr,&sockaddr,sizeof(sockaddr));

	setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tcp_ao,
	sizeof(tcp_ao));
	setsockopt(sk, IPPROTO_TCP, TCP_REPAIR, &one, sizeof(one));

	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htobe16(123);

	inet_aton("127.0.0.1", &sockaddr.sin_addr);

	connect(sk,(struct sockaddr *)&sockaddr,sizeof(sockaddr));

return 0;
}

This is the patch that was applied upstream [6]:

net/tcp: Fix a NULL pointer dereference when using TCP-AO with TCP_REPAIR
https://github.com/torvalds/linux/commit/2e7bba08923ebc675b1f0e0e0959e68e53047838

This issue also has a CVE registered:

CVE-2025-39950: net/tcp: Fix a NULL pointer dereference when using TCP-AO with TCP_REPAIR
https://lore.kernel.org/linux-cve-announce/2025100420-CVE-2025-39950-e7d6@gregkh

OUT-OF-BOUNDS WRITE IN THE BTRFS FILE SYSTEM

This is a potential issue, as we did not invest time to trigger it in a realistic scenario. It is an “ancient” bug (17 years old), meaning it survived several code changes. The bug was even noticed in the past [7], but it seems no one interested in getting it fixed noticed it, and it would have been missed again if we didn’t follow up [8].

The vulnerability class is an out-of-bounds write, and it usually leads to privilege escalation. Even though file system vulnerabilities are usually not that interesting, the Btrfs file system is the default file system in some distributions like Fedora. Therefore, an unprivileged user could interact with the file system’s code naturally.

The vulnerability lies in a component of the file system called exportfs. As we understand it, exportfs is not a file system itself but a part of file systems that enables them to work properly with the Network File System (NFS). File systems that work with NFS need to support file handles (fh, which are different from file descriptors (fd)). To do this, they have to implement some functions to encode an inode to a file handle and vice-versa. This vulnerability is present in the file handle implementation of the Btrfs file system. Below, we show the patch [9] description we sent to the Btrfs developers that summarizes the issue. We also explain the vulnerability in the next section.

The function btrfs_encode_fh() does not properly account for the three cases it handles.

Before writing to the file handle (fh), the function only returns to the user BTRFS_FID_SIZE_NON_CONNECTABLE (5 dwords, 20 bytes) or BTRFS_FID_SIZE_CONNECTABLE (8 dwords, 32 bytes).

However, when a parent exists and the root ID of the parent and the inode are different, the function writes BTRFS_FID_SIZE_CONNECTABLE_ROOT (10 dwords, 40 bytes).

If *max_len is not large enough, this write goes out of bounds because BTRFS_FID_SIZE_CONNECTABLE_ROOT is greater than BTRFS_FID_SIZE_CONNECTABLE originally returned.

This results in an 8-byte out-of-bounds write at fid->parent_root_objectid = parent_root_id.”

VULNERABILITY

The code of the vulnerable function is shown below. We’ll explain it.

C
12 #define BTRFS_FID_SIZE_NON_CONNECTABLE (offsetof(struct btrfs_fid, \
13                                                  parent_objectid) / 4)
14 #define BTRFS_FID_SIZE_CONNECTABLE (offsetof(struct btrfs_fid, \
15                                              parent_root_objectid) / 4)
16 #define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4)
...
18 static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
19                            struct inode *parent)
20 {
21         struct btrfs_fid *fid = (struct btrfs_fid *)fh;
22         int len = *max_len;
23         int type;
24 
25         if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
26                 *max_len = BTRFS_FID_SIZE_CONNECTABLE;
27                 return FILEID_INVALID;
28         } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
29                 *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
30                 return FILEID_INVALID;
31         }
32 
33         len  = BTRFS_FID_SIZE_NON_CONNECTABLE;
34         type = FILEID_BTRFS_WITHOUT_PARENT;
35 
36         fid->objectid = btrfs_ino(BTRFS_I(inode));
37         fid->root_objectid = btrfs_root_id(BTRFS_I(inode)->root);
38         fid->gen = inode->i_generation;
39 
40         if (parent) {
41                 u64 parent_root_id;
42 
43                 fid->parent_objectid = btrfs_ino(BTRFS_I(parent));
44                 fid->parent_gen = parent->i_generation;
45                 parent_root_id = btrfs_root_id(BTRFS_I(parent)->root);
46 
47                 if (parent_root_id != fid->root_objectid) {
48                         fid->parent_root_objectid = parent_root_id;
49                         len = BTRFS_FID_SIZE_CONNECTABLE_ROOT;
50                         type = FILEID_BTRFS_WITH_PARENT_ROOT;
51                 } else {
52                         len = BTRFS_FID_SIZE_CONNECTABLE;
53                         type = FILEID_BTRFS_WITH_PARENT;
54                 }
55         }
56 
57         *max_len = len;
58         return type;
59 }

The function btrfs_encode_fh() is defined in a structure of the type struct export_operations. There are several of these structures implemented by file systems that are intended to support NFS.

C
295 const struct export_operations btrfs_export_ops = {
296         .encode_fh      = btrfs_encode_fh,
297         .fh_to_dentry   = btrfs_fh_to_dentry,
298         .fh_to_parent   = btrfs_fh_to_parent,
299         .get_parent     = btrfs_get_parent,
300         .get_name       = btrfs_get_name,
301 };

The function btrfs_encode_fh() is called twice and has two goals to be implemented. The first time it’s called, *max_len is 0, and the function should return the amount of bytes it would write to fh. The second time, it writes to fh and should respect the amount of bytes returned by the first call. That amount of bytes is used to allocate memory for fh. This component of file systems is reached via the system calls name_to_handle_at() and open_by_handle_at(), and the fanotify subsystem when there are events with specific flags defined. The manual of the name_to_handle_at() system call contains the following:

“The caller can discover the required size for the file_handle structure by making a call in which handle->handle_bytes is zero; in this case, the call fails with the error EOVERFLOW and handle->handle_bytes is set to indicate the required size; the caller can then use this information to allocate a structure of the correct size (see EXAMPLES below).”

The system call tries to detect if the amount of bytes written is greater than what the user passed in, but this is to avoid overflowing the user buffer and doesn’t avoid any kind of memory corruption in the kernel memory. This system call and the file system callback work based on the length of dwords, not bytes, so the code converts the bytes passed in by the user to the file system callbacks. The variable handle_dwords is max_len in btrfs_encode_fh().

C
17 static long do_sys_name_to_handle(const struct path *path,
18                                   struct file_handle __user *ufh,
19                                   void __user *mnt_id, bool unique_mntid,
20                                   int fh_flags)
21 {
...
48         handle = kzalloc(struct_size(handle, f_handle, f_handle.handle_bytes),
49                          GFP_KERNEL);
50         if (!handle)
51                 return -ENOMEM;
52 
53         /* convert handle size to multiple of sizeof(u32) */
54         handle_dwords = f_handle.handle_bytes >> 2;
55 
56         /* Encode a possibly decodeable/connectable file handle */
57         retval = exportfs_encode_fh(path->dentry,
58                                     (struct fid *)handle->f_handle,
59                                     &handle_dwords, fh_flags);
60         handle->handle_type = retval;
61         /* convert handle size to bytes */
62         handle_bytes = handle_dwords * sizeof(u32);
63         handle->handle_bytes = handle_bytes;
64         if ((handle->handle_bytes > f_handle.handle_bytes) ||
65             (retval == FILEID_INVALID) || (retval < 0)) {
66                 /* As per old exportfs_encode_fh documentation
67                  * we could return ENOSPC to indicate overflow
68                  * But file system returned 255 always. So handle
69                  * both the values
70                  */
71                 if (retval == FILEID_INVALID || retval == -ENOSPC)
72                         retval = -EOVERFLOW;
73                 /*
74                  * set the handle size to zero so we copy only
75                  * non variable part of the file_handle
76                  */
77                 handle_bytes = 0;
78         } else {
79                 /*
80                  * When asked to encode a connectable file handle, encode this
81                  * property in the file handle itself, so that we later know
82                  * how to decode it.
83                  * For sanity, also encode in the file handle if the encoded
84                  * object is a directory and verify this during decode, because
85                  * decoding directory file handles is quite different than
86                  * decoding connectable non-directory file handles.
87                  */
88                 if (fh_flags & EXPORT_FH_CONNECTABLE) {
89                         handle->handle_type |= FILEID_IS_CONNECTABLE;
90                         if (d_is_dir(path->dentry))
91                                 handle->handle_type |= FILEID_IS_DIR;
92                 }
93                 retval = 0;
94         }
...
112 }

The callback btrfs_encode_fh() has two scenarios, parent being defined or not. If the flags have EXPORT_FH_CONNECTABLE set and the inode passed in doesn’t represent a directory, based on the check !S_ISDIR(inode->i_mode), it obtains the parent through dget_parent(). This parent is then also passed in to the callback function, which is btrfs_encode_fh().

C
414 int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
415                        int flags)
416 {
417         int error;
418         struct dentry *p = NULL;
419         struct inode *inode = dentry->d_inode, *parent = NULL;
420 
421         if ((flags & EXPORT_FH_CONNECTABLE) && !S_ISDIR(inode->i_mode)) {
422                 p = dget_parent(dentry);
423                 /*
424                  * note that while p might've ceased to be our parent already,
425                  * it's still pinned by and still positive.
426                  */
427                 parent = p->d_inode;
428         }
429 
430         error = exportfs_encode_inode_fh(inode, fid, max_len, parent, flags);
431         dput(p);
432 
433         return error;
434 }

Now that we have the fundamentals, we can go back to the vulnerable function and the bug. If *max_len is 0, as it is intended to be on the first call, the function only returns BTRFS_FID_SIZE_CONNECTABLE or BTRFS_FID_SIZE_NON_CONNECTABLE.

C
12 #define BTRFS_FID_SIZE_NON_CONNECTABLE (offsetof(struct btrfs_fid, \
13                                                  parent_objectid) / 4)
14 #define BTRFS_FID_SIZE_CONNECTABLE (offsetof(struct btrfs_fid, \
15                                              parent_root_objectid) / 4)
16 #define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4)
...
25         if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
26                 *max_len = BTRFS_FID_SIZE_CONNECTABLE;
27                 return FILEID_INVALID;
28         } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
29                 *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
30                 return FILEID_INVALID;
31         }

To know the actual size returned, we need to look at the struct btrfs_fid as it is represented in memory. The values returned mean the size in dwords, which is why the values are divided by 4 in the macro definitions. Specifically, BTRFS_FID_SIZE_CONNECTABLE is 0x20 (32 bytes), which, when divided by 4, results in 8 dwords. Similarly, BTRFS_FID_SIZE_NON_CONNECTABLE is 0x14 (20 bytes), which, when divided by 4, results in 5 dwords.

C
(gdb) ptype/ox struct btrfs_fid
/* offset      |    size */  type = struct btrfs_fid {
/* 0x0000      |  0x0008 */    u64 objectid;
/* 0x0008      |  0x0008 */    u64 root_objectid;
/* 0x0010      |  0x0004 */    u32 gen;
/* 0x0014      |  0x0008 */    u64 parent_objectid;
/* 0x001c      |  0x0004 */    u32 parent_gen;
/* 0x0020      |  0x0008 */    u64 parent_root_objectid;

                               /* total size (bytes):   40 */
                             }
(gdb)

The case for BTRFS_FID_SIZE_NON_CONNECTABLE, when the parent doesn’t exist, is right. The code writes only 5 dwords as can be seen below:

C
36         fid->objectid = btrfs_ino(BTRFS_I(inode)); // 2 dwords
37         fid->root_objectid = btrfs_root_id(BTRFS_I(inode)->root); // 2 dwords
38         fid->gen = inode->i_generation; // 1 dword

In the case of the parent being defined, it has two scenarios depending on btrfs_root_id(BTRFS_I(parent)->root).

1 – If the parent root ID is equal to the inode root ID, the code only writes the length specified by BTRFS_FID_SIZE_CONNECTABLE (8 dwords), because fid->parent_root_objectid is not touched.

2 – When the root IDs are different, fid->parent_root_objectid is written to, but the code hasn’t allocated memory for it. It returns BTRFS_FID_SIZE_CONNECTABLE_ROOT (8 dwords) in the first call, but writes BTRFS_FID_SIZE_CONNECTABLE_ROOT (10 dwords). This causes the 8 bytes out-of-bounds write.

C
40         if (parent) {
41                 u64 parent_root_id;
42 
43                 fid->parent_objectid = btrfs_ino(BTRFS_I(parent));
44                 fid->parent_gen = parent->i_generation;
45                 parent_root_id = btrfs_root_id(BTRFS_I(parent)->root);
46 
47                 if (parent_root_id != fid->root_objectid) {
48                         fid->parent_root_objectid = parent_root_id;
49                         len = BTRFS_FID_SIZE_CONNECTABLE_ROOT;
50                         type = FILEID_BTRFS_WITH_PARENT_ROOT;
51                 } else {
52                         len = BTRFS_FID_SIZE_CONNECTABLE;
53                         type = FILEID_BTRFS_WITH_PARENT;
54                 }
55         }
...
57         *max_len = len;

In a scenario in which the issue could be triggered naturally, the following should happen. It can write up to 40 bytes in the second call, but in the first call the function only returns 20 or 32 bytes.

C
$ ./name_to_handle_at btrfs1/A #rootids equal
handle.handle_bytes: 0
handle.handle_bytes: 32
$ ./name_to_handle_at btrfs1/A #rootids different
handle.handle_bytes: 0
handle.handle_bytes: 40
$

We spent some time looking at the source code of the VFS and the Btrfs file system and doing some experiments, but none of them worked. We even tried to manipulate a Btrfs file system, manually corrupting some data, but it also didn’t work. There are several interesting utilities in the btrfs-progs that allows us to inspect the internals of a Btrfs file system, but as this wasn’t our research goals, we didn’t spend much time on it.

When we submitted the bug to the Btrfs developers, we asked if they knew how to trigger the if statement to be true and then naturally trigger the vulnerability, but one of them replied that he didn’t know. That if statement was suggested by a developer at [10]. We believe with time we could find a way to trigger that vulnerability with a manually crafted file system. It’s worth to mention crafted file system vulnerabilities are a hot discussion [11][12] at the moment due to the behavior of the Linux kernel maintainers refusing to register CVEs for vulnerabilities that have this dependency.

This is the patch that was applied upstream [9]:

btrfs: avoid potential out-of-bounds in btrfs_encode_fh()
https://github.com/torvalds/linux/commit/dff4f9ff5d7f289e4545cc936362e01ed3252742

This issue also has a CVE registered:

CVE-2025-40205: btrfs: avoid potential out-of-bounds in btrfs_encode_fh()
https://lore.kernel.org/linux-cve-announce/2025111247-CVE-2025-40205-ad43@gregkh/

CONCLUSION

We have decided to report all issues we find during our vulnerability research projects that fall outside our primary scope. This posture demonstrates our commitment to upstream software contribution, helping make the systems we all depend on safer and more stable for our clients and the broader community. Crucially, our clients receive this vulnerability intelligence first, enabling them to preemptively secure their systems and maintain smooth, uninterrupted operations. If you are interested in leveraging this intelligence to make your products and tools safer and more stable, please contact our team today.

These issues, especially the potential out-of-bounds write in the Btrfs file system, demonstrate our advanced ability to find vulnerabilities. It’s an ancient bug that has survived several code changes. The other issues we found mean we are following the Linux kernel development closely, auditing, testing, and validating old and new features. We have decades of experience in information security consulting and security research. Count on us to help you face the challenges of the modern world.

The kernel source code used in this blog post is from the kernel 6.16.7-200.fc42.x86_64 Fedora 42.

References

[1] – fanotify: support watching filesystems and mounts inside userns
https://github.com/torvalds/linux/commit/58f5fbeb367ff6f30a2448b2cad70f70b2de4b06

[2] – fanotify: Validate the return value of mnt_ns_from_dentry() before dereferencing
https://github.com/torvalds/linux/commit/62e59ffe8787b5550ccff70c30b6f6be6a3ac3dd

[3] – Accidentally uncovering a seven years old vulnerability in the Linux kernel
https://allelesecurity.com/accidentally-uncovering-a-seven-years-old-vulnerability-in-the-linux-kernel/

[4] – The TCP Authentication Option
https://datatracker.ietf.org/doc/html/rfc5925

[5] – TCP connection repair
https://lwn.net/Articles/495304

[6] – net/tcp: Fix a NULL pointer dereference when using TCP-AO with TCP_REPAIR
https://github.com/torvalds/linux/commit/2e7bba08923ebc675b1f0e0e0959e68e53047838

[7] – [PATCH] fix (latent?) memory corruption in btrfs_encode_fh()
https://lore.kernel.org/all/4CADAEEC020000780001B32C@vpn.id2.novell.com

[8] – Re: [PATCH] btrfs: Avoid potential out-of-bounds in btrfs_encode_fh()
https://lore.kernel.org/all/20250923151110.GV5333@suse.cz/

[9] – btrfs: avoid potential out-of-bounds in btrfs_encode_fh()
https://github.com/torvalds/linux/commit/dff4f9ff5d7f289e4545cc936362e01ed3252742

[10] – Re: [PATCH 1/3] Introduce btrfs_iget helper
https://lore.kernel.org/all/1218620490.2977.246.camel@pmac.infradead.org

[11] – Linux kernel: HFS+ filesystem implementation issues, exposure in distros
https://seclists.org/oss-sec/2025/q2/197

[12] – Re: Re: Re: Linux kernel: HFS+ filesystem implementation, issues, exposure in distros
https://seclists.org/oss-sec/2025/q4/3