To access this blog post in English, click here.
Durante nossos projetos de pesquisa, precisamos investigar profundamente os subsistemas dos sistemas operacionais que são nosso alvo. Nesse processo, frequentemente encontramos outros problemas que não se alinham diretamente com nossos objetivos de pesquisa. No passado, nós os ignorávamos, mas recentemente decidimos iniciar um ciclo de contribuição, reportando e corrigindo essas falhas.
Especificamente para os problemas abordados nesta postagem, nós não apenas os reportamos, como também submetemos os patches de correção. Embora já tenhamos reportado vulnerabilidades e auxiliado em suas correções no passado, estes problemas marcam as primeiras instâncias em que somos os únicos autores dos patches submetidos.
Nesta postagem, detalhamos os problemas que reportamos e corrigimos no kernel do Linux.
Dos três itens reportados, dois são NULL pointer dereferences e o terceiro é um potencial out-of-bounds write no subsistema de arquivos Btrfs. Os NULL pointer dereferences poderiam permitir que usuários não privilegiados afetassem o funcionamento do sistema. Não investimos tempo significativo para tentar acionar a vulnerabilidade potencial de out-of-bounds no Btrfs, pois ela não era prioritária para nossos objetivos de pesquisa.
Embora a vulnerabilidade exista, ela requer uma condição que não parece trivial de ser alcançada. O mais notável sobre essa vulnerabilidade em particular é que ela é extremamente antiga, estando presente no kernel do Linux por mais de 17 anos. Ela havia sido identificada e houve uma tentativa de correção no passado, mas essa falha foi posteriormente esquecida. Apesar de o código vulnerável ter sido modificado diversas vezes desde a tentativa de correção original, a vulnerabilidade persistiu.
Todos os patches que submetemos já foram aplicados no upstream do kernel. A seguir, você encontrará todos os detalhes técnicos sobre cada uma das correções.
NULL POINTER DEREFERENCE NO SUBSISTEMA FANOTIFY
O subsistema fanotify é um recurso do kernel do Linux que permite aos usuários receber notificações e interceptar eventos em objetos de sistemas de arquivos, como arquivos, diretórios e mounts.
Na versão v6.16 do kernel do Linux, este subsistema foi atualizado para permitir o monitoramento de objetos de user namespaces [1]. Ao utilizar esse novo recurso, o usuário da chamada de sistema é obrigado a fornecer um file descriptor que faça referência a um objeto do tipo namespace – e o código espera validar essa referência.
No entanto, quando o usuário fornece um objeto de tipo diferente, mas inclui as flags que indicam um namespace, o código falha. Ele retorna um ponteiro NULL e, em seguida, tenta desreferenciar esse valor, assumindo incorretamente que representa um objeto válido.
O código vulnerável é exibido a seguir. Se path.dentry não representa um mount namespace, a função mnt_ns_from_dentry() retorna NULL e o código subsequente tenta utilizar esse valor sem realizar a validação necessária.
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 }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 }O código estava checando adequadamente se o objeto era do tipo desejado e retornando NULL caso contrário, mas o valor de retorno estava sendo usado sem ser checado. Este problema poderia facilmente ser usado por usuários não privilegiados com o código abaixo em um unprivileged user namespace:
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;
}O subsistema fanotify é usado principalmente por soluções de EDR, antivírus e outros softwares de segurança. Embora o novo recurso represente uma adição positiva que concede mais capacidades a essas aplicações, ele introduziu uma falha.
Esse problema poderia ser desencadeado inadvertidamente por erros de codificação nesses mesmos softwares de segurança, resultando em um impacto negativo no sistema. Corrigir a vulnerabilidade antes que o recurso fosse amplamente integrado a essas ferramentas garantiu estabilidade e, consequentemente, melhorou a segurança do ecossistema Linux.
Este é o patch que foi aplicado em upstream [2]:
fanotify: Validate the return value of mnt_ns_from_dentry() before dereferencing
https://github.com/torvalds/linux/commit/62e59ffe8787b5550ccff70c30b6f6be6a3ac3dd
Este problema também tem um CVE registrado:
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 NO SUBSiSTEMA TCP
O segundo problema que reportamos e corrigimos reside no núcleo do subsistema TCP, sendo este o segundo que abordamos neste subsistema [3]. O componente afetado é a combinação de dois recursos distintos: TCP-AO e TCP_REPAIR.
TCP-AO (TCP Authentication Option) [4] é uma extensão recente ao subsistema TCP do kernel Linux que visa autenticar os segmentos TCP. Seu principal propósito é proteger sessões BGP contra segmentos TCP spoofed.
TCP_REPAIR [5] é um recurso que permite a restauração de conexões TCP, por exemplo, quando máquinas virtuais (VMs) ou contêineres são migrados de um host físico para outro. Ele oferece ao software a flexibilidade de substituir o estado de conexões já estabelecidas, sendo também conhecido como relocação transparente de conexões de rede.
Quando o TCP-AO foi implementado no kernel Linux, o recurso TCP_REPAIR não foi levado em consideração. Quando ambos estão em uso, e uma chamada de sistema connect() é realizada, um NULL pointer dereference é acionado.
A falha ocorre porque, ao ser chamada por tcp_connect(), a função tcp_finish_connect() recebe o parâmetro skb como NULL. A função tcp_ao_finish_connect() não valida esse parâmetro antes de utilizá-lo em tcp_hdr(). Este problema também pode ser acionado por um usuário não privilegiado.
4073 int tcp_connect(struct sock *sk)
4074 {
...
4133 if (unlikely(tp->repair)) {
4134 tcp_finish_connect(sk, NULL);
4135 return 0;
4136 }
...
4174 }6370 void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
6371 {
..
6375 tcp_ao_finish_connect(sk, skb);
...
6399 }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 }O código para acionar o problema é exibido abaixo:
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;
}Este é o patch que foi aplicado em upstream [6]:
net/tcp: Fix a NULL pointer dereference when using TCP-AO with TCP_REPAIR
https://github.com/torvalds/linux/commit/2e7bba08923ebc675b1f0e0e0959e68e53047838
Este problema também tem um CVE registrado:
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 NO SiSTEMA DE ARQUIVO BTRFS
Este é um problema em potencial, pois não investimos tempo significativo para acioná-lo em um cenário realista. Trata-se de um bug antigo (17 anos), o que significa que sobreviveu a diversas mudanças no código. A falha chegou a ser notada no passado [7], mas parece que o e-mail não alcançou ninguém interessado em sua correção, e o bug teria sido perdido novamente se não tivéssemos decidido acompanhá-lo [8].
A classe da vulnerabilidade é um out-of-bounds write, e essa classe normalmente leva à escalação de privilégio. Embora vulnerabilidades em sistemas de arquivo não sejam consideradas tão críticas, o Btrfs é o sistema padrão em algumas distribuições, como no Fedora.
A vulnerabilidade está em um componente de sistemas de arquivos chamado exportfs. Pelo que entendemos, o exportfs não é um sistema de arquivo em si, mas uma parte que habilita o suporte ao Network File System (NFS) nos sistemas de arquivos. Sistemas de arquivos que suportam NFS precisam lidar com file handles (fh, que são diferentes de file descriptors, fd). Para isso, eles necessitam implementar funções específicas para codificar um inode para um file handle e vice-versa. Esta vulnerabilidade está presente na implementação do file handle do sistema de arquivo Btrfs. Abaixo, apresentamos a descrição do patch [9] que enviamos aos desenvolvedores do Btrfs, que resume o problema. Explicaremos a vulnerabilidade em detalhes na seção a seguir.
“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.”
VULNERABILIDADE
O código da função vulnerável é exibido abaixo. Nós explicaremos ele.
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 }A função btrfs_encode_fh() é definida em uma estrutura do tipo struct export_operations. Existem várias estruturas similares a essa implementada pelos sistemas de arquivos que visam suportar NFS.
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 };
A função btrfs_encode_fh() é chamada duas vezes e possui dois objetivos a serem realizados. Na primeira vez em que é chamada, max_len é zero, e a função deve retornar a quantidade de dados que seria escrita em fh. Na segunda vez, ela escreve em fh e deve respeitar a quantidade de bytes retornada na primeira chamada. A quantidade de bytes é usada para alocar memória para fh.
Este componente dos sistemas de arquivos é acessado através das chamadas de sistema name_to_handle_at() e open_by_handle_at(), e pelo subsistema fanotify com configurações de eventos específicas. O manual da chamada de sistema name_to_handle_at() contém o seguinte texto:
“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).”
A chamada de sistema tenta detectar se a quantidade de bytes escrita é maior do que o valor informado pelo usuário, mas isto evita o overflow da região de memória especificada pelo usuário e não impede a corrupção da memória do kernel. Esta chamada de sistema e o sistema de arquivos funcionam baseados em quantidades de dwords, e não de bytes. Portanto, o código converte os bytes passados pelo usuário para as callbacks dos sistemas de arquivos. A variável handle_dwords é o max_len em btrfs_encode_fh().
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 }Existem dois cenários na callback btrfs_encode_fh(): a variável parent estar definida ou não.
Se as flags tiverem EXPORT_FH_CONNECTABLE definida e o inode passado não representar um diretório (baseado na checagem !S_ISDIR(inode->i_mode)), ela obtém o parent através de dget_parent(). A variável parent é então passada para a função callback, que é btrfs_encode_fh().
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 }Agora que os fundamentos foram passados, podemos voltar para a função vulnerável e o bug. Se *max_len é 0, como ela deveria ser na primeira chamada, a função somente retorna BTRFS_FID_SIZE_CONNECTABLE ou BTRFS_FID_SIZE_NON_CONNECTABLE.
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 }Para saber o tamanho realmente retornado, nós precisamos olhar na estrutura struct btrfs_fid como ela é representada na memória. Os valores retornados significam dwords, por isso que o valor das chamadas a offsetof() e sizeof() são divididos por 4 nas definições das macros. Especialmente, BTRFS_FID_SIZE_CONNECTABLE são 0x20 (32 bytes), no qual, quando dividido por 4, resulta em 8 dwords. De forma similar, BTRFS_FID_SIZE_NON_CONNECTABLE são 0x14 (20 bytes), que, quando dividido por 4, resulta em 5 dwords.
(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)O caso para BTRFS_FID_SIZE_NON_CONNECTABLE. quando a variável parent não existe, está certo. O código escreve somente 5 dwords como pode ser visto abaixo:
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 dwordNo caso da variável parent ser definida, o código tem dois cenários dependendo do valor de btrfs_root_id(BTRFS_I(parent)->root).
1 – Se o root ID do parent é igual ao root ID do inode, o código escreve somente a quantidade de bytes especificado por BTRFS_FID_SIZE_CONNECTABLE (8 dwords), porque fid->parent_root_objectid não é tocado.
2 – Quando os root IDs são diferentes, fid->parent_root_objectid é escrito, mas o código não alocou memória para esse membro. Ele retorna BTRFS_FID_SIZE_CONNECTABLE_ROOT (8 dwords) na primeira chamada, mas escreve BTRFS_FID_SIZE_CONNECTABLE_ROOT (10 dwords). Isso causa 8 bytes out-of-bounds write.
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;Em um cenário em que esse problema puder ser acionado naturalmente, o segundo deve acontecer. Ele pode escrever até 40 bytes na segunda chamada, mas a primeira retornar apenas 20 ou 32 bytes.
$ ./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
$Nós passamos um certo tempo analisando o código-fonte do VFS e do sistema de arquivos Btrfs, bem como realizando alguns experimentos, mas nenhum deles funcionou. Tentamos até manipular uma imagem de um sistema de arquivos Btrfs, corrompendo alguns dados manualmente, mas isso também não funcionou no curto período de tempo que dedicamos a essa tarefa. Existem várias ferramentas interessantes no pacote btrfs-progs que nos permitem inspecionar os internals de um sistema de arquivos Btrfs, mas como isso não era o nosso objetivo de pesquisa, não alocamos muito tempo para essa tarefa.
Quando submetemos o problema aos desenvolvedores do Btrfs, perguntamos se eles sabiam como fazer a condição if ser verdadeira e, assim, acionar a vulnerabilidade de forma natural. Um deles respondeu que não sabia como fazer isso. A condição if foi sugerida por um desenvolvedor em [10]. Nós acreditamos que, com tempo suficiente, talvez seja possível acionar a vulnerabilidade com uma imagem manualmente preparada.
Vale mencionar que vulnerabilidades dependentes de sistemas de arquivo manualmente preparados são um assunto em evidência nos dias atuais [11][12] devido ao comportamento de pessoas envolvidas com o kernel Linux de negarem registrar CVEs para uma vulnerabilidade que tinha essa dependência.
Este é o patch que foi aplicado em upstream [9]:
btrfs: avoid potential out-of-bounds in btrfs_encode_fh()
https://github.com/torvalds/linux/commit/dff4f9ff5d7f289e4545cc936362e01ed3252742
Este problema também tem um CVE registrado:
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/
CONCLUSÃO
Nós decidimos reportar os problemas encontrados durante os projetos de pesquisa que não são interessantes para nossos propósitos. Esta postura demonstra nosso desejo de contribuir para os projetos dos quais dependemos diariamente e de ajudar outros usuários e clientes ao tornar os sistemas mais estáveis e seguros.
Nossos clientes recebem essa inteligência antes de a reportarmos para os projetos afetados, o que lhes permite manter seus sistemas estáveis e seguros. Se você estiver interessado em aproveitar essa inteligência para tornar seus produtos e ferramentas mais seguros e estáveis, entre em contato com nossa equipe hoje mesmo.
Estes problemas, especialmente o out-of-bounds write em potencial no sistema de arquivos Btrfs, demonstram nossa avançada capacidade de encontrar vulnerabilidades e problemas. Nós temos décadas de experiência em consultoria e pesquisa em segurança da informação. Conte conosco para ajudá-lo a enfrentar os desafios do mundo digital moderno.
Os códigos-fonte utilizados neste conteúdo são do kernel 6.16.7-200.fc42.x86_64, conforme encontrado no Fedora 42.
REFERENCIAS
[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
